Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/fmi/fmi2Functions.c
169665 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2020-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file fmi2Functions.c
15
/// @author Robert Hilbrich
16
/// @author Matthias Schwamborn
17
/// @date Tue, 03 Mar 2020
18
///
19
// Implementation of the FMI2 interface functions
20
/****************************************************************************/
21
22
#ifdef _MSC_VER
23
// Avoid warnings in windows build because of strcpy instead of strcpy_s,
24
// because the latter is not available on all platforms
25
#define _CRT_SECURE_NO_WARNINGS
26
#pragma warning(disable:4820 4514 5045)
27
#endif
28
29
#include <string.h>
30
#include <stdio.h>
31
#include <stdarg.h>
32
#include <foreign/fmi/fmi2Functions.h>
33
#include "sumo2fmi_bridge.h"
34
#include "libsumocpp2c.h"
35
36
/* Explicit definition of unused parameters to avoid compiler warnings */
37
#define UNUSED_PARAMETER(x) ((void)(x))
38
39
/* **********************************************************************************************
40
* * IMPLEMENTATION OF GENERIC FUNCTIONALITY
41
* **********************************************************************************************/
42
const char* fmi2GetTypesPlatform(void) {
43
return fmi2TypesPlatform;
44
}
45
46
const char* fmi2GetVersion(void) {
47
return fmi2Version;
48
}
49
50
/* ***********************************************************************************************
51
* CREATION AND DESTRUCTION OF AN FMU
52
***********************************************************************************************/
53
54
/* Define what should be logged - if logging is enabled globally */
55
fmi2Status
56
fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) {
57
58
ModelInstance* comp = (ModelInstance*)c;
59
60
if (loggingOn) {
61
size_t i;
62
for (i = 0; i < nCategories; i++) {
63
if (categories[i] == NULL) {
64
sumo2fmi_logError(comp, "Log category[%d] must not be NULL", i);
65
return fmi2Error;
66
} else if (strcmp(categories[i], "logStatusError") == 0) {
67
comp->logErrors = true;
68
} else if (strcmp(categories[i], "logEvents") == 0) {
69
comp->logEvents = true;
70
} else {
71
sumo2fmi_logError(comp, "Log category[%d] must be one of logEvents or logStatusError but was %s", i, categories[i]);
72
return fmi2Error;
73
}
74
}
75
} else {
76
// Logging is disabled globally, no need for a more fine grained logging
77
comp->logEvents = false;
78
comp->logErrors = false;
79
}
80
81
return fmi2OK;
82
}
83
84
/* The function returns a new instance of an FMU. If a null pointer is returned, then instantiation
85
failed.*/
86
fmi2Component
87
fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID,
88
fmi2String fmuResourceLocation, const fmi2CallbackFunctions* functions,
89
fmi2Boolean visible, fmi2Boolean loggingOn) {
90
UNUSED_PARAMETER(fmuType);
91
UNUSED_PARAMETER(fmuGUID);
92
UNUSED_PARAMETER(visible);
93
94
allocateMemoryType funcAllocateMemory = (allocateMemoryType)functions->allocateMemory;
95
ModelInstance* comp = (ModelInstance*) funcAllocateMemory(1, sizeof(ModelInstance));
96
97
if (comp) {
98
comp->componentEnvironment = functions->componentEnvironment;
99
100
/* Callback functions for specific logging, malloc and free;
101
we need callback functions because we cannot know, which functions
102
the environment will provide for us */
103
comp->logger = (loggerType)functions->logger;
104
comp->allocateMemory = (allocateMemoryType)functions->allocateMemory;
105
comp->freeMemory = (freeMemoryType)functions->freeMemory;
106
107
comp->instanceName = (char*)comp->allocateMemory(1 + strlen(instanceName), sizeof(char));
108
strcpy((char*)comp->instanceName, (char*)instanceName);
109
110
if (fmuResourceLocation) {
111
comp->resourceLocation = (char*)comp->allocateMemory(1 + strlen(fmuResourceLocation), sizeof(char));
112
strcpy((char*)comp->resourceLocation, (char*)fmuResourceLocation);
113
} else {
114
comp->resourceLocation = NULL;
115
}
116
117
comp->logEvents = loggingOn;
118
comp->logErrors = true; // always log errors
119
}
120
121
return comp;
122
}
123
124
/* Disposes the given instance, unloads the loaded model, and frees all the allocated memory
125
and other resources that have been allocated by the functions of the FMU interface. */
126
void
127
fmi2FreeInstance(fmi2Component c) {
128
ModelInstance* comp = (ModelInstance*)c;
129
130
/* Store the pointer to the freeMemory function, because we
131
are going to free comp as well */
132
freeMemoryType freeMemoryFunc = comp->freeMemory;
133
134
/* We want to free everything that we allocated in fmi2Instantiate */
135
freeMemoryFunc((void*)comp->instanceName);
136
freeMemoryFunc((void*)comp->resourceLocation);
137
freeMemoryFunc((void*)comp->libsumoCallOptions);
138
freeMemoryFunc((void*)comp->getterParameters);
139
int i;
140
for (i = 0; i < comp->bufferArrayLength; i++) {
141
freeMemoryFunc((void*)comp->bufferArray[i]);
142
}
143
freeMemoryFunc((void*)comp->bufferArray);
144
freeMemoryFunc((void*)comp);
145
}
146
147
fmi2Status
148
fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance,
149
fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) {
150
151
UNUSED_PARAMETER(toleranceDefined);
152
UNUSED_PARAMETER(tolerance);
153
UNUSED_PARAMETER(stopTimeDefined);
154
155
// ignore arguments: toleranceDefined, tolerance
156
ModelInstance* comp = (ModelInstance*)c;
157
158
// Store the start and stop times of the experiment
159
comp->startTime = startTime;
160
comp->stopTime = stopTime;
161
162
sumo2fmi_set_startValues(comp);
163
164
return fmi2OK;
165
}
166
167
// Will be called after instantiation and after initial variables have been set
168
fmi2Status
169
fmi2EnterInitializationMode(fmi2Component c) {
170
UNUSED_PARAMETER(c);
171
172
return fmi2OK;
173
}
174
175
// Informs the FMU to exit Initialization Mode
176
fmi2Status
177
fmi2ExitInitializationMode(fmi2Component c) {
178
ModelInstance* comp = (ModelInstance*)c;
179
180
sumo2fmi_logEvent(comp, "Calling libsumo with the following options: \"%s\"", comp->libsumoCallOptions);
181
libsumo_load(comp->libsumoCallOptions);
182
183
return fmi2OK;
184
}
185
186
// Informs the FMU that the simulation run is terminated
187
// --> let libsumo know, that we want to close the simulation
188
fmi2Status
189
fmi2Terminate(fmi2Component c) {
190
UNUSED_PARAMETER(c);
191
192
libsumo_close();
193
return fmi2OK;
194
}
195
196
// Is called by the environment to reset the FMU after a simulation run
197
fmi2Status
198
fmi2Reset(fmi2Component c) {
199
UNUSED_PARAMETER(c);
200
201
// Should we set some start values?
202
return fmi2OK;
203
}
204
205
// Implementation of the getter features
206
fmi2Status
207
fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) {
208
UNUSED_PARAMETER(c);
209
UNUSED_PARAMETER(vr);
210
UNUSED_PARAMETER(nvr);
211
UNUSED_PARAMETER(value);
212
213
return fmi2Error;
214
}
215
216
fmi2Status
217
fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) {
218
219
ModelInstance* comp = (ModelInstance*)c;
220
221
// Check for null pointer errors
222
if (nvr > 0 && (!vr || !value)) {
223
return fmi2Error;
224
}
225
226
fmi2Status status = fmi2OK;
227
228
// Go through the list of arrays and save all requested values
229
size_t i;
230
for (i = 0; i < nvr; i++) {
231
fmi2Status s = sumo2fmi_getInteger(comp, vr[i], &(value[i]));
232
status = s > status ? s : status;
233
234
if (status > fmi2Warning) {
235
return status;
236
}
237
}
238
239
return status;
240
}
241
242
fmi2Status
243
fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) {
244
UNUSED_PARAMETER(c);
245
UNUSED_PARAMETER(vr);
246
UNUSED_PARAMETER(nvr);
247
UNUSED_PARAMETER(value);
248
249
return fmi2Error;
250
}
251
252
fmi2Status
253
fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) {
254
255
ModelInstance* comp = (ModelInstance*)c;
256
257
// Check for null pointer errors
258
if (nvr > 0 && (!vr || !value)) {
259
return fmi2Error;
260
}
261
262
fmi2Status status = fmi2OK;
263
264
/** Clear value array buffer before reuse */
265
int b;
266
for (b = 0; b < comp->bufferArrayLength; b++) {
267
comp->freeMemory((void*)comp->bufferArray[b]);
268
}
269
comp->freeMemory((void*)comp->bufferArray);
270
comp->bufferArray = (fmi2String*)comp->allocateMemory(nvr, sizeof(fmi2String));
271
comp->bufferArrayLength = (int)nvr;
272
273
// Go through the list of arrays and save all requested values
274
size_t i;
275
for (i = 0; i < nvr; i++) {
276
fmi2Status s = sumo2fmi_getString(comp, vr[i], &(comp->bufferArray[i]));
277
value[i] = comp->bufferArray[i];
278
if (value[i] == NULL) {
279
s = fmi2Error;
280
}
281
282
status = s > status ? s : status;
283
if (status > fmi2Warning) {
284
return status;
285
}
286
}
287
288
return status;
289
}
290
291
// Implementation of the setter features
292
fmi2Status
293
fmi2SetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) {
294
UNUSED_PARAMETER(c);
295
UNUSED_PARAMETER(vr);
296
UNUSED_PARAMETER(nvr);
297
UNUSED_PARAMETER(value);
298
return fmi2Error;
299
}
300
301
fmi2Status
302
fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) {
303
UNUSED_PARAMETER(c);
304
UNUSED_PARAMETER(vr);
305
UNUSED_PARAMETER(nvr);
306
UNUSED_PARAMETER(value);
307
308
return fmi2Error;
309
}
310
311
fmi2Status
312
fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) {
313
UNUSED_PARAMETER(c);
314
UNUSED_PARAMETER(vr);
315
UNUSED_PARAMETER(nvr);
316
UNUSED_PARAMETER(value);
317
318
return fmi2Error;
319
}
320
321
fmi2Status
322
fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) {
323
324
ModelInstance* comp = (ModelInstance*)c;
325
fmi2Status status = fmi2OK;
326
327
size_t i;
328
for (i = 0; i < nvr; i++) {
329
fmi2Status s = sumo2fmi_setString(comp, vr[i], value[i]);
330
status = s > status ? s : status;
331
if (status > fmi2Warning) {
332
return status;
333
}
334
}
335
336
return status;
337
}
338
339
fmi2Status
340
fmi2GetFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) {
341
UNUSED_PARAMETER(c);
342
UNUSED_PARAMETER(FMUstate);
343
return fmi2Error; /* Dummy implementation */
344
}
345
346
fmi2Status
347
fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) {
348
UNUSED_PARAMETER(c);
349
UNUSED_PARAMETER(FMUstate);
350
return fmi2Error; /* Dummy implementation */
351
}
352
353
fmi2Status
354
fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) {
355
UNUSED_PARAMETER(c);
356
UNUSED_PARAMETER(FMUstate);
357
return fmi2Error; /* Dummy implementation */
358
}
359
360
fmi2Status
361
fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t* size) {
362
UNUSED_PARAMETER(c);
363
UNUSED_PARAMETER(FMUstate);
364
UNUSED_PARAMETER(size);
365
return fmi2Error; /* Dummy implementation */
366
}
367
368
fmi2Status
369
fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte state[], size_t size) {
370
UNUSED_PARAMETER(c);
371
UNUSED_PARAMETER(FMUstate);
372
UNUSED_PARAMETER(state);
373
UNUSED_PARAMETER(size);
374
return fmi2Error; /* Dummy implementation */
375
}
376
377
fmi2Status
378
fmi2DeSerializeFMUstate(fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate) {
379
UNUSED_PARAMETER(c);
380
UNUSED_PARAMETER(serializedState);
381
UNUSED_PARAMETER(size);
382
UNUSED_PARAMETER(FMUstate);
383
return fmi2Error; /* Dummy implementation */
384
}
385
386
fmi2Status
387
fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown,
388
const fmi2ValueReference vKnown_ref[], size_t nKnown, const fmi2Real dvKnown[], fmi2Real dvUnknown[]) {
389
UNUSED_PARAMETER(c);
390
UNUSED_PARAMETER(vUnknown_ref);
391
UNUSED_PARAMETER(nUnknown);
392
UNUSED_PARAMETER(vKnown_ref);
393
UNUSED_PARAMETER(nKnown);
394
UNUSED_PARAMETER(dvKnown);
395
UNUSED_PARAMETER(dvUnknown);
396
return fmi2Error; /* Dummy implementation */
397
}
398
399
/* Further functions for interpolation */
400
fmi2Status
401
fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], const fmi2Real value[]) {
402
UNUSED_PARAMETER(c);
403
UNUSED_PARAMETER(vr);
404
UNUSED_PARAMETER(nvr);
405
UNUSED_PARAMETER(order);
406
UNUSED_PARAMETER(value);
407
408
return fmi2Error; /* Ignoring - SUMO cannot interpolate inputs */
409
}
410
411
fmi2Status
412
fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], fmi2Real value[]) {
413
UNUSED_PARAMETER(c);
414
UNUSED_PARAMETER(vr);
415
UNUSED_PARAMETER(order);
416
417
size_t i;
418
for (i = 0; i < nvr; i++) {
419
value[i] = 0; /* We cannot compute derivatives of outputs */
420
}
421
return fmi2Error;
422
}
423
424
/* Stepping */
425
fmi2Status
426
fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) {
427
UNUSED_PARAMETER(noSetFMUStatePriorToCurrentPoint);
428
429
ModelInstance* comp = (ModelInstance*)c;
430
431
if (communicationStepSize <= 0) {
432
return fmi2Error;
433
}
434
435
return sumo2fmi_step(comp, currentCommunicationPoint + communicationStepSize);
436
}
437
438
fmi2Status
439
fmi2CancelStep(fmi2Component c) {
440
UNUSED_PARAMETER(c);
441
442
return fmi2Error; /* We will never have a modelStepInProgress state */
443
}
444
445
/* Status functions */
446
fmi2Status
447
fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status* value) {
448
UNUSED_PARAMETER(c);
449
UNUSED_PARAMETER(s);
450
UNUSED_PARAMETER(value);
451
452
return fmi2Discard;
453
}
454
455
fmi2Status
456
fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real* value) {
457
UNUSED_PARAMETER(c);
458
UNUSED_PARAMETER(s);
459
UNUSED_PARAMETER(value);
460
461
return fmi2Discard;
462
}
463
464
fmi2Status
465
fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer* value) {
466
UNUSED_PARAMETER(c);
467
UNUSED_PARAMETER(s);
468
UNUSED_PARAMETER(value);
469
470
return fmi2Discard;
471
}
472
473
fmi2Status
474
fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean* value) {
475
UNUSED_PARAMETER(c);
476
UNUSED_PARAMETER(s);
477
UNUSED_PARAMETER(value);
478
479
return fmi2Discard;
480
}
481
482
fmi2Status
483
fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String* value) {
484
UNUSED_PARAMETER(c);
485
UNUSED_PARAMETER(s);
486
UNUSED_PARAMETER(value);
487
488
return fmi2Discard;
489
}
490
491