2 Copyright (C) 2012 Modelon AB
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the BSD style license.
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.
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>.
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"
29 static const char * module = "FMILIB";
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) {
34 char curDir[FILENAME_MAX + 2];
36 char* dllFileName = 0;
37 const char* modelIdentifier;
38 fmi2_callback_functions_t defaultCallbacks;
42 return jm_status_error;
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;
51 fmi2_import_destroy_dllfmu(fmu);
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);
60 return jm_status_error;
63 if (modelIdentifier == NULL) {
64 jm_log_error(fmu->callbacks, module, "No model identifier given");
65 return jm_status_error;
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));
73 dllDirPath = fmi_construct_dll_dir_name(fmu->callbacks, fmu->dirPath);
74 dllFileName = fmi_construct_dll_file_name(fmu->callbacks, dllDirPath, modelIdentifier);
76 if (!dllDirPath ||!dllFileName) {
77 fmu->callbacks->free(dllDirPath);
78 return jm_status_error;
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;
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);
94 jm_log_fatal(fmu->callbacks, module, "The FMU contains no binary for this platform.");
96 jm_log_fatal(fmu->callbacks, module, "System error: %s", strerror(errno));
99 /* Allocate memory for the C-API struct */
100 fmu -> capi = fmi2_capi_create_dllfmu(fmu->callbacks, dllFileName, modelIdentifier, callBackFunctions, fmuKind);
104 /* Load the DLL handle */
106 jm_log_info(fmu->callbacks, module,
\r
107 "Loading '" FMI_PLATFORM "' binary with '%s' platform types", fmi2_get_types_platform() );
\r
109 if(fmi2_capi_load_dll(fmu -> capi) == jm_status_error) {
110 fmi2_capi_destroy_dllfmu(fmu -> capi);
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));
119 fmu->callbacks->free((jm_voidp)dllDirPath);
120 fmu->callbacks->free((jm_voidp)dllFileName);
122 if (fmu -> capi == NULL) {
123 return jm_status_error;
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);
132 return jm_status_error;
134 jm_log_verbose(fmu->callbacks, module, "Successfully loaded all the interface functions");
136 return jm_status_success;
139 void fmi2_import_set_debug_mode(fmi2_import_t* fmu, int mode) {
143 fmi2_capi_set_debug_mode(fmu->capi, mode);
146 void fmi2_import_destroy_dllfmu(fmi2_import_t* fmu) {
154 jm_log_verbose(fmu->callbacks, module, "Releasing FMU CAPI interface");
156 /* Free DLL handle */
157 fmi2_capi_free_dll(fmu -> capi);
159 /* Destroy the C-API struct */
160 fmi2_capi_destroy_dllfmu(fmu -> capi);
166 /* FMI 2.0 Common functions */
167 const char* fmi2_import_get_version(fmi2_import_t* fmu) {
169 jm_log_error(fmu->callbacks, module,"FMU CAPI is not loaded");
172 return fmi2_capi_get_version(fmu -> capi);
175 fmi2_status_t fmi2_import_set_debug_logging(fmi2_import_t* fmu, fmi2_boolean_t loggingOn, size_t nCategories, fmi2_string_t categories[]) {
177 jm_log_error(fmu->callbacks, module,"FMU CAPI is not loaded");
178 return fmi2_status_fatal;
180 return fmi2_capi_set_debug_logging(fmu -> capi, loggingOn, nCategories, categories);
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);
190 if(!fmuResourceLocation)
191 fmuResourceLocation = fmu->resourceLocation;
192 c = fmi2_capi_instantiate(fmu -> capi, instanceName, fmuType, fmuGUID,
193 fmuResourceLocation, visible, loggingOn);
195 return jm_status_error;
197 return jm_status_success;
201 void fmi2_import_free_instance(fmi2_import_t* fmu) {
203 fmi2_capi_free_instance(fmu -> capi);
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)
213 return fmi2_capi_setup_experiment(fmu->capi, tolerance_defined, tolerance,
214 start_time, stop_time_defined, stop_time);
217 fmi2_status_t fmi2_import_enter_initialization_mode(fmi2_import_t* fmu)
220 return fmi2_capi_enter_initialization_mode(fmu->capi);
223 fmi2_status_t fmi2_import_exit_initialization_mode(fmi2_import_t* fmu)
226 return fmi2_capi_exit_initialization_mode(fmu->capi);
229 fmi2_status_t fmi2_import_terminate(fmi2_import_t* fmu) {
230 return fmi2_capi_terminate(fmu -> capi);
233 fmi2_status_t fmi2_import_reset(fmi2_import_t* fmu) {
234 return fmi2_capi_reset(fmu -> capi);
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);
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);
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);
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);
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);
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);
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);
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);
270 const char* fmi2_import_get_types_platform(fmi2_import_t* fmu) {
271 return fmi2_capi_get_types_platform(fmu -> capi);
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
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
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
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
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
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
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
299 /* FMI 2.0 ME functions */
301 fmi2_status_t fmi2_import_enter_event_mode(fmi2_import_t* fmu) {
302 return fmi2_capi_enter_event_mode(fmu->capi);
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);
309 fmi2_status_t fmi2_import_enter_continuous_time_mode(fmi2_import_t* fmu) {
310 return fmi2_capi_enter_continuous_time_mode(fmu->capi);
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);
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);
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);
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);
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);
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);
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);
344 /* FMI 2.0 CS functions */
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);
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);
354 fmi2_status_t fmi2_import_cancel_step(fmi2_import_t* fmu) {
355 return fmi2_capi_cancel_step(fmu -> capi);
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);
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);
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);
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);
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);
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);