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 <FMI1/fmi1_types.h>
23 #include <FMI1/fmi1_functions.h>
24 #include <FMI1/fmi1_enums.h>
\r
25 #include <FMI1/fmi1_capi.h>
26 #include <FMI/fmi_util.h>
27 #include "fmi1_import_impl.h"
29 static const char * module = "FMILIB";
31 /* Load and destroy functions */
32 jm_status_enu_t fmi1_import_create_dllfmu(fmi1_import_t* fmu, fmi1_callback_functions_t callBackFunctions, int registerGlobally) {
34 char curDir[FILENAME_MAX + 2];
36 char* dllFileName = 0;
37 const char* modelIdentifier;
38 fmi1_fmu_kind_enu_t standard;
42 return jm_status_error;
46 jm_log_warning(fmu->callbacks, module, "FMU binary is already loaded");
47 return jm_status_success;
50 standard = fmi1_import_get_fmu_kind(fmu);
52 modelIdentifier = fmi1_import_get_model_identifier(fmu);
53 if (modelIdentifier == NULL) {
54 return jm_status_error;
57 if( jm_portability_get_current_working_directory(curDir, FILENAME_MAX+1) != jm_status_success) {
58 jm_log_warning(fmu->callbacks, module, "Could not get current working directory (%s)", strerror(errno));
62 dllDirPath = fmi_construct_dll_dir_name(fmu->callbacks, fmu->dirPath);
63 dllFileName = fmi_construct_dll_file_name(fmu->callbacks, dllDirPath, modelIdentifier);
65 if (!dllDirPath ||!dllFileName) {
66 fmu->callbacks->free(dllDirPath);
67 return jm_status_error;
70 if(jm_portability_set_current_working_directory(dllDirPath) != jm_status_success) {
71 jm_log_fatal(fmu->callbacks, module, "Could not change to the DLL directory %s", dllDirPath);
73 jm_log_fatal(fmu->callbacks, module, "The FMU contains no binary for this platform.");
75 jm_log_fatal(fmu->callbacks, module, "System error: %s", strerror(errno));
78 /* Allocate memory for the C-API struct */
79 fmu -> capi = fmi1_capi_create_dllfmu(fmu->callbacks, dllFileName, modelIdentifier, callBackFunctions, standard);
83 /* Load the DLL handle */
85 jm_log_info(fmu->callbacks, module,
\r
86 "Loading '" FMI_PLATFORM "' binary with '%s' platform types", fmi1_get_platform() );
\r
88 if(fmi1_capi_load_dll(fmu -> capi) == jm_status_error) {
89 fmi1_capi_destroy_dllfmu(fmu -> capi);
94 if(curDir[0] && (jm_portability_set_current_working_directory(curDir) != jm_status_success)) {
95 jm_log_error(fmu->callbacks, module, "Could not restore current working directory (%s)", strerror(errno));
98 fmu->callbacks->free((jm_voidp)dllDirPath);
99 fmu->callbacks->free((jm_voidp)dllFileName);
101 if (fmu -> capi == NULL) {
102 return jm_status_error;
106 /* Load the DLL functions */
107 if (fmi1_capi_load_fcn(fmu -> capi) == jm_status_error) {
108 fmi1_capi_free_dll(fmu -> capi);
109 fmi1_capi_destroy_dllfmu(fmu -> capi);
111 return jm_status_error;
113 jm_log_verbose(fmu->callbacks, module, "Successfully loaded all the interface functions");
115 if (registerGlobally) {
116 fmu->registerGlobally = 1;
117 if(!fmi1_import_active_fmu) {
118 fmi1_import_active_fmu_store_callbacks = *fmu->callbacks;
119 fmi1_import_active_fmu_store_callbacks.context = 0;
120 jm_vector_init(jm_voidp)(&fmi1_import_active_fmu_store,0, &fmi1_import_active_fmu_store_callbacks);
121 fmi1_import_active_fmu = &fmi1_import_active_fmu_store;
122 jm_log_debug(fmu->callbacks, module, "Created an empty active fmu list");
124 jm_vector_push_back(jm_voidp)(fmi1_import_active_fmu, fmu);
125 jm_log_debug(fmu->callbacks, module, "Registrered active fmu(%p)", fmu);
128 return jm_status_success;
131 void fmi1_import_set_debug_mode(fmi1_import_t* fmu, int mode) {
135 fmi1_capi_set_debug_mode(fmu->capi, mode);
138 void fmi1_import_destroy_dllfmu(fmi1_import_t* fmu) {
146 jm_log_verbose(fmu->callbacks, module, "Releasing FMU CAPI interface");
148 /* Free DLL handle */
149 fmi1_capi_free_dll(fmu -> capi);
151 /* Destroy the C-API struct */
152 fmi1_capi_destroy_dllfmu(fmu -> capi);
154 if(fmu->registerGlobally && fmi1_import_active_fmu) {
158 index = jm_vector_find_index(jm_voidp)(fmi1_import_active_fmu, (void**)&fmu, jm_compare_voidp);
159 nFmu = jm_vector_get_size(jm_voidp)(fmi1_import_active_fmu);
161 jm_vector_remove_item(jm_voidp)(fmi1_import_active_fmu,index);
162 jm_log_debug(fmu->callbacks, module, "Unregistrered active fmu(%p)", fmu);
164 jm_vector_free_data(jm_voidp)(fmi1_import_active_fmu);
165 fmi1_import_active_fmu = 0;
166 jm_log_debug(fmu->callbacks, module, "Freed active fmu list");
169 fmu->registerGlobally = 0;
175 assert(fmu->registerGlobally == 0);
179 /* FMI 1.0 Common functions */
180 const char* fmi1_import_get_version(fmi1_import_t* fmu) {
182 jm_log_error(fmu->callbacks, module,"FMU CAPI is not loaded");
185 return fmi1_capi_get_version(fmu -> capi);
188 fmi1_status_t fmi1_import_set_debug_logging(fmi1_import_t* fmu, fmi1_boolean_t loggingOn) {
190 jm_log_error(fmu->callbacks, module,"FMU CAPI is not loaded");
191 return fmi1_status_fatal;
193 return fmi1_capi_set_debug_logging(fmu -> capi, loggingOn);
196 fmi1_status_t fmi1_import_set_real(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_real_t value[]) {
197 return fmi1_capi_set_real(fmu -> capi, vr, nvr, value);
200 fmi1_status_t fmi1_import_set_integer(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_integer_t value[]) {
201 return fmi1_capi_set_integer(fmu -> capi, vr, nvr, value);
204 fmi1_status_t fmi1_import_set_boolean(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_boolean_t value[]) {
205 return fmi1_capi_set_boolean(fmu -> capi, vr, nvr, value);
208 fmi1_status_t fmi1_import_set_string(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_string_t value[]) {
209 return fmi1_capi_set_string(fmu -> capi, vr, nvr, value);
212 fmi1_status_t fmi1_import_get_real(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, fmi1_real_t value[]) {
213 return fmi1_capi_get_real(fmu -> capi, vr, nvr, value);
216 fmi1_status_t fmi1_import_get_integer(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, fmi1_integer_t value[]) {
217 return fmi1_capi_get_integer(fmu -> capi, vr, nvr, value);
220 fmi1_status_t fmi1_import_get_boolean(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, fmi1_boolean_t value[]) {
221 return fmi1_capi_get_boolean(fmu -> capi, vr, nvr, value);
224 fmi1_status_t fmi1_import_get_string(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, fmi1_string_t value[]) {
225 return fmi1_capi_get_string(fmu -> capi, vr, nvr, value);
229 /* FMI 1.0 ME functions */
230 const char* fmi1_import_get_model_types_platform(fmi1_import_t* fmu) {
231 return fmi1_capi_get_model_types_platform(fmu -> capi);
234 jm_status_enu_t fmi1_import_instantiate_model(fmi1_import_t* fmu, fmi1_string_t instanceName) {
235 fmi1_string_t GUID = fmi1_import_get_GUID(fmu);
236 fmi1_boolean_t loggingOn = (fmu->callbacks->log_level > jm_log_level_nothing);
237 fmi1_component_t c = fmi1_capi_instantiate_model(fmu -> capi, instanceName, GUID, loggingOn);
239 return jm_status_error;
241 return jm_status_success;
245 void fmi1_import_free_model_instance(fmi1_import_t* fmu) {
246 fmi1_capi_free_model_instance(fmu -> capi);
249 fmi1_status_t fmi1_import_set_time(fmi1_import_t* fmu, fmi1_real_t time) {
250 return fmi1_capi_set_time(fmu -> capi, time);
253 fmi1_status_t fmi1_import_set_continuous_states(fmi1_import_t* fmu, const fmi1_real_t x[], size_t nx) {
254 return fmi1_capi_set_continuous_states(fmu -> capi, x, nx);
257 fmi1_status_t fmi1_import_completed_integrator_step(fmi1_import_t* fmu, fmi1_boolean_t* callEventUpdate) {
258 return fmi1_capi_completed_integrator_step(fmu -> capi, callEventUpdate);
261 fmi1_status_t fmi1_import_initialize(fmi1_import_t* fmu, fmi1_boolean_t toleranceControlled, fmi1_real_t relativeTolerance, fmi1_event_info_t* eventInfo) {
262 return fmi1_capi_initialize(fmu -> capi, toleranceControlled, relativeTolerance, eventInfo);
265 fmi1_status_t fmi1_import_get_derivatives(fmi1_import_t* fmu, fmi1_real_t derivatives[], size_t nx) {
266 return fmi1_capi_get_derivatives(fmu -> capi, derivatives, nx);
269 fmi1_status_t fmi1_import_get_event_indicators(fmi1_import_t* fmu, fmi1_real_t eventIndicators[], size_t ni) {
270 return fmi1_capi_get_event_indicators(fmu -> capi, eventIndicators, ni);
273 fmi1_status_t fmi1_import_eventUpdate(fmi1_import_t* fmu, fmi1_boolean_t intermediateResults, fmi1_event_info_t* eventInfo) {
274 return fmi1_capi_eventUpdate(fmu -> capi, intermediateResults, eventInfo);
277 fmi1_status_t fmi1_import_get_continuous_states(fmi1_import_t* fmu, fmi1_real_t states[], size_t nx) {
278 return fmi1_capi_get_continuous_states(fmu -> capi, states, nx);
281 fmi1_status_t fmi1_import_get_nominal_continuous_states(fmi1_import_t* fmu, fmi1_real_t x_nominal[], size_t nx) {
282 return fmi1_capi_get_nominal_continuous_states(fmu -> capi, x_nominal, nx);
285 fmi1_status_t fmi1_import_get_state_value_references(fmi1_import_t* fmu, fmi1_value_reference_t vrx[], size_t nx) {
286 return fmi1_capi_get_state_value_references(fmu -> capi, vrx, nx);
289 fmi1_status_t fmi1_import_terminate(fmi1_import_t* fmu) {
290 return fmi1_capi_terminate(fmu -> capi);
294 /* FMI 1.0 CS functions */
295 const char* fmi1_import_get_types_platform(fmi1_import_t* fmu) {
296 return fmi1_capi_get_types_platform(fmu -> capi);
299 jm_status_enu_t fmi1_import_instantiate_slave(fmi1_import_t* fmu, fmi1_string_t instanceName, fmi1_string_t fmuLocation, fmi1_string_t mimeType,
300 fmi1_real_t timeout, fmi1_boolean_t visible, fmi1_boolean_t interactive) {
301 fmi1_string_t fmuGUID = fmi1_import_get_GUID(fmu);
302 fmi1_boolean_t loggingOn = (fmu->callbacks->log_level > jm_log_level_nothing);
304 if(!mimeType) mimeType = "application/x-fmu-sharedlibrary";
305 if(!fmuLocation) fmuLocation = fmu->location;
306 jm_log_verbose(fmu->callbacks, module, "Instantiating the slave with \n"
\r
307 "\tFMU location ='%s'\n\tMIME type = '%s'", fmuLocation, mimeType);
\r
309 c = fmi1_capi_instantiate_slave(fmu -> capi, instanceName, fmuGUID, fmuLocation, mimeType, timeout, visible, interactive, loggingOn);
311 return jm_status_error;
313 return jm_status_success;
317 fmi1_status_t fmi1_import_initialize_slave(fmi1_import_t* fmu, fmi1_real_t tStart, fmi1_boolean_t StopTimeDefined, fmi1_real_t tStop) {
318 return fmi1_capi_initialize_slave(fmu -> capi, tStart, StopTimeDefined, tStop);
321 fmi1_status_t fmi1_import_terminate_slave(fmi1_import_t* fmu) {
322 return fmi1_capi_terminate_slave(fmu -> capi);
325 fmi1_status_t fmi1_import_reset_slave(fmi1_import_t* fmu) {
326 return fmi1_capi_reset_slave(fmu -> capi);
329 void fmi1_import_free_slave_instance(fmi1_import_t* fmu) {
330 fmi1_capi_free_slave_instance(fmu -> capi);
333 fmi1_status_t fmi1_import_set_real_input_derivatives(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_integer_t order[], const fmi1_real_t value[]) {
334 return fmi1_capi_set_real_input_derivatives(fmu -> capi, vr, nvr, order, value);
337 fmi1_status_t fmi1_import_get_real_output_derivatives(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_integer_t order[], fmi1_real_t value[]) {
338 return fmi1_capi_get_real_output_derivatives(fmu -> capi, vr, nvr, order, value);
341 fmi1_status_t fmi1_import_cancel_step(fmi1_import_t* fmu) {
342 return fmi1_capi_cancel_step(fmu -> capi);
345 fmi1_status_t fmi1_import_do_step(fmi1_import_t* fmu, fmi1_real_t currentCommunicationPoint, fmi1_real_t communicationStepSize, fmi1_boolean_t newStep) {
346 return fmi1_capi_do_step(fmu -> capi, currentCommunicationPoint, communicationStepSize, newStep);
349 fmi1_status_t fmi1_import_get_status(fmi1_import_t* fmu, const fmi1_status_kind_t s, fmi1_status_t* value) {
350 return fmi1_capi_get_status(fmu -> capi, s, value);
353 fmi1_status_t fmi1_import_get_real_status(fmi1_import_t* fmu, const fmi1_status_kind_t s, fmi1_real_t* value) {
354 return fmi1_capi_get_real_status(fmu -> capi, s, value);
357 fmi1_status_t fmi1_import_get_integer_status(fmi1_import_t* fmu, const fmi1_status_kind_t s, fmi1_integer_t* value) {
358 return fmi1_capi_get_integer_status(fmu -> capi, s, value);
361 fmi1_status_t fmi1_import_get_boolean_status(fmi1_import_t* fmu, const fmi1_status_kind_t s, fmi1_boolean_t* value) {
362 return fmi1_capi_get_boolean_status(fmu -> capi, s, value);
365 fmi1_status_t fmi1_import_get_string_status(fmi1_import_t* fmu, const fmi1_status_kind_t s, fmi1_string_t* value) {
366 return fmi1_capi_get_string_status(fmu -> capi, s, value);