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
|