1 /* -------------------------------------------------------------------------
3 * Simulation controls for fmus
5 * Free libraries and tools used to implement this simulator:
6 * - header files from the FMU specification
7 * - eXpat 2.0.1 XML parser, see http://expat.sourceforge.net
8 * - 7z.exe 4.57 zip and unzip tool, see http://www.7-zip.org <---------- Replace with zlib
9 * Author: Teemu Lempinen
10 * Copyright 2012 Semantum Oy
11 * -------------------------------------------------------------------------
23 #include <org_simantics_fmil_FMILJNI.h>
27 #include "sim_support.h"
32 #define PRINT(fmt,args) { FILE *fp = fopen("R:\\Simantics\\Sysdyn\\log.txt", "ab"); fprintf(fp, fmt, args); fclose(fp); }
40 vector<string> variables;
41 vector<string> descriptions;
42 vector<string> declaredTypes;
43 vector<int> valueReferences;
45 vector<int> variabilities;
46 vector<int> causalities;
48 vector<string> declaredTypeNames;
49 vector<string> typeDescriptions;
50 vector<string> quantities;
53 vector<int> subscription;
61 struct FMUControlStruct {
62 double step; // simulation step length
63 fmiReal currentTime; // current simulation time
65 fmiComponent c; // instance of the fmu
66 ScalarVariable** vars; // model variables
68 fmiEventInfo eventInfo; // updated by calls to initialize and eventUpdate
69 const char* guid; // global unique id of the fmu
70 fmiCallbackFunctions callbacks; // called by the model during simulation
71 fmiStatus fmiFlag; // return code of the fmu functions
73 map<string,int> indexes; // indexes for variable names in vars-table
74 map<string,int>::iterator it;
76 int nx; // number of state variables
77 double *x; // continuous states
78 double *xdot; // the crresponding derivatives in same order
79 int nz; // number of state event indicators
80 double *z; // state event indicators
81 double *prez; // previous values of state event indicators
83 bool initialized; // has the fmu been initialized
85 vector<fmiValueReference> subscription; // result subscriptions
86 vector<string> allVariables; // all variables in an initialized model
87 vector<fmiValueReference> fmiValueReferences; // all value references
89 string lastErrorMessage;
96 //map<string,FMUControlStruct> fmus; // indexes for variable names in vars-table
98 int throwFMILException(JNIEnv *env, string message) {
100 newExcCls = env->FindClass("org/simantics/fmil/core/FMILException");
101 if (newExcCls == NULL) {
102 newExcCls = env->FindClass("java/lang/Exception");
104 if (newExcCls == NULL) {
105 /* Unable to find the exception class, give up. */
108 env->ThrowNew(newExcCls, message.c_str());
112 int throwException(JNIEnv *env, string message) {
113 return throwFMILException(env, message);
116 bool isEmpty(const char *c) {
127 bool exists(string id) {
128 map<string,FMUControlStruct>::iterator it = fmus.find(id);
129 if(it != fmus.end()) {
139 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_loadFMUFile_1
140 (JNIEnv *env, jobject obj, jstring path, jstring tempDir) {
144 FMIL_DeclaredType *types;
148 int variableCount = 0;
152 const char *error = "";
154 const char *fmuPath = env->GetStringUTFChars(path, 0);
155 const char *fmuTempDir = env->GetStringUTFChars(tempDir, 0);
157 fmi1.currentTime = 0;
159 returnValue = FMI_CS_LOAD(fmuPath, fmuTempDir, &fmi1.fmu, &fmuVersion, &error);
161 if (returnValue != 0) {
162 string message = "Could not load FMU: ";
163 return throwFMILException(env, message += error);
166 string message = "No FMU loaded: ";
167 return throwFMILException(env, message += error);
170 fmi1.version = fmuVersion;
171 if (fmi1.version == 1) {
172 vars = FMI1_CS_GET_VARIABLES(fmi1.fmu, &variableCount, &error);
173 } else if (fmi1.version == 2) {
174 vars = FMI2_CS_GET_VARIABLES(fmi1.fmu, &variableCount, &error);
176 if (!isEmpty(error)) {
177 string message = "Could not get variables ";
178 return throwFMILException(env, message += error);
181 for(int i=0;i<variableCount;i++) {
182 fmi1.variables.push_back(string(vars[i].name));
183 if(vars[i].description)
184 fmi1.descriptions.push_back(string(vars[i].description));
186 fmi1.descriptions.push_back(string(""));
187 if(vars[i].declaredType)
188 fmi1.declaredTypes.push_back(string(vars[i].declaredType));
190 fmi1.declaredTypes.push_back(string(""));
191 fmi1.types.push_back(vars[i].type);
192 fmi1.causalities.push_back(vars[i].causality);
193 fmi1.variabilities.push_back(vars[i].variability);
194 fmi1.valueReferences.push_back(vars[i].vr);
197 if (fmi1.version == 1) {
198 types = FMI1_CS_GET_DECLARED_TYPES(fmi1.fmu, &typeCount, &error);
199 } else if (fmi1.version == 2) {
200 types = FMI2_CS_GET_DECLARED_TYPES(fmi1.fmu, &typeCount, &error);
202 if (!isEmpty(error)) {
203 string message = "Could not get declared types ";
204 return throwFMILException(env, message += error);
207 for(int i=0;i<typeCount;i++) {
208 fmi1.declaredTypeNames.push_back(string(types[i].name));
209 if(types[i].description)
210 fmi1.typeDescriptions.push_back(string(types[i].description));
212 fmi1.typeDescriptions.push_back(string(""));
213 if(types[i].quantity)
214 fmi1.quantities.push_back(string(types[i].quantity));
216 fmi1.quantities.push_back(string(""));
218 fmi1.units.push_back(string(types[i].unit));
220 fmi1.units.push_back(string(""));
224 fmus.push_back(fmi1);
226 env->ReleaseStringUTFChars(path, fmuPath);
227 env->ReleaseStringUTFChars(tempDir, fmuTempDir);
229 return fmus.size() - 1;
233 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setStepLength_1
234 (JNIEnv *env, jobject obj, jint id, jdouble stepLength) {
235 fmus[id].timeStep = stepLength;
239 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_subscribe_1
240 (JNIEnv *env, jobject obj, jint id, jintArray vrs) {
243 jint* elements = env -> GetIntArrayElements(vrs, &isCopy);
244 jsize n = env -> GetArrayLength(vrs);
247 for (i = 0; i < n; i++) {
248 fmus[id].subscription.push_back(elements[i]);
251 if (isCopy == JNI_TRUE) {
252 env -> ReleaseIntArrayElements(vrs, elements, 0);
259 bool referenceExists(FMUControlStruct fmuStruct, string variable) {
260 map<string,int>::iterator it = fmuStruct.indexes.find(variable);
261 if(it != fmuStruct.indexes.end()) {
268 // Remember to check if reference exists
269 fmiValueReference getReference(FMUControlStruct fmuStruct, string variable) {
270 return fmuStruct.fmiValueReferences[fmuStruct.indexes[variable]];
273 // Get string representation of a scalar variable type
274 string getTypeString(ScalarVariable* sv) {
275 switch (sv->typeSpec->type){
278 case elm_Enumeration:
279 return "Enumeration";
289 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setRealValue_1
290 (JNIEnv *env, jobject obj, jint id, jint vr, jdouble value) {
292 const char *error = "";
294 if (fmi.version == 1) {
295 FMI1_CS_SET_REAL(fmi.fmu, vr, value, &error);
296 } else if (fmi.version == 2) {
297 FMI2_CS_SET_REAL(fmi.fmu, vr, value, &error);
299 if (!isEmpty(error)) {
300 string message = "Could not set real value ";
301 return throwFMILException(env, message += error);
306 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setIntegerValue_1
307 (JNIEnv *env, jobject obj, jstring id, jstring parameter, jint value) {
309 const char *fmuId = env->GetStringUTFChars(id, 0);
311 FMUControlStruct& fmuStruct = fmus[fmuId];
312 const char *name = env->GetStringUTFChars(parameter, 0);
313 string nameString = name;
314 string modelId = fmuId;
315 if(!referenceExists(fmuStruct, name)) {
316 string errorMessage = "setIntegerValue: Model (id " + modelId + ") does not contain variable: " + nameString;
317 env->ReleaseStringUTFChars(parameter, name);
318 env->ReleaseStringUTFChars(id, fmuId);
319 return throwException(env, errorMessage);
321 // Check variable type
322 ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]];
323 switch (sv->typeSpec->type){
327 string errorMessage = "setIntegerValue: " + nameString + " is not of type Integer. (type: + " + getTypeString(sv) + ")";
328 env->ReleaseStringUTFChars(parameter, name);
329 env->ReleaseStringUTFChars(id, fmuId);
330 return throwException(env, errorMessage);
335 fmiValueReference vr = getReference(fmuStruct, name);
336 const int intValue = (int) value;
337 fmuStruct.fmu.setInteger(fmuStruct.c, &vr, 1, &intValue);
338 env->ReleaseStringUTFChars(parameter, name);
339 env->ReleaseStringUTFChars(id, fmuId);
343 string message = fmuId;
344 env->ReleaseStringUTFChars(id, fmuId);
345 return throwException(env, "setIntegerValue: Model id " + message + " not found");
351 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setBooleanValue_1
352 (JNIEnv *env, jobject obj, jstring id, jstring parameter, jboolean value) {
354 const char *fmuId = env->GetStringUTFChars(id, 0);
356 FMUControlStruct& fmuStruct = fmus[fmuId];
357 const char *name = env->GetStringUTFChars(parameter, 0);
358 string nameString = name;
359 string modelId = fmuId;
360 if(!referenceExists(fmuStruct, name)) {
361 string errorMessage = "setBooleanValue: Model (id " + modelId + ") does not contain variable: " + nameString;
362 env->ReleaseStringUTFChars(parameter, name);
363 env->ReleaseStringUTFChars(id, fmuId);
364 return throwException(env, errorMessage);
366 // Check variable type
367 ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]];
368 switch (sv->typeSpec->type){
372 string errorMessage = "setBooleanValue: " + nameString + " is not of type Boolean. (type: + " + getTypeString(sv) + ")";
373 env->ReleaseStringUTFChars(parameter, name);
374 env->ReleaseStringUTFChars(id, fmuId);
375 return throwException(env, errorMessage);
380 fmiValueReference vr = getReference(fmuStruct, name);
381 fmiBoolean result = 1;
384 fmuStruct.fmu.setBoolean(fmuStruct.c, &vr, 1, &result);
385 env->ReleaseStringUTFChars(parameter, name);
386 env->ReleaseStringUTFChars(id, fmuId);
390 string message = fmuId;
391 env->ReleaseStringUTFChars(id, fmuId);
392 return throwException(env, "setBooleanValue: Model id " + message + " not found");
397 JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_isInitialized_1
398 (JNIEnv *env, jobject obj, jstring id) {
400 const char *fmuId = env->GetStringUTFChars(id, 0);
402 FMUControlStruct& fmuStruct = fmus[fmuId];
403 env->ReleaseStringUTFChars(id, fmuId);
404 return fmuStruct.initialized;
406 env->ReleaseStringUTFChars(id, fmuId);
414 JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getTime_1
415 (JNIEnv *env, jobject obj, jint id) {
416 return fmus[id].currentTime;
419 double getRealValue(FMUControlStruct fmuStruct, int index) {
420 ScalarVariable *sv = fmuStruct.vars[index];
421 fmiValueReference vr = fmuStruct.fmiValueReferences[index];
426 switch (sv->typeSpec->type){
428 fmuStruct.fmu.getReal(fmuStruct.c, &vr, 1, &real);
431 case elm_Enumeration:
432 fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &integer);
433 real = (double)integer;
436 fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &fmibool);
437 if(fmibool == fmiTrue)
446 JNIEXPORT jdoubleArray JNICALL Java_org_simantics_fmil_core_FMIL_getSubscribedResults_1
447 (JNIEnv *env, jobject obj, jint id, jdoubleArray result) {
450 jdouble* resultElements = env -> GetDoubleArrayElements(result, &isCopy);
451 jsize n = env -> GetArrayLength(result);
453 const char *error = "";
457 vrs = &(fmus[id].subscription[0]);
458 if (fmi.version == 1) {
459 FMI1_CS_GET_REALS(fmi.fmu, vrs, resultElements, n, &error);
460 } else if (fmi.version == 2) {
461 FMI2_CS_GET_REALS(fmi.fmu, vrs, resultElements, n, &error);
464 if (isCopy == JNI_TRUE) {
465 env -> ReleaseDoubleArrayElements(result, resultElements, 0);
472 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_instantiateSimulation_1
473 (JNIEnv *env, jobject obj, jint id) {
476 const char *error = "";
478 FMI1 &fmi = fmus[id];
479 if (fmi.version == 1) {
480 returnValue = FMI1_CS_INSTANTIATE(fmi.fmu, "", &error);
481 } else if (fmi.version == 2) {
482 returnValue = FMI2_CS_INSTANTIATE(fmi.fmu, "", &error);
484 if(returnValue != 0) {
485 string message = "No FMU loaded: ";
486 return throwFMILException(env, message += error);
491 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_initializeSimulation_1
492 (JNIEnv *env, jobject obj, jint id) {
494 const char *error = "";
497 if (fmi.version == 1) {
498 returnValue = FMI1_CS_INITIALIZE(fmi.fmu, &error);
499 } else if (fmi.version == 2) {
500 returnValue = FMI2_CS_INITIALIZE(fmi.fmu, &error);
502 if(returnValue != 0) {
503 string message = "Could not initialize simulation: ";
504 return throwFMILException(env, message += error);
511 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setTime_1
512 (JNIEnv *env, jobject obj, jstring id, jdouble time) {
516 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariables_1
517 (JNIEnv *env, jobject obj, jint id) {
519 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].variables.size(),
520 env->FindClass("java/lang/String"),
521 env->NewStringUTF(""));
523 for(unsigned int i=0;i<fmus[id].variables.size();i++) {
524 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].variables[i].c_str()));
531 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDescriptions_1
532 (JNIEnv *env, jobject obj, jint id) {
534 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].descriptions.size(),
535 env->FindClass("java/lang/String"),
536 env->NewStringUTF(""));
538 for(unsigned int i=0;i<fmus[id].descriptions.size();i++) {
539 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].descriptions[i].c_str()));
546 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDeclaredTypes_1
547 (JNIEnv *env, jobject obj, jint id) {
549 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypes.size(),
550 env->FindClass("java/lang/String"),
551 env->NewStringUTF(""));
553 for(unsigned int i=0;i<fmus[id].declaredTypes.size();i++) {
554 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypes[i].c_str()));
561 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableReferences_1
562 (JNIEnv *env, jobject obj, jint id, jintArray result) {
565 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
566 jsize n = env -> GetArrayLength(result);
569 for (i = 0; i < n; i++) {
570 resultElements[i] = fmus[id].valueReferences[i];
573 if (isCopy == JNI_TRUE) {
574 env -> ReleaseIntArrayElements(result, resultElements, 0);
581 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableTypes_1
582 (JNIEnv *env, jobject obj, jint id, jintArray result) {
585 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
586 jsize n = env -> GetArrayLength(result);
589 for (i = 0; i < n; i++) {
590 resultElements[i] = fmus[id].types[i];
593 if (isCopy == JNI_TRUE) {
594 env -> ReleaseIntArrayElements(result, resultElements, 0);
601 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableVariabilities_1
602 (JNIEnv *env, jobject obj, jint id, jintArray result) {
605 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
606 jsize n = env -> GetArrayLength(result);
608 for (jsize i = 0; i < n; i++) {
609 resultElements[i] = fmus[id].variabilities[i];
612 if (isCopy == JNI_TRUE) {
613 env -> ReleaseIntArrayElements(result, resultElements, 0);
620 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableCausalities_1
621 (JNIEnv *env, jobject obj, jint id, jintArray result) {
624 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
625 jsize n = env -> GetArrayLength(result);
627 for (jsize i = 0; i < n; i++) {
628 resultElements[i] = fmus[id].causalities[i];
631 if (isCopy == JNI_TRUE) {
632 env -> ReleaseIntArrayElements(result, resultElements, 0);
639 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypes_1
640 (JNIEnv *env, jobject obj, jint id) {
642 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypeNames.size(),
643 env->FindClass("java/lang/String"),
644 env->NewStringUTF(""));
646 for(unsigned int i=0;i<fmus[id].declaredTypeNames.size();i++) {
647 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypeNames[i].c_str()));
654 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeDescriptions_1
655 (JNIEnv *env, jobject obj, jint id) {
657 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].typeDescriptions.size(),
658 env->FindClass("java/lang/String"),
659 env->NewStringUTF(""));
661 for(unsigned int i=0;i<fmus[id].typeDescriptions.size();i++) {
662 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].typeDescriptions[i].c_str()));
669 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeQuantities_1
670 (JNIEnv *env, jobject obj, jint id) {
672 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].quantities.size(),
673 env->FindClass("java/lang/String"),
674 env->NewStringUTF(""));
676 for(unsigned int i=0;i<fmus[id].quantities.size();i++) {
677 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].quantities[i].c_str()));
684 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeUnits_1
685 (JNIEnv *env, jobject obj, jint id) {
687 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].units.size(),
688 env->FindClass("java/lang/String"),
689 env->NewStringUTF(""));
691 for(unsigned int i=0;i<fmus[id].units.size();i++) {
692 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].units[i].c_str()));
700 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_filterVariables_1
701 (JNIEnv *env, jobject obj, jstring id, jstring regexp) {
702 const char *rx = env->GetStringUTFChars(regexp, 0);
703 jobjectArray result = filterVariables(env, obj, id, rx);
704 env->ReleaseStringUTFChars(regexp, rx);
709 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_simulateStep_1
710 (JNIEnv *env, jobject obj, jint id) {
713 const char *error = "";
715 FMI1 &fmi = fmus[id];
716 if (fmi.version == 1) {
717 returnValue = FMI1_CS_STEP(fmi.fmu, fmi.currentTime, fmi.timeStep, &error);
718 } else if (fmi.version == 2) {
719 returnValue = FMI2_CS_STEP(fmi.fmu, fmi.currentTime, fmi.timeStep, &error);
721 if(returnValue != 0) {
722 string message = "Could not simulate step: ";
723 return throwException(env, message += error);
726 fmi.currentTime += fmi.timeStep;
731 const char *fmuId = env->GetStringUTFChars(id, 0);
733 FMUControlStruct& fmuStruct = fmus[fmuId];
734 env->ReleaseStringUTFChars(id, fmuId);
736 if(&fmuStruct.fmu == NULL || fmuStruct.fmu.modelDescription == NULL || &fmuStruct.vars == NULL) {
737 return throwException(env, "Simulate step failed - fmu not loaded");
740 if(fmuStruct.x == NULL) {
741 return throwException(env, "Simulate step failed - fmu not instantiated");
744 if(fmuStruct.initialized == false) {
745 fmiBoolean toleranceControlled = fmiFalse;
746 fmuStruct.fmiFlag = fmuStruct.fmu.initialize(fmuStruct.c, toleranceControlled, fmuStruct.currentTime, &(fmuStruct.eventInfo));
747 if (fmuStruct.fmiFlag > fmiWarning) return throwException(env, "could not initialize model");
748 fmuStruct.initialized = true;
751 FMU& fmu = fmuStruct.fmu;
752 int debug = 0; // DEBUG ON = 1, OFF = 0
755 double dt, tPre, tEnd = fmuStruct.currentTime + fmuStruct.step;
757 fmiBoolean timeEvent, stateEvent, stepEvent;
758 fmiStatus fmiFlag; // return code of the fmu functions
759 fmiValueReference vr;
763 /* Simulate the duration of one step. The simulation may be done in
764 * multiple parts if events occur
766 while (fmuStruct.currentTime < tEnd) {
767 // get current state and derivatives
768 fmiFlag = fmu.getContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);
769 if (fmiFlag > fmiWarning)
770 return throwException(env, "could not retrieve states");
772 fmiFlag = fmu.getDerivatives(fmuStruct.c, fmuStruct.xdot, fmuStruct.nx);
773 if (fmiFlag > fmiWarning)
774 return throwException(env, "could not retrieve derivatives");
777 tPre = fmuStruct.currentTime;
778 fmuStruct.currentTime = min(fmuStruct.currentTime+fmuStruct.step, tEnd);
779 timeEvent = fmuStruct.eventInfo.upcomingTimeEvent && fmuStruct.eventInfo.nextEventTime < fmuStruct.currentTime;
781 if (timeEvent) fmuStruct.currentTime = fmuStruct.eventInfo.nextEventTime;
782 dt = fmuStruct.currentTime - tPre;
783 fmiFlag = fmu.setTime(fmuStruct.c, fmuStruct.currentTime);
784 if (fmiFlag > fmiWarning) throwException(env, "could not set time");
786 if(referenceExists(fmuStruct, "time")) {
787 vr = getReference(fmuStruct, "time");
789 fmu.setReal(fmuStruct.c, &vr, 1, &(fmuStruct.currentTime));
794 printf("Actual time: %lf\n", fmuStruct.currentTime);
796 if (fmiFlag > fmiWarning)
797 return throwException(env, "could not set time");
800 for (i=0; i<fmuStruct.nx; i++)
801 fmuStruct.x[i] += dt*fmuStruct.xdot[i]; // forward Euler method
803 fmiFlag = fmu.setContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);
804 if (fmiFlag > fmiWarning)
805 return throwException(env, "could not set states");
807 // Check for step event, e.g. dynamic state selection
808 fmiFlag = fmu.completedIntegratorStep(fmuStruct.c, &stepEvent);
809 if (fmiFlag > fmiWarning) return throwException(env, "could not complete intgrator step");
811 /* for (i=0; i<fmuStruct.nz; i++) fmuStruct.prez[i] = fmuStruct.z[i];
812 fmiFlag = fmu.getEventIndicators(fmuStruct.c, fmuStruct.z, fmuStruct.nz);
813 if (fmiFlag > fmiWarning) return throwException(env, "could not retrieve event indicators");
815 for (i=0; i<fmuStruct.nz; i++)
816 stateEvent = stateEvent || (fmuStruct.prez[i] * fmuStruct.z[i] < 0);
821 if (timeEvent || stateEvent || stepEvent) {
823 // event iteration in one step, ignoring intermediate results
824 fmiFlag = fmu.eventUpdate(fmuStruct.c, fmiFalse, &(fmuStruct.eventInfo));
825 if (fmiFlag > fmiWarning) return throwException(env, "could not perform event update");
836 string message = fmuId;
837 env->ReleaseStringUTFChars(id, fmuId);
838 return throwException(env, "simulateStep: Model id " + message + " not found");
843 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_unloadFMU_1
844 (JNIEnv *env, jobject obj, jint id) {
847 const char *error = "";
850 if (fmi.version == 1) {
851 returnValue = FMI1_CS_UNLOAD(fmi.fmu, &error);
852 } else if (fmi.version == 2) {
853 returnValue = FMI2_CS_UNLOAD(fmi.fmu, &error);
855 if(returnValue != 0) {
856 string message = "Could not unload FMU: ";
857 return throwException(env, message += error);
862 JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getRealValue_1
863 (JNIEnv *env, jobject obj, jint id, jint vr) {
866 const char *error = "";
869 if (fmi.version == 1) {
870 value = FMI1_CS_GET_REAL(fmi.fmu, vr, &error);
871 } else if (fmi.version == 2) {
872 value = FMI2_CS_GET_REAL(fmi.fmu, vr, &error);
874 if (!isEmpty(error)) {
875 string message = "Could not get real value: ";
876 return throwFMILException(env, message += error);
881 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_getIntegerValue_1
882 (JNIEnv *env, jobject obj, jstring id, jstring variable) {
884 const char *fmuId = env->GetStringUTFChars(id, 0);
886 FMUControlStruct fmuStruct = fmus[fmuId];
887 env->ReleaseStringUTFChars(id, fmuId);
888 const char *name = env->GetStringUTFChars(variable, 0);
890 if(referenceExists(fmuStruct, name)) {
891 fmiValueReference vr = getReference(fmuStruct, name);
893 fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &result);
894 env->ReleaseStringUTFChars(variable, name);
898 string nameString = name;
899 string message = "Variable " + nameString + " not found";
900 env->ReleaseStringUTFChars(variable, name);
901 return throwException(env, message);
905 string message = fmuId;
906 env->ReleaseStringUTFChars(id, fmuId);
907 return throwException(env, "unloadFMU: Model id " + message + " not found");
914 JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_getBooleanValue_1
915 (JNIEnv *env, jobject obj, jstring id, jstring variable) {
917 const char *fmuId = env->GetStringUTFChars(id, 0);
919 FMUControlStruct fmuStruct = fmus[fmuId];
920 env->ReleaseStringUTFChars(id, fmuId);
921 const char *name = env->GetStringUTFChars(variable, 0);
923 if(referenceExists(fmuStruct, name)) {
924 fmiValueReference vr = getReference(fmuStruct, name);
926 fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &result);
927 env->ReleaseStringUTFChars(variable, name);
931 string nameString = name;
932 string message = "Variable " + nameString + " not found";
933 env->ReleaseStringUTFChars(variable, name);
934 return throwException(env, message);
938 string message = fmuId;
939 env->ReleaseStringUTFChars(id, fmuId);
940 return throwException(env, "unloadFMU: Model id " + message + " not found");
946 JNIEXPORT jstring JNICALL Java_org_simantics_fmil_core_FMIL_getStringValue_1
947 (JNIEnv *env, jobject obj, jstring id, jstring variable) {
949 const char *fmuId = env->GetStringUTFChars(id, 0);
951 FMUControlStruct fmuStruct = fmus[fmuId];
952 env->ReleaseStringUTFChars(id, fmuId);
953 const char *name = env->GetStringUTFChars(variable, 0);
955 if(referenceExists(fmuStruct, name)) {
956 fmiValueReference vr = getReference(fmuStruct, name);
958 fmuStruct.fmu.getString(fmuStruct.c, &vr, 1, &result);
959 env->ReleaseStringUTFChars(variable, name);
960 return env->NewStringUTF(result);
963 string nameString = name;
964 string message = "Variable " + nameString + " not found";
965 env->ReleaseStringUTFChars(variable, name);
966 return 0; //throwException(env, message);
970 string message = fmuId;
971 env->ReleaseStringUTFChars(id, fmuId);
972 return 0; //throwException(env, "unloadFMU: Model id " + message + " not found");