]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/src/Import/src/FMI2/fmi2_import_capi.c
Switch to full JavaSE-11+ compatibility
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / src / Import / src / FMI2 / fmi2_import_capi.c
1 /*
2     Copyright (C) 2012 Modelon AB
3
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the BSD style license.
6
7      This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10     FMILIB_License.txt file for more details.
11
12     You should have received a copy of the FMILIB_License.txt file
13     along with this program. If not, contact Modelon AB <http://www.modelon.com>.
14 */
15
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19
20 #include <stdio.h>
21 #include <errno.h>
22 #include <FMI2/fmi2_types.h>
23 #include <FMI2/fmi2_functions.h>
24 #include <FMI2/fmi2_enums.h>\r
25 #include <FMI2/fmi2_capi.h>
26 #include <FMI/fmi_util.h>
27 #include "fmi2_import_impl.h"
28
29 static const char * module = "FMILIB";
30
31 /* Load and destroy functions */
32 jm_status_enu_t fmi2_import_create_dllfmu(fmi2_import_t* fmu, fmi2_fmu_kind_enu_t fmuKind, const fmi2_callback_functions_t* callBackFunctions) {
33
34         char curDir[FILENAME_MAX + 2];
35         char* dllDirPath = 0;
36         char* dllFileName = 0;
37         const char* modelIdentifier;
38         fmi2_callback_functions_t defaultCallbacks;
39
40         if (fmu == NULL) {
41                 assert(0);
42                 return jm_status_error;
43         }
44
45         if(fmu -> capi) {
46                 if(fmi2_capi_get_fmu_kind(fmu -> capi) == fmuKind) {
47                         jm_log_warning(fmu->callbacks, module, "FMU binary is already loaded"); 
48                         return jm_status_success;
49                 }
50                 else
51                         fmi2_import_destroy_dllfmu(fmu);                
52         }
53
54         if(fmuKind == fmi2_fmu_kind_me)
55                 modelIdentifier = fmi2_import_get_model_identifier_ME(fmu);
56         else    if(fmuKind == fmi2_fmu_kind_cs)
57                 modelIdentifier = fmi2_import_get_model_identifier_CS(fmu);
58         else {
59                 assert(0);
60                 return jm_status_error;
61         }
62
63         if (modelIdentifier == NULL) {
64                 jm_log_error(fmu->callbacks, module, "No model identifier given");
65                 return jm_status_error;
66         }
67
68         if( jm_portability_get_current_working_directory(curDir, FILENAME_MAX+1) != jm_status_success) {
69                 jm_log_warning(fmu->callbacks, module, "Could not get current working directory (%s)", strerror(errno));
70                 curDir[0] = 0;
71         };
72
73         dllDirPath = fmi_construct_dll_dir_name(fmu->callbacks, fmu->dirPath);
74         dllFileName = fmi_construct_dll_file_name(fmu->callbacks, dllDirPath, modelIdentifier);
75
76         if (!dllDirPath ||!dllFileName) {
77                 fmu->callbacks->free(dllDirPath);
78                 return jm_status_error;
79         }
80
81         if(!callBackFunctions) {
82                 jm_callbacks* cb = fmu->callbacks;
83                 defaultCallbacks.allocateMemory = cb->calloc;
84                 defaultCallbacks.freeMemory = cb->free;
85                 defaultCallbacks.componentEnvironment = fmu;
86                 defaultCallbacks.logger = fmi2_log_forwarding;
87                 defaultCallbacks.stepFinished = 0;
88                 callBackFunctions = &defaultCallbacks;
89         }
90
91         if(jm_portability_set_current_working_directory(dllDirPath) != jm_status_success) {
92                 jm_log_fatal(fmu->callbacks, module, "Could not change to the DLL directory %s", dllDirPath);
93                 if(ENOENT == errno)
94                         jm_log_fatal(fmu->callbacks, module, "The FMU contains no binary for this platform.");
95                 else
96                         jm_log_fatal(fmu->callbacks, module, "System error: %s", strerror(errno));
97         }
98         else {
99                 /* Allocate memory for the C-API struct */
100                 fmu -> capi = fmi2_capi_create_dllfmu(fmu->callbacks, dllFileName, modelIdentifier, callBackFunctions, fmuKind);
101         }
102
103
104         /* Load the DLL handle */
105         if (fmu -> capi) {
106                 jm_log_info(fmu->callbacks, module, \r
107                         "Loading '" FMI_PLATFORM "' binary with '%s' platform types", fmi2_get_types_platform() );\r
108
109                 if(fmi2_capi_load_dll(fmu -> capi) == jm_status_error) {                
110                         fmi2_capi_destroy_dllfmu(fmu -> capi);
111                         fmu -> capi = NULL;
112                 }
113         }
114
115         if(curDir[0] && (jm_portability_set_current_working_directory(curDir) != jm_status_success)) {
116                 jm_log_error(fmu->callbacks, module, "Could not restore current working directory (%s)", strerror(errno));
117         }
118
119         fmu->callbacks->free((jm_voidp)dllDirPath);
120         fmu->callbacks->free((jm_voidp)dllFileName);
121
122         if (fmu -> capi == NULL) {
123                 return jm_status_error;
124         }
125
126
127         /* Load the DLL functions */
128         if (fmi2_capi_load_fcn(fmu -> capi, fmi2_xml_get_capabilities(fmu->md)) == jm_status_error) {
129                 fmi2_capi_free_dll(fmu -> capi);                        
130                 fmi2_capi_destroy_dllfmu(fmu -> capi);
131                 fmu -> capi = NULL;
132                 return jm_status_error;
133         }
134         jm_log_verbose(fmu->callbacks, module, "Successfully loaded all the interface functions"); 
135
136         return jm_status_success;
137 }
138
139 void fmi2_import_set_debug_mode(fmi2_import_t* fmu, int mode) {
140         if (fmu == NULL) {
141                 return;
142         }
143         fmi2_capi_set_debug_mode(fmu->capi, mode);
144 }
145
146 void fmi2_import_destroy_dllfmu(fmi2_import_t* fmu) {
147         
148         if (fmu == NULL) {
149                 return;
150         }
151
152         
153         if(fmu -> capi) {
154                 jm_log_verbose(fmu->callbacks, module, "Releasing FMU CAPI interface"); 
155
156                 /* Free DLL handle */
157                 fmi2_capi_free_dll(fmu -> capi);
158
159                 /* Destroy the C-API struct */
160                 fmi2_capi_destroy_dllfmu(fmu -> capi);
161
162                 fmu -> capi = NULL;
163         }
164 }
165
166 /* FMI 2.0 Common functions */
167 const char* fmi2_import_get_version(fmi2_import_t* fmu) {
168         if(!fmu->capi) {
169                 jm_log_error(fmu->callbacks, module,"FMU CAPI is not loaded");
170                 return 0;
171         }
172         return fmi2_capi_get_version(fmu -> capi);
173 }
174
175 fmi2_status_t fmi2_import_set_debug_logging(fmi2_import_t* fmu, fmi2_boolean_t loggingOn, size_t nCategories, fmi2_string_t categories[]) {
176         if(!fmu->capi) {
177                 jm_log_error(fmu->callbacks, module,"FMU CAPI is not loaded");
178                 return fmi2_status_fatal;
179         }
180         return fmi2_capi_set_debug_logging(fmu -> capi, loggingOn, nCategories, categories);
181 }
182
183
184 jm_status_enu_t fmi2_import_instantiate(fmi2_import_t* fmu,
185   fmi2_string_t instanceName, fmi2_type_t fmuType,
186   fmi2_string_t fmuResourceLocation, fmi2_boolean_t visible) {
187     fmi2_string_t fmuGUID = fmi2_import_get_GUID(fmu);
188     fmi2_boolean_t loggingOn = (fmu->callbacks->log_level > jm_log_level_nothing);
189     fmi2_component_t c;
190     if(!fmuResourceLocation) 
191         fmuResourceLocation = fmu->resourceLocation;
192     c = fmi2_capi_instantiate(fmu -> capi, instanceName, fmuType, fmuGUID,
193                               fmuResourceLocation, visible, loggingOn);
194     if (c == NULL) {
195         return jm_status_error;
196     } else {
197         return jm_status_success;
198     }
199 }
200
201 void fmi2_import_free_instance(fmi2_import_t* fmu) {
202     if (fmu != NULL) {
203         fmi2_capi_free_instance(fmu -> capi);
204     }
205 }
206
207 fmi2_status_t fmi2_import_setup_experiment(fmi2_import_t* fmu,
208     fmi2_boolean_t tolerance_defined, fmi2_real_t tolerance,
209     fmi2_real_t start_time, fmi2_boolean_t stop_time_defined,
210     fmi2_real_t stop_time)
211 {
212     assert(fmu);
213     return fmi2_capi_setup_experiment(fmu->capi, tolerance_defined, tolerance,
214                                       start_time, stop_time_defined, stop_time);
215 }
216
217 fmi2_status_t fmi2_import_enter_initialization_mode(fmi2_import_t* fmu)
218 {
219     assert(fmu);
220     return fmi2_capi_enter_initialization_mode(fmu->capi);
221 }
222
223 fmi2_status_t fmi2_import_exit_initialization_mode(fmi2_import_t* fmu)
224 {
225     assert(fmu);
226     return fmi2_capi_exit_initialization_mode(fmu->capi);
227 }
228
229 fmi2_status_t fmi2_import_terminate(fmi2_import_t* fmu) {
230         return fmi2_capi_terminate(fmu -> capi);
231 }
232
233 fmi2_status_t fmi2_import_reset(fmi2_import_t* fmu) {
234         return fmi2_capi_reset(fmu -> capi);
235 }
236
237
238 fmi2_status_t fmi2_import_set_real(fmi2_import_t* fmu, const fmi2_value_reference_t vr[], size_t nvr, const fmi2_real_t    value[]) {
239         return fmi2_capi_set_real(fmu -> capi, vr, nvr, value);
240 }
241
242 fmi2_status_t fmi2_import_set_integer(fmi2_import_t* fmu, const fmi2_value_reference_t vr[], size_t nvr, const fmi2_integer_t value[]) {
243         return fmi2_capi_set_integer(fmu -> capi, vr, nvr, value);
244 }
245
246 fmi2_status_t fmi2_import_set_boolean(fmi2_import_t* fmu, const fmi2_value_reference_t vr[], size_t nvr, const fmi2_boolean_t value[]) {
247         return fmi2_capi_set_boolean(fmu -> capi, vr, nvr, value);
248 }
249
250 fmi2_status_t fmi2_import_set_string(fmi2_import_t* fmu, const fmi2_value_reference_t vr[], size_t nvr, const fmi2_string_t  value[]) {
251         return fmi2_capi_set_string(fmu -> capi, vr, nvr, value);
252 }
253
254 fmi2_status_t fmi2_import_get_real(fmi2_import_t* fmu, const fmi2_value_reference_t vr[], size_t nvr, fmi2_real_t    value[]) {
255         return fmi2_capi_get_real(fmu -> capi, vr, nvr, value);
256 }
257
258 fmi2_status_t fmi2_import_get_integer(fmi2_import_t* fmu, const fmi2_value_reference_t vr[], size_t nvr, fmi2_integer_t value[]) {
259         return fmi2_capi_get_integer(fmu -> capi, vr, nvr, value);
260 }
261
262 fmi2_status_t fmi2_import_get_boolean(fmi2_import_t* fmu, const fmi2_value_reference_t vr[], size_t nvr, fmi2_boolean_t value[]) {
263         return fmi2_capi_get_boolean(fmu -> capi, vr, nvr, value);
264 }
265
266 fmi2_status_t fmi2_import_get_string(fmi2_import_t* fmu, const fmi2_value_reference_t vr[], size_t nvr, fmi2_string_t  value[]) {
267         return fmi2_capi_get_string(fmu -> capi, vr, nvr, value);
268 }
269
270 const char* fmi2_import_get_types_platform(fmi2_import_t* fmu) {
271         return fmi2_capi_get_types_platform(fmu -> capi);
272 }
273
274 fmi2_status_t fmi2_import_get_fmu_state           (fmi2_import_t* fmu, fmi2_FMU_state_t* s) {\r
275         return fmi2_capi_get_fmu_state(fmu -> capi,s);\r
276 }\r
277 fmi2_status_t fmi2_import_set_fmu_state           (fmi2_import_t* fmu, fmi2_FMU_state_t s){\r
278         return fmi2_capi_set_fmu_state(fmu -> capi,s);\r
279 }\r
280 fmi2_status_t fmi2_import_free_fmu_state          (fmi2_import_t* fmu, fmi2_FMU_state_t* s){\r
281         return fmi2_capi_free_fmu_state (fmu -> capi,s);\r
282 }\r
283 fmi2_status_t fmi2_import_serialized_fmu_state_size(fmi2_import_t* fmu, fmi2_FMU_state_t s, size_t* sz){\r
284         return fmi2_capi_serialized_fmu_state_size(fmu -> capi,s,sz);\r
285 }\r
286 fmi2_status_t fmi2_import_serialize_fmu_state     (fmi2_import_t* fmu, fmi2_FMU_state_t s , fmi2_byte_t data[], size_t sz){\r
287         return fmi2_capi_serialize_fmu_state(fmu -> capi,s,data,sz);\r
288 }\r
289 fmi2_status_t fmi2_import_de_serialize_fmu_state  (fmi2_import_t* fmu, const fmi2_byte_t data[], size_t sz, fmi2_FMU_state_t* s){\r
290         return fmi2_capi_de_serialize_fmu_state (fmu -> capi,data,sz,s);\r
291 }\r
292 \r
293 fmi2_status_t fmi2_import_get_directional_derivative(fmi2_import_t* fmu, const fmi2_value_reference_t v_ref[], size_t nv,\r
294                                                                    const fmi2_value_reference_t z_ref[], size_t nz,\r
295                                                                    const fmi2_real_t dv[], fmi2_real_t dz[]){\r
296         return fmi2_capi_get_directional_derivative(fmu -> capi,v_ref, nv, z_ref, nz, dv, dz);\r
297 }
298
299 /* FMI 2.0 ME functions */
300
301 fmi2_status_t fmi2_import_enter_event_mode(fmi2_import_t* fmu) {
302     return fmi2_capi_enter_event_mode(fmu->capi);
303 }
304
305 fmi2_status_t fmi2_import_new_discrete_states(fmi2_import_t* fmu, fmi2_event_info_t* eventInfo) {
306     return fmi2_capi_new_discrete_states(fmu->capi, eventInfo);
307 }
308
309 fmi2_status_t fmi2_import_enter_continuous_time_mode(fmi2_import_t* fmu) {
310     return fmi2_capi_enter_continuous_time_mode(fmu->capi);
311 }
312
313 fmi2_status_t fmi2_import_set_time(fmi2_import_t* fmu, fmi2_real_t time) {
314         return fmi2_capi_set_time(fmu -> capi, time);
315 }
316
317 fmi2_status_t fmi2_import_set_continuous_states(fmi2_import_t* fmu, const fmi2_real_t x[], size_t nx) {
318         return fmi2_capi_set_continuous_states(fmu -> capi, x, nx);
319 }
320
321 fmi2_status_t fmi2_import_completed_integrator_step(fmi2_import_t* fmu,
322   fmi2_boolean_t noSetFMUStatePriorToCurrentPoint,
323   fmi2_boolean_t* enterEventMode, fmi2_boolean_t* terminateSimulation) {
324     return fmi2_capi_completed_integrator_step(fmu -> capi, noSetFMUStatePriorToCurrentPoint,
325                                                enterEventMode, terminateSimulation);
326 }
327
328 fmi2_status_t fmi2_import_get_derivatives(fmi2_import_t* fmu, fmi2_real_t derivatives[], size_t nx) {
329         return fmi2_capi_get_derivatives(fmu -> capi, derivatives, nx);
330 }
331
332 fmi2_status_t fmi2_import_get_event_indicators(fmi2_import_t* fmu, fmi2_real_t eventIndicators[], size_t ni) {
333         return fmi2_capi_get_event_indicators(fmu -> capi, eventIndicators, ni);
334 }
335
336 fmi2_status_t fmi2_import_get_continuous_states(fmi2_import_t* fmu, fmi2_real_t states[], size_t nx) {
337         return fmi2_capi_get_continuous_states(fmu -> capi, states, nx);
338 }
339
340 fmi2_status_t fmi2_import_get_nominals_of_continuous_states(fmi2_import_t* fmu, fmi2_real_t x_nominal[], size_t nx) {
341         return fmi2_capi_get_nominals_of_continuous_states(fmu -> capi, x_nominal, nx);
342 }
343
344 /* FMI 2.0 CS functions */
345
346 fmi2_status_t fmi2_import_set_real_input_derivatives(fmi2_import_t* fmu, const fmi2_value_reference_t vr[], size_t nvr, const fmi2_integer_t order[], const  fmi2_real_t value[]) {
347         return fmi2_capi_set_real_input_derivatives(fmu -> capi, vr, nvr, order, value);
348 }
349                                                   
350 fmi2_status_t fmi2_import_get_real_output_derivatives(fmi2_import_t* fmu, const fmi2_value_reference_t vr[], size_t nvr, const fmi2_integer_t order[], fmi2_real_t value[]) {
351         return fmi2_capi_get_real_output_derivatives(fmu -> capi, vr, nvr, order, value);
352 }
353                                               
354 fmi2_status_t fmi2_import_cancel_step(fmi2_import_t* fmu) {
355         return fmi2_capi_cancel_step(fmu -> capi);
356 }
357
358 fmi2_status_t fmi2_import_do_step(fmi2_import_t* fmu, fmi2_real_t currentCommunicationPoint, fmi2_real_t communicationStepSize, fmi2_boolean_t newStep) {
359         return fmi2_capi_do_step(fmu -> capi, currentCommunicationPoint, communicationStepSize, newStep);
360 }
361
362 fmi2_status_t fmi2_import_get_status(fmi2_import_t* fmu, const fmi2_status_kind_t s, fmi2_status_t*  value) {
363         return fmi2_capi_get_status(fmu -> capi, s, value);
364 }
365
366 fmi2_status_t fmi2_import_get_real_status(fmi2_import_t* fmu, const fmi2_status_kind_t s, fmi2_real_t*    value) {
367         return fmi2_capi_get_real_status(fmu -> capi, s, value);
368 }
369
370 fmi2_status_t fmi2_import_get_integer_status(fmi2_import_t* fmu, const fmi2_status_kind_t s, fmi2_integer_t* value) {
371         return fmi2_capi_get_integer_status(fmu -> capi, s, value);
372 }
373
374 fmi2_status_t fmi2_import_get_boolean_status(fmi2_import_t* fmu, const fmi2_status_kind_t s, fmi2_boolean_t* value) {
375         return fmi2_capi_get_boolean_status(fmu -> capi, s, value);
376 }
377
378 fmi2_status_t fmi2_import_get_string_status(fmi2_import_t* fmu, const fmi2_status_kind_t s, fmi2_string_t*  value) {
379         return fmi2_capi_get_string_status(fmu -> capi, s, value);
380 }
381
382 #ifdef __cplusplus
383 }
384 #endif