-/* ------------------------------------------------------------------------- \r
- * fmu_control.c\r
- * Simulation controls for fmus\r
- *\r
- * Free libraries and tools used to implement this simulator:\r
- * - header files from the FMU specification\r
- * - eXpat 2.0.1 XML parser, see http://expat.sourceforge.net\r
- * - 7z.exe 4.57 zip and unzip tool, see http://www.7-zip.org <---------- Replace with zlib\r
- * Author: Teemu Lempinen\r
- * Copyright 2012 Semantum Oy\r
- * -------------------------------------------------------------------------\r
- */\r
-\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <map>\r
-#include <string>\r
-#include <vector>\r
-#include <iostream>\r
-#include <regex>\r
-\r
-#include <org_simantics_fmil_FMILJNI.h>\r
-\r
-extern "C" {\r
- #include "fmi_me.h"\r
- #include "sim_support.h"\r
-}\r
-\r
-#include "fmi1_cs.h"\r
-\r
-#define PRINT(fmt,args) { FILE *fp = fopen("R:\\Simantics\\Sysdyn\\log.txt", "ab"); fprintf(fp, fmt, args); fclose(fp); }\r
-\r
-#include <direct.h>\r
-#define GetCurrentDir _getcwd\r
-\r
-using namespace std;\r
-\r
-struct FMI1 {\r
-\r
- void *fmu;\r
-\r
- vector<string> variables;\r
- vector<string> descriptions;\r
- vector<string> declaredTypes;\r
- vector<int> valueReferences;\r
- vector<int> types;\r
- vector<int> variabilities;\r
- vector<int> causalities;\r
-\r
- vector<string> declaredTypeNames;\r
- vector<string> typeDescriptions;\r
- vector<string> quantities;\r
- vector<string> units;\r
-\r
- vector<int> subscription;\r
- double currentTime;\r
- double timeStep;\r
-\r
-};\r
-\r
-struct FMUControlStruct {\r
- double step; // simulation step length\r
- fmiReal currentTime; // current simulation time\r
-\r
- fmiComponent c; // instance of the fmu \r
- ScalarVariable** vars; // model variables\r
-\r
- fmiEventInfo eventInfo; // updated by calls to initialize and eventUpdate\r
- const char* guid; // global unique id of the fmu\r
- fmiCallbackFunctions callbacks; // called by the model during simulation\r
- fmiStatus fmiFlag; // return code of the fmu functions\r
-\r
- map<string,int> indexes; // indexes for variable names in vars-table\r
- map<string,int>::iterator it;\r
-\r
- int nx; // number of state variables\r
- double *x; // continuous states\r
- double *xdot; // the crresponding derivatives in same order\r
- int nz; // number of state event indicators\r
- double *z; // state event indicators\r
- double *prez; // previous values of state event indicators\r
- \r
- bool initialized; // has the fmu been initialized\r
-\r
- vector<fmiValueReference> subscription; // result subscriptions\r
- vector<string> allVariables; // all variables in an initialized model\r
- vector<fmiValueReference> fmiValueReferences; // all value references\r
-\r
- string lastErrorMessage;\r
-\r
- FMU fmu;\r
-};\r
-\r
-vector<FMI1> fmus;\r
-\r
-//map<string,FMUControlStruct> fmus; // indexes for variable names in vars-table\r
-\r
-int throwException(JNIEnv *env, string message) {\r
- jclass newExcCls;\r
- newExcCls = env->FindClass("java/lang/Exception");\r
- if (newExcCls == NULL) {\r
- /* Unable to find the exception class, give up. */\r
- return 0;\r
- }\r
- env->ThrowNew(newExcCls, message.c_str());\r
- return 0;\r
-}\r
-\r
-/*\r
-bool exists(string id) {\r
- map<string,FMUControlStruct>::iterator it = fmus.find(id);\r
- if(it != fmus.end()) {\r
- return true;\r
- } else {\r
- return false;\r
- }\r
-}\r
-*/\r
-\r
-\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_loadFMUFile_1 \r
- (JNIEnv *env, jobject obj, jstring path, jstring tempDir) {\r
-\r
- HMODULE module = NULL;\r
- FMI1 fmi1;\r
- FMIL_Variable *vars;\r
- FMIL_DeclaredType *types;\r
- int variableCount = 0;\r
- int typeCount = 0;\r
-\r
- const char *fmuPath = env->GetStringUTFChars(path, 0);\r
- const char *fmuTempDir = env->GetStringUTFChars(tempDir, 0);\r
-\r
- fmi1.currentTime = 0;\r
- fmi1.timeStep = 0.1;\r
- fmi1.fmu = FMI1_CS_LOAD(fmuPath, fmuTempDir);\r
- if(!fmi1.fmu)\r
- return throwException(env, "No FMU loaded");\r
-\r
- vars = FMI1_CS_GET_VARIABLES(fmi1.fmu, &variableCount);\r
- for(int i=0;i<variableCount;i++) {\r
- fmi1.variables.push_back(string(vars[i].name));\r
- if(vars[i].description)\r
- fmi1.descriptions.push_back(string(vars[i].description));\r
- else\r
- fmi1.descriptions.push_back(string(""));\r
- if(vars[i].declaredType)\r
- fmi1.declaredTypes.push_back(string(vars[i].declaredType));\r
- else\r
- fmi1.declaredTypes.push_back(string(""));\r
- fmi1.types.push_back(vars[i].type);\r
- fmi1.causalities.push_back(vars[i].causality);\r
- fmi1.variabilities.push_back(vars[i].variability);\r
- fmi1.valueReferences.push_back(vars[i].vr);\r
- }\r
-\r
- types = FMI1_CS_GET_DECLARED_TYPES(fmi1.fmu, &typeCount);\r
- for(int i=0;i<typeCount;i++) {\r
- fmi1.declaredTypeNames.push_back(string(types[i].name));\r
- if(types[i].description)\r
- fmi1.typeDescriptions.push_back(string(types[i].description));\r
- else\r
- fmi1.typeDescriptions.push_back(string(""));\r
- if(types[i].quantity)\r
- fmi1.quantities.push_back(string(types[i].quantity));\r
- else\r
- fmi1.quantities.push_back(string(""));\r
- if(types[i].unit)\r
- fmi1.units.push_back(string(types[i].unit));\r
- else\r
- fmi1.units.push_back(string(""));\r
- }\r
-\r
-\r
- fmus.push_back(fmi1);\r
-\r
- env->ReleaseStringUTFChars(path, fmuPath);\r
- env->ReleaseStringUTFChars(tempDir, fmuTempDir);\r
-\r
- return fmus.size() - 1;\r
-\r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setStepLength_1 \r
- (JNIEnv *env, jobject obj, jint id, jdouble stepLength) {\r
- fmus[id].timeStep = stepLength;\r
- return 1;\r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_subscribe_1\r
- (JNIEnv *env, jobject obj, jint id, jintArray vrs) {\r
-\r
- jboolean isCopy;\r
- jint* elements = env -> GetIntArrayElements(vrs, &isCopy);\r
- jsize n = env -> GetArrayLength(vrs);\r
-\r
- int i;\r
- for (i = 0; i < n; i++) {\r
- fmus[id].subscription.push_back(elements[i]);\r
- } \r
- \r
- if (isCopy == JNI_TRUE) {\r
- env -> ReleaseIntArrayElements(vrs, elements, 0);\r
- }\r
-\r
- return 1;\r
-\r
-}\r
-\r
-bool referenceExists(FMUControlStruct fmuStruct, string variable) {\r
- map<string,int>::iterator it = fmuStruct.indexes.find(variable);\r
- if(it != fmuStruct.indexes.end()) {\r
- return true;\r
- } else {\r
- return false;\r
- }\r
-}\r
-\r
-// Remember to check if reference exists\r
-fmiValueReference getReference(FMUControlStruct fmuStruct, string variable) {\r
- return fmuStruct.fmiValueReferences[fmuStruct.indexes[variable]];\r
-}\r
-\r
-// Get string representation of a scalar variable type\r
-string getTypeString(ScalarVariable* sv) {\r
- switch (sv->typeSpec->type){\r
- case elm_Integer:\r
- return "Integer";\r
- case elm_Enumeration:\r
- return "Enumeration";\r
- case elm_Real:\r
- return "Real";\r
- case elm_Boolean:\r
- return "Boolean";\r
- default:\r
- return "No type";\r
- }\r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setRealValue_1\r
- (JNIEnv *env, jobject obj, jint id, jint vr, jdouble value) {\r
-\r
- FMI1_CS_SET_REAL(fmus[id].fmu, vr, value);\r
- return 1;\r
-\r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setIntegerValue_1\r
- (JNIEnv *env, jobject obj, jstring id, jstring parameter, jint value) {\r
- /*\r
- const char *fmuId = env->GetStringUTFChars(id, 0);\r
- if(exists(fmuId)) {\r
- FMUControlStruct& fmuStruct = fmus[fmuId];\r
- const char *name = env->GetStringUTFChars(parameter, 0);\r
- string nameString = name;\r
- string modelId = fmuId;\r
- if(!referenceExists(fmuStruct, name)) {\r
- string errorMessage = "setIntegerValue: Model (id " + modelId + ") does not contain variable: " + nameString;\r
- env->ReleaseStringUTFChars(parameter, name);\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return throwException(env, errorMessage);\r
- } else {\r
- // Check variable type\r
- ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]];\r
- switch (sv->typeSpec->type){\r
- case elm_Integer:\r
- break; // ok\r
- default: {\r
- string errorMessage = "setIntegerValue: " + nameString + " is not of type Integer. (type: + " + getTypeString(sv) + ")";\r
- env->ReleaseStringUTFChars(parameter, name);\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return throwException(env, errorMessage);\r
- }\r
- }\r
-\r
- // Change value\r
- fmiValueReference vr = getReference(fmuStruct, name);\r
- const int intValue = (int) value;\r
- fmuStruct.fmu.setInteger(fmuStruct.c, &vr, 1, &intValue);\r
- env->ReleaseStringUTFChars(parameter, name);\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return 1;\r
- }\r
- } else {\r
- string message = fmuId;\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return throwException(env, "setIntegerValue: Model id " + message + " not found");\r
- }\r
- */\r
- return 1;\r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setBooleanValue_1\r
- (JNIEnv *env, jobject obj, jstring id, jstring parameter, jboolean value) {\r
- /*\r
- const char *fmuId = env->GetStringUTFChars(id, 0);\r
- if(exists(fmuId)) {\r
- FMUControlStruct& fmuStruct = fmus[fmuId];\r
- const char *name = env->GetStringUTFChars(parameter, 0);\r
- string nameString = name;\r
- string modelId = fmuId;\r
- if(!referenceExists(fmuStruct, name)) {\r
- string errorMessage = "setBooleanValue: Model (id " + modelId + ") does not contain variable: " + nameString;\r
- env->ReleaseStringUTFChars(parameter, name);\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return throwException(env, errorMessage);\r
- } else {\r
- // Check variable type\r
- ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]];\r
- switch (sv->typeSpec->type){\r
- case elm_Boolean:\r
- break; // ok\r
- default: {\r
- string errorMessage = "setBooleanValue: " + nameString + " is not of type Boolean. (type: + " + getTypeString(sv) + ")";\r
- env->ReleaseStringUTFChars(parameter, name);\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return throwException(env, errorMessage);\r
- }\r
- }\r
-\r
- // Change value\r
- fmiValueReference vr = getReference(fmuStruct, name);\r
- fmiBoolean result = 1;\r
- if(value == 0)\r
- result = 0;\r
- fmuStruct.fmu.setBoolean(fmuStruct.c, &vr, 1, &result);\r
- env->ReleaseStringUTFChars(parameter, name);\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return 1;\r
- }\r
- } else {\r
- string message = fmuId;\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return throwException(env, "setBooleanValue: Model id " + message + " not found");\r
- }*/\r
- return 1;\r
-}\r
-\r
-JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_FMIL_isInitialized_1\r
- (JNIEnv *env, jobject obj, jstring id) {\r
- /*\r
- const char *fmuId = env->GetStringUTFChars(id, 0);\r
- if(exists(fmuId)) {\r
- FMUControlStruct& fmuStruct = fmus[fmuId];\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return fmuStruct.initialized;\r
- } else {\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return false;\r
- }\r
- */\r
- return 1;\r
-}\r
-\r
-\r
-JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_FMIL_getTime_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
- return fmus[id].currentTime;\r
-}\r
-\r
-double getRealValue(FMUControlStruct fmuStruct, int index) {\r
- ScalarVariable *sv = fmuStruct.vars[index];\r
- fmiValueReference vr = fmuStruct.fmiValueReferences[index];\r
- double real;\r
- fmiInteger integer;\r
- fmiBoolean fmibool;\r
-\r
- switch (sv->typeSpec->type){\r
- case elm_Real:\r
- fmuStruct.fmu.getReal(fmuStruct.c, &vr, 1, &real);\r
- break;\r
- case elm_Integer:\r
- case elm_Enumeration:\r
- fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &integer);\r
- real = (double)integer;\r
- break;\r
- case elm_Boolean:\r
- fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &fmibool);\r
- if(fmibool == fmiTrue)\r
- real = 1.0;\r
- else\r
- real = 0.0;\r
- break;\r
- }\r
- return real;\r
-}\r
-\r
-JNIEXPORT jdoubleArray JNICALL Java_org_simantics_fmil_FMIL_getSubscribedResults_1\r
- (JNIEnv *env, jobject obj, jint id, jdoubleArray result) {\r
-\r
- jboolean isCopy;\r
- jdouble* resultElements = env -> GetDoubleArrayElements(result, &isCopy);\r
- jsize n = env -> GetArrayLength(result);\r
- int *vrs;\r
- if(n > 0) {\r
- vrs = &(fmus[id].subscription[0]);\r
- FMI1_CS_GET_REALS(fmus[id].fmu, vrs, resultElements, n);\r
- }\r
- if (isCopy == JNI_TRUE) {\r
- env -> ReleaseDoubleArrayElements(result, resultElements, 0);\r
- }\r
-\r
- return result;\r
- \r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_instantiateSimulation_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- int asd = FMI1_CS_INSTANTIATE(fmus[id].fmu);\r
- if(asd != 0)\r
- return throwException(env, "No FMU loaded");\r
-\r
- return 1;\r
-\r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_initializeSimulation_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- int asd = FMI1_CS_INITIALIZE(fmus[id].fmu);\r
- if(asd != 0)\r
- return throwException(env, "No FMU loaded");\r
-\r
- return 1;\r
-\r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_setTime_1\r
- (JNIEnv *env, jobject obj, jstring id, jdouble time) {\r
- return 1;\r
-}\r
-\r
-JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariables_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].variables.size(), \r
- env->FindClass("java/lang/String"), \r
- env->NewStringUTF("")); \r
- \r
- for(int i=0;i<fmus[id].variables.size();i++) { \r
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].variables[i].c_str())); \r
- } \r
-\r
- return ret; \r
-\r
-}\r
-\r
-JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableDescriptions_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].descriptions.size(), \r
- env->FindClass("java/lang/String"), \r
- env->NewStringUTF("")); \r
- \r
- for(int i=0;i<fmus[id].descriptions.size();i++) { \r
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].descriptions[i].c_str())); \r
- } \r
-\r
- return ret; \r
-\r
-}\r
-\r
-JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableDeclaredTypes_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypes.size(), \r
- env->FindClass("java/lang/String"), \r
- env->NewStringUTF(""));\r
- \r
- for(int i=0;i<fmus[id].declaredTypes.size();i++) { \r
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypes[i].c_str())); \r
- } \r
-\r
- return ret; \r
-\r
-}\r
-\r
-JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableReferences_1\r
- (JNIEnv *env, jobject obj, jint id, jintArray result) {\r
-\r
- jboolean isCopy;\r
- jint* resultElements = env -> GetIntArrayElements(result, &isCopy);\r
- jsize n = env -> GetArrayLength(result);\r
-\r
- int i;\r
- for (i = 0; i < n; i++) {\r
- resultElements[i] = fmus[id].valueReferences[i];\r
- } \r
- \r
- if (isCopy == JNI_TRUE) {\r
- env -> ReleaseIntArrayElements(result, resultElements, 0);\r
- }\r
-\r
- return result;\r
-\r
-}\r
-\r
-JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableTypes_1\r
- (JNIEnv *env, jobject obj, jint id, jintArray result) {\r
-\r
- jboolean isCopy;\r
- jint* resultElements = env -> GetIntArrayElements(result, &isCopy);\r
- jsize n = env -> GetArrayLength(result);\r
-\r
- int i;\r
- for (i = 0; i < n; i++) {\r
- resultElements[i] = fmus[id].types[i];\r
- } \r
- \r
- if (isCopy == JNI_TRUE) {\r
- env -> ReleaseIntArrayElements(result, resultElements, 0);\r
- }\r
-\r
- return result;\r
-\r
-}\r
-\r
-JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableVariabilities_1\r
- (JNIEnv *env, jobject obj, jint id, jintArray result) {\r
-\r
- jboolean isCopy;\r
- jint* resultElements = env -> GetIntArrayElements(result, &isCopy);\r
- jsize n = env -> GetArrayLength(result);\r
-\r
- int i;\r
- for (i = 0; i < n; i++) {\r
- resultElements[i] = fmus[id].variabilities[i];\r
- } \r
- \r
- if (isCopy == JNI_TRUE) {\r
- env -> ReleaseIntArrayElements(result, resultElements, 0);\r
- }\r
-\r
- return result;\r
-\r
-}\r
-\r
-JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_FMIL_getAllVariableCausalities_1\r
- (JNIEnv *env, jobject obj, jint id, jintArray result) {\r
-\r
- jboolean isCopy;\r
- jint* resultElements = env -> GetIntArrayElements(result, &isCopy);\r
- jsize n = env -> GetArrayLength(result);\r
-\r
- int i;\r
- for (i = 0; i < n; i++) {\r
- resultElements[i] = fmus[id].causalities[i];\r
- } \r
- \r
- if (isCopy == JNI_TRUE) {\r
- env -> ReleaseIntArrayElements(result, resultElements, 0);\r
- }\r
-\r
- return result;\r
-\r
-}\r
-\r
-JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypes_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypeNames.size(), \r
- env->FindClass("java/lang/String"), \r
- env->NewStringUTF(""));\r
- \r
- for(int i=0;i<fmus[id].declaredTypeNames.size();i++) { \r
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypeNames[i].c_str())); \r
- } \r
-\r
- return ret; \r
-\r
-}\r
-\r
-JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypeDescriptions_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].typeDescriptions.size(), \r
- env->FindClass("java/lang/String"), \r
- env->NewStringUTF(""));\r
- \r
- for(int i=0;i<fmus[id].typeDescriptions.size();i++) { \r
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].typeDescriptions[i].c_str())); \r
- } \r
-\r
- return ret; \r
-\r
-}\r
-\r
-JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypeQuantities_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].quantities.size(), \r
- env->FindClass("java/lang/String"), \r
- env->NewStringUTF(""));\r
- \r
- for(int i=0;i<fmus[id].quantities.size();i++) { \r
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].quantities[i].c_str())); \r
- } \r
-\r
- return ret; \r
-\r
-}\r
-\r
-JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_getAllDeclaredTypeUnits_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].units.size(), \r
- env->FindClass("java/lang/String"), \r
- env->NewStringUTF(""));\r
- \r
- for(int i=0;i<fmus[id].units.size();i++) { \r
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].units[i].c_str())); \r
- } \r
-\r
- return ret; \r
-\r
-}\r
-\r
-/*\r
-JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_FMIL_filterVariables_1\r
- (JNIEnv *env, jobject obj, jstring id, jstring regexp) {\r
- const char *rx = env->GetStringUTFChars(regexp, 0);\r
- jobjectArray result = filterVariables(env, obj, id, rx);\r
- env->ReleaseStringUTFChars(regexp, rx);\r
- return result;\r
-}\r
-*/\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_simulateStep_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- int asd = FMI1_CS_STEP(fmus[id].fmu, fmus[id].currentTime, fmus[id].timeStep);\r
- if(asd != 0)\r
- return throwException(env, "No FMU loaded");\r
-\r
- fmus[id].currentTime += fmus[id].timeStep;\r
-\r
- return 1;\r
-\r
- /*\r
- const char *fmuId = env->GetStringUTFChars(id, 0);\r
- if(exists(fmuId)) {\r
- FMUControlStruct& fmuStruct = fmus[fmuId];\r
- env->ReleaseStringUTFChars(id, fmuId);\r
-\r
- if(&fmuStruct.fmu == NULL || fmuStruct.fmu.modelDescription == NULL || &fmuStruct.vars == NULL) {\r
- return throwException(env, "Simulate step failed - fmu not loaded");\r
- }\r
-\r
- if(fmuStruct.x == NULL) {\r
- return throwException(env, "Simulate step failed - fmu not instantiated");\r
- }\r
-\r
- if(fmuStruct.initialized == false) {\r
- fmiBoolean toleranceControlled = fmiFalse;\r
- fmuStruct.fmiFlag = fmuStruct.fmu.initialize(fmuStruct.c, toleranceControlled, fmuStruct.currentTime, &(fmuStruct.eventInfo));\r
- if (fmuStruct.fmiFlag > fmiWarning) return throwException(env, "could not initialize model");\r
- fmuStruct.initialized = true;\r
- }\r
-\r
- FMU& fmu = fmuStruct.fmu;\r
- int debug = 0; // DEBUG ON = 1, OFF = 0\r
-\r
- int i;\r
- double dt, tPre, tEnd = fmuStruct.currentTime + fmuStruct.step;\r
-\r
- fmiBoolean timeEvent, stateEvent, stepEvent;\r
- fmiStatus fmiFlag; // return code of the fmu functions\r
- fmiValueReference vr;\r
-\r
-\r
- */\r
- /* Simulate the duration of one step. The simulation may be done in \r
- * multiple parts if events occur\r
- */ /*\r
- while (fmuStruct.currentTime < tEnd) {\r
- // get current state and derivatives\r
- fmiFlag = fmu.getContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);\r
- if (fmiFlag > fmiWarning) \r
- return throwException(env, "could not retrieve states");\r
-\r
- fmiFlag = fmu.getDerivatives(fmuStruct.c, fmuStruct.xdot, fmuStruct.nx);\r
- if (fmiFlag > fmiWarning) \r
- return throwException(env, "could not retrieve derivatives");\r
-\r
- // advance time\r
- tPre = fmuStruct.currentTime;\r
- fmuStruct.currentTime = min(fmuStruct.currentTime+fmuStruct.step, tEnd);\r
- timeEvent = fmuStruct.eventInfo.upcomingTimeEvent && fmuStruct.eventInfo.nextEventTime < fmuStruct.currentTime; \r
- \r
- if (timeEvent) fmuStruct.currentTime = fmuStruct.eventInfo.nextEventTime;\r
- dt = fmuStruct.currentTime - tPre; \r
- fmiFlag = fmu.setTime(fmuStruct.c, fmuStruct.currentTime);\r
- if (fmiFlag > fmiWarning) throwException(env, "could not set time");\r
-\r
- if(referenceExists(fmuStruct, "time")) {\r
- vr = getReference(fmuStruct, "time");\r
- if(vr != NULL) {\r
- fmu.setReal(fmuStruct.c, &vr, 1, &(fmuStruct.currentTime));\r
- }\r
- }\r
-\r
- if(debug)\r
- printf("Actual time: %lf\n", fmuStruct.currentTime);\r
-\r
- if (fmiFlag > fmiWarning) \r
- return throwException(env, "could not set time");\r
-\r
- // perform one step\r
- for (i=0; i<fmuStruct.nx; i++) \r
- fmuStruct.x[i] += dt*fmuStruct.xdot[i]; // forward Euler method\r
-\r
- fmiFlag = fmu.setContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);\r
- if (fmiFlag > fmiWarning) \r
- return throwException(env, "could not set states");\r
-\r
- // Check for step event, e.g. dynamic state selection\r
- fmiFlag = fmu.completedIntegratorStep(fmuStruct.c, &stepEvent);\r
- if (fmiFlag > fmiWarning) return throwException(env, "could not complete intgrator step");\r
- */\r
-/* for (i=0; i<fmuStruct.nz; i++) fmuStruct.prez[i] = fmuStruct.z[i]; \r
- fmiFlag = fmu.getEventIndicators(fmuStruct.c, fmuStruct.z, fmuStruct.nz);\r
- if (fmiFlag > fmiWarning) return throwException(env, "could not retrieve event indicators");\r
- stateEvent = FALSE;\r
- for (i=0; i<fmuStruct.nz; i++) \r
- stateEvent = stateEvent || (fmuStruct.prez[i] * fmuStruct.z[i] < 0); \r
- \r
-\r
- stepEvent = fmiTrue;\r
- // handle events\r
- if (timeEvent || stateEvent || stepEvent) {\r
- \r
- // event iteration in one step, ignoring intermediate results\r
- fmiFlag = fmu.eventUpdate(fmuStruct.c, fmiFalse, &(fmuStruct.eventInfo));\r
- if (fmiFlag > fmiWarning) return throwException(env, "could not perform event update");\r
- \r
- } // if event\r
- */\r
- \r
-/* }\r
-\r
- fflush(stdout);\r
- return 1;\r
-\r
- } else {\r
- string message = fmuId;\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return throwException(env, "simulateStep: Model id " + message + " not found");\r
- }*/\r
- return 1;\r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_unloadFMU_1\r
- (JNIEnv *env, jobject obj, jint id) {\r
-\r
- int asd = FMI1_CS_UNLOAD(fmus[id].fmu);\r
- return asd;\r
-\r
-}\r
-\r
-JNIEXPORT jstring JNICALL Java_org_simantics_fmil_FMIL_getLastErrorMessage_1\r
- (JNIEnv *env, jobject obj, jstring id) {\r
- return env->NewStringUTF("No errors");\r
-}\r
-\r
-JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_FMIL_getRealValue_1\r
- (JNIEnv *env, jobject obj, jint id, jint vr) {\r
- return FMI1_CS_GET_REAL(fmus[id].fmu, vr);\r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_fmil_FMIL_getIntegerValue_1\r
- (JNIEnv *env, jobject obj, jstring id, jstring variable) {\r
- /*\r
- const char *fmuId = env->GetStringUTFChars(id, 0);\r
- if(exists(fmuId)) {\r
- FMUControlStruct fmuStruct = fmus[fmuId];\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- const char *name = env->GetStringUTFChars(variable, 0);\r
-\r
- if(referenceExists(fmuStruct, name)) {\r
- fmiValueReference vr = getReference(fmuStruct, name);\r
- int result;\r
- fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &result);\r
- env->ReleaseStringUTFChars(variable, name);\r
- return result;\r
-\r
- } else {\r
- string nameString = name;\r
- string message = "Variable " + nameString + " not found";\r
- env->ReleaseStringUTFChars(variable, name);\r
- return throwException(env, message);\r
- }\r
-\r
- } else {\r
- string message = fmuId;\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return throwException(env, "unloadFMU: Model id " + message + " not found");\r
- }\r
- */\r
- return 1;\r
-\r
-}\r
-\r
-JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_FMIL_getBooleanValue_1\r
- (JNIEnv *env, jobject obj, jstring id, jstring variable) {\r
- /*\r
- const char *fmuId = env->GetStringUTFChars(id, 0);\r
- if(exists(fmuId)) {\r
- FMUControlStruct fmuStruct = fmus[fmuId];\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- const char *name = env->GetStringUTFChars(variable, 0);\r
-\r
- if(referenceExists(fmuStruct, name)) {\r
- fmiValueReference vr = getReference(fmuStruct, name);\r
- fmiBoolean result;\r
- fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &result);\r
- env->ReleaseStringUTFChars(variable, name);\r
- return result;\r
-\r
- } else {\r
- string nameString = name;\r
- string message = "Variable " + nameString + " not found";\r
- env->ReleaseStringUTFChars(variable, name);\r
- return throwException(env, message);\r
- }\r
-\r
- } else {\r
- string message = fmuId;\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return throwException(env, "unloadFMU: Model id " + message + " not found");\r
- }*/\r
- return 1;\r
-\r
-}\r
-\r
-JNIEXPORT jstring JNICALL Java_org_simantics_fmil_FMIL_getStringValue_1\r
- (JNIEnv *env, jobject obj, jstring id, jstring variable) {\r
- /*\r
- const char *fmuId = env->GetStringUTFChars(id, 0);\r
- if(exists(fmuId)) {\r
- FMUControlStruct fmuStruct = fmus[fmuId];\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- const char *name = env->GetStringUTFChars(variable, 0);\r
-\r
- if(referenceExists(fmuStruct, name)) {\r
- fmiValueReference vr = getReference(fmuStruct, name);\r
- fmiString result;\r
- fmuStruct.fmu.getString(fmuStruct.c, &vr, 1, &result);\r
- env->ReleaseStringUTFChars(variable, name);\r
- return env->NewStringUTF(result);\r
-\r
- } else {\r
- string nameString = name;\r
- string message = "Variable " + nameString + " not found";\r
- env->ReleaseStringUTFChars(variable, name);\r
- return 0; //throwException(env, message);\r
- }\r
-\r
- } else {\r
- string message = fmuId;\r
- env->ReleaseStringUTFChars(id, fmuId);\r
- return 0; //throwException(env, "unloadFMU: Model id " + message + " not found");\r
- }\r
- */\r
- return 0;\r
-\r
-}
\ No newline at end of file
+/* -------------------------------------------------------------------------
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <map>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <regex>
+
+#include <org_simantics_fmil_FMILJNI.h>
+
+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); }
+
+using namespace std;
+
+struct FMI1 {
+
+ void *fmu;
+
+ vector<string> variables;
+ vector<string> descriptions;
+ vector<string> declaredTypes;
+ vector<int> valueReferences;
+ vector<int> types;
+ vector<int> variabilities;
+ vector<int> causalities;
+
+ vector<string> declaredTypeNames;
+ vector<string> typeDescriptions;
+ vector<string> quantities;
+ vector<string> units;
+
+ vector<int> 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<string,int> indexes; // indexes for variable names in vars-table
+ map<string,int>::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<fmiValueReference> subscription; // result subscriptions
+ vector<string> allVariables; // all variables in an initialized model
+ vector<fmiValueReference> fmiValueReferences; // all value references
+
+ string lastErrorMessage;
+
+ FMU fmu;
+};
+
+vector<FMI1> fmus;
+
+//map<string,FMUControlStruct> 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<string,FMUControlStruct>::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) {
+
+ 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;i<variableCount;i++) {
+ fmi1.variables.push_back(string(vars[i].name));
+ if(vars[i].description)
+ fmi1.descriptions.push_back(string(vars[i].description));
+ else
+ fmi1.descriptions.push_back(string(""));
+ if(vars[i].declaredType)
+ fmi1.declaredTypes.push_back(string(vars[i].declaredType));
+ else
+ fmi1.declaredTypes.push_back(string(""));
+ fmi1.types.push_back(vars[i].type);
+ fmi1.causalities.push_back(vars[i].causality);
+ fmi1.variabilities.push_back(vars[i].variability);
+ fmi1.valueReferences.push_back(vars[i].vr);
+ }
+
+ if (fmi1.version == 1) {
+ types = FMI1_CS_GET_DECLARED_TYPES(fmi1.fmu, &typeCount, &error);
+ } else if (fmi1.version == 2) {
+ types = FMI2_CS_GET_DECLARED_TYPES(fmi1.fmu, &typeCount, &error);
+ }
+ if (!isEmpty(error)) {
+ string message = "Could not get declared types ";
+ return throwFMILException(env, message += error);
+ }
+
+ for(int i=0;i<typeCount;i++) {
+ fmi1.declaredTypeNames.push_back(string(types[i].name));
+ if(types[i].description)
+ fmi1.typeDescriptions.push_back(string(types[i].description));
+ else
+ fmi1.typeDescriptions.push_back(string(""));
+ if(types[i].quantity)
+ fmi1.quantities.push_back(string(types[i].quantity));
+ else
+ fmi1.quantities.push_back(string(""));
+ if(types[i].unit)
+ fmi1.units.push_back(string(types[i].unit));
+ else
+ fmi1.units.push_back(string(""));
+ }
+
+
+ fmus.push_back(fmi1);
+
+ env->ReleaseStringUTFChars(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<string,int>::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 = "";
+
+ 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(unsigned int i=0;i<fmus[id].variables.size();i++) {
+ env->SetObjectArrayElement(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(unsigned int i=0;i<fmus[id].descriptions.size();i++) {
+ env->SetObjectArrayElement(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(unsigned int i=0;i<fmus[id].declaredTypes.size();i++) {
+ env->SetObjectArrayElement(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);
+
+ for (jsize 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);
+
+ for (jsize 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(unsigned int i=0;i<fmus[id].declaredTypeNames.size();i++) {
+ env->SetObjectArrayElement(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(unsigned int i=0;i<fmus[id].typeDescriptions.size();i++) {
+ env->SetObjectArrayElement(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(unsigned int i=0;i<fmus[id].quantities.size();i++) {
+ env->SetObjectArrayElement(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(unsigned int i=0;i<fmus[id].units.size();i++) {
+ env->SetObjectArrayElement(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<fmuStruct.nx; i++)
+ fmuStruct.x[i] += dt*fmuStruct.xdot[i]; // forward Euler method
+
+ fmiFlag = fmu.setContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);
+ if (fmiFlag > 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<fmuStruct.nz; i++) fmuStruct.prez[i] = fmuStruct.z[i];
+ fmiFlag = fmu.getEventIndicators(fmuStruct.c, fmuStruct.z, fmuStruct.nz);
+ if (fmiFlag > fmiWarning) return throwException(env, "could not retrieve event indicators");
+ stateEvent = FALSE;
+ for (i=0; i<fmuStruct.nz; i++)
+ stateEvent = stateEvent || (fmuStruct.prez[i] * fmuStruct.z[i] < 0);
+
+
+ stepEvent = fmiTrue;
+ // handle events
+ if (timeEvent || stateEvent || stepEvent) {
+
+ // event iteration in one step, ignoring intermediate results
+ fmiFlag = fmu.eventUpdate(fmuStruct.c, fmiFalse, &(fmuStruct.eventInfo));
+ if (fmiFlag > 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;
+
+}