LCOV - code coverage report
Current view: top level - EnergyPlus - PlantCondLoopOperation.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 1469 2208 66.5 %
Date: 2024-08-24 18:31:18 Functions: 22 24 91.7 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <algorithm>
      50             : #include <cassert>
      51             : #include <cmath>
      52             : #include <vector>
      53             : 
      54             : // ObjexxFCL Headers
      55             : #include <ObjexxFCL/Array.functions.hh>
      56             : #include <ObjexxFCL/Array1D.hh>
      57             : #include <ObjexxFCL/Fmath.hh>
      58             : 
      59             : // EnergyPlus Headers
      60             : #include <EnergyPlus/Autosizing/Base.hh>
      61             : #include <EnergyPlus/BranchNodeConnections.hh>
      62             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      63             : #include <EnergyPlus/DataEnvironment.hh>
      64             : #include <EnergyPlus/DataHVACGlobals.hh>
      65             : #include <EnergyPlus/DataIPShortCuts.hh>
      66             : #include <EnergyPlus/DataRuntimeLanguage.hh>
      67             : #include <EnergyPlus/DataSizing.hh>
      68             : #include <EnergyPlus/EMSManager.hh>
      69             : #include <EnergyPlus/FluidProperties.hh>
      70             : #include <EnergyPlus/General.hh>
      71             : #include <EnergyPlus/GeneralRoutines.hh>
      72             : #include <EnergyPlus/GlobalNames.hh>
      73             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      74             : #include <EnergyPlus/NodeInputManager.hh>
      75             : #include <EnergyPlus/Plant/DataPlant.hh>
      76             : #include <EnergyPlus/Plant/EquipAndOperations.hh>
      77             : #include <EnergyPlus/PlantCondLoopOperation.hh>
      78             : #include <EnergyPlus/PlantUtilities.hh>
      79             : #include <EnergyPlus/PluginManager.hh>
      80             : #include <EnergyPlus/ScheduleManager.hh>
      81             : #include <EnergyPlus/SetPointManager.hh>
      82             : #include <EnergyPlus/UtilityRoutines.hh>
      83             : 
      84             : namespace EnergyPlus::PlantCondLoopOperation {
      85             : 
      86             : // MODIFIED       LKL Sep 03: adding integer/pointers for various parts of operation schemes
      87             : // MODIFIED       DEF JUL 10: complete re-write to support new Plant manager
      88             : 
      89             : // PURPOSE OF THIS MODULE: This module assigns loads to the equipment on
      90             : // the plant and condenser loops that will operate
      91             : // for a given timestep.
      92             : 
      93             : // METHODOLOGY EMPLOYED:  The main driver, "ManagePlantLoadDistribution",
      94             : // gets 'Plant Operation scheme' and 'Plant Equipment List' input.  Pointers are
      95             : // set up in the PlantLoop data structure to allow components to directly access the
      96             : // operation schemes and plant lists that the component shows up on.
      97             : // ManagePlantLoadDistribution is called one time for each component on the loop.
      98             : // It finds the operation scheme and equipment list associated with the component
      99             : // and calculates the component load.  If the component is part of a 'load range'
     100             : // based scheme, it also assigns a component load to each of the components on the
     101             : // equipment list.
     102             : 
     103             : // Using/Aliasing
     104             : using namespace DataPlant;
     105             : using FluidProperties::GetSpecificHeatGlycol;
     106             : using HVAC::SmallLoad;
     107             : 
     108    38710704 : void ManagePlantLoadDistribution(EnergyPlusData &state,
     109             :                                  PlantLocation const &plantLoc, // PlantLoop data structure Location struct
     110             :                                  Real64 &LoopDemand,
     111             :                                  Real64 &RemLoopDemand,
     112             :                                  bool const FirstHVACIteration,
     113             :                                  bool &LoopShutDownFlag, // EMS flag to tell loop solver to shut down pumps
     114             :                                  bool &LoadDistributionWasPerformed)
     115             : {
     116             :     // SUBROUTINE INFORMATION:
     117             :     //       AUTHOR:          Dan Fisher
     118             :     //       DATE WRITTEN:    April 1999
     119             :     //       REVISED:         March 2001
     120             :     //                        July 2001, Rick Strand (revision of pump and loop control code)
     121             :     //                        July 2010, Dan Fisher, complete rewrite to component based control
     122             : 
     123             :     // PURPOSE OF THIS SUBROUTINE:
     124             :     // ManageLoopOperation is the driver routine
     125             :     // for plant equipment selection.  It calls the general "Get-
     126             :     // Input" routines, initializes the loop pointers, then calls the
     127             :     // appropriate type of control algorithm (setpoint, load range based,
     128             :     // or uncontrolled) for the component
     129             : 
     130             :     int ListNum;    // DO loop index in PlantLoop()%LoopSide()%Branch()%Comp()%OpScheme()%EquipList(ListNum)
     131             :     int CurListNum; // Current list...= ListNum,  used for error checking only
     132             :     // Indices in PlantLoop.LoopSide.Branch.Comp data structure
     133             :     int CurCompLevelOpNum; // This is set by the init routine at each FirstHVACIteration.
     134             :     // It tells which scheme for this component is currently scheduled
     135             :     // and is used to avoid a 'schedule search' on each call
     136             :     // It is used as the OpScheme index in PlantLoop.LoopSide.Branch.Comp.OpScheme(CurCompLevelOpNum)
     137             :     // Value of pointers held in PlantLoop.LoopSide.Branch.Comp() data structure
     138             :     // Used as indices in PlantLoop.OpScheme() data structure
     139             :     int CurSchemePtr; // set by PlantLoop.LoopSide.Branch.Comp.OpScheme.OpSchemePtr
     140             :     // used to locate data in PL()%OpScheme(CurSchemePtr)
     141             :     int ListPtr; // !set by PL()%LoopSide()%Branch()%Comp()%OpScheme(CurCompLevelOpNum)%EquipList(CurListNum)ListPtr
     142             :     // used to locate data in PL()%OpScheme(CurSchemePtr)%EquipList(ListPtr)
     143             :     // Local values from the PlantLoop()%OpScheme() data structure
     144    38710704 :     Real64 RangeVariable(0.0); // holds the 'loop demand', wetbulb temp, etc.
     145             :     Real64 TestRangeVariable;  // abs of RangeVariable for logic tests etc.
     146             :     Real64 RangeHiLimit;       // upper limit of the range variable
     147             :     Real64 RangeLoLimit;       // lower limit of the range variable
     148             :     // Local values from the PlantLoop()%LoopSide()%Branch()%Comp() data structure
     149             :     int NumEquipLists; // number of equipment lists
     150             :     // Error control flags
     151             :     int NumCompsOnList;
     152             :     int CompIndex;
     153             :     int EquipBranchNum;
     154             :     int EquipCompNum;
     155             : 
     156             :     // Shut down equipment and return if so instructed by LoopShutDownFlag
     157    38710704 :     if (LoopShutDownFlag) {
     158        8356 :         TurnOffLoopEquipment(state, plantLoc.loopNum);
     159        8356 :         return;
     160             :     }
     161             : 
     162             :     // Return if there are no loop operation schemes available
     163    38702348 :     if (!std::any_of(state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme.begin(),
     164    38702348 :                      state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme.end(),
     165    41472260 :                      [](DataPlant::OperationData const &e) { return e.Available; }))
     166           0 :         return;
     167             : 
     168             :     // set up references
     169    38702348 :     auto &loop_side = state.dataPlnt->PlantLoop(plantLoc.loopNum).LoopSide(plantLoc.loopSideNum);
     170    38702348 :     auto &this_component = loop_side.Branch(plantLoc.branchNum).Comp(plantLoc.compNum);
     171             : 
     172             :     // Implement EMS control commands
     173    38702348 :     ActivateEMSControls(state, plantLoc, LoopShutDownFlag);
     174             : 
     175             :     // Schedules are checked and CurOpScheme updated on FirstHVACIteration in InitLoadDistribution
     176             :     // Here we just load CurOpScheme to a local variable
     177    38702348 :     CurCompLevelOpNum = this_component.CurCompLevelOpNum;
     178             :     // If no current operation scheme for component, RETURN
     179    38702348 :     if (CurCompLevelOpNum == 0) return;
     180             :     // set local variables from data structure
     181    38702348 :     NumEquipLists = this_component.OpScheme(CurCompLevelOpNum).NumEquipLists;
     182    38702348 :     CurSchemePtr = this_component.OpScheme(CurCompLevelOpNum).OpSchemePtr;
     183    38702348 :     DataPlant::OpScheme CurSchemeType = state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).Type;
     184             : 
     185             :     // another reference
     186    38702348 :     auto &this_op_scheme = state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr);
     187             : 
     188             :     // Load the 'range variable' according to the type of control scheme specified
     189    38702348 :     switch (CurSchemeType) {
     190     1160704 :     case OpScheme::Uncontrolled:
     191             :     case OpScheme::CompSetPtBased: {
     192             :         // No RangeVariable specified for these types
     193     1160704 :         break;
     194             :     }
     195      322816 :     case OpScheme::EMS: {
     196      322816 :         InitLoadDistribution(state, FirstHVACIteration);
     197             :         // No RangeVariable specified for these types
     198      322816 :         break;
     199             :     }
     200    15895078 :     case OpScheme::HeatingRB: {
     201             :         // For zero demand, we need to clean things out before we leave
     202    15895078 :         if (LoopDemand < SmallLoad) {
     203     6793266 :             InitLoadDistribution(state, FirstHVACIteration);
     204     6793266 :             this_component.MyLoad = 0.0;
     205     6793266 :             this_component.ON = false;
     206     6793266 :             return;
     207             :         }
     208     9101812 :         RangeVariable = LoopDemand;
     209     9101812 :         break;
     210             :     }
     211    20865874 :     case OpScheme::CoolingRB: {
     212             :         // For zero demand, we need to clean things out before we leave
     213    20865874 :         if (LoopDemand > (-1.0 * SmallLoad)) {
     214    12437831 :             InitLoadDistribution(state, FirstHVACIteration);
     215    12437831 :             this_component.MyLoad = 0.0;
     216    12437831 :             this_component.ON = false;
     217    12437831 :             return;
     218             :         }
     219     8428043 :         RangeVariable = LoopDemand;
     220     8428043 :         break;
     221             :     }
     222       14544 :     case OpScheme::DryBulbRB: {
     223       14544 :         RangeVariable = state.dataEnvrn->OutDryBulbTemp;
     224       14544 :         break;
     225             :     }
     226       14544 :     case OpScheme::WetBulbRB: {
     227       14544 :         RangeVariable = state.dataEnvrn->OutWetBulbTemp;
     228       14544 :         break;
     229             :     }
     230       14544 :     case OpScheme::RelHumRB: {
     231       14544 :         RangeVariable = state.dataEnvrn->OutRelHum;
     232       14544 :         break;
     233             :     }
     234       14544 :     case OpScheme::DewPointRB: {
     235       14544 :         RangeVariable = state.dataEnvrn->OutDewPointTemp;
     236       14544 :         break;
     237             :     }
     238      399700 :     case OpScheme::DryBulbTDB:
     239             :     case OpScheme::WetBulbTDB:
     240             :     case OpScheme::DewPointTDB: {
     241      399700 :         RangeVariable = FindRangeVariable(state, plantLoc.loopNum, CurSchemePtr, CurSchemeType);
     242      399700 :         break;
     243             :     }
     244           0 :     default: {
     245             :         // No controls specified.  This is a fatal error
     246           0 :         ShowFatalError(state,
     247           0 :                        format("Invalid Operation Scheme Type Requested={}, in ManagePlantLoadDistribution",
     248           0 :                               state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).TypeOf));
     249             :     }
     250             :     }
     251             : 
     252    19471251 :     switch (CurSchemeType) {
     253           0 :     case OpScheme::Uncontrolled: {
     254             :         //!***what else do we do with 'uncontrolled' equipment?
     255             :         // There's an equipment list...but I think the idea is to just
     256             :         // Set one component to run in an 'uncontrolled' way (whatever that means!)
     257           0 :         break;
     258             :     }
     259     1160704 :     case OpScheme::CompSetPtBased: {
     260             :         // check for EMS Control
     261     1160704 :         TurnOnPlantLoopPipes(state, plantLoc.loopNum, plantLoc.loopSideNum);
     262     1160704 :         FindCompSPLoad(state, plantLoc, CurCompLevelOpNum);
     263     1160704 :         break;
     264             :     }
     265      322816 :     case OpScheme::EMS: {
     266      322816 :         TurnOnPlantLoopPipes(state, plantLoc.loopNum, plantLoc.loopSideNum);
     267      322816 :         DistributeUserDefinedPlantLoad(state, plantLoc, CurCompLevelOpNum, CurSchemePtr, LoopDemand, RemLoopDemand);
     268      322816 :         break;
     269             :     }
     270    17987731 :     default: { // it's a range based control type with multiple equipment lists
     271    17987731 :         CurListNum = 0;
     272    18417031 :         for (ListNum = 1; ListNum <= NumEquipLists; ++ListNum) {
     273             :             // setpointers to 'PlantLoop()%OpScheme()...'structure
     274    18125893 :             ListPtr = this_component.OpScheme(CurCompLevelOpNum).EquipList(ListNum).ListPtr;
     275    18125893 :             RangeHiLimit = this_op_scheme.EquipList(ListPtr).RangeUpperLimit;
     276    18125893 :             RangeLoLimit = this_op_scheme.EquipList(ListPtr).RangeLowerLimit;
     277    18125893 :             if (CurSchemeType == OpScheme::HeatingRB || CurSchemeType == OpScheme::CoolingRB) {
     278             :                 // these limits are stored with absolute values, but the LoopDemand can be negative for cooling
     279    17638075 :                 TestRangeVariable = std::abs(RangeVariable);
     280             :             } else {
     281      487818 :                 TestRangeVariable = RangeVariable;
     282             :             }
     283             : 
     284             :             // trying to do something where the last stage still runs the equipment but at the hi limit.
     285             : 
     286    18125893 :             if (TestRangeVariable < RangeLoLimit || TestRangeVariable > RangeHiLimit) {
     287      465708 :                 if ((TestRangeVariable > RangeHiLimit) && (ListPtr == this_op_scheme.EquipListNumForLastStage)) {
     288             :                     // let this go thru, later AdjustChangeInLoadForLastStageUpperRangeLimit will cap dispatch to RangeHiLimit
     289       36408 :                     CurListNum = ListNum;
     290       36408 :                     break;
     291             :                 } else {
     292      429300 :                     continue;
     293             :                 }
     294             :             } else {
     295    17660185 :                 CurListNum = ListNum;
     296    17660185 :                 break;
     297             :             }
     298             :         }
     299             : 
     300    17987731 :         if (CurListNum > 0) {
     301             :             // there could be equipment on another list that needs to be nulled out, it may have a load from earlier iteration
     302    35644218 :             for (ListNum = 1; ListNum <= NumEquipLists; ++ListNum) {
     303    17947625 :                 if (ListNum == CurListNum) continue; // leave current one alone
     304      251032 :                 NumCompsOnList = this_op_scheme.EquipList(ListNum).NumComps;
     305      582618 :                 for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
     306      331586 :                     EquipBranchNum = this_op_scheme.EquipList(ListNum).Comp(CompIndex).BranchNumPtr;
     307      331586 :                     EquipCompNum = this_op_scheme.EquipList(ListNum).Comp(CompIndex).CompNumPtr;
     308      331586 :                     loop_side.Branch(EquipBranchNum).Comp(EquipCompNum).MyLoad = 0.0;
     309             :                 }
     310             :             }
     311    17696593 :             if (this_op_scheme.EquipList(ListPtr).NumComps > 0) {
     312    17696593 :                 TurnOnPlantLoopPipes(state, plantLoc.loopNum, plantLoc.loopSideNum);
     313    17696593 :                 DistributePlantLoad(state, plantLoc.loopNum, plantLoc.loopSideNum, CurSchemePtr, ListPtr, LoopDemand, RemLoopDemand);
     314    17696593 :                 LoadDistributionWasPerformed = true;
     315             :             }
     316             :         }
     317             : 
     318             :     } // End of range based schemes
     319             :     }
     320             : }
     321             : 
     322             : // Beginning of GetInput subroutines for the Module
     323             : //******************************************************************************
     324             : 
     325         458 : void GetPlantOperationInput(EnergyPlusData &state, bool &GetInputOK)
     326             : {
     327             : 
     328             :     // SUBROUTINE INFORMATION:
     329             :     //       AUTHOR         Dan Fisher
     330             :     //       DATE WRITTEN   October 1998
     331             :     //       MODIFIED       July 2010, Dan Fisher, restructure input data
     332             :     //       RE-ENGINEERED  na
     333             : 
     334             :     // PURPOSE OF THIS SUBROUTINE: This subroutine reads the primary plant loop
     335             :     // operation schemes from the input file
     336             : 
     337             :     // METHODOLOGY EMPLOYED: calls the Input Processor to retrieve data from input file.
     338             :     // The format of the Energy+.idd (the EnergyPlus input data dictionary) for the
     339             :     // following keywords is reflected exactly in this subroutine:
     340             :     //    PlantEquipmentOperationSchemes
     341             :     //    CondenserEquipmentOperationSchemes
     342             : 
     343             :     // Using/Aliasing
     344             :     using ScheduleManager::GetScheduleIndex;
     345             : 
     346             :     // SUBROUTINE PARAMETER DEFINITIONS:
     347             :     static constexpr std::string_view RoutineName("GetPlantOperationInput: "); // include trailing blank space
     348             : 
     349             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     350             :     int LoopNum;           // Loop counter (Plant or Cond)
     351             :     int OpNum;             // Scheme counter
     352             :     int Num;               // Item counter
     353             :     int NumPlantOpSchemes; // Total Number of PlantEquipmentOperationSchemes
     354             :     int NumCondOpSchemes;  // Total Number of CondenserEquipmentOperationSchemes
     355             :     int NumAlphas;         // Number of alpha items in the input object
     356             :     int NumNums;           // Number of numeric items in the input object
     357             :     int IOStat;
     358         458 :     std::string PlantOpSchemeName;   // Name of the plant or condenser operating scheme
     359         458 :     std::string CurrentModuleObject; // for ease in renaming
     360         458 :     std::string PlantLoopObject;     // for ease in renaming
     361             :     bool ErrorsFound;                // Passed in from OpSchemeInput
     362             : 
     363         458 :     ErrorsFound = false;
     364             : 
     365         458 :     if (!allocated(state.dataPlnt->PlantLoop)) {
     366           0 :         GetInputOK = false;
     367           0 :         return;
     368             :     } else {
     369         458 :         GetInputOK = true;
     370             :     }
     371             : 
     372             :     // get number of operation schemes
     373         458 :     CurrentModuleObject = "PlantEquipmentOperationSchemes";
     374         458 :     NumPlantOpSchemes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     375        1341 :     for (OpNum = 1; OpNum <= NumPlantOpSchemes; ++OpNum) {
     376        1766 :         state.dataInputProcessing->inputProcessor->getObjectItem(
     377         883 :             state, CurrentModuleObject, OpNum, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
     378         883 :         if (Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound)) continue;
     379             :     }
     380             : 
     381         458 :     CurrentModuleObject = "CondenserEquipmentOperationSchemes";
     382         458 :     NumCondOpSchemes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     383         718 :     for (OpNum = 1; OpNum <= NumCondOpSchemes; ++OpNum) {
     384         520 :         state.dataInputProcessing->inputProcessor->getObjectItem(
     385         260 :             state, CurrentModuleObject, OpNum, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
     386         260 :         if (Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound)) continue;
     387             :     }
     388             : 
     389             :     // Load the Plant data structure
     390        1605 :     for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
     391        1147 :         PlantOpSchemeName = state.dataPlnt->PlantLoop(LoopNum).OperationScheme;
     392        1147 :         if (LoopNum <= state.dataHVACGlobal->NumPlantLoops) {
     393         889 :             CurrentModuleObject = "PlantEquipmentOperationSchemes";
     394         889 :             PlantLoopObject = "PlantLoop";
     395             :         } else {
     396         258 :             CurrentModuleObject = "CondenserEquipmentOperationSchemes";
     397         258 :             PlantLoopObject = "CondenserLoop";
     398             :         }
     399        1147 :         OpNum = state.dataInputProcessing->inputProcessor->getObjectItemNum(state, CurrentModuleObject, PlantOpSchemeName);
     400        1147 :         if (OpNum > 0) {
     401        2294 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     402             :                                                                      CurrentModuleObject,
     403             :                                                                      OpNum,
     404        1147 :                                                                      state.dataIPShortCut->cAlphaArgs,
     405             :                                                                      NumAlphas,
     406        1147 :                                                                      state.dataIPShortCut->rNumericArgs,
     407             :                                                                      NumNums,
     408             :                                                                      IOStat,
     409        1147 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     410        1147 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     411        1147 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     412        1147 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     413        1147 :             state.dataPlnt->PlantLoop(LoopNum).NumOpSchemes = (NumAlphas - 1) / 3;
     414        1147 :             if (state.dataPlnt->PlantLoop(LoopNum).NumOpSchemes > 0) {
     415        1147 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme.clear();
     416        1147 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme.allocate(state.dataPlnt->PlantLoop(LoopNum).NumOpSchemes);
     417        2416 :                 for (Num = 1; Num <= state.dataPlnt->PlantLoop(LoopNum).NumOpSchemes; ++Num) {
     418        1269 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).TypeOf = state.dataIPShortCut->cAlphaArgs(Num * 3 - 1);
     419             : 
     420             :                     {
     421        1269 :                         std::string const &plantLoopOperation = state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).TypeOf;
     422        1269 :                         if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:COOLINGLOAD") {
     423         695 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::CoolingRB;
     424         574 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:HEATINGLOAD") {
     425         494 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::HeatingRB;
     426          80 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:COMPONENTSETPOINT") { //* Temp Based Control
     427          14 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::CompSetPtBased;
     428          66 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:CHILLERHEATERCHANGEOVER") {
     429          10 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::ChillerHeaterSupervisory;
     430          56 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:THERMALENERGYSTORAGE") { //* Simple TES Control
     431           1 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type =
     432             :                                 OpScheme::CompSetPtBased; // set this to component based as it will be converted to this
     433          55 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:USERDEFINED") {
     434           6 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::EMS;
     435           6 :                             state.dataPlnt->AnyEMSPlantOpSchemesInModel = true;
     436          49 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDRYBULB") {
     437           1 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::DryBulbRB;
     438          48 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORWETBULB") {
     439           1 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::WetBulbRB;
     440          47 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDEWPOINT") {
     441           1 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::DewPointRB;
     442          46 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORRELATIVEHUMIDITY") {
     443           1 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::RelHumRB;
     444          45 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDRYBULBDIFFERENCE") {
     445           1 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::DryBulbTDB;
     446          44 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORWETBULBDIFFERENCE") {
     447           1 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::WetBulbTDB;
     448          43 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDEWPOINTDIFFERENCE") {
     449           1 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::DewPointTDB;
     450          42 :                         } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:UNCONTROLLED") {
     451          42 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::Uncontrolled;
     452             :                         } else { // invalid op scheme type for plant loop
     453           0 :                             ShowSevereError(state,
     454           0 :                                             format("{}Invalid {}={}, entered in {}={}",
     455             :                                                    RoutineName,
     456           0 :                                                    state.dataIPShortCut->cAlphaFieldNames(Num * 3 - 1),
     457           0 :                                                    state.dataIPShortCut->cAlphaArgs(Num * 3 - 1),
     458             :                                                    CurrentModuleObject,
     459           0 :                                                    state.dataIPShortCut->cAlphaArgs(1)));
     460           0 :                             ErrorsFound = true;
     461             :                         }
     462             :                     }
     463             : 
     464        1269 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Name = state.dataIPShortCut->cAlphaArgs(Num * 3);
     465        1269 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Sched = state.dataIPShortCut->cAlphaArgs(Num * 3 + 1);
     466        1269 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).SchedPtr =
     467        1269 :                         GetScheduleIndex(state, state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Sched);
     468        1269 :                     if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).SchedPtr == 0) {
     469           0 :                         ShowSevereError(state,
     470           0 :                                         format("{}Invalid {} = \"{}\", entered in {}= \"{}\".",
     471             :                                                RoutineName,
     472           0 :                                                state.dataIPShortCut->cAlphaFieldNames(Num * 3 + 1),
     473           0 :                                                state.dataIPShortCut->cAlphaArgs(Num * 3 + 1),
     474             :                                                CurrentModuleObject,
     475           0 :                                                state.dataIPShortCut->cAlphaArgs(1)));
     476           0 :                         ErrorsFound = true;
     477             :                     }
     478             :                 }
     479             :             } else {
     480           0 :                 ShowSevereError(state,
     481           0 :                                 format("{} = \"{}\", requires at least {}, {} and {} to be specified.",
     482             :                                        CurrentModuleObject,
     483           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
     484           0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
     485           0 :                                        state.dataIPShortCut->cAlphaFieldNames(3),
     486           0 :                                        state.dataIPShortCut->cAlphaFieldNames(4)));
     487           0 :                 ErrorsFound = true;
     488             :             }
     489             :         } else {
     490           0 :             ShowSevereError(state, format("{}{}={} is expecting", RoutineName, PlantLoopObject, state.dataPlnt->PlantLoop(LoopNum).Name));
     491           0 :             ShowContinueError(state, format("{}={}, but not found.", CurrentModuleObject, PlantOpSchemeName));
     492           0 :             ErrorsFound = true;
     493             :         }
     494             :     }
     495             : 
     496         458 :     if (ErrorsFound) {
     497           0 :         ShowFatalError(
     498           0 :             state, format("{}Errors found in getting input for PlantEquipmentOperationSchemes or CondenserEquipmentOperationSchemes", RoutineName));
     499             :     }
     500         458 : }
     501             : 
     502         458 : void GetOperationSchemeInput(EnergyPlusData &state)
     503             : {
     504             : 
     505             :     // SUBROUTINE INFORMATION:
     506             :     //       AUTHOR         Dan Fisher
     507             :     //       DATE WRITTEN   October 1998
     508             :     //       MODIFIED       August 2001, LKL -- Validations
     509             :     //       RE-ENGINEERED  July 2010, Dan Fisher, restructure input data
     510             : 
     511             :     // PURPOSE OF THIS SUBROUTINE:
     512             :     // This subroutine reads the primary plant loop
     513             :     // operation schemes from the input file
     514             : 
     515             :     // METHODOLOGY EMPLOYED:
     516             :     // calls the Input Processor to retrieve data from input file.
     517             :     // The format of the Energy+.idd (the EnergyPlus input data dictionary) for the
     518             :     // following keywords is reflected exactly in this subroutine:
     519             :     //    PlantEquipmentOperation:*
     520             : 
     521             :     // Using/Aliasing
     522             :     using namespace DataLoopNode;
     523             :     using namespace DataSizing;
     524             : 
     525             :     // SUBROUTINE PARAMETER DEFINITIONS:
     526             :     static constexpr std::string_view RoutineName("GetOperationSchemeInput: "); // include trailing blank space
     527             : 
     528             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     529             :     int SchemeNum;
     530             :     int Num;
     531             :     int NumAlphas;
     532             :     int NumNums;
     533             :     int IOStat;
     534             :     bool ErrorsFound;           // May be set here and passed on
     535             :     int CLRBO;                  // Number ofCooling Load Range Based Operation Inputs
     536             :     int HLRBO;                  // Number ofHeating Load Range Based Operation Inputs
     537             :     int DBRBO;                  // Number ofDry Bulb Temperature Range Based Operation Inputs
     538             :     int WBRBO;                  // Number ofWet Bulb Temperature Range Based Operation Inputs
     539             :     int DPRBO;                  // Number ofDewPoint Temperature Range Based Operation Inputs
     540             :     int RHRBO;                  // Number ofRelative Humidity Range Based Operation Inputs
     541             :     int CSPBO;                  // Number of Component SetPoint Based Operation Inputs
     542             :     int DBTDBO;                 // Number ofDry Bulb Temperature Range Based Operation Inputs
     543             :     int WBTDBO;                 // Number ofWet Bulb Temperature Range Based Operation Inputs
     544             :     int DPTDBO;                 // Number ofDewPoint Temperature Range Based Operation Inputs
     545             :     int TESSPBO;                // Number of Thermal Energy Storage Setpoint Based Operation Inputs
     546             :     int ACXSPBO;                // Number of Chiller Heater setpoint based operation inputs
     547             :     int NumSchemes;             // Number of Condenser equipment lists
     548             :     int NumUncontrolledSchemes; // Number of Condenser equipment lists
     549             :     int NumUserDefOpSchemes;    // number of user defined EMS op schemes
     550             :     int CELists;                // Number of Condenser equipment lists
     551             :     int PELists;                // Number of Plant equipment lists
     552             :     int Count;                  // Loop counter
     553             :     int NumSchemeLists;
     554             :     int LoopNum;
     555         458 :     std::string CurrentModuleObject; // for ease in renaming.
     556         458 :     std::unordered_map<std::string, std::string> UniqueNames;
     557             : 
     558         458 :     ErrorsFound = false;
     559             : 
     560             :     //**********VERIFY THE 'PLANTEQUIPMENTOPERATION:...' KEYWORDS**********
     561         458 :     CLRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:CoolingLoad");
     562         458 :     HLRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:HeatingLoad");
     563         458 :     DBRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorDryBulb");
     564         458 :     WBRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorWetBulb");
     565         458 :     DPRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorDewpoint");
     566         458 :     RHRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorRelativeHumidity");
     567         458 :     CSPBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:ComponentSetpoint"); //* Temp Based Control
     568         458 :     NumUserDefOpSchemes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:UserDefined");
     569         458 :     DBTDBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorDryBulbDifference");
     570         458 :     WBTDBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorWetBulbDifference");
     571         458 :     DPTDBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorDewpointDifference");
     572         458 :     TESSPBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:ThermalEnergyStorage");
     573         458 :     ACXSPBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:ChillerHeaterChangeover");
     574         458 :     NumSchemes = CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO + NumUserDefOpSchemes + TESSPBO + ACXSPBO;
     575         458 :     NumUncontrolledSchemes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:Uncontrolled");
     576         458 :     if ((NumSchemes + NumUncontrolledSchemes) <= 0) {
     577           0 :         ShowFatalError(state, "No PlantEquipmentOperation:* objects specified. Stop simulation.");
     578             :     }
     579             : 
     580             :     // test for blank or duplicates -- this section just determines if there are any duplicate operation scheme names
     581         458 :     UniqueNames.reserve(static_cast<unsigned>(NumSchemes));
     582             : 
     583             :     // Check for existence of duplicates in keyword names
     584         458 :     Count = 0;
     585        1687 :     for (Num = 1; Num <= NumSchemes; ++Num) {
     586        1229 :         if (CLRBO > 0 && Num <= CLRBO) {
     587         704 :             CurrentModuleObject = "PlantEquipmentOperation:CoolingLoad";
     588         704 :             Count = Num;
     589         525 :         } else if (HLRBO > 0 && Num <= (CLRBO + HLRBO)) {
     590         494 :             CurrentModuleObject = "PlantEquipmentOperation:HeatingLoad";
     591         494 :             Count = Num - CLRBO;
     592          31 :         } else if (DBRBO > 0 && Num <= (CLRBO + HLRBO + DBRBO)) {
     593           1 :             CurrentModuleObject = "PlantEquipmentOperation:OutdoorDryBulb";
     594           1 :             Count = Num - CLRBO - HLRBO;
     595          30 :         } else if (WBRBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO)) {
     596           1 :             CurrentModuleObject = "PlantEquipmentOperation:OutdoorWetBulb";
     597           1 :             Count = Num - CLRBO - HLRBO - DBRBO;
     598          29 :         } else if (DPRBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO)) {
     599           1 :             CurrentModuleObject = "PlantEquipmentOperation:OutdoorDewpoint";
     600           1 :             Count = Num - CLRBO - HLRBO - DBRBO - WBRBO;
     601          28 :         } else if (RHRBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO)) {
     602           1 :             CurrentModuleObject = "PlantEquipmentOperation:OutdoorRelativeHumidity";
     603           1 :             Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO;
     604          27 :         } else if (CSPBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO)) {
     605          14 :             CurrentModuleObject = "PlantEquipmentOperation:ComponentSetpoint";
     606          14 :             Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO;
     607          13 :         } else if (DBTDBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO)) {
     608           1 :             CurrentModuleObject = "PlantEquipmentOperation:OutdoorDryBulbDifference";
     609           1 :             Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO;
     610          12 :         } else if (WBTDBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO)) {
     611           1 :             CurrentModuleObject = "PlantEquipmentOperation:OutdoorWetBulbDifference";
     612           1 :             Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO;
     613          11 :         } else if (DPTDBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO)) {
     614           1 :             CurrentModuleObject = "PlantEquipmentOperation:OutdoorDewpointDifference";
     615           1 :             Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO - WBTDBO;
     616          10 :         } else if (NumUncontrolledSchemes > 0 &&
     617           1 :                    Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO + NumUncontrolledSchemes)) {
     618           1 :             CurrentModuleObject = "PlantEquipmentOperation:Uncontrolled";
     619           1 :             Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO - WBTDBO - DPTDBO;
     620           9 :         } else if (NumUserDefOpSchemes > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO +
     621           6 :                                                       NumUncontrolledSchemes + NumUserDefOpSchemes)) {
     622           6 :             CurrentModuleObject = "PlantEquipmentOperation:UserDefined";
     623           6 :             Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO - WBTDBO - DPTDBO - NumUncontrolledSchemes;
     624           3 :         } else if (TESSPBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO + NumUncontrolledSchemes +
     625           1 :                                           NumUserDefOpSchemes + TESSPBO)) {
     626           1 :             CurrentModuleObject = "PlantEquipmentOperation:ThermalEnergyStorage";
     627           1 :             Count =
     628           1 :                 Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO - WBTDBO - DPTDBO - NumUncontrolledSchemes - NumUserDefOpSchemes;
     629           2 :         } else if (ACXSPBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO + NumUncontrolledSchemes +
     630           2 :                                           NumUserDefOpSchemes + TESSPBO + ACXSPBO)) {
     631           2 :             CurrentModuleObject = "PlantEquipmentOperation:ChillerHeaterChangeover";
     632           2 :             Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO - WBTDBO - DPTDBO - NumUncontrolledSchemes -
     633             :                     NumUserDefOpSchemes - TESSPBO;
     634             :         } else {
     635           0 :             ShowFatalError(state, "Error in control scheme identification");
     636             :         }
     637             : 
     638        2458 :         state.dataInputProcessing->inputProcessor->getObjectItem(
     639        1229 :             state, CurrentModuleObject, Count, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
     640        1229 :         if (GlobalNames::VerifyUniqueInterObjectName(state, UniqueNames, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound)) {
     641           0 :             continue;
     642             :         }
     643             :     }
     644             : 
     645             :     //**********VERIFY THE 'PlantEquipmentList' AND 'CondenserEquipmentList' KEYWORDS*********
     646         458 :     PELists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentList");
     647         458 :     CELists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "CondenserEquipmentList");
     648         458 :     NumSchemeLists = PELists + CELists;
     649         458 :     UniqueNames.clear();
     650         458 :     UniqueNames.reserve(NumSchemeLists);
     651         458 :     Count = 0;
     652        1952 :     for (Num = 1; Num <= NumSchemeLists; ++Num) {
     653        1494 :         if (Num <= PELists) {
     654        1225 :             CurrentModuleObject = "PlantEquipmentList";
     655        1225 :             Count = Num;
     656             :         } else {
     657         269 :             CurrentModuleObject = "CondenserEquipmentList";
     658         269 :             Count = Num - PELists;
     659             :         }
     660        2988 :         state.dataInputProcessing->inputProcessor->getObjectItem(
     661        1494 :             state, CurrentModuleObject, Count, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
     662        1494 :         if (GlobalNames::VerifyUniqueInterObjectName(state, UniqueNames, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound)) {
     663           0 :             continue;
     664             :         }
     665             :     }
     666             : 
     667             :     //**********GET INPUT AND LOAD PLANT DATA STRUCTURE*********
     668             : 
     669             :     // extend number of equipment lists to include one for each CSPBO
     670         458 :     NumSchemeLists += CSPBO + TESSPBO + NumUserDefOpSchemes;
     671        1605 :     for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
     672        2416 :         for (SchemeNum = 1; SchemeNum <= state.dataPlnt->PlantLoop(LoopNum).NumOpSchemes; ++SchemeNum) {
     673             : 
     674             :             {
     675        1269 :                 std::string const &plantLoopOperation = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).TypeOf;
     676             : 
     677        1269 :                 if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:COOLINGLOAD") {
     678         695 :                     CurrentModuleObject = "PlantEquipmentOperation:CoolingLoad";
     679         695 :                     FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, CLRBO, LoopNum, SchemeNum, ErrorsFound);
     680             : 
     681         574 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:HEATINGLOAD") {
     682         494 :                     CurrentModuleObject = "PlantEquipmentOperation:HeatingLoad";
     683         494 :                     FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, HLRBO, LoopNum, SchemeNum, ErrorsFound);
     684             : 
     685          80 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:COMPONENTSETPOINT") { //* Temp Based Control
     686          14 :                     CurrentModuleObject = "PlantEquipmentOperation:ComponentSetPoint";
     687          14 :                     FindCompSPInput(state, CurrentModuleObject, CSPBO, LoopNum, SchemeNum, ErrorsFound);
     688             : 
     689          66 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:USERDEFINED") {
     690           6 :                     CurrentModuleObject = "PlantEquipmentOperation:UserDefined";
     691           6 :                     GetUserDefinedOpSchemeInput(state, CurrentModuleObject, NumUserDefOpSchemes, LoopNum, SchemeNum, ErrorsFound);
     692             : 
     693          60 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDRYBULB") {
     694           1 :                     CurrentModuleObject = "PlantEquipmentOperation:OutdoorDryBulb";
     695           1 :                     FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, DBRBO, LoopNum, SchemeNum, ErrorsFound);
     696             : 
     697          59 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORWETBULB") {
     698           1 :                     CurrentModuleObject = "PlantEquipmentOperation:OutdoorWetBulb";
     699           1 :                     FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, WBRBO, LoopNum, SchemeNum, ErrorsFound);
     700             : 
     701          58 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDEWPOINT") {
     702           1 :                     CurrentModuleObject = "PlantEquipmentOperation:OutdoorDewPoint";
     703           1 :                     FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, DPRBO, LoopNum, SchemeNum, ErrorsFound);
     704             : 
     705          57 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORRELATIVEHUMIDITY") {
     706           1 :                     CurrentModuleObject = "PlantEquipmentOperation:OutdoorrelativeHumidity";
     707           1 :                     FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, RHRBO, LoopNum, SchemeNum, ErrorsFound);
     708             : 
     709          56 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDRYBULBDIFFERENCE") {
     710           1 :                     CurrentModuleObject = "PlantEquipmentOperation:OutdoorDryBulbDifference";
     711           1 :                     FindDeltaTempRangeInput(state,
     712             :                                             DataLoopNode::ConnectionObjectType::PlantEquipmentOperationOutdoorDrybulbDifference,
     713             :                                             DBTDBO,
     714             :                                             LoopNum,
     715             :                                             SchemeNum,
     716             :                                             ErrorsFound);
     717             : 
     718          55 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORWETBULBDIFFERENCE") {
     719           1 :                     CurrentModuleObject = "PlantEquipmentOperation:OutdoorWetBulbDifference";
     720           1 :                     FindDeltaTempRangeInput(state,
     721             :                                             DataLoopNode::ConnectionObjectType::PlantEquipmentOperationOutdoorWetbulbDifference,
     722             :                                             WBTDBO,
     723             :                                             LoopNum,
     724             :                                             SchemeNum,
     725             :                                             ErrorsFound);
     726             : 
     727          54 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDEWPOINTDIFFERENCE") {
     728           1 :                     CurrentModuleObject = "PlantEquipmentOperation:OutdoorDewPointDifference";
     729           1 :                     FindDeltaTempRangeInput(state,
     730             :                                             DataLoopNode::ConnectionObjectType::PlantEquipmentOperationOutdoorDewpointDifference,
     731             :                                             DPTDBO,
     732             :                                             LoopNum,
     733             :                                             SchemeNum,
     734             :                                             ErrorsFound);
     735             : 
     736          53 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:UNCONTROLLED") {
     737          42 :                     CurrentModuleObject = "PlantEquipmentOperation:Uncontrolled";
     738          42 :                     FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, NumUncontrolledSchemes, LoopNum, SchemeNum, ErrorsFound);
     739             : 
     740          11 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:THERMALENERGYSTORAGE") { //* Temp Based Control
     741           1 :                     CurrentModuleObject = "PlantEquipmentOperation:ThermalEnergyStorage";
     742           1 :                     FindCompSPInput(state, CurrentModuleObject, TESSPBO, LoopNum, SchemeNum, ErrorsFound);
     743             : 
     744          10 :                 } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:CHILLERHEATERCHANGEOVER") {
     745          10 :                     CurrentModuleObject = "PlantEquipmentOperation:ChillerHeaterChangeover";
     746          10 :                     GetChillerHeaterChangeoverOpSchemeInput(state, CurrentModuleObject, ACXSPBO, ErrorsFound);
     747             : 
     748             :                 } else { // invalid op scheme type for plant loop
     749             :                     // Seems like the alpha args below is incorrect....
     750           0 :                     ShowSevereError(state,
     751           0 :                                     format("Invalid operation scheme type = \"{}\", entered in {}={}",
     752           0 :                                            state.dataIPShortCut->cAlphaArgs(Num * 3 - 1),
     753             :                                            CurrentModuleObject,
     754           0 :                                            state.dataIPShortCut->cAlphaArgs(1)));
     755           0 :                     ErrorsFound = true;
     756             :                 }
     757             :             }
     758             : 
     759             :             // At this point, switch the thermal energy storage controls to setpoint based controls as all of the
     760             :             // internally generated setpoints and schedules have been generated and this can now be handled like
     761             :             // the long form setpoint based control.
     762        1269 :             if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).TypeOf == "PLANTEQUIPMENTOPERATION:THERMALENERGYSTORAGE") {
     763           1 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).TypeOf = "PLANTEQUIPMENTOPERATION:COMPONENTSETPOINT";
     764             :             }
     765             :         }
     766             :     }
     767             : 
     768             :     // Validate that component names/types in each list correspond to a valid component in input file
     769         458 :     if (ErrorsFound) {
     770           0 :         ShowFatalError(state, format("{}Errors found getting inputs. Previous error(s) cause program termination.", RoutineName));
     771             :     }
     772         458 : }
     773             : 
     774        1235 : void FindRangeBasedOrUncontrolledInput(EnergyPlusData &state,
     775             :                                        std::string &CurrentModuleObject, // for ease in renaming
     776             :                                        int const NumSchemes,             // May be set here and passed on
     777             :                                        int const LoopNum,                // May be set here and passed on
     778             :                                        int const SchemeNum,              // May be set here and passed on
     779             :                                        bool &ErrorsFound                 // May be set here and passed on
     780             : )
     781             : {
     782             :     // SUBROUTINE INFORMATION:
     783             :     //       AUTHOR         Dan Fisher
     784             :     //       DATE WRITTEN   July 2010
     785             :     //       MODIFIED       Chandan Sharma, August 2010
     786             :     //       RE-ENGINEERED  na
     787             : 
     788             :     // PURPOSE OF THIS SUBROUTINE:
     789             :     // Load range based or uncontrolled input into PLANTLOOP data structure
     790             : 
     791             :     // METHODOLOGY EMPLOYED:
     792             :     // calls the Input Processor to retrieve data from input file.
     793             :     // The format of the Energy+.idd (the EnergyPlus input data dictionary) for the
     794             :     // following keywords is reflected exactly in this subroutine:
     795             :     //       PlantEquipmentOperation:CoolingLoad
     796             :     //       PlantEquipmentOperation:HeatingLoad
     797             :     //       PlantEquipmentOperation:OutdoorDryBulb
     798             :     //       PlantEquipmentOperation:OutdoorWetBulb
     799             :     //       PlantEquipmentOperation:OutdoorDewPoint
     800             :     //       PlantEquipmentOperation:OutdoorRelativeHumidity
     801             :     //       PlantEquipmentOperation:Uncontrolled
     802             : 
     803             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     804             :     int NumAlphas;
     805             :     int NumNums;
     806             :     int IOStat;
     807        1235 :     Array1D_string AlphArray;      // Alpha input items for object
     808        1235 :     Array1D_string cAlphaFields;   // Alpha field names
     809        1235 :     Array1D_string cNumericFields; // Numeric field names
     810        1235 :     Array1D<Real64> NumArray;      // Numeric input items for object
     811        1235 :     Array1D_bool lAlphaBlanks;     // Logical array, alpha field input BLANK = .TRUE.
     812        1235 :     Array1D_bool lNumericBlanks;   // Logical array, numeric field input BLANK = .TRUE.
     813        1235 :     int TotalArgs(0);              // Total number of alpha and numeric arguments (max) for a
     814             :     //   certain object in the input file
     815             :     int Num;
     816             :     int NumEquipLists;
     817             :     int ListNum;
     818        1235 :     std::string LoopOpSchemeObj; // Used to identify the object name for loop equipment operation scheme
     819             :     bool SchemeNameFound;        // Set to FALSE if a match of OpScheme object and OpScheme name is not found
     820             :     int InnerListNum;            // inner loop list number
     821             :     Real64 OuterListNumLowerLimit;
     822             :     Real64 OuterListNumUpperLimit;
     823             :     Real64 InnerListNumLowerLimit;
     824             :     Real64 InnerListNumUpperLimit;
     825             : 
     826        1235 :     SchemeNameFound = true;
     827             : 
     828             :     // Determine max number of alpha and numeric arguments for all objects being read, in order to allocate local arrays
     829        1235 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     830             : 
     831        1235 :     AlphArray.allocate(NumAlphas);
     832        1235 :     cAlphaFields.allocate(NumAlphas);
     833        1235 :     cNumericFields.allocate(NumNums);
     834        1235 :     NumArray.dimension(NumNums, 0.0);
     835        1235 :     lAlphaBlanks.dimension(NumAlphas, true);
     836        1235 :     lNumericBlanks.dimension(NumNums, true);
     837             : 
     838        1235 :     if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
     839         982 :         LoopOpSchemeObj = "PlantEquipmentOperationSchemes";
     840         253 :     } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Condenser) {
     841         253 :         LoopOpSchemeObj = "CondenserEquipmentOperationSchemes";
     842             :     }
     843             : 
     844        1235 :     if (NumSchemes > 0) {
     845        1745 :         for (Num = 1; Num <= NumSchemes; ++Num) {
     846        1745 :             state.dataInputProcessing->inputProcessor->getObjectItem(
     847             :                 state, CurrentModuleObject, Num, AlphArray, NumAlphas, NumArray, NumNums, IOStat);
     848        1745 :             if (Util::SameString(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name, AlphArray(1))) break;
     849         510 :             if (Num == NumSchemes) {
     850           0 :                 ShowSevereError(state,
     851           0 :                                 format("{} = \"{}\", could not find {} = \"{}\".",
     852             :                                        LoopOpSchemeObj,
     853           0 :                                        state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
     854             :                                        CurrentModuleObject,
     855           0 :                                        state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
     856           0 :                 ErrorsFound = true;
     857           0 :                 SchemeNameFound = false;
     858             :             }
     859             :         }
     860        1235 :         if (SchemeNameFound) {
     861        1235 :             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists = (NumAlphas - 1);
     862        1235 :             if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists <= 0) {
     863           0 :                 ShowSevereError(state, format("{} = \"{}\", specified without equipment list.", CurrentModuleObject, AlphArray(1)));
     864           0 :                 ErrorsFound = true;
     865             :             } else {
     866        2470 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList.allocate(
     867        1235 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists);
     868        1235 :                 NumEquipLists = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists;
     869        1235 :                 if (NumNums <= 0) {          // Uncontrolled OpScheme type
     870          42 :                     ListNum = NumEquipLists; // NumEquipLists is always 1 for Uncontrolled OpScheme type
     871          42 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Name = AlphArray(2);
     872          42 :                     LoadEquipList(state, LoopNum, SchemeNum, ListNum, ErrorsFound);
     873             :                 } else { // Range based OpScheme type
     874        2541 :                     for (ListNum = 1; ListNum <= NumEquipLists; ++ListNum) {
     875        1348 :                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit = NumArray(ListNum * 2 - 1);
     876        1348 :                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit = NumArray(ListNum * 2);
     877        1348 :                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Name = AlphArray(ListNum + 1);
     878        1348 :                         if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit < 0.0) {
     879           0 :                             ShowSevereError(state,
     880           0 :                                             format("{} = \"{}\", found a negative value for an upper limit in {} = \"{}\".",
     881             :                                                    LoopOpSchemeObj,
     882           0 :                                                    state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
     883             :                                                    CurrentModuleObject,
     884           0 :                                                    state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
     885           0 :                             ErrorsFound = true;
     886             :                         }
     887             : 
     888             :                         {
     889        1348 :                             std::string const &plantLoopOperation =
     890             :                                 CurrentModuleObject; // different op schemes have different lower limit check values
     891             : 
     892        1855 :                             if (plantLoopOperation == "PlantEquipmentOperation:CoolingLoad" ||
     893        1855 :                                 plantLoopOperation == "PlantEquipmentOperation:HeatingLoad" ||
     894           8 :                                 plantLoopOperation == "PlantEquipmentOperation:OutdoorrelativeHumidity") {
     895             :                                 // these should not be less than zero
     896        1342 :                                 if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit < 0.0) {
     897           0 :                                     ShowSevereError(state,
     898           0 :                                                     format("{} = \"{}\", found a negative value for a lower limit in {} = \"{}\".",
     899             :                                                            LoopOpSchemeObj,
     900           0 :                                                            state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
     901             :                                                            CurrentModuleObject,
     902           0 :                                                            state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
     903           0 :                                     ErrorsFound = true;
     904             :                                 }
     905             :                             } else {
     906             :                                 // others should not be less than -70
     907           6 :                                 if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit < -70.0) {
     908           0 :                                     ShowSevereError(state,
     909           0 :                                                     format("{} = \"{}\", found too low of a value for a lower limit in {} = \"{}\".",
     910             :                                                            LoopOpSchemeObj,
     911           0 :                                                            state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
     912             :                                                            CurrentModuleObject,
     913           0 :                                                            state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
     914           0 :                                     ErrorsFound = true;
     915             :                                 }
     916             :                             }
     917             :                         }
     918             : 
     919        1348 :                         if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit >
     920        1348 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit) {
     921           0 :                             ShowSevereError(state,
     922           0 :                                             format("{} = \"{}\", found a lower limit that is higher than an upper limit in {} = \"{}\".",
     923             :                                                    LoopOpSchemeObj,
     924           0 :                                                    state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
     925             :                                                    CurrentModuleObject,
     926           0 :                                                    state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
     927           0 :                             ErrorsFound = true;
     928             :                         }
     929             : 
     930        1348 :                         LoadEquipList(state, LoopNum, SchemeNum, ListNum, ErrorsFound);
     931             :                     }
     932             :                     // now run through lists again and check that range limits do not overlap each other
     933        2541 :                     for (ListNum = 1; ListNum <= NumEquipLists; ++ListNum) {
     934        1348 :                         OuterListNumLowerLimit = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit;
     935        1348 :                         OuterListNumUpperLimit = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit;
     936        3136 :                         for (InnerListNum = 1; InnerListNum <= NumEquipLists; ++InnerListNum) {
     937        1788 :                             if (InnerListNum == ListNum) continue; // don't check against self.
     938         440 :                             InnerListNumLowerLimit = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(InnerListNum).RangeLowerLimit;
     939         440 :                             InnerListNumUpperLimit = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(InnerListNum).RangeUpperLimit;
     940             :                             // Check if inner list has a lower limit that is between an outer's lower and upper limit
     941         440 :                             if (InnerListNumLowerLimit > OuterListNumLowerLimit && InnerListNumLowerLimit < OuterListNumUpperLimit) {
     942           0 :                                 ShowWarningError(state,
     943           0 :                                                  format("{} = \"{}\", detected overlapping ranges in {} = \"{}\".",
     944             :                                                         LoopOpSchemeObj,
     945           0 :                                                         state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
     946             :                                                         CurrentModuleObject,
     947           0 :                                                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
     948           0 :                                 ShowContinueError(state,
     949           0 :                                                   format("Range # {} Lower limit = {:.1R} lies within the Range # {} ({:.1R} to {:.1R}).",
     950             :                                                          InnerListNum,
     951             :                                                          InnerListNumLowerLimit,
     952             :                                                          ListNum,
     953             :                                                          OuterListNumLowerLimit,
     954             :                                                          OuterListNumUpperLimit));
     955           0 :                                 ShowContinueError(state,
     956             :                                                   "Check that input for load range limit values do not overlap, and the simulation continues...");
     957             :                             }
     958             :                             // Check if inner list has an upper limit that is between an outer's lower and upper limit
     959         440 :                             if (InnerListNumUpperLimit > OuterListNumLowerLimit && InnerListNumUpperLimit < OuterListNumUpperLimit) {
     960           0 :                                 ShowWarningError(state,
     961           0 :                                                  format("{} = \"{}\", detected overlapping ranges in {} = \"{}\".",
     962             :                                                         LoopOpSchemeObj,
     963           0 :                                                         state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
     964             :                                                         CurrentModuleObject,
     965           0 :                                                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
     966           0 :                                 ShowContinueError(state,
     967           0 :                                                   format("Range # {} Upper limit = {:.1R} lies within Range # {} ({:.1R} to {:.1R}).",
     968             :                                                          InnerListNum,
     969             :                                                          InnerListNumUpperLimit,
     970             :                                                          ListNum,
     971             :                                                          OuterListNumLowerLimit,
     972             :                                                          OuterListNumUpperLimit));
     973           0 :                                 ShowContinueError(state,
     974             :                                                   "Check that input for load range limit values do not overlap, and the simulation continues...");
     975             :                             }
     976             :                         }
     977             :                     }
     978             :                 }
     979             :             }
     980             :         }
     981             :     } else {
     982           0 :         ShowSevereError(state,
     983           0 :                         format("{} = \"{}\", could not find {} = \"{}\".",
     984             :                                LoopOpSchemeObj,
     985           0 :                                state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
     986             :                                CurrentModuleObject,
     987           0 :                                state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
     988           0 :         ErrorsFound = true;
     989             :     }
     990             : 
     991        1235 :     AlphArray.deallocate();
     992        1235 :     cAlphaFields.deallocate();
     993        1235 :     cNumericFields.deallocate();
     994        1235 :     NumArray.deallocate();
     995        1235 :     lAlphaBlanks.deallocate();
     996        1235 :     lNumericBlanks.deallocate();
     997        1235 : }
     998             : 
     999           3 : void FindDeltaTempRangeInput(EnergyPlusData &state,
    1000             :                              DataLoopNode::ConnectionObjectType const CurrentModuleObject, // for ease in renaming
    1001             :                              int const NumSchemes,                                         // May be set here and passed on
    1002             :                              int const LoopNum,                                            // May be set here and passed on
    1003             :                              int const SchemeNum,                                          // May be set here and passed on
    1004             :                              bool &ErrorsFound                                             // May be set here and passed on
    1005             : )
    1006             : {
    1007             :     // SUBROUTINE INFORMATION:
    1008             :     //       AUTHOR         Chandan Sharma
    1009             :     //       DATE WRITTEN   August 2010
    1010             :     //       MODIFIED       na
    1011             :     //       RE-ENGINEERED  na
    1012             : 
    1013             :     // PURPOSE OF THIS SUBROUTINE:
    1014             :     // Load range based input into PLANTLOOP data structure
    1015             : 
    1016             :     // METHODOLOGY EMPLOYED:
    1017             :     // calls the Input Processor to retrieve data from input file.
    1018             :     // The format of the Energy+.idd (the EnergyPlus input data dictionary) for the
    1019             :     // following keywords is reflected exactly in this subroutine:
    1020             :     //       PlantEquipmentOperation:OutdoorDryBulbDifference
    1021             :     //       PlantEquipmentOperation:OutdoorWetBulbDifference
    1022             :     //       PlantEquipmentOperation:OutdoorDewPointDifference
    1023             : 
    1024             :     // REFERENCES:
    1025             :     // Based on subroutine FindRangeBasedOrUncontrolledInput from Dan Fisher, July 2010
    1026             : 
    1027             :     // Using/Aliasing
    1028             :     using NodeInputManager::GetOnlySingleNode;
    1029             :     using namespace DataLoopNode;
    1030             : 
    1031             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1032             :     int NumAlphas;
    1033             :     int NumNums;
    1034             :     int IOStat;
    1035           3 :     Array1D_string AlphArray;      // Alpha input items for object
    1036           3 :     Array1D_string cAlphaFields;   // Alpha field names
    1037           3 :     Array1D_string cNumericFields; // Numeric field names
    1038           3 :     Array1D<Real64> NumArray;      // Numeric input items for object
    1039           3 :     Array1D_bool lAlphaBlanks;     // Logical array, alpha field input BLANK = .TRUE.
    1040           3 :     Array1D_bool lNumericBlanks;   // Logical array, numeric field input BLANK = .TRUE.
    1041           3 :     int TotalArgs(0);              // Total number of alpha and numeric arguments (max) for a
    1042             :     //   certain object in the input file
    1043             :     int Num;
    1044             :     int NumEquipLists;
    1045             :     int ListNum;
    1046           3 :     std::string LoopOpSchemeObj; // Used to identify the object name for loop equipment operation scheme
    1047             :     bool SchemeNameFound;        // Set to FALSE if a match of OpScheme object and OpScheme name is not found
    1048             : 
    1049           3 :     SchemeNameFound = true;
    1050             : 
    1051           3 :     std::string cmoStr = std::string(BranchNodeConnections::ConnectionObjectTypeNamesUC[static_cast<int>(CurrentModuleObject)]);
    1052             : 
    1053             :     // Determine max number of alpha and numeric arguments for all objects being read, in order to allocate local arrays
    1054           3 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cmoStr, TotalArgs, NumAlphas, NumNums);
    1055             : 
    1056           3 :     AlphArray.allocate(NumAlphas);
    1057           3 :     cAlphaFields.allocate(NumAlphas);
    1058           3 :     cNumericFields.allocate(NumNums);
    1059           3 :     NumArray.dimension(NumNums, 0.0);
    1060           3 :     lAlphaBlanks.dimension(NumAlphas, true);
    1061           3 :     lNumericBlanks.dimension(NumNums, true);
    1062             : 
    1063           3 :     if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    1064           0 :         LoopOpSchemeObj = "PlantEquipmentOperationSchemes";
    1065           3 :     } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Condenser) {
    1066           3 :         LoopOpSchemeObj = "CondenserEquipmentOperationSchemes";
    1067             :     }
    1068             : 
    1069           3 :     if (NumSchemes > 0) {
    1070           3 :         for (Num = 1; Num <= NumSchemes; ++Num) {
    1071           3 :             state.dataInputProcessing->inputProcessor->getObjectItem(state, cmoStr, Num, AlphArray, NumAlphas, NumArray, NumNums, IOStat);
    1072           3 :             if (Util::SameString(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name, AlphArray(1))) break;
    1073           0 :             if (Num == NumSchemes) {
    1074           0 :                 ShowSevereError(state,
    1075           0 :                                 format("{} = \"{}\", could not find {} = \"{}\".",
    1076             :                                        LoopOpSchemeObj,
    1077           0 :                                        state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
    1078             :                                        cmoStr,
    1079           0 :                                        state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
    1080           0 :                 ErrorsFound = true;
    1081           0 :                 SchemeNameFound = false;
    1082             :             }
    1083             :         }
    1084           3 :         if (SchemeNameFound) {
    1085           3 :             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists = (NumAlphas - 2);
    1086           3 :             if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists <= 0) {
    1087           0 :                 ShowSevereError(state, format("{} = \"{}\", specified without equipment list.", cmoStr, AlphArray(1)));
    1088           0 :                 ErrorsFound = true;
    1089             :             } else {
    1090           6 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList.allocate(
    1091           3 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists);
    1092           3 :                 NumEquipLists = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists;
    1093           3 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).ReferenceNodeName = AlphArray(2);
    1094           3 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).ReferenceNodeNumber =
    1095           6 :                     GetOnlySingleNode(state,
    1096           3 :                                       AlphArray(2),
    1097             :                                       ErrorsFound,
    1098             :                                       CurrentModuleObject,
    1099           3 :                                       AlphArray(1),
    1100             :                                       DataLoopNode::NodeFluidType::Water,
    1101             :                                       DataLoopNode::ConnectionType::Sensor,
    1102             :                                       NodeInputManager::CompFluidStream::Primary,
    1103             :                                       ObjectIsNotParent);
    1104             :                 // For DO Loop below -- Check for lower limit > upper limit.(invalid)
    1105           9 :                 for (ListNum = 1; ListNum <= NumEquipLists; ++ListNum) {
    1106           6 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit = NumArray(ListNum * 2 - 1);
    1107           6 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit = NumArray(ListNum * 2);
    1108           6 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Name = AlphArray(ListNum + 2);
    1109           6 :                     if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit >
    1110           6 :                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit) {
    1111           0 :                         ShowSevereError(state,
    1112           0 :                                         format("{} = \"{}\", found a lower limit that is higher than an upper limit in {} = \"{}\".",
    1113             :                                                LoopOpSchemeObj,
    1114           0 :                                                state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
    1115             :                                                cmoStr,
    1116           0 :                                                state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
    1117           0 :                         ErrorsFound = true;
    1118             :                     }
    1119           6 :                     LoadEquipList(state, LoopNum, SchemeNum, ListNum, ErrorsFound);
    1120             :                 }
    1121             :             }
    1122             :         }
    1123             :     } else {
    1124           0 :         ShowSevereError(state,
    1125           0 :                         format("{} = \"{}\", could not find {} = \"{}\".",
    1126             :                                LoopOpSchemeObj,
    1127           0 :                                state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
    1128             :                                cmoStr,
    1129           0 :                                state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
    1130           0 :         ErrorsFound = true;
    1131             :     }
    1132             : 
    1133           3 :     AlphArray.deallocate();
    1134           3 :     cAlphaFields.deallocate();
    1135           3 :     cNumericFields.deallocate();
    1136           3 :     NumArray.deallocate();
    1137           3 :     lAlphaBlanks.deallocate();
    1138           3 :     lNumericBlanks.deallocate();
    1139           3 : }
    1140             : 
    1141        1396 : void LoadEquipList(EnergyPlusData &state,
    1142             :                    int const LoopNum,   // May be set here and passed on
    1143             :                    int const SchemeNum, // May be set here and passed on
    1144             :                    int const ListNum,   // May be set here and passed on
    1145             :                    bool &ErrorsFound    // May be set here and passed on
    1146             : )
    1147             : {
    1148             :     // SUBROUTINE INFORMATION:
    1149             :     //       AUTHOR         Dan Fisher
    1150             :     //       DATE WRITTEN   July 2010
    1151             :     //       MODIFIED       B. Griffith Sept 2011, major rewrite
    1152             :     //                      allow mixing list types across plant types, store info first time
    1153             :     //       RE-ENGINEERED  na
    1154             : 
    1155             :     // PURPOSE OF THIS SUBROUTINE:
    1156             :     // Load delta range based input into PLANTLOOP data structure
    1157             : 
    1158             :     // METHODOLOGY EMPLOYED:
    1159             :     // calls the Input Processor to retrieve data from input file.
    1160             : 
    1161             :     // Using/Aliasing
    1162             : 
    1163             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1164             : 
    1165             :     bool FoundIntendedList;
    1166             :     int Num;
    1167             :     int MachineNum;
    1168             :     int PELists;
    1169             :     int CELists;
    1170             :     //  INTEGER :: NumLists
    1171             :     int NumAlphas;
    1172             :     int NumNums;
    1173             :     int IOStat;
    1174             :     bool IsNotOK;
    1175        1396 :     std::string CurrentModuleObject;
    1176             :     int iIndex;
    1177             :     bool firstblank;
    1178             : 
    1179        1396 :     if (state.dataPlantCondLoopOp->LoadEquipListOneTimeFlag) {
    1180             :         // assemble mapping between list names and indices one time
    1181         458 :         PELists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentList");
    1182         458 :         CELists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "CondenserEquipmentList");
    1183         458 :         state.dataPlantCondLoopOp->TotNumLists = PELists + CELists;
    1184         458 :         if (state.dataPlantCondLoopOp->TotNumLists > 0) {
    1185         458 :             state.dataPlantCondLoopOp->EquipListsNameList.allocate(state.dataPlantCondLoopOp->TotNumLists);
    1186         458 :             state.dataPlantCondLoopOp->EquipListsTypeList.allocate(state.dataPlantCondLoopOp->TotNumLists);
    1187         458 :             state.dataPlantCondLoopOp->EquipListsIndexList.allocate(state.dataPlantCondLoopOp->TotNumLists);
    1188             : 
    1189             :             // First load PlantEquipmentList info
    1190         458 :             if (PELists > 0) {
    1191         441 :                 CurrentModuleObject = "PlantEquipmentList";
    1192        1666 :                 for (Num = 1; Num <= PELists; ++Num) {
    1193        1225 :                     iIndex = Num;
    1194        2450 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1195             :                                                                              CurrentModuleObject,
    1196             :                                                                              Num,
    1197        1225 :                                                                              state.dataIPShortCut->cAlphaArgs,
    1198             :                                                                              NumAlphas,
    1199        1225 :                                                                              state.dataIPShortCut->rNumericArgs,
    1200             :                                                                              NumNums,
    1201             :                                                                              IOStat,
    1202        1225 :                                                                              state.dataIPShortCut->lNumericFieldBlanks,
    1203        1225 :                                                                              state.dataIPShortCut->lAlphaFieldBlanks,
    1204        1225 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    1205        1225 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    1206        1225 :                     state.dataPlantCondLoopOp->EquipListsNameList(iIndex) = state.dataIPShortCut->cAlphaArgs(1);
    1207        1225 :                     state.dataPlantCondLoopOp->EquipListsTypeList(iIndex) = LoopType::Plant;
    1208        1225 :                     state.dataPlantCondLoopOp->EquipListsIndexList(iIndex) = Num;
    1209        1225 :                     MachineNum = 2;
    1210        2691 :                     while (MachineNum <= NumAlphas) {
    1211        1466 :                         firstblank = false;
    1212        1466 :                         if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum) || state.dataIPShortCut->lAlphaFieldBlanks(MachineNum + 1)) {
    1213           0 :                             if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum)) {
    1214           0 :                                 ShowSevereError(
    1215             :                                     state,
    1216           0 :                                     format("{}=\"{}\", invalid component specification.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    1217           0 :                                 ShowContinueError(state, format("{} is blank.", state.dataIPShortCut->cAlphaFieldNames(MachineNum)));
    1218           0 :                                 firstblank = true;
    1219           0 :                                 ErrorsFound = true;
    1220             :                             }
    1221           0 :                             if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum + 1)) {
    1222           0 :                                 if (!firstblank) {
    1223           0 :                                     ShowSevereError(state,
    1224           0 :                                                     format("{}=\"{}\", invalid component specification.",
    1225             :                                                            CurrentModuleObject,
    1226           0 :                                                            state.dataIPShortCut->cAlphaArgs(1)));
    1227             :                                 }
    1228           0 :                                 ShowContinueError(state, format("{} is blank.", state.dataIPShortCut->cAlphaFieldNames(MachineNum + 1)));
    1229           0 :                                 ErrorsFound = true;
    1230             :                             }
    1231             :                         } else {
    1232        2932 :                             ValidateComponent(state,
    1233        1466 :                                               state.dataIPShortCut->cAlphaArgs(MachineNum),
    1234        1466 :                                               state.dataIPShortCut->cAlphaArgs(MachineNum + 1),
    1235             :                                               IsNotOK,
    1236             :                                               CurrentModuleObject);
    1237        1466 :                             if (IsNotOK) {
    1238           0 :                                 ShowContinueError(state, format("{}=\"{}\", Input Error.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    1239           0 :                                 ErrorsFound = true;
    1240             :                             }
    1241             :                         }
    1242        1466 :                         MachineNum += 2;
    1243             :                     }
    1244             :                 }
    1245             :             }
    1246         458 :             if (CELists > 0) {
    1247         255 :                 CurrentModuleObject = "CondenserEquipmentList";
    1248         524 :                 for (Num = 1; Num <= CELists; ++Num) {
    1249         269 :                     iIndex = Num + PELists;
    1250         538 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1251             :                                                                              CurrentModuleObject,
    1252             :                                                                              Num,
    1253         269 :                                                                              state.dataIPShortCut->cAlphaArgs,
    1254             :                                                                              NumAlphas,
    1255         269 :                                                                              state.dataIPShortCut->rNumericArgs,
    1256             :                                                                              NumNums,
    1257             :                                                                              IOStat,
    1258         269 :                                                                              state.dataIPShortCut->lNumericFieldBlanks,
    1259         269 :                                                                              state.dataIPShortCut->lAlphaFieldBlanks,
    1260         269 :                                                                              state.dataIPShortCut->cAlphaFieldNames,
    1261         269 :                                                                              state.dataIPShortCut->cNumericFieldNames);
    1262         269 :                     state.dataPlantCondLoopOp->EquipListsNameList(iIndex) = state.dataIPShortCut->cAlphaArgs(1);
    1263         269 :                     state.dataPlantCondLoopOp->EquipListsTypeList(iIndex) = LoopType::Condenser;
    1264         269 :                     state.dataPlantCondLoopOp->EquipListsIndexList(iIndex) = Num;
    1265         269 :                     MachineNum = 2;
    1266         563 :                     while (MachineNum <= NumAlphas) {
    1267         294 :                         firstblank = false;
    1268         294 :                         if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum) || state.dataIPShortCut->lAlphaFieldBlanks(MachineNum + 1)) {
    1269           0 :                             if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum)) {
    1270           0 :                                 ShowSevereError(
    1271             :                                     state,
    1272           0 :                                     format("{}=\"{}\", invalid component specification.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    1273           0 :                                 ShowContinueError(state, format("{} is blank.", state.dataIPShortCut->cAlphaFieldNames(MachineNum)));
    1274           0 :                                 firstblank = true;
    1275           0 :                                 ErrorsFound = true;
    1276             :                             }
    1277           0 :                             if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum + 1)) {
    1278           0 :                                 if (!firstblank) {
    1279           0 :                                     ShowSevereError(state,
    1280           0 :                                                     format("{}=\"{}\", invalid component specification.",
    1281             :                                                            CurrentModuleObject,
    1282           0 :                                                            state.dataIPShortCut->cAlphaArgs(1)));
    1283             :                                 }
    1284           0 :                                 ShowContinueError(state, format("{} is blank.", state.dataIPShortCut->cAlphaFieldNames(MachineNum + 1)));
    1285           0 :                                 ErrorsFound = true;
    1286             :                             }
    1287             :                         } else {
    1288         588 :                             ValidateComponent(state,
    1289         294 :                                               state.dataIPShortCut->cAlphaArgs(MachineNum),
    1290         294 :                                               state.dataIPShortCut->cAlphaArgs(MachineNum + 1),
    1291             :                                               IsNotOK,
    1292             :                                               CurrentModuleObject);
    1293         294 :                             if (IsNotOK) {
    1294           0 :                                 ShowContinueError(state, format("{}=\"{}\", Input Error.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    1295           0 :                                 ErrorsFound = true;
    1296             :                             }
    1297             :                         }
    1298         294 :                         MachineNum += 2;
    1299             :                     }
    1300             :                 }
    1301             :             }
    1302             :         }
    1303         458 :         if (ErrorsFound) {
    1304           0 :             ShowFatalError(state, "LoadEquipList/GetEquipmentLists: Failed due to preceding errors.");
    1305             :         }
    1306         458 :         state.dataPlantCondLoopOp->LoadEquipListOneTimeFlag = false;
    1307             :     }
    1308             : 
    1309        1396 :     FoundIntendedList = false;
    1310             :     // find name in set of possible list
    1311        7375 :     for (Num = 1; Num <= state.dataPlantCondLoopOp->TotNumLists; ++Num) {
    1312        5979 :         if (Util::SameString(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Name,
    1313        5979 :                              state.dataPlantCondLoopOp->EquipListsNameList(Num))) {
    1314        1396 :             FoundIntendedList = true;
    1315             :             // get object item for real this time
    1316             :             {
    1317        1396 :                 if (state.dataPlantCondLoopOp->EquipListsTypeList(Num) == LoopType::Plant) {
    1318        1127 :                     CurrentModuleObject = "PlantEquipmentList";
    1319         269 :                 } else if (state.dataPlantCondLoopOp->EquipListsTypeList(Num) == LoopType::Condenser) {
    1320         269 :                     CurrentModuleObject = "CondenserEquipmentList";
    1321             :                 }
    1322             :             }
    1323        2792 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1324             :                                                                      CurrentModuleObject,
    1325        1396 :                                                                      state.dataPlantCondLoopOp->EquipListsIndexList(Num),
    1326        1396 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1327             :                                                                      NumAlphas,
    1328        1396 :                                                                      state.dataIPShortCut->rNumericArgs,
    1329             :                                                                      NumNums,
    1330             :                                                                      IOStat,
    1331        1396 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1332        1396 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1333        1396 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1334        1396 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1335        1396 :             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).NumComps = (NumAlphas - 1) / 2;
    1336        1396 :             if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).NumComps > 0) {
    1337        2784 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Comp.allocate(
    1338        1392 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).NumComps);
    1339        2985 :                 for (MachineNum = 1; MachineNum <= state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).NumComps; ++MachineNum) {
    1340        1593 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Comp(MachineNum).TypeOf =
    1341        3186 :                         state.dataIPShortCut->cAlphaArgs(MachineNum * 2);
    1342        1593 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Comp(MachineNum).Name =
    1343        3186 :                         state.dataIPShortCut->cAlphaArgs(MachineNum * 2 + 1);
    1344             :                 } // MachineList
    1345             :             }
    1346             :         }
    1347             :     }
    1348             : 
    1349        1396 :     if (!FoundIntendedList) {
    1350           0 :         ShowSevereError(state,
    1351           0 :                         format("LoadEquipList: Failed to find PlantEquipmentList or CondenserEquipmentList object named = {}",
    1352           0 :                                state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Name));
    1353           0 :         ErrorsFound = true;
    1354             :     }
    1355        1396 : }
    1356             : 
    1357          15 : void FindCompSPInput(EnergyPlusData &state,
    1358             :                      std::string &CurrentModuleObject, // for ease in renaming
    1359             :                      int const NumSchemes,             // May be set here and passed on
    1360             :                      int const LoopNum,                // May be set here and passed on
    1361             :                      int const SchemeNum,              // May be set here and passed on
    1362             :                      bool &ErrorsFound                 // May be set here and passed on
    1363             : )
    1364             : {
    1365             :     // SUBROUTINE INFORMATION:
    1366             :     //       AUTHOR         Dan Fisher
    1367             :     //       DATE WRITTEN   July 2010
    1368             :     //       MODIFIED       B. Griffith, check setpoint nodes have setpoint managers on EMS on them.
    1369             :     //                      Rick Strand, Aug 2014, added simple thermal energy storage controls
    1370             :     //       RE-ENGINEERED  na
    1371             : 
    1372             :     // PURPOSE OF THIS SUBROUTINE:
    1373             :     // Load component setpoint based input into PLANTLOOP data structure
    1374             : 
    1375             :     // METHODOLOGY EMPLOYED:
    1376             :     // calls the Input Processor to retrieve data from input file.
    1377             :     // The format of the Energy+.idd (the EnergyPlus input data dictionary) for the
    1378             :     // following keywords is reflected exactly in this subroutine:
    1379             :     //    PlantEquipmentOperation:ComponentSetPoint
    1380             :     //    PlantEquipmentOperation:ThermalEnergyStorage
    1381             : 
    1382             :     // Using/Aliasing
    1383             :     using namespace DataLoopNode;
    1384             :     using NodeInputManager::GetOnlySingleNode;
    1385             :     using namespace DataSizing;
    1386             :     using EMSManager::CheckIfNodeSetPointManagedByEMS;
    1387             :     using ScheduleManager::GetScheduleIndex;
    1388             :     using SetPointManager::SetUpNewScheduledTESSetPtMgr;
    1389             : 
    1390             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1391             :     int NumAlphas;
    1392             :     int NumNums;
    1393             :     int CompNum;
    1394             :     int CompInNode;
    1395             :     int IOStat;
    1396          15 :     Real64 CompFlowRate(0.0);
    1397          15 :     std::string LoopOpSchemeObj; // Used to identify the object name for loop equipment operation scheme
    1398             :     bool SchemeNameFound;        // Set to FALSE if a match of OpScheme object and OpScheme name is not found
    1399             :     bool NodeEMSSetPointMissing;
    1400          15 :     std::string OnPeakSchedName;
    1401             :     int OnPeakSchedPtr;
    1402          15 :     std::string ChargeSchedName;
    1403             :     int ChargeSchedPtr;
    1404             :     Real64 NonChargCHWTemp;
    1405             :     Real64 OffPeakCHWTemp;
    1406             :     int CompNumA;
    1407             :     int CompNumN;
    1408             :     CtrlType CompOpType; // 1=cooling, 2=dual(or other)
    1409             : 
    1410          15 :     SchemeNameFound = true;
    1411             : 
    1412             :     DataLoopNode::ConnectionObjectType objType = static_cast<DataLoopNode::ConnectionObjectType>(
    1413          15 :         getEnumValue(BranchNodeConnections::ConnectionObjectTypeNamesUC, Util::makeUPPER(CurrentModuleObject)));
    1414             : 
    1415          15 :     if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    1416          15 :         LoopOpSchemeObj = "PlantEquipmentOperationSchemes";
    1417           0 :     } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Condenser) {
    1418           0 :         LoopOpSchemeObj = "CondenserEquipmentOperationSchemes";
    1419             :     }
    1420             : 
    1421          15 :     if (NumSchemes > 0) {
    1422          15 :         for (int Num = 1; Num <= NumSchemes; ++Num) {
    1423          30 :             state.dataInputProcessing->inputProcessor->getObjectItem(
    1424          15 :                 state, CurrentModuleObject, Num, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
    1425          15 :             if (Util::SameString(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name, state.dataIPShortCut->cAlphaArgs(1))) break;
    1426           0 :             if (Num == NumSchemes) {
    1427           0 :                 ShowSevereError(state,
    1428           0 :                                 format("{} = \"{}\", could not find {} = \"{}\".",
    1429             :                                        LoopOpSchemeObj,
    1430           0 :                                        state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
    1431             :                                        CurrentModuleObject,
    1432           0 :                                        state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
    1433           0 :                 ErrorsFound = true;
    1434           0 :                 SchemeNameFound = false;
    1435             :             }
    1436             :         }
    1437          15 :         if (SchemeNameFound) {
    1438             :             // why only one equip list assumed here? because component setpoint managers have their own lists contained.
    1439          15 :             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists = 1;
    1440          15 :             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList.allocate(1);
    1441          15 :             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps = (NumAlphas - 1) / 5;
    1442             : 
    1443          15 :             if (CurrentModuleObject == "PlantEquipmentOperation:ThermalEnergyStorage") {
    1444             :                 // Read all of the additional parameters for ice storage control scheme and error check various parameters
    1445           1 :                 OnPeakSchedName = state.dataIPShortCut->cAlphaArgs(2);
    1446           1 :                 OnPeakSchedPtr = GetScheduleIndex(state, OnPeakSchedName);
    1447           1 :                 if (OnPeakSchedPtr == 0) {
    1448           0 :                     ShowSevereError(state,
    1449           0 :                                     format("Could not find On Peak Schedule {} in {}{}\".",
    1450             :                                            OnPeakSchedName,
    1451             :                                            CurrentModuleObject,
    1452           0 :                                            state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
    1453           0 :                     ErrorsFound = true;
    1454             :                 }
    1455           1 :                 ChargeSchedName = state.dataIPShortCut->cAlphaArgs(3);
    1456           1 :                 ChargeSchedPtr = GetScheduleIndex(state, ChargeSchedName);
    1457           1 :                 if (ChargeSchedPtr == 0) {
    1458           0 :                     ShowSevereError(state,
    1459           0 :                                     format("Could not find Charging Availability Schedule {} in {}{}\".",
    1460             :                                            ChargeSchedName,
    1461             :                                            CurrentModuleObject,
    1462           0 :                                            state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
    1463           0 :                     ErrorsFound = true;
    1464             :                 }
    1465           1 :                 NonChargCHWTemp = state.dataIPShortCut->rNumericArgs(1);
    1466           1 :                 OffPeakCHWTemp = state.dataIPShortCut->rNumericArgs(2);
    1467             :             }
    1468             : 
    1469          15 :             if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps > 0) {
    1470          30 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp.allocate(
    1471          15 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps);
    1472          47 :                 for (CompNum = 1; CompNum <= state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps; ++CompNum) {
    1473          32 :                     if (CurrentModuleObject == "PlantEquipmentOperation:ComponentSetPoint") {
    1474          30 :                         CompNumA = CompNum * 5;
    1475          30 :                         CompNumN = CompNum;
    1476           2 :                     } else if (CurrentModuleObject == "PlantEquipmentOperation:ThermalEnergyStorage") {
    1477           2 :                         CompNumA = CompNum * 5 + 2;
    1478           2 :                         CompNumN = CompNum + 2;
    1479             :                     }
    1480          32 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).TypeOf =
    1481          64 :                         state.dataIPShortCut->cAlphaArgs(CompNumA - 3);
    1482          32 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).Name =
    1483          64 :                         state.dataIPShortCut->cAlphaArgs(CompNumA - 2);
    1484          32 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).DemandNodeName =
    1485          64 :                         state.dataIPShortCut->cAlphaArgs(CompNumA - 1);
    1486          32 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).DemandNodeNum =
    1487          64 :                         GetOnlySingleNode(state,
    1488          32 :                                           state.dataIPShortCut->cAlphaArgs(CompNumA - 1),
    1489             :                                           ErrorsFound,
    1490             :                                           objType,
    1491          32 :                                           state.dataIPShortCut->cAlphaArgs(1),
    1492             :                                           DataLoopNode::NodeFluidType::Water,
    1493             :                                           DataLoopNode::ConnectionType::Sensor,
    1494             :                                           NodeInputManager::CompFluidStream::Primary,
    1495             :                                           ObjectIsNotParent);
    1496          32 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName =
    1497          64 :                         state.dataIPShortCut->cAlphaArgs(CompNumA);
    1498          32 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum =
    1499          64 :                         GetOnlySingleNode(state,
    1500          32 :                                           state.dataIPShortCut->cAlphaArgs(CompNumA),
    1501             :                                           ErrorsFound,
    1502             :                                           objType,
    1503          32 :                                           state.dataIPShortCut->cAlphaArgs(1),
    1504             :                                           DataLoopNode::NodeFluidType::Water,
    1505             :                                           DataLoopNode::ConnectionType::Sensor,
    1506             :                                           NodeInputManager::CompFluidStream::Primary,
    1507             :                                           ObjectIsNotParent);
    1508          32 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointFlowRate =
    1509          32 :                         state.dataIPShortCut->rNumericArgs(CompNumN);
    1510             : 
    1511          32 :                     if (state.dataIPShortCut->rNumericArgs(CompNumN) == AutoSize) {
    1512          15 :                         int Num = 1;
    1513         480 :                         for (; Num <= state.dataSize->SaveNumPlantComps; ++Num) {
    1514         465 :                             CompInNode = state.dataSize->CompDesWaterFlow(Num).SupNode;
    1515         465 :                             CompFlowRate = state.dataSize->CompDesWaterFlow(Num).DesVolFlowRate;
    1516         465 :                             if (CompInNode == state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).DemandNodeNum) {
    1517          15 :                                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointFlowRate = CompFlowRate;
    1518             :                             } else {
    1519             :                                 // call error...Demand node must be component inlet node for autosizing
    1520             :                             }
    1521             :                         }
    1522          60 :                         BaseSizer::reportSizerOutput(state,
    1523             :                                                      CurrentModuleObject,
    1524          15 :                                                      state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name,
    1525          30 :                                                      format("Design Water Flow Rate [m3/s] Equipment # {}", Num),
    1526             :                                                      CompFlowRate);
    1527             :                     }
    1528             : 
    1529             :                     {
    1530          32 :                         std::string const &controlType = state.dataIPShortCut->cAlphaArgs(CompNumA + 1);
    1531          32 :                         if (controlType == "COOLING") {
    1532          18 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType = CtrlType::CoolingOp;
    1533          14 :                         } else if (controlType == "HEATING") {
    1534           5 :                             if (CurrentModuleObject == "PlantEquipmentOperation:ThermalEnergyStorage") {
    1535           0 :                                 ShowSevereError(
    1536             :                                     state,
    1537           0 :                                     format(
    1538             :                                         "Equipment Operation Mode cannot be HEATING for any equipment found in {} in thermal energy storage control",
    1539           0 :                                         state.dataIPShortCut->cAlphaArgs(1)));
    1540           0 :                                 ErrorsFound = true;
    1541             :                             }
    1542           5 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType = CtrlType::HeatingOp;
    1543           9 :                         } else if (controlType == "DUAL") {
    1544           9 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType = CtrlType::DualOp;
    1545             :                         }
    1546             :                     }
    1547             : 
    1548          46 :                     if ((state.dataIPShortCut->cAlphaArgs(CompNumA + 1) != "COOLING") &&
    1549          46 :                         (state.dataIPShortCut->cAlphaArgs(CompNumA + 1) != "HEATING") && (state.dataIPShortCut->cAlphaArgs(CompNumA + 1) != "DUAL")) {
    1550           0 :                         ShowSevereError(state,
    1551           0 :                                         format("Equipment Operation Mode should be either HEATING or COOLING or DUAL mode, for {}={}",
    1552             :                                                CurrentModuleObject,
    1553           0 :                                                state.dataIPShortCut->cAlphaArgs(1)));
    1554             :                     }
    1555             : 
    1556          32 :                     if (CurrentModuleObject == "PlantEquipmentOperation:ThermalEnergyStorage") {
    1557             : 
    1558             :                         // Special case for ThermalStorage:Ice:XXXX objects which can only be dual (cf #6958)
    1559           4 :                         if (((state.dataIPShortCut->cAlphaArgs(CompNumA - 3) == "THERMALSTORAGE:ICE:SIMPLE") ||
    1560           4 :                              (state.dataIPShortCut->cAlphaArgs(CompNumA - 3) == "THERMALSTORAGE:ICE:DETAILED")) &&
    1561           1 :                             (state.dataIPShortCut->cAlphaArgs(CompNumA + 1) != "DUAL")) {
    1562             : 
    1563           0 :                             ShowWarningError(state,
    1564           0 :                                              format("Equipment Operation Mode was reset to 'DUAL' for Component '{}' in {}='{}'.",
    1565           0 :                                                     state.dataIPShortCut->cAlphaArgs(CompNumA - 2),
    1566             :                                                     CurrentModuleObject,
    1567           0 :                                                     state.dataIPShortCut->cAlphaArgs(1)));
    1568           0 :                             ShowContinueError(state,
    1569           0 :                                               format("Equipment Operation Mode can only be 'DUAL' for {} objects.",
    1570           0 :                                                      state.dataIPShortCut->cAlphaArgs(CompNumA - 3)));
    1571             : 
    1572           0 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType = CtrlType::DualOp;
    1573             :                         }
    1574             : 
    1575             :                         // This block forces CompOpType to be either Cooling if explicitly provided, all other cases = Dual
    1576           2 :                         switch (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType) {
    1577           1 :                         case CtrlType::DualOp:
    1578           1 :                             CompOpType = CtrlType::CoolingOp;
    1579           1 :                             break;
    1580           1 :                         case CtrlType::CoolingOp:
    1581           1 :                             CompOpType = CtrlType::HeatingOp;
    1582           1 :                             break;
    1583           0 :                         case CtrlType::HeatingOp:
    1584           0 :                             CompOpType = CtrlType::CoolingOp;
    1585           0 :                             break;
    1586           0 :                         default:
    1587           0 :                             assert(false);
    1588             :                         }
    1589             : 
    1590             :                         // for each component, a new scheduled setpoint manager needs to be defined to internally generate the more
    1591             :                         // detailed input that is necessary to get thermal energy storage to work from the simpler input.
    1592           2 :                         SetUpNewScheduledTESSetPtMgr(
    1593             :                             state,
    1594             :                             OnPeakSchedPtr,
    1595             :                             ChargeSchedPtr,
    1596             :                             NonChargCHWTemp,
    1597             :                             OffPeakCHWTemp,
    1598             :                             CompOpType,
    1599           2 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum);
    1600             :                     }
    1601             : 
    1602             :                     // check that setpoint node has valid setpoint managers or EMS
    1603             : 
    1604          32 :                     switch (state.dataPlnt->PlantLoop(LoopNum).LoopDemandCalcScheme) {
    1605          24 :                     case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
    1606          24 :                         if (state.dataLoopNodes
    1607          24 :                                 ->Node(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum)
    1608          24 :                                 .TempSetPoint == SensedNodeFlagValue) {
    1609           0 :                             if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1610           0 :                                 ShowSevereError(
    1611             :                                     state,
    1612           0 :                                     format("Missing temperature setpoint for {} named {}", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    1613           0 :                                 ShowContinueError(
    1614             :                                     state,
    1615           0 :                                     format("A temperature setpoint is needed at the node named {}",
    1616           0 :                                            state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
    1617           0 :                                 if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    1618           0 :                                     ShowContinueError(state,
    1619           0 :                                                       format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=SingleSetpoint",
    1620           0 :                                                              state.dataPlnt->PlantLoop(LoopNum).Name));
    1621           0 :                                 } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
    1622             :                                            LoopType::Condenser) { // not applicable to Condenser loops
    1623             :                                 }
    1624           0 :                                 ShowContinueError(state, " Use a setpoint manager to place a single temperature setpoint on the node");
    1625           0 :                                 ErrorsFound = true;
    1626             :                             } else {
    1627             :                                 // need call to EMS to check node
    1628           0 :                                 NodeEMSSetPointMissing = false;
    1629           0 :                                 CheckIfNodeSetPointManagedByEMS(
    1630             :                                     state,
    1631           0 :                                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum,
    1632             :                                     HVAC::CtrlVarType::Temp,
    1633             :                                     NodeEMSSetPointMissing);
    1634           0 :                                 if (NodeEMSSetPointMissing) {
    1635           0 :                                     ShowSevereError(state,
    1636           0 :                                                     format("Missing temperature setpoint for {} named {}",
    1637             :                                                            CurrentModuleObject,
    1638           0 :                                                            state.dataIPShortCut->cAlphaArgs(1)));
    1639           0 :                                     ShowContinueError(
    1640             :                                         state,
    1641           0 :                                         format("A temperature setpoint is needed at the node named {}",
    1642           0 :                                                state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
    1643           0 :                                     if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    1644           0 :                                         ShowContinueError(state,
    1645           0 :                                                           format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=SingleSetpoint",
    1646           0 :                                                                  state.dataPlnt->PlantLoop(LoopNum).Name));
    1647           0 :                                     } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
    1648             :                                                LoopType::Condenser) { // not applicable to Condenser loops
    1649             :                                     }
    1650           0 :                                     ShowContinueError(state,
    1651             :                                                       " Use a setpoint manager or EMS actuator to place a single temperature setpoint on node");
    1652           0 :                                     ErrorsFound = true;
    1653             :                                 }
    1654             :                             }
    1655             :                         }
    1656          24 :                         break;
    1657             :                     }
    1658           8 :                     case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
    1659           8 :                         if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType == CtrlType::CoolingOp) {
    1660           4 :                             if (state.dataLoopNodes
    1661           4 :                                     ->Node(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum)
    1662           4 :                                     .TempSetPointHi == SensedNodeFlagValue) {
    1663           0 :                                 if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1664           0 :                                     ShowSevereError(state,
    1665           0 :                                                     format("Missing temperature high setpoint for {} named {}",
    1666             :                                                            CurrentModuleObject,
    1667           0 :                                                            state.dataIPShortCut->cAlphaArgs(1)));
    1668           0 :                                     ShowContinueError(
    1669             :                                         state,
    1670           0 :                                         format("A temperature high setpoint is needed at the node named {}",
    1671           0 :                                                state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
    1672           0 :                                     if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    1673           0 :                                         ShowContinueError(state,
    1674           0 :                                                           format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
    1675           0 :                                                                  state.dataPlnt->PlantLoop(LoopNum).Name));
    1676           0 :                                     } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
    1677             :                                                LoopType::Condenser) { // not applicable to Condenser loops
    1678             :                                     }
    1679           0 :                                     ShowContinueError(state, " Use a setpoint manager to place a dual temperature setpoint on the node");
    1680           0 :                                     ErrorsFound = true;
    1681             :                                 } else {
    1682             :                                     // need call to EMS to check node
    1683           0 :                                     NodeEMSSetPointMissing = false;
    1684           0 :                                     CheckIfNodeSetPointManagedByEMS(
    1685             :                                         state,
    1686           0 :                                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum,
    1687             :                                         HVAC::CtrlVarType::Temp,
    1688             :                                         NodeEMSSetPointMissing);
    1689           0 :                                     if (NodeEMSSetPointMissing) {
    1690           0 :                                         ShowSevereError(state,
    1691           0 :                                                         format("Missing high temperature setpoint for {} named {}",
    1692             :                                                                CurrentModuleObject,
    1693           0 :                                                                state.dataIPShortCut->cAlphaArgs(1)));
    1694           0 :                                         ShowContinueError(
    1695             :                                             state,
    1696           0 :                                             format(
    1697             :                                                 "A high temperature setpoint is needed at the node named {}",
    1698           0 :                                                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
    1699           0 :                                         if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    1700           0 :                                             ShowContinueError(state,
    1701           0 :                                                               format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
    1702           0 :                                                                      state.dataPlnt->PlantLoop(LoopNum).Name));
    1703           0 :                                         } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
    1704             :                                                    LoopType::Condenser) { // not applicable to Condenser loops
    1705             :                                         }
    1706           0 :                                         ShowContinueError(
    1707             :                                             state, " Use a setpoint manager or EMS actuator to place a dual or high temperature setpoint on node");
    1708           0 :                                         ErrorsFound = true;
    1709             :                                     }
    1710             :                                 }
    1711             :                             }
    1712           4 :                         } else if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType ==
    1713             :                                    CtrlType::HeatingOp) {
    1714           4 :                             if (state.dataLoopNodes
    1715           4 :                                     ->Node(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum)
    1716           4 :                                     .TempSetPointLo == SensedNodeFlagValue) {
    1717           0 :                                 if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1718           0 :                                     ShowSevereError(state,
    1719           0 :                                                     format("Missing temperature low setpoint for {} named {}",
    1720             :                                                            CurrentModuleObject,
    1721           0 :                                                            state.dataIPShortCut->cAlphaArgs(1)));
    1722           0 :                                     ShowContinueError(
    1723             :                                         state,
    1724           0 :                                         format("A temperature low setpoint is needed at the node named {}",
    1725           0 :                                                state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
    1726           0 :                                     if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    1727           0 :                                         ShowContinueError(state,
    1728           0 :                                                           format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
    1729           0 :                                                                  state.dataPlnt->PlantLoop(LoopNum).Name));
    1730           0 :                                     } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
    1731             :                                                LoopType::Condenser) { // not applicable to Condenser loops
    1732             :                                     }
    1733           0 :                                     ShowContinueError(state, " Use a setpoint manager to place a dual temperature setpoint on the node");
    1734           0 :                                     ErrorsFound = true;
    1735             :                                 } else {
    1736             :                                     // need call to EMS to check node
    1737           0 :                                     NodeEMSSetPointMissing = false;
    1738           0 :                                     CheckIfNodeSetPointManagedByEMS(
    1739             :                                         state,
    1740           0 :                                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum,
    1741             :                                         HVAC::CtrlVarType::Temp,
    1742             :                                         NodeEMSSetPointMissing);
    1743           0 :                                     CheckIfNodeSetPointManagedByEMS(
    1744             :                                         state,
    1745           0 :                                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum,
    1746             :                                         HVAC::CtrlVarType::Temp,
    1747             :                                         NodeEMSSetPointMissing);
    1748           0 :                                     if (NodeEMSSetPointMissing) {
    1749           0 :                                         ShowSevereError(state,
    1750           0 :                                                         format("Missing low temperature setpoint for {} named {}",
    1751             :                                                                CurrentModuleObject,
    1752           0 :                                                                state.dataIPShortCut->cAlphaArgs(1)));
    1753           0 :                                         ShowContinueError(
    1754             :                                             state,
    1755           0 :                                             format(
    1756             :                                                 "A low temperature setpoint is needed at the node named {}",
    1757           0 :                                                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
    1758           0 :                                         if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    1759           0 :                                             ShowContinueError(state,
    1760           0 :                                                               format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
    1761           0 :                                                                      state.dataPlnt->PlantLoop(LoopNum).Name));
    1762           0 :                                         } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
    1763             :                                                    LoopType::Condenser) { // not applicable to Condenser loops
    1764             :                                         }
    1765           0 :                                         ShowContinueError(
    1766             :                                             state, " Use a setpoint manager or EMS actuator to place a dual or low temperature setpoint on node");
    1767           0 :                                         ErrorsFound = true;
    1768             :                                     }
    1769             :                                 }
    1770             :                             }
    1771           0 :                         } else if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType == CtrlType::DualOp) {
    1772           0 :                             if ((state.dataLoopNodes
    1773           0 :                                      ->Node(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum)
    1774           0 :                                      .TempSetPointHi == SensedNodeFlagValue) ||
    1775             :                                 (state.dataLoopNodes
    1776           0 :                                      ->Node(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum)
    1777           0 :                                      .TempSetPointLo == SensedNodeFlagValue)) {
    1778           0 :                                 if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1779           0 :                                     ShowSevereError(state,
    1780           0 :                                                     format("Missing temperature dual setpoints for {} named {}",
    1781             :                                                            CurrentModuleObject,
    1782           0 :                                                            state.dataIPShortCut->cAlphaArgs(1)));
    1783           0 :                                     ShowContinueError(
    1784             :                                         state,
    1785           0 :                                         format("A dual temperaturesetpoint is needed at the node named {}",
    1786           0 :                                                state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
    1787           0 :                                     if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    1788           0 :                                         ShowContinueError(state,
    1789           0 :                                                           format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
    1790           0 :                                                                  state.dataPlnt->PlantLoop(LoopNum).Name));
    1791           0 :                                     } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
    1792             :                                                LoopType::Condenser) { // not applicable to Condenser loops
    1793             :                                     }
    1794           0 :                                     ShowContinueError(state, " Use a setpoint manager to place a dual temperature setpoint on the node");
    1795           0 :                                     ErrorsFound = true;
    1796             :                                 } else {
    1797             :                                     // need call to EMS to check node
    1798           0 :                                     NodeEMSSetPointMissing = false;
    1799           0 :                                     CheckIfNodeSetPointManagedByEMS(
    1800             :                                         state,
    1801           0 :                                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum,
    1802             :                                         HVAC::CtrlVarType::Temp,
    1803             :                                         NodeEMSSetPointMissing);
    1804           0 :                                     if (NodeEMSSetPointMissing) {
    1805           0 :                                         ShowSevereError(state,
    1806           0 :                                                         format("Missing dual temperature setpoint for {} named {}",
    1807             :                                                                CurrentModuleObject,
    1808           0 :                                                                state.dataIPShortCut->cAlphaArgs(1)));
    1809           0 :                                         ShowContinueError(
    1810             :                                             state,
    1811           0 :                                             format(
    1812             :                                                 "A dual temperature setpoint is needed at the node named {}",
    1813           0 :                                                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
    1814           0 :                                         if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    1815           0 :                                             ShowContinueError(state,
    1816           0 :                                                               format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
    1817           0 :                                                                      state.dataPlnt->PlantLoop(LoopNum).Name));
    1818           0 :                                         } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
    1819             :                                                    LoopType::Condenser) { // not applicable to Condenser loops
    1820             :                                         }
    1821           0 :                                         ShowContinueError(state,
    1822             :                                                           " Use a setpoint manager or EMS actuator to place a dual temperature setpoint on node");
    1823           0 :                                         ErrorsFound = true;
    1824             :                                     }
    1825             :                                 }
    1826             :                             }
    1827             :                         }
    1828           8 :                         break;
    1829             :                     }
    1830           0 :                     default:
    1831           0 :                         break;
    1832             :                     }
    1833             :                 }
    1834             :             } else {
    1835           0 :                 ShowSevereError(state,
    1836           0 :                                 format("{} = \"{}\", specified without any machines.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    1837           0 :                 ErrorsFound = true;
    1838             :             }
    1839             :         }
    1840             :     } else {
    1841           0 :         ShowSevereError(state,
    1842           0 :                         format("{} = \"{}\", could not find {} = \"{}\".",
    1843             :                                LoopOpSchemeObj,
    1844           0 :                                state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
    1845             :                                CurrentModuleObject,
    1846           0 :                                state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
    1847           0 :         ErrorsFound = true;
    1848             :     }
    1849          15 : }
    1850             : 
    1851          10 : void GetChillerHeaterChangeoverOpSchemeInput(EnergyPlusData &state,
    1852             :                                              [[maybe_unused]] std::string &CurrentModuleObject,
    1853             :                                              int const NumSchemes,
    1854             :                                              bool &ErrorsFound)
    1855             : {
    1856             :     // process input objects for advanced operation scheme, use json type input patterns
    1857             : 
    1858          10 :     if (NumSchemes > 0 && state.dataPlantCondLoopOp->LoadSupervisoryChillerHeaterOpScheme) {
    1859             : 
    1860           3 :         state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes.allocate(NumSchemes);
    1861           3 :         std::string heatingOnlyLoadOpName;
    1862           3 :         std::string coolingOnlyLoadOpName;
    1863           3 :         std::string simultHeatCoolHeatingOpName;
    1864           3 :         std::string simulHeatCoolCoolingOpName;
    1865           6 :         for (int Num = 1; Num <= NumSchemes; ++Num) {
    1866           3 :             auto &scheme = state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes(Num);
    1867           3 :             std::string cCurrentModuleObject("PlantEquipmentOperation:ChillerHeaterChangeover");
    1868           3 :             static const std::string routineName("GetChillerHeaterChangeoverOpSchemeInput: ");
    1869           3 :             auto const schemeInstances = state.dataInputProcessing->inputProcessor->epJSON.find(cCurrentModuleObject);
    1870           3 :             auto &ip = state.dataInputProcessing->inputProcessor;
    1871           3 :             if (schemeInstances != ip->epJSON.end()) {
    1872           3 :                 auto &instancesValue = schemeInstances.value();
    1873           6 :                 for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
    1874           3 :                     auto const &fields = instance.value();
    1875           3 :                     auto const &thisObjectName = Util::makeUPPER(instance.key());
    1876           3 :                     state.dataInputProcessing->inputProcessor->markObjectAsUsed(cCurrentModuleObject, thisObjectName);
    1877           3 :                     scheme.Name = thisObjectName;
    1878           3 :                     scheme.TypeOf = "PlantEquipmentOperation:ChillerHeaterChangeover";
    1879           3 :                     scheme.Type = OpScheme::ChillerHeaterSupervisory;
    1880           3 :                     scheme.Setpoint.PrimCW = fields.at("primary_cooling_plant_setpoint_temperature").get<Real64>();
    1881           3 :                     auto const secCWSP = fields.find("secondary_distribution_cooling_plant_setpoint_temperature");
    1882           3 :                     if (secCWSP != fields.end()) { // not required field
    1883           3 :                         scheme.Setpoint.SecCW = secCWSP.value().get<Real64>();
    1884             :                     }
    1885           3 :                     scheme.Setpoint.PrimHW_High = fields.at("primary_heating_plant_setpoint_at_outdoor_high_temperature").get<Real64>();
    1886           3 :                     scheme.TempReset.HighOutdoorTemp = fields.at("outdoor_high_temperature").get<Real64>();
    1887           3 :                     scheme.Setpoint.PrimHW_Low = fields.at("primary_heating_plant_setpoint_at_outdoor_low_temperature").get<Real64>();
    1888           3 :                     scheme.TempReset.LowOutdoorTemp = fields.at("outdoor_low_temperature").get<Real64>();
    1889           3 :                     auto const secHWSP = fields.find("secondary_distribution_heating_plant_setpoint_temperature");
    1890           3 :                     if (secHWSP != fields.end()) { // not required field
    1891           3 :                         scheme.Setpoint.SecHW = secHWSP.value().get<Real64>();
    1892             :                     }
    1893           3 :                     auto const boilerOffset = fields.find("boiler_setpoint_temperature_offset");
    1894           6 :                     (boilerOffset != fields.end()) ? (scheme.TempReset.BoilerTemperatureOffset = boilerOffset.value().get<Real64>())
    1895           3 :                                                    : (scheme.TempReset.BoilerTemperatureOffset = 0.5);
    1896           3 :                     auto const backUpLow_HWset = fields.find("primary_heating_plant_setpoint_at_backup_outdoor_low_temperature");
    1897           6 :                     (backUpLow_HWset != fields.end()) ? (scheme.Setpoint.PrimHW_BackupLow = backUpLow_HWset.value().get<Real64>())
    1898           3 :                                                       : (scheme.Setpoint.PrimHW_BackupLow = scheme.Setpoint.PrimHW_Low);
    1899           3 :                     auto const backUpLowTemp = fields.find("backup_outdoor_low_temperature");
    1900           6 :                     (backUpLowTemp != fields.end()) ? (scheme.TempReset.BackupLowOutdoorTemp = backUpLowTemp.value().get<Real64>())
    1901           3 :                                                     : (scheme.TempReset.BackupLowOutdoorTemp = scheme.TempReset.LowOutdoorTemp);
    1902           3 :                     auto const zoneNameList = fields.find("zone_load_polling_zonelist_name");
    1903           3 :                     if (zoneNameList != fields.end()) {
    1904           3 :                         scheme.ZoneListName = Util::makeUPPER(zoneNameList.value().get<std::string>());
    1905             :                     }
    1906           3 :                     auto const coolPlantEqOpCoolingLoad = fields.find("cooling_only_load_plant_equipment_operation_cooling_load_name");
    1907           3 :                     if (coolPlantEqOpCoolingLoad != fields.end()) {
    1908           3 :                         coolingOnlyLoadOpName = Util::makeUPPER(coolPlantEqOpCoolingLoad.value().get<std::string>());
    1909             :                     }
    1910           3 :                     auto const heatPlantEqOpHeatingLoad = fields.find("heating_only_load_plant_equipment_operation_heating_load_name");
    1911           3 :                     if (heatPlantEqOpHeatingLoad != fields.end()) {
    1912           3 :                         heatingOnlyLoadOpName = Util::makeUPPER(heatPlantEqOpHeatingLoad.value().get<std::string>());
    1913             :                     }
    1914           3 :                     auto const simulEqOpCoolingLoad = fields.find("simultaneous_cooling_and_heating_plant_equipment_operation_cooling_load_name");
    1915           3 :                     if (simulEqOpCoolingLoad != fields.end()) {
    1916           2 :                         simulHeatCoolCoolingOpName = Util::makeUPPER(simulEqOpCoolingLoad.value().get<std::string>());
    1917           2 :                         scheme.PlantOps.SimulHeatCoolCoolingOpInput = true;
    1918             :                     }
    1919           3 :                     auto const simulEqOpHeatingLoad = fields.find("simultaneous_cooling_and_heating_plant_equipment_operation_heating_load_name");
    1920           3 :                     if (simulEqOpHeatingLoad != fields.end()) {
    1921           2 :                         simultHeatCoolHeatingOpName = Util::makeUPPER(simulEqOpHeatingLoad.value().get<std::string>());
    1922           2 :                         scheme.PlantOps.SimultHeatCoolHeatingOpInput = true;
    1923             :                     }
    1924           3 :                     auto const dedicatedCWHPName = fields.find("dedicated_chilled_water_return_recovery_heat_pump_name");
    1925           3 :                     if (dedicatedCWHPName != fields.end()) {
    1926           1 :                         scheme.DedicatedHR_ChWRetControl_Name = Util::makeUPPER(dedicatedCWHPName.value().get<std::string>());
    1927           1 :                         scheme.PlantOps.DedicatedHR_ChWRetControl_Input = true;
    1928             :                     }
    1929           3 :                     auto const dedicatedHWHPName = fields.find("dedicated_hot_water_return_recovery_heat_pump_name");
    1930           3 :                     if (dedicatedHWHPName != fields.end()) {
    1931           1 :                         scheme.DedicatedHR_HWRetControl_Name = Util::makeUPPER(dedicatedHWHPName.value().get<std::string>());
    1932           1 :                         scheme.PlantOps.DedicatedHR_HWRetControl_Input = true;
    1933             :                     }
    1934           6 :                 }
    1935             :             }
    1936             : 
    1937             :             //  Load input instances from input processor
    1938           3 :             cCurrentModuleObject = "PlantEquipmentOperation:CoolingLoad";
    1939           3 :             auto const coolLoadInstances = ip->epJSON.find(cCurrentModuleObject);
    1940           3 :             auto &coolLoadInstancesValue = coolLoadInstances.value();
    1941             : 
    1942           3 :             cCurrentModuleObject = "PlantEquipmentOperation:HeatingLoad";
    1943           3 :             auto const heatLoadInstances = ip->epJSON.find(cCurrentModuleObject);
    1944           3 :             auto &heatLoadInstancesValue = heatLoadInstances.value();
    1945             : 
    1946           3 :             cCurrentModuleObject = "PlantEquipmentList";
    1947           3 :             auto const equipListInstances = ip->epJSON.find(cCurrentModuleObject);
    1948           3 :             auto const &equipListObjectSchemaProps = ip->getObjectSchemaProps(state, cCurrentModuleObject);
    1949           3 :             auto &equipListInstancesValue = equipListInstances.value();
    1950             : 
    1951             :             // process cooling only mode equipment lists and ranges
    1952           8 :             for (auto instance = coolLoadInstancesValue.begin(); instance != coolLoadInstancesValue.end(); ++instance) {
    1953           5 :                 auto const &fields = instance.value();
    1954           5 :                 auto const &thisObjectName = Util::makeUPPER(instance.key());
    1955           5 :                 if (!Util::SameString(coolingOnlyLoadOpName, thisObjectName)) continue;
    1956             : 
    1957           3 :                 int numfields = fields.size();
    1958           3 :                 scheme.PlantOps.NumCoolingOnlyEquipLists = (numfields - 1) / 3; //  assume correctly formed field sets?
    1959           3 :                 scheme.CoolingOnlyEquipList.allocate(scheme.PlantOps.NumCoolingOnlyEquipLists);
    1960           9 :                 for (int listNum = 1; listNum <= scheme.PlantOps.NumCoolingOnlyEquipLists; ++listNum) {
    1961           6 :                     switch (listNum) {
    1962           3 :                     case 1: {
    1963           3 :                         scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_1_equipment_list_name").get<std::string>());
    1964           3 :                         scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_1_lower_limit").get<Real64>();
    1965           3 :                         scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_1_upper_limit").get<Real64>();
    1966           3 :                     } break;
    1967             : 
    1968           3 :                     case 2: {
    1969           3 :                         scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_2_equipment_list_name").get<std::string>());
    1970           3 :                         scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_2_lower_limit").get<Real64>();
    1971           3 :                         scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_2_upper_limit").get<Real64>();
    1972             : 
    1973           3 :                     } break;
    1974             : 
    1975           0 :                     case 3: {
    1976           0 :                         scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_3_equipment_list_name").get<std::string>());
    1977           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_3_lower_limit").get<Real64>();
    1978           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_3_upper_limit").get<Real64>();
    1979             : 
    1980           0 :                     } break;
    1981             : 
    1982           0 :                     case 4: {
    1983           0 :                         scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_4_equipment_list_name").get<std::string>());
    1984           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_4_lower_limit").get<Real64>();
    1985           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_4_upper_limit").get<Real64>();
    1986             : 
    1987           0 :                     } break;
    1988           0 :                     case 5: {
    1989           0 :                         scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_5_equipment_list_name").get<std::string>());
    1990           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_5_lower_limit").get<Real64>();
    1991           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_5_upper_limit").get<Real64>();
    1992             : 
    1993           0 :                     } break;
    1994           0 :                     case 6: {
    1995           0 :                         scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_6_equipment_list_name").get<std::string>());
    1996           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_6_lower_limit").get<Real64>();
    1997           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_6_upper_limit").get<Real64>();
    1998             : 
    1999           0 :                     } break;
    2000             : 
    2001           0 :                     case 7: {
    2002           0 :                         scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_7_equipment_list_name").get<std::string>());
    2003           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_7_lower_limit").get<Real64>();
    2004           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_7_upper_limit").get<Real64>();
    2005             : 
    2006           0 :                     } break;
    2007             : 
    2008           0 :                     case 8: {
    2009           0 :                         scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_8_equipment_list_name").get<std::string>());
    2010           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_8_lower_limit").get<Real64>();
    2011           0 :                         scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_8_upper_limit").get<Real64>();
    2012             : 
    2013           0 :                     } break;
    2014             :                     }
    2015             :                 }
    2016           8 :             }
    2017             : 
    2018           3 :             if (!allocated(scheme.CoolingOnlyEquipList)) { // never found a match
    2019           0 :                 ShowSevereError(state,
    2020           0 :                                 format("GetChillerHeaterChangeoverOpSchemeInput problem with PlantEquipmentOperation:ChillerHeaterChangeover name "
    2021             :                                        "=\"{}\", PlantEquipmentOperation:CoolingLoad name = \"{}\" was not found.",
    2022           0 :                                        scheme.Name,
    2023             :                                        coolingOnlyLoadOpName));
    2024           0 :                 ErrorsFound = true;
    2025             :             }
    2026             : 
    2027           9 :             for (int listNum = 1; listNum <= scheme.PlantOps.NumCoolingOnlyEquipLists; ++listNum) {
    2028             : 
    2029          44 :                 for (auto instance = equipListInstancesValue.begin(); instance != equipListInstancesValue.end(); ++instance) {
    2030          38 :                     auto const &objectFields = instance.value();
    2031          38 :                     auto const &thisObjectName = Util::makeUPPER(instance.key());
    2032          38 :                     if (!Util::SameString(scheme.CoolingOnlyEquipList(listNum).Name, thisObjectName)) continue;
    2033             : 
    2034           6 :                     auto extensibles = objectFields.find("equipment");
    2035           6 :                     auto const &extensionSchemaProps = equipListObjectSchemaProps["equipment"]["items"]["properties"];
    2036           6 :                     if (extensibles != objectFields.end()) {
    2037           6 :                         auto extensiblesArray = extensibles.value();
    2038           6 :                         int numExtensibles = extensiblesArray.size();
    2039           6 :                         scheme.CoolingOnlyEquipList(listNum).NumComps = numExtensibles;
    2040           6 :                         scheme.CoolingOnlyEquipList(listNum).Comp.allocate(numExtensibles);
    2041           6 :                         int listItem = 0;
    2042          15 :                         for (nlohmann::json const &extensibleInstance : extensiblesArray) {
    2043           9 :                             ++listItem;
    2044           9 :                             scheme.CoolingOnlyEquipList(listNum).Comp(listItem).TypeOf =
    2045          18 :                                 ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_object_type");
    2046           9 :                             scheme.CoolingOnlyEquipList(listNum).Comp(listItem).Name =
    2047          18 :                                 ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_name");
    2048           6 :                         }
    2049           6 :                     }
    2050          44 :                 }
    2051             :             }
    2052             : 
    2053             :             // process heating only mode equipment lists and ranges
    2054          14 :             for (auto instance = heatLoadInstancesValue.begin(); instance != heatLoadInstancesValue.end(); ++instance) {
    2055          11 :                 auto const &fields = instance.value();
    2056          11 :                 auto const &thisObjectName = Util::makeUPPER(instance.key());
    2057          11 :                 if (!Util::SameString(heatingOnlyLoadOpName, thisObjectName)) continue;
    2058             : 
    2059           3 :                 int numfields = fields.size();
    2060           3 :                 scheme.PlantOps.NumHeatingOnlyEquipLists = (numfields - 1) / 3; //  assume correctly formed field sets?
    2061           3 :                 scheme.HeatingOnlyEquipList.allocate(scheme.PlantOps.NumHeatingOnlyEquipLists);
    2062           9 :                 for (int listNum = 1; listNum <= scheme.PlantOps.NumHeatingOnlyEquipLists; ++listNum) {
    2063           6 :                     switch (listNum) {
    2064           3 :                     case 1: {
    2065           3 :                         scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_1_equipment_list_name").get<std::string>());
    2066           3 :                         scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_1_lower_limit").get<Real64>();
    2067           3 :                         scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_1_upper_limit").get<Real64>();
    2068           3 :                     } break;
    2069             : 
    2070           3 :                     case 2: {
    2071           3 :                         scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_2_equipment_list_name").get<std::string>());
    2072           3 :                         scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_2_lower_limit").get<Real64>();
    2073           3 :                         scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_2_upper_limit").get<Real64>();
    2074             : 
    2075           3 :                     } break;
    2076             : 
    2077           0 :                     case 3: {
    2078           0 :                         scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_3_equipment_list_name").get<std::string>());
    2079           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_3_lower_limit").get<Real64>();
    2080           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_3_upper_limit").get<Real64>();
    2081             : 
    2082           0 :                     } break;
    2083             : 
    2084           0 :                     case 4: {
    2085           0 :                         scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_4_equipment_list_name").get<std::string>());
    2086           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_4_lower_limit").get<Real64>();
    2087           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_4_upper_limit").get<Real64>();
    2088             : 
    2089           0 :                     } break;
    2090           0 :                     case 5: {
    2091           0 :                         scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_5_equipment_list_name").get<std::string>());
    2092           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_5_lower_limit").get<Real64>();
    2093           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_5_upper_limit").get<Real64>();
    2094             : 
    2095           0 :                     } break;
    2096           0 :                     case 6: {
    2097           0 :                         scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_6_equipment_list_name").get<std::string>());
    2098           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_6_lower_limit").get<Real64>();
    2099           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_6_upper_limit").get<Real64>();
    2100             : 
    2101           0 :                     } break;
    2102             : 
    2103           0 :                     case 7: {
    2104           0 :                         scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_7_equipment_list_name").get<std::string>());
    2105           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_7_lower_limit").get<Real64>();
    2106           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_7_upper_limit").get<Real64>();
    2107             : 
    2108           0 :                     } break;
    2109             : 
    2110           0 :                     case 8: {
    2111           0 :                         scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_8_equipment_list_name").get<std::string>());
    2112           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_8_lower_limit").get<Real64>();
    2113           0 :                         scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_8_upper_limit").get<Real64>();
    2114             : 
    2115           0 :                     } break;
    2116             :                     }
    2117             :                 }
    2118          14 :             }
    2119             : 
    2120           3 :             if (!allocated(scheme.HeatingOnlyEquipList)) { // never found a match
    2121           0 :                 ShowSevereError(state,
    2122           0 :                                 format("GetChillerHeaterChangeoverOpSchemeInput problem with PlantEquipmentOperation:ChillerHeaterChangeover name "
    2123             :                                        "=\"{}\", PlantEquipmentOperation:HeatingLoad name = \"{}\" was not found.",
    2124           0 :                                        scheme.Name,
    2125             :                                        heatingOnlyLoadOpName));
    2126           0 :                 ErrorsFound = true;
    2127             :             }
    2128             : 
    2129           9 :             for (int listNum = 1; listNum <= scheme.PlantOps.NumHeatingOnlyEquipLists; ++listNum) {
    2130             : 
    2131          44 :                 for (auto instance = equipListInstancesValue.begin(); instance != equipListInstancesValue.end(); ++instance) {
    2132          38 :                     auto const &objectFields = instance.value();
    2133          38 :                     auto const &thisObjectName = Util::makeUPPER(instance.key());
    2134          38 :                     if (!Util::SameString(scheme.HeatingOnlyEquipList(listNum).Name, thisObjectName)) continue;
    2135             : 
    2136           6 :                     auto extensibles = objectFields.find("equipment");
    2137           6 :                     auto const &extensionSchemaProps = equipListObjectSchemaProps["equipment"]["items"]["properties"];
    2138           6 :                     if (extensibles != objectFields.end()) {
    2139           6 :                         auto extensiblesArray = extensibles.value();
    2140           6 :                         int numExtensibles = extensiblesArray.size();
    2141           6 :                         scheme.HeatingOnlyEquipList(listNum).NumComps = numExtensibles;
    2142           6 :                         scheme.HeatingOnlyEquipList(listNum).Comp.allocate(numExtensibles);
    2143           6 :                         int listItem = 0;
    2144          15 :                         for (nlohmann::json const &extensibleInstance : extensiblesArray) {
    2145           9 :                             ++listItem;
    2146           9 :                             scheme.HeatingOnlyEquipList(listNum).Comp(listItem).TypeOf =
    2147          18 :                                 ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_object_type");
    2148           9 :                             scheme.HeatingOnlyEquipList(listNum).Comp(listItem).Name =
    2149          18 :                                 ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_name");
    2150           6 :                         }
    2151           6 :                     }
    2152          44 :                 }
    2153             :             }
    2154             : 
    2155             :             // process simulataneous heating and cooling mode cooling equipment lists and ranges
    2156             : 
    2157           8 :             for (auto instance = coolLoadInstancesValue.begin(); instance != coolLoadInstancesValue.end(); ++instance) {
    2158           5 :                 auto const &fields = instance.value();
    2159           5 :                 auto const &thisObjectName = Util::makeUPPER(instance.key());
    2160           5 :                 if (!Util::SameString(simulHeatCoolCoolingOpName, thisObjectName)) continue;
    2161             : 
    2162           2 :                 int numfields = fields.size();
    2163           2 :                 scheme.PlantOps.NumSimultHeatCoolCoolingEquipLists = (numfields - 1) / 3; //  assume correctly formed field sets?
    2164           2 :                 scheme.SimultHeatCoolCoolingEquipList.allocate(scheme.PlantOps.NumSimultHeatCoolCoolingEquipLists);
    2165           4 :                 for (int listNum = 1; listNum <= scheme.PlantOps.NumSimultHeatCoolCoolingEquipLists; ++listNum) {
    2166           2 :                     switch (listNum) {
    2167           2 :                     case 1: {
    2168           2 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
    2169           4 :                             Util::makeUPPER(fields.at("range_1_equipment_list_name").get<std::string>());
    2170           2 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_1_lower_limit").get<Real64>();
    2171           2 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_1_upper_limit").get<Real64>();
    2172           2 :                     } break;
    2173             : 
    2174           0 :                     case 2: {
    2175           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
    2176           0 :                             Util::makeUPPER(fields.at("range_2_equipment_list_name").get<std::string>());
    2177           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_2_lower_limit").get<Real64>();
    2178           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_2_upper_limit").get<Real64>();
    2179             : 
    2180           0 :                     } break;
    2181             : 
    2182           0 :                     case 3: {
    2183           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
    2184           0 :                             Util::makeUPPER(fields.at("range_3_equipment_list_name").get<std::string>());
    2185           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_3_lower_limit").get<Real64>();
    2186           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_3_upper_limit").get<Real64>();
    2187             : 
    2188           0 :                     } break;
    2189             : 
    2190           0 :                     case 4: {
    2191           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
    2192           0 :                             Util::makeUPPER(fields.at("range_4_equipment_list_name").get<std::string>());
    2193           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_4_lower_limit").get<Real64>();
    2194           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_4_upper_limit").get<Real64>();
    2195             : 
    2196           0 :                     } break;
    2197           0 :                     case 5: {
    2198           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
    2199           0 :                             Util::makeUPPER(fields.at("range_5_equipment_list_name").get<std::string>());
    2200           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_5_lower_limit").get<Real64>();
    2201           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_5_upper_limit").get<Real64>();
    2202             : 
    2203           0 :                     } break;
    2204           0 :                     case 6: {
    2205           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
    2206           0 :                             Util::makeUPPER(fields.at("range_6_equipment_list_name").get<std::string>());
    2207           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_6_lower_limit").get<Real64>();
    2208           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_6_upper_limit").get<Real64>();
    2209             : 
    2210           0 :                     } break;
    2211             : 
    2212           0 :                     case 7: {
    2213           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
    2214           0 :                             Util::makeUPPER(fields.at("range_7_equipment_list_name").get<std::string>());
    2215           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_7_lower_limit").get<Real64>();
    2216           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_7_upper_limit").get<Real64>();
    2217             : 
    2218           0 :                     } break;
    2219             : 
    2220           0 :                     case 8: {
    2221           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
    2222           0 :                             Util::makeUPPER(fields.at("range_8_equipment_list_name").get<std::string>());
    2223           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_8_lower_limit").get<Real64>();
    2224           0 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_8_upper_limit").get<Real64>();
    2225             : 
    2226           0 :                     } break;
    2227             :                     }
    2228             :                 }
    2229           8 :             }
    2230             : 
    2231           3 :             if (scheme.PlantOps.SimulHeatCoolCoolingOpInput && !allocated(scheme.SimultHeatCoolCoolingEquipList)) {
    2232           0 :                 ShowSevereError(state,
    2233           0 :                                 format("GetChillerHeaterChangeoverOpSchemeInput problem with PlantEquipmentOperation:ChillerHeaterChangeover name "
    2234             :                                        "=\"{}\", PlantEquipmentOperation:CoolingLoad name = \"{}\" was not found.",
    2235           0 :                                        scheme.Name,
    2236             :                                        simulHeatCoolCoolingOpName));
    2237           0 :                 ErrorsFound = true;
    2238             :             }
    2239             : 
    2240           5 :             for (int listNum = 1; listNum <= scheme.PlantOps.NumSimultHeatCoolCoolingEquipLists; ++listNum) {
    2241             : 
    2242          14 :                 for (auto instance = equipListInstancesValue.begin(); instance != equipListInstancesValue.end(); ++instance) {
    2243          12 :                     auto const &objectFields = instance.value();
    2244          12 :                     auto const &thisObjectName = Util::makeUPPER(instance.key());
    2245          12 :                     if (!Util::SameString(scheme.SimultHeatCoolCoolingEquipList(listNum).Name, thisObjectName)) continue;
    2246             : 
    2247           2 :                     auto extensibles = objectFields.find("equipment");
    2248           2 :                     auto const &extensionSchemaProps = equipListObjectSchemaProps["equipment"]["items"]["properties"];
    2249           2 :                     if (extensibles != objectFields.end()) {
    2250           2 :                         auto extensiblesArray = extensibles.value();
    2251           2 :                         int numExtensibles = extensiblesArray.size();
    2252           2 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).NumComps = numExtensibles;
    2253           2 :                         scheme.SimultHeatCoolCoolingEquipList(listNum).Comp.allocate(numExtensibles);
    2254           2 :                         int listItem = 0;
    2255           4 :                         for (nlohmann::json const &extensibleInstance : extensiblesArray) {
    2256           2 :                             ++listItem;
    2257           2 :                             scheme.SimultHeatCoolCoolingEquipList(listNum).Comp(listItem).TypeOf =
    2258           4 :                                 ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_object_type");
    2259           2 :                             scheme.SimultHeatCoolCoolingEquipList(listNum).Comp(listItem).Name =
    2260           4 :                                 ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_name");
    2261           2 :                         }
    2262           2 :                     }
    2263          14 :                 }
    2264             :             }
    2265             : 
    2266             :             // process simultaneous heating and cooling mode heating equipment lists and ranges
    2267             : 
    2268          14 :             for (auto instance = heatLoadInstancesValue.begin(); instance != heatLoadInstancesValue.end(); ++instance) {
    2269          11 :                 auto const &fields = instance.value();
    2270          11 :                 auto const &thisObjectName = Util::makeUPPER(instance.key());
    2271          11 :                 if (!Util::SameString(simultHeatCoolHeatingOpName, thisObjectName)) continue;
    2272             : 
    2273           2 :                 int numfields = fields.size();
    2274           2 :                 scheme.PlantOps.NumSimultHeatCoolHeatingEquipLists = (numfields - 1) / 3; //  assume correctly formed field sets?
    2275           2 :                 scheme.SimultHeatCoolHeatingEquipList.allocate(scheme.PlantOps.NumSimultHeatCoolHeatingEquipLists);
    2276           4 :                 for (int listNum = 1; listNum <= scheme.PlantOps.NumSimultHeatCoolHeatingEquipLists; ++listNum) {
    2277           2 :                     switch (listNum) {
    2278           2 :                     case 1: {
    2279           2 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
    2280           4 :                             Util::makeUPPER(fields.at("range_1_equipment_list_name").get<std::string>());
    2281           2 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_1_lower_limit").get<Real64>();
    2282           2 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_1_upper_limit").get<Real64>();
    2283           2 :                     } break;
    2284             : 
    2285           0 :                     case 2: {
    2286           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
    2287           0 :                             Util::makeUPPER(fields.at("range_2_equipment_list_name").get<std::string>());
    2288           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_2_lower_limit").get<Real64>();
    2289           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_2_upper_limit").get<Real64>();
    2290             : 
    2291           0 :                     } break;
    2292             : 
    2293           0 :                     case 3: {
    2294           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
    2295           0 :                             Util::makeUPPER(fields.at("range_3_equipment_list_name").get<std::string>());
    2296           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_3_lower_limit").get<Real64>();
    2297           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_3_upper_limit").get<Real64>();
    2298             : 
    2299           0 :                     } break;
    2300             : 
    2301           0 :                     case 4: {
    2302           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
    2303           0 :                             Util::makeUPPER(fields.at("range_4_equipment_list_name").get<std::string>());
    2304           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_4_lower_limit").get<Real64>();
    2305           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_4_upper_limit").get<Real64>();
    2306             : 
    2307           0 :                     } break;
    2308           0 :                     case 5: {
    2309           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
    2310           0 :                             Util::makeUPPER(fields.at("range_5_equipment_list_name").get<std::string>());
    2311           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_5_lower_limit").get<Real64>();
    2312           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_5_upper_limit").get<Real64>();
    2313             : 
    2314           0 :                     } break;
    2315           0 :                     case 6: {
    2316           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
    2317           0 :                             Util::makeUPPER(fields.at("range_6_equipment_list_name").get<std::string>());
    2318           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_6_lower_limit").get<Real64>();
    2319           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_6_upper_limit").get<Real64>();
    2320             : 
    2321           0 :                     } break;
    2322             : 
    2323           0 :                     case 7: {
    2324           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
    2325           0 :                             Util::makeUPPER(fields.at("range_7_equipment_list_name").get<std::string>());
    2326           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_7_lower_limit").get<Real64>();
    2327           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_7_upper_limit").get<Real64>();
    2328             : 
    2329           0 :                     } break;
    2330             : 
    2331           0 :                     case 8: {
    2332           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
    2333           0 :                             Util::makeUPPER(fields.at("range_8_equipment_list_name").get<std::string>());
    2334           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_8_lower_limit").get<Real64>();
    2335           0 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_8_upper_limit").get<Real64>();
    2336             : 
    2337           0 :                     } break;
    2338             :                     }
    2339             :                 }
    2340          14 :             }
    2341           3 :             if (scheme.PlantOps.SimultHeatCoolHeatingOpInput && !allocated(scheme.SimultHeatCoolHeatingEquipList)) {
    2342           0 :                 ShowSevereError(state,
    2343           0 :                                 format("GetChillerHeaterChangeoverOpSchemeInput problem with PlantEquipmentOperation:ChillerHeaterChangeover name "
    2344             :                                        "=\"{}\", PlantEquipmentOperation:HeatingLoad name = \"{}\" was not found.",
    2345           0 :                                        scheme.Name,
    2346             :                                        simultHeatCoolHeatingOpName));
    2347           0 :                 ErrorsFound = true;
    2348             :             }
    2349             : 
    2350           5 :             for (int listNum = 1; listNum <= scheme.PlantOps.NumSimultHeatCoolHeatingEquipLists; ++listNum) {
    2351             : 
    2352           2 :                 std::string cCurrentModuleObject("PlantEquipmentList");
    2353             : 
    2354           2 :                 auto const instances = ip->epJSON.find(cCurrentModuleObject);
    2355           2 :                 auto const &objectSchemaProps = ip->getObjectSchemaProps(state, cCurrentModuleObject);
    2356             : 
    2357           2 :                 auto &instancesValue = instances.value();
    2358          14 :                 for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
    2359          12 :                     auto const &objectFields = instance.value();
    2360          12 :                     auto const &thisObjectName = Util::makeUPPER(instance.key());
    2361          12 :                     if (!Util::SameString(scheme.SimultHeatCoolHeatingEquipList(listNum).Name, thisObjectName)) continue;
    2362             : 
    2363           2 :                     auto extensibles = objectFields.find("equipment");
    2364           2 :                     auto const &extensionSchemaProps = objectSchemaProps["equipment"]["items"]["properties"];
    2365           2 :                     if (extensibles != objectFields.end()) {
    2366           2 :                         auto extensiblesArray = extensibles.value();
    2367           2 :                         int numExtensibles = extensiblesArray.size();
    2368           2 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).NumComps = numExtensibles;
    2369           2 :                         scheme.SimultHeatCoolHeatingEquipList(listNum).Comp.allocate(numExtensibles);
    2370           2 :                         int listItem = 0;
    2371           4 :                         for (nlohmann::json const &extensibleInstance : extensiblesArray) {
    2372           2 :                             ++listItem;
    2373           2 :                             scheme.SimultHeatCoolHeatingEquipList(listNum).Comp(listItem).TypeOf =
    2374           4 :                                 ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_object_type");
    2375           2 :                             scheme.SimultHeatCoolHeatingEquipList(listNum).Comp(listItem).Name =
    2376           4 :                                 ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_name");
    2377           2 :                         }
    2378           2 :                     }
    2379          14 :                 }
    2380           2 :             }
    2381           3 :         }
    2382           3 :     }
    2383          10 :     state.dataPlantCondLoopOp->LoadSupervisoryChillerHeaterOpScheme = false;
    2384          10 : }
    2385             : 
    2386           6 : void GetUserDefinedOpSchemeInput(EnergyPlusData &state,
    2387             :                                  std::string &CurrentModuleObject, // for ease in renaming
    2388             :                                  int const NumSchemes,             // May be set here and passed on
    2389             :                                  int const LoopNum,                // May be set here and passed on
    2390             :                                  int const SchemeNum,              // May be set here and passed on
    2391             :                                  bool &ErrorsFound                 // May be set here and passed on
    2392             : )
    2393             : {
    2394             : 
    2395             :     // SUBROUTINE INFORMATION:
    2396             :     //       AUTHOR         <author>
    2397             :     //       DATE WRITTEN   <date_written>
    2398             :     //       MODIFIED       na
    2399             :     //       RE-ENGINEERED  na
    2400             : 
    2401             :     // PURPOSE OF THIS SUBROUTINE:
    2402             :     // <description>
    2403             : 
    2404             :     // Using/Aliasing
    2405             :     using namespace DataPlant;
    2406             : 
    2407             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2408             :     int NumAlphas;
    2409             :     int NumNums;
    2410             :     int Num;
    2411             :     int CompNum;
    2412             :     int IOStat;
    2413             :     bool SchemeNameFound;        // Set to FALSE if a match of OpScheme object and OpScheme name is not found
    2414           6 :     std::string LoopOpSchemeObj; // Used to identify the object name for loop equipment operation scheme
    2415             :     int StackMngrNum;            // local temporary for Erl program calling manager index
    2416             : 
    2417           6 :     SchemeNameFound = true;
    2418             : 
    2419           6 :     if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
    2420           4 :         LoopOpSchemeObj = "PlantEquipmentOperationSchemes";
    2421           2 :     } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Condenser) {
    2422           2 :         LoopOpSchemeObj = "CondenserEquipmentOperationSchemes";
    2423             :     }
    2424             : 
    2425           6 :     if (NumSchemes > 0) {
    2426             : 
    2427          12 :         for (Num = 1; Num <= NumSchemes; ++Num) {
    2428          24 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    2429             :                                                                      CurrentModuleObject,
    2430             :                                                                      Num,
    2431          12 :                                                                      state.dataIPShortCut->cAlphaArgs,
    2432             :                                                                      NumAlphas,
    2433          12 :                                                                      state.dataIPShortCut->rNumericArgs,
    2434             :                                                                      NumNums,
    2435             :                                                                      IOStat,
    2436          12 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    2437          12 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    2438          12 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    2439          12 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    2440          12 :             if (Util::SameString(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name, state.dataIPShortCut->cAlphaArgs(1)))
    2441           6 :                 break;               // found the correct one
    2442           6 :             if (Num == NumSchemes) { // did not find it
    2443           0 :                 ShowSevereError(state,
    2444           0 :                                 format("{} = \"{}\", could not find {} = \"{}\".",
    2445             :                                        LoopOpSchemeObj,
    2446           0 :                                        state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
    2447             :                                        CurrentModuleObject,
    2448           0 :                                        state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
    2449           0 :                 ErrorsFound = true;
    2450           0 :                 SchemeNameFound = false;
    2451             :             }
    2452             :         }
    2453           6 :         if (SchemeNameFound) {
    2454           6 :             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists = 1;
    2455           6 :             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList.allocate(1);
    2456             : 
    2457           6 :             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps = (NumAlphas - 3) / 2;
    2458           6 :             if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps > 0) {
    2459          12 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp.allocate(
    2460           6 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps);
    2461          14 :                 for (CompNum = 1; CompNum <= state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps; ++CompNum) {
    2462           8 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).TypeOf =
    2463          16 :                         state.dataIPShortCut->cAlphaArgs(CompNum * 2 + 2);
    2464           8 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).Name =
    2465          16 :                         state.dataIPShortCut->cAlphaArgs(CompNum * 2 + 3);
    2466             : 
    2467             :                     // Setup EMS actuators for machines' MyLoad.
    2468          16 :                     SetupEMSActuator(
    2469             :                         state,
    2470             :                         "Plant Equipment Operation",
    2471          16 :                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name + ':' +
    2472           8 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).Name,
    2473             :                         "Distributed Load Rate",
    2474             :                         "[W]",
    2475           8 :                         state.dataPlantCondLoopOp->lDummy,
    2476           8 :                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).EMSActuatorDispatchedLoadValue);
    2477             :                     // TODO: I think this should be a sensor really
    2478           8 :                     SetupEMSInternalVariable(
    2479             :                         state,
    2480             :                         "Component Remaining Current Demand Rate",
    2481          16 :                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name + ':' +
    2482           8 :                             state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).Name,
    2483             :                         "[W]",
    2484           8 :                         state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).EMSIntVarRemainingLoadValue);
    2485             :                 }
    2486             :             }
    2487           6 :             StackMngrNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataRuntimeLang->EMSProgramCallManager);
    2488           6 :             if (StackMngrNum > 0) { // found it
    2489           3 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).ErlSimProgramMngr = StackMngrNum;
    2490             :             } else {
    2491           3 :                 state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).simPluginLocation =
    2492           3 :                     state.dataPluginManager->pluginManager->getLocationOfUserDefinedPlugin(state, state.dataIPShortCut->cAlphaArgs(2));
    2493           3 :                 if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).simPluginLocation == -1) {
    2494           0 :                     ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
    2495           0 :                     ShowContinueError(state, format("Entered in {}={}", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    2496           0 :                     ShowContinueError(state, "Not found as either an EMS Program Manager or a Python Plugin instance.");
    2497           0 :                     ErrorsFound = true;
    2498             :                 }
    2499             :             }
    2500           6 :             if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
    2501           1 :                 StackMngrNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataRuntimeLang->EMSProgramCallManager);
    2502           1 :                 if (StackMngrNum > 0) { // found it
    2503           1 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).ErlInitProgramMngr = StackMngrNum;
    2504             :                 } else {
    2505           0 :                     state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).initPluginLocation =
    2506           0 :                         state.dataPluginManager->pluginManager->getLocationOfUserDefinedPlugin(state, state.dataIPShortCut->cAlphaArgs(3));
    2507           0 :                     if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).initPluginLocation == -1) {
    2508           0 :                         ShowSevereError(state,
    2509           0 :                                         format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
    2510           0 :                         ShowContinueError(state, format("Entered in {}={}", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
    2511           0 :                         ShowContinueError(state, "Not found as either an EMS Program Manager or a Python Plugin instance.");
    2512           0 :                         ErrorsFound = true;
    2513             :                     }
    2514             :                 }
    2515             :             }
    2516             : 
    2517             :             // setup internal variable for Supply Side Current Demand Rate [W]
    2518           6 :             SetupEMSInternalVariable(state,
    2519             :                                      "Supply Side Current Demand Rate",
    2520           6 :                                      state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name,
    2521             :                                      "[W]",
    2522           6 :                                      state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EMSIntVarLoopDemandRate);
    2523             :         }
    2524             : 
    2525             :     } else {
    2526           0 :         ShowSevereError(state,
    2527           0 :                         format("{} = \"{}\", could not find {} = \"{}\".",
    2528             :                                LoopOpSchemeObj,
    2529           0 :                                state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
    2530             :                                CurrentModuleObject,
    2531           0 :                                state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
    2532           0 :         ErrorsFound = true;
    2533             :     }
    2534           6 : }
    2535             : 
    2536             : // End of GetInput subroutines for the Module
    2537             : //******************************************************************************
    2538             : 
    2539             : // Beginning Initialization Section of the Plant Loop Module
    2540             : //******************************************************************************
    2541             : 
    2542    31741579 : void InitLoadDistribution(EnergyPlusData &state, bool const FirstHVACIteration)
    2543             : {
    2544             :     // SUBROUTINE INFORMATION:
    2545             :     //       AUTHOR:          Dan Fisher
    2546             :     //       DATE WRITTEN:    July 2010
    2547             :     //       REVISED:
    2548             : 
    2549             :     // PURPOSE OF THIS SUBROUTINE:
    2550             :     // This subroutine scans equipment lists and matches a particular
    2551             :     // plant component with a component on the list.  Pointers to the
    2552             :     // operation scheme and equipment list are saved on the plant data
    2553             :     // structure to facilitate a new load management routine that calls
    2554             :     // ManageLoadDistribution for every component.
    2555             : 
    2556             :     // Using/Aliasing
    2557             :     using EMSManager::ManageEMS;
    2558             :     using ScheduleManager::GetCurrentScheduleValue;
    2559             :     using ScheduleManager::GetScheduleIndex;
    2560             : 
    2561             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2562             :     int LoopPtr;
    2563             :     DataPlant::LoopSideLocation LoopSidePtr;
    2564             :     int BranchPtr;
    2565             :     int CompPtr;
    2566    31741579 :     PlantLocation plantLoc{};
    2567             :     int Index;
    2568             :     int OpSchemePtr;
    2569             :     int thisSchemeNum;
    2570             : 
    2571             :     bool FoundScheme;
    2572             :     bool FoundSchemeMatch;
    2573             :     //  LOGICAL, SAVE                     :: FirstHVACInitsDone = .FALSE.
    2574             :     //  LOGICAL, SAVE                     :: MyEnvrnFlag = .TRUE.
    2575             :     DataPlant::PlantEquipmentType Type;
    2576             :     int CompOpNum;
    2577             :     int OldNumOpSchemes;
    2578             :     int NewNumEquipLists;
    2579             :     int NewNumOpSchemes;
    2580             :     int NumSearchResults;
    2581             :     bool GetInputOK; // successful Get Input
    2582             : 
    2583             :     bool errFlag1;
    2584             :     bool errFlag2;
    2585             :     Real64 HighestRange;
    2586             : 
    2587             :     // Object Data
    2588             : 
    2589    31741579 :     errFlag2 = false;
    2590             :     // Get Input
    2591    31741579 :     if (state.dataPlantCondLoopOp->GetPlantOpInput) {
    2592         458 :         GetPlantOperationInput(state, GetInputOK);
    2593         458 :         if (GetInputOK) {
    2594         458 :             GetOperationSchemeInput(state);
    2595         458 :             state.dataPlantCondLoopOp->GetPlantOpInput = false;
    2596             :         } else {
    2597           0 :             return;
    2598             :         }
    2599             :     }
    2600             : 
    2601             :     // ONE TIME INITS
    2602    31741579 :     if (state.dataPlantCondLoopOp->InitLoadDistributionOneTimeFlag) {
    2603             :         // Set up 'component' to 'op scheme' pointers in Plant data structure
    2604             :         // We're looking for matches between a component on a PlantLoop.OpScheme.List()
    2605             :         // and the same component in the PlantLoop.LoopSide.Branch.Comp() data structure
    2606             : 
    2607             :         // first loop over main operation scheme data and finish filling out indexes to plant topology for the components in the lists
    2608        1605 :         for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
    2609        1147 :             auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
    2610        2416 :             for (int OpNum = 1, OpNum_end = this_plant_loop.NumOpSchemes; OpNum <= OpNum_end; ++OpNum) {
    2611        1269 :                 auto &this_op_scheme = this_plant_loop.OpScheme(OpNum);
    2612        2686 :                 for (int ListNum = 1, ListNum_end = this_op_scheme.NumEquipLists; ListNum <= ListNum_end; ++ListNum) {
    2613        1417 :                     auto &this_equip_list = this_op_scheme.EquipList(ListNum);
    2614        3050 :                     for (int EquipNum = 1, EquipNum_end = this_equip_list.NumComps; EquipNum <= EquipNum_end; ++EquipNum) {
    2615        1633 :                         auto &this_equip = this_equip_list.Comp(EquipNum);
    2616        1633 :                         Type = static_cast<DataPlant::PlantEquipmentType>(getEnumValue(PlantEquipTypeNamesUC, Util::makeUPPER(this_equip.TypeOf)));
    2617        1633 :                         errFlag1 = false;
    2618        1633 :                         PlantUtilities::ScanPlantLoopsForObject(state, this_equip.Name, Type, plantLoc, errFlag1, _, _, NumSearchResults, _, LoopNum);
    2619             : 
    2620        1633 :                         if (errFlag1) {
    2621           0 :                             ShowSevereError(state, "InitLoadDistribution: Equipment specified for operation scheme not found on correct loop");
    2622           0 :                             ShowContinueError(state, format("Operation Scheme name = {}", this_op_scheme.Name));
    2623           0 :                             ShowContinueError(state, format("Loop name = {}", this_plant_loop.Name));
    2624           0 :                             ShowContinueError(state, format("Component name = {}", this_equip.Name));
    2625           0 :                             ShowFatalError(state, "InitLoadDistribution: Simulation terminated because of error in operation scheme.");
    2626             :                         }
    2627             : 
    2628        1633 :                         this_equip.LoopNumPtr = plantLoc.loopNum;
    2629        1633 :                         this_equip.LoopSideNumPtr = plantLoc.loopSideNum;
    2630        1633 :                         this_equip.BranchNumPtr = plantLoc.branchNum;
    2631        1633 :                         this_equip.CompNumPtr = plantLoc.compNum;
    2632             : 
    2633        1633 :                         if (ValidLoopEquipTypes[static_cast<int>(Type)] == LoopType::Plant && this_plant_loop.TypeOfLoop == LoopType::Condenser) {
    2634           0 :                             ShowSevereError(state,
    2635           0 :                                             format("InitLoadDistribution: CondenserLoop=\"{}\", Operation Scheme=\"{}\",",
    2636           0 :                                                    this_plant_loop.Name,
    2637           0 :                                                    this_plant_loop.OperationScheme));
    2638           0 :                             ShowContinueError(state,
    2639           0 :                                               format("Scheme type={}, Name=\"{}\" includes equipment that is not valid on a Condenser Loop",
    2640           0 :                                                      this_op_scheme.TypeOf,
    2641           0 :                                                      this_op_scheme.Name));
    2642           0 :                             ShowContinueError(state,
    2643           0 :                                               format("Component {} not allowed as supply equipment on this type of loop.",
    2644           0 :                                                      PlantEquipTypeNames[static_cast<int>(Type)]));
    2645           0 :                             ShowContinueError(state, format("Component name = {}", this_equip.Name));
    2646           0 :                             errFlag2 = true;
    2647             :                         }
    2648        1633 :                         if (ValidLoopEquipTypes[static_cast<int>(Type)] == LoopType::Condenser && this_plant_loop.TypeOfLoop == LoopType::Plant) {
    2649           0 :                             ShowSevereError(state,
    2650           0 :                                             format("InitLoadDistribution: PlantLoop=\"{}\", Operation Scheme=\"{}\",",
    2651           0 :                                                    this_plant_loop.Name,
    2652           0 :                                                    this_plant_loop.OperationScheme));
    2653           0 :                             ShowContinueError(state,
    2654           0 :                                               format("Scheme type={}, Name=\"{}\" includes equipment that is not valid on a Plant Loop",
    2655           0 :                                                      this_op_scheme.TypeOf,
    2656           0 :                                                      this_op_scheme.Name));
    2657           0 :                             ShowContinueError(state,
    2658           0 :                                               format("Component {} not allowed as supply equipment on this type of loop.",
    2659           0 :                                                      PlantEquipTypeNames[static_cast<int>(Type)]));
    2660           0 :                             ShowContinueError(state, format("Component name = {}", this_equip.Name));
    2661           0 :                             errFlag2 = true;
    2662             :                         }
    2663             : 
    2664             :                     } // Equipment on List
    2665             :                 }     // List
    2666        1269 :                 if (this_op_scheme.Type == OpScheme::ChillerHeaterSupervisory) {
    2667             :                     // do one time set up for custom chillerheater controls
    2668          10 :                     bool found = false;
    2669          10 :                     for (auto &s : state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes) {
    2670          10 :                         if (s.Name == this_op_scheme.Name) {
    2671          10 :                             this_op_scheme.ChillerHeaterSupervisoryOperation = &s; // assign as pointer
    2672          10 :                             found = true;
    2673          10 :                             break;
    2674             :                         }
    2675             :                     }
    2676          10 :                     if (found) {
    2677          10 :                         this_op_scheme.ChillerHeaterSupervisoryOperation->OneTimeInitChillerHeaterChangeoverOpScheme(state);
    2678             :                     } else {
    2679           0 :                         ShowSevereError(state,
    2680           0 :                                         format("InitLoadDistribution: PlantLoop=\"{}\", Operation Scheme=\"{}\", was not found, check input",
    2681           0 :                                                this_plant_loop.Name,
    2682           0 :                                                this_op_scheme.Name));
    2683           0 :                         ShowFatalError(state, "Program halted because ChillerHeaterSupervisory operation scheme not found.");
    2684             :                     }
    2685             :                 }
    2686             :             } // operation scheme
    2687             :         }     // loop
    2688             : 
    2689             :         // second loop, fill op schemes info at each component.
    2690        1605 :         for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
    2691        1147 :             auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
    2692        2416 :             for (int OpNum = 1, OpNum_end = this_plant_loop.NumOpSchemes; OpNum <= OpNum_end; ++OpNum) {
    2693        1269 :                 auto &this_op_scheme = this_plant_loop.OpScheme(OpNum);
    2694        2686 :                 for (int ListNum = 1, ListNum_end = this_op_scheme.NumEquipLists; ListNum <= ListNum_end; ++ListNum) {
    2695        1417 :                     auto &this_equip_list = this_op_scheme.EquipList(ListNum);
    2696        3050 :                     for (int EquipNum = 1, EquipNum_end = this_equip_list.NumComps; EquipNum <= EquipNum_end; ++EquipNum) {
    2697        1633 :                         auto &this_equip = this_equip_list.Comp(EquipNum);
    2698             :                         // dereference indices (stored in previous loop)
    2699        1633 :                         plantLoc.loopNum = this_equip.LoopNumPtr;
    2700        1633 :                         plantLoc.loopSideNum = this_equip.LoopSideNumPtr;
    2701        1633 :                         plantLoc.branchNum = this_equip.BranchNumPtr;
    2702        1633 :                         plantLoc.compNum = this_equip.CompNumPtr;
    2703        1633 :                         auto &dummy_loop_equip = DataPlant::CompData::getPlantComponent(state, plantLoc);
    2704             : 
    2705        1633 :                         if (dummy_loop_equip.NumOpSchemes == 0) {
    2706             :                             // first op scheme for this component, allocate OpScheme and its EquipList to size 1
    2707        1362 :                             dummy_loop_equip.OpScheme.allocate(1);
    2708        1362 :                             auto &dummy_op_scheme_1(dummy_loop_equip.OpScheme(1));
    2709        1362 :                             dummy_op_scheme_1.EquipList.allocate(1);
    2710        1362 :                             dummy_loop_equip.NumOpSchemes = 1;
    2711        1362 :                             dummy_op_scheme_1.NumEquipLists = 1;
    2712             :                             // store pointers
    2713        1362 :                             dummy_op_scheme_1.OpSchemePtr = OpNum;
    2714        1362 :                             dummy_op_scheme_1.EquipList(1).ListPtr = ListNum;
    2715        1362 :                             dummy_op_scheme_1.EquipList(1).CompPtr = EquipNum;
    2716             :                         } else { // already an op scheme
    2717         271 :                             OldNumOpSchemes = dummy_loop_equip.NumOpSchemes;
    2718             : 
    2719             :                             // could be new list on existing scheme or new scheme with new list.  Check and see
    2720         271 :                             FoundSchemeMatch = false;
    2721         452 :                             for (thisSchemeNum = 1; thisSchemeNum <= OldNumOpSchemes; ++thisSchemeNum) { // Loop index used below
    2722             :                                 // compare the OpScheme index, 'opnum', in the PlantLoop()%OpScheme()data structure
    2723             :                                 // with the OpSchemePtr in the PlantLoop()%LoopSide()%Branch()%Comp() data structure.
    2724         271 :                                 if (OpNum != dummy_loop_equip.OpScheme(thisSchemeNum).OpSchemePtr) continue;
    2725          90 :                                 FoundSchemeMatch = true;
    2726          90 :                                 break;
    2727             :                             }
    2728         271 :                             if (FoundSchemeMatch) { // op scheme already exists, but need to add a list to the existing OpScheme
    2729          90 :                                 auto &this_op_scheme = dummy_loop_equip.OpScheme(thisSchemeNum);
    2730          90 :                                 NewNumEquipLists = this_op_scheme.NumEquipLists + 1;
    2731          90 :                                 this_op_scheme.EquipList.redimension(NewNumEquipLists);
    2732          90 :                                 this_op_scheme.NumEquipLists = NewNumEquipLists;
    2733          90 :                                 this_op_scheme.EquipList(NewNumEquipLists).ListPtr = ListNum;
    2734          90 :                                 this_op_scheme.EquipList(NewNumEquipLists).CompPtr = EquipNum;
    2735             :                             } else { // !FoundSchemeMatch: Add new op scheme and a new list
    2736         181 :                                 NewNumOpSchemes = OldNumOpSchemes + 1;
    2737         181 :                                 dummy_loop_equip.OpScheme.redimension(NewNumOpSchemes);
    2738         181 :                                 auto &new_op_scheme = dummy_loop_equip.OpScheme(NewNumOpSchemes);
    2739         181 :                                 new_op_scheme.EquipList.allocate(1);
    2740         181 :                                 dummy_loop_equip.NumOpSchemes = NewNumOpSchemes;
    2741         181 :                                 new_op_scheme.NumEquipLists = 1;
    2742         181 :                                 new_op_scheme.OpSchemePtr = OpNum;
    2743         181 :                                 new_op_scheme.EquipList(1).ListPtr = ListNum;
    2744         181 :                                 new_op_scheme.EquipList(1).CompPtr = EquipNum;
    2745             :                             }
    2746             :                         }
    2747             : 
    2748             :                     } // Equipment on List
    2749             :                 }     // List
    2750             :             }         // operation scheme
    2751             :         }             // loop
    2752             : 
    2753             :         // check the pointers to see if a single component is attached to more than one type of control scheme
    2754        1605 :         for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
    2755        1147 :             auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
    2756        3441 :             for (DataPlant::LoopSideLocation LoopSideNum : DataPlant::LoopSideKeys) {
    2757        2294 :                 auto const &this_loop_side = this_plant_loop.LoopSide(LoopSideNum);
    2758       15736 :                 for (int BranchNum = 1, BranchNum_end = this_loop_side.TotalBranches; BranchNum <= BranchNum_end; ++BranchNum) {
    2759       13442 :                     auto const &this_branch = this_loop_side.Branch(BranchNum);
    2760       26968 :                     for (int CompNum = 1, CompNum_end = this_branch.TotalComponents; CompNum <= CompNum_end; ++CompNum) {
    2761       13526 :                         auto const &this_component = this_branch.Comp(CompNum);
    2762       13526 :                         if (allocated(this_component.OpScheme)) {
    2763        2921 :                             for (Index = 1; Index <= this_component.NumOpSchemes; ++Index) {
    2764        1543 :                                 OpSchemePtr = this_component.OpScheme(Index).OpSchemePtr;
    2765        1543 :                                 if (OpSchemePtr == 0) {
    2766           0 :                                     ShowSevereError(state,
    2767           0 :                                                     format("InitLoadDistribution: no operation scheme index found for component on PlantLoop={}",
    2768           0 :                                                            this_plant_loop.Name));
    2769           0 :                                     ShowContinueError(state, format("Component name = {}", this_component.Name));
    2770           0 :                                     errFlag2 = true;
    2771             :                                 }
    2772        1543 :                                 DataPlant::OpScheme SchemeType{};
    2773        1543 :                                 if (Index == 1) {
    2774        1362 :                                     SchemeType = this_plant_loop.OpScheme(OpSchemePtr).Type;
    2775             :                                 } else {
    2776         181 :                                     if (SchemeType != this_plant_loop.OpScheme(OpSchemePtr).Type) {
    2777             :                                         // CALL FATAL ERROR 'component may not be specified on two types of operation schemes
    2778             :                                         // Cannot different op schemes be in effect at different times?
    2779             :                                         //  I thought this would be allowed??
    2780             :                                     }
    2781             :                                 }
    2782             :                             }
    2783             :                         }
    2784             :                     }
    2785             :                 }
    2786             :             }
    2787             :         }
    2788             : 
    2789             :         // fill out information on which equipment list is the "last" meaning it has the highest upper limit for load range
    2790        1605 :         for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
    2791        1147 :             auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
    2792        2416 :             for (int OpNum = 1, OpNum_end = this_plant_loop.NumOpSchemes; OpNum <= OpNum_end; ++OpNum) {
    2793        1269 :                 auto &this_op_scheme = this_plant_loop.OpScheme(OpNum);
    2794             :                 // skip non-load based op schemes
    2795        1269 :                 if ((this_op_scheme.Type != OpScheme::HeatingRB) && (this_op_scheme.Type != OpScheme::CoolingRB)) continue;
    2796        1189 :                 HighestRange = 0.0;
    2797        2529 :                 for (int ListNum = 1, ListNum_end = this_op_scheme.NumEquipLists; ListNum <= ListNum_end; ++ListNum) {
    2798        1340 :                     HighestRange = max(HighestRange, this_op_scheme.EquipList(ListNum).RangeUpperLimit);
    2799             :                 } // List
    2800        2529 :                 for (int ListNum = 1, ListNum_end = this_op_scheme.NumEquipLists; ListNum <= ListNum_end; ++ListNum) {
    2801        1340 :                     if (HighestRange == this_op_scheme.EquipList(ListNum).RangeUpperLimit) {
    2802        1189 :                         this_op_scheme.EquipListNumForLastStage = ListNum;
    2803             :                     }
    2804             :                 }
    2805             :             } // operation scheme
    2806             :         }     // loop
    2807             : 
    2808         458 :         state.dataPlantCondLoopOp->InitLoadDistributionOneTimeFlag = false;
    2809             :     }
    2810             : 
    2811    31741579 :     if (state.dataPlnt->AnyEMSPlantOpSchemesInModel) { // Execute any Initialization EMS program calling managers for User-Defined operation.
    2812     1943560 :         for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
    2813     1554848 :             auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
    2814     3109696 :             for (int OpNum = 1, OpNum_end = this_plant_loop.NumOpSchemes; OpNum <= OpNum_end; ++OpNum) {
    2815     1554848 :                 auto &this_op_scheme = this_plant_loop.OpScheme(OpNum);
    2816     1554848 :                 if (this_op_scheme.Type == OpScheme::EMS) {
    2817     1166136 :                     if (state.dataGlobal->BeginEnvrnFlag && this_op_scheme.MyEnvrnFlag) {
    2818          30 :                         if (this_op_scheme.ErlInitProgramMngr > 0) {
    2819             :                             bool anyEMSRan;
    2820           5 :                             ManageEMS(state, EMSManager::EMSCallFrom::UserDefinedComponentModel, anyEMSRan, this_op_scheme.ErlInitProgramMngr);
    2821          25 :                         } else if (this_op_scheme.initPluginLocation > -1) {
    2822           0 :                             state.dataPluginManager->pluginManager->runSingleUserDefinedPlugin(state, this_op_scheme.initPluginLocation);
    2823             :                         }
    2824          30 :                         this_op_scheme.MyEnvrnFlag = false;
    2825             :                     }
    2826     1166136 :                     if (!state.dataGlobal->BeginEnvrnFlag) this_op_scheme.MyEnvrnFlag = true;
    2827             :                 }
    2828             :             } // operation scheme
    2829             :         }     // loop
    2830             :     }
    2831             : 
    2832             :     // FIRST HVAC INITS
    2833    31741579 :     if (FirstHVACIteration) {
    2834    62901638 :         for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
    2835    47555535 :             auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
    2836   142666605 :             for (DataPlant::LoopSideLocation LoopSideNum : LoopSideKeys) {
    2837    95111070 :                 auto &this_loop_side = this_plant_loop.LoopSide(LoopSideNum);
    2838   675251648 :                 for (int BranchNum = 1, BranchNum_end = this_loop_side.TotalBranches; BranchNum <= BranchNum_end; ++BranchNum) {
    2839   580140578 :                     auto &this_branch = this_loop_side.Branch(BranchNum);
    2840  1163896283 :                     for (int CompNum = 1, CompNum_end = this_branch.TotalComponents; CompNum <= CompNum_end; ++CompNum) {
    2841   583755705 :                         auto &this_component = this_branch.Comp(CompNum);
    2842             :                         // initalize components 'ON-AVAILABLE-NO LOAD-NO EMS CTRL'
    2843   583755705 :                         this_component.ON = true;
    2844   583755705 :                         this_component.Available = true;
    2845   583755705 :                         this_component.MyLoad = 0.0;
    2846   583755705 :                         this_component.EMSLoadOverrideOn = false;
    2847             :                         // Zero out the old curOpSchemePtr so that we don't get 'carry-over' when we update schedules
    2848   583755705 :                         if (this_component.CurOpSchemeType != OpScheme::Demand && this_component.CurOpSchemeType != OpScheme::Pump &&
    2849   298206723 :                             this_component.CurOpSchemeType != OpScheme::WSEcon && this_component.CurOpSchemeType != OpScheme::NoControl) {
    2850    57414960 :                             this_component.CurOpSchemeType = OpScheme::NoControl;
    2851             :                         }
    2852   583755705 :                         this_component.CurCompLevelOpNum = 0;
    2853             :                     }
    2854             :                 }
    2855             :             }
    2856             :         }
    2857             :         // set sim flag so each supervisor is only simulated once in the plant loop below
    2858    15449755 :         for (DataPlant::ChillerHeaterSupervisoryOperationData &supervisor : state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes) {
    2859      103652 :             supervisor.needsSimulation = true;
    2860             :         }
    2861             :         // Update the OpScheme schedules
    2862    62901638 :         for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
    2863    47555535 :             FoundScheme = false;
    2864    47555535 :             auto &this_loop = state.dataPlnt->PlantLoop(LoopNum);
    2865   100691478 :             for (int OpNum = 1; OpNum <= this_loop.NumOpSchemes; ++OpNum) {
    2866    53135943 :                 auto &this_op_scheme = this_loop.OpScheme(OpNum);
    2867             : 
    2868    53135943 :                 if (this_op_scheme.Type == OpScheme::ChillerHeaterSupervisory) {
    2869      326552 :                     if (this_op_scheme.ChillerHeaterSupervisoryOperation != nullptr &&
    2870      326552 :                         this_op_scheme.ChillerHeaterSupervisoryOperation->needsSimulation) {
    2871      103652 :                         this_op_scheme.ChillerHeaterSupervisoryOperation->EvaluateChillerHeaterChangeoverOpScheme(state);
    2872      103652 :                         this_op_scheme.ChillerHeaterSupervisoryOperation->needsSimulation = false;
    2873             :                     }
    2874      326552 :                     continue;
    2875             :                 }
    2876             : 
    2877    52809391 :                 if (GetCurrentScheduleValue(state, this_op_scheme.SchedPtr) > 0.0) {
    2878    47261177 :                     this_op_scheme.Available = true;
    2879    47261177 :                     FoundScheme = true;
    2880    98408674 :                     for (int ListNum = 1, ListNum_end = this_op_scheme.NumEquipLists; ListNum <= ListNum_end; ++ListNum) {
    2881    51147497 :                         auto &this_equip_list = this_op_scheme.EquipList(ListNum);
    2882             :                         // The component loop loads the pointers from the OpScheme data structure
    2883             :                         // If the component happens to be active in more than schedule, the *LAST*
    2884             :                         // schedule found will be activated
    2885   110454635 :                         for (int CompNum = 1; CompNum <= this_equip_list.NumComps; ++CompNum) {
    2886             : 
    2887             :                             // set up a reference to the component instance on the list data structure
    2888    59307138 :                             auto const &this_list_component = this_equip_list.Comp(CompNum);
    2889             : 
    2890             :                             // then look up the component topological position from this structure
    2891    59307138 :                             LoopPtr = this_list_component.LoopNumPtr;
    2892    59307138 :                             LoopSidePtr = this_list_component.LoopSideNumPtr;
    2893    59307138 :                             BranchPtr = this_list_component.BranchNumPtr;
    2894    59307138 :                             CompPtr = this_list_component.CompNumPtr;
    2895             : 
    2896             :                             // then set up a reference to the component on the plant data structure
    2897    59307138 :                             auto &this_loop_component = state.dataPlnt->PlantLoop(LoopPtr).LoopSide(LoopSidePtr).Branch(BranchPtr).Comp(CompPtr);
    2898             : 
    2899    59307138 :                             if (this_loop_component.CurOpSchemeType != OpScheme::Pump) {
    2900    59307138 :                                 this_loop_component.CurOpSchemeType = this_op_scheme.Type;
    2901             :                             } else {
    2902           0 :                                 ShowSevereError(state,
    2903             :                                                 "Invalid [pump] component found on equipment list.  Pumps are not allowed on equipment lists.");
    2904           0 :                                 ShowContinueError(state, format("Problem component name = {}", this_op_scheme.EquipList(ListNum).Comp(CompNum).Name));
    2905           0 :                                 ShowContinueError(state, "Remove pump component and place other plant equipment on the list to correct.");
    2906           0 :                                 errFlag2 = true;
    2907             :                             }
    2908             : 
    2909   127609820 :                             for (CompOpNum = 1; CompOpNum <= this_loop_component.NumOpSchemes; ++CompOpNum) {
    2910    68302682 :                                 if (this_loop_component.OpScheme(CompOpNum).OpSchemePtr == OpNum) {
    2911    59307138 :                                     this_loop_component.CurCompLevelOpNum = CompOpNum;
    2912             :                                 }
    2913             :                             }
    2914             :                         }
    2915             :                     }
    2916             :                 } else {
    2917     5548214 :                     this_op_scheme.Available = false;
    2918             :                 }
    2919             :             }
    2920             :             //    IF(.NOT. foundscheme)THEN
    2921             :             //      !'call warning 'no current control scheme specified.  Loop Equipment will be shut down'
    2922             :             //    ENDIF
    2923             :         }
    2924             :     } else { // call supervisory scheme every iteration
    2925    16395476 :         if (!state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes.empty()) {
    2926             :             // set sim flag so each supervisor is only simulated once in the plant loop below
    2927      453386 :             for (DataPlant::ChillerHeaterSupervisoryOperationData &supervisor : state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes) {
    2928      226693 :                 supervisor.needsSimulation = true;
    2929             :             }
    2930     1231306 :             for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
    2931     1004613 :                 auto &this_loop = state.dataPlnt->PlantLoop(LoopNum);
    2932     2009226 :                 for (int OpNum = 1; OpNum <= this_loop.NumOpSchemes; ++OpNum) {
    2933     1004613 :                     auto &this_op_scheme = this_loop.OpScheme(OpNum);
    2934     1004613 :                     if (this_op_scheme.Type == OpScheme::ChillerHeaterSupervisory) {
    2935      649068 :                         if (this_op_scheme.ChillerHeaterSupervisoryOperation != nullptr &&
    2936      649068 :                             this_op_scheme.ChillerHeaterSupervisoryOperation->needsSimulation) {
    2937      226693 :                             this_op_scheme.ChillerHeaterSupervisoryOperation->EvaluateChillerHeaterChangeoverOpScheme(state);
    2938      226693 :                             this_op_scheme.ChillerHeaterSupervisoryOperation->needsSimulation = false;
    2939             :                         }
    2940      649068 :                         continue;
    2941             :                     }
    2942             :                 }
    2943             :             }
    2944             :         }
    2945             :     }
    2946             : 
    2947    31741579 :     if (errFlag2) {
    2948           0 :         ShowFatalError(state, "InitLoadDistribution: Fatal error caused by previous severe error(s).");
    2949             :     }
    2950             : }
    2951             : 
    2952             : // End Initialization Section of the Plant Loop Module
    2953             : //******************************************************************************
    2954             : 
    2955             : // Begin Load Calculation/Distribution Section of the Plant Loop Module
    2956             : //******************************************************************************
    2957             : 
    2958    17696593 : void DistributePlantLoad(EnergyPlusData &state,
    2959             :                          int const LoopNum,
    2960             :                          const LoopSideLocation LoopSideNum,
    2961             :                          int const CurSchemePtr, // use as index in PlantLoop()OpScheme() data structure
    2962             :                          int const ListPtr,      // use as index in PlantLoop()OpScheme() data structure
    2963             :                          Real64 const LoopDemand,
    2964             :                          Real64 &RemLoopDemand)
    2965             : {
    2966             : 
    2967             :     // SUBROUTINE INFORMATION:
    2968             :     //       AUTHOR         Dan Fisher
    2969             :     //       DATE WRITTEN   July 1998
    2970             :     //       MODIFIED       na
    2971             :     //       RE-ENGINEERED  July 2010
    2972             :     //                      Sept 2010 B. Griffith, retain actual sign of load values
    2973             :     //                        July 2014 M. Mitchell, added SequentialUniformPLR and UniformPLR schemes
    2974             : 
    2975             :     // PURPOSE OF THIS SUBROUTINE: This subroutine distributes the load
    2976             :     // to plant equipment according to one of two distribution schemes:
    2977             :     //     OPTIMAL    = 1
    2978             :     //     SEQUENTIALLOAD = 2
    2979             :     //     UNIFORMLOAD  = 3
    2980             :     //     UNIFORMPLR = 4
    2981             :     //     SEQUENTIALUNIFORMPLR = 5
    2982             :     // METHODOLOGY EMPLOYED:
    2983             :     // na
    2984             :     // REFERENCES:
    2985             :     // na
    2986             :     // Using/Aliasing
    2987             :     using namespace DataLoopNode;
    2988             : 
    2989             :     // Locals
    2990             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    2991             : 
    2992             :     // SUBROUTINE PARAMETER DEFINITIONS:
    2993             :     // na
    2994             :     // INTERFACE BLOCK SPECIFICATIONS
    2995             :     // na
    2996             :     // DERIVED TYPE DEFINITIONS
    2997             :     // na
    2998             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2999             :     Real64 ChangeInLoad;
    3000             :     Real64 DivideLoad;
    3001             :     Real64 UniformLoad;
    3002             :     Real64 NewLoad;
    3003             :     Real64 PlantCapacity;
    3004             :     Real64 MinCompPLR;
    3005             :     Real64 LargestMinCompPLR;
    3006             :     Real64 PlantPLR;
    3007             :     Real64 CompLoad;
    3008             : 
    3009             :     int BranchNum;
    3010             :     int CompNum;
    3011             :     int CompIndex;
    3012             :     int NumCompsOnList;
    3013             : 
    3014             :     // start with some references
    3015    17696593 :     auto &this_loop = state.dataPlnt->PlantLoop(LoopNum);
    3016    17696593 :     auto &this_loopside = this_loop.LoopSide(LoopSideNum);
    3017    17696593 :     auto &this_equiplist = this_loop.OpScheme(CurSchemePtr).EquipList(ListPtr);
    3018             : 
    3019             :     struct LoadPLRPoint
    3020             :     {
    3021             :         Real64 plant_capacity_to_this_point;
    3022             :         Real64 largest_min_plr_to_this_point;
    3023           0 :         LoadPLRPoint(Real64 capacity, Real64 plr) : plant_capacity_to_this_point(capacity), largest_min_plr_to_this_point(plr)
    3024             :         {
    3025           0 :         }
    3026             :     };
    3027    17696593 :     std::vector<LoadPLRPoint> accrued_load_plr_values;
    3028             : 
    3029             :     // load local variables
    3030    17696593 :     NumCompsOnList = this_equiplist.NumComps;
    3031    17696593 :     int numAvail = 0;
    3032             : 
    3033             :     // Allocate array once
    3034    17696593 :     accrued_load_plr_values.reserve(NumCompsOnList);
    3035    17696593 :     RemLoopDemand = LoopDemand;
    3036    17696593 :     if (NumCompsOnList <= 0) return;
    3037             : 
    3038    17696593 :     if (std::abs(RemLoopDemand) < SmallLoad) {
    3039             :         // no load to distribute
    3040             :     } else {
    3041             : 
    3042             :         // OPTIMAL DISTRIBUTION SCHEME
    3043    17582025 :         switch (this_loop.LoadDistribution) {
    3044     9570883 :         case DataPlant::LoadingScheme::Optimal:
    3045             :             // step 1: load all machines to optimal PLR
    3046     9570883 :             numAvail = 0;
    3047    19665714 :             for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3048             : 
    3049             :                 // look up topology from the equipment list
    3050    10094831 :                 BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3051    10094831 :                 CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3052             : 
    3053             :                 // create a reference to the component itself
    3054    10094831 :                 auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3055             : 
    3056    10094831 :                 if (!this_component.Available) continue;
    3057    10094828 :                 ++numAvail;
    3058             : 
    3059    10094828 :                 if (this_component.OptLoad > 0.0) {
    3060    10001624 :                     ChangeInLoad = min(this_component.OptLoad, std::abs(RemLoopDemand));
    3061             :                 } else {
    3062             :                     // this is for some components like cooling towers don't have well defined OptLoad
    3063       93204 :                     ChangeInLoad = std::abs(RemLoopDemand);
    3064             :                 }
    3065             : 
    3066    10094828 :                 AdjustChangeInLoadForLastStageUpperRangeLimit(state, LoopNum, CurSchemePtr, ListPtr, ChangeInLoad);
    3067             : 
    3068    10094828 :                 AdjustChangeInLoadByEMSControls(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
    3069             : 
    3070    10094828 :                 AdjustChangeInLoadByHowServed(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
    3071             : 
    3072    10094828 :                 ChangeInLoad = max(0.0, ChangeInLoad);
    3073    10094828 :                 this_component.MyLoad = sign(ChangeInLoad, RemLoopDemand);
    3074             : 
    3075    10094828 :                 RemLoopDemand -= this_component.MyLoad;
    3076    10094828 :                 if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0; // CR8631 don't just exit or %MyLoad on second device isn't reset
    3077             :             }
    3078             : 
    3079             :             // step 2: Evenly distribute remaining loop demand
    3080     9570883 :             if (numAvail > 0 && std::abs(RemLoopDemand) > SmallLoad) {
    3081      523275 :                 DivideLoad = std::abs(RemLoopDemand) / numAvail;
    3082     1083226 :                 for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3083             : 
    3084      559951 :                     BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3085      559951 :                     CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3086             : 
    3087             :                     // create a reference to the component itself
    3088      559951 :                     auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3089             : 
    3090      559951 :                     if (!this_component.Available) continue;
    3091             : 
    3092      559950 :                     NewLoad = this_component.MyLoad;
    3093      559950 :                     NewLoad = min(this_component.MaxLoad, std::abs(NewLoad) + DivideLoad);
    3094      559950 :                     ChangeInLoad = NewLoad - std::abs(this_component.MyLoad);
    3095      559950 :                     this_component.MyLoad = sign(NewLoad, RemLoopDemand);
    3096      559950 :                     RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
    3097      559950 :                     if (std::abs(RemLoopDemand) < SmallLoad)
    3098      178978 :                         RemLoopDemand = 0.0; // CR8631 don't just exit or %MyLoad on second device isn't
    3099             :                                              // reset
    3100             :                 }
    3101             :             }
    3102             : 
    3103             :             // step 3: If RemLoopDemand is still greater than zero, look for any machine
    3104     9570883 :             if (numAvail > 0 && std::abs(RemLoopDemand) > SmallLoad) {
    3105      722464 :                 for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3106             : 
    3107      378167 :                     BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3108      378167 :                     CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3109             : 
    3110             :                     // create a reference to the component itself
    3111      378167 :                     auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3112             : 
    3113      378167 :                     if (!this_component.Available) continue;
    3114      378166 :                     DivideLoad = this_component.MaxLoad - std::abs(this_component.MyLoad);
    3115      378166 :                     ChangeInLoad = min(std::abs(RemLoopDemand), DivideLoad);
    3116      378166 :                     this_component.MyLoad += sign(ChangeInLoad, RemLoopDemand);
    3117      378166 :                     RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
    3118      378166 :                     if (std::abs(RemLoopDemand) < SmallLoad)
    3119        4229 :                         RemLoopDemand = 0.0; // CR8631 don't just exit or %MyLoad on second device isn't
    3120             :                                              // reset
    3121             :                 }
    3122             :             }
    3123             : 
    3124     9570883 :             break;
    3125             : 
    3126             :         // SEQUENTIALLOAD DISTRIBUTION SCHEME
    3127     7432098 :         case DataPlant::LoadingScheme::Sequential:
    3128             : 
    3129             :             // step 1: Load machines in list order
    3130    15206562 :             for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3131             : 
    3132     7774464 :                 BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3133     7774464 :                 CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3134             : 
    3135             :                 // create a reference to the component itself
    3136     7774464 :                 auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3137             : 
    3138     7774464 :                 if (!this_component.Available) continue;
    3139             : 
    3140     7774464 :                 if (this_component.MaxLoad > 0.0) { // apply known limit
    3141     7741984 :                     ChangeInLoad = min(this_component.MaxLoad, std::abs(RemLoopDemand));
    3142             :                 } else {
    3143             :                     // this is for some components like cooling towers don't have well defined MaxLoad
    3144       32480 :                     ChangeInLoad = std::abs(RemLoopDemand);
    3145             :                 }
    3146             : 
    3147     7774464 :                 AdjustChangeInLoadForLastStageUpperRangeLimit(state, LoopNum, CurSchemePtr, ListPtr, ChangeInLoad);
    3148             : 
    3149     7774464 :                 AdjustChangeInLoadByEMSControls(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
    3150             : 
    3151     7774464 :                 AdjustChangeInLoadByHowServed(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
    3152             : 
    3153     7774464 :                 ChangeInLoad = max(0.0, ChangeInLoad);
    3154     7774464 :                 this_component.MyLoad = sign(ChangeInLoad, RemLoopDemand);
    3155     7774464 :                 RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
    3156     7774464 :                 if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0; // CR8631 don't just exit or %MyLoad on second device isn't reset
    3157             :             }
    3158             : 
    3159     7432098 :             break;
    3160             : 
    3161             :         // UNIFORMLOAD DISTRIBUTION SCHEME
    3162      579044 :         case DataPlant::LoadingScheme::Uniform:
    3163             : 
    3164             :             // step 1: distribute load equally to all available machines
    3165      579044 :             numAvail = 0;
    3166     1651498 :             for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3167             : 
    3168     1072454 :                 BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3169     1072454 :                 CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3170             : 
    3171             :                 // create a reference to the component itself
    3172     1072454 :                 auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3173             : 
    3174     1072454 :                 if (this_component.Available) ++numAvail;
    3175             :             }
    3176      579044 :             if (numAvail > 0) {
    3177      579042 :                 UniformLoad = std::abs(RemLoopDemand) / numAvail;
    3178             :             } else {
    3179           2 :                 UniformLoad = 0.0;
    3180             :             }
    3181     1651498 :             for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3182             : 
    3183     1072454 :                 BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3184     1072454 :                 CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3185             : 
    3186             :                 // create a reference to the component itself
    3187     1072454 :                 auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3188             : 
    3189     1072454 :                 if (!this_component.Available) continue;
    3190     1072450 :                 if (this_component.MaxLoad > 0.0) {
    3191     1072450 :                     ChangeInLoad = min(this_component.MaxLoad, UniformLoad);
    3192             :                 } else {
    3193             :                     // this is for some components like cooling towers don't have well defined MaxLoad
    3194           0 :                     ChangeInLoad = std::abs(RemLoopDemand);
    3195             :                 }
    3196             : 
    3197     1072450 :                 AdjustChangeInLoadForLastStageUpperRangeLimit(state, LoopNum, CurSchemePtr, ListPtr, ChangeInLoad);
    3198             : 
    3199     1072450 :                 AdjustChangeInLoadByEMSControls(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
    3200             : 
    3201     1072450 :                 AdjustChangeInLoadByHowServed(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
    3202     1072450 :                 ChangeInLoad = max(0.0, ChangeInLoad);
    3203     1072450 :                 this_component.MyLoad = sign(ChangeInLoad, RemLoopDemand);
    3204     1072450 :                 RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
    3205     1072450 :                 if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0;
    3206             :             }
    3207             : 
    3208             :             // step 2: If RemLoopDemand is not zero, then distribute remainder sequentially.
    3209      579044 :             if (std::abs(RemLoopDemand) > SmallLoad) {
    3210      345799 :                 for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3211             : 
    3212      217520 :                     BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3213      217520 :                     CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3214             : 
    3215             :                     // create a reference to the component itself
    3216      217520 :                     auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3217             : 
    3218      217520 :                     if (!this_component.Available) continue;
    3219      217516 :                     ChangeInLoad = min(this_component.MaxLoad - std::abs(this_component.MyLoad), std::abs(RemLoopDemand));
    3220      217516 :                     ChangeInLoad = max(0.0, ChangeInLoad);
    3221      217516 :                     this_component.MyLoad += sign(ChangeInLoad, RemLoopDemand);
    3222      217516 :                     RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
    3223      217516 :                     if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0;
    3224             :                 }
    3225             :             }
    3226             : 
    3227      579044 :             break;
    3228             : 
    3229             :         // UNIFORMPLR LOAD DISTRIBUTION SCHEME
    3230           0 :         case DataPlant::LoadingScheme::UniformPLR:
    3231             :             // Get total plant capacity and remove last component from list if load is less
    3232             :             // than plant capacity at min PLR
    3233           0 :             PlantCapacity = 0.0;
    3234           0 :             PlantPLR = 0.0;
    3235           0 :             MinCompPLR = 0.0;
    3236           0 :             LargestMinCompPLR = 0.0;
    3237             : 
    3238             :             // Determine PlantCapacity and LargestMinCompPLR
    3239           0 :             for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3240             : 
    3241           0 :                 BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3242           0 :                 CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3243             : 
    3244             :                 // create a reference to the component itself
    3245           0 :                 auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3246             : 
    3247           0 :                 if (!this_component.Available) continue;
    3248             : 
    3249           0 :                 PlantCapacity += this_component.MaxLoad;
    3250             : 
    3251           0 :                 if (this_component.MaxLoad < SmallLoad) {
    3252           0 :                     ShowWarningMessage(state,
    3253           0 :                                        format("Plant component {} has zero available capacity. Check component controls.", this_component.Name));
    3254           0 :                     MinCompPLR = 0.0;
    3255             :                 } else {
    3256           0 :                     MinCompPLR = this_component.MinLoad / this_component.MaxLoad;
    3257             :                 }
    3258             : 
    3259             :                 // Set LargestMinCompPLR to largest MinCompPLR
    3260           0 :                 LargestMinCompPLR = max(LargestMinCompPLR, MinCompPLR);
    3261             : 
    3262             :                 // Update the array
    3263           0 :                 accrued_load_plr_values.push_back(LoadPLRPoint(PlantCapacity, LargestMinCompPLR));
    3264             :             }
    3265             : 
    3266             :             // work backwards from full capacity down to 1 unit on
    3267           0 :             for (int i = accrued_load_plr_values.size() - 1; i >= 0; --i) {
    3268             : 
    3269             :                 // if i == 0 then we need to take that as the resulting value
    3270           0 :                 if (i == 0) {
    3271           0 :                     PlantCapacity = accrued_load_plr_values[i].plant_capacity_to_this_point;
    3272           0 :                     LargestMinCompPLR = accrued_load_plr_values[i].largest_min_plr_to_this_point;
    3273           0 :                     break;
    3274             : 
    3275             :                     // if the capacity is greater than the demand, just store the latest values and continue
    3276           0 :                 } else if (std::abs(RemLoopDemand) <
    3277           0 :                            (accrued_load_plr_values[i].largest_min_plr_to_this_point * accrued_load_plr_values[i].plant_capacity_to_this_point)) {
    3278           0 :                     PlantCapacity = accrued_load_plr_values[i].plant_capacity_to_this_point;
    3279           0 :                     LargestMinCompPLR = accrued_load_plr_values[i].largest_min_plr_to_this_point;
    3280           0 :                     continue;
    3281             : 
    3282             :                     // if the capacity is less than the demand, accept the last values from the previous iteration and exit
    3283             :                 } else {
    3284           0 :                     break;
    3285             :                 }
    3286             :             }
    3287             : 
    3288             :             // Determine PLR for uniform PLR loading of all equipment
    3289           0 :             if (PlantCapacity > 0.0) {
    3290           0 :                 PlantPLR = min(1.0, std::abs(RemLoopDemand) / PlantCapacity);
    3291             :             } else {
    3292           0 :                 ShowWarningError(state, format("Zero available plant capacity for Plant Loop = {}", state.dataPlnt->PlantLoop(LoopNum).Name));
    3293             :             }
    3294             : 
    3295             :             // Distribute load to each machine
    3296           0 :             for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3297             : 
    3298           0 :                 CompLoad = 0.0;
    3299             : 
    3300           0 :                 BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3301           0 :                 CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3302             : 
    3303             :                 // create a reference to the component itself
    3304           0 :                 auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3305             : 
    3306           0 :                 if (!this_component.Available) continue;
    3307             : 
    3308           0 :                 CompLoad = PlantPLR * this_component.MaxLoad;
    3309             : 
    3310           0 :                 if (this_component.MaxLoad > 0.0) {
    3311           0 :                     ChangeInLoad = min(std::abs(RemLoopDemand), CompLoad);
    3312             :                 } else {
    3313             :                     // this is for some components like cooling towers don't have well defined MaxLoad
    3314           0 :                     ChangeInLoad = std::abs(RemLoopDemand);
    3315             :                 }
    3316             : 
    3317           0 :                 AdjustChangeInLoadForLastStageUpperRangeLimit(state, LoopNum, CurSchemePtr, ListPtr, ChangeInLoad);
    3318             : 
    3319           0 :                 AdjustChangeInLoadByEMSControls(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
    3320             : 
    3321           0 :                 AdjustChangeInLoadByHowServed(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
    3322             : 
    3323           0 :                 ChangeInLoad = max(0.0, ChangeInLoad);
    3324             : 
    3325           0 :                 this_component.MyLoad = sign(ChangeInLoad, RemLoopDemand);
    3326             : 
    3327           0 :                 RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
    3328             : 
    3329           0 :                 if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0;
    3330             :             }
    3331             : 
    3332           0 :             break;
    3333             : 
    3334             :         // SEQUENTIALUNIFORMPLR LOAD DISTRIBUTION SCHEME
    3335           0 :         case DataPlant::LoadingScheme::SequentialUniformPLR:
    3336             : 
    3337           0 :             PlantCapacity = 0.0;
    3338           0 :             PlantPLR = 0.0;
    3339           0 :             MinCompPLR = 0.0;
    3340           0 :             LargestMinCompPLR = 0.0;
    3341             : 
    3342             :             // Determine PlantCapacity and LargestMinCompPLR
    3343           0 :             for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3344             : 
    3345           0 :                 BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3346           0 :                 CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3347             : 
    3348             :                 // create a reference to the component itself
    3349           0 :                 auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3350             : 
    3351           0 :                 if (!this_component.Available) continue;
    3352             : 
    3353           0 :                 PlantCapacity += this_component.MaxLoad;
    3354             : 
    3355           0 :                 if (this_component.MaxLoad < SmallLoad) {
    3356           0 :                     ShowWarningMessage(state,
    3357           0 :                                        format("Plant component {} has zero available capacity. Check component controls.", this_component.Name));
    3358           0 :                     MinCompPLR = 0.0;
    3359             :                 } else {
    3360           0 :                     MinCompPLR = this_component.MinLoad / this_component.MaxLoad;
    3361             :                 }
    3362             : 
    3363             :                 // Set LargestMinCompPLR to largest MinCompPLR
    3364           0 :                 if (MinCompPLR > LargestMinCompPLR) LargestMinCompPLR = MinCompPLR;
    3365             : 
    3366           0 :                 if (std::abs(RemLoopDemand) <= PlantCapacity) {
    3367           0 :                     break;
    3368             :                 }
    3369             :             }
    3370             : 
    3371             :             // Determine PLR for uniform PLR loading of all equipment
    3372           0 :             if (PlantCapacity > 0.0) {
    3373           0 :                 PlantPLR = min(1.0, std::abs(RemLoopDemand) / PlantCapacity);
    3374             :             } else {
    3375           0 :                 ShowWarningError(state, format("Zero available plant capacity for Plant Loop = {}", state.dataPlnt->PlantLoop(LoopNum).Name));
    3376             :             }
    3377             : 
    3378             :             // Distribute load to each machine
    3379           0 :             for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3380             : 
    3381           0 :                 CompLoad = 0.0;
    3382             : 
    3383           0 :                 BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3384           0 :                 CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3385             : 
    3386             :                 // create a reference to the component itself
    3387           0 :                 auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3388             : 
    3389           0 :                 if (!this_component.Available) continue;
    3390             : 
    3391           0 :                 CompLoad = PlantPLR * this_component.MaxLoad;
    3392             : 
    3393           0 :                 if (this_component.MaxLoad > 0.0) {
    3394           0 :                     ChangeInLoad = min(std::abs(RemLoopDemand), CompLoad);
    3395             :                 } else {
    3396             :                     // this is for some components like cooling towers don't have well defined MaxLoad
    3397           0 :                     ChangeInLoad = std::abs(RemLoopDemand);
    3398             :                 }
    3399             : 
    3400           0 :                 AdjustChangeInLoadForLastStageUpperRangeLimit(state, LoopNum, CurSchemePtr, ListPtr, ChangeInLoad);
    3401             : 
    3402           0 :                 AdjustChangeInLoadByEMSControls(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
    3403             : 
    3404           0 :                 AdjustChangeInLoadByHowServed(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
    3405             : 
    3406           0 :                 ChangeInLoad = max(0.0, ChangeInLoad);
    3407             : 
    3408           0 :                 this_component.MyLoad = sign(ChangeInLoad, RemLoopDemand);
    3409             : 
    3410           0 :                 RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
    3411             : 
    3412           0 :                 if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0;
    3413             :             }
    3414           0 :             break;
    3415           0 :         default:
    3416           0 :             assert(false);
    3417             :         }
    3418             : 
    3419             :     } // load is small check
    3420             : 
    3421             :     // now update On flags according to result for MyLoad
    3422    36861878 :     for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
    3423             : 
    3424    19165285 :         BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
    3425    19165285 :         CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
    3426             : 
    3427             :         // create a reference to the component itself
    3428    19165285 :         auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
    3429             : 
    3430    19165285 :         if (std::abs(this_component.MyLoad) < SmallLoad) {
    3431      876212 :             this_component.ON = false;
    3432             :         } else {
    3433    18289073 :             this_component.ON = true;
    3434             :         }
    3435             :     }
    3436    17696593 : }
    3437             : 
    3438    18941742 : void AdjustChangeInLoadForLastStageUpperRangeLimit(EnergyPlusData &state,
    3439             :                                                    int const LoopNum,         // component topology
    3440             :                                                    int const CurOpSchemePtr,  // current active operation scheme
    3441             :                                                    int const CurEquipListPtr, // current equipment list
    3442             :                                                    Real64 &ChangeInLoad       // positive magnitude of load change
    3443             : )
    3444             : {
    3445             : 
    3446             :     // SUBROUTINE INFORMATION:
    3447             :     //       AUTHOR         B. Griffith
    3448             :     //       DATE WRITTEN   May 2012
    3449             :     //       MODIFIED       na
    3450             :     //       RE-ENGINEERED  na
    3451             : 
    3452             :     // PURPOSE OF THIS SUBROUTINE:
    3453             :     // if this is the last stage for a load based operation, then limit load to upper range
    3454             : 
    3455             :     // METHODOLOGY EMPLOYED:
    3456             :     // <description>
    3457             : 
    3458             :     // REFERENCES:
    3459             :     // na
    3460             : 
    3461             :     // USE STATEMENTS:
    3462             :     // na
    3463             : 
    3464             :     // Locals
    3465             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    3466             : 
    3467             :     // SUBROUTINE PARAMETER DEFINITIONS:
    3468             :     // na
    3469             : 
    3470             :     // INTERFACE BLOCK SPECIFICATIONS:
    3471             :     // na
    3472             : 
    3473             :     // DERIVED TYPE DEFINITIONS:
    3474             :     // na
    3475             : 
    3476             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3477             :     Real64 RangeHiLimit;
    3478             : 
    3479    18941742 :     if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(CurOpSchemePtr).EquipListNumForLastStage == CurEquipListPtr) { // at final last stage
    3480             : 
    3481    18359198 :         RangeHiLimit = state.dataPlnt->PlantLoop(LoopNum).OpScheme(CurOpSchemePtr).EquipList(CurEquipListPtr).RangeUpperLimit;
    3482    18359198 :         ChangeInLoad = min(ChangeInLoad, RangeHiLimit);
    3483             :     }
    3484    18941742 : }
    3485             : 
    3486    18941742 : void AdjustChangeInLoadByHowServed(EnergyPlusData &state,
    3487             :                                    PlantLocation const &plantLoc, // component topology
    3488             :                                    Real64 &ChangeInLoad           // positive magnitude of load change
    3489             : )
    3490             : {
    3491             : 
    3492             :     // SUBROUTINE INFORMATION:
    3493             :     //       AUTHOR         B. Griffith
    3494             :     //       DATE WRITTEN   Nov 2011
    3495             :     //       MODIFIED       March 2012, B. Griffith add controls for free cooling heat exchanger overrides of chillers
    3496             :     //       RE-ENGINEERED  na
    3497             : 
    3498             :     // PURPOSE OF THIS SUBROUTINE:
    3499             :     // central place to apply limits to machine load dispatch based on how the machine serves loads
    3500             : 
    3501             :     // METHODOLOGY EMPLOYED:
    3502             :     // Components are machines on plant equipment operation lists.  Need to make adjustments to the
    3503             :     // load dispatch to account for limits and floating capacities.
    3504             : 
    3505             :     // SUBROUTINE PARAMETER DEFINITIONS:
    3506             :     static constexpr std::string_view RoutineName("PlantCondLoopOperation:DistributePlantLoad");
    3507             : 
    3508             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3509    18941742 :     Real64 CurMassFlowRate(0.0);
    3510    18941742 :     Real64 ToutLowLimit(0.0);
    3511    18941742 :     Real64 ToutHiLimit(0.0);
    3512    18941742 :     Real64 TinLowLimit(0.0);
    3513    18941742 :     Real64 Tinlet(0.0);
    3514    18941742 :     Real64 Tsensor(0.0);
    3515    18941742 :     Real64 CurSpecHeat(0.0);
    3516    18941742 :     Real64 QdotTmp(0.0);
    3517    18941742 :     int ControlNodeNum(0);
    3518             : 
    3519    18941742 :     auto &this_component = CompData::getPlantComponent(state, plantLoc);
    3520             : 
    3521             :     // start of bad band-aid, need a general and comprehensive approach for determining current capacity of all kinds of equipment
    3522             :     // Need to truncate the load down in case outlet temperature will hit a lower/upper limit
    3523             : 
    3524    18941742 :     switch (this_component.HowLoadServed) {
    3525             : 
    3526             :     // Chillers
    3527     4867016 :     case DataPlant::HowMet::ByNominalCapLowOutLimit: { // chillers with lower limit on outlet temperature
    3528             : 
    3529             :         //- Retrieve data from the plant loop data structure
    3530     4867016 :         CurMassFlowRate = state.dataLoopNodes->Node(this_component.NodeNumIn).MassFlowRate;
    3531     4867016 :         ToutLowLimit = this_component.MinOutletTemp;
    3532     4867016 :         Tinlet = state.dataLoopNodes->Node(this_component.NodeNumIn).Temp;
    3533     4867016 :         CurSpecHeat = GetSpecificHeatGlycol(state,
    3534     4867016 :                                             state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidName,
    3535             :                                             Tinlet,
    3536     4867016 :                                             state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidIndex,
    3537             :                                             RoutineName);
    3538     4867016 :         QdotTmp = CurMassFlowRate * CurSpecHeat * (Tinlet - ToutLowLimit);
    3539             : 
    3540             :         //        !- Don't correct if Q is zero, as this could indicate a component which this hasn't been implemented or not yet turned on
    3541     4867016 :         if (CurMassFlowRate > 0.0) {
    3542     4769342 :             ChangeInLoad = min(ChangeInLoad, QdotTmp);
    3543             :         }
    3544             : 
    3545     4867016 :         break;
    3546             :     }
    3547       45881 :     case DataPlant::HowMet::ByNominalCapFreeCoolCntrl: {
    3548             :         // for chillers with free cooling shutdown (HeatExchanger:Hydronic currently)
    3549             :         // determine if free cooling controls shut off chiller
    3550       45881 :         TinLowLimit = this_component.FreeCoolCntrlMinCntrlTemp;
    3551       45881 :         switch (this_component.FreeCoolCntrlMode) {
    3552           0 :         case DataPlant::FreeCoolControlMode::WetBulb: {
    3553           0 :             Tsensor = state.dataEnvrn->OutWetBulbTemp;
    3554           0 :             break;
    3555             :         }
    3556           0 :         case DataPlant::FreeCoolControlMode::DryBulb: {
    3557           0 :             Tsensor = state.dataEnvrn->OutDryBulbTemp;
    3558           0 :             break;
    3559             :         }
    3560       45881 :         case DataPlant::FreeCoolControlMode::Loop: {
    3561       45881 :             ControlNodeNum = this_component.FreeCoolCntrlNodeNum;
    3562       45881 :             if (ControlNodeNum > 0) {
    3563       45881 :                 Tsensor = state.dataLoopNodes->Node(ControlNodeNum).TempLastTimestep; // use lagged value for stability
    3564             :             } else {
    3565           0 :                 Tsensor = 23.0;
    3566             :             }
    3567       45881 :             break;
    3568             :         }
    3569           0 :         default:
    3570           0 :             break;
    3571             :         }
    3572             : 
    3573       45881 :         if (Tsensor < TinLowLimit) { // turn off chiller to initiate free cooling
    3574           1 :             ChangeInLoad = 0.0;
    3575           1 :             this_component.Available = false;
    3576           1 :             this_component.FreeCoolCntrlShutDown = true;
    3577             :         } else {
    3578       45880 :             this_component.Available = true;
    3579       45880 :             this_component.FreeCoolCntrlShutDown = false;
    3580             :         }
    3581             : 
    3582       45881 :         break;
    3583             :     }
    3584           0 :     case DataPlant::HowMet::ByNominalCapLowOutLimitFreeCoolCntrl: {
    3585             :         // for chillers with free cooling shutdown (HeatExchanger:Hydronic currently)
    3586             :         // determine if free cooling controls shut off chiller
    3587           0 :         TinLowLimit = this_component.FreeCoolCntrlMinCntrlTemp;
    3588           0 :         switch (this_component.FreeCoolCntrlMode) {
    3589           0 :         case DataPlant::FreeCoolControlMode::WetBulb: {
    3590           0 :             Tsensor = state.dataEnvrn->OutWetBulbTemp;
    3591           0 :             break;
    3592             :         }
    3593           0 :         case DataPlant::FreeCoolControlMode::DryBulb: {
    3594           0 :             Tsensor = state.dataEnvrn->OutDryBulbTemp;
    3595           0 :             break;
    3596             :         }
    3597           0 :         case DataPlant::FreeCoolControlMode::Loop: {
    3598           0 :             ControlNodeNum = this_component.FreeCoolCntrlNodeNum;
    3599           0 :             if (ControlNodeNum > 0) {
    3600           0 :                 Tsensor = state.dataLoopNodes->Node(ControlNodeNum).TempLastTimestep; // use lagged value for stability
    3601             :             } else {
    3602           0 :                 Tsensor = 23.0;
    3603             :             }
    3604           0 :             break;
    3605             :         }
    3606           0 :         default:
    3607           0 :             break;
    3608             :         }
    3609             : 
    3610           0 :         if (Tsensor < TinLowLimit) { // turn off chiller to initiate free cooling
    3611           0 :             ChangeInLoad = 0.0;
    3612           0 :             this_component.Available = false;
    3613           0 :             this_component.FreeCoolCntrlShutDown = true;
    3614             :         } else {
    3615             :             //- Retrieve data from the plant loop data structure
    3616           0 :             this_component.Available = true;
    3617           0 :             this_component.FreeCoolCntrlShutDown = false;
    3618           0 :             CurMassFlowRate = state.dataLoopNodes->Node(this_component.NodeNumIn).MassFlowRate;
    3619           0 :             ToutLowLimit = this_component.MinOutletTemp;
    3620           0 :             Tinlet = state.dataLoopNodes->Node(this_component.NodeNumIn).Temp;
    3621           0 :             CurSpecHeat = GetSpecificHeatGlycol(state,
    3622           0 :                                                 state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidName,
    3623             :                                                 Tinlet,
    3624           0 :                                                 state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidIndex,
    3625             :                                                 RoutineName);
    3626           0 :             QdotTmp = CurMassFlowRate * CurSpecHeat * (Tinlet - ToutLowLimit);
    3627             : 
    3628             :             //        !- Don't correct if Q is zero, as this could indicate a component which this hasn't been implemented or not yet turned
    3629             :             //        on
    3630           0 :             if (CurMassFlowRate > 0.0) {
    3631           0 :                 ChangeInLoad = min(ChangeInLoad, QdotTmp);
    3632             :             }
    3633             :         }
    3634             : 
    3635           0 :         break;
    3636             :     }
    3637     4745540 :     case DataPlant::HowMet::ByNominalCapHiOutLimit: { // boilers with upper limit on outlet temperature
    3638             :         //- Retrieve data from the plant loop data structure
    3639     4745540 :         CurMassFlowRate = state.dataLoopNodes->Node(this_component.NodeNumIn).MassFlowRate;
    3640     4745540 :         ToutHiLimit = this_component.MaxOutletTemp;
    3641     4745540 :         Tinlet = state.dataLoopNodes->Node(this_component.NodeNumIn).Temp;
    3642     4745540 :         CurSpecHeat = GetSpecificHeatGlycol(state,
    3643     4745540 :                                             state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidName,
    3644             :                                             Tinlet,
    3645     4745540 :                                             state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidIndex,
    3646             :                                             RoutineName);
    3647     4745540 :         QdotTmp = CurMassFlowRate * CurSpecHeat * (ToutHiLimit - Tinlet);
    3648             : 
    3649     4745540 :         if (CurMassFlowRate > 0.0) {
    3650     4681709 :             ChangeInLoad = min(ChangeInLoad, QdotTmp);
    3651             :         }
    3652             : 
    3653     4745540 :         break;
    3654             :     }
    3655     4515564 :     case DataPlant::HowMet::PassiveCap: { // need to estimate current capacity if more or less passive devices ??
    3656             : 
    3657     4515564 :         break;
    3658             :     }
    3659     4767741 :     default:
    3660     4767741 :         break;
    3661             :     }
    3662    18941742 : }
    3663             : 
    3664     1160704 : void FindCompSPLoad(EnergyPlusData &state,
    3665             :                     PlantLocation const &plantLoc,
    3666             :                     int const OpNum // index for Plant()%LoopSide()%Branch()%Comp()%OpScheme()
    3667             : )
    3668             : {
    3669             : 
    3670             :     // SUBROUTINE INFORMATION:
    3671             :     //       AUTHOR         Sankaranarayanan K P
    3672             :     //       DATE WRITTEN   Jan 2005
    3673             :     //       MODIFIED       na
    3674             :     //       RE-ENGINEERED  Dan Fisher July 2010
    3675             : 
    3676             :     // PURPOSE OF THIS SUBROUTINE:
    3677             :     // To calculate the load on a component controlled by
    3678             :     // Component SetPoint based scheme.
    3679             : 
    3680             :     // Using/Aliasing
    3681             :     using DataLoopNode::SensedNodeFlagValue;
    3682             :     using FluidProperties::GetDensityGlycol;
    3683             : 
    3684             :     // Locals
    3685             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    3686             : 
    3687             :     // SUBROUTINE PARAMETER DEFINITIONS:
    3688             :     static constexpr std::string_view RoutineName("FindCompSPLoad");
    3689             : 
    3690             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3691             :     Real64 CompDemand;
    3692             :     Real64 DemandMdot;
    3693             :     Real64 ActualMdot;
    3694             :     Real64 TempIn;
    3695             :     Real64 CurSpecHeat;
    3696     1160704 :     Real64 TempSetPt(0.0);
    3697             :     Real64 CompMinLoad;
    3698             :     Real64 CompMaxLoad;
    3699             :     Real64 CompOptLoad;
    3700             :     int DemandNode;
    3701             :     int CompPtr;
    3702             :     int OpSchemePtr;
    3703             :     int ListPtr;
    3704             :     int SetPtNode;
    3705             :     int NumEquipLists;
    3706             :     Real64 rho;
    3707             :     Real64 CurrentDemandForCoolingOp;
    3708             :     Real64 CurrentDemandForHeatingOp;
    3709             : 
    3710     1160704 :     auto &this_component = CompData::getPlantComponent(state, plantLoc);
    3711             : 
    3712             :     // find the pointer to the 'PlantLoop()%OpScheme()'...data structure
    3713     1160704 :     NumEquipLists = this_component.OpScheme(OpNum).NumEquipLists;
    3714             :     if (NumEquipLists != 1) {
    3715             :         // CALL Severe error) there should be exactly one list associated with component setpoint scheme
    3716             :     }
    3717             : 
    3718     1160704 :     OpSchemePtr = this_component.OpScheme(OpNum).OpSchemePtr;
    3719     1160704 :     ListPtr = this_component.OpScheme(OpNum).EquipList(1).ListPtr;
    3720     1160704 :     CompPtr = this_component.OpScheme(OpNum).EquipList(1).CompPtr;
    3721             : 
    3722             :     // load local variables from the data structures
    3723     1160704 :     CompMinLoad = this_component.MinLoad;
    3724     1160704 :     CompMaxLoad = this_component.MaxLoad;
    3725     1160704 :     CompOptLoad = this_component.OptLoad;
    3726     1160704 :     DemandNode = state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).DemandNodeNum;
    3727     1160704 :     SetPtNode = state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).SetPointNodeNum;
    3728     1160704 :     TempIn = state.dataLoopNodes->Node(DemandNode).Temp;
    3729     1160704 :     rho = GetDensityGlycol(
    3730     1160704 :         state, state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidName, TempIn, state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidIndex, RoutineName);
    3731             : 
    3732     1160704 :     DemandMdot = state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).SetPointFlowRate * rho;
    3733             :     // DemandMDot is a constant design flow rate, next based on actual current flow rate for accurate current demand?
    3734     1160704 :     ActualMdot = state.dataLoopNodes->Node(DemandNode).MassFlowRate;
    3735     1160704 :     CurSpecHeat = GetSpecificHeatGlycol(
    3736     1160704 :         state, state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidName, TempIn, state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidIndex, RoutineName);
    3737     1160704 :     if ((ActualMdot > 0.0) && (ActualMdot != DemandMdot)) {
    3738      794506 :         DemandMdot = ActualMdot;
    3739             :     }
    3740             : 
    3741     1160704 :     switch (state.dataPlnt->PlantLoop(plantLoc.loopNum).LoopDemandCalcScheme) {
    3742      931488 :     case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
    3743      931488 :         TempSetPt = state.dataLoopNodes->Node(SetPtNode).TempSetPoint;
    3744      931488 :         break;
    3745             :     }
    3746      229216 :     case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
    3747      229216 :         if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType == CtrlType::CoolingOp) {
    3748      114608 :             TempSetPt = state.dataLoopNodes->Node(SetPtNode).TempSetPointHi;
    3749      114608 :         } else if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType ==
    3750             :                    CtrlType::HeatingOp) {
    3751      114608 :             TempSetPt = state.dataLoopNodes->Node(SetPtNode).TempSetPointLo;
    3752           0 :         } else if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType == CtrlType::DualOp) {
    3753           0 :             CurrentDemandForCoolingOp = DemandMdot * CurSpecHeat * (state.dataLoopNodes->Node(SetPtNode).TempSetPointHi - TempIn);
    3754           0 :             CurrentDemandForHeatingOp = DemandMdot * CurSpecHeat * (state.dataLoopNodes->Node(SetPtNode).TempSetPointLo - TempIn);
    3755           0 :             if ((CurrentDemandForCoolingOp < 0.0) && (CurrentDemandForHeatingOp <= 0.0)) { // cooling
    3756           0 :                 TempSetPt = state.dataLoopNodes->Node(SetPtNode).TempSetPointHi;
    3757           0 :             } else if ((CurrentDemandForCoolingOp >= 0.0) && (CurrentDemandForHeatingOp > 0.0)) { // heating
    3758           0 :                 TempSetPt = state.dataLoopNodes->Node(SetPtNode).TempSetPointLo;
    3759             :             } else { // deadband
    3760           0 :                 TempSetPt = TempIn;
    3761             :             }
    3762             :         } else {
    3763           0 :             assert(false);
    3764             :         }
    3765      229216 :         break;
    3766             :     }
    3767           0 :     default:
    3768           0 :         assert(false);
    3769             :         break;
    3770             :     }
    3771             : 
    3772     1160704 :     if (TempSetPt == SensedNodeFlagValue) {
    3773         120 :         this_component.ON = false;
    3774         120 :         this_component.MyLoad = 0.0;
    3775         120 :         this_component.EquipDemand = 0.0;
    3776             :     } else {
    3777             : 
    3778     1160584 :         CompDemand = (DemandMdot * CurSpecHeat * (TempSetPt - TempIn));
    3779             : 
    3780     1160584 :         if (std::abs(CompDemand) < LoopDemandTol) CompDemand = 0.0;
    3781     1160584 :         this_component.EquipDemand = CompDemand;
    3782             : 
    3783             :         // set MyLoad and runflag
    3784     1160584 :         if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType == CtrlType::CoolingOp) {
    3785      664376 :             if (CompDemand < (-LoopDemandTol)) {
    3786      461338 :                 this_component.ON = true;
    3787      461338 :                 this_component.MyLoad = CompDemand;
    3788             :             } else {
    3789      203038 :                 this_component.ON = false;
    3790      203038 :                 this_component.MyLoad = 0.0;
    3791             :             }
    3792      496208 :         } else if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType ==
    3793             :                    CtrlType::HeatingOp) {
    3794      120740 :             if (CompDemand > LoopDemandTol) {
    3795        1832 :                 this_component.ON = true;
    3796        1832 :                 this_component.MyLoad = CompDemand;
    3797             :             } else {
    3798      118908 :                 this_component.ON = false;
    3799      118908 :                 this_component.MyLoad = 0.0;
    3800             :             }
    3801      375468 :         } else if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType == CtrlType::DualOp) {
    3802      375468 :             if (CompDemand > LoopDemandTol || CompDemand < (-LoopDemandTol)) {
    3803      234384 :                 this_component.ON = true;
    3804      234384 :                 this_component.MyLoad = CompDemand;
    3805             :             } else {
    3806      141084 :                 this_component.ON = false;
    3807      141084 :                 this_component.MyLoad = 0.0;
    3808             :             }
    3809             :         }
    3810             : 
    3811             :         // Check bounds on MyLoad
    3812     1160584 :         if (std::abs(this_component.MyLoad) > CompMaxLoad) {
    3813      457160 :             this_component.MyLoad = sign(CompMaxLoad, this_component.MyLoad);
    3814             :         }
    3815             :         //   PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchNum)%Comp(CompNum)%MyLoad = &
    3816             :         //   MIN(PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchNum)%Comp(CompNum)%MyLoad,CompMaxLoad)
    3817             : 
    3818     1160584 :         if (std::abs(this_component.MyLoad) < CompMinLoad) {
    3819       87432 :             this_component.MyLoad = sign(CompMinLoad, this_component.MyLoad);
    3820             :         }
    3821             :         //   PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchNum)%Comp(CompNum)%MyLoad = &
    3822             :         //   MAX(PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchNum)%Comp(CompNum)%MyLoad,CompMinLoad)
    3823             : 
    3824             :     } // valid setpoint (TempSetPt /= SensedNodeFlagValue)
    3825     1160704 : }
    3826             : 
    3827      322816 : void DistributeUserDefinedPlantLoad(EnergyPlusData &state,
    3828             :                                     PlantLocation const &plantLoc,
    3829             :                                     int const CurCompLevelOpNum, // index for Plant()%LoopSide()%Branch()%Comp()%OpScheme()
    3830             :                                     int const CurSchemePtr,
    3831             :                                     Real64 const LoopDemand,
    3832             :                                     [[maybe_unused]] Real64 &RemLoopDemand)
    3833             : {
    3834             : 
    3835             :     // SUBROUTINE INFORMATION:
    3836             :     //       AUTHOR         B. Griffith
    3837             :     //       DATE WRITTEN   August 2013
    3838             :     //       MODIFIED       na
    3839             :     //       RE-ENGINEERED  na
    3840             : 
    3841             :     // PURPOSE OF THIS SUBROUTINE:
    3842             :     // <description>
    3843             : 
    3844             :     // METHODOLOGY EMPLOYED:
    3845             :     // <description>
    3846             : 
    3847             :     // REFERENCES:
    3848             :     // na
    3849             : 
    3850             :     // Using/Aliasing
    3851             :     using EMSManager::ManageEMS;
    3852             : 
    3853             :     // Locals
    3854             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    3855             : 
    3856             :     // SUBROUTINE PARAMETER DEFINITIONS:
    3857             :     // na
    3858             : 
    3859             :     // INTERFACE BLOCK SPECIFICATIONS:
    3860             :     // na
    3861             : 
    3862             :     // DERIVED TYPE DEFINITIONS:
    3863             :     // na
    3864             : 
    3865             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3866             :     int CompPtr;
    3867             : 
    3868      322816 :     auto &this_component = CompData::getPlantComponent(state, plantLoc);
    3869             : 
    3870             :     // ListPtr = PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchNum)%Comp(CompNum)%OpScheme(CurCompLevelOpNum)%EquipList(1)%ListPtr
    3871      322816 :     CompPtr = this_component.OpScheme(CurCompLevelOpNum).EquipList(1).CompPtr;
    3872             : 
    3873             :     // fill internal variable
    3874      322816 :     state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).EquipList(1).Comp(CompPtr).EMSIntVarRemainingLoadValue = LoopDemand;
    3875             : 
    3876             :     // Call EMS program(s)
    3877      322816 :     if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).ErlSimProgramMngr > 0) {
    3878             :         bool anyEMSRan;
    3879      161408 :         ManageEMS(state,
    3880             :                   EMSManager::EMSCallFrom::UserDefinedComponentModel,
    3881             :                   anyEMSRan,
    3882      161408 :                   state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).ErlSimProgramMngr);
    3883      161408 :     } else if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).simPluginLocation > -1) {
    3884      161408 :         state.dataPluginManager->pluginManager->runSingleUserDefinedPlugin(
    3885      161408 :             state, state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).simPluginLocation);
    3886             :     }
    3887             : 
    3888             :     // move actuated value to MyLoad
    3889             : 
    3890      322816 :     this_component.MyLoad =
    3891      322816 :         state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).EquipList(1).Comp(CompPtr).EMSActuatorDispatchedLoadValue;
    3892      322816 :     this_component.EquipDemand =
    3893      322816 :         state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).EquipList(1).Comp(CompPtr).EMSActuatorDispatchedLoadValue;
    3894      322816 :     if (std::abs(this_component.MyLoad) > LoopDemandTol) {
    3895      125424 :         this_component.ON = true;
    3896             : 
    3897             :     } else {
    3898      197392 :         this_component.ON = false;
    3899             :     }
    3900      322816 : }
    3901             : 
    3902             : // End Load Calculation/Distribution Section of the Plant Loop Module
    3903             : //******************************************************************************
    3904             : 
    3905             : //********************************
    3906             : 
    3907      399700 : Real64 FindRangeVariable(EnergyPlusData &state,
    3908             :                          int const LoopNum,                // PlantLoop data structure loop counter
    3909             :                          int const CurSchemePtr,           // set by PL()%LoopSide()%Branch()%Comp()%OpScheme()%OpSchemePtr
    3910             :                          DataPlant::OpScheme CurSchemeType // identifier set in PlantData
    3911             : )
    3912             : {
    3913             : 
    3914             :     // SUBROUTINE INFORMATION:
    3915             :     //       AUTHOR         Sankaranarayanan K P
    3916             :     //       DATE WRITTEN   Jan 2004
    3917             :     //       MODIFIED       Chandan Sharma, August 2010
    3918             :     //       RE-ENGINEERED  na
    3919             : 
    3920             :     // Using/Aliasing
    3921             :     using namespace DataLoopNode;
    3922             :     // Return value
    3923      399700 :     Real64 FindRangeVariable(0.0);
    3924             : 
    3925             :     // Locals
    3926             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    3927             :     // used to locate data in PL()%OpScheme(CurSchemePtr)
    3928             :     // SUBROUTINE PARAMETER DEFINITIONS:
    3929             :     // na
    3930             : 
    3931             :     // INTERFACE BLOCK SPECIFICATIONS
    3932             :     // na
    3933             : 
    3934             :     // DERIVED TYPE DEFINITIONS
    3935             :     // na
    3936             : 
    3937             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3938             :     int ReferenceNodeNum;
    3939             :     Real64 NodeTemperature;
    3940             : 
    3941      399700 :     switch (CurSchemeType) {
    3942       14584 :     case OpScheme::DryBulbTDB: { // drybulb temp based controls
    3943       14584 :         ReferenceNodeNum = state.dataPlnt->PlantLoop(LoopNum).OpScheme(CurSchemePtr).ReferenceNodeNumber;
    3944       14584 :         NodeTemperature = state.dataLoopNodes->Node(ReferenceNodeNum).Temp;
    3945       14584 :         FindRangeVariable = NodeTemperature - state.dataEnvrn->OutDryBulbTemp;
    3946       14584 :         break;
    3947             :     }
    3948      370572 :     case OpScheme::WetBulbTDB: { // wetbulb temp based controls
    3949      370572 :         ReferenceNodeNum = state.dataPlnt->PlantLoop(LoopNum).OpScheme(CurSchemePtr).ReferenceNodeNumber;
    3950      370572 :         NodeTemperature = state.dataLoopNodes->Node(ReferenceNodeNum).Temp;
    3951      370572 :         FindRangeVariable = NodeTemperature - state.dataEnvrn->OutWetBulbTemp;
    3952      370572 :         break;
    3953             :     }
    3954       14544 :     case OpScheme::DewPointTDB: { // dewpoint temp based controls
    3955       14544 :         ReferenceNodeNum = state.dataPlnt->PlantLoop(LoopNum).OpScheme(CurSchemePtr).ReferenceNodeNumber;
    3956       14544 :         NodeTemperature = state.dataLoopNodes->Node(ReferenceNodeNum).Temp;
    3957       14544 :         FindRangeVariable = NodeTemperature - state.dataEnvrn->OutDewPointTemp;
    3958       14544 :         break;
    3959             :     }
    3960           0 :     default: {
    3961           0 :         assert(false);
    3962             :         break;
    3963             :     }
    3964             :     } // OperationScheme
    3965             : 
    3966      399700 :     return FindRangeVariable;
    3967             : }
    3968             : 
    3969             : //********************************
    3970             : 
    3971             : // Begin Plant Loop ON/OFF Utility Subroutines
    3972             : //******************************************************************************
    3973             : 
    3974    19180113 : void TurnOnPlantLoopPipes(EnergyPlusData &state, int const LoopNum, const LoopSideLocation LoopSideNum)
    3975             : {
    3976             :     // SUBROUTINE INFORMATION:
    3977             :     //       AUTHOR         Dan Fisher
    3978             :     //       DATE WRITTEN   July 1998
    3979             :     //       MODIFIED       na
    3980             :     //       RE-ENGINEERED  na
    3981             : 
    3982             :     // PURPOSE OF THIS SUBROUTINE: This subroutine sets a logical flag
    3983             :     // for the loop circulation pump to TRUE.
    3984             : 
    3985             :     // METHODOLOGY EMPLOYED:
    3986             :     // na
    3987             :     // REFERENCES:
    3988             :     // na
    3989             :     // USE STATEMENTS:
    3990             :     // na
    3991             : 
    3992             :     // Locals
    3993             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    3994             : 
    3995             :     // SUBROUTINE PARAMETER DEFINITIONS:
    3996             :     // na
    3997             :     // INTERFACE BLOCK SPECIFICATIONS
    3998             :     // na
    3999             :     // DERIVED TYPE DEFINITIONS
    4000             :     // na
    4001             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4002             :     int MachineOnLoopNum;
    4003             :     int Num;
    4004             : 
    4005    98352680 :     for (Num = 1; Num <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++Num) {
    4006   160583675 :         for (MachineOnLoopNum = 1; MachineOnLoopNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).TotalComponents;
    4007             :              ++MachineOnLoopNum) {
    4008    81411108 :             switch (state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnLoopNum).Type) {
    4009    37562619 :             case DataPlant::PlantEquipmentType::Pipe:
    4010             :             case DataPlant::PlantEquipmentType::PipeInterior:
    4011             :             case DataPlant::PlantEquipmentType::PipeExterior:
    4012             :             case DataPlant::PlantEquipmentType::PipeUnderground: {
    4013    37562619 :                 state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnLoopNum).ON = true;
    4014    37562619 :                 break;
    4015             :             }
    4016    43848489 :             default:
    4017    43848489 :                 break; // Don't do anything
    4018             :             }
    4019             :         }
    4020             :     }
    4021    19180113 : }
    4022             : 
    4023       16712 : void TurnOffLoopEquipment(EnergyPlusData &state, int const LoopNum)
    4024             : {
    4025             :     // SUBROUTINE INFORMATION:
    4026             :     //       AUTHOR         D.E. Fisher
    4027             :     //       DATE WRITTEN   July 1998
    4028             :     //       MODIFIED       D.E. Fisher, Aug. 2010
    4029             :     //       RE-ENGINEERED
    4030             : 
    4031             :     // PURPOSE OF THIS SUBROUTINE:
    4032             :     // METHODOLOGY EMPLOYED:
    4033             :     // na
    4034             :     // REFERENCES:
    4035             :     // na
    4036             :     // USE STATEMENTS:
    4037             :     // na
    4038             : 
    4039             :     // Locals
    4040             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    4041             : 
    4042             :     // SUBROUTINE PARAMETER DEFINITIONS:
    4043             :     // na
    4044             :     // INTERFACE BLOCK SPECIFICATIONS
    4045             :     // na
    4046             :     // DERIVED TYPE DEFINITIONS
    4047             :     // na
    4048             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4049             :     int MachineOnBranch;
    4050             :     int Num;
    4051             : 
    4052       50136 :     for (DataPlant::LoopSideLocation LoopSideNum : LoopSideKeys) {
    4053      167120 :         for (Num = 1; Num <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++Num) {
    4054      267392 :             for (MachineOnBranch = 1; MachineOnBranch <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).TotalComponents;
    4055             :                  ++MachineOnBranch) {
    4056             :                 // Sankar Non Integrated Economizer
    4057      133696 :                 if (!DataPlant::PlantEquipmentTypeIsPump[static_cast<int>(
    4058      133696 :                         state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).Type)]) {
    4059      116984 :                     state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).ON = false;
    4060      116984 :                     state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).MyLoad = 0.0;
    4061             :                 }
    4062             :             }
    4063             :         }
    4064             :     }
    4065       16712 : }
    4066             : 
    4067           0 : void TurnOffLoopSideEquipment(EnergyPlusData &state, int const LoopNum, const LoopSideLocation LoopSideNum)
    4068             : {
    4069             :     // SUBROUTINE INFORMATION:
    4070             :     //       AUTHOR         D.E. Fisher
    4071             :     //       DATE WRITTEN   July 1998
    4072             :     //       MODIFIED       D.E. Fisher, Aug. 2010
    4073             :     //       RE-ENGINEERED
    4074             : 
    4075             :     // PURPOSE OF THIS SUBROUTINE:
    4076             :     // METHODOLOGY EMPLOYED:
    4077             :     // na
    4078             :     // REFERENCES:
    4079             :     // na
    4080             :     // USE STATEMENTS:
    4081             :     // na
    4082             : 
    4083             :     // Locals
    4084             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    4085             : 
    4086             :     // SUBROUTINE PARAMETER DEFINITIONS:
    4087             :     // na
    4088             :     // INTERFACE BLOCK SPECIFICATIONS
    4089             :     // na
    4090             :     // DERIVED TYPE DEFINITIONS
    4091             :     // na
    4092             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4093             :     int MachineOnBranch;
    4094             :     int Num;
    4095             : 
    4096           0 :     for (Num = 1; Num <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++Num) {
    4097           0 :         for (MachineOnBranch = 1; MachineOnBranch <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).TotalComponents;
    4098             :              ++MachineOnBranch) {
    4099             :             // Sankar Non Integrated Economizer
    4100           0 :             if (!DataPlant::PlantEquipmentTypeIsPump[static_cast<int>(
    4101           0 :                     state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).Type)]) {
    4102           0 :                 state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).ON = false;
    4103           0 :                 state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).MyLoad = 0.0;
    4104             :             }
    4105             :         }
    4106             :     }
    4107           0 : }
    4108             : 
    4109             : // End Plant Loop ON/OFF Utility Subroutines
    4110             : //******************************************************************************
    4111             : 
    4112             : // Begin Plant EMS Control Routines
    4113             : //******************************************************************************
    4114             : 
    4115          73 : void SetupPlantEMSActuators(EnergyPlusData &state)
    4116             : {
    4117             : 
    4118             :     // SUBROUTINE INFORMATION:
    4119             :     //       AUTHOR         D.E. Fisher
    4120             :     //       DATE WRITTEN   Feb 2007
    4121             :     //       MODIFIED       B. Griffith August 2009, D. Fisher, Aug. 2010
    4122             :     //       RE-ENGINEERED  na
    4123             : 
    4124             :     // PURPOSE OF THIS SUBROUTINE:
    4125             :     // This subroutine loads the plant EMS actuators
    4126             : 
    4127             :     // METHODOLOGY EMPLOYED:
    4128             :     // Call the setupAcuator routine
    4129             : 
    4130             :     // Locals
    4131          73 :     std::string ActuatorType;
    4132          73 :     std::string ActuatorName;
    4133          73 :     std::string UniqueIDName;
    4134             :     static constexpr std::string_view Units("[on/off]");
    4135             :     // INTEGER                      :: NumAct
    4136             :     int LoopNum;
    4137             :     int BranchNum;
    4138             :     int CompNum;
    4139             : 
    4140         191 :     for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
    4141         118 :         ActuatorName = "Plant Loop Overall";
    4142         118 :         UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).Name;
    4143         118 :         ActuatorType = "On/Off Supervisory";
    4144         118 :         SetupEMSActuator(state,
    4145             :                          ActuatorName,
    4146             :                          UniqueIDName,
    4147             :                          ActuatorType,
    4148             :                          Units,
    4149         118 :                          state.dataPlnt->PlantLoop(LoopNum).EMSCtrl,
    4150         118 :                          state.dataPlnt->PlantLoop(LoopNum).EMSValue);
    4151             : 
    4152         118 :         ActuatorName = "Supply Side Half Loop";
    4153         118 :         UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).Name;
    4154         118 :         ActuatorType = "On/Off Supervisory";
    4155         118 :         SetupEMSActuator(state,
    4156             :                          ActuatorName,
    4157             :                          UniqueIDName,
    4158             :                          ActuatorType,
    4159             :                          Units,
    4160         118 :                          state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideLocation::Supply).EMSCtrl,
    4161         118 :                          state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideLocation::Supply).EMSValue);
    4162             : 
    4163         118 :         ActuatorName = "Demand Side Half Loop";
    4164         118 :         UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).Name;
    4165         118 :         ActuatorType = "On/Off Supervisory";
    4166         118 :         SetupEMSActuator(state,
    4167             :                          ActuatorName,
    4168             :                          UniqueIDName,
    4169             :                          ActuatorType,
    4170             :                          Units,
    4171         118 :                          state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideLocation::Demand).EMSCtrl,
    4172         118 :                          state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideLocation::Demand).EMSValue);
    4173             : 
    4174         354 :         for (DataPlant::LoopSideLocation LoopSideNum : LoopSideKeys) {
    4175        2520 :             for (BranchNum = 1; BranchNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++BranchNum) {
    4176        2284 :                 if (LoopSideNum == LoopSideLocation::Supply) {
    4177         488 :                     ActuatorName = "Supply Side Branch";
    4178         488 :                     UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Name;
    4179         488 :                     ActuatorType = "On/Off Supervisory";
    4180         488 :                     SetupEMSActuator(state,
    4181             :                                      ActuatorName,
    4182             :                                      UniqueIDName,
    4183             :                                      ActuatorType,
    4184             :                                      Units,
    4185         488 :                                      state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).EMSCtrlOverrideOn,
    4186         488 :                                      state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).EMSCtrlOverrideValue);
    4187        1796 :                 } else if (LoopSideNum == LoopSideLocation::Demand) {
    4188        1796 :                     ActuatorName = "Demand Side Branch";
    4189        1796 :                     UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Name;
    4190        1796 :                     ActuatorType = "On/Off Supervisory";
    4191        1796 :                     SetupEMSActuator(state,
    4192             :                                      ActuatorName,
    4193             :                                      UniqueIDName,
    4194             :                                      ActuatorType,
    4195             :                                      Units,
    4196        1796 :                                      state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).EMSCtrlOverrideOn,
    4197        1796 :                                      state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).EMSCtrlOverrideValue);
    4198             :                 }
    4199        4583 :                 for (CompNum = 1; CompNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).TotalComponents; ++CompNum) {
    4200        4598 :                     ActuatorName = format("Plant Component {}",
    4201             :                                           PlantEquipTypeNames[static_cast<int>(
    4202        4598 :                                               state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).Type)]);
    4203        2299 :                     UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).Name;
    4204        2299 :                     ActuatorType = "On/Off Supervisory";
    4205        2299 :                     SetupEMSActuator(state,
    4206             :                                      ActuatorName,
    4207             :                                      UniqueIDName,
    4208             :                                      ActuatorType,
    4209             :                                      "[fraction]",
    4210        2299 :                                      state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).EMSLoadOverrideOn,
    4211        2299 :                                      state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).EMSLoadOverrideValue);
    4212             :                 }
    4213             :             }
    4214             :         }
    4215             :     }
    4216          73 : }
    4217             : 
    4218    38702348 : void ActivateEMSControls(EnergyPlusData &state, PlantLocation const &plantLoc, bool &LoopShutDownFlag)
    4219             : {
    4220             : 
    4221             :     // SUBROUTINE INFORMATION:
    4222             :     //       AUTHOR         D.E. Fisher
    4223             :     //       DATE WRITTEN   Feb 2007
    4224             :     //       MODIFIED
    4225             :     //       RE-ENGINEERED  na
    4226             : 
    4227             :     // PURPOSE OF THIS SUBROUTINE:
    4228             :     // This subroutine loads the plant EMS actuators
    4229             : 
    4230             :     // METHODOLOGY EMPLOYED: The EMS flags are evaluated in hierarchical order:
    4231             :     //     LOOP flags override branch and component flags
    4232             :     //     BRANCH flags override component flags
    4233             :     // If the loop flag (EMSCtrl) is true, then
    4234             :     //     IF EMSValue <= 0, shut down the entire loop including the pumps
    4235             :     //     IF EMSValue > 0, no action
    4236             :     // If the LoopSide flag (EMSCtrl) is true, then:
    4237             :     //     IF EMSValue <=0, shut down all components on the LoopSide except the pumps
    4238             :     //     IF EMSValue > 0, no action
    4239             :     // If a component flag (EMSCtrl) is true, then:
    4240             :     //     EMSValue <=0, shut down the component
    4241             :     //     EMSValue > 0, calc. component load: MyLoad=MIN(MaxCompLoad,MaxCompLoad*EMSValue)
    4242             : 
    4243             :     // REFERENCES:
    4244             :     // na
    4245             : 
    4246             :     // Using/Aliasing
    4247             :     using namespace DataLoopNode;
    4248             : 
    4249             :     // SUBROUTINE ARGUMENT DEFINITIONS
    4250             : 
    4251             :     // Locals
    4252             :     // SUBROUTINE PARAMETER DEFINITIONS
    4253             :     static constexpr std::string_view RoutineName("ActivateEMSControls");
    4254             : 
    4255             :     // SUBROUTINE VARIABLE DEFINITIONS
    4256             :     Real64 CurMassFlowRate;
    4257             :     Real64 ToutLowLimit;
    4258             :     Real64 Tinlet;
    4259             :     Real64 CurSpecHeat;
    4260             :     Real64 QTemporary;
    4261             :     // unused REAL(r64)                  :: ChangeInLoad
    4262             : 
    4263             :     // MODULE VARIABLE DECLARATIONS:
    4264             : 
    4265             :     // set up some nice references to avoid lookups
    4266    38702348 :     auto &this_loop = state.dataPlnt->PlantLoop(plantLoc.loopNum);
    4267    38702348 :     auto &this_loopside = this_loop.LoopSide(plantLoc.loopSideNum);
    4268    38702348 :     auto &this_comp = this_loopside.Branch(plantLoc.branchNum).Comp(plantLoc.compNum);
    4269             : 
    4270             :     // Loop Control
    4271    38702348 :     if (this_loop.EMSCtrl) {
    4272        8356 :         if (this_loop.EMSValue <= 0.0) {
    4273        8356 :             LoopShutDownFlag = true;
    4274        8356 :             TurnOffLoopEquipment(state, plantLoc.loopNum);
    4275      153468 :             return;
    4276             :         } else {
    4277           0 :             LoopShutDownFlag = false;
    4278             :         }
    4279             :     } else {
    4280    38693992 :         LoopShutDownFlag = false;
    4281             :     }
    4282             : 
    4283             :     // Half-loop control
    4284    38693992 :     if (this_loopside.EMSCtrl) {
    4285           0 :         if (this_loopside.EMSValue <= 0.0) {
    4286           0 :             TurnOffLoopSideEquipment(state, plantLoc.loopNum, plantLoc.loopSideNum);
    4287           0 :             return;
    4288             :         } else {
    4289             :             // do nothing:  can't turn all LoopSide equip. ON with loop switch
    4290             :         }
    4291             :     }
    4292             : 
    4293    38693992 :     if (this_comp.EMSLoadOverrideOn) {
    4294             :         // EMSValue <= 0 turn component OFF
    4295      145112 :         if (this_comp.EMSLoadOverrideValue <= 0.0) {
    4296      145112 :             this_comp.ON = false;
    4297      145112 :             this_comp.Available = false;
    4298      145112 :             this_comp.MyLoad = 0.0;
    4299      145112 :             return;
    4300             :         } else {
    4301             :             // EMSValue > 0 Set Component Load and Turn component ON
    4302           0 :             this_comp.ON = true;
    4303           0 :             this_comp.Available = false;
    4304           0 :             this_comp.MyLoad = min(this_comp.MaxLoad, (this_comp.MaxLoad * this_comp.EMSLoadOverrideValue));
    4305             : 
    4306             :             // Check lower/upper temperature limit for chillers
    4307           0 :             switch (this_comp.Type) {
    4308             : 
    4309           0 :             case DataPlant::PlantEquipmentType::Chiller_ElectricEIR:
    4310             :             case DataPlant::PlantEquipmentType::Chiller_Electric:
    4311             :             case DataPlant::PlantEquipmentType::Chiller_ElectricReformEIR: {
    4312             : 
    4313             :                 //- Retrieve data from the plant loop data structure
    4314           0 :                 CurMassFlowRate = state.dataLoopNodes->Node(this_comp.NodeNumIn).MassFlowRate;
    4315           0 :                 ToutLowLimit = this_comp.MinOutletTemp;
    4316           0 :                 Tinlet = state.dataLoopNodes->Node(this_comp.NodeNumIn).Temp;
    4317           0 :                 CurSpecHeat = GetSpecificHeatGlycol(state, this_loop.FluidName, Tinlet, this_loop.FluidIndex, RoutineName);
    4318           0 :                 QTemporary = CurMassFlowRate * CurSpecHeat * (Tinlet - ToutLowLimit);
    4319             : 
    4320             :                 //- Don't correct if Q is zero, as this could indicate a component which this hasn't been implemented
    4321           0 :                 if (QTemporary > 0.0) {
    4322           0 :                     if (std::abs(this_comp.MyLoad) > this_comp.MaxLoad) {
    4323           0 :                         this_comp.MyLoad = sign(this_comp.MaxLoad, this_comp.MyLoad);
    4324             :                     }
    4325           0 :                     if (std::abs(this_comp.MyLoad) > QTemporary) {
    4326           0 :                         this_comp.MyLoad = sign(QTemporary, this_comp.MyLoad);
    4327             :                     }
    4328             :                 }
    4329           0 :                 break;
    4330             :             }
    4331           0 :             default:
    4332           0 :                 break; // Nothing Changes for now, could add in case statements for boilers, which would use upper limit temp check
    4333             :             }
    4334           0 :             return;
    4335             :         } // EMSValue <=> 0
    4336             :     }     // EMSFlag
    4337             : }
    4338             : 
    4339    18941742 : void AdjustChangeInLoadByEMSControls(EnergyPlusData &state,
    4340             :                                      PlantLocation const &plantLoc,
    4341             :                                      Real64 &ChangeInLoad // positive magnitude of load change
    4342             : )
    4343             : {
    4344             : 
    4345             :     // SUBROUTINE INFORMATION:
    4346             :     //       AUTHOR         B. Griffith
    4347             :     //       DATE WRITTEN   April 2012
    4348             :     //       MODIFIED       na
    4349             :     //       RE-ENGINEERED  na
    4350             : 
    4351             :     // PURPOSE OF THIS SUBROUTINE:
    4352             :     // modify load dispatch if EMS controls are in place for a specific component
    4353             : 
    4354             :     // METHODOLOGY EMPLOYED:
    4355             :     // Check if Loop Side is shutdown
    4356             :     //  then check if branch is shutdown
    4357             :     // then  check if component is overridden and use the value if it is.
    4358             :     // take ABS() of EMS value to ensure sign is correct.
    4359             : 
    4360             :     // REFERENCES:
    4361             :     // na
    4362             : 
    4363             :     // USE STATEMENTS:
    4364             :     // na
    4365             : 
    4366             :     // Locals
    4367             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    4368             : 
    4369             :     // SUBROUTINE PARAMETER DEFINITIONS:
    4370             :     // na
    4371             : 
    4372             :     // INTERFACE BLOCK SPECIFICATIONS:
    4373             :     // na
    4374             : 
    4375             :     // DERIVED TYPE DEFINITIONS:
    4376             :     // na
    4377             : 
    4378             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4379             : 
    4380             :     // set up some nice references to avoid lookups
    4381    18941742 :     auto &this_loopside = state.dataPlnt->PlantLoop(plantLoc.loopNum).LoopSide(plantLoc.loopSideNum);
    4382    18941742 :     auto &this_branch = this_loopside.Branch(plantLoc.branchNum);
    4383    18941742 :     auto &this_comp = this_branch.Comp(plantLoc.compNum);
    4384             : 
    4385    18941742 :     if ((this_loopside.EMSCtrl) && (this_loopside.EMSValue <= 0.0)) {
    4386           0 :         ChangeInLoad = 0.0;
    4387           0 :         return;
    4388             :     }
    4389             : 
    4390    18941742 :     if ((this_branch.EMSCtrlOverrideOn) && (this_branch.EMSCtrlOverrideValue <= 0.0)) {
    4391           0 :         ChangeInLoad = 0.0;
    4392           0 :         return;
    4393             :     }
    4394             : 
    4395    18941742 :     if (this_comp.EMSLoadOverrideOn) {
    4396       52228 :         if (this_comp.EMSLoadOverrideValue == 0.0) {
    4397         672 :             ChangeInLoad = 0.0;
    4398             :         }
    4399             :     }
    4400             : }
    4401             : 
    4402             : //*END PLANT EMS CONTROL ROUTINES!
    4403             : //******************************************************************************
    4404             : 
    4405             : } // namespace EnergyPlus::PlantCondLoopOperation

Generated by: LCOV version 1.14