Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : #ifndef ExternalInterface_hh_INCLUDED
49 : #define ExternalInterface_hh_INCLUDED
50 :
51 : // FMI-Related Headers
52 : extern "C" {
53 : #include <FMI/main.h>
54 : }
55 :
56 : // EnergyPlus Headers
57 : #include <EnergyPlus/Data/BaseData.hh>
58 : #include <EnergyPlus/EnergyPlus.hh>
59 : #include <EnergyPlus/ExternalInterface.hh>
60 : #include <EnergyPlus/FileSystem.hh>
61 : #include <EnergyPlus/OutputProcessor.hh>
62 :
63 : // C++ Standard Library Headers
64 : #include <string>
65 :
66 : // Objexx Headers
67 : #include <ObjexxFCL/Array1D.hh>
68 :
69 : namespace EnergyPlus {
70 :
71 : // Forward declarations
72 : struct EnergyPlusData;
73 :
74 : namespace ExternalInterface {
75 :
76 : // MODULE PARAMETER DEFINITIONS:
77 : int constexpr maxVar(100000); // Maximum number of variables to be exchanged
78 : int constexpr maxErrMsgLength(10000); // Maximum error message length from xml schema validation
79 :
80 : // can't change these to enum class since these are used in getepvariables() in utilXml.c as arguments
81 : int constexpr indexSchedule(1); // Index for schedule in inpVarTypes
82 : int constexpr indexVariable(2); // Index for variable in inpVarTypes
83 : int constexpr indexActuator(3); // Index for actuator in inpVarTypes
84 :
85 : // can't change these to enum class since these are compared to fmistatus defined in hmiModelFunctions.h
86 : int constexpr fmiOK(0); // fmiOK
87 : int constexpr fmiWarning(1); // fmiWarning
88 : int constexpr fmiDiscard(2); // fmiDiscard
89 : int constexpr fmiError(3); // fmiError
90 : int constexpr fmiFatal(4); // fmiPending
91 : int constexpr fmiPending(5); // fmiPending
92 :
93 : struct fmuInputVariableType
94 : {
95 :
96 : std::string Name; // Name of FMU input variable
97 : int ValueReference; // = fmiValueReference specific to FMU variable
98 :
99 : // Default Constructor
100 9 : fmuInputVariableType() : Name(std::string()), ValueReference(0)
101 : {
102 9 : }
103 : };
104 :
105 : struct checkFMUInstanceNameType
106 : {
107 :
108 : std::string Name; // Name of fmu instance
109 :
110 : // Default Constructor
111 3 : checkFMUInstanceNameType() : Name(std::string())
112 : {
113 3 : }
114 : };
115 :
116 : struct eplusOutputVariableType
117 : {
118 :
119 : std::string Name; // Variable name in EnergyPlus
120 : std::string VarKey; // Key value in EnergyPlus
121 : Real64 RTSValue; // Real value of variable at the Zone Time Step
122 : int ITSValue; // Integer value of variable at the Zone Time Step
123 : int VarIndex; // Index Value of variable
124 : OutputProcessor::VariableType VarType; // Type of variable at the Zone Time Step
125 : std::string VarUnits; // Units string, may be blank
126 :
127 : // Default Constructor
128 6 : eplusOutputVariableType()
129 6 : : Name(std::string()), VarKey(std::string()), RTSValue(0.0), ITSValue(0), VarIndex(0), VarType(OutputProcessor::VariableType::Invalid),
130 6 : VarUnits(std::string())
131 : {
132 6 : }
133 : };
134 :
135 : struct fmuOutputVariableScheduleType
136 : {
137 :
138 : std::string Name; // Name of fmu output variable --> schedule in energyplus
139 : Real64 RealVarValue; // = Real value at the Zone Time Step
140 : int ValueReference; // = fmiValueReference specific to FMU variable
141 :
142 : // Default Constructor
143 6 : fmuOutputVariableScheduleType() : Name(std::string()), RealVarValue(0.0), ValueReference(0)
144 : {
145 6 : }
146 : };
147 :
148 : struct fmuOutputVariableVariableType
149 : {
150 :
151 : std::string Name; // Name of fmu output variable --> variable in energyplus
152 : Real64 RealVarValue; // = Real value at the Zone Time Step
153 : int ValueReference; // = fmiValueReference specific to FMU variable
154 :
155 : // Default Constructor
156 6 : fmuOutputVariableVariableType() : Name(std::string()), RealVarValue(0.0), ValueReference(0)
157 : {
158 6 : }
159 : };
160 :
161 : struct fmuOutputVariableActuatorType
162 : {
163 :
164 : std::string Name; // Name of fmu output variable --> actuator in energyplus
165 : Real64 RealVarValue; // = Real value at the Zone Time Step
166 : int ValueReference; // = fmiValueReference specific to FMU variable
167 :
168 : // Default Constructor
169 6 : fmuOutputVariableActuatorType() : Name(std::string()), RealVarValue(0.0), ValueReference(0)
170 : {
171 6 : }
172 : };
173 :
174 : struct eplusInputVariableScheduleType
175 : {
176 :
177 : std::string Name; // Name of energyplus input variable from Type schedule
178 : int VarIndex; // Index Value of this variable
179 : int InitialValue; // Initial value used during the warmup
180 :
181 : // Default Constructor
182 3 : eplusInputVariableScheduleType() : Name(std::string()), VarIndex(0)
183 : {
184 : // InitialValue not initialized in default constructor
185 3 : }
186 : };
187 :
188 : struct eplusInputVariableVariableType
189 : {
190 :
191 : std::string Name; // Name of energyplus input variable from Type variable
192 : int VarIndex; // Index Value of this variable
193 :
194 : // Default Constructor
195 3 : eplusInputVariableVariableType() : Name(std::string()), VarIndex(0)
196 : {
197 3 : }
198 : };
199 :
200 : struct eplusInputVariableActuatorType
201 : {
202 :
203 : std::string Name; // Name of energyplus input variable from Type actuator
204 : int VarIndex; // Index Value of this variable
205 :
206 : // Default Constructor
207 3 : eplusInputVariableActuatorType() : Name(std::string()), VarIndex(0)
208 : {
209 3 : }
210 : };
211 :
212 : struct InstanceType
213 : {
214 :
215 : std::string Name; // FMU Filename
216 : std::string modelID; // FMU modelID
217 : std::string modelGUID; // FMU modelGUID
218 : fs::path WorkingFolder; // Path to the FMU wokring folder
219 : fs::path WorkingFolder_wLib; // Path to the binaries
220 : std::string fmiVersionNumber; // Version number of FMI used
221 : int NumInputVariablesInFMU; // Number of input variables in fmu
222 : int NumInputVariablesInIDF; // Number of fmus input variables in idf
223 : int NumOutputVariablesInFMU; // Number of output variables in fmu
224 : int NumOutputVariablesInIDF; // Number of output variables in idf
225 : int NumOutputVariablesSchedule; // Number of output variables from type schedule
226 : int NumOutputVariablesVariable; // Number of output variables from type variable
227 : int NumOutputVariablesActuator; // Number of output variables from type actuator
228 : int LenModelID; // Length of modelID trimmed
229 : int LenModelGUID; // Length of modelGUID trimmed
230 : int LenWorkingFolder; // Length of working folder trimmed
231 : int LenWorkingFolder_wLib; // Length of working folder with libraries trimmed
232 : fmiComponent fmicomponent; // FMU instance
233 : fmiStatus fmistatus; // Status of fmi
234 : int Index; // Index of FMU
235 : // Variable Types structure for fmu input variables
236 : Array1D<fmuInputVariableType> fmuInputVariable;
237 : // Variable Types structure for checking duplicates fmu input variables
238 : Array1D<fmuInputVariableType> checkfmuInputVariable;
239 : // Variable Types structure for energyplus output variables
240 : Array1D<eplusOutputVariableType> eplusOutputVariable;
241 : // Variable Types structure for fmu output variables from type schedule
242 : Array1D<fmuOutputVariableScheduleType> fmuOutputVariableSchedule;
243 : // Variable Types structure for energyplus input variables from type schedule
244 : Array1D<eplusInputVariableScheduleType> eplusInputVariableSchedule;
245 : // Variable Types structure for fmu output variables from type variable
246 : Array1D<fmuOutputVariableVariableType> fmuOutputVariableVariable;
247 : // Variable Types structure for energyplus input variables from type variable
248 : Array1D<eplusInputVariableVariableType> eplusInputVariableVariable;
249 : // Variable Types structure for fmu output variables from type actuator
250 : Array1D<fmuOutputVariableActuatorType> fmuOutputVariableActuator;
251 : // Variable Types structure for energyplus input variables from type actuator
252 : Array1D<eplusInputVariableActuatorType> eplusInputVariableActuator;
253 :
254 : // Default Constructor
255 6 : InstanceType()
256 6 : : Name(std::string()), modelID(std::string()), modelGUID(std::string()), WorkingFolder(fs::path()), WorkingFolder_wLib(fs::path()),
257 6 : fmiVersionNumber(std::string()), NumInputVariablesInFMU(0), NumInputVariablesInIDF(0), NumOutputVariablesInFMU(0),
258 6 : NumOutputVariablesInIDF(0), NumOutputVariablesSchedule(0), NumOutputVariablesVariable(0), NumOutputVariablesActuator(0), LenModelID(0),
259 6 : LenModelGUID(0), LenWorkingFolder(0), LenWorkingFolder_wLib(0)
260 : {
261 : // fmiStatus, Index, and arrays not initialized in default constructor
262 6 : }
263 : };
264 :
265 : struct FMUType
266 : {
267 :
268 : std::string Name; // FMU Filename
269 : Real64 TimeOut; // Default TimeOut value
270 : int Visible; // Default Visible value
271 : int Interactive; // Default Interactive value
272 : int LoggingOn; // Default LoggingOn value
273 : int NumInstances; // Number of Instances
274 : int TotNumInputVariablesInIDF; // Number of input variables
275 : int TotNumOutputVariablesSchedule; // Number of output variables from type schedule
276 : int TotNumOutputVariablesVariable; // Number of output variables from type variable
277 : int TotNumOutputVariablesActuator; // Number of output variables from type actuator
278 : Array1D<InstanceType> Instance; // Variable Types structure for energyplus input variables from type actuator
279 :
280 : // Default Constructor
281 6 : FMUType()
282 6 : : Name(std::string()), TimeOut(0.0), Visible(0), Interactive(0), LoggingOn(0), NumInstances(0), TotNumInputVariablesInIDF(0),
283 6 : TotNumOutputVariablesSchedule(0), TotNumOutputVariablesVariable(0), TotNumOutputVariablesActuator(0)
284 : {
285 : // Instance not instantiated in default constructor
286 6 : }
287 : };
288 :
289 : // Functions
290 :
291 : void ExternalInterfaceExchangeVariables(EnergyPlusData &state);
292 :
293 : void CloseSocket(EnergyPlusData &state, int FlagToWriteToSocket);
294 :
295 : void InitExternalInterface(EnergyPlusData &state);
296 :
297 : void GetExternalInterfaceInput(EnergyPlusData &state);
298 :
299 : void CalcExternalInterface(EnergyPlusData &state);
300 :
301 : void ParseString(std::string const &str, Array1D_string &ele, int nEle);
302 :
303 : void GetReportVariableKey(EnergyPlusData &state,
304 : const Array1D_string &varKeys,
305 : int numberOfKeys,
306 : const Array1D_string &varNames,
307 : Array1D_int &keyVarIndexes,
308 : Array1D<OutputProcessor::VariableType> &varTypes);
309 :
310 : std::vector<char> getCharArrayFromString(std::string const &originalString);
311 :
312 : std::string getStringFromCharArray(std::vector<char> originalCharArray);
313 :
314 : void StopExternalInterfaceIfError(EnergyPlusData &state);
315 :
316 : void ValidateRunControl(EnergyPlusData &state);
317 :
318 : void WarnIfExternalInterfaceObjectsAreUsed(EnergyPlusData &state, std::string const &ObjectWord);
319 :
320 : void CalcExternalInterfaceFMUImport(EnergyPlusData &state);
321 :
322 : void InitExternalInterfaceFMUImport(EnergyPlusData &state);
323 :
324 : void InstantiateInitializeFMUImport(EnergyPlusData &state);
325 :
326 : void TerminateResetFreeFMUImport(EnergyPlusData &state, int fmiEndSimulation);
327 :
328 : void GetSetVariablesAndDoStepFMUImport(EnergyPlusData &state);
329 :
330 : void VerifyExternalInterfaceObject(EnergyPlusData &state);
331 :
332 : Real64 GetCurSimStartTimeSeconds(const EnergyPlusData &state);
333 :
334 : std::string trim(std::string const &str);
335 :
336 : } // namespace ExternalInterface
337 :
338 : struct ExternalInterfaceData : BaseGlobalStruct
339 : {
340 : Real64 tComm = 0.0;
341 : Real64 tStop = 3600.0;
342 : Real64 tStart = 0.0;
343 : Real64 hStep = 15.0;
344 : bool FlagReIni = false;
345 : fs::path FMURootWorkingFolder;
346 : int nInKeys = 3; // Number of input variables available in ExternalInterface (=highest index* number)
347 :
348 : Array1D<ExternalInterface::FMUType> FMU; // Variable Types structure
349 : Array1D<ExternalInterface::FMUType> FMUTemp; // Variable Types structure
350 : Array1D<ExternalInterface::checkFMUInstanceNameType> checkInstanceName; // Variable Types structure for checking instance names
351 :
352 : int NumExternalInterfaces = 0; // Number of ExternalInterface objects
353 : int NumExternalInterfacesBCVTB = 0; // Number of BCVTB ExternalInterface objects
354 : int NumExternalInterfacesFMUImport = 0; // Number of FMU ExternalInterface objects
355 : int NumExternalInterfacesFMUExport = 0; // Number of FMU ExternalInterface objects
356 : int NumFMUObjects = 0; // Number of FMU objects
357 : int FMUExportActivate = 0; // FMU Export flag
358 : bool haveExternalInterfaceBCVTB = false; // Flag for BCVTB interface
359 : bool haveExternalInterfaceFMUImport = false; // Flag for FMU-Import interface
360 : bool haveExternalInterfaceFMUExport = false; // Flag for FMU-Export interface
361 : int simulationStatus = 1; // Status flag. Used to report during which phase an error occurred. (1=initialization, 2=time stepping)
362 :
363 : Array1D<int> keyVarIndexes; // Array index for specific key name
364 : Array1D<OutputProcessor::VariableType> varTypes; // Types of variables in keyVarIndexes
365 : Array1D<int> varInd; // Index of ErlVariables for ExternalInterface
366 : int socketFD = -1; // socket file descriptor
367 : bool ErrorsFound = false; // Set to true if errors are found
368 : bool noMoreValues = false; // Flag, true if no more values will be sent by the server
369 :
370 : Array1D<std::string> varKeys; // Keys of report variables used for data exchange
371 : Array1D<std::string> varNames; // Names of report variables used for data exchange
372 : Array1D<int> inpVarTypes; // Names of report variables used for data exchange
373 : Array1D<std::string> inpVarNames; // Names of report variables used for data exchange
374 :
375 : bool configuredControlPoints = false; // True if control points have been configured
376 : bool useEMS = false; // Will be set to true if ExternalInterface writes to EMS variables or actuators
377 :
378 : bool firstCall = true;
379 : bool showContinuationWithoutUpdate = true;
380 : bool GetInputFlag = true; // First time, input is "gotten"
381 : bool InitExternalInterfacefirstCall = true;
382 : bool FirstCallGetSetDoStep = true; // Flag to check when External Interface is called first time
383 : bool FirstCallIni = true; // First time, input has been read
384 : bool FirstCallDesignDays = true; // Flag fo first call during warmup
385 : bool FirstCallWUp = true; // Flag fo first call during warmup
386 : bool FirstCallTStep = true; // Flag for first call during time stepping
387 : int fmiEndSimulation = 0; // Flag to indicate end of simulation
388 :
389 : fs::path const socCfgFilPath = "socket.cfg"; // socket configuration file
390 : std::unordered_map<std::string, std::string> UniqueFMUInputVarNames;
391 :
392 : int nOutVal; // Number of output values (E+ -> ExternalInterface)
393 : int nInpVar; // Number of input values (ExternalInterface -> E+)
394 :
395 796 : void init_state([[maybe_unused]] EnergyPlusData &state) override
396 : {
397 796 : }
398 :
399 0 : void clear_state() override
400 : {
401 0 : this->tComm = 0.0;
402 0 : this->tStop = 3600.0;
403 0 : this->tStart = 0.0;
404 0 : this->hStep = 15.0;
405 0 : this->FlagReIni = false;
406 0 : this->FMURootWorkingFolder.clear();
407 0 : this->nInKeys = 3; // Number of input variables available in ExternalInterface (=highest index* number)
408 :
409 0 : this->FMU.clear(); // Variable Types structure
410 0 : this->FMUTemp.clear(); // Variable Types structure
411 0 : this->checkInstanceName.clear(); // Variable Types structure for checking instance names
412 :
413 0 : this->NumExternalInterfaces = 0; // Number of ExternalInterface objects
414 0 : this->NumExternalInterfacesBCVTB = 0; // Number of BCVTB ExternalInterface objects
415 0 : this->NumExternalInterfacesFMUImport = 0; // Number of FMU ExternalInterface objects
416 0 : this->NumExternalInterfacesFMUExport = 0; // Number of FMU ExternalInterface objects
417 0 : this->NumFMUObjects = 0; // Number of FMU objects
418 0 : this->FMUExportActivate = 0; // FMU Export flag
419 0 : this->haveExternalInterfaceBCVTB = false; // Flag for BCVTB interface
420 0 : this->haveExternalInterfaceFMUImport = false; // Flag for FMU-Import interface
421 0 : this->haveExternalInterfaceFMUExport = false; // Flag for FMU-Export interface
422 0 : this->simulationStatus = 1; // Status flag. Used to report during which phase an error occurred. (1=initialization, 2=time stepping)
423 :
424 0 : this->keyVarIndexes.clear(); // Array index for specific key name
425 0 : this->varTypes.clear(); // Types of variables in keyVarIndexes
426 0 : this->varInd.clear(); // Index of ErlVariables for ExternalInterface
427 0 : this->socketFD = -1; // socket file descriptor
428 0 : this->ErrorsFound = false; // Set to true if errors are found
429 0 : this->noMoreValues = false; // Flag, true if no more values will be sent by the server
430 :
431 0 : this->varKeys.clear(); // Keys of report variables used for data exchange
432 0 : this->varNames.clear(); // Names of report variables used for data exchange
433 0 : this->inpVarTypes.clear(); // Names of report variables used for data exchange
434 0 : this->inpVarNames.clear(); // Names of report variables used for data exchange
435 :
436 0 : this->configuredControlPoints = false; // True if control points have been configured
437 0 : this->useEMS = false; // Will be set to true if ExternalInterface writes to EMS variables or actuators
438 0 : this->firstCall = true;
439 0 : this->showContinuationWithoutUpdate = true;
440 0 : this->GetInputFlag = true; // First time, input is "gotten"
441 0 : this->InitExternalInterfacefirstCall = true;
442 0 : this->FirstCallGetSetDoStep = true; // Flag to check when External Interface is called first time
443 0 : this->FirstCallIni = true; // First time, input has been read
444 0 : this->FirstCallDesignDays = true; // Flag fo first call during warmup
445 0 : this->FirstCallWUp = true; // Flag fo first call during warmup
446 0 : this->FirstCallTStep = true; // Flag for first call during time stepping
447 0 : this->fmiEndSimulation = 0; // Flag to indicate end of simulation
448 0 : this->UniqueFMUInputVarNames.clear();
449 :
450 : // these were statics without an initial value
451 : // int nOutVal; // Number of output values (E+ -> ExternalInterface)
452 : // int nInpVar; // Number of input values (ExternalInterface -> E+)
453 0 : }
454 : };
455 :
456 : } // namespace EnergyPlus
457 :
458 : #endif
|