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

Generated by: LCOV version 1.14