LCOV - code coverage report
Current view: top level - EnergyPlus - EMSManager.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 883 1165 75.8 %
Date: 2023-01-17 19:17:23 Functions: 30 31 96.8 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <cmath>
      50             : 
      51             : // ObjexxFCL Headers
      52             : #include <ObjexxFCL/Array.functions.hh>
      53             : #include <ObjexxFCL/Array1D.hh>
      54             : #include <ObjexxFCL/Fmath.hh>
      55             : 
      56             : // EnergyPlus Headers
      57             : #include <EnergyPlus/Construction.hh>
      58             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      59             : #include <EnergyPlus/DataAirLoop.hh>
      60             : #include <EnergyPlus/DataAirSystems.hh>
      61             : #include <EnergyPlus/DataHVACGlobals.hh>
      62             : #include <EnergyPlus/DataHeatBalance.hh>
      63             : #include <EnergyPlus/DataIPShortCuts.hh>
      64             : #include <EnergyPlus/DataLoopNode.hh>
      65             : #include <EnergyPlus/DataRuntimeLanguage.hh>
      66             : #include <EnergyPlus/DataSurfaces.hh>
      67             : #include <EnergyPlus/DataZoneControls.hh>
      68             : #include <EnergyPlus/EMSManager.hh>
      69             : #include <EnergyPlus/General.hh>
      70             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      71             : #include <EnergyPlus/OutAirNodeManager.hh>
      72             : #include <EnergyPlus/OutputProcessor.hh>
      73             : #include <EnergyPlus/PluginManager.hh>
      74             : #include <EnergyPlus/RuntimeLanguageProcessor.hh>
      75             : #include <EnergyPlus/ScheduleManager.hh>
      76             : #include <EnergyPlus/UtilityRoutines.hh>
      77             : 
      78             : namespace EnergyPlus {
      79             : 
      80             : // note there are routines that lie outside of the Module at the end of this file
      81             : 
      82             : namespace EMSManager {
      83             : 
      84             :     // MODULE INFORMATION:
      85             :     //       AUTHOR         Peter Graham Ellis
      86             :     //       DATE WRITTEN   June 2006
      87             :     //       MODIFIED       Brent Griffith
      88             :     //                      May - August 2009
      89             :     //       RE-ENGINEERED  na
      90             : 
      91             :     // PURPOSE OF THIS MODULE:
      92             :     // This module manages the programmable energy management system(EMS).
      93             : 
      94             :     // Using/Aliasing
      95             :     using namespace DataRuntimeLanguage;
      96             : 
      97             :     constexpr std::array<std::string_view, static_cast<int>(EMSCallFrom::Num)> EMSCallFromNamesUC{"ENDOFZONESIZING",
      98             :                                                                                                   "ENDOFSYSTEMSIZING",
      99             :                                                                                                   "BEGINNEWENVIRONMENT",
     100             :                                                                                                   "AFTERNEWENVIRONMENTWARMUPISCOMPLETE",
     101             :                                                                                                   "BEGINTIMESTEPBEFOREPREDICTOR",
     102             :                                                                                                   "AFTERPREDICTORBEFOREHVACMANAGERS",
     103             :                                                                                                   "AFTERPREDICTORAFTERHVACMANAGERS",
     104             :                                                                                                   "INSIDEHVACSYSTEMITERATIONLOOP",
     105             :                                                                                                   "ENDOFSYSTEMTIMESTEPBEFOREHVACREPORTING",
     106             :                                                                                                   "ENDOFSYSTEMTIMESTEPAFTERHVACREPORTING",
     107             :                                                                                                   "ENDOFZONETIMESTEPBEFOREZONEREPORTING",
     108             :                                                                                                   "ENDOFZONETIMESTEPAFTERZONEREPORTING",
     109             :                                                                                                   "SETUPSIMULATION",
     110             :                                                                                                   "EXTERNALINTERFACE",
     111             :                                                                                                   "AFTERCOMPONENTINPUTREADIN",
     112             :                                                                                                   "USERDEFINEDCOMPONENTMODEL",
     113             :                                                                                                   "UNITARYSYSTEMSIZING",
     114             :                                                                                                   "BEGINZONETIMESTEPBEFOREINITHEATBALANCE",
     115             :                                                                                                   "BEGINZONETIMESTEPAFTERINITHEATBALANCE",
     116             :                                                                                                   "BEGINZONETIMESTEPBEFORESETCURRENTWEATHER"};
     117             : 
     118             :     std::array<std::string_view, static_cast<int>(SPControlType::Num)> controlTypeName{"Temperature Setpoint",
     119             :                                                                                        "Temperature Minimum Setpoint",
     120             :                                                                                        "Temperature Maximum Setpoint",
     121             :                                                                                        "Humidity Ratio Setpoint",
     122             :                                                                                        "Humidity Ratio Minimum Setpoint",
     123             :                                                                                        "Humidity Ratio Maximum Setpoint",
     124             :                                                                                        "Mass Flow Rate Setpoint",
     125             :                                                                                        "Mass Flow Rate Minimum Available Setpoint",
     126             :                                                                                        "Mass Flow Rate Maximum Available Setpoint"};
     127             : 
     128         771 :     void CheckIfAnyEMS(EnergyPlusData &state)
     129             :     {
     130             : 
     131             :         // SUBROUTINE INFORMATION:
     132             :         //       AUTHOR         Brent Griffith
     133             :         //       DATE WRITTEN   April 2009
     134             :         //       MODIFIED       Rui Zhang February 2010
     135             :         //       RE-ENGINEERED  na
     136             : 
     137             :         // PURPOSE OF THIS SUBROUTINE:
     138             :         // Determine if EMS is used in model and set flag
     139             :         // This needs to be checked early so calls to SetupEMSActuator
     140             :         // can be avoided if there is no EMS in model.
     141             :         // We cannot do error checking during the full get input until later in the simulation.
     142             : 
     143             :         // METHODOLOGY EMPLOYED:
     144             :         // Get number of EMS-related input objects and set
     145             :         // global logical AnyEnergyManagementSystemInModel
     146             : 
     147             :         // Using/Aliasing
     148             :         using General::ScanForReports;
     149             : 
     150             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     151             : 
     152        1542 :         std::string cCurrentModuleObject;
     153             : 
     154         771 :         cCurrentModuleObject = "EnergyManagementSystem:Sensor";
     155         771 :         state.dataRuntimeLang->NumSensors = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     156             : 
     157         771 :         cCurrentModuleObject = "EnergyManagementSystem:Actuator";
     158         771 :         state.dataRuntimeLang->numActuatorsUsed = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     159             : 
     160         771 :         cCurrentModuleObject = "EnergyManagementSystem:ProgramCallingManager";
     161         771 :         state.dataRuntimeLang->NumProgramCallManagers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     162             : 
     163         771 :         cCurrentModuleObject = "EnergyManagementSystem:Program";
     164         771 :         state.dataRuntimeLang->NumErlPrograms = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     165             : 
     166         771 :         cCurrentModuleObject = "EnergyManagementSystem:Subroutine";
     167         771 :         state.dataRuntimeLang->NumErlSubroutines = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     168             : 
     169         771 :         cCurrentModuleObject = "EnergyManagementSystem:GlobalVariable";
     170         771 :         state.dataRuntimeLang->NumUserGlobalVariables = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     171             : 
     172         771 :         cCurrentModuleObject = "EnergyManagementSystem:OutputVariable";
     173         771 :         state.dataRuntimeLang->NumEMSOutputVariables = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     174             : 
     175         771 :         cCurrentModuleObject = "EnergyManagementSystem:MeteredOutputVariable";
     176         771 :         state.dataRuntimeLang->NumEMSMeteredOutputVariables =
     177         771 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     178             : 
     179         771 :         cCurrentModuleObject = "EnergyManagementSystem:CurveOrTableIndexVariable";
     180         771 :         state.dataRuntimeLang->NumEMSCurveIndices = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     181             : 
     182         771 :         cCurrentModuleObject = "ExternalInterface:Variable";
     183         771 :         state.dataRuntimeLang->NumExternalInterfaceGlobalVariables =
     184         771 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     185             : 
     186             :         // added for FMUImport
     187         771 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Variable";
     188         771 :         state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportGlobalVariables =
     189         771 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     190             : 
     191             :         // added for FMUExport
     192         771 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitExport:To:Variable";
     193         771 :         state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportGlobalVariables =
     194         771 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     195             : 
     196         771 :         cCurrentModuleObject = "ExternalInterface:Actuator";
     197         771 :         state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed =
     198         771 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     199             : 
     200             :         // added for FMUImport
     201         771 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Actuator";
     202         771 :         state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed =
     203         771 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     204             : 
     205             :         // added for FMUExport
     206         771 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitExport:To:Actuator";
     207         771 :         state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportActuatorsUsed =
     208         771 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     209             : 
     210         771 :         cCurrentModuleObject = "EnergyManagementSystem:ConstructionIndexVariable";
     211         771 :         state.dataRuntimeLang->NumEMSConstructionIndices = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     212             : 
     213         771 :         cCurrentModuleObject = "Output:EnergyManagementSystem";
     214         771 :         int NumOutputEMSs = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     215             : 
     216             :         // Python plugin instances also count since actuators need to be set up for them
     217         771 :         int numPythonPlugins = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PythonPlugin:Instance");
     218         771 :         int numActiveCallbacks = PluginManagement::PluginManager::numActiveCallbacks(state);
     219             : 
     220             :         // added for FMU
     221        2313 :         if ((state.dataRuntimeLang->NumSensors + state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumProgramCallManagers +
     222        2313 :              state.dataRuntimeLang->NumErlPrograms + state.dataRuntimeLang->NumErlSubroutines + state.dataRuntimeLang->NumUserGlobalVariables +
     223        2313 :              state.dataRuntimeLang->NumEMSOutputVariables + state.dataRuntimeLang->NumEMSCurveIndices +
     224        2313 :              state.dataRuntimeLang->NumExternalInterfaceGlobalVariables + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
     225        2313 :              state.dataRuntimeLang->NumEMSConstructionIndices + state.dataRuntimeLang->NumEMSMeteredOutputVariables +
     226        1542 :              state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed +
     227        1542 :              state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportGlobalVariables +
     228        1542 :              state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportActuatorsUsed +
     229        1542 :              state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportGlobalVariables + NumOutputEMSs + numPythonPlugins +
     230         771 :              numActiveCallbacks) > 0) {
     231          71 :             state.dataGlobal->AnyEnergyManagementSystemInModel = true;
     232             :         } else {
     233         700 :             state.dataGlobal->AnyEnergyManagementSystemInModel = false;
     234             :         }
     235             : 
     236         771 :         state.dataGlobal->AnyEnergyManagementSystemInModel =
     237         771 :             state.dataGlobal->AnyEnergyManagementSystemInModel || state.dataGlobal->externalHVACManager;
     238             : 
     239         771 :         if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
     240             : 
     241          71 :             ScanForReports(state, "EnergyManagementSystem", state.dataRuntimeLang->OutputEDDFile);
     242          71 :             if (state.dataRuntimeLang->OutputEDDFile) {
     243             :                 // open up output file for EMS EDD file  EMS Data and Debug
     244          39 :                 state.files.edd.ensure_open(state, "CheckIFAnyEMS", state.files.outputControl.edd);
     245             :             }
     246             :         } else {
     247         700 :             ScanForReports(state, "EnergyManagementSystem", state.dataRuntimeLang->OutputEDDFile);
     248         700 :             if (state.dataRuntimeLang->OutputEDDFile) {
     249           0 :                 ShowWarningError(state, "CheckIFAnyEMS: No EnergyManagementSystem has been set up in the input file but output is requested.");
     250           0 :                 ShowContinueError(state,
     251             :                                   "No EDD file will be produced. Refer to EMS Application Guide and/or InputOutput Reference to set up your "
     252             :                                   "EnergyManagementSystem.");
     253             :             }
     254             :         }
     255         771 :     }
     256             : 
     257             :     // MODULE SUBROUTINES:
     258             : 
     259    32565618 :     void ManageEMS(EnergyPlusData &state,
     260             :                    EMSCallFrom const iCalledFrom,         // indicates where subroutine was called from, parameters in DataGlobals.
     261             :                    bool &anyProgramRan,                   // true if any Erl programs ran for this call
     262             :                    Optional_int_const ProgramManagerToRun // specific program manager to run
     263             :     )
     264             :     {
     265             : 
     266             :         // SUBROUTINE INFORMATION:
     267             :         //       AUTHOR         Peter Graham Ellis
     268             :         //       DATE WRITTEN   June 2006
     269             :         //       MODIFIED       na
     270             :         //       RE-ENGINEERED  Brent Griffith, April 2009
     271             :         //                      added calling point argument and logic.
     272             :         //                      Collapsed SimulateEMS into this routine
     273             : 
     274             :         // PURPOSE OF THIS SUBROUTINE:
     275             : 
     276             :         // METHODOLOGY EMPLOYED:
     277             :         // Standard EnergyPlus methodology.
     278             : 
     279             :         // Using/Aliasing
     280             :         using OutputProcessor::MeterType;
     281             :         using OutputProcessor::RealVariables;
     282             :         using OutputProcessor::RealVariableType;
     283             :         using RuntimeLanguageProcessor::BeginEnvrnInitializeRuntimeLanguage;
     284             :         using RuntimeLanguageProcessor::EvaluateStack;
     285             : 
     286             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     287             : 
     288             :         int ErlVariableNum;    // local index
     289             :         int ProgramManagerNum; // local index and loop
     290             :         int ErlProgramNum;     // local index
     291             :         int ActuatorUsedLoop;  // local loop
     292             :         int EMSActuatorVariableNum;
     293             : 
     294             :         int tmpInteger;
     295             :         //  INTEGER  :: ProgramNum
     296             : 
     297    32565618 :         anyProgramRan = false;
     298    64062194 :         if (!state.dataGlobal->AnyEnergyManagementSystemInModel) return; // quick return if nothing to do
     299             : 
     300     4116641 :         if (iCalledFrom == EMSCallFrom::BeginNewEnvironment) {
     301         139 :             BeginEnvrnInitializeRuntimeLanguage(state);
     302         139 :             PluginManagement::onBeginEnvironment(state);
     303             :         }
     304             : 
     305     4116641 :         InitEMS(state, iCalledFrom);
     306             : 
     307             :         // also call plugins and callbacks here for convenience
     308     4116641 :         bool anyPluginsOrCallbacksRan = false;
     309     4116641 :         if (iCalledFrom != EMSCallFrom::UserDefinedComponentModel) { // don't run user-defined component plugins this way
     310     3685788 :             PluginManagement::runAnyRegisteredCallbacks(state, iCalledFrom, anyPluginsOrCallbacksRan);
     311     3685788 :             if (anyPluginsOrCallbacksRan) {
     312      244253 :                 anyProgramRan = true;
     313             :             }
     314             :         }
     315             : 
     316     4116641 :         if (iCalledFrom == EMSCallFrom::SetupSimulation) {
     317          69 :             ProcessEMSInput(state, true);
     318          69 :             return;
     319             :         }
     320             : 
     321             :         // Run the Erl programs depending on calling point.
     322             : 
     323     4116572 :         if (iCalledFrom != EMSCallFrom::UserDefinedComponentModel) {
     324    25311927 :             for (ProgramManagerNum = 1; ProgramManagerNum <= state.dataRuntimeLang->NumProgramCallManagers; ++ProgramManagerNum) {
     325             : 
     326    21626209 :                 if (state.dataRuntimeLang->EMSProgramCallManager(ProgramManagerNum).CallingPoint == iCalledFrom) {
     327     3924489 :                     for (ErlProgramNum = 1; ErlProgramNum <= state.dataRuntimeLang->EMSProgramCallManager(ProgramManagerNum).NumErlPrograms;
     328             :                          ++ErlProgramNum) {
     329     2028502 :                         EvaluateStack(state, state.dataRuntimeLang->EMSProgramCallManager(ProgramManagerNum).ErlProgramARR(ErlProgramNum));
     330     2028501 :                         anyProgramRan = true;
     331             :                     }
     332             :                 }
     333             :             }
     334             :         } else { // call specific program manager
     335      430853 :             if (present(ProgramManagerToRun)) {
     336     1302828 :                 for (ErlProgramNum = 1; ErlProgramNum <= state.dataRuntimeLang->EMSProgramCallManager(ProgramManagerToRun).NumErlPrograms;
     337             :                      ++ErlProgramNum) {
     338      871975 :                     EvaluateStack(state, state.dataRuntimeLang->EMSProgramCallManager(ProgramManagerToRun).ErlProgramARR(ErlProgramNum));
     339      871975 :                     anyProgramRan = true;
     340             :                 }
     341             :             }
     342             :         }
     343             : 
     344     4116571 :         if (iCalledFrom == EMSCallFrom::ExternalInterface) {
     345           0 :             anyProgramRan = true;
     346             :         }
     347             : 
     348     4116571 :         if (!anyProgramRan) return;
     349             : 
     350             :         // Set actuated variables with new values
     351    24405149 :         for (ActuatorUsedLoop = 1;
     352    73215447 :              ActuatorUsedLoop <= state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
     353    48810298 :                                      state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed +
     354    24405149 :                                      state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportActuatorsUsed;
     355             :              ++ActuatorUsedLoop) {
     356    23336108 :             ErlVariableNum = state.dataRuntimeLang->EMSActuatorUsed(ActuatorUsedLoop).ErlVariableNum;
     357    23336108 :             if (ErlVariableNum <= 0) continue; // this can happen for good reason during sizing
     358             : 
     359    23336108 :             EMSActuatorVariableNum = state.dataRuntimeLang->EMSActuatorUsed(ActuatorUsedLoop).ActuatorVariableNum;
     360    23336108 :             if (EMSActuatorVariableNum <= 0) continue; // this can happen for good reason during sizing
     361             : 
     362    23249007 :             if (state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value.Type == Value::Null) {
     363     2412781 :                 *state.dataRuntimeLang->EMSActuatorAvailable(EMSActuatorVariableNum).Actuated = false;
     364             :             } else {
     365             :                 // Set the value and the actuated flag remotely on the actuated object via the pointer
     366    20836226 :                 switch (state.dataRuntimeLang->EMSActuatorAvailable(EMSActuatorVariableNum).PntrVarTypeUsed) {
     367    20757893 :                 case PtrDataType::Real: {
     368    20757893 :                     *state.dataRuntimeLang->EMSActuatorAvailable(EMSActuatorVariableNum).Actuated = true;
     369    20757893 :                     *state.dataRuntimeLang->EMSActuatorAvailable(EMSActuatorVariableNum).RealValue =
     370    20757893 :                         state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value.Number;
     371    20757893 :                 } break;
     372       78333 :                 case PtrDataType::Integer: {
     373       78333 :                     *state.dataRuntimeLang->EMSActuatorAvailable(EMSActuatorVariableNum).Actuated = true;
     374       78333 :                     tmpInteger = std::floor(state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value.Number);
     375       78333 :                     *state.dataRuntimeLang->EMSActuatorAvailable(EMSActuatorVariableNum).IntValue = tmpInteger;
     376       78333 :                 } break;
     377           0 :                 case PtrDataType::Logical: {
     378           0 :                     *state.dataRuntimeLang->EMSActuatorAvailable(EMSActuatorVariableNum).Actuated = true;
     379           0 :                     if (state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value.Number == 0.0) {
     380           0 :                         *state.dataRuntimeLang->EMSActuatorAvailable(EMSActuatorVariableNum).LogValue = false;
     381           0 :                     } else if (state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value.Number == 1.0) {
     382           0 :                         *state.dataRuntimeLang->EMSActuatorAvailable(EMSActuatorVariableNum).LogValue = true;
     383             :                     } else {
     384           0 :                         *state.dataRuntimeLang->EMSActuatorAvailable(EMSActuatorVariableNum).LogValue = false;
     385             :                     }
     386           0 :                 } break;
     387           0 :                 default:
     388           0 :                     break;
     389             :                 }
     390             :             }
     391             :         }
     392             : 
     393     1069041 :         ReportEMS(state);
     394             :     }
     395             : 
     396     4116641 :     void InitEMS(EnergyPlusData &state, EMSCallFrom const iCalledFrom) // indicates where subroutine was called from, parameters in DataGlobals.
     397             :     {
     398             : 
     399             :         // SUBROUTINE INFORMATION:
     400             :         //       AUTHOR         Brent Griffith
     401             :         //       DATE WRITTEN   May 2009
     402             :         //       MODIFIED       na
     403             :         //       RE-ENGINEERED  na
     404             : 
     405             :         // PURPOSE OF THIS SUBROUTINE:
     406             :         // collect routines needed to initialize EMS
     407             : 
     408             :         // Using/Aliasing
     409             :         using RuntimeLanguageProcessor::InitializeRuntimeLanguage;
     410             :         using RuntimeLanguageProcessor::SetErlValueNumber;
     411             :         using ScheduleManager::GetCurrentScheduleValue;
     412             : 
     413             :         int InternalVarUsedNum; // local index and loop
     414             :         int InternVarAvailNum;  // local index
     415             :         int SensorNum;          // local loop and index
     416             :         int ErlVariableNum;     // local index
     417             :         Real64 tmpReal;         // temporary local integer
     418             : 
     419     4116641 :         if (state.dataEMSMgr->GetEMSUserInput) {
     420          71 :             SetupZoneInfoAsInternalDataAvail(state);
     421          71 :             SetupWindowShadingControlActuators(state);
     422          71 :             SetupSurfaceConvectionActuators(state);
     423          71 :             SetupSurfaceConstructionActuators(state);
     424          71 :             SetupSurfaceOutdoorBoundaryConditionActuators(state);
     425          71 :             SetupZoneOutdoorBoundaryConditionActuators(state);
     426          71 :             GetEMSInput(state);
     427          71 :             state.dataEMSMgr->GetEMSUserInput = false;
     428             :         }
     429             : 
     430     4116641 :         if (!state.dataZoneCtrls->GetZoneAirStatsInputFlag && !state.dataEMSMgr->ZoneThermostatActuatorsHaveBeenSetup) {
     431          71 :             SetupThermostatActuators(state);
     432          71 :             state.dataEMSMgr->ZoneThermostatActuatorsHaveBeenSetup = true;
     433             :         }
     434             : 
     435             :         // need to delay setup of HVAC actuator until after the systems input has been processed (if present)
     436     4116641 :         if (state.dataEMSMgr->FinishProcessingUserInput && !state.dataGlobal->DoingSizing && !state.dataGlobal->KickOffSimulation) {
     437          69 :             SetupNodeSetPointsAsActuators(state);
     438          69 :             SetupPrimaryAirSystemAvailMgrAsActuators(state);
     439             :             //    CALL SetupWindowShadingControlActuators !this is too late for including in sizing, moved to GetEMSUserInput
     440             :             //    CALL SetupThermostatActuators !this is too late for including in sizing, moved to GetEMSUserInput
     441             :             //    CALL SetupSurfaceConvectionActuators !this is too late for including in sizing, moved to GetEMSUserInput
     442          69 :             state.dataEMSMgr->FinishProcessingUserInput = false;
     443             :         }
     444             : 
     445     4116641 :         InitializeRuntimeLanguage(state);
     446             : 
     447     4116641 :         if ((state.dataGlobal->BeginEnvrnFlag) || (iCalledFrom == EMSCallFrom::ZoneSizing) || (iCalledFrom == EMSCallFrom::SystemSizing) ||
     448             :             (iCalledFrom == EMSCallFrom::UserDefinedComponentModel)) {
     449             : 
     450             :             // another pass at trying to setup input data.
     451      441366 :             if (state.dataEMSMgr->FinishProcessingUserInput) {
     452        6368 :                 ProcessEMSInput(state, false);
     453             :             }
     454             : 
     455             :             // update internal data variables being used by Erl
     456    26167192 :             for (InternalVarUsedNum = 1; InternalVarUsedNum <= state.dataRuntimeLang->NumInternalVariablesUsed; ++InternalVarUsedNum) {
     457    25725826 :                 ErlVariableNum = state.dataRuntimeLang->EMSInternalVarsUsed(InternalVarUsedNum).ErlVariableNum;
     458    25725826 :                 InternVarAvailNum = state.dataRuntimeLang->EMSInternalVarsUsed(InternalVarUsedNum).InternVarNum;
     459    25725826 :                 if (InternVarAvailNum <= 0) continue; // sometimes executes before completely finished setting up.
     460    25717872 :                 if (ErlVariableNum <= 0) continue;
     461             : 
     462    25717872 :                 switch (state.dataRuntimeLang->EMSInternalVarsAvailable(InternVarAvailNum).PntrVarTypeUsed) {
     463    25717872 :                 case PtrDataType::Real: {
     464    51435744 :                     state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value =
     465    77153616 :                         SetErlValueNumber(*state.dataRuntimeLang->EMSInternalVarsAvailable(InternVarAvailNum).RealValue);
     466    25717872 :                 } break;
     467           0 :                 case PtrDataType::Integer: {
     468           0 :                     tmpReal = double(*state.dataRuntimeLang->EMSInternalVarsAvailable(InternVarAvailNum).IntValue);
     469           0 :                     state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value = SetErlValueNumber(tmpReal);
     470           0 :                 } break;
     471           0 :                 default:
     472           0 :                     break;
     473             :                 }
     474             :             }
     475             :         }
     476             : 
     477             :         // Update sensors with current data
     478    87530108 :         for (SensorNum = 1; SensorNum <= state.dataRuntimeLang->NumSensors; ++SensorNum) {
     479    83413467 :             ErlVariableNum = state.dataRuntimeLang->Sensor(SensorNum).VariableNum;
     480    83413467 :             if ((ErlVariableNum > 0) && (state.dataRuntimeLang->Sensor(SensorNum).Index > 0)) {
     481    71117627 :                 if (state.dataRuntimeLang->Sensor(SensorNum).SchedNum == 0) { // not a schedule so get from output processor
     482             : 
     483   279463896 :                     state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value = SetErlValueNumber(
     484             :                         GetInternalVariableValue(
     485   139731948 :                             state, state.dataRuntimeLang->Sensor(SensorNum).VariableType, state.dataRuntimeLang->Sensor(SensorNum).Index),
     486   139731948 :                         state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value);
     487             :                 } else { // schedule so use schedule service
     488             : 
     489     2503306 :                     state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value =
     490     2503306 :                         SetErlValueNumber(GetCurrentScheduleValue(state, state.dataRuntimeLang->Sensor(SensorNum).SchedNum),
     491     2503306 :                                           state.dataRuntimeLang->ErlVariable(ErlVariableNum).Value);
     492             :                 }
     493             :             }
     494             :         }
     495     4116641 :     }
     496             : 
     497     1069041 :     void ReportEMS(EnergyPlusData &state)
     498             :     {
     499             : 
     500             :         // SUBROUTINE INFORMATION:
     501             :         //       AUTHOR         Peter Graham Ellis
     502             :         //       DATE WRITTEN   June 2006
     503             :         //       MODIFIED       na
     504             :         //       RE-ENGINEERED  na
     505             :         // PURPOSE OF THIS SUBROUTINE:
     506             :         // Calculates report variables.
     507             : 
     508             :         // METHODOLOGY EMPLOYED:
     509             :         // Standard EnergyPlus methodology.
     510             : 
     511     1069041 :         RuntimeLanguageProcessor::ReportRuntimeLanguage(state);
     512     1069041 :     }
     513             : 
     514          71 :     void GetEMSInput(EnergyPlusData &state)
     515             :     {
     516             : 
     517             :         // SUBROUTINE INFORMATION:
     518             :         //       AUTHOR         Peter Graham Ellis
     519             :         //       DATE WRITTEN   June 2006
     520             :         //       MODIFIED       BG April 2009, finishing, renaming, etc.
     521             :         //       RE-ENGINEERED  na
     522             : 
     523             :         // PURPOSE OF THIS SUBROUTINE:
     524             :         // Gets the EMS input from the input file.
     525             : 
     526             :         // METHODOLOGY EMPLOYED:
     527             :         // Standard EnergyPlus methodology.
     528             : 
     529             :         // Using/Aliasing
     530             :         using RuntimeLanguageProcessor::ExternalInterfaceInitializeErlVariable;
     531             :         using RuntimeLanguageProcessor::FindEMSVariable;
     532             :         using RuntimeLanguageProcessor::InitializeRuntimeLanguage;
     533             :         using RuntimeLanguageProcessor::NewEMSVariable;
     534             :         using RuntimeLanguageProcessor::SetErlValueNumber;
     535             : 
     536             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     537             : 
     538             :         int StackNum;
     539             :         int SensorNum;
     540             :         int ActuatorNum;
     541             :         int ActuatorVariableNum;
     542             :         int VariableNum; // local do loop index
     543             :         int NumAlphas;   // Number of elements in the alpha array
     544             :         int NumNums;     // Number of elements in the numeric array
     545             :         int AlphaNum;
     546             :         int IOStat; // IO Status when calling get input subroutine
     547          71 :         bool ErrorsFound(false);
     548         142 :         Array1D_string cAlphaFieldNames;
     549         142 :         Array1D_string cNumericFieldNames;
     550         142 :         Array1D_bool lNumericFieldBlanks;
     551         142 :         Array1D_bool lAlphaFieldBlanks;
     552         142 :         Array1D_string cAlphaArgs;
     553         142 :         Array1D<Real64> rNumericArgs;
     554         142 :         std::string cCurrentModuleObject;
     555             :         OutputProcessor::VariableType VarType;
     556             :         int VarIndex;
     557             :         bool FoundObjectType;
     558             :         bool FoundObjectName;
     559             :         bool FoundActuatorName;
     560             :         int NumErlProgramsThisManager; // temporary size of Erl programs in EMSProgramCallManager
     561             :         int ManagerProgramNum;         // index counter for Erl programs inside EMSProgramCallManager
     562             :         int CallManagerNum;            // loop counter for EMSProgramCallManager structure
     563             :         int InternVarNum;              // do loop counter for internal variables used (outer)
     564             :         int InternalVarAvailNum;       // do loop counter for internal variables available (inner)
     565             :         int Loop;                      // do loop counter
     566          71 :         int MaxNumAlphas(0);           // argument for call to GetObjectDefMaxArgs
     567          71 :         int MaxNumNumbers(0);          // argument for call to GetObjectDefMaxArgs
     568          71 :         int TotalArgs(0);              // argument for call to GetObjectDefMaxArgs
     569             :         bool errFlag;
     570             : 
     571          71 :         cCurrentModuleObject = "EnergyManagementSystem:Sensor";
     572          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     573          71 :         MaxNumNumbers = NumNums;
     574          71 :         MaxNumAlphas = NumAlphas;
     575          71 :         cCurrentModuleObject = "EnergyManagementSystem:Actuator";
     576          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     577          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     578          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     579          71 :         cCurrentModuleObject = "EnergyManagementSystem:ProgramCallingManager";
     580          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     581          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     582          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     583          71 :         cCurrentModuleObject = "EnergyManagementSystem:Program";
     584          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     585          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     586          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     587          71 :         cCurrentModuleObject = "EnergyManagementSystem:Subroutine";
     588          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     589          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     590          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     591          71 :         cCurrentModuleObject = "EnergyManagementSystem:OutputVariable";
     592          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     593          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     594          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     595          71 :         cCurrentModuleObject = "ExternalInterface:Variable";
     596          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     597          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     598          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     599          71 :         cCurrentModuleObject = "ExternalInterface:Actuator";
     600          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     601          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     602          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     603          71 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Variable";
     604          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     605          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     606          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     607          71 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Actuator";
     608          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     609          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     610          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     611          71 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitExport:To:Variable";
     612          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     613          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     614          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     615          71 :         cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitExport:To:Actuator";
     616          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     617          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     618          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     619             :         //  cCurrentModuleObject = 'EnergyManagementSystem:Sensor'
     620             :         //  CALL state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(cCurrentModuleObject,TotalArgs,NumAlphas,NumNums)
     621             :         //  MaxNumNumbers=MAX(MaxNumNumbers,NumNums)
     622             :         //  MaxNumAlphas=MAX(MaxNumAlphas,NumAlphas)
     623          71 :         cCurrentModuleObject = "EnergyManagementSystem:GlobalVariable";
     624          71 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cCurrentModuleObject, TotalArgs, NumAlphas, NumNums);
     625          71 :         MaxNumNumbers = max(MaxNumNumbers, NumNums);
     626          71 :         MaxNumAlphas = max(MaxNumAlphas, NumAlphas);
     627             : 
     628          71 :         cAlphaFieldNames.allocate(MaxNumAlphas);
     629          71 :         cAlphaArgs.allocate(MaxNumAlphas);
     630          71 :         lAlphaFieldBlanks.dimension(MaxNumAlphas, false);
     631          71 :         cNumericFieldNames.allocate(MaxNumNumbers);
     632          71 :         rNumericArgs.dimension(MaxNumNumbers, 0.0);
     633          71 :         lNumericFieldBlanks.dimension(MaxNumNumbers, false);
     634             : 
     635          71 :         cCurrentModuleObject = "EnergyManagementSystem:Sensor";
     636          71 :         if (state.dataRuntimeLang->NumSensors > 0) {
     637          50 :             state.dataRuntimeLang->Sensor.allocate(state.dataRuntimeLang->NumSensors);
     638             : 
     639        1852 :             for (SensorNum = 1; SensorNum <= state.dataRuntimeLang->NumSensors; ++SensorNum) {
     640        1802 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     641             :                                                                          cCurrentModuleObject,
     642             :                                                                          SensorNum,
     643             :                                                                          cAlphaArgs,
     644             :                                                                          NumAlphas,
     645             :                                                                          rNumericArgs,
     646             :                                                                          NumNums,
     647             :                                                                          IOStat,
     648             :                                                                          lNumericFieldBlanks,
     649             :                                                                          lAlphaFieldBlanks,
     650             :                                                                          cAlphaFieldNames,
     651             :                                                                          cNumericFieldNames);
     652        1802 :                 UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     653        1802 :                 ValidateEMSVariableName(state, cCurrentModuleObject, cAlphaArgs(1), cAlphaFieldNames(1), errFlag, ErrorsFound);
     654        1802 :                 if (!errFlag) {
     655        1802 :                     state.dataRuntimeLang->Sensor(SensorNum).Name = cAlphaArgs(1);
     656             : 
     657             :                     // really needs to check for conflicts with program and function names too...done later
     658        1802 :                     VariableNum = FindEMSVariable(state, cAlphaArgs(1), 0);
     659             : 
     660        1802 :                     if (VariableNum > 0) {
     661           0 :                         ShowSevereError(state, "Invalid " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     662           0 :                         ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + cAlphaArgs(1));
     663           0 :                         ShowContinueError(state, "Object name conflicts with a global variable name in EMS");
     664           0 :                         ErrorsFound = true;
     665             :                     } else {
     666        1802 :                         VariableNum = NewEMSVariable(state, cAlphaArgs(1), 0);
     667        1802 :                         state.dataRuntimeLang->Sensor(SensorNum).VariableNum = VariableNum;
     668        1802 :                         state.dataRuntimeLang->ErlVariable(VariableNum).Value.initialized = true;
     669             :                     }
     670             :                 }
     671             : 
     672        1802 :                 if (cAlphaArgs(2) == "*") cAlphaArgs(2).clear();
     673        1802 :                 state.dataRuntimeLang->Sensor(SensorNum).UniqueKeyName = cAlphaArgs(2);
     674        1802 :                 state.dataRuntimeLang->Sensor(SensorNum).OutputVarName = cAlphaArgs(3);
     675             : 
     676        1802 :                 VarIndex = GetMeterIndex(state, cAlphaArgs(3));
     677        1802 :                 if (VarIndex > 0) {
     678          11 :                     if (!lAlphaFieldBlanks(2)) {
     679           0 :                         ShowWarningError(state, "Unused" + cAlphaFieldNames(2) + '=' + cAlphaArgs(2));
     680           0 :                         ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + cAlphaArgs(1));
     681           0 :                         ShowContinueError(state, "Meter Name found; Key Name will be ignored"); // why meters have no keys..
     682             :                     } else {
     683          11 :                         state.dataRuntimeLang->Sensor(SensorNum).VariableType = OutputProcessor::VariableType::Meter;
     684          11 :                         state.dataRuntimeLang->Sensor(SensorNum).Index = VarIndex;
     685          11 :                         state.dataRuntimeLang->Sensor(SensorNum).CheckedOkay = true;
     686             :                     }
     687             :                 } else {
     688             :                     // Search for variable names
     689        1791 :                     GetVariableTypeAndIndex(state, cAlphaArgs(3), cAlphaArgs(2), VarType, VarIndex);
     690        1791 :                     if (VarType != OutputProcessor::VariableType::NotFound) {
     691         531 :                         state.dataRuntimeLang->Sensor(SensorNum).VariableType = VarType;
     692         531 :                         if (VarIndex != 0) {
     693         531 :                             state.dataRuntimeLang->Sensor(SensorNum).Index = VarIndex;
     694         531 :                             state.dataRuntimeLang->Sensor(SensorNum).CheckedOkay = true;
     695             :                         }
     696             :                     }
     697             :                 }
     698             : 
     699             :             } // SensorNum
     700             :         }
     701             : 
     702          71 :         cCurrentModuleObject = "EnergyManagementSystem:Actuator";
     703             : 
     704         213 :         if (state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
     705         142 :                 state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed +
     706         142 :                 state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportActuatorsUsed >
     707             :             0) {
     708         176 :             state.dataRuntimeLang->EMSActuatorUsed.allocate(state.dataRuntimeLang->numActuatorsUsed +
     709          88 :                                                             state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
     710          44 :                                                             state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed +
     711         132 :                                                             state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportActuatorsUsed);
     712        2223 :             for (ActuatorNum = 1; ActuatorNum <= state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
     713        1482 :                                                      state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed +
     714         741 :                                                      state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportActuatorsUsed;
     715             :                  ++ActuatorNum) {
     716             :                 // If we process the ExternalInterface actuators, all we need to do is to change the
     717             :                 // name of the module object, and shift the ActuatorNum in GetObjectItem
     718         697 :                 if (ActuatorNum <= state.dataRuntimeLang->numActuatorsUsed) {
     719         696 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
     720             :                                                                              cCurrentModuleObject,
     721             :                                                                              ActuatorNum,
     722             :                                                                              cAlphaArgs,
     723             :                                                                              NumAlphas,
     724             :                                                                              rNumericArgs,
     725             :                                                                              NumNums,
     726             :                                                                              IOStat,
     727             :                                                                              lNumericFieldBlanks,
     728             :                                                                              lAlphaFieldBlanks,
     729             :                                                                              cAlphaFieldNames,
     730             :                                                                              cNumericFieldNames);
     731           2 :                 } else if (ActuatorNum > state.dataRuntimeLang->numActuatorsUsed &&
     732           1 :                            ActuatorNum <= state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed) {
     733           0 :                     cCurrentModuleObject = "ExternalInterface:Actuator";
     734           0 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
     735             :                                                                              cCurrentModuleObject,
     736           0 :                                                                              ActuatorNum - state.dataRuntimeLang->numActuatorsUsed,
     737             :                                                                              cAlphaArgs,
     738             :                                                                              NumAlphas,
     739             :                                                                              rNumericArgs,
     740             :                                                                              NumNums,
     741             :                                                                              IOStat,
     742             :                                                                              lNumericFieldBlanks,
     743             :                                                                              lAlphaFieldBlanks,
     744             :                                                                              cAlphaFieldNames,
     745             :                                                                              cNumericFieldNames);
     746           2 :                 } else if (ActuatorNum > state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed &&
     747           2 :                            ActuatorNum <= (state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
     748           1 :                                            state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed)) {
     749           1 :                     cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Actuator";
     750           2 :                     state.dataInputProcessing->inputProcessor->getObjectItem(state,
     751             :                                                                              cCurrentModuleObject,
     752           1 :                                                                              ActuatorNum - state.dataRuntimeLang->numActuatorsUsed -
     753           1 :                                                                                  state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed,
     754             :                                                                              cAlphaArgs,
     755             :                                                                              NumAlphas,
     756             :                                                                              rNumericArgs,
     757             :                                                                              NumNums,
     758             :                                                                              IOStat,
     759             :                                                                              lNumericFieldBlanks,
     760             :                                                                              lAlphaFieldBlanks,
     761             :                                                                              cAlphaFieldNames,
     762             :                                                                              cNumericFieldNames);
     763           0 :                 } else if (ActuatorNum > state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
     764           0 :                                              state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed &&
     765           0 :                            ActuatorNum <= state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
     766           0 :                                               state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed +
     767           0 :                                               state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportActuatorsUsed) {
     768           0 :                     cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitExport:To:Actuator";
     769           0 :                     state.dataInputProcessing->inputProcessor->getObjectItem(
     770             :                         state,
     771             :                         cCurrentModuleObject,
     772           0 :                         ActuatorNum - state.dataRuntimeLang->numActuatorsUsed - state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed -
     773           0 :                             state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed,
     774             :                         cAlphaArgs,
     775             :                         NumAlphas,
     776             :                         rNumericArgs,
     777             :                         NumNums,
     778             :                         IOStat,
     779             :                         lNumericFieldBlanks,
     780             :                         lAlphaFieldBlanks,
     781             :                         cAlphaFieldNames,
     782             :                         cNumericFieldNames);
     783             :                 }
     784             : 
     785         697 :                 UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     786         697 :                 ValidateEMSVariableName(state, cCurrentModuleObject, cAlphaArgs(1), cAlphaFieldNames(1), errFlag, ErrorsFound);
     787         697 :                 if (!errFlag) {
     788         697 :                     state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).Name = cAlphaArgs(1);
     789             : 
     790             :                     // really needs to check for conflicts with program and function names too...
     791         697 :                     VariableNum = FindEMSVariable(state, cAlphaArgs(1), 0);
     792             : 
     793         697 :                     if (VariableNum > 0) {
     794           0 :                         ShowSevereError(state, "Invalid " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     795           0 :                         ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + cAlphaArgs(1));
     796           0 :                         ShowContinueError(state, "Object name conflicts with a global variable name in EMS");
     797           0 :                         ErrorsFound = true;
     798             :                     } else {
     799         697 :                         VariableNum = NewEMSVariable(state, cAlphaArgs(1), 0);
     800         697 :                         state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ErlVariableNum = VariableNum;
     801             :                         // initialize Erl variable for actuator to null
     802         697 :                         state.dataRuntimeLang->ErlVariable(VariableNum).Value = state.dataRuntimeLang->Null;
     803         697 :                         if (ActuatorNum > state.dataRuntimeLang->numActuatorsUsed) {
     804             :                             // Initialize variables for the ExternalInterface variables
     805           1 :                             ExternalInterfaceInitializeErlVariable(state, VariableNum, SetErlValueNumber(rNumericArgs(1)), lNumericFieldBlanks(1));
     806             :                         }
     807             :                     }
     808             :                 }
     809             : 
     810             :                 // need to store characters to finish processing later (once available Actuators have all been setup)
     811         697 :                 state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ComponentTypeName = cAlphaArgs(3);
     812         697 :                 state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).UniqueIDName = cAlphaArgs(2);
     813         697 :                 state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ControlTypeName = cAlphaArgs(4);
     814             : 
     815         697 :                 FoundObjectType = false;
     816         697 :                 FoundObjectName = false;
     817         697 :                 FoundActuatorName = false;
     818      338562 :                 for (ActuatorVariableNum = 1; ActuatorVariableNum <= state.dataRuntimeLang->numEMSActuatorsAvailable; ++ActuatorVariableNum) {
     819      338221 :                     if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorAvailable(ActuatorVariableNum).ComponentTypeName,
     820      338221 :                                                     cAlphaArgs(3))) {
     821        6651 :                         FoundObjectType = true;
     822        6651 :                         if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorAvailable(ActuatorVariableNum).UniqueIDName,
     823        6651 :                                                         cAlphaArgs(2))) {
     824         358 :                             FoundObjectName = true;
     825         358 :                             if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorAvailable(ActuatorVariableNum).ControlTypeName,
     826         358 :                                                             cAlphaArgs(4))) {
     827         356 :                                 FoundActuatorName = true;
     828         356 :                                 break;
     829             :                             }
     830             :                         }
     831             :                     }
     832             :                 }
     833             : 
     834         697 :                 if (FoundActuatorName) {
     835             :                     // SetupNodeSetPointAsActuators has NOT been called yet at this point
     836         356 :                     state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ActuatorVariableNum = ActuatorVariableNum;
     837         356 :                     state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).CheckedOkay = true;
     838             : 
     839         356 :                     int nHandle = state.dataRuntimeLang->EMSActuatorAvailable(ActuatorVariableNum).handleCount;
     840         356 :                     if (nHandle > 0) {
     841           0 :                         EnergyPlus::ShowWarningError(state,
     842           0 :                                                      format("Seems like you already tried to get a Handle on this Actuator {}times.", nHandle));
     843           0 :                         EnergyPlus::ShowContinueError(state,
     844           0 :                                                       "Occurred for componentType='" +
     845           0 :                                                           state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ComponentTypeName + "', controlType='" +
     846           0 :                                                           state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ControlTypeName + "', uniqueKey='" +
     847           0 :                                                           state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).UniqueIDName + "'.");
     848           0 :                         EnergyPlus::ShowContinueError(state, "You should take note that there is a risk of overwritting.");
     849             :                     }
     850         356 :                     ++state.dataRuntimeLang->EMSActuatorAvailable(ActuatorVariableNum).handleCount;
     851             :                 }
     852             :             } // ActuatorNum
     853             :         }
     854             : 
     855          71 :         cCurrentModuleObject = "EnergyManagementSystem:InternalVariable";
     856          71 :         state.dataRuntimeLang->NumInternalVariablesUsed = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     857          71 :         if (state.dataRuntimeLang->NumInternalVariablesUsed > 0) {
     858          28 :             state.dataRuntimeLang->EMSInternalVarsUsed.allocate(state.dataRuntimeLang->NumInternalVariablesUsed);
     859             : 
     860         583 :             for (InternVarNum = 1; InternVarNum <= state.dataRuntimeLang->NumInternalVariablesUsed; ++InternVarNum) {
     861         555 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     862             :                                                                          cCurrentModuleObject,
     863             :                                                                          InternVarNum,
     864             :                                                                          cAlphaArgs,
     865             :                                                                          NumAlphas,
     866             :                                                                          rNumericArgs,
     867             :                                                                          NumNums,
     868             :                                                                          IOStat,
     869             :                                                                          lNumericFieldBlanks,
     870             :                                                                          lAlphaFieldBlanks,
     871             :                                                                          cAlphaFieldNames,
     872             :                                                                          cNumericFieldNames);
     873             : 
     874         555 :                 UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     875         555 :                 ValidateEMSVariableName(state, cCurrentModuleObject, cAlphaArgs(1), cAlphaFieldNames(1), errFlag, ErrorsFound);
     876         555 :                 if (!errFlag) {
     877         555 :                     state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).Name = cAlphaArgs(1);
     878         555 :                     VariableNum = FindEMSVariable(state, cAlphaArgs(1), 0);
     879         555 :                     if (VariableNum > 0) {
     880           0 :                         ShowSevereError(state, "Invalid " + cAlphaFieldNames(1) + '=' + cAlphaArgs(1));
     881           0 :                         ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + cAlphaArgs(1));
     882           0 :                         ShowContinueError(state, "Object name conflicts with a global variable name in EMS");
     883           0 :                         ErrorsFound = true;
     884             :                     } else {
     885         555 :                         VariableNum = NewEMSVariable(state, cAlphaArgs(1), 0);
     886         555 :                         state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).ErlVariableNum = VariableNum;
     887             :                     }
     888             : 
     889         555 :                     state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).UniqueIDName = cAlphaArgs(2);
     890         555 :                     state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).InternalDataTypeName = cAlphaArgs(3);
     891             : 
     892         555 :                     FoundObjectType = false;
     893         555 :                     FoundObjectName = false;
     894       53843 :                     for (InternalVarAvailNum = 1; InternalVarAvailNum <= state.dataRuntimeLang->numEMSInternalVarsAvailable; ++InternalVarAvailNum) {
     895       53543 :                         if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).DataTypeName,
     896       53543 :                                                         cAlphaArgs(3))) {
     897        3473 :                             FoundObjectType = true;
     898        3473 :                             if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).UniqueIDName,
     899        3473 :                                                             cAlphaArgs(2))) {
     900         255 :                                 FoundObjectName = true;
     901         255 :                                 break; // InternalVarAvailNum now holds needed index pointer
     902             :                             }
     903             :                         }
     904             :                     }
     905             : 
     906         555 :                     if (FoundObjectName) {
     907         255 :                         state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).InternVarNum = InternalVarAvailNum;
     908         255 :                         state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).CheckedOkay = true;
     909             :                     }
     910             :                 }
     911             :             }
     912             :         }
     913             : 
     914          71 :         InitializeRuntimeLanguage(state); // Loads built-in globals and functions, then performs GetInput for runtime language objects
     915             : 
     916          71 :         if (state.dataRuntimeLang->NumProgramCallManagers > 0) {
     917          52 :             cCurrentModuleObject = "EnergyManagementSystem:ProgramCallingManager";
     918          52 :             state.dataRuntimeLang->EMSProgramCallManager.allocate(state.dataRuntimeLang->NumProgramCallManagers);
     919             : 
     920         591 :             for (CallManagerNum = 1; CallManagerNum <= state.dataRuntimeLang->NumProgramCallManagers; ++CallManagerNum) {
     921             : 
     922         539 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     923             :                                                                          cCurrentModuleObject,
     924             :                                                                          CallManagerNum,
     925             :                                                                          cAlphaArgs,
     926             :                                                                          NumAlphas,
     927             :                                                                          rNumericArgs,
     928             :                                                                          NumNums,
     929             :                                                                          IOStat,
     930             :                                                                          lNumericFieldBlanks,
     931             :                                                                          lAlphaFieldBlanks,
     932             :                                                                          cAlphaFieldNames,
     933             :                                                                          cNumericFieldNames);
     934             : 
     935         539 :                 UtilityRoutines::IsNameEmpty(state, cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     936         539 :                 state.dataRuntimeLang->EMSProgramCallManager(CallManagerNum).Name = cAlphaArgs(1);
     937             : 
     938         539 :                 state.dataRuntimeLang->EMSProgramCallManager(CallManagerNum).CallingPoint =
     939        1078 :                     static_cast<EMSCallFrom>(getEnumerationValue(EMSCallFromNamesUC, UtilityRoutines::MakeUPPERCase(cAlphaArgs(2))));
     940         539 :                 ErrorsFound = ErrorsFound || (state.dataRuntimeLang->EMSProgramCallManager(CallManagerNum).CallingPoint == EMSCallFrom::Invalid);
     941             : 
     942         539 :                 NumErlProgramsThisManager = NumAlphas - 2;
     943         539 :                 state.dataRuntimeLang->EMSProgramCallManager(CallManagerNum).NumErlPrograms = NumErlProgramsThisManager;
     944         539 :                 state.dataRuntimeLang->EMSProgramCallManager(CallManagerNum).ErlProgramARR.allocate(NumErlProgramsThisManager);
     945         539 :                 ManagerProgramNum = 0;
     946        1161 :                 for (AlphaNum = 3; AlphaNum <= NumAlphas; ++AlphaNum) {
     947             :                     // find program name in Stack structure
     948         622 :                     if (lAlphaFieldBlanks(AlphaNum)) { // throw error
     949           0 :                         ShowSevereError(state, "Invalid " + cAlphaFieldNames(AlphaNum) + '=' + cAlphaArgs(AlphaNum));
     950           0 :                         ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + cAlphaArgs(1));
     951           0 :                         ShowContinueError(state, "Program names cannot be blank");
     952           0 :                         ErrorsFound = true;
     953             :                     }
     954             : 
     955         622 :                     StackNum = UtilityRoutines::FindItemInList(cAlphaArgs(AlphaNum), state.dataRuntimeLang->ErlStack);
     956             : 
     957         622 :                     if (StackNum > 0) { // found it
     958             :                         // check for duplicate and warn.
     959         909 :                         for (Loop = 1; Loop <= ManagerProgramNum; ++Loop) {
     960         287 :                             if (state.dataRuntimeLang->EMSProgramCallManager(CallManagerNum).ErlProgramARR(Loop) == StackNum) {
     961           0 :                                 ShowWarningError(state, "Duplicate " + cAlphaFieldNames(AlphaNum) + '=' + cAlphaArgs(AlphaNum));
     962           0 :                                 ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + cAlphaArgs(1));
     963           0 :                                 ShowContinueError(state, "Erl program appears more than once, and the simulation continues.");
     964             :                             }
     965             :                         }
     966             : 
     967         622 :                         ++ManagerProgramNum;
     968             : 
     969         622 :                         state.dataRuntimeLang->EMSProgramCallManager(CallManagerNum).ErlProgramARR(ManagerProgramNum) = StackNum;
     970             : 
     971             :                     } else {
     972           0 :                         ShowSevereError(state, "Invalid " + cAlphaFieldNames(AlphaNum) + '=' + cAlphaArgs(AlphaNum));
     973           0 :                         ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + cAlphaArgs(1));
     974           0 :                         ShowContinueError(state, "Program Name not found.");
     975           0 :                         ErrorsFound = true;
     976             :                     }
     977             :                 } // AlphaNum
     978             :             }
     979             : 
     980             :         } else { // no program calling manager in input
     981          19 :             if (state.dataRuntimeLang->NumErlPrograms > 0) {
     982           0 :                 cCurrentModuleObject = "EnergyManagementSystem:ProgramCallingManager";
     983           0 :                 ShowWarningError(state, "Energy Management System is missing input object " + cCurrentModuleObject);
     984           0 :                 ShowContinueError(state, "EnergyPlus Runtime Language programs need a calling manager to control when they get executed");
     985             :             }
     986             :         }
     987             : 
     988          71 :         cAlphaFieldNames.deallocate();
     989          71 :         cAlphaArgs.deallocate();
     990          71 :         lAlphaFieldBlanks.deallocate();
     991          71 :         cNumericFieldNames.deallocate();
     992          71 :         rNumericArgs.deallocate();
     993          71 :         lNumericFieldBlanks.deallocate();
     994             : 
     995          71 :         if (ErrorsFound) {
     996           0 :             ShowFatalError(state, "Errors found in getting Energy Management System input. Preceding condition causes termination.");
     997             :         }
     998          71 :     }
     999             : 
    1000        6437 :     void ProcessEMSInput(EnergyPlusData &state, bool const reportErrors) // .  If true, then report out errors ,otherwise setup what we can
    1001             :     {
    1002             : 
    1003             :         // SUBROUTINE INFORMATION:
    1004             :         //       AUTHOR         B. Griffith
    1005             :         //       DATE WRITTEN   May 2009
    1006             :         //       MODIFIED       na
    1007             :         //       RE-ENGINEERED  na
    1008             : 
    1009             :         // PURPOSE OF THIS SUBROUTINE:
    1010             :         // contains Some input checks that need to be deferred until later in the simulation
    1011             : 
    1012             :         // METHODOLOGY EMPLOYED:
    1013             :         // Loop over objects doing input checks.
    1014             :         // Had to break up get user input into two phases because
    1015             :         // the actuators can't be set up until all the HVAC systems are read in, sized, etc.
    1016             :         // but we also want to allow customizing sizing calcs which occur much earlier in the simulation.
    1017             :         //  so here we do a final pass and throw the errors that would usually occur during get input.
    1018             : 
    1019             :         // Using/Aliasing
    1020             :         using RuntimeLanguageProcessor::BeginEnvrnInitializeRuntimeLanguage;
    1021             :         using ScheduleManager::GetScheduleIndex;
    1022             : 
    1023             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1024             :         int SensorNum; // local loop
    1025             :         //  INTEGER :: VariableNum  ! local do loop index
    1026             :         int VarIndex;
    1027             :         OutputProcessor::VariableType VarType;
    1028        6437 :         bool ErrorsFound(false);
    1029             :         int ActuatorNum;
    1030             :         bool FoundObjectType;
    1031             :         bool FoundObjectName;
    1032             :         bool FoundActuatorName;
    1033             :         int ActuatorVariableNum;
    1034             :         int InternVarNum;        // local do loop index
    1035             :         int InternalVarAvailNum; // local do loop index
    1036       12874 :         std::string cCurrentModuleObject;
    1037             : 
    1038        6437 :         cCurrentModuleObject = "EnergyManagementSystem:Sensor";
    1039      169373 :         for (SensorNum = 1; SensorNum <= state.dataRuntimeLang->NumSensors; ++SensorNum) {
    1040      162936 :             if (state.dataRuntimeLang->Sensor(SensorNum).CheckedOkay) continue;
    1041             : 
    1042             :             // try again to process sensor.
    1043       56093 :             VarIndex = GetMeterIndex(state, state.dataRuntimeLang->Sensor(SensorNum).OutputVarName);
    1044       56093 :             if (VarIndex > 0) {
    1045             : 
    1046         184 :                 state.dataRuntimeLang->Sensor(SensorNum).VariableType = OutputProcessor::VariableType::Meter;
    1047         184 :                 state.dataRuntimeLang->Sensor(SensorNum).Index = VarIndex;
    1048             : 
    1049             :             } else {
    1050             :                 // Search for variable names
    1051      111818 :                 GetVariableTypeAndIndex(state,
    1052       55909 :                                         state.dataRuntimeLang->Sensor(SensorNum).OutputVarName,
    1053       55909 :                                         state.dataRuntimeLang->Sensor(SensorNum).UniqueKeyName,
    1054             :                                         VarType,
    1055             :                                         VarIndex);
    1056       55909 :                 if (VarType == OutputProcessor::VariableType::NotFound) {
    1057       54653 :                     if (reportErrors) {
    1058           0 :                         ShowSevereError(state,
    1059           0 :                                         "Invalid Output:Variable or Output:Meter Name =" + state.dataRuntimeLang->Sensor(SensorNum).OutputVarName);
    1060           0 :                         ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + state.dataRuntimeLang->Sensor(SensorNum).Name);
    1061           0 :                         ShowContinueError(state, "Output:Variable Name not found");
    1062           0 :                         ErrorsFound = true;
    1063             :                     }
    1064        1256 :                 } else if (VarIndex == 0) {
    1065           0 :                     if (reportErrors) {
    1066           0 :                         ShowSevereError(state,
    1067           0 :                                         "Invalid Output:Variable or Output:Meter Index Key Name =" +
    1068           0 :                                             state.dataRuntimeLang->Sensor(SensorNum).UniqueKeyName);
    1069           0 :                         ShowContinueError(state, "For Output:Variable or Output:Meter = " + state.dataRuntimeLang->Sensor(SensorNum).OutputVarName);
    1070           0 :                         ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + state.dataRuntimeLang->Sensor(SensorNum).Name);
    1071           0 :                         ShowContinueError(state, "Unique Key Name not found.");
    1072           0 :                         ErrorsFound = true;
    1073             :                     }
    1074             :                 } else {
    1075        1256 :                     state.dataRuntimeLang->Sensor(SensorNum).VariableType = VarType;
    1076        1256 :                     state.dataRuntimeLang->Sensor(SensorNum).Index = VarIndex;
    1077        1256 :                     state.dataRuntimeLang->Sensor(SensorNum).CheckedOkay = true;
    1078             :                     // If variable is Schedule Value, then get the schedule id to register it as being used
    1079        1256 :                     if (UtilityRoutines::SameString(state.dataRuntimeLang->Sensor(SensorNum).OutputVarName, "Schedule Value")) {
    1080          34 :                         state.dataRuntimeLang->Sensor(SensorNum).SchedNum =
    1081          34 :                             GetScheduleIndex(state, state.dataRuntimeLang->Sensor(SensorNum).UniqueKeyName);
    1082          34 :                         if (state.dataRuntimeLang->Sensor(SensorNum).SchedNum == 0) {
    1083           0 :                             state.dataRuntimeLang->Sensor(SensorNum).CheckedOkay = false;
    1084           0 :                             if (reportErrors) {
    1085           0 :                                 ShowSevereError(state,
    1086           0 :                                                 "Invalid Output:Variable or Output:Meter Index Key Name =" +
    1087           0 :                                                     state.dataRuntimeLang->Sensor(SensorNum).UniqueKeyName);
    1088           0 :                                 ShowContinueError(state,
    1089           0 :                                                   "For Output:Variable or Output:Meter = " + state.dataRuntimeLang->Sensor(SensorNum).OutputVarName);
    1090           0 :                                 ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + state.dataRuntimeLang->Sensor(SensorNum).Name);
    1091           0 :                                 ShowContinueError(state, "Schedule Name not found.");
    1092           0 :                                 ErrorsFound = true;
    1093             :                             }
    1094             :                         }
    1095             :                     }
    1096             :                 }
    1097             :             }
    1098             : 
    1099             :         } // SensorNum
    1100             : 
    1101             :         // added for FMU
    1102      200532 :         for (ActuatorNum = 1; ActuatorNum <= state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
    1103      133688 :                                                  state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed +
    1104       66844 :                                                  state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportActuatorsUsed;
    1105             :              ++ActuatorNum) {
    1106             :             // If we process the ExternalInterface actuators, all we need to do is to change the
    1107             : 
    1108       60407 :             if (ActuatorNum <= state.dataRuntimeLang->numActuatorsUsed) {
    1109       60373 :                 cCurrentModuleObject = "EnergyManagementSystem:Actuator";
    1110          68 :             } else if (ActuatorNum > state.dataRuntimeLang->numActuatorsUsed &&
    1111          34 :                        ActuatorNum <= state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed) {
    1112           0 :                 cCurrentModuleObject = "ExternalInterface:Actuator";
    1113          68 :             } else if (ActuatorNum > state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed &&
    1114          68 :                        ActuatorNum <= state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
    1115          34 :                                           state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed) {
    1116          34 :                 cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitImport:To:Actuator";
    1117           0 :             } else if (ActuatorNum > state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
    1118           0 :                                          state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed &&
    1119           0 :                        ActuatorNum <= state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed +
    1120           0 :                                           state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitImportActuatorsUsed +
    1121           0 :                                           state.dataRuntimeLang->NumExternalInterfaceFunctionalMockupUnitExportActuatorsUsed) {
    1122           0 :                 cCurrentModuleObject = "ExternalInterface:FunctionalMockupUnitExport:To:Actuator";
    1123             :             }
    1124             : 
    1125       60407 :             if (state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).CheckedOkay) continue;
    1126       15854 :             FoundObjectType = false;
    1127       15854 :             FoundObjectName = false;
    1128       15854 :             FoundActuatorName = false;
    1129    22019869 :             for (ActuatorVariableNum = 1; ActuatorVariableNum <= state.dataRuntimeLang->numEMSActuatorsAvailable; ++ActuatorVariableNum) {
    1130    22004356 :                 if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorAvailable(ActuatorVariableNum).ComponentTypeName,
    1131    22004356 :                                                 state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ComponentTypeName)) {
    1132       55807 :                     FoundObjectType = true;
    1133       55807 :                     if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorAvailable(ActuatorVariableNum).UniqueIDName,
    1134       55807 :                                                     state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).UniqueIDName)) {
    1135         681 :                         FoundObjectName = true;
    1136         681 :                         if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorAvailable(ActuatorVariableNum).ControlTypeName,
    1137         681 :                                                         state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ControlTypeName)) {
    1138         341 :                             FoundActuatorName = true;
    1139         341 :                             break;
    1140             :                         }
    1141             :                     }
    1142             :                 }
    1143             :             }
    1144             : 
    1145       15854 :             if (!FoundObjectType) {
    1146       13913 :                 if (reportErrors) {
    1147           0 :                     ShowSevereError(state,
    1148           0 :                                     "Invalid Actuated Component Type =" + state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ComponentTypeName);
    1149           0 :                     ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).Name);
    1150           0 :                     ShowContinueError(state, "Component Type not found");
    1151           0 :                     if (state.dataRuntimeLang->OutputEDDFile) {
    1152           0 :                         ShowContinueError(state, "Review .edd file for valid component types.");
    1153             :                     } else {
    1154           0 :                         ShowContinueError(state, "Use Output:EnergyManagementSystem object to create .edd file for valid component types.");
    1155             :                     }
    1156           0 :                     ErrorsFound = true;
    1157             :                 }
    1158             :             }
    1159             : 
    1160       15854 :             if (!FoundObjectName) {
    1161       15513 :                 if (reportErrors) {
    1162           0 :                     ShowSevereError(state,
    1163           0 :                                     "Invalid Actuated Component Unique Name =" + state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).UniqueIDName);
    1164           0 :                     ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).Name);
    1165           0 :                     ShowContinueError(state, "Component Unique key name not found ");
    1166           0 :                     if (state.dataRuntimeLang->OutputEDDFile) {
    1167           0 :                         ShowContinueError(state, "Review edd file for valid component names.");
    1168             :                     } else {
    1169           0 :                         ShowContinueError(state, "Use Output:EnergyManagementSystem object to create .edd file for valid component names.");
    1170             :                     }
    1171           0 :                     ErrorsFound = true;
    1172             :                 }
    1173             :             }
    1174             : 
    1175       15854 :             if (!FoundActuatorName) {
    1176       15513 :                 if (reportErrors) {
    1177           0 :                     ShowSevereError(
    1178           0 :                         state, "Invalid Actuated Component Control Type =" + state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ControlTypeName);
    1179           0 :                     ShowContinueError(state, "Entered in " + cCurrentModuleObject + '=' + state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).Name);
    1180           0 :                     ShowContinueError(state, "Control Type not found");
    1181           0 :                     if (state.dataRuntimeLang->OutputEDDFile) {
    1182           0 :                         ShowContinueError(state, "Review edd file for valid component control types.");
    1183             :                     } else {
    1184           0 :                         ShowContinueError(state, "Use Output:EnergyManagementSystem object to create .edd file for valid component control types.");
    1185             :                     }
    1186           0 :                     ErrorsFound = true;
    1187             :                 }
    1188             :             } else {
    1189         341 :                 state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ActuatorVariableNum = ActuatorVariableNum;
    1190         341 :                 state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).CheckedOkay = true;
    1191         341 :                 int nHandle = state.dataRuntimeLang->EMSActuatorAvailable(ActuatorVariableNum).handleCount;
    1192         341 :                 if (nHandle > 0) {
    1193           8 :                     EnergyPlus::ShowWarningError(state, format("Seems like you already tried to get a Handle on this Actuator {}times.", nHandle));
    1194          24 :                     EnergyPlus::ShowContinueError(state,
    1195          16 :                                                   "Occurred for componentType='" +
    1196          24 :                                                       state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ComponentTypeName + "', controlType='" +
    1197          24 :                                                       state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ControlTypeName + "', uniqueKey='" +
    1198          24 :                                                       state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).UniqueIDName + "'.");
    1199           8 :                     EnergyPlus::ShowContinueError(state, "You should take note that there is a risk of overwritting.");
    1200             :                 }
    1201         341 :                 ++state.dataRuntimeLang->EMSActuatorAvailable(ActuatorVariableNum).handleCount;
    1202             : 
    1203             :                 // Warn if actuator applied to an air boundary surface
    1204         341 :                 if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).ComponentTypeName,
    1205         341 :                                                 "AIRFLOW NETWORK WINDOW/DOOR OPENING")) {
    1206             :                     int actuatedSurfNum =
    1207           1 :                         UtilityRoutines::FindItemInList(state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).UniqueIDName, state.dataSurface->Surface);
    1208           1 :                     if (actuatedSurfNum > 0) {
    1209           1 :                         if (state.dataSurface->Surface(actuatedSurfNum).IsAirBoundarySurf) {
    1210           0 :                             ShowWarningError(
    1211             :                                 state,
    1212           0 :                                 "GetEMSInput: EnergyManagementSystem:Actuator=" + state.dataRuntimeLang->EMSActuatorUsed(ActuatorNum).Name +
    1213             :                                     " actuates an opening attached to an air boundary surface.");
    1214             :                         }
    1215             :                     }
    1216             :                 }
    1217             :             }
    1218             :         } // ActuatorNum
    1219             : 
    1220        6437 :         cCurrentModuleObject = "EnergyManagementSystem:InternalVariable";
    1221       55615 :         for (InternVarNum = 1; InternVarNum <= state.dataRuntimeLang->NumInternalVariablesUsed; ++InternVarNum) {
    1222       49178 :             if (state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).CheckedOkay) continue;
    1223        8254 :             FoundObjectType = false;
    1224        8254 :             FoundObjectName = false;
    1225     2083885 :             for (InternalVarAvailNum = 1; InternalVarAvailNum <= state.dataRuntimeLang->numEMSInternalVarsAvailable; ++InternalVarAvailNum) {
    1226     2075931 :                 if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).DataTypeName,
    1227     2075931 :                                                 state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).InternalDataTypeName)) {
    1228        2156 :                     FoundObjectType = true;
    1229        2156 :                     if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).UniqueIDName,
    1230        2156 :                                                     state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).UniqueIDName)) {
    1231         300 :                         FoundObjectName = true;
    1232         300 :                         break; // InternalVarAvailNum now holds needed index pointer
    1233             :                     }
    1234             :                 }
    1235             :             }
    1236             : 
    1237        8254 :             if (!FoundObjectType) {
    1238        6674 :                 if (reportErrors) {
    1239           0 :                     ShowSevereError(state,
    1240           0 :                                     "Invalid Internal Data Type =" + state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).InternalDataTypeName);
    1241           0 :                     ShowContinueError(state,
    1242           0 :                                       "Entered in " + cCurrentModuleObject + '=' + state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).Name);
    1243           0 :                     ShowContinueError(state, "Internal data type name not found");
    1244           0 :                     ErrorsFound = true;
    1245             :                 }
    1246             :             }
    1247             : 
    1248        8254 :             if (!FoundObjectName) {
    1249        7954 :                 if (reportErrors) {
    1250           0 :                     ShowSevereError(state,
    1251           0 :                                     "Invalid Internal Data Index Key Name =" + state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).UniqueIDName);
    1252           0 :                     ShowContinueError(state,
    1253           0 :                                       "Entered in " + cCurrentModuleObject + '=' + state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).Name);
    1254           0 :                     ShowContinueError(state, "Internal data unique identifier not found");
    1255           0 :                     ErrorsFound = true;
    1256             :                 }
    1257             :             } else {
    1258         300 :                 state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).InternVarNum = InternalVarAvailNum;
    1259         300 :                 state.dataRuntimeLang->EMSInternalVarsUsed(InternVarNum).CheckedOkay = true;
    1260             :             }
    1261             :         }
    1262        6437 :         if (reportErrors) {
    1263          69 :             EchoOutActuatorKeyChoices(state);
    1264          69 :             EchoOutInternalVariableChoices(state);
    1265             :         }
    1266             : 
    1267        6437 :         if (ErrorsFound) {
    1268           0 :             ShowFatalError(state, "Errors found in processing Energy Management System input. Preceding condition causes termination.");
    1269             :         }
    1270             : 
    1271        6437 :         if (reportErrors) {
    1272          69 :             BeginEnvrnInitializeRuntimeLanguage(state);
    1273             :         }
    1274        6437 :     }
    1275             : 
    1276       57700 :     void GetVariableTypeAndIndex(
    1277             :         EnergyPlusData &state, std::string const &VarName, std::string const &VarKeyName, OutputProcessor::VariableType &VarType, int &VarIndex)
    1278             :     {
    1279             : 
    1280             :         // SUBROUTINE INFORMATION:
    1281             :         //       AUTHOR         Peter Graham Ellis
    1282             :         //       DATE WRITTEN   June 2006
    1283             :         //       MODIFIED       na
    1284             :         //       RE-ENGINEERED  na
    1285             : 
    1286             :         // PURPOSE OF THIS SUBROUTINE:
    1287             :         // local helper routine intended to lookup report variables only.
    1288             :         //    Use GetMeterIndex for meters.
    1289             : 
    1290             :         // METHODOLOGY EMPLOYED:
    1291             :         // make calls to OutputProcessor methods GetVariableKeyCountandType and GetVariableKeys
    1292             : 
    1293             :         // USE STATEMENTS:
    1294             : 
    1295             :         // Using/Aliasing
    1296             :         using RuntimeLanguageProcessor::EvaluateStack;
    1297             : 
    1298             :         // Locals
    1299             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    1300             : 
    1301             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1302             :         int NumKeys;
    1303             :         int KeyNum;
    1304             :         OutputProcessor::StoreType AvgOrSum;
    1305             :         OutputProcessor::TimeStepType StepType;
    1306       57700 :         OutputProcessor::Unit Units(OutputProcessor::Unit::None);
    1307      115400 :         Array1D_string KeyName;
    1308      115400 :         Array1D_int KeyIndex;
    1309             :         bool Found;
    1310             : 
    1311       57700 :         VarType = OutputProcessor::VariableType::NotFound;
    1312       57700 :         VarIndex = 0;
    1313       57700 :         Found = false;
    1314       57700 :         GetVariableKeyCountandType(state, VarName, NumKeys, VarType, AvgOrSum, StepType, Units);
    1315             : 
    1316             :         // note that schedules are not getting VarType set right...
    1317             : 
    1318       57700 :         if (NumKeys > 0) {
    1319        1787 :             KeyName.allocate(NumKeys);
    1320        1787 :             KeyIndex.allocate(NumKeys);
    1321        1787 :             GetVariableKeys(state, VarName, VarType, KeyName, KeyIndex);
    1322             : 
    1323        1787 :             if (KeyName(1) == "ENVIRONMENT") {
    1324          38 :                 VarIndex = KeyIndex(1);
    1325             :             } else {
    1326       72305 :                 for (KeyNum = 1; KeyNum <= NumKeys; ++KeyNum) {
    1327       72305 :                     if (KeyName(KeyNum) == VarKeyName) {
    1328        1749 :                         Found = true;
    1329        1749 :                         break;
    1330             :                     }
    1331             :                 }
    1332        1749 :                 if (Found) VarIndex = KeyIndex(KeyNum);
    1333             :             }
    1334             : 
    1335        1787 :             KeyName.deallocate();
    1336        1787 :             KeyIndex.deallocate();
    1337             :         }
    1338       57700 :     }
    1339             : 
    1340          69 :     void EchoOutActuatorKeyChoices(EnergyPlusData &state)
    1341             :     {
    1342             : 
    1343             :         // SUBROUTINE INFORMATION:
    1344             :         //       AUTHOR         Brent Griffith
    1345             :         //       DATE WRITTEN   April 2009
    1346             :         //       MODIFIED       na
    1347             :         //       RE-ENGINEERED  na
    1348             : 
    1349             :         // PURPOSE OF THIS SUBROUTINE:
    1350             :         // echo out actuators registered with SetupEMSActuator for user access
    1351             : 
    1352             :         // METHODOLOGY EMPLOYED:
    1353             :         // mine structure and write to edd file
    1354             :         // note this executes after final processing and sizing-related calling points may already execute Erl programs
    1355             : 
    1356             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1357             : 
    1358             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1359             : 
    1360          69 :         if (state.dataRuntimeLang->OutputEMSActuatorAvailFull) {
    1361             : 
    1362          37 :             print(state.files.edd, "! <EnergyManagementSystem:Actuator Available>, Component Unique Name, Component Type,  Control Type, Units\n");
    1363       61237 :             for (int ActuatorLoop = 1; ActuatorLoop <= state.dataRuntimeLang->numEMSActuatorsAvailable; ++ActuatorLoop) {
    1364      306000 :                 print(state.files.edd,
    1365             :                       "EnergyManagementSystem:Actuator Available,{},{},{},{}\n",
    1366       61200 :                       state.dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop).UniqueIDName,
    1367       61200 :                       state.dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop).ComponentTypeName,
    1368       61200 :                       state.dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop).ControlTypeName,
    1369      122400 :                       state.dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop).Units);
    1370             :             }
    1371          32 :         } else if (state.dataRuntimeLang->OutputEMSActuatorAvailSmall) {
    1372           0 :             print(state.files.edd, "! <EnergyManagementSystem:Actuator Available>, *, Component Type, Control Type, Units\n");
    1373             :             int FoundTypeName;
    1374             :             int FoundControlType;
    1375           0 :             for (int ActuatorLoop = 1; ActuatorLoop <= state.dataRuntimeLang->numEMSActuatorsAvailable; ++ActuatorLoop) {
    1376           0 :                 if (ActuatorLoop + 1 <= state.dataRuntimeLang->numEMSActuatorsAvailable) {
    1377           0 :                     FoundTypeName = UtilityRoutines::FindItemInList(
    1378           0 :                         state.dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop).ComponentTypeName,
    1379           0 :                         state.dataRuntimeLang->EMSActuatorAvailable({ActuatorLoop + 1, state.dataRuntimeLang->numEMSActuatorsAvailable}),
    1380             :                         &EMSActuatorAvailableType::ComponentTypeName,
    1381           0 :                         state.dataRuntimeLang->numEMSActuatorsAvailable - (ActuatorLoop + 1));
    1382           0 :                     FoundControlType = UtilityRoutines::FindItemInList(
    1383           0 :                         state.dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop).ControlTypeName,
    1384           0 :                         state.dataRuntimeLang->EMSActuatorAvailable({ActuatorLoop + 1, state.dataRuntimeLang->numEMSActuatorsAvailable}),
    1385             :                         &EMSActuatorAvailableType::ControlTypeName,
    1386           0 :                         state.dataRuntimeLang->numEMSActuatorsAvailable - (ActuatorLoop + 1));
    1387             :                 } else {
    1388           0 :                     FoundTypeName = 1;
    1389           0 :                     FoundControlType = 1;
    1390             :                 }
    1391           0 :                 if ((FoundTypeName == 0) || (FoundControlType == 0)) {
    1392           0 :                     print(state.files.edd,
    1393             :                           "EnergyManagementSystem:Actuator Available, *,{},{},{}\n",
    1394           0 :                           state.dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop).ComponentTypeName,
    1395           0 :                           state.dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop).ControlTypeName,
    1396           0 :                           state.dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop).Units);
    1397             :                 }
    1398             :             }
    1399             :         }
    1400          69 :     }
    1401             : 
    1402          69 :     void EchoOutInternalVariableChoices(EnergyPlusData &state)
    1403             :     {
    1404             : 
    1405             :         // SUBROUTINE INFORMATION:
    1406             :         //       AUTHOR         Brent Griffith
    1407             :         //       DATE WRITTEN   April 2009
    1408             :         //       MODIFIED       na
    1409             :         //       RE-ENGINEERED  na
    1410             : 
    1411             :         // PURPOSE OF THIS SUBROUTINE:
    1412             :         // echo out actuators registered with SetupEMSActuator for user access
    1413             : 
    1414             :         // METHODOLOGY EMPLOYED:
    1415             :         // mine structure and write to eio file
    1416             : 
    1417             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1418             : 
    1419             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1420             : 
    1421          69 :         if (state.dataRuntimeLang->OutputEMSInternalVarsFull) {
    1422             : 
    1423          37 :             print(state.files.edd, "! <EnergyManagementSystem:InternalVariable Available>, Unique Name, Internal Data Type, Units \n");
    1424       10432 :             for (int InternalDataLoop = 1; InternalDataLoop <= state.dataRuntimeLang->numEMSInternalVarsAvailable; ++InternalDataLoop) {
    1425       41580 :                 print(state.files.edd,
    1426             :                       "EnergyManagementSystem:InternalVariable Available,{},{},{}\n",
    1427       10395 :                       state.dataRuntimeLang->EMSInternalVarsAvailable(InternalDataLoop).UniqueIDName,
    1428       10395 :                       state.dataRuntimeLang->EMSInternalVarsAvailable(InternalDataLoop).DataTypeName,
    1429       20790 :                       state.dataRuntimeLang->EMSInternalVarsAvailable(InternalDataLoop).Units);
    1430             :             }
    1431             : 
    1432          32 :         } else if (state.dataRuntimeLang->OutputEMSInternalVarsSmall) {
    1433           0 :             print(state.files.edd, "! <EnergyManagementSystem:InternalVariable Available>, *, Internal Data Type\n");
    1434           0 :             for (int InternalDataLoop = 1; InternalDataLoop <= state.dataRuntimeLang->numEMSInternalVarsAvailable; ++InternalDataLoop) {
    1435           0 :                 int Found(0);
    1436           0 :                 if (InternalDataLoop + 1 <= state.dataRuntimeLang->numEMSInternalVarsAvailable) {
    1437           0 :                     Found = UtilityRoutines::FindItemInList(
    1438           0 :                         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalDataLoop).DataTypeName,
    1439           0 :                         state.dataRuntimeLang->EMSInternalVarsAvailable({InternalDataLoop + 1, state.dataRuntimeLang->numEMSInternalVarsAvailable}),
    1440             :                         &InternalVarsAvailableType::DataTypeName,
    1441           0 :                         state.dataRuntimeLang->numEMSInternalVarsAvailable - (InternalDataLoop + 1));
    1442             :                 }
    1443           0 :                 if (Found == 0) {
    1444           0 :                     print(state.files.edd,
    1445             :                           "EnergyManagementSystem:InternalVariable Available, *,{},{}\n",
    1446           0 :                           state.dataRuntimeLang->EMSInternalVarsAvailable(InternalDataLoop).DataTypeName,
    1447           0 :                           state.dataRuntimeLang->EMSInternalVarsAvailable(InternalDataLoop).Units);
    1448             :                 }
    1449             :             }
    1450             :         }
    1451          69 :     }
    1452             : 
    1453          69 :     void SetupNodeSetPointsAsActuators(EnergyPlusData &state)
    1454             :     {
    1455             : 
    1456             :         // SUBROUTINE INFORMATION:
    1457             :         //       AUTHOR         Brent Griffith
    1458             :         //       DATE WRITTEN   May 2009
    1459             :         //       MODIFIED       na
    1460             :         //       RE-ENGINEERED  na
    1461             : 
    1462             :         // PURPOSE OF THIS SUBROUTINE:
    1463             :         // make system nodes in model available for EMS control
    1464             : 
    1465             :         // METHODOLOGY EMPLOYED:
    1466             :         // Loop over node structures and make calls to SetupEMSActuator
    1467             :         // the pattern for the basic node setpoints is a little different in that the actuators directly
    1468             :         // affect the node variables, rather than using separate logical override flag and ems values
    1469             : 
    1470             :         // Using/Aliasing
    1471             : 
    1472             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1473             :         int LoopNode; // local do loop index
    1474             :         // (could this ever cause a fault?) // It caused illegal memory access/corruption
    1475             :         // make it optional in Setup call?
    1476             :         int OutsideAirNodeNum; // local do loop index
    1477             :         int NodeNum;           // local index.
    1478             : 
    1479          69 :         state.dataEMSMgr->lDummy = false;
    1480             : 
    1481          69 :         if (state.dataLoopNodes->NumOfNodes > 0) {
    1482             : 
    1483       13701 :             for (LoopNode = 1; LoopNode <= state.dataLoopNodes->NumOfNodes; ++LoopNode) {
    1484             :                 // setup the setpoint for each type of variable that can be controlled
    1485       54532 :                 SetupEMSActuator(state,
    1486             :                                  "System Node Setpoint",
    1487       13633 :                                  state.dataLoopNodes->NodeID(LoopNode),
    1488             :                                  "Temperature Setpoint",
    1489             :                                  "[C]",
    1490       13633 :                                  state.dataEMSMgr->lDummy,
    1491       40899 :                                  state.dataLoopNodes->Node(LoopNode).TempSetPoint);
    1492       54532 :                 SetupEMSActuator(state,
    1493             :                                  "System Node Setpoint",
    1494       13633 :                                  state.dataLoopNodes->NodeID(LoopNode),
    1495             :                                  "Temperature Minimum Setpoint",
    1496             :                                  "[C]",
    1497       13633 :                                  state.dataEMSMgr->lDummy,
    1498       40899 :                                  state.dataLoopNodes->Node(LoopNode).TempSetPointLo);
    1499       54532 :                 SetupEMSActuator(state,
    1500             :                                  "System Node Setpoint",
    1501       13633 :                                  state.dataLoopNodes->NodeID(LoopNode),
    1502             :                                  "Temperature Maximum Setpoint",
    1503             :                                  "[C]",
    1504       13633 :                                  state.dataEMSMgr->lDummy,
    1505       40899 :                                  state.dataLoopNodes->Node(LoopNode).TempSetPointHi);
    1506       54532 :                 SetupEMSActuator(state,
    1507             :                                  "System Node Setpoint",
    1508       13633 :                                  state.dataLoopNodes->NodeID(LoopNode),
    1509             :                                  "Humidity Ratio Setpoint",
    1510             :                                  "[kgWater/kgDryAir]",
    1511       13633 :                                  state.dataEMSMgr->lDummy,
    1512       40899 :                                  state.dataLoopNodes->Node(LoopNode).HumRatSetPoint);
    1513       54532 :                 SetupEMSActuator(state,
    1514             :                                  "System Node Setpoint",
    1515       13633 :                                  state.dataLoopNodes->NodeID(LoopNode),
    1516             :                                  "Humidity Ratio Maximum Setpoint",
    1517             :                                  "[kgWater/kgDryAir]",
    1518       13633 :                                  state.dataEMSMgr->lDummy,
    1519       40899 :                                  state.dataLoopNodes->Node(LoopNode).HumRatMax);
    1520       54532 :                 SetupEMSActuator(state,
    1521             :                                  "System Node Setpoint",
    1522       13633 :                                  state.dataLoopNodes->NodeID(LoopNode),
    1523             :                                  "Humidity Ratio Minimum Setpoint",
    1524             :                                  "[kgWater/kgDryAir]",
    1525       13633 :                                  state.dataEMSMgr->lDummy,
    1526       40899 :                                  state.dataLoopNodes->Node(LoopNode).HumRatMin);
    1527       54532 :                 SetupEMSActuator(state,
    1528             :                                  "System Node Setpoint",
    1529       13633 :                                  state.dataLoopNodes->NodeID(LoopNode),
    1530             :                                  "Mass Flow Rate Setpoint",
    1531             :                                  "[kg/s]",
    1532       13633 :                                  state.dataEMSMgr->lDummy,
    1533       40899 :                                  state.dataLoopNodes->Node(LoopNode).MassFlowRateSetPoint);
    1534       54532 :                 SetupEMSActuator(state,
    1535             :                                  "System Node Setpoint",
    1536       13633 :                                  state.dataLoopNodes->NodeID(LoopNode),
    1537             :                                  "Mass Flow Rate Maximum Available Setpoint",
    1538             :                                  "[kg/s]",
    1539       13633 :                                  state.dataEMSMgr->lDummy,
    1540       40899 :                                  state.dataLoopNodes->Node(LoopNode).MassFlowRateMaxAvail);
    1541       54532 :                 SetupEMSActuator(state,
    1542             :                                  "System Node Setpoint",
    1543       13633 :                                  state.dataLoopNodes->NodeID(LoopNode),
    1544             :                                  "Mass Flow Rate Minimum Available Setpoint",
    1545             :                                  "[kg/s]",
    1546       13633 :                                  state.dataEMSMgr->lDummy,
    1547       40899 :                                  state.dataLoopNodes->Node(LoopNode).MassFlowRateMinAvail);
    1548             :             }
    1549             : 
    1550             :         } // NumOfNodes > 0
    1551             : 
    1552          69 :         if (state.dataOutAirNodeMgr->NumOutsideAirNodes > 0) {
    1553         723 :             for (OutsideAirNodeNum = 1; OutsideAirNodeNum <= state.dataOutAirNodeMgr->NumOutsideAirNodes; ++OutsideAirNodeNum) {
    1554         664 :                 NodeNum = state.dataOutAirNodeMgr->OutsideAirNodeList(OutsideAirNodeNum);
    1555        2656 :                 SetupEMSActuator(state,
    1556             :                                  "Outdoor Air System Node",
    1557         664 :                                  state.dataLoopNodes->NodeID(NodeNum),
    1558             :                                  "Drybulb Temperature",
    1559             :                                  "[C]",
    1560         664 :                                  state.dataLoopNodes->Node(NodeNum).EMSOverrideOutAirDryBulb,
    1561        1992 :                                  state.dataLoopNodes->Node(NodeNum).EMSValueForOutAirDryBulb);
    1562        2656 :                 SetupEMSActuator(state,
    1563             :                                  "Outdoor Air System Node",
    1564         664 :                                  state.dataLoopNodes->NodeID(NodeNum),
    1565             :                                  "Wetbulb Temperature",
    1566             :                                  "[C]",
    1567         664 :                                  state.dataLoopNodes->Node(NodeNum).EMSOverrideOutAirWetBulb,
    1568        1992 :                                  state.dataLoopNodes->Node(NodeNum).EMSValueForOutAirWetBulb);
    1569        2656 :                 SetupEMSActuator(state,
    1570             :                                  "Outdoor Air System Node",
    1571         664 :                                  state.dataLoopNodes->NodeID(NodeNum),
    1572             :                                  "Wind Speed",
    1573             :                                  "[m/s]",
    1574         664 :                                  state.dataLoopNodes->Node(NodeNum).EMSOverrideOutAirWindSpeed,
    1575        1992 :                                  state.dataLoopNodes->Node(NodeNum).EMSValueForOutAirWindSpeed);
    1576        2656 :                 SetupEMSActuator(state,
    1577             :                                  "Outdoor Air System Node",
    1578         664 :                                  state.dataLoopNodes->NodeID(NodeNum),
    1579             :                                  "Wind Direction",
    1580             :                                  "[degree]",
    1581         664 :                                  state.dataLoopNodes->Node(NodeNum).EMSOverrideOutAirWindDir,
    1582        1992 :                                  state.dataLoopNodes->Node(NodeNum).EMSValueForOutAirWindDir);
    1583        8278 :                 for (int ActuatorUsedLoop = 1; ActuatorUsedLoop <= state.dataRuntimeLang->numActuatorsUsed; ActuatorUsedLoop++) {
    1584       15244 :                     if (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorUsed(ActuatorUsedLoop).ComponentTypeName,
    1585       15372 :                                                     "Outdoor Air System Node") &&
    1586         128 :                         UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorUsed(ActuatorUsedLoop).UniqueIDName,
    1587         128 :                                                     state.dataLoopNodes->NodeID(NodeNum))) {
    1588           8 :                         state.dataLoopNodes->Node(NodeNum).IsLocalNode = true;
    1589           8 :                         break;
    1590             :                     }
    1591             :                 }
    1592             :             }
    1593             :         }
    1594          69 :     }
    1595             : 
    1596     2568312 :     void UpdateEMSTrendVariables(EnergyPlusData &state)
    1597             :     {
    1598             : 
    1599             :         // SUBROUTINE INFORMATION:
    1600             :         //       AUTHOR         Brent Griffith
    1601             :         //       DATE WRITTEN   May 2009
    1602             :         //       MODIFIED       na
    1603             :         //       RE-ENGINEERED  na
    1604             : 
    1605             :         // PURPOSE OF THIS SUBROUTINE:
    1606             :         // Logged trend data
    1607             : 
    1608             :         // METHODOLOGY EMPLOYED:
    1609             :         // Store current value of Erl Variable in Trend stack
    1610             :         // Trend arrays are pushed so that the latest value is
    1611             :         //  always at index 1.  old values get lost.
    1612             : 
    1613     2568312 :         int TrendNum(0); // local loop counter
    1614     2568312 :         int ErlVarNum(0);
    1615     2568312 :         int TrendDepth(0);
    1616     2568312 :         Real64 currentVal(0.0);
    1617             : 
    1618             :         // checks with quick return if no updates needed.
    1619     2568312 :         if (!state.dataGlobal->AnyEnergyManagementSystemInModel) return;
    1620      280890 :         if (state.dataRuntimeLang->NumErlTrendVariables == 0) return;
    1621             : 
    1622       17931 :         for (TrendNum = 1; TrendNum <= state.dataRuntimeLang->NumErlTrendVariables; ++TrendNum) {
    1623       10605 :             ErlVarNum = state.dataRuntimeLang->TrendVariable(TrendNum).ErlVariablePointer;
    1624       10605 :             TrendDepth = state.dataRuntimeLang->TrendVariable(TrendNum).LogDepth;
    1625       10605 :             if ((ErlVarNum > 0) && (TrendDepth > 0)) {
    1626       10605 :                 currentVal = state.dataRuntimeLang->ErlVariable(ErlVarNum).Value.Number;
    1627             :                 // push into trend
    1628       10605 :                 state.dataRuntimeLang->TrendVariable(TrendNum).tempTrendARR = state.dataRuntimeLang->TrendVariable(TrendNum).TrendValARR;
    1629       10605 :                 state.dataRuntimeLang->TrendVariable(TrendNum).TrendValARR(1) = currentVal;
    1630       10605 :                 state.dataRuntimeLang->TrendVariable(TrendNum).TrendValARR({2, TrendDepth}) =
    1631       21210 :                     state.dataRuntimeLang->TrendVariable(TrendNum).tempTrendARR({1, TrendDepth - 1});
    1632             :             }
    1633             :         }
    1634             :     }
    1635             : 
    1636        1822 :     bool CheckIfNodeSetPointManaged(EnergyPlusData &state, int const NodeNum, SPControlType const SetPointType, bool byHandle)
    1637             :     {
    1638             : 
    1639             :         // SUBROUTINE INFORMATION:
    1640             :         //       AUTHOR         Brent Griffith
    1641             :         //       DATE WRITTEN   May 2009
    1642             :         //       MODIFIED       July 2020, Julien Marrec of EffiBEM: added option to check by handle (for API)
    1643             :         //       RE-ENGINEERED  na
    1644             : 
    1645             :         // PURPOSE OF THIS SUBROUTINE:
    1646             :         // Provide method to verify that a specific node is (probably) managed by EMS
    1647             : 
    1648             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1649        1822 :         bool FoundControl(false);
    1650             : 
    1651        3644 :         std::string cNodeName = state.dataLoopNodes->NodeID(NodeNum);
    1652        3644 :         std::string cComponentTypeName = "System Node Setpoint";
    1653        1822 :         std::string_view cControlTypeName = controlTypeName[static_cast<int>(SetPointType)];
    1654             : 
    1655        1822 :         if (byHandle) {
    1656       44242 :             for (int Loop = 1; Loop <= state.dataRuntimeLang->numEMSActuatorsAvailable; ++Loop) {
    1657       88969 :                 if ((state.dataRuntimeLang->EMSActuatorAvailable(Loop).handleCount > 0) &&
    1658         732 :                     (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorAvailable(Loop).ComponentTypeName, cComponentTypeName)) &&
    1659       44517 :                     (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorAvailable(Loop).UniqueIDName, cNodeName)) &&
    1660          28 :                     (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorAvailable(Loop).ControlTypeName, cControlTypeName))) {
    1661          28 :                     FoundControl = true;
    1662          28 :                     break;
    1663             :                 }
    1664             :             }
    1665          28 :             if (!FoundControl) {
    1666           0 :                 ShowWarningError(state,
    1667           0 :                                  "Missing '" + format(controlTypeName[static_cast<int>(SetPointType)]) + "' for node named named '" +
    1668           0 :                                      state.dataLoopNodes->NodeID(NodeNum) + "'.");
    1669             :             }
    1670             :         } else {
    1671        8092 :             for (int Loop = 1; Loop <= state.dataRuntimeLang->numActuatorsUsed + state.dataRuntimeLang->NumExternalInterfaceActuatorsUsed; ++Loop) {
    1672       13975 :                 if ((UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorUsed(Loop).ComponentTypeName, cComponentTypeName)) &&
    1673        6462 :                     (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorUsed(Loop).UniqueIDName, cNodeName)) &&
    1674          82 :                     (UtilityRoutines::SameString(state.dataRuntimeLang->EMSActuatorUsed(Loop).ControlTypeName, cControlTypeName))) {
    1675          82 :                     FoundControl = true;
    1676          82 :                     break;
    1677             :                 }
    1678             :             }
    1679             :         }
    1680             : 
    1681        3644 :         return FoundControl;
    1682             :     }
    1683             : 
    1684        1794 :     bool CheckIfNodeSetPointManagedByEMS(EnergyPlusData &state,
    1685             :                                          int const NodeNum, // index of node being checked.
    1686             :                                          SPControlType const SetPointType,
    1687             :                                          bool &ErrorFlag)
    1688             :     {
    1689             : 
    1690             :         // SUBROUTINE INFORMATION:
    1691             :         //       AUTHOR         Brent Griffith
    1692             :         //       DATE WRITTEN   May 2009
    1693             :         //       MODIFIED       na
    1694             :         //       RE-ENGINEERED  na
    1695             : 
    1696             :         // PURPOSE OF THIS SUBROUTINE:
    1697             :         // Provide method to verify that a specific node is (probably) managed by EMS
    1698             : 
    1699             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1700        3588 :         std::string cControlTypeName;
    1701        3588 :         std::string cComponentTypeName;
    1702        3588 :         std::string cNodeName;
    1703        1794 :         bool FoundControl = CheckIfNodeSetPointManaged(state, NodeNum, SetPointType, false);
    1704             : 
    1705        1794 :         if ((!ErrorFlag) && (!FoundControl)) {
    1706        1712 :             int numPythonPlugins = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PythonPlugin:Instance");
    1707        1712 :             int numActiveCallbacks = PluginManagement::PluginManager::numActiveCallbacks(state); // errorCallback;
    1708        1712 :             if ((numPythonPlugins + numActiveCallbacks) == 0) {
    1709        1312 :                 ErrorFlag = true;
    1710             :             } else {
    1711             :                 // We'll defer to checking at the end whether a Plugin / API called getActuatorHandle on it
    1712         400 :                 auto &nodeSetpointCheck = state.dataLoopNodes->NodeSetpointCheck(NodeNum);
    1713         400 :                 nodeSetpointCheck.needsSetpointChecking = true;
    1714             : 
    1715         400 :                 switch (SetPointType) {
    1716         370 :                 case SPControlType::TemperatureSetPoint: {
    1717         370 :                     nodeSetpointCheck.checkTemperatureSetPoint = true;
    1718         370 :                 } break;
    1719           0 :                 case SPControlType::TemperatureMinSetPoint: {
    1720           0 :                     nodeSetpointCheck.checkTemperatureMinSetPoint = true;
    1721           0 :                 } break;
    1722           0 :                 case SPControlType::TemperatureMaxSetPoint: {
    1723           0 :                     nodeSetpointCheck.checkTemperatureMaxSetPoint = true;
    1724           0 :                 } break;
    1725           0 :                 case SPControlType::HumidityRatioSetPoint: {
    1726           0 :                     nodeSetpointCheck.checkHumidityRatioSetPoint = true;
    1727           0 :                 } break;
    1728           0 :                 case SPControlType::HumidityRatioMinSetPoint: {
    1729           0 :                     nodeSetpointCheck.checkHumidityRatioMinSetPoint = true;
    1730           0 :                 } break;
    1731          30 :                 case SPControlType::HumidityRatioMaxSetPoint: {
    1732          30 :                     nodeSetpointCheck.checkHumidityRatioMaxSetPoint = true;
    1733          30 :                 } break;
    1734           0 :                 case SPControlType::MassFlowRateSetPoint: {
    1735           0 :                     nodeSetpointCheck.checkMassFlowRateSetPoint = true;
    1736           0 :                 } break;
    1737           0 :                 case SPControlType::MassFlowRateMinSetPoint: {
    1738           0 :                     nodeSetpointCheck.checkMassFlowRateMinSetPoint = true;
    1739           0 :                 } break;
    1740           0 :                 case SPControlType::MassFlowRateMaxSetPoint: {
    1741           0 :                     nodeSetpointCheck.checkMassFlowRateMaxSetPoint = true;
    1742           0 :                 } break;
    1743           0 :                 default:
    1744           0 :                     break;
    1745             :                 }
    1746             :             }
    1747             :         }
    1748             : 
    1749        3588 :         return FoundControl;
    1750             :     }
    1751             : 
    1752         769 :     void checkSetpointNodesAtEnd(EnergyPlusData &state)
    1753             :     {
    1754             : 
    1755             :         // SUBROUTINE INFORMATION:
    1756             :         //       AUTHOR         Julien Marrec of EffiBEM
    1757             :         //       DATE WRITTEN   July 2020
    1758             :         //       MODIFIED       na
    1759             :         //       RE-ENGINEERED  na
    1760             : 
    1761             :         // PURPOSE OF THIS SUBROUTINE:
    1762             :         // This subroutine checks any nodes where we couldn't find a Setpoint in EMS, after the PythonPlugin / API have been called
    1763             :         // so we can check if getActuatorHandle was ever actually called for that node.
    1764             : 
    1765         769 :         bool FatalErrorFlag = false;
    1766             : 
    1767       60194 :         for (int NodeNum = 1; NodeNum <= state.dataLoopNodes->NumOfNodes; ++NodeNum) {
    1768       59425 :             auto &nodeSetpointCheck = state.dataLoopNodes->NodeSetpointCheck(NodeNum);
    1769             : 
    1770       59425 :             if (nodeSetpointCheck.needsSetpointChecking) {
    1771             :                 // Start by setting it to false (assume matched)
    1772          28 :                 nodeSetpointCheck.needsSetpointChecking = false;
    1773             : 
    1774          28 :                 if (nodeSetpointCheck.checkTemperatureSetPoint) {
    1775          28 :                     nodeSetpointCheck.needsSetpointChecking |= !CheckIfNodeSetPointManaged(state, NodeNum, SPControlType::TemperatureSetPoint, true);
    1776             :                 }
    1777          28 :                 if (nodeSetpointCheck.checkTemperatureMinSetPoint) {
    1778           0 :                     nodeSetpointCheck.needsSetpointChecking |=
    1779           0 :                         !CheckIfNodeSetPointManaged(state, NodeNum, SPControlType::TemperatureMinSetPoint, true);
    1780             :                 }
    1781          28 :                 if (nodeSetpointCheck.checkTemperatureMaxSetPoint) {
    1782           0 :                     nodeSetpointCheck.needsSetpointChecking |=
    1783           0 :                         !CheckIfNodeSetPointManaged(state, NodeNum, SPControlType::TemperatureMaxSetPoint, true);
    1784             :                 }
    1785          28 :                 if (nodeSetpointCheck.checkHumidityRatioSetPoint) {
    1786           0 :                     nodeSetpointCheck.needsSetpointChecking |=
    1787           0 :                         !CheckIfNodeSetPointManaged(state, NodeNum, SPControlType::HumidityRatioSetPoint, true);
    1788             :                 }
    1789          28 :                 if (nodeSetpointCheck.checkHumidityRatioMinSetPoint) {
    1790           0 :                     nodeSetpointCheck.needsSetpointChecking |=
    1791           0 :                         !CheckIfNodeSetPointManaged(state, NodeNum, SPControlType::HumidityRatioMinSetPoint, true);
    1792             :                 }
    1793          28 :                 if (nodeSetpointCheck.checkHumidityRatioMaxSetPoint) {
    1794           0 :                     nodeSetpointCheck.needsSetpointChecking |=
    1795           0 :                         !CheckIfNodeSetPointManaged(state, NodeNum, SPControlType::HumidityRatioMaxSetPoint, true);
    1796             :                 }
    1797          28 :                 if (nodeSetpointCheck.checkMassFlowRateSetPoint) {
    1798           0 :                     nodeSetpointCheck.needsSetpointChecking |= !CheckIfNodeSetPointManaged(state, NodeNum, SPControlType::MassFlowRateSetPoint, true);
    1799             :                 }
    1800          28 :                 if (nodeSetpointCheck.checkMassFlowRateMinSetPoint) {
    1801           0 :                     nodeSetpointCheck.needsSetpointChecking |=
    1802           0 :                         !CheckIfNodeSetPointManaged(state, NodeNum, SPControlType::MassFlowRateMinSetPoint, true);
    1803             :                 }
    1804          28 :                 if (nodeSetpointCheck.checkMassFlowRateMaxSetPoint) {
    1805           0 :                     nodeSetpointCheck.needsSetpointChecking |=
    1806           0 :                         !CheckIfNodeSetPointManaged(state, NodeNum, SPControlType::MassFlowRateMaxSetPoint, true);
    1807             :                 }
    1808             : 
    1809          28 :                 if (nodeSetpointCheck.needsSetpointChecking) {
    1810           0 :                     FatalErrorFlag = true;
    1811             :                 }
    1812             :             }
    1813             :         }
    1814             : 
    1815         769 :         if (FatalErrorFlag) {
    1816           0 :             ShowFatalError(state,
    1817             :                            "checkSetpointNodesAtEnd: At least one node does not have a setpoint attached, "
    1818             :                            "neither via a SetpointManager, EMS:Actuator, or API");
    1819             :         }
    1820         769 :     }
    1821             : 
    1822      237700 :     bool CheckIfNodeMoreInfoSensedByEMS(EnergyPlusData &state,
    1823             :                                         int const nodeNum, // index of node being checked.
    1824             :                                         std::string const &varName)
    1825             :     {
    1826             :         bool returnValue;
    1827             : 
    1828      237700 :         returnValue = false;
    1829     5353532 :         for (auto loop = 1; loop <= state.dataRuntimeLang->NumSensors; ++loop) {
    1830     5117464 :             if (state.dataRuntimeLang->Sensor(loop).UniqueKeyName == state.dataLoopNodes->NodeID(nodeNum) &&
    1831        1632 :                 UtilityRoutines::SameString(state.dataRuntimeLang->Sensor(loop).OutputVarName, varName)) {
    1832           1 :                 returnValue = true;
    1833             :             }
    1834             :         }
    1835             : 
    1836      237700 :         return returnValue;
    1837             :     }
    1838             : 
    1839          69 :     void SetupPrimaryAirSystemAvailMgrAsActuators(EnergyPlusData &state)
    1840             :     {
    1841             : 
    1842             :         // SUBROUTINE INFORMATION:
    1843             :         //       AUTHOR         Brent Griffith
    1844             :         //       DATE WRITTEN   May 2009
    1845             :         //       MODIFIED       na
    1846             :         //       RE-ENGINEERED  na
    1847             : 
    1848             :         // PURPOSE OF THIS SUBROUTINE:
    1849             :         // make air system status available as EMS actuator
    1850             : 
    1851             :         // METHODOLOGY EMPLOYED:
    1852             :         // <description>
    1853             : 
    1854             :         // REFERENCES:
    1855             :         // na
    1856             : 
    1857             :         // Using/Aliasing
    1858             :         // Locals
    1859             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    1860             :         // na
    1861             : 
    1862             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1863             :         // na
    1864             : 
    1865             :         // INTERFACE BLOCK SPECIFICATIONS:
    1866             :         // na
    1867             : 
    1868             :         // DERIVED TYPE DEFINITIONS:
    1869             :         // na
    1870             : 
    1871             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1872          69 :         int numAirLoops(0);
    1873          69 :         int Loop(0);
    1874             : 
    1875          69 :         state.dataEMSMgr->lDummy2 = false;
    1876             : 
    1877          69 :         if (allocated(state.dataAirLoop->PriAirSysAvailMgr)) {
    1878          58 :             numAirLoops = isize(state.dataAirLoop->PriAirSysAvailMgr);
    1879         389 :             for (Loop = 1; Loop <= numAirLoops; ++Loop) {
    1880        1324 :                 SetupEMSActuator(state,
    1881             :                                  "AirLoopHVAC",
    1882         331 :                                  state.dataAirSystemsData->PrimaryAirSystems(Loop).Name,
    1883             :                                  "Availability Status",
    1884             :                                  "[ ]",
    1885         331 :                                  state.dataEMSMgr->lDummy2,
    1886         993 :                                  state.dataAirLoop->PriAirSysAvailMgr(Loop).AvailStatus);
    1887             :             }
    1888             : 
    1889             :         } else {
    1890             :         }
    1891          69 :     }
    1892             : 
    1893          71 :     void SetupWindowShadingControlActuators(EnergyPlusData &state)
    1894             :     {
    1895             : 
    1896             :         // SUBROUTINE INFORMATION:
    1897             :         //       AUTHOR         Brent Griffith
    1898             :         //       DATE WRITTEN   May 2009
    1899             :         //       MODIFIED       na
    1900             :         //       RE-ENGINEERED  na
    1901             : 
    1902             :         // PURPOSE OF THIS SUBROUTINE:
    1903             :         // make calls to SetupEMSactuator for public data for Window Shades
    1904             : 
    1905             :         // METHODOLOGY EMPLOYED:
    1906             :         // Loop thru SurfaceWindow and register any shading controls
    1907             : 
    1908             :         // Using/Aliasing
    1909             :         using DataSurfaces::ExternalEnvironment;
    1910             :         using DataSurfaces::WinShadingType;
    1911             : 
    1912             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1913          71 :         int loopSurfNum(0); // local do loop index
    1914             : 
    1915       10916 :         for (loopSurfNum = 1; loopSurfNum <= state.dataSurface->TotSurfaces; ++loopSurfNum) {
    1916             : 
    1917       10845 :             if (state.dataSurface->Surface(loopSurfNum).Class != DataSurfaces::SurfaceClass::Window) continue;
    1918        1682 :             if (state.dataSurface->Surface(loopSurfNum).ExtBoundCond != ExternalEnvironment) continue;
    1919        1682 :             if (!state.dataSurface->Surface(loopSurfNum).HasShadeControl) continue;
    1920             : 
    1921          12 :             if (state.dataSurface->SurfWinHasShadeOrBlindLayer(loopSurfNum)) {
    1922          40 :                 SetupEMSActuator(state,
    1923             :                                  "Window Shading Control",
    1924          10 :                                  state.dataSurface->Surface(loopSurfNum).Name,
    1925             :                                  "Control Status",
    1926             :                                  "[ShadeStatus]",
    1927          10 :                                  state.dataSurface->SurfWinShadingFlagEMSOn(loopSurfNum),
    1928          30 :                                  state.dataSurface->SurfWinShadingFlagEMSValue(loopSurfNum));
    1929          10 :                 if (state.dataSurface->SurfWinMovableSlats(loopSurfNum)) {
    1930           0 :                     SetupEMSActuator(state,
    1931             :                                      "Window Shading Control",
    1932           0 :                                      state.dataSurface->Surface(loopSurfNum).Name,
    1933             :                                      "Slat Angle",
    1934             :                                      "[degrees]",
    1935           0 :                                      state.dataSurface->SurfWinSlatAngThisTSDegEMSon(loopSurfNum),
    1936           0 :                                      state.dataSurface->SurfWinSlatAngThisTSDegEMSValue(loopSurfNum));
    1937             :                 }
    1938           2 :             } else if (state.dataSurface->WindowShadingControl(state.dataSurface->Surface(loopSurfNum).activeWindowShadingControl).ShadingType ==
    1939             :                        WinShadingType::ExtScreen) {
    1940           0 :                 SetupEMSActuator(state,
    1941             :                                  "Window Shading Control",
    1942           0 :                                  state.dataSurface->Surface(loopSurfNum).Name,
    1943             :                                  "Control Status",
    1944             :                                  "[ShadeStatus]",
    1945           0 :                                  state.dataSurface->SurfWinShadingFlagEMSOn(loopSurfNum),
    1946           0 :                                  state.dataSurface->SurfWinShadingFlagEMSValue(loopSurfNum));
    1947             :             } else {
    1948           2 :                 if (state.dataSurface->WindowShadingControl(state.dataSurface->Surface(loopSurfNum).activeWindowShadingControl).ShadingType !=
    1949             :                     WinShadingType::SwitchableGlazing) {
    1950           0 :                     ShowSevereError(state,
    1951           0 :                                     "Missing shade or blind layer in window construction name = '" +
    1952           0 :                                         state.dataConstruction->Construct(state.dataSurface->Surface(loopSurfNum).activeShadedConstruction).Name +
    1953           0 :                                         "', surface name = '" + state.dataSurface->Surface(loopSurfNum).Name + "'.");
    1954           0 :                     ShowContinueError(state,
    1955             :                                       "...'Control Status' or 'Slat Angle' EMS Actuator cannot be set for a construction that does not have a shade "
    1956             :                                       "or a blind layer.");
    1957           0 :                     ShowContinueError(state, "...Add shade or blind layer to this construction in order to be able to apply EMS Actuator.");
    1958             :                 }
    1959             :             }
    1960             :         }
    1961          71 :     }
    1962             : 
    1963          71 :     void SetupThermostatActuators(EnergyPlusData &state)
    1964             :     {
    1965             : 
    1966             :         // SUBROUTINE INFORMATION:
    1967             :         //       AUTHOR         Brent Griffith
    1968             :         //       DATE WRITTEN   May 2009
    1969             :         //       MODIFIED       na
    1970             :         //       RE-ENGINEERED  na
    1971             : 
    1972             :         // PURPOSE OF THIS SUBROUTINE:
    1973             :         // Make zone thermostats, humidistats, and comfort controls available to EMS
    1974             : 
    1975             :         // METHODOLOGY EMPLOYED:
    1976             :         // Loop over structures and call SetupEMSactuator for public data in DataZoneControls.
    1977             : 
    1978             :         // REFERENCES:
    1979             :         // na
    1980             : 
    1981             :         // Using/Aliasing
    1982             :         using namespace DataZoneControls;
    1983             : 
    1984             :         // Locals
    1985             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    1986             :         // na
    1987             : 
    1988             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1989             :         // na
    1990             : 
    1991             :         // INTERFACE BLOCK SPECIFICATIONS:
    1992             :         // na
    1993             : 
    1994             :         // DERIVED TYPE DEFINITIONS:
    1995             :         // na
    1996             : 
    1997             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1998          71 :         int Loop(0); // local do loop index
    1999             : 
    2000        1084 :         for (Loop = 1; Loop <= state.dataZoneCtrls->NumTempControlledZones; ++Loop) {
    2001        4052 :             SetupEMSActuator(state,
    2002             :                              "Zone Temperature Control",
    2003        1013 :                              state.dataZoneCtrls->TempControlledZone(Loop).ZoneName,
    2004             :                              "Heating Setpoint",
    2005             :                              "[C]",
    2006        1013 :                              state.dataZoneCtrls->TempControlledZone(Loop).EMSOverrideHeatingSetPointOn,
    2007        3039 :                              state.dataZoneCtrls->TempControlledZone(Loop).EMSOverrideHeatingSetPointValue);
    2008        4052 :             SetupEMSActuator(state,
    2009             :                              "Zone Temperature Control",
    2010        1013 :                              state.dataZoneCtrls->TempControlledZone(Loop).ZoneName,
    2011             :                              "Cooling Setpoint",
    2012             :                              "[C]",
    2013        1013 :                              state.dataZoneCtrls->TempControlledZone(Loop).EMSOverrideCoolingSetPointOn,
    2014        3039 :                              state.dataZoneCtrls->TempControlledZone(Loop).EMSOverrideCoolingSetPointValue);
    2015             :         }
    2016             : 
    2017          93 :         for (Loop = 1; Loop <= state.dataZoneCtrls->NumHumidityControlZones; ++Loop) {
    2018          88 :             SetupEMSActuator(state,
    2019             :                              "Zone Humidity Control",
    2020          22 :                              state.dataZoneCtrls->HumidityControlZone(Loop).ZoneName,
    2021             :                              "Relative Humidity Humidifying Setpoint",
    2022             :                              "[%]",
    2023          22 :                              state.dataZoneCtrls->HumidityControlZone(Loop).EMSOverrideHumidifySetPointOn,
    2024          66 :                              state.dataZoneCtrls->HumidityControlZone(Loop).EMSOverrideHumidifySetPointValue);
    2025          88 :             SetupEMSActuator(state,
    2026             :                              "Zone Humidity Control",
    2027          22 :                              state.dataZoneCtrls->HumidityControlZone(Loop).ZoneName,
    2028             :                              "Relative Humidity Dehumidifying Setpoint",
    2029             :                              "[%]",
    2030          22 :                              state.dataZoneCtrls->HumidityControlZone(Loop).EMSOverrideDehumidifySetPointOn,
    2031          66 :                              state.dataZoneCtrls->HumidityControlZone(Loop).EMSOverrideDehumidifySetPointValue);
    2032             :         }
    2033             : 
    2034          71 :         for (Loop = 1; Loop <= state.dataZoneCtrls->NumComfortControlledZones; ++Loop) {
    2035           0 :             SetupEMSActuator(state,
    2036             :                              "Zone Comfort Control",
    2037           0 :                              state.dataZoneCtrls->ComfortControlledZone(Loop).ZoneName,
    2038             :                              "Heating Setpoint",
    2039             :                              "[]",
    2040           0 :                              state.dataZoneCtrls->ComfortControlledZone(Loop).EMSOverrideHeatingSetPointOn,
    2041           0 :                              state.dataZoneCtrls->ComfortControlledZone(Loop).EMSOverrideHeatingSetPointValue);
    2042           0 :             SetupEMSActuator(state,
    2043             :                              "Zone Comfort Control",
    2044           0 :                              state.dataZoneCtrls->ComfortControlledZone(Loop).ZoneName,
    2045             :                              "Cooling Setpoint",
    2046             :                              "[]",
    2047           0 :                              state.dataZoneCtrls->ComfortControlledZone(Loop).EMSOverrideCoolingSetPointOn,
    2048           0 :                              state.dataZoneCtrls->ComfortControlledZone(Loop).EMSOverrideCoolingSetPointValue);
    2049             :         }
    2050          71 :     }
    2051             : 
    2052          71 :     void SetupSurfaceConvectionActuators(EnergyPlusData &state)
    2053             :     {
    2054             : 
    2055             :         // SUBROUTINE INFORMATION:
    2056             :         //       AUTHOR         Brent Griffith
    2057             :         //       DATE WRITTEN   May 2009
    2058             :         //       MODIFIED       na
    2059             :         //       RE-ENGINEERED  na
    2060             : 
    2061             :         // PURPOSE OF THIS SUBROUTINE:
    2062             :         // Setup EMS actuators available for surface convection coefficients
    2063             : 
    2064             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2065             :         int SurfNum; // local loop index.
    2066             : 
    2067       10916 :         for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2068       32535 :             SetupEMSActuator(state,
    2069             :                              "Surface",
    2070       10845 :                              state.dataSurface->Surface(SurfNum).Name,
    2071             :                              "Interior Surface Convection Heat Transfer Coefficient",
    2072             :                              "[W/m2-K]",
    2073       10845 :                              state.dataSurface->SurfEMSOverrideIntConvCoef(SurfNum),
    2074       32535 :                              state.dataSurface->SurfEMSValueForIntConvCoef(SurfNum));
    2075       32535 :             SetupEMSActuator(state,
    2076             :                              "Surface",
    2077       10845 :                              state.dataSurface->Surface(SurfNum).Name,
    2078             :                              "Exterior Surface Convection Heat Transfer Coefficient",
    2079             :                              "[W/m2-K]",
    2080       10845 :                              state.dataSurface->SurfEMSOverrideExtConvCoef(SurfNum),
    2081       32535 :                              state.dataSurface->SurfEMSValueForExtConvCoef(SurfNum));
    2082             :         }
    2083          71 :     }
    2084             : 
    2085          71 :     void SetupSurfaceConstructionActuators(EnergyPlusData &state)
    2086             :     {
    2087             : 
    2088             :         // SUBROUTINE INFORMATION:
    2089             :         //       AUTHOR         B. Griffith
    2090             :         //       DATE WRITTEN   Jan 2012
    2091             :         //       MODIFIED       na
    2092             :         //       RE-ENGINEERED  na
    2093             : 
    2094             :         // PURPOSE OF THIS SUBROUTINE:
    2095             :         // setup EMS actuators available for surface construction
    2096             : 
    2097             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2098             :         int SurfNum; // local loop index.
    2099             : 
    2100       10916 :         for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2101             : 
    2102       10845 :             if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    2103             : 
    2104       43292 :             SetupEMSActuator(state,
    2105             :                              "Surface",
    2106       10823 :                              state.dataSurface->Surface(SurfNum).Name,
    2107             :                              "Construction State",
    2108             :                              "[ ]",
    2109       10823 :                              state.dataSurface->SurfEMSConstructionOverrideON(SurfNum),
    2110       32469 :                              state.dataSurface->SurfEMSConstructionOverrideValue(SurfNum));
    2111             :         }
    2112             : 
    2113             :         // Setup error checking storage
    2114             : 
    2115          71 :         if (!allocated(state.dataRuntimeLang->EMSConstructActuatorChecked))
    2116          71 :             state.dataRuntimeLang->EMSConstructActuatorChecked.allocate(state.dataHeatBal->TotConstructs, state.dataSurface->TotSurfaces);
    2117          71 :         state.dataRuntimeLang->EMSConstructActuatorChecked = false;
    2118             : 
    2119          71 :         if (!allocated(state.dataRuntimeLang->EMSConstructActuatorIsOkay))
    2120          71 :             state.dataRuntimeLang->EMSConstructActuatorIsOkay.allocate(state.dataHeatBal->TotConstructs, state.dataSurface->TotSurfaces);
    2121          71 :         state.dataRuntimeLang->EMSConstructActuatorIsOkay = false;
    2122          71 :     }
    2123             : 
    2124          71 :     void SetupSurfaceOutdoorBoundaryConditionActuators(EnergyPlusData &state)
    2125             :     {
    2126             : 
    2127             :         // SUBROUTINE INFORMATION:
    2128             :         //       AUTHOR         B. Griffith
    2129             :         //       DATE WRITTEN   May 2013
    2130             :         //       MODIFIED       na
    2131             :         //       RE-ENGINEERED  na
    2132             : 
    2133             :         // PURPOSE OF THIS SUBROUTINE:
    2134             :         // setup EMS actuators for outside boundary conditions by surface
    2135             : 
    2136             :         // METHODOLOGY EMPLOYED:
    2137             :         // loop through all surfaces, cycle if not heat transfer or outdoors BC
    2138             : 
    2139             :         // Using/Aliasing
    2140             :         using DataSurfaces::ExternalEnvironment;
    2141             : 
    2142             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2143             :         int SurfNum; // local loop index.
    2144             : 
    2145       10916 :         for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    2146             : 
    2147       10845 :             if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
    2148       10823 :             if (state.dataSurface->Surface(SurfNum).ExtBoundCond != ExternalEnvironment) continue;
    2149             : 
    2150       11634 :             SetupEMSActuator(state,
    2151             :                              "Surface",
    2152        3878 :                              state.dataSurface->Surface(SurfNum).Name,
    2153             :                              "View Factor To Ground",
    2154             :                              "[ ]",
    2155        3878 :                              state.dataSurface->SurfViewFactorGroundEMSOverrideOn(SurfNum),
    2156       11634 :                              state.dataSurface->SurfViewFactorGroundEMSOverrideValue(SurfNum));
    2157             : 
    2158       11634 :             SetupEMSActuator(state,
    2159             :                              "Surface",
    2160        3878 :                              state.dataSurface->Surface(SurfNum).Name,
    2161             :                              "Outdoor Air Drybulb Temperature",
    2162             :                              "[C]",
    2163        3878 :                              state.dataSurface->SurfOutDryBulbTempEMSOverrideOn(SurfNum),
    2164       11634 :                              state.dataSurface->SurfOutDryBulbTempEMSOverrideValue(SurfNum));
    2165             : 
    2166       11634 :             SetupEMSActuator(state,
    2167             :                              "Surface",
    2168        3878 :                              state.dataSurface->Surface(SurfNum).Name,
    2169             :                              "Outdoor Air Wetbulb Temperature",
    2170             :                              "[C]",
    2171        3878 :                              state.dataSurface->SurfOutWetBulbTempEMSOverrideOn(SurfNum),
    2172       11634 :                              state.dataSurface->SurfOutWetBulbTempEMSOverrideValue(SurfNum));
    2173        3878 :             if (state.dataSurface->Surface(SurfNum).ExtWind) {
    2174       11613 :                 SetupEMSActuator(state,
    2175             :                                  "Surface",
    2176        3871 :                                  state.dataSurface->Surface(SurfNum).Name,
    2177             :                                  "Outdoor Air Wind Speed",
    2178             :                                  "[m/s]",
    2179        3871 :                                  state.dataSurface->SurfWindSpeedEMSOverrideOn(SurfNum),
    2180       11613 :                                  state.dataSurface->SurfWindSpeedEMSOverrideValue(SurfNum));
    2181       11613 :                 SetupEMSActuator(state,
    2182             :                                  "Surface",
    2183        3871 :                                  state.dataSurface->Surface(SurfNum).Name,
    2184             :                                  "Outdoor Air Wind Direction",
    2185             :                                  "[degree]",
    2186        3871 :                                  state.dataSurface->SurfWindDirEMSOverrideOn(SurfNum),
    2187       11613 :                                  state.dataSurface->SurfWindDirEMSOverrideValue(SurfNum));
    2188             :             }
    2189             :         }
    2190          71 :     }
    2191             : 
    2192          71 :     void SetupZoneInfoAsInternalDataAvail(EnergyPlusData &state)
    2193             :     {
    2194             : 
    2195             :         // SUBROUTINE INFORMATION:
    2196             :         //       AUTHOR         Brent Griffith
    2197             :         //       DATE WRITTEN   May 2009
    2198             :         //       MODIFIED       na
    2199             :         //       RE-ENGINEERED  na
    2200             : 
    2201             :         // PURPOSE OF THIS SUBROUTINE:
    2202             :         // set up zone-related info as internal data
    2203             : 
    2204             :         // METHODOLOGY EMPLOYED:
    2205             :         // <description>
    2206             : 
    2207             :         // REFERENCES:
    2208             :         // na
    2209             : 
    2210             :         // Using/Aliasing
    2211             : 
    2212             :         // Locals
    2213             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    2214             :         // na
    2215             : 
    2216             :         // SUBROUTINE PARAMETER DEFINITIONS:
    2217             :         // na
    2218             : 
    2219             :         // INTERFACE BLOCK SPECIFICATIONS:
    2220             :         // na
    2221             : 
    2222             :         // DERIVED TYPE DEFINITIONS:
    2223             :         // na
    2224             : 
    2225             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2226             : 
    2227             :         int ZoneNum;
    2228          71 :         auto &Zone(state.dataHeatBal->Zone);
    2229             : 
    2230          71 :         if (allocated(Zone)) {
    2231        1183 :             for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2232             : 
    2233        1112 :                 SetupEMSInternalVariable(state, "Zone Floor Area", Zone(ZoneNum).Name, "[m2]", Zone(ZoneNum).FloorArea);
    2234        1112 :                 SetupEMSInternalVariable(state, "Zone Air Volume", Zone(ZoneNum).Name, "[m3]", Zone(ZoneNum).Volume);
    2235        1112 :                 SetupEMSInternalVariable(state, "Zone Multiplier", Zone(ZoneNum).Name, "[ ]", Zone(ZoneNum).Multiplier);
    2236        1112 :                 SetupEMSInternalVariable(state, "Zone List Multiplier", Zone(ZoneNum).Name, "[ ]", Zone(ZoneNum).ListMultiplier);
    2237             :             }
    2238             :         }
    2239          71 :     }
    2240             : 
    2241          71 :     void SetupZoneOutdoorBoundaryConditionActuators(EnergyPlusData &state)
    2242             :     {
    2243             : 
    2244             :         // SUBROUTINE INFORMATION:
    2245             :         //       AUTHOR         X Luo
    2246             :         //       DATE WRITTEN   July 2017
    2247             :         //       MODIFIED       na
    2248             :         //       RE-ENGINEERED  na
    2249             : 
    2250             :         // PURPOSE OF THIS SUBROUTINE:
    2251             :         // setup EMS actuators for outside boundary conditions by surface
    2252             : 
    2253             :         // METHODOLOGY EMPLOYED:
    2254             :         // loop through all surfaces, cycle if not heat transfer or outdoors BC
    2255             : 
    2256             :         // REFERENCES:
    2257             :         // na
    2258             : 
    2259             :         // Using/Aliasing
    2260             : 
    2261             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2262             :         int ZoneNum; // local loop index.
    2263          71 :         auto &Zone(state.dataHeatBal->Zone);
    2264             : 
    2265        1183 :         for (ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    2266             : 
    2267        4448 :             SetupEMSActuator(state,
    2268             :                              "Zone",
    2269        1112 :                              Zone(ZoneNum).Name,
    2270             :                              "Outdoor Air Drybulb Temperature",
    2271             :                              "[C]",
    2272        1112 :                              Zone(ZoneNum).OutDryBulbTempEMSOverrideOn,
    2273        3336 :                              Zone(ZoneNum).OutDryBulbTempEMSOverrideValue);
    2274        4448 :             SetupEMSActuator(state,
    2275             :                              "Zone",
    2276        1112 :                              Zone(ZoneNum).Name,
    2277             :                              "Outdoor Air Wetbulb Temperature",
    2278             :                              "[C]",
    2279        1112 :                              Zone(ZoneNum).OutWetBulbTempEMSOverrideOn,
    2280        3336 :                              Zone(ZoneNum).OutWetBulbTempEMSOverrideValue);
    2281        4448 :             SetupEMSActuator(state,
    2282             :                              "Zone",
    2283        1112 :                              Zone(ZoneNum).Name,
    2284             :                              "Outdoor Air Wind Speed",
    2285             :                              "[m/s]",
    2286        1112 :                              Zone(ZoneNum).WindSpeedEMSOverrideOn,
    2287        3336 :                              Zone(ZoneNum).WindSpeedEMSOverrideValue);
    2288        4448 :             SetupEMSActuator(state,
    2289             :                              "Zone",
    2290        1112 :                              Zone(ZoneNum).Name,
    2291             :                              "Outdoor Air Wind Direction",
    2292             :                              "[degree]",
    2293        1112 :                              Zone(ZoneNum).WindDirEMSOverrideOn,
    2294        3336 :                              Zone(ZoneNum).WindDirEMSOverrideValue);
    2295             :         }
    2296          71 :     }
    2297             : 
    2298         769 :     void checkForUnusedActuatorsAtEnd(EnergyPlusData &state)
    2299             :     {
    2300             :         // call at end of simulation to check if any of the user's actuators were never initialized.
    2301             :         // Could be a mistake we want to help users catch // Issue #4404.
    2302        1465 :         for (int actuatorUsedLoop = 1; actuatorUsedLoop <= state.dataRuntimeLang->numActuatorsUsed; ++actuatorUsedLoop) {
    2303         696 :             if (!state.dataRuntimeLang->ErlVariable(state.dataRuntimeLang->EMSActuatorUsed(actuatorUsedLoop).ErlVariableNum).Value.initialized) {
    2304           0 :                 ShowWarningError(state,
    2305             :                                  "checkForUnusedActuatorsAtEnd: Unused EMS Actuator detected, suggesting possible unintended programming error or "
    2306             :                                  "spelling mistake.");
    2307           0 :                 ShowContinueError(state,
    2308           0 :                                   "Check Erl programs related to EMS actuator variable name = " +
    2309           0 :                                       state.dataRuntimeLang->EMSActuatorUsed(actuatorUsedLoop).Name);
    2310           0 :                 ShowContinueError(state, "EMS Actuator type name = " + state.dataRuntimeLang->EMSActuatorUsed(actuatorUsedLoop).ComponentTypeName);
    2311           0 :                 ShowContinueError(state,
    2312           0 :                                   "EMS Actuator unique component name = " + state.dataRuntimeLang->EMSActuatorUsed(actuatorUsedLoop).UniqueIDName);
    2313           0 :                 ShowContinueError(state, "EMS Actuator control type = " + state.dataRuntimeLang->EMSActuatorUsed(actuatorUsedLoop).ControlTypeName);
    2314             :             }
    2315             :         }
    2316         769 :     }
    2317             : 
    2318             : } // namespace EMSManager
    2319             : 
    2320             : // Moved these setup EMS actuator routines out of module to solve circular use problems between
    2321             : //  ScheduleManager and OutputProcessor. Followed pattern used for SetupOutputVariable
    2322             : 
    2323      206506 : void SetupEMSActuator(EnergyPlusData &state,
    2324             :                       std::string_view cComponentTypeName,
    2325             :                       std::string_view cUniqueIDName,
    2326             :                       std::string_view cControlTypeName,
    2327             :                       std::string_view cUnits,
    2328             :                       bool &lEMSActuated,
    2329             :                       Real64 &rValue)
    2330             : {
    2331             : 
    2332             :     // SUBROUTINE INFORMATION:
    2333             :     //       AUTHOR         Peter Graham Ellis
    2334             :     //       DATE WRITTEN   June 2006
    2335             :     //       MODIFIED       Brent Griffith April 2009,
    2336             :     //       RE-ENGINEERED  na
    2337             : 
    2338             :     // PURPOSE OF THIS SUBROUTINE:
    2339             :     // register a new actuator for EMS
    2340             :     //   set  up pointer to logical and real value
    2341             : 
    2342             :     // METHODOLOGY EMPLOYED:
    2343             :     // push size of ActuatorVariable and add a new one.
    2344             :     //  check for duplicates.
    2345             : 
    2346             :     // Using/Aliasing
    2347             :     using namespace DataRuntimeLanguage;
    2348             : 
    2349      413012 :     std::string const UpperCaseObjectType(UtilityRoutines::MakeUPPERCase(cComponentTypeName));
    2350      413012 :     std::string const UpperCaseObjectName(UtilityRoutines::MakeUPPERCase(cUniqueIDName));
    2351      413012 :     std::string const UpperCaseActuatorName(UtilityRoutines::MakeUPPERCase(cControlTypeName));
    2352             : 
    2353      413012 :     EMSActuatorKey const key(UpperCaseObjectType, UpperCaseObjectName, UpperCaseActuatorName);
    2354             : 
    2355      206506 :     if (state.dataRuntimeLang->EMSActuator_lookup.find(key) == state.dataRuntimeLang->EMSActuator_lookup.end()) {
    2356      206466 :         if (state.dataRuntimeLang->numEMSActuatorsAvailable == 0) {
    2357          71 :             state.dataRuntimeLang->EMSActuatorAvailable.allocate(state.dataRuntimeLang->varsAvailableAllocInc);
    2358          71 :             state.dataRuntimeLang->numEMSActuatorsAvailable = 1;
    2359          71 :             state.dataRuntimeLang->maxEMSActuatorsAvailable = state.dataRuntimeLang->varsAvailableAllocInc;
    2360             :         } else {
    2361      206395 :             if (state.dataRuntimeLang->numEMSActuatorsAvailable + 1 > state.dataRuntimeLang->maxEMSActuatorsAvailable) {
    2362          85 :                 state.dataRuntimeLang->EMSActuatorAvailable.redimension(state.dataRuntimeLang->maxEMSActuatorsAvailable *= 2);
    2363             :             }
    2364      206395 :             ++state.dataRuntimeLang->numEMSActuatorsAvailable;
    2365             :         }
    2366             : 
    2367      206466 :         auto &actuator(state.dataRuntimeLang->EMSActuatorAvailable(state.dataRuntimeLang->numEMSActuatorsAvailable));
    2368      206466 :         actuator.ComponentTypeName = cComponentTypeName;
    2369      206466 :         actuator.UniqueIDName = cUniqueIDName;
    2370      206466 :         actuator.ControlTypeName = cControlTypeName;
    2371      206466 :         actuator.Units = cUnits;
    2372      206466 :         actuator.Actuated = &lEMSActuated; // Pointer assigment
    2373      206466 :         actuator.RealValue = &rValue;      // Pointer assigment
    2374      206466 :         actuator.PntrVarTypeUsed = PtrDataType::Real;
    2375      206466 :         state.dataRuntimeLang->EMSActuator_lookup.insert(key);
    2376             :     }
    2377      206506 : }
    2378             : 
    2379       11164 : void SetupEMSActuator(EnergyPlusData &state,
    2380             :                       std::string_view cComponentTypeName,
    2381             :                       std::string_view cUniqueIDName,
    2382             :                       std::string_view cControlTypeName,
    2383             :                       std::string_view cUnits,
    2384             :                       bool &lEMSActuated,
    2385             :                       int &iValue)
    2386             : {
    2387             : 
    2388             :     // SUBROUTINE INFORMATION:
    2389             :     //       AUTHOR         Brent Griffith
    2390             :     //       DATE WRITTEN   May 2009
    2391             :     //       MODIFIED
    2392             :     //       RE-ENGINEERED  na
    2393             : 
    2394             :     // PURPOSE OF THIS SUBROUTINE:
    2395             :     // register a new actuator for EMS
    2396             :     //   set  up pointer to logical and integer value
    2397             : 
    2398             :     // METHODOLOGY EMPLOYED:
    2399             :     // push size of ActuatorVariable and add a new one.
    2400             :     //  check for duplicates.
    2401             : 
    2402             :     // Using/Aliasing
    2403             :     using namespace DataRuntimeLanguage;
    2404             : 
    2405       22328 :     std::string const UpperCaseObjectType(UtilityRoutines::MakeUPPERCase(cComponentTypeName));
    2406       22328 :     std::string const UpperCaseObjectName(UtilityRoutines::MakeUPPERCase(cUniqueIDName));
    2407       22328 :     std::string const UpperCaseActuatorName(UtilityRoutines::MakeUPPERCase(cControlTypeName));
    2408             : 
    2409       22328 :     EMSActuatorKey const key(UpperCaseObjectType, UpperCaseObjectName, UpperCaseActuatorName);
    2410             : 
    2411       11164 :     if (state.dataRuntimeLang->EMSActuator_lookup.find(key) == state.dataRuntimeLang->EMSActuator_lookup.end()) {
    2412       11164 :         if (state.dataRuntimeLang->numEMSActuatorsAvailable == 0) {
    2413           0 :             state.dataRuntimeLang->EMSActuatorAvailable.allocate(state.dataRuntimeLang->varsAvailableAllocInc);
    2414           0 :             state.dataRuntimeLang->numEMSActuatorsAvailable = 1;
    2415           0 :             state.dataRuntimeLang->maxEMSActuatorsAvailable = state.dataRuntimeLang->varsAvailableAllocInc;
    2416             :         } else {
    2417       11164 :             if (state.dataRuntimeLang->numEMSActuatorsAvailable + 1 > state.dataRuntimeLang->maxEMSActuatorsAvailable) {
    2418           7 :                 state.dataRuntimeLang->EMSActuatorAvailable.redimension(state.dataRuntimeLang->maxEMSActuatorsAvailable *= 2);
    2419             :             }
    2420       11164 :             ++state.dataRuntimeLang->numEMSActuatorsAvailable;
    2421             :         }
    2422             : 
    2423       11164 :         auto &actuator(state.dataRuntimeLang->EMSActuatorAvailable(state.dataRuntimeLang->numEMSActuatorsAvailable));
    2424       11164 :         actuator.ComponentTypeName = cComponentTypeName;
    2425       11164 :         actuator.UniqueIDName = cUniqueIDName;
    2426       11164 :         actuator.ControlTypeName = cControlTypeName;
    2427       11164 :         actuator.Units = cUnits;
    2428       11164 :         actuator.Actuated = &lEMSActuated; // Pointer assigment
    2429       11164 :         actuator.IntValue = &iValue;       // Pointer assigment
    2430       11164 :         actuator.PntrVarTypeUsed = PtrDataType::Integer;
    2431       11164 :         state.dataRuntimeLang->EMSActuator_lookup.insert(key);
    2432             :     }
    2433       11164 : }
    2434             : 
    2435           0 : void SetupEMSActuator(EnergyPlusData &state,
    2436             :                       std::string_view cComponentTypeName,
    2437             :                       std::string_view cUniqueIDName,
    2438             :                       std::string_view cControlTypeName,
    2439             :                       std::string_view cUnits,
    2440             :                       bool &lEMSActuated,
    2441             :                       bool &lValue)
    2442             : {
    2443             : 
    2444             :     // SUBROUTINE INFORMATION:
    2445             :     //       AUTHOR         Brent Griffith
    2446             :     //       DATE WRITTEN   August 2009
    2447             :     //       MODIFIED
    2448             :     //       RE-ENGINEERED  na
    2449             : 
    2450             :     // PURPOSE OF THIS SUBROUTINE:
    2451             :     // register a new actuator for EMS
    2452             :     //   set  up pointer to logical and logical value
    2453             : 
    2454             :     // METHODOLOGY EMPLOYED:
    2455             :     // push size of ActuatorVariable and add a new one.
    2456             :     //  check for duplicates.
    2457             : 
    2458             :     // Using/Aliasing
    2459             :     using namespace DataRuntimeLanguage;
    2460             : 
    2461           0 :     std::string const UpperCaseObjectType(UtilityRoutines::MakeUPPERCase(cComponentTypeName));
    2462           0 :     std::string const UpperCaseObjectName(UtilityRoutines::MakeUPPERCase(cUniqueIDName));
    2463           0 :     std::string const UpperCaseActuatorName(UtilityRoutines::MakeUPPERCase(cControlTypeName));
    2464             : 
    2465           0 :     EMSActuatorKey const key(UpperCaseObjectType, UpperCaseObjectName, UpperCaseActuatorName);
    2466             : 
    2467           0 :     if (state.dataRuntimeLang->EMSActuator_lookup.find(key) == state.dataRuntimeLang->EMSActuator_lookup.end()) {
    2468           0 :         if (state.dataRuntimeLang->numEMSActuatorsAvailable == 0) {
    2469           0 :             state.dataRuntimeLang->EMSActuatorAvailable.allocate(state.dataRuntimeLang->varsAvailableAllocInc);
    2470           0 :             state.dataRuntimeLang->numEMSActuatorsAvailable = 1;
    2471           0 :             state.dataRuntimeLang->maxEMSActuatorsAvailable = state.dataRuntimeLang->varsAvailableAllocInc;
    2472             :         } else {
    2473           0 :             if (state.dataRuntimeLang->numEMSActuatorsAvailable + 1 > state.dataRuntimeLang->maxEMSActuatorsAvailable) {
    2474           0 :                 state.dataRuntimeLang->EMSActuatorAvailable.redimension(state.dataRuntimeLang->maxEMSActuatorsAvailable *= 2);
    2475             :             }
    2476           0 :             ++state.dataRuntimeLang->numEMSActuatorsAvailable;
    2477             :         }
    2478             : 
    2479           0 :         auto &actuator(state.dataRuntimeLang->EMSActuatorAvailable(state.dataRuntimeLang->numEMSActuatorsAvailable));
    2480           0 :         actuator.ComponentTypeName = cComponentTypeName;
    2481           0 :         actuator.UniqueIDName = cUniqueIDName;
    2482           0 :         actuator.ControlTypeName = cControlTypeName;
    2483           0 :         actuator.Units = cUnits;
    2484           0 :         actuator.Actuated = &lEMSActuated; // Pointer assigment
    2485           0 :         actuator.LogValue = &lValue;       // Pointer assigment
    2486           0 :         actuator.PntrVarTypeUsed = PtrDataType::Logical;
    2487           0 :         state.dataRuntimeLang->EMSActuator_lookup.insert(key);
    2488             :     }
    2489           0 : }
    2490             : 
    2491       34409 : void SetupEMSInternalVariable(
    2492             :     EnergyPlusData &state, std::string_view cDataTypeName, std::string_view cUniqueIDName, std::string_view cUnits, Real64 &rValue)
    2493             : {
    2494             : 
    2495             :     // SUBROUTINE INFORMATION:
    2496             :     //       AUTHOR         Brent Griffith
    2497             :     //       DATE WRITTEN   May 2009
    2498             :     //       MODIFIED       na
    2499             :     //       RE-ENGINEERED  na
    2500             : 
    2501             :     // PURPOSE OF THIS SUBROUTINE:
    2502             :     // Setup internal data source and make available to EMS
    2503             : 
    2504             :     // Using/Aliasing
    2505             :     using namespace DataRuntimeLanguage;
    2506             : 
    2507             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2508             :     int InternalVarAvailNum; // loop index
    2509             :     bool FoundInternalDataType;
    2510             :     bool FoundDuplicate;
    2511             : 
    2512             :     // Object Data
    2513             : 
    2514       34409 :     FoundInternalDataType = false;
    2515       34409 :     FoundDuplicate = false;
    2516             : 
    2517    32057210 :     for (InternalVarAvailNum = 1; InternalVarAvailNum <= state.dataRuntimeLang->numEMSInternalVarsAvailable; ++InternalVarAvailNum) {
    2518    32836690 :         if ((UtilityRoutines::SameString(cDataTypeName, state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).DataTypeName)) &&
    2519      813889 :             (UtilityRoutines::SameString(cUniqueIDName, state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).UniqueIDName))) {
    2520           0 :             FoundDuplicate = true;
    2521           0 :             break;
    2522             :         }
    2523             :     }
    2524             : 
    2525       34409 :     if (FoundDuplicate) {
    2526           0 :         ShowSevereError(state, "Duplicate internal variable was sent to SetupEMSInternalVariable.");
    2527           0 :         ShowContinueError(state, "Internal variable type = " + std::string{cDataTypeName} + " ; name = " + std::string{cUniqueIDName});
    2528           0 :         ShowContinueError(state, "Called from SetupEMSInternalVariable.");
    2529             :     } else {
    2530             :         // add new internal data variable
    2531       34409 :         if (state.dataRuntimeLang->numEMSInternalVarsAvailable == 0) {
    2532         343 :             state.dataRuntimeLang->EMSInternalVarsAvailable.allocate(state.dataRuntimeLang->varsAvailableAllocInc);
    2533         343 :             state.dataRuntimeLang->numEMSInternalVarsAvailable = 1;
    2534         343 :             state.dataRuntimeLang->maxEMSInternalVarsAvailable = state.dataRuntimeLang->varsAvailableAllocInc;
    2535             :         } else {
    2536       34066 :             if (state.dataRuntimeLang->numEMSInternalVarsAvailable + 1 > state.dataRuntimeLang->maxEMSInternalVarsAvailable) {
    2537          60 :                 state.dataRuntimeLang->EMSInternalVarsAvailable.redimension(state.dataRuntimeLang->maxEMSInternalVarsAvailable +=
    2538          60 :                                                                             state.dataRuntimeLang->varsAvailableAllocInc);
    2539             :             }
    2540       34066 :             ++state.dataRuntimeLang->numEMSInternalVarsAvailable;
    2541             :         }
    2542             : 
    2543       34409 :         InternalVarAvailNum = state.dataRuntimeLang->numEMSInternalVarsAvailable;
    2544       34409 :         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).DataTypeName = cDataTypeName;
    2545       34409 :         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).UniqueIDName = cUniqueIDName;
    2546       34409 :         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).Units = cUnits;
    2547       34409 :         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).RealValue = &rValue;
    2548       34409 :         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).PntrVarTypeUsed = PtrDataType::Real;
    2549             :     }
    2550       34409 : }
    2551             : 
    2552        2224 : void SetupEMSInternalVariable(
    2553             :     EnergyPlusData &state, std::string_view cDataTypeName, std::string_view cUniqueIDName, std::string_view cUnits, int &iValue)
    2554             : {
    2555             : 
    2556             :     // SUBROUTINE INFORMATION:
    2557             :     //       AUTHOR         Brent Griffith
    2558             :     //       DATE WRITTEN   May 2009
    2559             :     //       MODIFIED       na
    2560             :     //       RE-ENGINEERED  na
    2561             : 
    2562             :     // PURPOSE OF THIS SUBROUTINE:
    2563             :     // Setup internal data source and make available to EMS
    2564             : 
    2565             :     // Using/Aliasing
    2566             :     using namespace DataRuntimeLanguage;
    2567             : 
    2568             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2569             :     int InternalVarAvailNum; // loop index
    2570             :     bool FoundInternalDataType;
    2571             :     bool FoundDuplicate;
    2572             : 
    2573             :     // Object Data
    2574             : 
    2575        2224 :     FoundInternalDataType = false;
    2576        2224 :     FoundDuplicate = false;
    2577             : 
    2578      595552 :     for (InternalVarAvailNum = 1; InternalVarAvailNum <= state.dataRuntimeLang->numEMSInternalVarsAvailable; ++InternalVarAvailNum) {
    2579      651372 :         if ((UtilityRoutines::SameString(cDataTypeName, state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).DataTypeName)) &&
    2580       58044 :             (UtilityRoutines::SameString(cUniqueIDName, state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).UniqueIDName))) {
    2581           0 :             FoundDuplicate = true;
    2582           0 :             break;
    2583             :         }
    2584             :     }
    2585             : 
    2586        2224 :     if (FoundDuplicate) {
    2587           0 :         ShowSevereError(state, "Duplicate internal variable was sent to SetupEMSInternalVariable.");
    2588           0 :         ShowContinueError(state, "Internal variable type = " + std::string{cDataTypeName} + " ; name = " + std::string{cUniqueIDName});
    2589           0 :         ShowContinueError(state, "called from SetupEMSInternalVariable");
    2590             :     } else {
    2591             :         // add new internal data variable
    2592        2224 :         if (state.dataRuntimeLang->numEMSInternalVarsAvailable == 0) {
    2593           0 :             state.dataRuntimeLang->EMSInternalVarsAvailable.allocate(state.dataRuntimeLang->varsAvailableAllocInc);
    2594           0 :             state.dataRuntimeLang->numEMSInternalVarsAvailable = 1;
    2595           0 :             state.dataRuntimeLang->maxEMSInternalVarsAvailable = state.dataRuntimeLang->varsAvailableAllocInc;
    2596             :         } else {
    2597        2224 :             if (state.dataRuntimeLang->numEMSInternalVarsAvailable + 1 > state.dataRuntimeLang->maxEMSInternalVarsAvailable) {
    2598           0 :                 state.dataRuntimeLang->EMSInternalVarsAvailable.redimension(state.dataRuntimeLang->maxEMSInternalVarsAvailable +=
    2599           0 :                                                                             state.dataRuntimeLang->varsAvailableAllocInc);
    2600             :             }
    2601        2224 :             ++state.dataRuntimeLang->numEMSInternalVarsAvailable;
    2602             :         }
    2603             : 
    2604        2224 :         InternalVarAvailNum = state.dataRuntimeLang->numEMSInternalVarsAvailable;
    2605        2224 :         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).DataTypeName = cDataTypeName;
    2606        2224 :         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).UniqueIDName = cUniqueIDName;
    2607        2224 :         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).Units = cUnits;
    2608        2224 :         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).IntValue = &iValue;
    2609        2224 :         state.dataRuntimeLang->EMSInternalVarsAvailable(InternalVarAvailNum).PntrVarTypeUsed = PtrDataType::Integer;
    2610             :     }
    2611        2224 : }
    2612             : 
    2613        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13