From: jsimomaa Date: Mon, 21 Aug 2017 06:07:34 +0000 (+0300) Subject: Improvements to FMI-support to support 2.0 FMU's X-Git-Tag: v1.31.0~3 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=9dcc8cac323b2fc064007203ef76e57e152699db;p=simantics%2Ffmil.git Improvements to FMI-support to support 2.0 FMU's refs #7440 Change-Id: I53dc3fc59308d00c3ab6285d33e1bc2d664c0413 --- diff --git a/org.simantics.fmil.core/META-INF/MANIFEST.MF b/org.simantics.fmil.core/META-INF/MANIFEST.MF index e5b5fa2..29e24d2 100644 --- a/org.simantics.fmil.core/META-INF/MANIFEST.MF +++ b/org.simantics.fmil.core/META-INF/MANIFEST.MF @@ -7,5 +7,6 @@ Bundle-Vendor: Semantum Oy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.eclipse.core.runtime;bundle-version="3.7.0", org.simantics.utils;bundle-version="1.1.0", - org.simantics;bundle-version="1.0.0" + org.simantics;bundle-version="1.0.0", + org.slf4j.api Export-Package: org.simantics.fmil.core diff --git a/org.simantics.fmil.core/README.md b/org.simantics.fmil.core/README.md new file mode 100644 index 0000000..e132c0d --- /dev/null +++ b/org.simantics.fmil.core/README.md @@ -0,0 +1,5 @@ +# How to build FMUSimulator and FMILibrary + +CMake GUI for generating Visual Studio project files from FMILibrary sources + +Remember to manually delete CMakeCache and CMakeFiles from FMILibrary/build/expatex/-folder \ No newline at end of file diff --git a/org.simantics.fmil.core/native/.gitingore b/org.simantics.fmil.core/native/.gitingore new file mode 100644 index 0000000..13e9162 --- /dev/null +++ b/org.simantics.fmil.core/native/.gitingore @@ -0,0 +1,4 @@ +Debug +x64 +x86 +Release \ No newline at end of file diff --git a/org.simantics.fmil.core/native/FMUSimulator/.gitignore b/org.simantics.fmil.core/native/FMUSimulator/.gitignore new file mode 100644 index 0000000..13e9162 --- /dev/null +++ b/org.simantics.fmil.core/native/FMUSimulator/.gitignore @@ -0,0 +1,4 @@ +Debug +x64 +x86 +Release \ No newline at end of file diff --git a/org.simantics.fmil.core/native/FMUSimulator/DEBUG_fmilib_shared32.lib b/org.simantics.fmil.core/native/FMUSimulator/DEBUG_fmilib_shared32.lib new file mode 100644 index 0000000..7507612 Binary files /dev/null and b/org.simantics.fmil.core/native/FMUSimulator/DEBUG_fmilib_shared32.lib differ diff --git a/org.simantics.fmil.core/native/FMUSimulator/DEBUG_fmilib_shared64.lib b/org.simantics.fmil.core/native/FMUSimulator/DEBUG_fmilib_shared64.lib new file mode 100644 index 0000000..cefe035 Binary files /dev/null and b/org.simantics.fmil.core/native/FMUSimulator/DEBUG_fmilib_shared64.lib differ diff --git a/org.simantics.fmil.core/native/FMUSimulator/fmi_util.c.txt b/org.simantics.fmil.core/native/FMUSimulator/fmi_util.c.txt index ab87846..7b90df5 100644 --- a/org.simantics.fmil.core/native/FMUSimulator/fmi_util.c.txt +++ b/org.simantics.fmil.core/native/FMUSimulator/fmi_util.c.txt @@ -1,489 +1,787 @@ -/* - Copyright (C) 2012 Modelon AB - - This program is free software: you can redistribute it and/or modify - it under the terms of the BSD style license. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - FMILIB_License.txt file for more details. - - You should have received a copy of the FMILIB_License.txt file - along with this program. If not, contact Modelon AB . -*/ - -#include -#include -#include -#include -#include - -char* fmi_construct_dll_dir_name(jm_callbacks* callbacks, const char* fmu_unzipped_path) { - char* dir_path; - size_t len; - - assert( fmu_unzipped_path && callbacks); - - len = - strlen(fmu_unzipped_path) + strlen(FMI_FILE_SEP) - + strlen(FMI_BINARIES) + strlen(FMI_FILE_SEP) - + strlen(FMI_PLATFORM) + strlen(FMI_FILE_SEP) + 1; - - dir_path = (char*)callbacks->malloc(len); - if (dir_path == NULL) { - jm_log_fatal(callbacks, "FMIUT", "Failed to allocate memory."); - return NULL; - } - - sprintf(dir_path, "%s%s%s%s%s%s", fmu_unzipped_path, FMI_FILE_SEP, FMI_BINARIES, FMI_FILE_SEP, FMI_PLATFORM, FMI_FILE_SEP);/*safe */ - - return dir_path; -} - -char* fmi_construct_dll_file_name(jm_callbacks* callbacks, const char* dll_dir_name, const char* model_identifier) { - char* fname; - size_t len; - assert(callbacks && model_identifier); - len = - strlen(dll_dir_name) + - strlen(model_identifier) - + strlen(FMI_DLL_EXT) + 1; - fname = (char*)callbacks->malloc(len); - if (fname == NULL) { - jm_log_fatal(callbacks, "FMIUT", "Failed to allocate memory."); - return NULL; - } - sprintf(fname, "%s%s%s", dll_dir_name, model_identifier, FMI_DLL_EXT);/*safe */ - - return fname; -} - - -//// - -#include -#include -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - char *name; - char *description; - char *declaredType; - long vr; - // 0 = real - // 1 = integer - // 2 = boolean - // 3 = string - // 4 = enumeration - int type; - // 0 = constant - // 1 = parameter - // 2 = discrete - // 3 = continuous - // 4 = unknown - int variability; - // 0 = input - // 1 = output - // 2 = internal - // 3 = none - // 4 = unknown - int causality; -} FMIL_Variable; - -typedef struct { - char *name; - char *description; - char *quantity; - char *unit; -} FMIL_DeclaredType; - -__declspec(dllexport) void* FMI1_CS_LOAD(const char *zipFilePath, const char *unzipFolder); -__declspec(dllexport) int FMI1_CS_UNLOAD(void* fmu); -__declspec(dllexport) FMIL_Variable *FMI1_CS_GET_VARIABLES(void* fmu, int *count); -__declspec(dllexport) FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void* fmu, int *count); -__declspec(dllexport) int FMI1_CS_INSTANTIATE(void* fmu); -__declspec(dllexport) int FMI1_CS_INITIALIZE(void* fmu); -__declspec(dllexport) int FMI1_CS_STEP(void* fmu, double masterTime, double stepSize); -__declspec(dllexport) int FMI1_CS_SET_REAL(void* fmu, int vr, double value); -__declspec(dllexport) double FMI1_CS_GET_REAL(void* fmu, int vr); -__declspec(dllexport) int FMI1_CS_GET_REALS(void* fmu, int *vrs, double *values, int count); - -#ifdef __cplusplus -} -#endif - -#define BUFFER 4096 - -/* Logger function used by the C-API */ -void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message) -{ - printf("module = %s, log level = %d: %s\n", module, log_level, message); -} - -/* Logger function used by the FMU internally */ -void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_status_t status, fmi1_string_t category, fmi1_string_t message, ...) -{ - char msg[BUFFER]; - int len; - va_list argp; - va_start(argp, message); - /*len=jm_vsnprintf(msg, BUFFER, message, argp); - printf("fmiStatus = %d; %s (%s): %s\n", status, instanceName, category, msg); - if(len > BUFFER) { - printf("Warning: message was trancated"); - }*/ -} - -void *FMI1_CS_LOAD(char *zipFilePath, char *unzipFolder) { - - fmi1_callback_functions_t callBackFunctions; - fmi_import_context_t* context; - fmi1_fmu_kind_enu_t standard = fmi1_fmu_kind_enu_cs_standalone; - fmi_version_enu_t version; - jm_status_enu_t status; - fmi1_import_t *fmu; - jm_callbacks* callbacks; - - callbacks = (jm_callbacks *)calloc(1, sizeof(jm_callbacks)); - - callbacks->malloc = malloc; - callbacks->calloc = calloc; - callbacks->realloc = realloc; - callbacks->free = free; - callbacks->logger = importlogger; - callbacks->log_level = jm_log_level_debug; - callbacks->context = 0; - - callBackFunctions.logger = fmilogger; - callBackFunctions.allocateMemory = calloc; - callBackFunctions.freeMemory = free; - - context = fmi_import_allocate_context(callbacks); - - version = fmi_import_get_fmi_version(context, zipFilePath, unzipFolder); - - fmu = fmi1_import_parse_xml(context, unzipFolder); - - status = fmi1_import_create_dllfmu(fmu, callBackFunctions, 0); - - fmi_import_free_context(context); - - return fmu; - -} - -int FMI1_CS_UNLOAD(void *fmu_) { - - fmi1_import_t *fmu = (fmi1_import_t *)fmu_; - - fmi1_import_destroy_dllfmu(fmu); - - fmi1_import_free(fmu); - - return 1; - -} - -/* - if(!vt) { - printf("No type definition\n"); - return; - } - - quan = fmi1_import_get_type_quantity(vt); - - printf("Type %s\n description: %s\n", fmi1_import_get_type_name(vt), fmi1_import_get_type_description(vt)); - - printf("Base type: %s\n", fmi1_base_type_to_string(fmi1_import_get_base_type(vt))); - - if(quan) { - printf("Quantity: %s\n", quan); - } - switch(fmi1_import_get_base_type(vt)) { - case fmi1_base_type_real: { - fmi1_import_real_typedef_t* rt = fmi1_import_get_type_as_real(vt); - fmi1_real_t min = fmi1_import_get_real_type_min(rt); - fmi1_real_t max = fmi1_import_get_real_type_max(rt); - fmi1_real_t nom = fmi1_import_get_real_type_nominal(rt); - fmi1_import_unit_t* u = fmi1_import_get_real_type_unit(rt); - fmi1_import_display_unit_t* du = fmi1_import_get_type_display_unit(rt); - - printf("Min %g, max %g, nominal %g\n", min, max, nom); - - if(u) { - printf("Unit: %s\n", fmi1_import_get_unit_name(u)); - } - if(du) { - printf("Display unit: %s, gain: %g, offset: %g, is relative: %s", - fmi1_import_get_display_unit_name(du), - fmi1_import_get_display_unit_gain(du), - fmi1_import_get_display_unit_offset(du), - fmi1_import_get_real_type_is_relative_quantity(rt)?"yes":"no" - ); - } - - break; - } - case fmi1_base_type_int:{ - fmi1_import_integer_typedef_t* it = fmi1_import_get_type_as_int(vt); - int min = fmi1_import_get_integer_type_min(it); - int max = fmi1_import_get_integer_type_max(it); - printf("Min %d, max %d\n", min, max); - break; - } - case fmi1_base_type_bool:{ - break; - } - case fmi1_base_type_str:{ - break; - } - case fmi1_base_type_enum:{ - fmi1_import_enumeration_typedef_t* et = fmi1_import_get_type_as_enum(vt); - int min = fmi1_import_get_enum_type_min(et); - int max = fmi1_import_get_enum_type_max(et); - printf("Min %d, max %d\n", min, max); - { - size_t ni; - unsigned i; - ni = fmi1_import_get_enum_type_size(et); - i = (unsigned)(ni); - assert( i == ni); - printf("There are %u items \n",(unsigned)ni); - for(i = 0; i < ni; i++) { - printf("[%u] %s (%s) \n", (unsigned)i+1, fmi1_import_get_enum_type_item_name(et, i), fmi1_import_get_enum_type_item_description(et, i)); - } - } - break; - } - default: - printf("Error in fmiGetBaseType()\n"); - } -*/ - - -FMIL_Variable *FMI1_CS_GET_VARIABLES(void *fmu, int *count) { - - int i; - FMIL_Variable *result; - fmi1_import_variable_list_t* vl = fmi1_import_get_variable_list((fmi1_import_t *)fmu); - fmi1_import_variable_typedef_t* type; - - count[0] = fmi1_import_get_variable_list_size(vl); - - result = (FMIL_Variable *)malloc(count[0]*sizeof(FMIL_Variable)); - - for(i = 0; i < count[0]; i++) { - - fmi1_import_variable_t* var = fmi1_import_get_variable(vl, i); - if(!var) { - - printf("Something wrong with variable %d \n",i); - return 0; - - } else { - - result[i].name = fmi1_import_get_variable_name(var); - result[i].description = fmi1_import_get_variable_description(var); - - switch (fmi1_import_get_variability(var)) { - case fmi1_variability_enu_constant: - result[i].variability = 0; - break; - case fmi1_variability_enu_parameter: - result[i].variability = 1; - break; - case fmi1_variability_enu_discrete: - result[i].variability = 2; - break; - case fmi1_variability_enu_continuous: - result[i].variability = 3; - break; - case fmi1_variability_enu_unknown: - result[i].variability = 4; - break; - } - - switch (fmi1_import_get_causality(var)) { - case fmi1_causality_enu_input: - result[i].causality = 0; - break; - case fmi1_causality_enu_output: - result[i].causality = 1; - break; - case fmi1_causality_enu_internal: - result[i].causality = 2; - break; - case fmi1_causality_enu_none: - result[i].causality = 3; - break; - case fmi1_causality_enu_unknown: - result[i].causality = 4; - break; - } - - switch (fmi1_import_get_variable_base_type(var)) { - case fmi1_base_type_real: - result[i].type = 0; - break; - case fmi1_base_type_int: - result[i].type = 1; - break; - case fmi1_base_type_bool: - result[i].type = 2; - break; - case fmi1_base_type_str: - result[i].type = 3; - break; - case fmi1_base_type_enum: - result[i].type = 4; - break; - } - - result[i].vr = fmi1_import_get_variable_vr(var); - - type = fmi1_import_get_variable_declared_type(var); - if(type) { - result[i].declaredType = fmi1_import_get_type_name(type); - } else { - result[i].declaredType = 0; - } - - } - - } - - fmi1_import_free_variable_list(vl); - - return result; - -} - -FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void *fmu, int *count) { - - FMIL_DeclaredType *result; - fmi1_import_type_definitions_t* td = fmi1_import_get_type_definitions((fmi1_import_t *)fmu); - fmi1_import_variable_typedef_t* type; - unsigned i, ntd = (unsigned)fmi1_import_get_type_definition_number(td); - - count[0] = ntd; - - result = (FMIL_DeclaredType *)malloc(count[0]*sizeof(FMIL_DeclaredType)); - - for(i = 0; i < ntd; i++) { - type = fmi1_import_get_typedef(td, i); - result[i].name = fmi1_import_get_type_name(type); - result[i].description = fmi1_import_get_type_description(type); - result[i].quantity = fmi1_import_get_type_quantity(type); - result[i].unit = 0; - - switch(fmi1_import_get_base_type(type)) { - case fmi1_base_type_real: { - fmi1_import_real_typedef_t* rt = fmi1_import_get_type_as_real(type); - fmi1_import_unit_t* u = fmi1_import_get_real_type_unit(rt); - if(u) result[i].unit = fmi1_import_get_unit_name(u); - } - } - - } - - return result; - -} - -#define INSTANCE_NAME "kekkeli" - -int FMI1_CS_INSTANTIATE(void *fmu) { - - fmi1_string_t fmuLocation; - fmi1_string_t mimeType; - fmi1_real_t timeout; - fmi1_boolean_t visible; - fmi1_boolean_t interactive; - fmi1_boolean_t loggingOn; - - fmuLocation = ""; - mimeType = ""; - timeout = 0; - visible = fmi1_false; - interactive = fmi1_false; - loggingOn = fmi1_true; - - if (fmi1_import_instantiate_slave(fmu, INSTANCE_NAME, NULL, NULL, timeout, fmi1_false, fmi1_false) == NULL) { - printf("fmi1_capi_instantiate_slave: Failed\n"); - return 0; - } else { - printf("fmi1_capi_instantiate_slave: Success\n"); - } - return 0; - -} - -int FMI1_CS_INITIALIZE(void *fmu) { - - fmi1_status_t status; - fmi1_real_t tStart; - fmi1_real_t tStop; - fmi1_boolean_t StopTimeDefined; - - tStart = 0; - tStop = 10; - StopTimeDefined = fmi1_false; - - status = fmi1_import_initialize_slave((fmi1_import_t *)fmu, tStart, StopTimeDefined, tStop); - if (status == fmi1_status_error || status == fmi1_status_fatal) { - printf("fmi1_capi_initialize_slave: Failed\n"); - return 0; - } else { - printf("fmi1_capi_initialize_slave: Success\n"); - } - return 0; - -} - -int FMI1_CS_STEP(void *fmu, double masterTime, double stepSize) { - - fmi1_status_t status; - - status = fmi1_import_do_step((fmi1_import_t *)fmu, (fmi1_real_t)masterTime, (fmi1_real_t)stepSize, fmi1_true); - if (status == fmi1_status_error || status == fmi1_status_fatal) { - return 1; - } else { - return 0; - } -} - -int FMI1_CS_SET_REAL(void *fmu, long valueId, double value) { - - fmi1_value_reference_t vr = valueId; - fmi1_import_set_real((fmi1_import_t *)fmu, &vr, 1, &value); - - return 0; - -} - -double FMI1_CS_GET_REAL(void *fmu, int valueReference) { - - fmi1_value_reference_t vr = valueReference; - fmi1_real_t value; - fmi1_import_get_real((fmi1_import_t *)fmu, &vr, 1, &value); - return value; - -} - -int FMI1_CS_GET_REALS(void *fmu, int *valueReferences, double *result, int count) { - - fmi1_value_reference_t *vrs = valueReferences; - fmi1_real_t value; - fmi1_import_get_real((fmi1_import_t *)fmu, vrs, count, result); - return 1; - -} +/* + Copyright (C) 2012 Modelon AB + + This program is free software: you can redistribute it and/or modify + it under the terms of the BSD style license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + FMILIB_License.txt file for more details. + + You should have received a copy of the FMILIB_License.txt file + along with this program. If not, contact Modelon AB . +*/ + +#include +#include +#include +#include +#include + +char* fmi_construct_dll_dir_name(jm_callbacks* callbacks, const char* fmu_unzipped_path) { + char* dir_path; + size_t len; + + assert( fmu_unzipped_path && callbacks); + + len = + strlen(fmu_unzipped_path) + strlen(FMI_FILE_SEP) + + strlen(FMI_BINARIES) + strlen(FMI_FILE_SEP) + + strlen(FMI_PLATFORM) + strlen(FMI_FILE_SEP) + 1; + + dir_path = (char*)callbacks->malloc(len); + if (dir_path == NULL) { + jm_log_fatal(callbacks, "FMIUT", "Failed to allocate memory."); + return NULL; + } + + sprintf(dir_path, "%s%s%s%s%s%s", fmu_unzipped_path, FMI_FILE_SEP, FMI_BINARIES, FMI_FILE_SEP, FMI_PLATFORM, FMI_FILE_SEP);/*safe */ + + return dir_path; +} + +char* fmi_construct_dll_file_name(jm_callbacks* callbacks, const char* dll_dir_name, const char* model_identifier) { + char* fname; + size_t len; + assert(callbacks && model_identifier); + len = + strlen(dll_dir_name) + + strlen(model_identifier) + + strlen(FMI_DLL_EXT) + 1; + fname = (char*)callbacks->malloc(len); + if (fname == NULL) { + jm_log_fatal(callbacks, "FMIUT", "Failed to allocate memory."); + return NULL; + } + sprintf(fname, "%s%s%s", dll_dir_name, model_identifier, FMI_DLL_EXT);/*safe */ + + return fname; +} + +//// + +#include +#include +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char *name; + char *description; + char *declaredType; + long vr; + // 0 = real + // 1 = integer + // 2 = boolean + // 3 = string + // 4 = enumeration + int type; + // 0 = constant + // 1 = parameter + // 2 = discrete + // 3 = continuous + // 4 = unknown + int variability; + // 0 = input + // 1 = output + // 2 = internal + // 3 = none + // 4 = unknown + int causality; +} FMIL_Variable; + +typedef struct { + char *name; + char *description; + char *quantity; + char *unit; +} FMIL_DeclaredType; + +__declspec(dllexport) int FMI_CS_LOAD(const char *zipFilePath, const char *unzipFolder, void **fmuPointer, int *fmuVersion, const char **error); + +__declspec(dllexport) int FMI1_CS_UNLOAD(void* fmu, const char **error); +__declspec(dllexport) FMIL_Variable *FMI1_CS_GET_VARIABLES(void* fmu, int *count, const char **error); +__declspec(dllexport) FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void* fmu, int *count, const char **error); +__declspec(dllexport) int FMI1_CS_INSTANTIATE(void* fmu, const char *instanceName, const char **error); +__declspec(dllexport) int FMI1_CS_INITIALIZE(void* fmu, const char **error); +__declspec(dllexport) int FMI1_CS_STEP(void* fmu, double masterTime, double stepSize, const char **error); +__declspec(dllexport) int FMI1_CS_SET_REAL(void* fmu, int vr, double value, const char **error); +__declspec(dllexport) double FMI1_CS_GET_REAL(void* fmu, int vr, const char **error); +__declspec(dllexport) int FMI1_CS_GET_REALS(void* fmu, int *vrs, double *values, int count, const char **error); + +__declspec(dllexport) int FMI2_CS_UNLOAD(void* fmu, const char **error); +__declspec(dllexport) FMIL_Variable *FMI2_CS_GET_VARIABLES(void* fmu, int *count, const char **error); +__declspec(dllexport) FMIL_DeclaredType *FMI2_CS_GET_DECLARED_TYPES(void* fmu, int *count, const char **error); +__declspec(dllexport) int FMI2_CS_INSTANTIATE(void* fmu, const char *instanceName, const char **error); +__declspec(dllexport) int FMI2_CS_INITIALIZE(void* fmu, const char **error); +__declspec(dllexport) int FMI2_CS_STEP(void* fmu, double masterTime, double stepSize, const char **error); +__declspec(dllexport) int FMI2_CS_SET_REAL(void* fmu, int vr, double value, const char **error); +__declspec(dllexport) double FMI2_CS_GET_REAL(void* fmu, int vr, const char **error); +__declspec(dllexport) int FMI2_CS_GET_REALS(void* fmu, int *vrs, double *values, int count, const char **error); + +#ifdef __cplusplus +} +#endif + +#define BUFFER 4096 + +/* Logger function used by the C-API */ +void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message) +{ + printf("module = %s, log level = %d: %s\n", module, log_level, message); +} + +/* Logger function used by the FMU internally */ +void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_status_t status, fmi1_string_t category, fmi1_string_t message, ...) +{ + char msg[BUFFER]; + int len; + va_list argp; + va_start(argp, message); + /*len=jm_vsnprintf(msg, BUFFER, message, argp); + printf("fmiStatus = %d; %s (%s): %s\n", status, instanceName, category, msg); + if(len > BUFFER) { + printf("Warning: message was trancated"); + }*/ +} + +int FMI_CS_LOAD(char *zipFilePath, char *unzipFolder, void **fmuPointer, int *fmuVersion, const char **error) { + + fmi1_callback_functions_t callBackFunctions; + fmi2_callback_functions_t callBackFunctions2; + fmi_import_context_t* context; + fmi_version_enu_t version; + jm_status_enu_t status; + fmi1_import_t *fmu; + fmi2_import_t *fmu2; + jm_callbacks* callbacks; + + callbacks = (jm_callbacks *)calloc(1, sizeof(jm_callbacks)); + + callbacks->malloc = malloc; + callbacks->calloc = calloc; + callbacks->realloc = realloc; + callbacks->free = free; + callbacks->logger = importlogger; + callbacks->log_level = jm_log_level_debug; + callbacks->context = 0; + + context = fmi_import_allocate_context(callbacks); + + version = fmi_import_get_fmi_version(context, zipFilePath, unzipFolder); + + if (version == fmi_version_1_enu ) { + fmu = fmi1_import_parse_xml(context, unzipFolder); + if (fmi1_import_get_fmu_kind(fmu) != fmi1_fmu_kind_enu_cs_standalone && fmi1_import_get_fmu_kind(fmu) != fmi1_fmu_kind_enu_cs_tool) { + *error = "Provided FMU is version 1 but wrong type me (Model Exchange) when it should be cs (Co-Simulation)"; + return 2; // wrong type, should be co-simulation + } + + callBackFunctions.logger = fmilogger; + callBackFunctions.allocateMemory = calloc; + callBackFunctions.freeMemory = free; + + status = fmi1_import_create_dllfmu(fmu, callBackFunctions, 0); + if (status == jm_status_error) { + *error = fmi1_import_get_last_error(fmu); + return 3; + } + + *fmuPointer = fmu; + *fmuVersion = 1; + } else if (version == fmi_version_2_0_enu) { + fmu2 = fmi2_import_parse_xml(context, unzipFolder, 0); + + if (fmi2_import_get_fmu_kind(fmu2) != fmi1_fmu_kind_enu_cs_standalone && fmi2_import_get_fmu_kind(fmu2) != fmi1_fmu_kind_enu_cs_tool) { + *error = "Provided FMU is version 2.0 but wrong type me (Model Exchange) when it should be cs (Co-Simulation)"; + return 2; // wrong type, should be co-simulation + } + + callBackFunctions2.logger = fmi2_log_forwarding; + callBackFunctions2.allocateMemory = calloc; + callBackFunctions2.freeMemory = free; + callBackFunctions2.componentEnvironment = fmu2; + + status = fmi2_import_create_dllfmu(fmu2, fmi2_fmu_kind_cs, &callBackFunctions2); + if (status == jm_status_error) { + *error = fmi2_import_get_last_error(fmu2); + return 3; + } + + *fmuPointer = fmu2; + *fmuVersion = 2; + } + + fmi_import_free_context(context); + + return 0; // success +} + +int FMI1_CS_UNLOAD(void *fmu_, const char **error) { + fmi1_import_t *fmu = (fmi1_import_t *)fmu_; + fmi1_import_destroy_dllfmu(fmu); + fmi1_import_free(fmu); + return 0; +} + +int FMI2_CS_UNLOAD(void *fmu_, const char **error) { + fmi2_import_t *fmu = (fmi2_import_t *)fmu_; + fmi2_import_destroy_dllfmu(fmu); + fmi2_import_free(fmu); + return 0; +} + +/* + if(!vt) { + printf("No type definition\n"); + return; + } + + quan = fmi1_import_get_type_quantity(vt); + + printf("Type %s\n description: %s\n", fmi1_import_get_type_name(vt), fmi1_import_get_type_description(vt)); + + printf("Base type: %s\n", fmi1_base_type_to_string(fmi1_import_get_base_type(vt))); + + if(quan) { + printf("Quantity: %s\n", quan); + } + switch(fmi1_import_get_base_type(vt)) { + case fmi1_base_type_real: { + fmi1_import_real_typedef_t* rt = fmi1_import_get_type_as_real(vt); + fmi1_real_t min = fmi1_import_get_real_type_min(rt); + fmi1_real_t max = fmi1_import_get_real_type_max(rt); + fmi1_real_t nom = fmi1_import_get_real_type_nominal(rt); + fmi1_import_unit_t* u = fmi1_import_get_real_type_unit(rt); + fmi1_import_display_unit_t* du = fmi1_import_get_type_display_unit(rt); + + printf("Min %g, max %g, nominal %g\n", min, max, nom); + + if(u) { + printf("Unit: %s\n", fmi1_import_get_unit_name(u)); + } + if(du) { + printf("Display unit: %s, gain: %g, offset: %g, is relative: %s", + fmi1_import_get_display_unit_name(du), + fmi1_import_get_display_unit_gain(du), + fmi1_import_get_display_unit_offset(du), + fmi1_import_get_real_type_is_relative_quantity(rt)?"yes":"no" + ); + } + + break; + } + case fmi1_base_type_int:{ + fmi1_import_integer_typedef_t* it = fmi1_import_get_type_as_int(vt); + int min = fmi1_import_get_integer_type_min(it); + int max = fmi1_import_get_integer_type_max(it); + printf("Min %d, max %d\n", min, max); + break; + } + case fmi1_base_type_bool:{ + break; + } + case fmi1_base_type_str:{ + break; + } + case fmi1_base_type_enum:{ + fmi1_import_enumeration_typedef_t* et = fmi1_import_get_type_as_enum(vt); + int min = fmi1_import_get_enum_type_min(et); + int max = fmi1_import_get_enum_type_max(et); + printf("Min %d, max %d\n", min, max); + { + size_t ni; + unsigned i; + ni = fmi1_import_get_enum_type_size(et); + i = (unsigned)(ni); + assert( i == ni); + printf("There are %u items \n",(unsigned)ni); + for(i = 0; i < ni; i++) { + printf("[%u] %s (%s) \n", (unsigned)i+1, fmi1_import_get_enum_type_item_name(et, i), fmi1_import_get_enum_type_item_description(et, i)); + } + } + break; + } + default: + printf("Error in fmiGetBaseType()\n"); + } +*/ + + +FMIL_Variable *FMI1_CS_GET_VARIABLES(void *fmu, int *count, const char **error) { + + int i; + FMIL_Variable *result; + fmi1_import_variable_list_t* vl = fmi1_import_get_variable_list((fmi1_import_t *)fmu); + fmi1_import_variable_typedef_t* type; + + count[0] = fmi1_import_get_variable_list_size(vl); + + result = (FMIL_Variable *)malloc(count[0]*sizeof(FMIL_Variable)); + + for(i = 0; i < count[0]; i++) { + + fmi1_import_variable_t* var = fmi1_import_get_variable(vl, i); + if(!var) { + + printf("Something wrong with variable %d \n",i); + return 0; + + } else { + + result[i].name = fmi1_import_get_variable_name(var); + result[i].description = fmi1_import_get_variable_description(var); + + switch (fmi1_import_get_variability(var)) { + case fmi1_variability_enu_constant: + result[i].variability = 0; + break; + case fmi1_variability_enu_parameter: + result[i].variability = 1; + break; + case fmi1_variability_enu_discrete: + result[i].variability = 2; + break; + case fmi1_variability_enu_continuous: + result[i].variability = 3; + break; + case fmi1_variability_enu_unknown: + result[i].variability = 4; + break; + } + + switch (fmi1_import_get_causality(var)) { + case fmi1_causality_enu_input: + result[i].causality = 0; + break; + case fmi1_causality_enu_output: + result[i].causality = 1; + break; + case fmi1_causality_enu_internal: + result[i].causality = 2; + break; + case fmi1_causality_enu_none: + result[i].causality = 3; + break; + case fmi1_causality_enu_unknown: + result[i].causality = 4; + break; + } + + switch (fmi1_import_get_variable_base_type(var)) { + case fmi1_base_type_real: + result[i].type = 0; + break; + case fmi1_base_type_int: + result[i].type = 1; + break; + case fmi1_base_type_bool: + result[i].type = 2; + break; + case fmi1_base_type_str: + result[i].type = 3; + break; + case fmi1_base_type_enum: + result[i].type = 4; + break; + } + + result[i].vr = fmi1_import_get_variable_vr(var); + + type = fmi1_import_get_variable_declared_type(var); + if(type) { + result[i].declaredType = fmi1_import_get_type_name(type); + } else { + result[i].declaredType = 0; + } + + } + + } + + fmi1_import_free_variable_list(vl); + + return result; + +} + +FMIL_Variable *FMI2_CS_GET_VARIABLES(void *fmu, int *count, const char **error) { + + int i; + FMIL_Variable *result; + fmi2_import_variable_list_t* vl = fmi2_import_get_variable_list((fmi2_import_t *)fmu, 0); + fmi2_import_variable_typedef_t* type; + + count[0] = fmi2_import_get_variable_list_size(vl); + + result = (FMIL_Variable *)malloc(count[0]*sizeof(FMIL_Variable)); + + for(i = 0; i < count[0]; i++) { + + fmi2_import_variable_t* var = fmi2_import_get_variable(vl, i); + if(!var) { + + printf("Something wrong with variable %d \n",i); + return 0; + + } else { + + result[i].name = fmi2_import_get_variable_name(var); + result[i].description = fmi2_import_get_variable_description(var); + + switch (fmi2_import_get_variability(var)) { + case fmi2_variability_enu_constant: + result[i].variability = 0; + break; + case fmi2_variability_enu_fixed: + case fmi2_variability_enu_tunable: + result[i].variability = 1; + break; + case fmi2_variability_enu_discrete: + result[i].variability = 2; + break; + case fmi2_variability_enu_continuous: + result[i].variability = 3; + break; + case fmi2_variability_enu_unknown: + result[i].variability = 4; + break; + } + + switch (fmi2_import_get_causality(var)) { + case fmi2_causality_enu_input: + result[i].causality = 0; + break; + case fmi2_causality_enu_output: + result[i].causality = 1; + break; + case fmi2_causality_enu_local: + result[i].causality = 2; + break; + case fmi2_causality_enu_independent: + result[i].causality = 3; + break; + case fmi2_causality_enu_unknown: + result[i].causality = 4; + break; + } + + switch (fmi2_import_get_variable_base_type(var)) { + case fmi2_base_type_real: + result[i].type = 0; + break; + case fmi2_base_type_int: + result[i].type = 1; + break; + case fmi2_base_type_bool: + result[i].type = 2; + break; + case fmi2_base_type_str: + result[i].type = 3; + break; + case fmi2_base_type_enum: + result[i].type = 4; + break; + } + + result[i].vr = fmi2_import_get_variable_vr(var); + + type = fmi2_import_get_variable_declared_type(var); + if(type) { + result[i].declaredType = fmi2_import_get_type_name(type); + } else { + result[i].declaredType = 0; + } + + } + + } + + fmi2_import_free_variable_list(vl); + + return result; + +} + +FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void *fmu, int *count, const char **error) { + + FMIL_DeclaredType *result; + fmi1_import_type_definitions_t* td = fmi1_import_get_type_definitions((fmi1_import_t *)fmu); + fmi1_import_variable_typedef_t* type; + unsigned i, ntd = (unsigned)fmi1_import_get_type_definition_number(td); + + count[0] = ntd; + + result = (FMIL_DeclaredType *)malloc(count[0]*sizeof(FMIL_DeclaredType)); + + for(i = 0; i < ntd; i++) { + type = fmi1_import_get_typedef(td, i); + result[i].name = fmi1_import_get_type_name(type); + result[i].description = fmi1_import_get_type_description(type); + result[i].quantity = fmi1_import_get_type_quantity(type); + result[i].unit = 0; + + switch(fmi1_import_get_base_type(type)) { + case fmi1_base_type_real: { + fmi1_import_real_typedef_t* rt = fmi1_import_get_type_as_real(type); + fmi1_import_unit_t* u = fmi1_import_get_real_type_unit(rt); + if(u) result[i].unit = fmi1_import_get_unit_name(u); + } + } + + } + + return result; + +} + +FMIL_DeclaredType *FMI2_CS_GET_DECLARED_TYPES(void *fmu, int *count, const char **error) { + + FMIL_DeclaredType *result; + fmi2_import_type_definitions_t* td = fmi2_import_get_type_definitions((fmi2_import_t *)fmu); + fmi2_import_variable_typedef_t* type; + unsigned i, ntd = (unsigned)fmi2_import_get_type_definition_number(td); + + count[0] = ntd; + + result = (FMIL_DeclaredType *)malloc(count[0]*sizeof(FMIL_DeclaredType)); + + for(i = 0; i < ntd; i++) { + type = fmi2_import_get_typedef(td, i); + result[i].name = fmi2_import_get_type_name(type); + result[i].description = fmi2_import_get_type_description(type); + result[i].quantity = fmi2_import_get_type_quantity(type); + result[i].unit = 0; + + switch(fmi2_import_get_base_type(type)) { + case fmi2_base_type_real: { + fmi2_import_real_typedef_t* rt = fmi2_import_get_type_as_real(type); + fmi2_import_unit_t* u = fmi2_import_get_real_type_unit(rt); + if(u) result[i].unit = fmi2_import_get_unit_name(u); + } + } + + } + + return result; + +} + +int FMI1_CS_INSTANTIATE(void *fmu, const char *instanceName, const char **error) { + + fmi1_string_t fmuLocation; + fmi1_string_t mimeType; + fmi1_real_t timeout; + fmi1_boolean_t visible; + fmi1_boolean_t interactive; + fmi1_boolean_t loggingOn; + + jm_status_enu_t jmstatus; + + fmuLocation = ""; + mimeType = ""; + timeout = 0; + visible = fmi1_false; + interactive = fmi1_false; + loggingOn = fmi1_true; + + jmstatus = fmi1_import_instantiate_slave((fmi1_import_t*)fmu, instanceName, NULL, NULL, timeout, fmi1_false, fmi1_false); + if (jmstatus == jm_status_error) { + *error = fmi1_import_get_last_error((fmi1_import_t*)fmu); + return 1; + } + return 0; +} + +int FMI2_CS_INSTANTIATE(void *fmu, const char *instanceName, const char **error) { + + fmi2_string_t fmuLocation; + fmi2_string_t mimeType; + fmi2_real_t timeout; + fmi2_boolean_t visible; + fmi2_boolean_t interactive; + fmi2_boolean_t loggingOn; + jm_status_enu_t jmstatus; + + fmuLocation = ""; + mimeType = ""; + timeout = 0; + visible = fmi2_false; + jmstatus = fmi2_import_instantiate((fmi2_import_t*)fmu, instanceName, fmi2_cosimulation, NULL, visible); + if (jmstatus == jm_status_error) { + *error = fmi2_import_get_last_error((fmi2_import_t*)fmu); + return 1; + } + return 0; +} + +int FMI1_CS_INITIALIZE(void *fmu, const char **error) { + + fmi1_status_t status; + fmi1_real_t tStart; + fmi1_real_t tStop; + fmi1_boolean_t StopTimeDefined; + + tStart = 0; + tStop = 10; + StopTimeDefined = fmi1_false; + + status = fmi1_import_initialize_slave((fmi1_import_t *)fmu, tStart, StopTimeDefined, tStop); + if (status == fmi1_status_error || status == fmi1_status_fatal) { + printf("fmi1_capi_initialize_slave: Failed\n"); + return 0; + } else { + printf("fmi1_capi_initialize_slave: Success\n"); + } + return 0; + +} + +int FMI2_CS_INITIALIZE(void *fmu, const char **error) { + + fmi2_real_t tStart; + fmi2_real_t tStop; + fmi2_boolean_t StopTimeDefined; + fmi2_real_t relativeTol = 1e-4; + + fmi2_status_t fmistatus; + + tStart = 0; + tStop = 10; + StopTimeDefined = fmi1_false; + + fmistatus = fmi2_import_setup_experiment((fmi2_import_t*)fmu, fmi2_true, relativeTol, tStart, StopTimeDefined, tStop); + if(fmistatus != fmi2_status_ok) { + *error = ("fmi2_import_setup_experiment failed\n"); + return 1; + } + + fmistatus = fmi2_import_enter_initialization_mode((fmi2_import_t*)fmu); + if(fmistatus != fmi2_status_ok) { + *error = ("fmi2_import_enter_initialization_mode failed\n"); + return 1; + } + + fmistatus = fmi2_import_exit_initialization_mode((fmi2_import_t*)fmu); + if(fmistatus != fmi2_status_ok) { + *error = ("fmi2_import_exit_initialization_mode failed\n"); + return 1; + } + + return 0; +} + +int FMI1_CS_STEP(void *fmu, double masterTime, double stepSize, const char **error) { + + fmi1_status_t status; + + status = fmi1_import_do_step((fmi1_import_t *)fmu, (fmi1_real_t)masterTime, (fmi1_real_t)stepSize, fmi1_true); + if (status == fmi1_status_error || status == fmi1_status_fatal) { + *error = "Error happened during stepping!"; + return 1; + } + return 0; +} + +int FMI2_CS_STEP(void *fmu, double masterTime, double stepSize, const char **error) { + + fmi2_status_t status; + + status = fmi2_import_do_step((fmi2_import_t *)fmu, (fmi2_real_t)masterTime, (fmi2_real_t)stepSize, fmi2_true); + if (status == fmi2_status_error || status == fmi2_status_fatal) { + *error = "Error happened during stepping!"; + return 1; + } + return 0; +} + +int FMI1_CS_SET_REAL(void *fmu, long valueId, double value, const char **error) { + + fmi1_status_t status; + + fmi1_value_reference_t vr = valueId; + status = fmi1_import_set_real((fmi1_import_t *)fmu, &vr, 1, &value); + if (status == fmi1_status_error || status == fmi1_status_fatal) { + *error = "Error happened during setting real value!"; + return 1; + } + return 0; +} + +int FMI2_CS_SET_REAL(void *fmu, long valueId, double value, const char **error) { + + fmi2_status_t status; + + fmi2_value_reference_t vr = valueId; + status = fmi2_import_set_real((fmi2_import_t *)fmu, &vr, 1, &value); + if (status == fmi2_status_error || status == fmi2_status_fatal) { + *error = "Error happened during setting real value!"; + return 1; + } + return 0; +} + +double FMI1_CS_GET_REAL(void *fmu, int valueReference, const char **error) { + + fmi1_value_reference_t vr = valueReference; + fmi1_real_t value; + + fmi1_status_t status; + + status = fmi1_import_get_real((fmi1_import_t *)fmu, &vr, 1, &value); + if (status == fmi1_status_error || status == fmi1_status_fatal) { + *error = "Error happened during getting real value!"; + } + return value; +} + +double FMI2_CS_GET_REAL(void *fmu, int valueReference, const char **error) { + + fmi2_value_reference_t vr = valueReference; + fmi2_real_t value; + + fmi2_status_t status; + + status = fmi2_import_get_real((fmi2_import_t *)fmu, &vr, 1, &value); + if (status == fmi2_status_error || status == fmi2_status_fatal) { + *error = "Error happened during setting real value!"; + } + return value; +} + +int FMI1_CS_GET_REALS(void *fmu, int *valueReferences, double *result, int count, const char **error) { + + fmi1_value_reference_t *vrs = valueReferences; + fmi1_real_t value; + + fmi1_status_t status; + + status = fmi1_import_get_real((fmi1_import_t *)fmu, vrs, count, result); + if (status == fmi1_status_error || status == fmi1_status_fatal) { + *error = "Error happened during getting reals value!"; + } + return 0; +} + +int FMI2_CS_GET_REALS(void *fmu, int *valueReferences, double *result, int count, const char **error) { + + fmi2_value_reference_t *vrs = valueReferences; + fmi2_real_t value; + + fmi2_status_t status; + + status = fmi2_import_get_real((fmi2_import_t *)fmu, vrs, count, result); + if (status == fmi2_status_error || status == fmi2_status_fatal) { + *error = "Error happened during getting reals value!"; + } + return 0; + +} diff --git a/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared32.lib b/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared32.lib index 4a2c027..205ff49 100644 Binary files a/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared32.lib and b/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared32.lib differ diff --git a/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared64.lib b/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared64.lib index 191166a..d181250 100644 Binary files a/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared64.lib and b/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared64.lib differ diff --git a/org.simantics.fmil.core/native/FMUSimulator/include/fmi1_cs.h b/org.simantics.fmil.core/native/FMUSimulator/include/fmi1_cs.h index 65072e1..40d942b 100644 --- a/org.simantics.fmil.core/native/FMUSimulator/include/fmi1_cs.h +++ b/org.simantics.fmil.core/native/FMUSimulator/include/fmi1_cs.h @@ -1,55 +1,66 @@ -#ifndef __FMI1_CS_H__ -#define __FMI1_CS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - char *name; - char *description; - char *declaredType; - long vr; - // 0 = real - // 1 = integer - // 2 = boolean - // 3 = string - // 4 = enumeration - int type; - // 0 = constant - // 1 = parameter - // 2 = discrete - // 3 = continuous - // 4 = unknown - int variability; - // 0 = input - // 1 = output - // 2 = internal - // 3 = none - // 4 = unknown - int causality; -} FMIL_Variable; - -typedef struct { - char *name; - char *description; - char *quantity; - char *unit; -} FMIL_DeclaredType; - -__declspec(dllexport) void* FMI1_CS_LOAD(const char *zipFilePath, const char *unzipFolder); -__declspec(dllexport) int FMI1_CS_UNLOAD(void* fmu); -__declspec(dllexport) FMIL_Variable *FMI1_CS_GET_VARIABLES(void* fmu, int *count); -__declspec(dllexport) FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void* fmu, int *count); -__declspec(dllexport) int FMI1_CS_INSTANTIATE(void* fmu); -__declspec(dllexport) int FMI1_CS_INITIALIZE(void* fmu); -__declspec(dllexport) int FMI1_CS_STEP(void* fmu, double masterTime, double stepSize); -__declspec(dllexport) double FMI1_CS_SET_REAL(void* fmu, int vr, double value); -__declspec(dllexport) int FMI1_CS_GET_REALS(void* fmu, int *vrs, double *values, int count); -__declspec(dllexport) double FMI1_CS_GET_REAL(void* fmu, int vr); - -#ifdef __cplusplus -} -#endif - +#ifndef __FMI1_CS_H__ +#define __FMI1_CS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char *name; + char *description; + char *declaredType; + long vr; + // 0 = real + // 1 = integer + // 2 = boolean + // 3 = string + // 4 = enumeration + int type; + // 0 = constant + // 1 = parameter + // 2 = discrete + // 3 = continuous + // 4 = unknown + int variability; + // 0 = input + // 1 = output + // 2 = internal + // 3 = none + // 4 = unknown + int causality; +} FMIL_Variable; + +typedef struct { + char *name; + char *description; + char *quantity; + char *unit; +} FMIL_DeclaredType; + +__declspec(dllexport) int FMI_CS_LOAD(const char *zipFilePath, const char *unzipFolder, void **fmuPointer, int *fmuVersion, const char **error); + +__declspec(dllexport) int FMI1_CS_UNLOAD(void* fmu, const char **error); +__declspec(dllexport) FMIL_Variable *FMI1_CS_GET_VARIABLES(void* fmu, int *count, const char **error); +__declspec(dllexport) FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void* fmu, int *count, const char **error); +__declspec(dllexport) int FMI1_CS_INSTANTIATE(void* fmu, const char *instanceName, const char **error); +__declspec(dllexport) int FMI1_CS_INITIALIZE(void* fmu, const char **error); +__declspec(dllexport) int FMI1_CS_STEP(void* fmu, double masterTime, double stepSize, const char **error); +__declspec(dllexport) int FMI1_CS_SET_REAL(void* fmu, int vr, double value, const char **error); +__declspec(dllexport) double FMI1_CS_GET_REAL(void* fmu, int vr, const char **error); +__declspec(dllexport) int FMI1_CS_GET_REALS(void* fmu, int *vrs, double *values, int count, const char **error); + +__declspec(dllexport) int FMI2_CS_UNLOAD(void* fmu, const char **error); +__declspec(dllexport) FMIL_Variable *FMI2_CS_GET_VARIABLES(void* fmu, int *count, const char **error); +__declspec(dllexport) FMIL_DeclaredType *FMI2_CS_GET_DECLARED_TYPES(void* fmu, int *count, const char **error); +__declspec(dllexport) int FMI2_CS_INSTANTIATE(void* fmu, const char *instanceName, const char **error); +__declspec(dllexport) int FMI2_CS_INITIALIZE(void* fmu, const char **error); +__declspec(dllexport) int FMI2_CS_STEP(void* fmu, double masterTime, double stepSize, const char **error); +__declspec(dllexport) int FMI2_CS_SET_REAL(void* fmu, int vr, double value, const char **error); +__declspec(dllexport) double FMI2_CS_GET_REAL(void* fmu, int vr, const char **error); +__declspec(dllexport) int FMI2_CS_GET_REALS(void* fmu, int *vrs, double *values, int count, const char **error); + +#ifdef __cplusplus +} +#endif + #endif \ No newline at end of file diff --git a/org.simantics.fmil.core/native/FMUSimulator/include/org_simantics_fmil_FMILJNI.h b/org.simantics.fmil.core/native/FMUSimulator/include/org_simantics_fmil_FMILJNI.h index 7f860d2..67e18e3 100644 --- a/org.simantics.fmil.core/native/FMUSimulator/include/org_simantics_fmil_FMILJNI.h +++ b/org.simantics.fmil.core/native/FMUSimulator/include/org_simantics_fmil_FMILJNI.h @@ -1,207 +1,199 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class org_simantics_fmu_FMUControlJNI */ - -#ifndef _Included_org_simantics_fmu_FMUControlJNI -#define _Included_org_simantics_fmu_FMUControlJNI -#ifdef __cplusplus -extern "C" { -#endif - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_loadFMUFile_1 - (JNIEnv *, jobject, jstring, jstring); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: setStepLength_ - * Signature: (Ljava/lang/String;D)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setStepLength_1 - (JNIEnv *, jobject, jint, jdouble); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: instantiateSimulation_ - * Signature: (Ljava/lang/String;)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_instantiateSimulation_1 - (JNIEnv *, jobject, jint); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: initializeSimulation_ - * Signature: (Ljava/lang/String;)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_initializeSimulation_1 - (JNIEnv *, jobject, jint); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: subscribe_ - * Signature: (Ljava/lang/String;[Ljava/lang/String;I)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_subscribe_1 - (JNIEnv *, jobject, jint, jintArray); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: setRealValue_ - * Signature: (Ljava/lang/String;Ljava/lang/String;D)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setRealValue_1 - (JNIEnv *, jobject, jint, jint, jdouble); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: setIntegerValue_ - * Signature: (Ljava/lang/String;Ljava/lang/String;I)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setIntegerValue_1 - (JNIEnv *, jobject, jstring, jstring, jint); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: setBooleanValue_ - * Signature: (Ljava/lang/String;Ljava/lang/String;Z)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setBooleanValue_1 - (JNIEnv *, jobject, jstring, jstring, jboolean); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: setTime_ - * Signature: (Ljava/lang/String;D)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setTime_1 - (JNIEnv *, jobject, jstring, jdouble); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: simulateStep_ - * Signature: (Ljava/lang/String;)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_simulateStep_1 - (JNIEnv *, jobject, jint); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: getSubscribedResults_ - * Signature: (Ljava/lang/String;[D)[D - */ -JNIEXPORT jdoubleArray JNICALL Java_org_simantics_fmil_FMIL_getSubscribedResults_1 - (JNIEnv *, jobject, jint, jdoubleArray); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: unloadFMU_ - * Signature: (Ljava/lang/String;)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_unloadFMU_1 - (JNIEnv *, jobject, jint); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: isInitialized_ - * Signature: (Ljava/lang/String;)Z - */ -JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_FMIL_isInitialized_1 - (JNIEnv *, jobject, jstring); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: getTime_ - * Signature: (Ljava/lang/String;)D - */ -JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_FMIL_getTime_1 - (JNIEnv *, jobject, jint); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: getAllVariables_ - * Signature: (Ljava/lang/String;)[Ljava/lang/String; - */ -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariables_1 - (JNIEnv *, jobject, jint); - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableDescriptions_1 - (JNIEnv *, jobject, jint); - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableDeclaredTypes_1 - (JNIEnv *, jobject, jint); - -JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableReferences_1 - (JNIEnv *, jobject, jint, jintArray); - -JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableTypes_1 - (JNIEnv *, jobject, jint, jintArray); - -JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableVariabilities_1 - (JNIEnv *, jobject, jint, jintArray); - -JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableCausalities_1 - (JNIEnv *, jobject, jint, jintArray); - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypes_1 - (JNIEnv *, jobject, jint); - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypeDescriptions_1 - (JNIEnv *, jobject, jint); - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypeQuantities_1 - (JNIEnv *, jobject, jint); - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypeUnits_1 - (JNIEnv *, jobject, jint); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: filterVariables_ - * Signature: (Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String; - */ -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_filterVariables_1 - (JNIEnv *, jobject, jstring, jstring); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: getLastErrorMessage_ - * Signature: (Ljava/lang/String;)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_org_simantics_fmil_FMIL_getLastErrorMessage_1 - (JNIEnv *, jobject, jstring); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: getRealValue_ - * Signature: (Ljava/lang/String;Ljava/lang/String;)D - */ -JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_FMIL_getRealValue_1 - (JNIEnv *, jobject, jint, jint); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: getStringValue_ - * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_org_simantics_fmil_FMIL_getStringValue_1 - (JNIEnv *, jobject, jstring, jstring); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: getIntegerValue_ - * Signature: (Ljava/lang/String;Ljava/lang/String;)I - */ -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_getIntegerValue_1 - (JNIEnv *, jobject, jstring, jstring); - -/* - * Class: org_simantics_fmu_FMUControlJNI - * Method: getBooleanValue_ - * Signature: (Ljava/lang/String;Ljava/lang/String;)Z - */ -JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_FMIL_getBooleanValue_1 - (JNIEnv *, jobject, jstring, jstring); - -#ifdef __cplusplus -} -#endif -#endif +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_simantics_fmu_FMUControlJNI */ + +#ifndef _Included_org_simantics_fmu_FMUControlJNI +#define _Included_org_simantics_fmu_FMUControlJNI +#ifdef __cplusplus +extern "C" { +#endif + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_loadFMUFile_1 + (JNIEnv *, jobject, jstring, jstring); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: setStepLength_ + * Signature: (Ljava/lang/String;D)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setStepLength_1 + (JNIEnv *, jobject, jint, jdouble); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: instantiateSimulation_ + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_instantiateSimulation_1 + (JNIEnv *, jobject, jint); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: initializeSimulation_ + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_initializeSimulation_1 + (JNIEnv *, jobject, jint); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: subscribe_ + * Signature: (Ljava/lang/String;[Ljava/lang/String;I)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_subscribe_1 + (JNIEnv *, jobject, jint, jintArray); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: setRealValue_ + * Signature: (Ljava/lang/String;Ljava/lang/String;D)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setRealValue_1 + (JNIEnv *, jobject, jint, jint, jdouble); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: setIntegerValue_ + * Signature: (Ljava/lang/String;Ljava/lang/String;I)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setIntegerValue_1 + (JNIEnv *, jobject, jstring, jstring, jint); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: setBooleanValue_ + * Signature: (Ljava/lang/String;Ljava/lang/String;Z)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setBooleanValue_1 + (JNIEnv *, jobject, jstring, jstring, jboolean); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: setTime_ + * Signature: (Ljava/lang/String;D)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setTime_1 + (JNIEnv *, jobject, jstring, jdouble); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: simulateStep_ + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_simulateStep_1 + (JNIEnv *, jobject, jint); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: getSubscribedResults_ + * Signature: (Ljava/lang/String;[D)[D + */ +JNIEXPORT jdoubleArray JNICALL Java_org_simantics_fmil_core_FMIL_getSubscribedResults_1 + (JNIEnv *, jobject, jint, jdoubleArray); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: unloadFMU_ + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_unloadFMU_1 + (JNIEnv *, jobject, jint); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: isInitialized_ + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_isInitialized_1 + (JNIEnv *, jobject, jstring); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: getTime_ + * Signature: (Ljava/lang/String;)D + */ +JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getTime_1 + (JNIEnv *, jobject, jint); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: getAllVariables_ + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariables_1 + (JNIEnv *, jobject, jint); + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDescriptions_1 + (JNIEnv *, jobject, jint); + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDeclaredTypes_1 + (JNIEnv *, jobject, jint); + +JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableReferences_1 + (JNIEnv *, jobject, jint, jintArray); + +JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableTypes_1 + (JNIEnv *, jobject, jint, jintArray); + +JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableVariabilities_1 + (JNIEnv *, jobject, jint, jintArray); + +JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableCausalities_1 + (JNIEnv *, jobject, jint, jintArray); + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypes_1 + (JNIEnv *, jobject, jint); + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeDescriptions_1 + (JNIEnv *, jobject, jint); + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeQuantities_1 + (JNIEnv *, jobject, jint); + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeUnits_1 + (JNIEnv *, jobject, jint); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: filterVariables_ + * Signature: (Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_filterVariables_1 + (JNIEnv *, jobject, jstring, jstring); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: getRealValue_ + * Signature: (Ljava/lang/String;Ljava/lang/String;)D + */ +JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getRealValue_1 + (JNIEnv *, jobject, jint, jint); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: getStringValue_ + * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_simantics_fmil_core_FMIL_getStringValue_1 + (JNIEnv *, jobject, jstring, jstring); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: getIntegerValue_ + * Signature: (Ljava/lang/String;Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_getIntegerValue_1 + (JNIEnv *, jobject, jstring, jstring); + +/* + * Class: org_simantics_fmu_FMUControlJNI + * Method: getBooleanValue_ + * Signature: (Ljava/lang/String;Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_getBooleanValue_1 + (JNIEnv *, jobject, jstring, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/org.simantics.fmil.core/native/FMUSimulator/src/fmu_control.cpp b/org.simantics.fmil.core/native/FMUSimulator/src/fmu_control.cpp index c5c9941..310e906 100644 --- a/org.simantics.fmil.core/native/FMUSimulator/src/fmu_control.cpp +++ b/org.simantics.fmil.core/native/FMUSimulator/src/fmu_control.cpp @@ -1,869 +1,984 @@ -/* ------------------------------------------------------------------------- - * fmu_control.c - * Simulation controls for fmus - * - * Free libraries and tools used to implement this simulator: - * - header files from the FMU specification - * - eXpat 2.0.1 XML parser, see http://expat.sourceforge.net - * - 7z.exe 4.57 zip and unzip tool, see http://www.7-zip.org <---------- Replace with zlib - * Author: Teemu Lempinen - * Copyright 2012 Semantum Oy - * ------------------------------------------------------------------------- - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -extern "C" { - #include "fmi_me.h" - #include "sim_support.h" -} - -#include "fmi1_cs.h" - -#define PRINT(fmt,args) { FILE *fp = fopen("R:\\Simantics\\Sysdyn\\log.txt", "ab"); fprintf(fp, fmt, args); fclose(fp); } - -#include -#define GetCurrentDir _getcwd - -using namespace std; - -struct FMI1 { - - void *fmu; - - vector variables; - vector descriptions; - vector declaredTypes; - vector valueReferences; - vector types; - vector variabilities; - vector causalities; - - vector declaredTypeNames; - vector typeDescriptions; - vector quantities; - vector units; - - vector subscription; - double currentTime; - double timeStep; - -}; - -struct FMUControlStruct { - double step; // simulation step length - fmiReal currentTime; // current simulation time - - fmiComponent c; // instance of the fmu - ScalarVariable** vars; // model variables - - fmiEventInfo eventInfo; // updated by calls to initialize and eventUpdate - const char* guid; // global unique id of the fmu - fmiCallbackFunctions callbacks; // called by the model during simulation - fmiStatus fmiFlag; // return code of the fmu functions - - map indexes; // indexes for variable names in vars-table - map::iterator it; - - int nx; // number of state variables - double *x; // continuous states - double *xdot; // the crresponding derivatives in same order - int nz; // number of state event indicators - double *z; // state event indicators - double *prez; // previous values of state event indicators - - bool initialized; // has the fmu been initialized - - vector subscription; // result subscriptions - vector allVariables; // all variables in an initialized model - vector fmiValueReferences; // all value references - - string lastErrorMessage; - - FMU fmu; -}; - -vector fmus; - -//map fmus; // indexes for variable names in vars-table - -int throwException(JNIEnv *env, string message) { - jclass newExcCls; - newExcCls = env->FindClass("java/lang/Exception"); - if (newExcCls == NULL) { - /* Unable to find the exception class, give up. */ - return 0; - } - env->ThrowNew(newExcCls, message.c_str()); - return 0; -} - -/* -bool exists(string id) { - map::iterator it = fmus.find(id); - if(it != fmus.end()) { - return true; - } else { - return false; - } -} -*/ - - - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_loadFMUFile_1 - (JNIEnv *env, jobject obj, jstring path, jstring tempDir) { - - HMODULE module = NULL; - FMI1 fmi1; - FMIL_Variable *vars; - FMIL_DeclaredType *types; - int variableCount = 0; - int typeCount = 0; - - const char *fmuPath = env->GetStringUTFChars(path, 0); - const char *fmuTempDir = env->GetStringUTFChars(tempDir, 0); - - fmi1.currentTime = 0; - fmi1.timeStep = 0.1; - fmi1.fmu = FMI1_CS_LOAD(fmuPath, fmuTempDir); - if(!fmi1.fmu) - return throwException(env, "No FMU loaded"); - - vars = FMI1_CS_GET_VARIABLES(fmi1.fmu, &variableCount); - for(int i=0;iReleaseStringUTFChars(path, fmuPath); - env->ReleaseStringUTFChars(tempDir, fmuTempDir); - - return fmus.size() - 1; - -} - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setStepLength_1 - (JNIEnv *env, jobject obj, jint id, jdouble stepLength) { - fmus[id].timeStep = stepLength; - return 1; -} - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_subscribe_1 - (JNIEnv *env, jobject obj, jint id, jintArray vrs) { - - jboolean isCopy; - jint* elements = env -> GetIntArrayElements(vrs, &isCopy); - jsize n = env -> GetArrayLength(vrs); - - int i; - for (i = 0; i < n; i++) { - fmus[id].subscription.push_back(elements[i]); - } - - if (isCopy == JNI_TRUE) { - env -> ReleaseIntArrayElements(vrs, elements, 0); - } - - return 1; - -} - -bool referenceExists(FMUControlStruct fmuStruct, string variable) { - map::iterator it = fmuStruct.indexes.find(variable); - if(it != fmuStruct.indexes.end()) { - return true; - } else { - return false; - } -} - -// Remember to check if reference exists -fmiValueReference getReference(FMUControlStruct fmuStruct, string variable) { - return fmuStruct.fmiValueReferences[fmuStruct.indexes[variable]]; -} - -// Get string representation of a scalar variable type -string getTypeString(ScalarVariable* sv) { - switch (sv->typeSpec->type){ - case elm_Integer: - return "Integer"; - case elm_Enumeration: - return "Enumeration"; - case elm_Real: - return "Real"; - case elm_Boolean: - return "Boolean"; - default: - return "No type"; - } -} - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setRealValue_1 - (JNIEnv *env, jobject obj, jint id, jint vr, jdouble value) { - - FMI1_CS_SET_REAL(fmus[id].fmu, vr, value); - return 1; - -} - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setIntegerValue_1 - (JNIEnv *env, jobject obj, jstring id, jstring parameter, jint value) { - /* - const char *fmuId = env->GetStringUTFChars(id, 0); - if(exists(fmuId)) { - FMUControlStruct& fmuStruct = fmus[fmuId]; - const char *name = env->GetStringUTFChars(parameter, 0); - string nameString = name; - string modelId = fmuId; - if(!referenceExists(fmuStruct, name)) { - string errorMessage = "setIntegerValue: Model (id " + modelId + ") does not contain variable: " + nameString; - env->ReleaseStringUTFChars(parameter, name); - env->ReleaseStringUTFChars(id, fmuId); - return throwException(env, errorMessage); - } else { - // Check variable type - ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]]; - switch (sv->typeSpec->type){ - case elm_Integer: - break; // ok - default: { - string errorMessage = "setIntegerValue: " + nameString + " is not of type Integer. (type: + " + getTypeString(sv) + ")"; - env->ReleaseStringUTFChars(parameter, name); - env->ReleaseStringUTFChars(id, fmuId); - return throwException(env, errorMessage); - } - } - - // Change value - fmiValueReference vr = getReference(fmuStruct, name); - const int intValue = (int) value; - fmuStruct.fmu.setInteger(fmuStruct.c, &vr, 1, &intValue); - env->ReleaseStringUTFChars(parameter, name); - env->ReleaseStringUTFChars(id, fmuId); - return 1; - } - } else { - string message = fmuId; - env->ReleaseStringUTFChars(id, fmuId); - return throwException(env, "setIntegerValue: Model id " + message + " not found"); - } - */ - return 1; -} - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setBooleanValue_1 - (JNIEnv *env, jobject obj, jstring id, jstring parameter, jboolean value) { - /* - const char *fmuId = env->GetStringUTFChars(id, 0); - if(exists(fmuId)) { - FMUControlStruct& fmuStruct = fmus[fmuId]; - const char *name = env->GetStringUTFChars(parameter, 0); - string nameString = name; - string modelId = fmuId; - if(!referenceExists(fmuStruct, name)) { - string errorMessage = "setBooleanValue: Model (id " + modelId + ") does not contain variable: " + nameString; - env->ReleaseStringUTFChars(parameter, name); - env->ReleaseStringUTFChars(id, fmuId); - return throwException(env, errorMessage); - } else { - // Check variable type - ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]]; - switch (sv->typeSpec->type){ - case elm_Boolean: - break; // ok - default: { - string errorMessage = "setBooleanValue: " + nameString + " is not of type Boolean. (type: + " + getTypeString(sv) + ")"; - env->ReleaseStringUTFChars(parameter, name); - env->ReleaseStringUTFChars(id, fmuId); - return throwException(env, errorMessage); - } - } - - // Change value - fmiValueReference vr = getReference(fmuStruct, name); - fmiBoolean result = 1; - if(value == 0) - result = 0; - fmuStruct.fmu.setBoolean(fmuStruct.c, &vr, 1, &result); - env->ReleaseStringUTFChars(parameter, name); - env->ReleaseStringUTFChars(id, fmuId); - return 1; - } - } else { - string message = fmuId; - env->ReleaseStringUTFChars(id, fmuId); - return throwException(env, "setBooleanValue: Model id " + message + " not found"); - }*/ - return 1; -} - -JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_FMIL_isInitialized_1 - (JNIEnv *env, jobject obj, jstring id) { - /* - const char *fmuId = env->GetStringUTFChars(id, 0); - if(exists(fmuId)) { - FMUControlStruct& fmuStruct = fmus[fmuId]; - env->ReleaseStringUTFChars(id, fmuId); - return fmuStruct.initialized; - } else { - env->ReleaseStringUTFChars(id, fmuId); - return false; - } - */ - return 1; -} - - -JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_FMIL_getTime_1 - (JNIEnv *env, jobject obj, jint id) { - return fmus[id].currentTime; -} - -double getRealValue(FMUControlStruct fmuStruct, int index) { - ScalarVariable *sv = fmuStruct.vars[index]; - fmiValueReference vr = fmuStruct.fmiValueReferences[index]; - double real; - fmiInteger integer; - fmiBoolean fmibool; - - switch (sv->typeSpec->type){ - case elm_Real: - fmuStruct.fmu.getReal(fmuStruct.c, &vr, 1, &real); - break; - case elm_Integer: - case elm_Enumeration: - fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &integer); - real = (double)integer; - break; - case elm_Boolean: - fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &fmibool); - if(fmibool == fmiTrue) - real = 1.0; - else - real = 0.0; - break; - } - return real; -} - -JNIEXPORT jdoubleArray JNICALL Java_org_simantics_fmil_FMIL_getSubscribedResults_1 - (JNIEnv *env, jobject obj, jint id, jdoubleArray result) { - - jboolean isCopy; - jdouble* resultElements = env -> GetDoubleArrayElements(result, &isCopy); - jsize n = env -> GetArrayLength(result); - int *vrs; - if(n > 0) { - vrs = &(fmus[id].subscription[0]); - FMI1_CS_GET_REALS(fmus[id].fmu, vrs, resultElements, n); - } - if (isCopy == JNI_TRUE) { - env -> ReleaseDoubleArrayElements(result, resultElements, 0); - } - - return result; - -} - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_instantiateSimulation_1 - (JNIEnv *env, jobject obj, jint id) { - - int asd = FMI1_CS_INSTANTIATE(fmus[id].fmu); - if(asd != 0) - return throwException(env, "No FMU loaded"); - - return 1; - -} - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_initializeSimulation_1 - (JNIEnv *env, jobject obj, jint id) { - - int asd = FMI1_CS_INITIALIZE(fmus[id].fmu); - if(asd != 0) - return throwException(env, "No FMU loaded"); - - return 1; - -} - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setTime_1 - (JNIEnv *env, jobject obj, jstring id, jdouble time) { - return 1; -} - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariables_1 - (JNIEnv *env, jobject obj, jint id) { - - jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].variables.size(), - env->FindClass("java/lang/String"), - env->NewStringUTF("")); - - for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].variables[i].c_str())); - } - - return ret; - -} - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableDescriptions_1 - (JNIEnv *env, jobject obj, jint id) { - - jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].descriptions.size(), - env->FindClass("java/lang/String"), - env->NewStringUTF("")); - - for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].descriptions[i].c_str())); - } - - return ret; - -} - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableDeclaredTypes_1 - (JNIEnv *env, jobject obj, jint id) { - - jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypes.size(), - env->FindClass("java/lang/String"), - env->NewStringUTF("")); - - for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypes[i].c_str())); - } - - return ret; - -} - -JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableReferences_1 - (JNIEnv *env, jobject obj, jint id, jintArray result) { - - jboolean isCopy; - jint* resultElements = env -> GetIntArrayElements(result, &isCopy); - jsize n = env -> GetArrayLength(result); - - int i; - for (i = 0; i < n; i++) { - resultElements[i] = fmus[id].valueReferences[i]; - } - - if (isCopy == JNI_TRUE) { - env -> ReleaseIntArrayElements(result, resultElements, 0); - } - - return result; - -} - -JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableTypes_1 - (JNIEnv *env, jobject obj, jint id, jintArray result) { - - jboolean isCopy; - jint* resultElements = env -> GetIntArrayElements(result, &isCopy); - jsize n = env -> GetArrayLength(result); - - int i; - for (i = 0; i < n; i++) { - resultElements[i] = fmus[id].types[i]; - } - - if (isCopy == JNI_TRUE) { - env -> ReleaseIntArrayElements(result, resultElements, 0); - } - - return result; - -} - -JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableVariabilities_1 - (JNIEnv *env, jobject obj, jint id, jintArray result) { - - jboolean isCopy; - jint* resultElements = env -> GetIntArrayElements(result, &isCopy); - jsize n = env -> GetArrayLength(result); - - int i; - for (i = 0; i < n; i++) { - resultElements[i] = fmus[id].variabilities[i]; - } - - if (isCopy == JNI_TRUE) { - env -> ReleaseIntArrayElements(result, resultElements, 0); - } - - return result; - -} - -JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableCausalities_1 - (JNIEnv *env, jobject obj, jint id, jintArray result) { - - jboolean isCopy; - jint* resultElements = env -> GetIntArrayElements(result, &isCopy); - jsize n = env -> GetArrayLength(result); - - int i; - for (i = 0; i < n; i++) { - resultElements[i] = fmus[id].causalities[i]; - } - - if (isCopy == JNI_TRUE) { - env -> ReleaseIntArrayElements(result, resultElements, 0); - } - - return result; - -} - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypes_1 - (JNIEnv *env, jobject obj, jint id) { - - jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypeNames.size(), - env->FindClass("java/lang/String"), - env->NewStringUTF("")); - - for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypeNames[i].c_str())); - } - - return ret; - -} - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypeDescriptions_1 - (JNIEnv *env, jobject obj, jint id) { - - jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].typeDescriptions.size(), - env->FindClass("java/lang/String"), - env->NewStringUTF("")); - - for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].typeDescriptions[i].c_str())); - } - - return ret; - -} - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypeQuantities_1 - (JNIEnv *env, jobject obj, jint id) { - - jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].quantities.size(), - env->FindClass("java/lang/String"), - env->NewStringUTF("")); - - for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].quantities[i].c_str())); - } - - return ret; - -} - -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypeUnits_1 - (JNIEnv *env, jobject obj, jint id) { - - jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].units.size(), - env->FindClass("java/lang/String"), - env->NewStringUTF("")); - - for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].units[i].c_str())); - } - - return ret; - -} - -/* -JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_filterVariables_1 - (JNIEnv *env, jobject obj, jstring id, jstring regexp) { - const char *rx = env->GetStringUTFChars(regexp, 0); - jobjectArray result = filterVariables(env, obj, id, rx); - env->ReleaseStringUTFChars(regexp, rx); - return result; -} -*/ - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_simulateStep_1 - (JNIEnv *env, jobject obj, jint id) { - - int asd = FMI1_CS_STEP(fmus[id].fmu, fmus[id].currentTime, fmus[id].timeStep); - if(asd != 0) - return throwException(env, "No FMU loaded"); - - fmus[id].currentTime += fmus[id].timeStep; - - return 1; - - /* - const char *fmuId = env->GetStringUTFChars(id, 0); - if(exists(fmuId)) { - FMUControlStruct& fmuStruct = fmus[fmuId]; - env->ReleaseStringUTFChars(id, fmuId); - - if(&fmuStruct.fmu == NULL || fmuStruct.fmu.modelDescription == NULL || &fmuStruct.vars == NULL) { - return throwException(env, "Simulate step failed - fmu not loaded"); - } - - if(fmuStruct.x == NULL) { - return throwException(env, "Simulate step failed - fmu not instantiated"); - } - - if(fmuStruct.initialized == false) { - fmiBoolean toleranceControlled = fmiFalse; - fmuStruct.fmiFlag = fmuStruct.fmu.initialize(fmuStruct.c, toleranceControlled, fmuStruct.currentTime, &(fmuStruct.eventInfo)); - if (fmuStruct.fmiFlag > fmiWarning) return throwException(env, "could not initialize model"); - fmuStruct.initialized = true; - } - - FMU& fmu = fmuStruct.fmu; - int debug = 0; // DEBUG ON = 1, OFF = 0 - - int i; - double dt, tPre, tEnd = fmuStruct.currentTime + fmuStruct.step; - - fmiBoolean timeEvent, stateEvent, stepEvent; - fmiStatus fmiFlag; // return code of the fmu functions - fmiValueReference vr; - - - */ - /* Simulate the duration of one step. The simulation may be done in - * multiple parts if events occur - */ /* - while (fmuStruct.currentTime < tEnd) { - // get current state and derivatives - fmiFlag = fmu.getContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx); - if (fmiFlag > fmiWarning) - return throwException(env, "could not retrieve states"); - - fmiFlag = fmu.getDerivatives(fmuStruct.c, fmuStruct.xdot, fmuStruct.nx); - if (fmiFlag > fmiWarning) - return throwException(env, "could not retrieve derivatives"); - - // advance time - tPre = fmuStruct.currentTime; - fmuStruct.currentTime = min(fmuStruct.currentTime+fmuStruct.step, tEnd); - timeEvent = fmuStruct.eventInfo.upcomingTimeEvent && fmuStruct.eventInfo.nextEventTime < fmuStruct.currentTime; - - if (timeEvent) fmuStruct.currentTime = fmuStruct.eventInfo.nextEventTime; - dt = fmuStruct.currentTime - tPre; - fmiFlag = fmu.setTime(fmuStruct.c, fmuStruct.currentTime); - if (fmiFlag > fmiWarning) throwException(env, "could not set time"); - - if(referenceExists(fmuStruct, "time")) { - vr = getReference(fmuStruct, "time"); - if(vr != NULL) { - fmu.setReal(fmuStruct.c, &vr, 1, &(fmuStruct.currentTime)); - } - } - - if(debug) - printf("Actual time: %lf\n", fmuStruct.currentTime); - - if (fmiFlag > fmiWarning) - return throwException(env, "could not set time"); - - // perform one step - for (i=0; i fmiWarning) - return throwException(env, "could not set states"); - - // Check for step event, e.g. dynamic state selection - fmiFlag = fmu.completedIntegratorStep(fmuStruct.c, &stepEvent); - if (fmiFlag > fmiWarning) return throwException(env, "could not complete intgrator step"); - */ -/* for (i=0; i fmiWarning) return throwException(env, "could not retrieve event indicators"); - stateEvent = FALSE; - for (i=0; i fmiWarning) return throwException(env, "could not perform event update"); - - } // if event - */ - -/* } - - fflush(stdout); - return 1; - - } else { - string message = fmuId; - env->ReleaseStringUTFChars(id, fmuId); - return throwException(env, "simulateStep: Model id " + message + " not found"); - }*/ - return 1; -} - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_unloadFMU_1 - (JNIEnv *env, jobject obj, jint id) { - - int asd = FMI1_CS_UNLOAD(fmus[id].fmu); - return asd; - -} - -JNIEXPORT jstring JNICALL Java_org_simantics_fmil_FMIL_getLastErrorMessage_1 - (JNIEnv *env, jobject obj, jstring id) { - return env->NewStringUTF("No errors"); -} - -JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_FMIL_getRealValue_1 - (JNIEnv *env, jobject obj, jint id, jint vr) { - return FMI1_CS_GET_REAL(fmus[id].fmu, vr); -} - -JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_getIntegerValue_1 - (JNIEnv *env, jobject obj, jstring id, jstring variable) { - /* - const char *fmuId = env->GetStringUTFChars(id, 0); - if(exists(fmuId)) { - FMUControlStruct fmuStruct = fmus[fmuId]; - env->ReleaseStringUTFChars(id, fmuId); - const char *name = env->GetStringUTFChars(variable, 0); - - if(referenceExists(fmuStruct, name)) { - fmiValueReference vr = getReference(fmuStruct, name); - int result; - fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &result); - env->ReleaseStringUTFChars(variable, name); - return result; - - } else { - string nameString = name; - string message = "Variable " + nameString + " not found"; - env->ReleaseStringUTFChars(variable, name); - return throwException(env, message); - } - - } else { - string message = fmuId; - env->ReleaseStringUTFChars(id, fmuId); - return throwException(env, "unloadFMU: Model id " + message + " not found"); - } - */ - return 1; - -} - -JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_FMIL_getBooleanValue_1 - (JNIEnv *env, jobject obj, jstring id, jstring variable) { - /* - const char *fmuId = env->GetStringUTFChars(id, 0); - if(exists(fmuId)) { - FMUControlStruct fmuStruct = fmus[fmuId]; - env->ReleaseStringUTFChars(id, fmuId); - const char *name = env->GetStringUTFChars(variable, 0); - - if(referenceExists(fmuStruct, name)) { - fmiValueReference vr = getReference(fmuStruct, name); - fmiBoolean result; - fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &result); - env->ReleaseStringUTFChars(variable, name); - return result; - - } else { - string nameString = name; - string message = "Variable " + nameString + " not found"; - env->ReleaseStringUTFChars(variable, name); - return throwException(env, message); - } - - } else { - string message = fmuId; - env->ReleaseStringUTFChars(id, fmuId); - return throwException(env, "unloadFMU: Model id " + message + " not found"); - }*/ - return 1; - -} - -JNIEXPORT jstring JNICALL Java_org_simantics_fmil_FMIL_getStringValue_1 - (JNIEnv *env, jobject obj, jstring id, jstring variable) { - /* - const char *fmuId = env->GetStringUTFChars(id, 0); - if(exists(fmuId)) { - FMUControlStruct fmuStruct = fmus[fmuId]; - env->ReleaseStringUTFChars(id, fmuId); - const char *name = env->GetStringUTFChars(variable, 0); - - if(referenceExists(fmuStruct, name)) { - fmiValueReference vr = getReference(fmuStruct, name); - fmiString result; - fmuStruct.fmu.getString(fmuStruct.c, &vr, 1, &result); - env->ReleaseStringUTFChars(variable, name); - return env->NewStringUTF(result); - - } else { - string nameString = name; - string message = "Variable " + nameString + " not found"; - env->ReleaseStringUTFChars(variable, name); - return 0; //throwException(env, message); - } - - } else { - string message = fmuId; - env->ReleaseStringUTFChars(id, fmuId); - return 0; //throwException(env, "unloadFMU: Model id " + message + " not found"); - } - */ - return 0; - +/* ------------------------------------------------------------------------- + * fmu_control.c + * Simulation controls for fmus + * + * Free libraries and tools used to implement this simulator: + * - header files from the FMU specification + * - eXpat 2.0.1 XML parser, see http://expat.sourceforge.net + * - 7z.exe 4.57 zip and unzip tool, see http://www.7-zip.org <---------- Replace with zlib + * Author: Teemu Lempinen + * Copyright 2012 Semantum Oy + * ------------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern "C" { + #include "fmi_me.h" + #include "sim_support.h" +} + +#include "fmi1_cs.h" + +#define PRINT(fmt,args) { FILE *fp = fopen("R:\\Simantics\\Sysdyn\\log.txt", "ab"); fprintf(fp, fmt, args); fclose(fp); } + +#include +#define GetCurrentDir _getcwd + +using namespace std; + +struct FMI1 { + + void *fmu; + + vector variables; + vector descriptions; + vector declaredTypes; + vector valueReferences; + vector types; + vector variabilities; + vector causalities; + + vector declaredTypeNames; + vector typeDescriptions; + vector quantities; + vector units; + + vector subscription; + double currentTime; + double timeStep; + + int version; + +}; + +struct FMUControlStruct { + double step; // simulation step length + fmiReal currentTime; // current simulation time + + fmiComponent c; // instance of the fmu + ScalarVariable** vars; // model variables + + fmiEventInfo eventInfo; // updated by calls to initialize and eventUpdate + const char* guid; // global unique id of the fmu + fmiCallbackFunctions callbacks; // called by the model during simulation + fmiStatus fmiFlag; // return code of the fmu functions + + map indexes; // indexes for variable names in vars-table + map::iterator it; + + int nx; // number of state variables + double *x; // continuous states + double *xdot; // the crresponding derivatives in same order + int nz; // number of state event indicators + double *z; // state event indicators + double *prez; // previous values of state event indicators + + bool initialized; // has the fmu been initialized + + vector subscription; // result subscriptions + vector allVariables; // all variables in an initialized model + vector fmiValueReferences; // all value references + + string lastErrorMessage; + + FMU fmu; +}; + +vector fmus; + +//map fmus; // indexes for variable names in vars-table + +int throwFMILException(JNIEnv *env, string message) { + jclass newExcCls; + newExcCls = env->FindClass("org/simantics/fmil/core/FMILException"); + if (newExcCls == NULL) { + newExcCls = env->FindClass("java/lang/Exception"); + } + if (newExcCls == NULL) { + /* Unable to find the exception class, give up. */ + return 1; + } + env->ThrowNew(newExcCls, message.c_str()); + return 1; +} + +int throwException(JNIEnv *env, string message) { + return throwFMILException(env, message); +} + +bool isEmpty(const char *c) { + if (c == NULL) { + return true; + } + if (c[0] == '\0') { + return true; + } + return false; +} + +/* +bool exists(string id) { + map::iterator it = fmus.find(id); + if(it != fmus.end()) { + return true; + } else { + return false; + } +} +*/ + + + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_loadFMUFile_1 + (JNIEnv *env, jobject obj, jstring path, jstring tempDir) { + + HMODULE module = NULL; + FMI1 fmi1; + FMIL_Variable *vars; + FMIL_DeclaredType *types; + + int returnValue; + + int variableCount = 0; + int typeCount = 0; + + int fmuVersion = 0; + const char *error = ""; + + const char *fmuPath = env->GetStringUTFChars(path, 0); + const char *fmuTempDir = env->GetStringUTFChars(tempDir, 0); + + fmi1.currentTime = 0; + fmi1.timeStep = 0.1; + returnValue = FMI_CS_LOAD(fmuPath, fmuTempDir, &fmi1.fmu, &fmuVersion, &error); + + if (returnValue != 0) { + string message = "Could not load FMU: "; + return throwFMILException(env, message += error); + } + if(!fmi1.fmu) { + string message = "No FMU loaded: "; + return throwFMILException(env, message += error); + } + + fmi1.version = fmuVersion; + if (fmi1.version == 1) { + vars = FMI1_CS_GET_VARIABLES(fmi1.fmu, &variableCount, &error); + } else if (fmi1.version == 2) { + vars = FMI2_CS_GET_VARIABLES(fmi1.fmu, &variableCount, &error); + } + if (!isEmpty(error)) { + string message = "Could not get variables "; + return throwFMILException(env, message += error); + } + + for(int i=0;iReleaseStringUTFChars(path, fmuPath); + env->ReleaseStringUTFChars(tempDir, fmuTempDir); + + return fmus.size() - 1; + +} + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setStepLength_1 + (JNIEnv *env, jobject obj, jint id, jdouble stepLength) { + fmus[id].timeStep = stepLength; + return 0; +} + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_subscribe_1 + (JNIEnv *env, jobject obj, jint id, jintArray vrs) { + + jboolean isCopy; + jint* elements = env -> GetIntArrayElements(vrs, &isCopy); + jsize n = env -> GetArrayLength(vrs); + + int i; + for (i = 0; i < n; i++) { + fmus[id].subscription.push_back(elements[i]); + } + + if (isCopy == JNI_TRUE) { + env -> ReleaseIntArrayElements(vrs, elements, 0); + } + + return 0; + +} + +bool referenceExists(FMUControlStruct fmuStruct, string variable) { + map::iterator it = fmuStruct.indexes.find(variable); + if(it != fmuStruct.indexes.end()) { + return true; + } else { + return false; + } +} + +// Remember to check if reference exists +fmiValueReference getReference(FMUControlStruct fmuStruct, string variable) { + return fmuStruct.fmiValueReferences[fmuStruct.indexes[variable]]; +} + +// Get string representation of a scalar variable type +string getTypeString(ScalarVariable* sv) { + switch (sv->typeSpec->type){ + case elm_Integer: + return "Integer"; + case elm_Enumeration: + return "Enumeration"; + case elm_Real: + return "Real"; + case elm_Boolean: + return "Boolean"; + default: + return "No type"; + } +} + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setRealValue_1 + (JNIEnv *env, jobject obj, jint id, jint vr, jdouble value) { + + const char *error = ""; + FMI1 fmi = fmus[id]; + if (fmi.version == 1) { + FMI1_CS_SET_REAL(fmi.fmu, vr, value, &error); + } else if (fmi.version == 2) { + FMI2_CS_SET_REAL(fmi.fmu, vr, value, &error); + } + if (!isEmpty(error)) { + string message = "Could not set real value "; + return throwFMILException(env, message += error); + } + return 0; +} + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setIntegerValue_1 + (JNIEnv *env, jobject obj, jstring id, jstring parameter, jint value) { + /* + const char *fmuId = env->GetStringUTFChars(id, 0); + if(exists(fmuId)) { + FMUControlStruct& fmuStruct = fmus[fmuId]; + const char *name = env->GetStringUTFChars(parameter, 0); + string nameString = name; + string modelId = fmuId; + if(!referenceExists(fmuStruct, name)) { + string errorMessage = "setIntegerValue: Model (id " + modelId + ") does not contain variable: " + nameString; + env->ReleaseStringUTFChars(parameter, name); + env->ReleaseStringUTFChars(id, fmuId); + return throwException(env, errorMessage); + } else { + // Check variable type + ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]]; + switch (sv->typeSpec->type){ + case elm_Integer: + break; // ok + default: { + string errorMessage = "setIntegerValue: " + nameString + " is not of type Integer. (type: + " + getTypeString(sv) + ")"; + env->ReleaseStringUTFChars(parameter, name); + env->ReleaseStringUTFChars(id, fmuId); + return throwException(env, errorMessage); + } + } + + // Change value + fmiValueReference vr = getReference(fmuStruct, name); + const int intValue = (int) value; + fmuStruct.fmu.setInteger(fmuStruct.c, &vr, 1, &intValue); + env->ReleaseStringUTFChars(parameter, name); + env->ReleaseStringUTFChars(id, fmuId); + return 1; + } + } else { + string message = fmuId; + env->ReleaseStringUTFChars(id, fmuId); + return throwException(env, "setIntegerValue: Model id " + message + " not found"); + } + */ + return 1; +} + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setBooleanValue_1 + (JNIEnv *env, jobject obj, jstring id, jstring parameter, jboolean value) { + /* + const char *fmuId = env->GetStringUTFChars(id, 0); + if(exists(fmuId)) { + FMUControlStruct& fmuStruct = fmus[fmuId]; + const char *name = env->GetStringUTFChars(parameter, 0); + string nameString = name; + string modelId = fmuId; + if(!referenceExists(fmuStruct, name)) { + string errorMessage = "setBooleanValue: Model (id " + modelId + ") does not contain variable: " + nameString; + env->ReleaseStringUTFChars(parameter, name); + env->ReleaseStringUTFChars(id, fmuId); + return throwException(env, errorMessage); + } else { + // Check variable type + ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]]; + switch (sv->typeSpec->type){ + case elm_Boolean: + break; // ok + default: { + string errorMessage = "setBooleanValue: " + nameString + " is not of type Boolean. (type: + " + getTypeString(sv) + ")"; + env->ReleaseStringUTFChars(parameter, name); + env->ReleaseStringUTFChars(id, fmuId); + return throwException(env, errorMessage); + } + } + + // Change value + fmiValueReference vr = getReference(fmuStruct, name); + fmiBoolean result = 1; + if(value == 0) + result = 0; + fmuStruct.fmu.setBoolean(fmuStruct.c, &vr, 1, &result); + env->ReleaseStringUTFChars(parameter, name); + env->ReleaseStringUTFChars(id, fmuId); + return 1; + } + } else { + string message = fmuId; + env->ReleaseStringUTFChars(id, fmuId); + return throwException(env, "setBooleanValue: Model id " + message + " not found"); + }*/ + return 1; +} + +JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_isInitialized_1 + (JNIEnv *env, jobject obj, jstring id) { + /* + const char *fmuId = env->GetStringUTFChars(id, 0); + if(exists(fmuId)) { + FMUControlStruct& fmuStruct = fmus[fmuId]; + env->ReleaseStringUTFChars(id, fmuId); + return fmuStruct.initialized; + } else { + env->ReleaseStringUTFChars(id, fmuId); + return false; + } + */ + return 1; +} + + +JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getTime_1 + (JNIEnv *env, jobject obj, jint id) { + return fmus[id].currentTime; +} + +double getRealValue(FMUControlStruct fmuStruct, int index) { + ScalarVariable *sv = fmuStruct.vars[index]; + fmiValueReference vr = fmuStruct.fmiValueReferences[index]; + double real; + fmiInteger integer; + fmiBoolean fmibool; + + switch (sv->typeSpec->type){ + case elm_Real: + fmuStruct.fmu.getReal(fmuStruct.c, &vr, 1, &real); + break; + case elm_Integer: + case elm_Enumeration: + fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &integer); + real = (double)integer; + break; + case elm_Boolean: + fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &fmibool); + if(fmibool == fmiTrue) + real = 1.0; + else + real = 0.0; + break; + } + return real; +} + +JNIEXPORT jdoubleArray JNICALL Java_org_simantics_fmil_core_FMIL_getSubscribedResults_1 + (JNIEnv *env, jobject obj, jint id, jdoubleArray result) { + + jboolean isCopy; + jdouble* resultElements = env -> GetDoubleArrayElements(result, &isCopy); + jsize n = env -> GetArrayLength(result); + int *vrs; + const char *error = ""; + int returnValue = 0; + + FMI1 fmi = fmus[id]; + if(n > 0) { + vrs = &(fmus[id].subscription[0]); + if (fmi.version == 1) { + FMI1_CS_GET_REALS(fmi.fmu, vrs, resultElements, n, &error); + } else if (fmi.version == 2) { + FMI2_CS_GET_REALS(fmi.fmu, vrs, resultElements, n, &error); + } + } + if (isCopy == JNI_TRUE) { + env -> ReleaseDoubleArrayElements(result, resultElements, 0); + } + + return result; + +} + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_instantiateSimulation_1 + (JNIEnv *env, jobject obj, jint id) { + + int returnValue; + const char *error = ""; + + FMI1 fmi = fmus[id]; + if (fmi.version == 1) { + returnValue = FMI1_CS_INSTANTIATE(fmi.fmu, "", &error); + } else if (fmi.version == 2) { + returnValue = FMI2_CS_INSTANTIATE(fmi.fmu, "", &error); + } + if(returnValue != 0) { + string message = "No FMU loaded: "; + return throwFMILException(env, message += error); + } + return 0; +} + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_initializeSimulation_1 + (JNIEnv *env, jobject obj, jint id) { + + const char *error = ""; + int returnValue; + FMI1 fmi = fmus[id]; + if (fmi.version == 1) { + returnValue = FMI1_CS_INITIALIZE(fmi.fmu, &error); + } else if (fmi.version == 2) { + returnValue = FMI2_CS_INITIALIZE(fmi.fmu, &error); + } + if(returnValue != 0) { + string message = "Could not initialize simulation: "; + return throwFMILException(env, message += error); + } + + return 0; + +} + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setTime_1 + (JNIEnv *env, jobject obj, jstring id, jdouble time) { + return 0; +} + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariables_1 + (JNIEnv *env, jobject obj, jint id) { + + jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].variables.size(), + env->FindClass("java/lang/String"), + env->NewStringUTF("")); + + for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].variables[i].c_str())); + } + + return ret; + +} + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDescriptions_1 + (JNIEnv *env, jobject obj, jint id) { + + jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].descriptions.size(), + env->FindClass("java/lang/String"), + env->NewStringUTF("")); + + for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].descriptions[i].c_str())); + } + + return ret; + +} + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDeclaredTypes_1 + (JNIEnv *env, jobject obj, jint id) { + + jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypes.size(), + env->FindClass("java/lang/String"), + env->NewStringUTF("")); + + for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypes[i].c_str())); + } + + return ret; + +} + +JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableReferences_1 + (JNIEnv *env, jobject obj, jint id, jintArray result) { + + jboolean isCopy; + jint* resultElements = env -> GetIntArrayElements(result, &isCopy); + jsize n = env -> GetArrayLength(result); + + int i; + for (i = 0; i < n; i++) { + resultElements[i] = fmus[id].valueReferences[i]; + } + + if (isCopy == JNI_TRUE) { + env -> ReleaseIntArrayElements(result, resultElements, 0); + } + + return result; + +} + +JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableTypes_1 + (JNIEnv *env, jobject obj, jint id, jintArray result) { + + jboolean isCopy; + jint* resultElements = env -> GetIntArrayElements(result, &isCopy); + jsize n = env -> GetArrayLength(result); + + int i; + for (i = 0; i < n; i++) { + resultElements[i] = fmus[id].types[i]; + } + + if (isCopy == JNI_TRUE) { + env -> ReleaseIntArrayElements(result, resultElements, 0); + } + + return result; + +} + +JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableVariabilities_1 + (JNIEnv *env, jobject obj, jint id, jintArray result) { + + jboolean isCopy; + jint* resultElements = env -> GetIntArrayElements(result, &isCopy); + jsize n = env -> GetArrayLength(result); + + int i; + for (i = 0; i < n; i++) { + resultElements[i] = fmus[id].variabilities[i]; + } + + if (isCopy == JNI_TRUE) { + env -> ReleaseIntArrayElements(result, resultElements, 0); + } + + return result; + +} + +JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableCausalities_1 + (JNIEnv *env, jobject obj, jint id, jintArray result) { + + jboolean isCopy; + jint* resultElements = env -> GetIntArrayElements(result, &isCopy); + jsize n = env -> GetArrayLength(result); + + int i; + for (i = 0; i < n; i++) { + resultElements[i] = fmus[id].causalities[i]; + } + + if (isCopy == JNI_TRUE) { + env -> ReleaseIntArrayElements(result, resultElements, 0); + } + + return result; + +} + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypes_1 + (JNIEnv *env, jobject obj, jint id) { + + jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypeNames.size(), + env->FindClass("java/lang/String"), + env->NewStringUTF("")); + + for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypeNames[i].c_str())); + } + + return ret; + +} + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeDescriptions_1 + (JNIEnv *env, jobject obj, jint id) { + + jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].typeDescriptions.size(), + env->FindClass("java/lang/String"), + env->NewStringUTF("")); + + for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].typeDescriptions[i].c_str())); + } + + return ret; + +} + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeQuantities_1 + (JNIEnv *env, jobject obj, jint id) { + + jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].quantities.size(), + env->FindClass("java/lang/String"), + env->NewStringUTF("")); + + for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].quantities[i].c_str())); + } + + return ret; + +} + +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeUnits_1 + (JNIEnv *env, jobject obj, jint id) { + + jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].units.size(), + env->FindClass("java/lang/String"), + env->NewStringUTF("")); + + for(int i=0;iSetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].units[i].c_str())); + } + + return ret; + +} + +/* +JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_filterVariables_1 + (JNIEnv *env, jobject obj, jstring id, jstring regexp) { + const char *rx = env->GetStringUTFChars(regexp, 0); + jobjectArray result = filterVariables(env, obj, id, rx); + env->ReleaseStringUTFChars(regexp, rx); + return result; +} +*/ + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_simulateStep_1 + (JNIEnv *env, jobject obj, jint id) { + + int returnValue; + const char *error = ""; + + FMI1 fmi = fmus[id]; + if (fmi.version == 1) { + returnValue = FMI1_CS_STEP(fmi.fmu, fmi.currentTime, fmi.timeStep, &error); + } else if (fmi.version == 2) { + returnValue = FMI2_CS_STEP(fmi.fmu, fmi.currentTime, fmi.timeStep, &error); + } + if(returnValue != 0) { + string message = "Could not simulate step: "; + return throwException(env, message += error); + } + + fmi.currentTime += fmi.timeStep; + + return 0; + + /* + const char *fmuId = env->GetStringUTFChars(id, 0); + if(exists(fmuId)) { + FMUControlStruct& fmuStruct = fmus[fmuId]; + env->ReleaseStringUTFChars(id, fmuId); + + if(&fmuStruct.fmu == NULL || fmuStruct.fmu.modelDescription == NULL || &fmuStruct.vars == NULL) { + return throwException(env, "Simulate step failed - fmu not loaded"); + } + + if(fmuStruct.x == NULL) { + return throwException(env, "Simulate step failed - fmu not instantiated"); + } + + if(fmuStruct.initialized == false) { + fmiBoolean toleranceControlled = fmiFalse; + fmuStruct.fmiFlag = fmuStruct.fmu.initialize(fmuStruct.c, toleranceControlled, fmuStruct.currentTime, &(fmuStruct.eventInfo)); + if (fmuStruct.fmiFlag > fmiWarning) return throwException(env, "could not initialize model"); + fmuStruct.initialized = true; + } + + FMU& fmu = fmuStruct.fmu; + int debug = 0; // DEBUG ON = 1, OFF = 0 + + int i; + double dt, tPre, tEnd = fmuStruct.currentTime + fmuStruct.step; + + fmiBoolean timeEvent, stateEvent, stepEvent; + fmiStatus fmiFlag; // return code of the fmu functions + fmiValueReference vr; + + + */ + /* Simulate the duration of one step. The simulation may be done in + * multiple parts if events occur + */ /* + while (fmuStruct.currentTime < tEnd) { + // get current state and derivatives + fmiFlag = fmu.getContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx); + if (fmiFlag > fmiWarning) + return throwException(env, "could not retrieve states"); + + fmiFlag = fmu.getDerivatives(fmuStruct.c, fmuStruct.xdot, fmuStruct.nx); + if (fmiFlag > fmiWarning) + return throwException(env, "could not retrieve derivatives"); + + // advance time + tPre = fmuStruct.currentTime; + fmuStruct.currentTime = min(fmuStruct.currentTime+fmuStruct.step, tEnd); + timeEvent = fmuStruct.eventInfo.upcomingTimeEvent && fmuStruct.eventInfo.nextEventTime < fmuStruct.currentTime; + + if (timeEvent) fmuStruct.currentTime = fmuStruct.eventInfo.nextEventTime; + dt = fmuStruct.currentTime - tPre; + fmiFlag = fmu.setTime(fmuStruct.c, fmuStruct.currentTime); + if (fmiFlag > fmiWarning) throwException(env, "could not set time"); + + if(referenceExists(fmuStruct, "time")) { + vr = getReference(fmuStruct, "time"); + if(vr != NULL) { + fmu.setReal(fmuStruct.c, &vr, 1, &(fmuStruct.currentTime)); + } + } + + if(debug) + printf("Actual time: %lf\n", fmuStruct.currentTime); + + if (fmiFlag > fmiWarning) + return throwException(env, "could not set time"); + + // perform one step + for (i=0; i fmiWarning) + return throwException(env, "could not set states"); + + // Check for step event, e.g. dynamic state selection + fmiFlag = fmu.completedIntegratorStep(fmuStruct.c, &stepEvent); + if (fmiFlag > fmiWarning) return throwException(env, "could not complete intgrator step"); + */ +/* for (i=0; i fmiWarning) return throwException(env, "could not retrieve event indicators"); + stateEvent = FALSE; + for (i=0; i fmiWarning) return throwException(env, "could not perform event update"); + + } // if event + */ + +/* } + + fflush(stdout); + return 1; + + } else { + string message = fmuId; + env->ReleaseStringUTFChars(id, fmuId); + return throwException(env, "simulateStep: Model id " + message + " not found"); + }*/ + return 1; +} + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_unloadFMU_1 + (JNIEnv *env, jobject obj, jint id) { + + int returnValue; + const char *error = ""; + + FMI1 fmi = fmus[id]; + if (fmi.version == 1) { + returnValue = FMI1_CS_UNLOAD(fmi.fmu, &error); + } else if (fmi.version == 2) { + returnValue = FMI2_CS_UNLOAD(fmi.fmu, &error); + } + if(returnValue != 0) { + string message = "Could not unload FMU: "; + return throwException(env, message += error); + } + return returnValue; +} + +JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getRealValue_1 + (JNIEnv *env, jobject obj, jint id, jint vr) { + + double value; + const char *error = ""; + + FMI1 fmi = fmus[id]; + if (fmi.version == 1) { + value = FMI1_CS_GET_REAL(fmi.fmu, vr, &error); + } else if (fmi.version == 2) { + value = FMI2_CS_GET_REAL(fmi.fmu, vr, &error); + } + if (!isEmpty(error)) { + string message = "Could not get real value: "; + return throwFMILException(env, message += error); + } + return value; +} + +JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_getIntegerValue_1 + (JNIEnv *env, jobject obj, jstring id, jstring variable) { + /* + const char *fmuId = env->GetStringUTFChars(id, 0); + if(exists(fmuId)) { + FMUControlStruct fmuStruct = fmus[fmuId]; + env->ReleaseStringUTFChars(id, fmuId); + const char *name = env->GetStringUTFChars(variable, 0); + + if(referenceExists(fmuStruct, name)) { + fmiValueReference vr = getReference(fmuStruct, name); + int result; + fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &result); + env->ReleaseStringUTFChars(variable, name); + return result; + + } else { + string nameString = name; + string message = "Variable " + nameString + " not found"; + env->ReleaseStringUTFChars(variable, name); + return throwException(env, message); + } + + } else { + string message = fmuId; + env->ReleaseStringUTFChars(id, fmuId); + return throwException(env, "unloadFMU: Model id " + message + " not found"); + } + */ + return 1; + +} + +JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_getBooleanValue_1 + (JNIEnv *env, jobject obj, jstring id, jstring variable) { + /* + const char *fmuId = env->GetStringUTFChars(id, 0); + if(exists(fmuId)) { + FMUControlStruct fmuStruct = fmus[fmuId]; + env->ReleaseStringUTFChars(id, fmuId); + const char *name = env->GetStringUTFChars(variable, 0); + + if(referenceExists(fmuStruct, name)) { + fmiValueReference vr = getReference(fmuStruct, name); + fmiBoolean result; + fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &result); + env->ReleaseStringUTFChars(variable, name); + return result; + + } else { + string nameString = name; + string message = "Variable " + nameString + " not found"; + env->ReleaseStringUTFChars(variable, name); + return throwException(env, message); + } + + } else { + string message = fmuId; + env->ReleaseStringUTFChars(id, fmuId); + return throwException(env, "unloadFMU: Model id " + message + " not found"); + }*/ + return 1; + +} + +JNIEXPORT jstring JNICALL Java_org_simantics_fmil_core_FMIL_getStringValue_1 + (JNIEnv *env, jobject obj, jstring id, jstring variable) { + /* + const char *fmuId = env->GetStringUTFChars(id, 0); + if(exists(fmuId)) { + FMUControlStruct fmuStruct = fmus[fmuId]; + env->ReleaseStringUTFChars(id, fmuId); + const char *name = env->GetStringUTFChars(variable, 0); + + if(referenceExists(fmuStruct, name)) { + fmiValueReference vr = getReference(fmuStruct, name); + fmiString result; + fmuStruct.fmu.getString(fmuStruct.c, &vr, 1, &result); + env->ReleaseStringUTFChars(variable, name); + return env->NewStringUTF(result); + + } else { + string nameString = name; + string message = "Variable " + nameString + " not found"; + env->ReleaseStringUTFChars(variable, name); + return 0; //throwException(env, message); + } + + } else { + string message = fmuId; + env->ReleaseStringUTFChars(id, fmuId); + return 0; //throwException(env, "unloadFMU: Model id " + message + " not found"); + } + */ + return 0; + } \ No newline at end of file diff --git a/org.simantics.fmil.core/src/org/simantics/fmil/core/FMIL.java b/org.simantics.fmil.core/src/org/simantics/fmil/core/FMIL.java index 5c00607..b2928b9 100644 --- a/org.simantics.fmil.core/src/org/simantics/fmil/core/FMIL.java +++ b/org.simantics.fmil.core/src/org/simantics/fmil/core/FMIL.java @@ -1,993 +1,1020 @@ -package org.simantics.fmil.core; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; - -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.Platform; -import org.osgi.framework.Bundle; -import org.simantics.Simantics; -import org.simantics.fmil.core.ExecEnvironment.ARCHType; -import org.simantics.fmil.core.ExecEnvironment.OSType; -import org.simantics.utils.FileUtils; - -import gnu.trove.list.array.TIntArrayList; -import gnu.trove.map.hash.TObjectIntHashMap; - - -public class FMIL { - - /** - * Static variables - */ - private static int ERROR = 0; - private static int OK = 1; - private static String UNSATISFIED_LINK = "Method not found. DLL might not be loaded properly."; - private static String TEMP_FMU_DIRECTORY_NAME = "fmil"; - public static String TEMP_FMU_COMMON_DIRECTORY; - public static String LOCK_FILE_NAME = "fmil.lock"; - - public static Object syncObject = new Object(); - - /** - * Static: load native libraries required for the FMU simulation to work. - */ - static { - - File[] libraries = new File[2]; - - Bundle bundle = null; - - ExecEnvironment env = ExecEnvironment.calculate(); - if (env.os == OSType.WINDOWS) { - if (env.arch == ARCHType.X86) { - bundle = Platform.getBundle("org.simantics.fmil.win32"); - } else if (env.arch == ARCHType.X86_64) { - bundle = Platform.getBundle("org.simantics.fmil.win64"); - } - } - - if (bundle != null) { - try{ - String root = FileLocator.getBundleFile(bundle).getAbsolutePath(); -// if (env.arch == ARCHType.X86_64) { -// File newFIle = new File(root, "libraries/libexpat.dll"); -// System.load(newFIle.getAbsolutePath()); -// } -// libraries[0] = new File(root, "libraries/zlibwapi.dll"); -// libraries[1] = new File(root, "libraries/miniunz.dll"); - libraries[0] = new File(root, "libraries/fmilib_shared.dll"); - libraries[1] = new File(root, "libraries/FMUSimulator.dll"); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - for(File library : libraries) { - if(library == null) { - System.err.println("FMU library not loaded. FMU simulation not working."); - continue; - } else if(!library.isFile()) { - System.err.println(library.getAbsolutePath() + " not found"); - } else { - try { - System.load(library.getAbsolutePath()); - } catch (Throwable t) { - System.err.println(t.getMessage()); - } - } - } - } - - /** - * Static: initialize fmu temp folder - */ - static { - File dir = Simantics.getTemporaryDirectory(TEMP_FMU_DIRECTORY_NAME); - TEMP_FMU_COMMON_DIRECTORY = dir.getAbsolutePath(); - } - - - private String fmuDir; - private int id; - - public String TEMP_FOLDER_1; - public String TEMP_FOLDER_2; - public String TEMP_FMU_DIRECTORY; - private String dirName; - - private String[] variableNames; - private String[] variableDescriptions; - private String[] variableDeclaredTypes; - private int[] variableReferences; - private int[] variableTypes; - private int[] variableCausalities; - private int[] variableVariabilities; - - private String[] declaredTypes; - private String[] declaredTypeDescriptions; - private String[] declaredTypeQuantities; - private String[] declaredTypeUnits; - - private TObjectIntHashMap variableMap = new TObjectIntHashMap(); - - private Set subscriptionSet = new HashSet(); - private TIntArrayList subscription = new TIntArrayList(); - private ArrayList subscribedNames = new ArrayList(); - - public List getSubscribedNames() { - return subscribedNames; - } - - public boolean subscribe(String name) throws FMILException { - // Safety check - int vr = variableMap.get(name); - if(vr == 0) return false; - if(!subscriptionSet.add(name)) return false; - subscribedNames.add(name); - System.err.println("subscribed : " + name + " => " + subscribedNames.size()); - subscription.add(vr); - subscribe(new int[] { vr }); - return true; - } - - public FMIL() { - // Create a directory for this control - File tempDir = new File(TEMP_FMU_COMMON_DIRECTORY, UUID.randomUUID().toString()); - tempDir.mkdir(); - TEMP_FMU_DIRECTORY = tempDir.getAbsolutePath(); - - // Create two directories inside the temp directory for this control - dirName = UUID.randomUUID().toString(); - File fmuDir = new File(TEMP_FMU_DIRECTORY, dirName); - fmuDir.mkdir(); - - TEMP_FOLDER_1 = fmuDir.toString(); - TEMP_FOLDER_2 = fmuDir.toString() + "_2"; - - // Lock fmu directory in temp directory - lockFMUDirectory(); - } - - public int getModelIDNew() { - return id; - } - - public String getModelID() { - return dirName; - } - - public String getFmuDir() { - return fmuDir; - } - - /** - * Load fmu from a given file path. Releases the (possible) previously - * loaded fmu. - * - * @param path absolute file path for fmu file - * @throws FMILException - */ - private int fmuN = 0; - private boolean fmuLoaded = false; - public void loadFMUFile(String path) throws FMILException { - - synchronized(syncObject) { - - if(fmuN % 2 == 0) { - fmuDir = TEMP_FOLDER_1; - fmuN++; - } else { - fmuDir = TEMP_FOLDER_2; - fmuN = 0; - } - - File tempDir = new File(fmuDir); - if(tempDir.isDirectory()) { - try { - FileUtils.deleteAll(tempDir); - } catch (IOException e) { - throw new FMILException("Could not create temp folder for fmu"); - } - tempDir.mkdir(); - } else { - tempDir.mkdir(); - } - - - try { - String tmpPath = tempDir.getAbsolutePath(); - if(!tmpPath.endsWith("\\")) - tmpPath = tmpPath + "\\"; - id = loadFMUFile_(path, tmpPath); - - getAllVariables(); - getAllVariableReferences(); - - for(int i=0;i - * Make sure that an FMU is loaded first. - * @throws FMILException - */ - public void instantiateSimulation() throws FMILException { - synchronized(syncObject) { - - try { - - int ret = instantiateSimulation_(getModelIDNew()); - if(ret == ERROR) - throw new FMILException(getLastErrorMessage()); - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native int instantiateSimulation_(int id); - - - /** - * Initializes a simulation. - *

- * Make sure that simulation is instantiated first! - * @throws FMILException - */ - public void initializeSimulation() throws FMILException { - synchronized(syncObject) { - - try { - - int ret = initializeSimulation_(getModelIDNew()); - if(ret == ERROR) - throw new FMILException(getLastErrorMessage()); - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native int initializeSimulation_(int id); - - /** - * Subscribe a set of variables from a loaded simulation. - *

- * Make sure that an FMU is loaded first. - * @param variables Array of variables - * @throws FMILException - */ - public void subscribe(int[] variables) throws FMILException { - synchronized(syncObject) { - - try { - - int ret = subscribe_(getModelIDNew(), variables); - if(ret == ERROR) - throw new FMILException(getLastErrorMessage()); - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native int subscribe_(int id, int[] variables); - - /** - * Set a new (Real, double) value for a variable. If the variable is a - * parameter, the change is effective immediately. - * - * @param name Variable - * @param value New (Real, double) value - * @throws FMILException - */ - public void setRealValue(String name, double value) throws FMILException { - - synchronized(syncObject) { - - try { - - int ret = setRealValue_(getModelIDNew(), variableMap.get(name), value); - if(ret == ERROR) - throw new FMILException(getLastErrorMessage()); - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - - } - - } - - public void setRealValue(int variableReference, double value) throws FMILException { - - synchronized(syncObject) { - - try { - - int ret = setRealValue_(getModelIDNew(), variableReference, value); - if(ret == ERROR) - throw new FMILException(getLastErrorMessage()); - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - - } - - } - - private native int setRealValue_(int id, int variableReference, double value); - -// /** -// * Set a new (integer) value for a variable. If the variable is a -// * parameter, the change is effective immediately. -// * -// * @param name Variable -// * @param value New (integer) value -// * @throws FMILException -// */ -// public void setIntegerValue(String name, int value) throws FMILException { -// synchronized(syncObject) { -// -// try { -// -// int ret = setIntegerValue_(getModelID(), name, value); -// if(ret == ERROR) -// throw new FMILException(getLastErrorMessage()); -// -// } catch (UnsatisfiedLinkError err) { -// throw new FMILException(UNSATISFIED_LINK); -// } catch (Exception e) { -// throw new FMILException(e.getMessage()); -// } -// } -// } -// private native int setIntegerValue_(String id, String name, int value); -// -// /** -// * Set a new (boolean) value for a variable. If the variable is a -// * parameter, the change is effective immediately. -// * -// * @param name Variable -// * @param value New (boolean) value -// * @throws FMILException -// */ -// public void setBooleanValue(String name, boolean value) throws FMILException { -// synchronized(syncObject) { -// -// try { -// -// int ret = setBooleanValue_(getModelID(), name, value); -// if(ret == ERROR) -// throw new FMILException(getLastErrorMessage()); -// -// } catch (UnsatisfiedLinkError err) { -// throw new FMILException(UNSATISFIED_LINK); -// } catch (Exception e) { -// throw new FMILException(e.getMessage()); -// } -// } -// } -// private native int setBooleanValue_(String id, String name, boolean value); -// -// public void setTime(double time) throws FMILException { -// synchronized(syncObject) { -// -// try { -// -// int ret = setTime_(getModelID(), time); -// if(ret == ERROR) -// throw new FMILException(getLastErrorMessage()); -// -// } catch (UnsatisfiedLinkError err) { -// throw new FMILException(UNSATISFIED_LINK); -// } catch (Exception e) { -// throw new FMILException(e.getMessage()); -// } -// } -// } -// private native int setTime_(String id, double time); - - /** - * Simulate one step forward. The step length can be set with - * setStepLength() - * - * @throws FMILException - */ - public void simulateStep() throws FMILException { - synchronized(syncObject) { - - try { - - int ret = simulateStep_(getModelIDNew()); - if(ret == ERROR) - throw new FMILException(getLastErrorMessage()); - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - private native int simulateStep_(int id); - - /** - * Get an array containing the current values for subscribed variables. The - * values are in the same order as in the subscription. - * - * @param results An array the size of subscribed results - * @return - */ - public double[] getSubscribedResults() throws FMILException { - synchronized(syncObject) { - - try { - - double[] results = new double[subscription.size()]; - return getSubscribedResults_(getModelIDNew(), results); - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native double[] getSubscribedResults_(int id, double[] results); - - - /** - * Unload FMU and the dll:s that it requires. - *

- * To be called after all FMU simulations are ended. - * If the fmu is loaded again / changed, call to loadFMUFile is sufficient. loadFMUFile - * releases the previous fmu.dll - * - * @throws FMILException - */ - public void unloadFMU() throws FMILException { - synchronized(syncObject) { - - try { - - unlockFMUDirectory(); - if(fmuLoaded) { - int ret = unloadFMU_(getModelIDNew()); - if(ret == ERROR) - throw new FMILException(getLastErrorMessage()); - } - removeFMUDirectoryContents(); - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - private native int unloadFMU_(int id); - -// /** -// * Checks if fmu has been initialized -// * @return current simulation time -// */ -// public boolean isInitialized() throws FMILException { -// synchronized(syncObject) { -// try { -// return isInitialized_(getModelID()); -// } catch (UnsatisfiedLinkError err) { -// throw new FMILException(UNSATISFIED_LINK); -// } catch (Exception e) { -// throw new FMILException(e.getMessage()); -// } -// } -// } -// -// private native boolean isInitialized_(String id); -// - /** - * Get the current simulation time - * @return current simulation time - */ - public double getTime() throws FMILException { - synchronized(syncObject) { - - try { - - return getTime_(getModelIDNew()); - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native double getTime_(int id); - - /** - * Get all variables in a loaded model - * @return all variables in a loaded model - */ - public String[] getAllVariables() throws FMILException { - synchronized(syncObject) { - - try { - - if(variableNames == null) { - variableNames = getAllVariables_(getModelIDNew()); - } - return variableNames; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native String[] getAllVariables_(int id); - - public String[] getAllVariableDescriptions() throws FMILException { - synchronized(syncObject) { - - try { - - if(variableDescriptions == null) { - variableDescriptions = getAllVariableDescriptions_(getModelIDNew()); - } - return variableDescriptions; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native String[] getAllVariableDescriptions_(int id); - - public String[] getAllVariableDeclaredTypes() throws FMILException { - synchronized(syncObject) { - - try { - - if(variableDeclaredTypes == null) { - variableDeclaredTypes = getAllVariableDeclaredTypes_(getModelIDNew()); - } - return variableDeclaredTypes; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native String[] getAllVariableDeclaredTypes_(int id); - - public int[] getAllVariableReferences() throws FMILException { - synchronized(syncObject) { - - try { - - if(variableReferences == null) { - variableReferences = getAllVariableReferences_(getModelIDNew(), new int[variableNames.length]); - } - return variableReferences; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native int[] getAllVariableReferences_(int id, int[] array); - - public int[] getAllVariableTypes() throws FMILException { - synchronized(syncObject) { - - try { - - if(variableTypes == null) { - variableTypes = getAllVariableTypes_(getModelIDNew(), new int[variableNames.length]); - } - return variableTypes; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native int[] getAllVariableTypes_(int id, int[] array); - - public int[] getAllVariableCausalities() throws FMILException { - synchronized(syncObject) { - - try { - - if(variableCausalities == null) { - variableCausalities = getAllVariableCausalities_(getModelIDNew(), new int[variableNames.length]); - } - return variableCausalities; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native int[] getAllVariableCausalities_(int id, int[] array); - - public int[] getAllVariableVariabilities() throws FMILException { - synchronized(syncObject) { - - try { - - if(variableVariabilities == null) { - variableVariabilities = getAllVariableVariabilities_(getModelIDNew(), new int[variableNames.length]); - } - return variableVariabilities; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native int[] getAllVariableVariabilities_(int id, int[] array); - - /** - * Get all variables in a loaded model - * @return all variables in a loaded model - */ - public String[] getAllDeclaredTypes() throws FMILException { - synchronized(syncObject) { - - try { - - if(declaredTypes == null) { - declaredTypes = getAllDeclaredTypes_(getModelIDNew()); - } - return declaredTypes; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native String[] getAllDeclaredTypes_(int id); - - public String[] getAllDeclaredTypeDescriptions() throws FMILException { - synchronized(syncObject) { - - try { - - if(declaredTypeDescriptions == null) { - declaredTypeDescriptions = getAllDeclaredTypeDescriptions_(getModelIDNew()); - } - return declaredTypeDescriptions; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native String[] getAllDeclaredTypeDescriptions_(int id); - - public String[] getAllDeclaredTypeQuantities() throws FMILException { - synchronized(syncObject) { - - try { - - if(declaredTypeQuantities == null) { - declaredTypeQuantities = getAllDeclaredTypeQuantities_(getModelIDNew()); - } - return declaredTypeQuantities; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native String[] getAllDeclaredTypeQuantities_(int id); - - public String[] getAllDeclaredTypeUnits() throws FMILException { - synchronized(syncObject) { - - try { - - if(declaredTypeUnits == null) { - declaredTypeUnits = getAllDeclaredTypeUnits_(getModelIDNew()); - } - return declaredTypeUnits; - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native String[] getAllDeclaredTypeUnits_(int id); - - -// -// /** -// * Get all variables from model that match the filter (and time variable) -// * -// * @param regexp Regular expression filter -// * @return An array of variable names that match regexp filter (and time-variable) -// * @throws FMILException -// */ -// public String[] filterVariables(String regexp) throws FMILException { -// synchronized(syncObject) { -// try { -// -// return filterVariables_(getModelID(), regexp + "|time"); -// -// } catch (UnsatisfiedLinkError err) { -// throw new FMILException(UNSATISFIED_LINK); -// } catch (Exception e) { -// throw new FMILException(e.getMessage()); -// } -// } -// } -// -// private native String[] filterVariables_(String id, String regexp); -// - /** - * Get the last error message - * @return Last error message - */ - public String getLastErrorMessage() throws FMILException { - synchronized(syncObject) { - - try { - - return "err"; - //return getLastErrorMessage_(getModelID()); - - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } -// -// private native String getLastErrorMessage_(String id); - - /** - * Get a real (double) value for variable - * @param name Name of the variable - * @return value - * @throws FMILException - */ - public double getRealValue(String name) throws FMILException { - synchronized(syncObject) { - - try { - // TODO: printtaa id ja name, jotta saadaan virheessä kiinni - double result = getRealValue_(getModelIDNew(), variableMap.get(name)); - System.err.println("getRealValue " + name + " = " + result); - return result; - } catch (UnsatisfiedLinkError err) { - throw new FMILException(UNSATISFIED_LINK); - } catch (Exception e) { - throw new FMILException(e.getMessage()); - } - } - } - - private native double getRealValue_(int id, int variableReference); - -// /** -// * Get a string value for variable -// * @param name Name of the variable -// * @return value -// * @throws FMILException -// */ -// public String getStringValue(String name) throws FMILException { -// synchronized(syncObject) { -// -// try { -// return getStringValue_(getModelID(), name); -// } catch (UnsatisfiedLinkError err) { -// throw new FMILException(UNSATISFIED_LINK); -// } catch (Exception e) { -// throw new FMILException(e.getMessage()); -// } -// } -// } -// -// private native String getStringValue_(String id, String name); -// -// /** -// * Get an integer value for variable -// * @param name Name of the variable -// * @return value -// * @throws FMILException -// */ -// public int getIntegerValue(String name) throws FMILException { -// synchronized(syncObject) { -// -// try { -// return getIntegerValue_(getModelID(), name); -// } catch (UnsatisfiedLinkError err) { -// throw new FMILException(UNSATISFIED_LINK); -// } catch (Exception e) { -// throw new FMILException(e.getMessage()); -// } -// } -// } -// -// private native int getIntegerValue_(String id, String name); -// -// /** -// * Get a real (double) value for variable -// * @param name Name of the variable -// * @return value -// * @throws FMILException -// */ -// public boolean getBooleanValue(String name) throws FMILException { -// synchronized(syncObject) { -// -// try { -// return getBooleanValue_(getModelID(), name); -// } catch (UnsatisfiedLinkError err) { -// throw new FMILException(UNSATISFIED_LINK); -// } catch (Exception e) { -// throw new FMILException(e.getMessage()); -// } -// } -// } -// -// private native boolean getBooleanValue_(String id, String name); - - private FileChannel channel; - private FileLock lock; - - @SuppressWarnings("resource") - private boolean lockFMUDirectory() { - - try { - // Get a file channel for the lock file - File lockFile = new File(TEMP_FMU_DIRECTORY, LOCK_FILE_NAME); - if(!lockFile.isFile()) - lockFile.createNewFile(); - - channel = new RandomAccessFile(lockFile, "rw").getChannel(); - - // Use the file channel to create a lock on the file. - // This method blocks until it can retrieve the lock. - lock = channel.lock(); - - // // Try acquiring the lock without blocking. This method returns - // // null or throws an exception if the file is already locked. - // try { - // lock = channel.tryLock(); - // } catch (OverlappingFileLockException e) { - // // File is already locked in this thread or virtual machine - // } - } catch (IOException e) { - return false; - } - - return true; - } - - private boolean unlockFMUDirectory() { - try { - // Release the lock - if(lock != null) - lock.release(); - - // Close the file - if(channel != null) - channel.close(); - } catch (IOException e) { - return false; - } - return true; - } - - private boolean removeFMUDirectoryContents() { - // Remove contents - try { - File tempDir = new File(TEMP_FMU_DIRECTORY); - FileUtils.deleteAll(tempDir); - tempDir.delete(); - } catch (IOException e) { - return false; - } - return true; - } -} +package org.simantics.fmil.core; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Platform; +import org.osgi.framework.Bundle; +import org.simantics.Simantics; +import org.simantics.fmil.core.ExecEnvironment.ARCHType; +import org.simantics.fmil.core.ExecEnvironment.OSType; +import org.simantics.utils.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TObjectIntHashMap; + + +public class FMIL { + + private static final Logger LOGGER = LoggerFactory.getLogger(FMIL.class); + + /** + * Static variables + */ + private static int OK = 0; + private static int ERROR = 1; + private static String UNSATISFIED_LINK = "Method not found. DLL might not be loaded properly."; + private static String TEMP_FMU_DIRECTORY_NAME = "fmil"; + public static String TEMP_FMU_COMMON_DIRECTORY; + public static String LOCK_FILE_NAME = "fmil.lock"; + + public static Object syncObject = new Object(); + + /** + * Static: load native libraries required for the FMU simulation to work. + */ + static { + + File[] libraries = new File[2]; + + Bundle bundle = null; + + ExecEnvironment env = ExecEnvironment.calculate(); + if (env.os == OSType.WINDOWS) { + if (env.arch == ARCHType.X86) { + bundle = Platform.getBundle("org.simantics.fmil.win32"); + } else if (env.arch == ARCHType.X86_64) { + bundle = Platform.getBundle("org.simantics.fmil.win64"); + } + } + + if (bundle != null) { + try{ + String root = FileLocator.getBundleFile(bundle).getAbsolutePath(); +// if (env.arch == ARCHType.X86_64) { +// File newFIle = new File(root, "libraries/libexpat.dll"); +// System.load(newFIle.getAbsolutePath()); +// } +// libraries[0] = new File(root, "libraries/zlibwapi.dll"); +// libraries[1] = new File(root, "libraries/miniunz.dll"); + libraries[0] = new File(root, "libraries/fmilib_shared.dll"); + libraries[1] = new File(root, "libraries/FMUSimulator.dll"); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + for(File library : libraries) { + if(library == null) { + System.err.println("FMU library not loaded. FMU simulation not working."); + continue; + } else if(!library.isFile()) { + System.err.println(library.getAbsolutePath() + " not found"); + } else { + try { + System.load(library.getAbsolutePath()); + } catch (Throwable t) { + System.err.println(t.getMessage()); + } + } + } + } + + /** + * Static: initialize fmu temp folder + */ + static { + File dir = Simantics.getTemporaryDirectory(TEMP_FMU_DIRECTORY_NAME); + TEMP_FMU_COMMON_DIRECTORY = dir.getAbsolutePath(); + } + + + private String fmuDir; + private int id; + + public String TEMP_FOLDER_1; + public String TEMP_FOLDER_2; + public String TEMP_FMU_DIRECTORY; + private String dirName; + + private String[] variableNames; + private String[] variableDescriptions; + private String[] variableDeclaredTypes; + private int[] variableReferences; + private int[] variableTypes; + private int[] variableCausalities; + private int[] variableVariabilities; + + private String[] declaredTypes; + private String[] declaredTypeDescriptions; + private String[] declaredTypeQuantities; + private String[] declaredTypeUnits; + + private TObjectIntHashMap variableMap = new TObjectIntHashMap(); + + private Set subscriptionSet = new HashSet(); + private TIntArrayList subscription = new TIntArrayList(); + private ArrayList subscribedNames = new ArrayList(); + + public List getSubscribedNames() { + return subscribedNames; + } + + public boolean subscribe(String name) throws FMILException { + // Safety check + int vr = variableMap.get(name); + if(vr == 0) return false; + if(!subscriptionSet.add(name)) return false; + subscribedNames.add(name); + System.err.println("subscribed : " + name + " => " + subscribedNames.size()); + subscription.add(vr); + subscribe(new int[] { vr }); + return true; + } + + public FMIL() { + // Create a directory for this control + File tempDir = new File(TEMP_FMU_COMMON_DIRECTORY, UUID.randomUUID().toString()); + tempDir.mkdir(); + TEMP_FMU_DIRECTORY = tempDir.getAbsolutePath(); + + // Create two directories inside the temp directory for this control + dirName = UUID.randomUUID().toString(); + File fmuDir = new File(TEMP_FMU_DIRECTORY, dirName); + fmuDir.mkdir(); + + TEMP_FOLDER_1 = fmuDir.toString(); + TEMP_FOLDER_2 = fmuDir.toString() + "_2"; + + // Lock fmu directory in temp directory + lockFMUDirectory(); + } + + public int getModelIDNew() { + return id; + } + + public String getModelID() { + return dirName; + } + + public String getFmuDir() { + return fmuDir; + } + + /** + * Load fmu from a given file path. Releases the (possible) previously + * loaded fmu. + * + * @param path absolute file path for fmu file + * @throws FMILException + */ + private int fmuN = 0; + private boolean fmuLoaded = false; + public void loadFMUFile(String path) throws FMILException { + + synchronized(syncObject) { + + if(fmuN % 2 == 0) { + fmuDir = TEMP_FOLDER_1; + fmuN++; + } else { + fmuDir = TEMP_FOLDER_2; + fmuN = 0; + } + + File tempDir = new File(fmuDir); + if(tempDir.isDirectory()) { + try { + FileUtils.deleteAll(tempDir); + } catch (IOException e) { + throw new FMILException("Could not create temp folder for fmu"); + } + tempDir.mkdir(); + } else { + tempDir.mkdir(); + } + + + try { + String tmpPath = tempDir.getAbsolutePath(); + if(!tmpPath.endsWith("\\")) + tmpPath = tmpPath + "\\"; + id = loadFMUFile_(path, tmpPath); + + getAllVariables(); + getAllVariableReferences(); + + for(int i=0;i + * Make sure that an FMU is loaded first. + * @throws FMILException + */ + public void instantiateSimulation() throws FMILException { + synchronized(syncObject) { + + try { + + int ret = instantiateSimulation_(getModelIDNew()); + if(ret != OK) + LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!"); + + } catch (FMILException e) { + throw e; + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native int instantiateSimulation_(int id) throws FMILException; + + + /** + * Initializes a simulation. + *

+ * Make sure that simulation is instantiated first! + * @throws FMILException + */ + public void initializeSimulation() throws FMILException { + synchronized(syncObject) { + + try { + + int ret = initializeSimulation_(getModelIDNew()); + if(ret != OK) + LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!"); + + } catch (FMILException e) { + throw e; + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native int initializeSimulation_(int id) throws FMILException; + + /** + * Subscribe a set of variables from a loaded simulation. + *

+ * Make sure that an FMU is loaded first. + * @param variables Array of variables + * @throws FMILException + */ + public void subscribe(int[] variables) throws FMILException { + synchronized(syncObject) { + + try { + + int ret = subscribe_(getModelIDNew(), variables); + if(ret != OK) + LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!"); + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native int subscribe_(int id, int[] variables); + + /** + * Set a new (Real, double) value for a variable. If the variable is a + * parameter, the change is effective immediately. + * + * @param name Variable + * @param value New (Real, double) value + * @throws FMILException + */ + public void setRealValue(String name, double value) throws FMILException { + + synchronized(syncObject) { + + try { + + int ret = setRealValue_(getModelIDNew(), variableMap.get(name), value); + if(ret != OK) + LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!"); + + } catch (FMILException e) { + throw e; + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + + } + + } + + public void setRealValue(int variableReference, double value) throws FMILException { + + synchronized(syncObject) { + + try { + + int ret = setRealValue_(getModelIDNew(), variableReference, value); + if(ret != OK) + LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!"); + + } catch (FMILException e) { + throw e; + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + + } + + } + + private native int setRealValue_(int id, int variableReference, double value) throws FMILException; + +// /** +// * Set a new (integer) value for a variable. If the variable is a +// * parameter, the change is effective immediately. +// * +// * @param name Variable +// * @param value New (integer) value +// * @throws FMILException +// */ +// public void setIntegerValue(String name, int value) throws FMILException { +// synchronized(syncObject) { +// +// try { +// +// int ret = setIntegerValue_(getModelID(), name, value); +// if(ret == ERROR) +// throw new FMILException(getLastErrorMessage()); +// +// } catch (UnsatisfiedLinkError err) { +// throw new FMILException(UNSATISFIED_LINK); +// } catch (Exception e) { +// throw new FMILException(e.getMessage()); +// } +// } +// } +// private native int setIntegerValue_(String id, String name, int value); +// +// /** +// * Set a new (boolean) value for a variable. If the variable is a +// * parameter, the change is effective immediately. +// * +// * @param name Variable +// * @param value New (boolean) value +// * @throws FMILException +// */ +// public void setBooleanValue(String name, boolean value) throws FMILException { +// synchronized(syncObject) { +// +// try { +// +// int ret = setBooleanValue_(getModelID(), name, value); +// if(ret == ERROR) +// throw new FMILException(getLastErrorMessage()); +// +// } catch (UnsatisfiedLinkError err) { +// throw new FMILException(UNSATISFIED_LINK); +// } catch (Exception e) { +// throw new FMILException(e.getMessage()); +// } +// } +// } +// private native int setBooleanValue_(String id, String name, boolean value); +// +// public void setTime(double time) throws FMILException { +// synchronized(syncObject) { +// +// try { +// +// int ret = setTime_(getModelID(), time); +// if(ret == ERROR) +// throw new FMILException(getLastErrorMessage()); +// +// } catch (UnsatisfiedLinkError err) { +// throw new FMILException(UNSATISFIED_LINK); +// } catch (Exception e) { +// throw new FMILException(e.getMessage()); +// } +// } +// } +// private native int setTime_(String id, double time); + + /** + * Simulate one step forward. The step length can be set with + * setStepLength() + * + * @throws FMILException + */ + public void simulateStep() throws FMILException { + synchronized(syncObject) { + + try { + + int ret = simulateStep_(getModelIDNew()); + if(ret != OK) + LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!"); + + } catch (FMILException e) { + throw e; + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + private native int simulateStep_(int id) throws FMILException; + + /** + * Get an array containing the current values for subscribed variables. The + * values are in the same order as in the subscription. + * + * @param results An array the size of subscribed results + * @return + */ + public double[] getSubscribedResults() throws FMILException { + synchronized(syncObject) { + + try { + + double[] results = new double[subscription.size()]; + return getSubscribedResults_(getModelIDNew(), results); + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native double[] getSubscribedResults_(int id, double[] results); + + + /** + * Unload FMU and the dll:s that it requires. + *

+ * To be called after all FMU simulations are ended. + * If the fmu is loaded again / changed, call to loadFMUFile is sufficient. loadFMUFile + * releases the previous fmu.dll + * + * @throws FMILException + */ + public void unloadFMU() throws FMILException { + synchronized(syncObject) { + + try { + + unlockFMUDirectory(); + if(fmuLoaded) { + int ret = unloadFMU_(getModelIDNew()); + if(ret != OK) + LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!"); + fmuLoaded = false; + } + removeFMUDirectoryContents(); + + } catch (FMILException e) { + throw e; + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + private native int unloadFMU_(int id) throws FMILException; + +// /** +// * Checks if fmu has been initialized +// * @return current simulation time +// */ +// public boolean isInitialized() throws FMILException { +// synchronized(syncObject) { +// try { +// return isInitialized_(getModelID()); +// } catch (UnsatisfiedLinkError err) { +// throw new FMILException(UNSATISFIED_LINK); +// } catch (Exception e) { +// throw new FMILException(e.getMessage()); +// } +// } +// } +// +// private native boolean isInitialized_(String id); +// + /** + * Get the current simulation time + * @return current simulation time + */ + public double getTime() throws FMILException { + synchronized(syncObject) { + + try { + + return getTime_(getModelIDNew()); + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native double getTime_(int id); + + /** + * Get all variables in a loaded model + * @return all variables in a loaded model + */ + public String[] getAllVariables() throws FMILException { + synchronized(syncObject) { + + try { + + if(variableNames == null) { + variableNames = getAllVariables_(getModelIDNew()); + } + return variableNames; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native String[] getAllVariables_(int id); + + public String[] getAllVariableDescriptions() throws FMILException { + synchronized(syncObject) { + + try { + + if(variableDescriptions == null) { + variableDescriptions = getAllVariableDescriptions_(getModelIDNew()); + } + return variableDescriptions; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native String[] getAllVariableDescriptions_(int id); + + public String[] getAllVariableDeclaredTypes() throws FMILException { + synchronized(syncObject) { + + try { + + if(variableDeclaredTypes == null) { + variableDeclaredTypes = getAllVariableDeclaredTypes_(getModelIDNew()); + } + return variableDeclaredTypes; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native String[] getAllVariableDeclaredTypes_(int id); + + public int[] getAllVariableReferences() throws FMILException { + synchronized(syncObject) { + + try { + + if(variableReferences == null) { + variableReferences = getAllVariableReferences_(getModelIDNew(), new int[variableNames.length]); + } + return variableReferences; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native int[] getAllVariableReferences_(int id, int[] array); + + public int[] getAllVariableTypes() throws FMILException { + synchronized(syncObject) { + + try { + + if(variableTypes == null) { + variableTypes = getAllVariableTypes_(getModelIDNew(), new int[variableNames.length]); + } + return variableTypes; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native int[] getAllVariableTypes_(int id, int[] array); + + public int[] getAllVariableCausalities() throws FMILException { + synchronized(syncObject) { + + try { + + if(variableCausalities == null) { + variableCausalities = getAllVariableCausalities_(getModelIDNew(), new int[variableNames.length]); + } + return variableCausalities; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native int[] getAllVariableCausalities_(int id, int[] array); + + public int[] getAllVariableVariabilities() throws FMILException { + synchronized(syncObject) { + + try { + + if(variableVariabilities == null) { + variableVariabilities = getAllVariableVariabilities_(getModelIDNew(), new int[variableNames.length]); + } + return variableVariabilities; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native int[] getAllVariableVariabilities_(int id, int[] array); + + /** + * Get all variables in a loaded model + * @return all variables in a loaded model + */ + public String[] getAllDeclaredTypes() throws FMILException { + synchronized(syncObject) { + + try { + + if(declaredTypes == null) { + declaredTypes = getAllDeclaredTypes_(getModelIDNew()); + } + return declaredTypes; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native String[] getAllDeclaredTypes_(int id); + + public String[] getAllDeclaredTypeDescriptions() throws FMILException { + synchronized(syncObject) { + + try { + + if(declaredTypeDescriptions == null) { + declaredTypeDescriptions = getAllDeclaredTypeDescriptions_(getModelIDNew()); + } + return declaredTypeDescriptions; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native String[] getAllDeclaredTypeDescriptions_(int id); + + public String[] getAllDeclaredTypeQuantities() throws FMILException { + synchronized(syncObject) { + + try { + + if(declaredTypeQuantities == null) { + declaredTypeQuantities = getAllDeclaredTypeQuantities_(getModelIDNew()); + } + return declaredTypeQuantities; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native String[] getAllDeclaredTypeQuantities_(int id); + + public String[] getAllDeclaredTypeUnits() throws FMILException { + synchronized(syncObject) { + + try { + + if(declaredTypeUnits == null) { + declaredTypeUnits = getAllDeclaredTypeUnits_(getModelIDNew()); + } + return declaredTypeUnits; + + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native String[] getAllDeclaredTypeUnits_(int id); + + +// +// /** +// * Get all variables from model that match the filter (and time variable) +// * +// * @param regexp Regular expression filter +// * @return An array of variable names that match regexp filter (and time-variable) +// * @throws FMILException +// */ +// public String[] filterVariables(String regexp) throws FMILException { +// synchronized(syncObject) { +// try { +// +// return filterVariables_(getModelID(), regexp + "|time"); +// +// } catch (UnsatisfiedLinkError err) { +// throw new FMILException(UNSATISFIED_LINK); +// } catch (Exception e) { +// throw new FMILException(e.getMessage()); +// } +// } +// } +// +// private native String[] filterVariables_(String id, String regexp); +//// +// /** +// * Get the last error message +// * @return Last error message +// */ +// public String getLastErrorMessage() throws FMILException { +// synchronized(syncObject) { +// +// try { +// +// return "err"; +// //return getLastErrorMessage_(getModelID()); +// +// } catch (UnsatisfiedLinkError err) { +// throw new FMILException(UNSATISFIED_LINK); +// } catch (Exception e) { +// throw new FMILException(e.getMessage()); +// } +// } +// } +// +// private native String getLastErrorMessage_(String id); + + /** + * Get a real (double) value for variable + * @param name Name of the variable + * @return value + * @throws FMILException + */ + public double getRealValue(String name) throws FMILException { + synchronized(syncObject) { + + try { + // TODO: printtaa id ja name, jotta saadaan virheessä kiinni + double result = getRealValue_(getModelIDNew(), variableMap.get(name)); + System.err.println("getRealValue " + name + " = " + result); + return result; + } catch (UnsatisfiedLinkError err) { + throw new FMILException(UNSATISFIED_LINK); + } catch (Exception e) { + throw new FMILException(e.getMessage()); + } + } + } + + private native double getRealValue_(int id, int variableReference); + +// /** +// * Get a string value for variable +// * @param name Name of the variable +// * @return value +// * @throws FMILException +// */ +// public String getStringValue(String name) throws FMILException { +// synchronized(syncObject) { +// +// try { +// return getStringValue_(getModelID(), name); +// } catch (UnsatisfiedLinkError err) { +// throw new FMILException(UNSATISFIED_LINK); +// } catch (Exception e) { +// throw new FMILException(e.getMessage()); +// } +// } +// } +// +// private native String getStringValue_(String id, String name); +// +// /** +// * Get an integer value for variable +// * @param name Name of the variable +// * @return value +// * @throws FMILException +// */ +// public int getIntegerValue(String name) throws FMILException { +// synchronized(syncObject) { +// +// try { +// return getIntegerValue_(getModelID(), name); +// } catch (UnsatisfiedLinkError err) { +// throw new FMILException(UNSATISFIED_LINK); +// } catch (Exception e) { +// throw new FMILException(e.getMessage()); +// } +// } +// } +// +// private native int getIntegerValue_(String id, String name); +// +// /** +// * Get a real (double) value for variable +// * @param name Name of the variable +// * @return value +// * @throws FMILException +// */ +// public boolean getBooleanValue(String name) throws FMILException { +// synchronized(syncObject) { +// +// try { +// return getBooleanValue_(getModelID(), name); +// } catch (UnsatisfiedLinkError err) { +// throw new FMILException(UNSATISFIED_LINK); +// } catch (Exception e) { +// throw new FMILException(e.getMessage()); +// } +// } +// } +// +// private native boolean getBooleanValue_(String id, String name); + + private FileChannel channel; + private FileLock lock; + + @SuppressWarnings("resource") + private boolean lockFMUDirectory() { + + try { + // Get a file channel for the lock file + File lockFile = new File(TEMP_FMU_DIRECTORY, LOCK_FILE_NAME); + if(!lockFile.isFile()) + lockFile.createNewFile(); + + channel = new RandomAccessFile(lockFile, "rw").getChannel(); + + // Use the file channel to create a lock on the file. + // This method blocks until it can retrieve the lock. + lock = channel.lock(); + + // // Try acquiring the lock without blocking. This method returns + // // null or throws an exception if the file is already locked. + // try { + // lock = channel.tryLock(); + // } catch (OverlappingFileLockException e) { + // // File is already locked in this thread or virtual machine + // } + } catch (IOException e) { + return false; + } + + return true; + } + + private boolean unlockFMUDirectory() { + try { + // Release the lock + if(lock != null) + lock.release(); + + // Close the file + if(channel != null) + channel.close(); + } catch (IOException e) { + return false; + } + return true; + } + + private boolean removeFMUDirectoryContents() { + // Remove contents + try { + File tempDir = new File(TEMP_FMU_DIRECTORY); + FileUtils.deleteAll(tempDir); + tempDir.delete(); + } catch (IOException e) { + return false; + } + return true; + } + + @Override + protected void finalize() throws Throwable { + try { + unloadFMU(); + } catch (Throwable t) { + LOGGER.error("Could not unload native FMU!", t); + } finally { + super.finalize(); + } + } +} diff --git a/org.simantics.fmil.win32/libraries/Debug/FMUSimulator.dll b/org.simantics.fmil.win32/libraries/Debug/FMUSimulator.dll new file mode 100644 index 0000000..5e6f109 Binary files /dev/null and b/org.simantics.fmil.win32/libraries/Debug/FMUSimulator.dll differ diff --git a/org.simantics.fmil.win32/libraries/Debug/fmilib_shared.dll b/org.simantics.fmil.win32/libraries/Debug/fmilib_shared.dll new file mode 100644 index 0000000..eedf974 Binary files /dev/null and b/org.simantics.fmil.win32/libraries/Debug/fmilib_shared.dll differ diff --git a/org.simantics.fmil.win32/libraries/Debug/fmu1_dll_cs.dll b/org.simantics.fmil.win32/libraries/Debug/fmu1_dll_cs.dll new file mode 100644 index 0000000..6397ee9 Binary files /dev/null and b/org.simantics.fmil.win32/libraries/Debug/fmu1_dll_cs.dll differ diff --git a/org.simantics.fmil.win32/libraries/Debug/fmu1_dll_me.dll b/org.simantics.fmil.win32/libraries/Debug/fmu1_dll_me.dll new file mode 100644 index 0000000..a518568 Binary files /dev/null and b/org.simantics.fmil.win32/libraries/Debug/fmu1_dll_me.dll differ diff --git a/org.simantics.fmil.win32/libraries/Debug/fmu2_dll_cs.dll b/org.simantics.fmil.win32/libraries/Debug/fmu2_dll_cs.dll new file mode 100644 index 0000000..89117c0 Binary files /dev/null and b/org.simantics.fmil.win32/libraries/Debug/fmu2_dll_cs.dll differ diff --git a/org.simantics.fmil.win32/libraries/Debug/fmu2_dll_me.dll b/org.simantics.fmil.win32/libraries/Debug/fmu2_dll_me.dll new file mode 100644 index 0000000..3350c00 Binary files /dev/null and b/org.simantics.fmil.win32/libraries/Debug/fmu2_dll_me.dll differ diff --git a/org.simantics.fmil.win32/libraries/FMUSimulator.dll b/org.simantics.fmil.win32/libraries/FMUSimulator.dll index 781a899..2907f2a 100644 Binary files a/org.simantics.fmil.win32/libraries/FMUSimulator.dll and b/org.simantics.fmil.win32/libraries/FMUSimulator.dll differ diff --git a/org.simantics.fmil.win32/libraries/fmilib_shared.dll b/org.simantics.fmil.win32/libraries/fmilib_shared.dll index 6824f1b..fa599b6 100644 Binary files a/org.simantics.fmil.win32/libraries/fmilib_shared.dll and b/org.simantics.fmil.win32/libraries/fmilib_shared.dll differ diff --git a/org.simantics.fmil.win32/libraries/fmu1_dll_cs.dll b/org.simantics.fmil.win32/libraries/fmu1_dll_cs.dll index dfce002..6569466 100644 Binary files a/org.simantics.fmil.win32/libraries/fmu1_dll_cs.dll and b/org.simantics.fmil.win32/libraries/fmu1_dll_cs.dll differ diff --git a/org.simantics.fmil.win32/libraries/fmu1_dll_me.dll b/org.simantics.fmil.win32/libraries/fmu1_dll_me.dll index 0455f86..1eb1f69 100644 Binary files a/org.simantics.fmil.win32/libraries/fmu1_dll_me.dll and b/org.simantics.fmil.win32/libraries/fmu1_dll_me.dll differ diff --git a/org.simantics.fmil.win32/libraries/fmu2_dll_cs.dll b/org.simantics.fmil.win32/libraries/fmu2_dll_cs.dll index 26bdc89..46fa620 100644 Binary files a/org.simantics.fmil.win32/libraries/fmu2_dll_cs.dll and b/org.simantics.fmil.win32/libraries/fmu2_dll_cs.dll differ diff --git a/org.simantics.fmil.win32/libraries/fmu2_dll_me.dll b/org.simantics.fmil.win32/libraries/fmu2_dll_me.dll index 056df37..da76130 100644 Binary files a/org.simantics.fmil.win32/libraries/fmu2_dll_me.dll and b/org.simantics.fmil.win32/libraries/fmu2_dll_me.dll differ diff --git a/org.simantics.fmil.win64/libraries/Debug/FMUSimulator.dll b/org.simantics.fmil.win64/libraries/Debug/FMUSimulator.dll new file mode 100644 index 0000000..e142ebe Binary files /dev/null and b/org.simantics.fmil.win64/libraries/Debug/FMUSimulator.dll differ diff --git a/org.simantics.fmil.win64/libraries/Debug/fmilib_shared.dll b/org.simantics.fmil.win64/libraries/Debug/fmilib_shared.dll new file mode 100644 index 0000000..5b7305c Binary files /dev/null and b/org.simantics.fmil.win64/libraries/Debug/fmilib_shared.dll differ diff --git a/org.simantics.fmil.win64/libraries/Debug/fmu1_dll_cs.dll b/org.simantics.fmil.win64/libraries/Debug/fmu1_dll_cs.dll new file mode 100644 index 0000000..263de8e Binary files /dev/null and b/org.simantics.fmil.win64/libraries/Debug/fmu1_dll_cs.dll differ diff --git a/org.simantics.fmil.win64/libraries/Debug/fmu1_dll_me.dll b/org.simantics.fmil.win64/libraries/Debug/fmu1_dll_me.dll new file mode 100644 index 0000000..75ffc94 Binary files /dev/null and b/org.simantics.fmil.win64/libraries/Debug/fmu1_dll_me.dll differ diff --git a/org.simantics.fmil.win64/libraries/Debug/fmu2_dll_cs.dll b/org.simantics.fmil.win64/libraries/Debug/fmu2_dll_cs.dll new file mode 100644 index 0000000..ce8c580 Binary files /dev/null and b/org.simantics.fmil.win64/libraries/Debug/fmu2_dll_cs.dll differ diff --git a/org.simantics.fmil.win64/libraries/Debug/fmu2_dll_me.dll b/org.simantics.fmil.win64/libraries/Debug/fmu2_dll_me.dll new file mode 100644 index 0000000..7c54efe Binary files /dev/null and b/org.simantics.fmil.win64/libraries/Debug/fmu2_dll_me.dll differ diff --git a/org.simantics.fmil.win64/libraries/FMUSimulator.dll b/org.simantics.fmil.win64/libraries/FMUSimulator.dll index 5553bc8..d0922ca 100644 Binary files a/org.simantics.fmil.win64/libraries/FMUSimulator.dll and b/org.simantics.fmil.win64/libraries/FMUSimulator.dll differ diff --git a/org.simantics.fmil.win64/libraries/fmilib_shared.dll b/org.simantics.fmil.win64/libraries/fmilib_shared.dll index fad052d..f33a53d 100644 Binary files a/org.simantics.fmil.win64/libraries/fmilib_shared.dll and b/org.simantics.fmil.win64/libraries/fmilib_shared.dll differ diff --git a/org.simantics.fmil.win64/libraries/fmu1_dll_cs.dll b/org.simantics.fmil.win64/libraries/fmu1_dll_cs.dll index fe20f46..ddfa7c3 100644 Binary files a/org.simantics.fmil.win64/libraries/fmu1_dll_cs.dll and b/org.simantics.fmil.win64/libraries/fmu1_dll_cs.dll differ diff --git a/org.simantics.fmil.win64/libraries/fmu1_dll_me.dll b/org.simantics.fmil.win64/libraries/fmu1_dll_me.dll index 173b097..432673b 100644 Binary files a/org.simantics.fmil.win64/libraries/fmu1_dll_me.dll and b/org.simantics.fmil.win64/libraries/fmu1_dll_me.dll differ diff --git a/org.simantics.fmil.win64/libraries/fmu2_dll_cs.dll b/org.simantics.fmil.win64/libraries/fmu2_dll_cs.dll index 4768f30..d8a7507 100644 Binary files a/org.simantics.fmil.win64/libraries/fmu2_dll_cs.dll and b/org.simantics.fmil.win64/libraries/fmu2_dll_cs.dll differ diff --git a/org.simantics.fmil.win64/libraries/fmu2_dll_me.dll b/org.simantics.fmil.win64/libraries/fmu2_dll_me.dll index 6a2c354..f4225cf 100644 Binary files a/org.simantics.fmil.win64/libraries/fmu2_dll_me.dll and b/org.simantics.fmil.win64/libraries/fmu2_dll_me.dll differ