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); }
35 #define GetCurrentDir _getcwd
43 vector<string> variables;
44 vector<string> descriptions;
45 vector<string> declaredTypes;
46 vector<int> valueReferences;
48 vector<int> variabilities;
49 vector<int> causalities;
51 vector<string> declaredTypeNames;
52 vector<string> typeDescriptions;
53 vector<string> quantities;
56 vector<int> subscription;
64 struct FMUControlStruct {
65 double step; // simulation step length
66 fmiReal currentTime; // current simulation time
68 fmiComponent c; // instance of the fmu
69 ScalarVariable** vars; // model variables
71 fmiEventInfo eventInfo; // updated by calls to initialize and eventUpdate
72 const char* guid; // global unique id of the fmu
73 fmiCallbackFunctions callbacks; // called by the model during simulation
74 fmiStatus fmiFlag; // return code of the fmu functions
76 map<string,int> indexes; // indexes for variable names in vars-table
77 map<string,int>::iterator it;
79 int nx; // number of state variables
80 double *x; // continuous states
81 double *xdot; // the crresponding derivatives in same order
82 int nz; // number of state event indicators
83 double *z; // state event indicators
84 double *prez; // previous values of state event indicators
86 bool initialized; // has the fmu been initialized
88 vector<fmiValueReference> subscription; // result subscriptions
89 vector<string> allVariables; // all variables in an initialized model
90 vector<fmiValueReference> fmiValueReferences; // all value references
92 string lastErrorMessage;
99 //map<string,FMUControlStruct> fmus; // indexes for variable names in vars-table
101 int throwFMILException(JNIEnv *env, string message) {
103 newExcCls = env->FindClass("org/simantics/fmil/core/FMILException");
104 if (newExcCls == NULL) {
105 newExcCls = env->FindClass("java/lang/Exception");
107 if (newExcCls == NULL) {
108 /* Unable to find the exception class, give up. */
111 env->ThrowNew(newExcCls, message.c_str());
115 int throwException(JNIEnv *env, string message) {
116 return throwFMILException(env, message);
119 bool isEmpty(const char *c) {
130 bool exists(string id) {
131 map<string,FMUControlStruct>::iterator it = fmus.find(id);
132 if(it != fmus.end()) {
142 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_loadFMUFile_1
143 (JNIEnv *env, jobject obj, jstring path, jstring tempDir) {
145 HMODULE module = NULL;
148 FMIL_DeclaredType *types;
152 int variableCount = 0;
156 const char *error = "";
158 const char *fmuPath = env->GetStringUTFChars(path, 0);
159 const char *fmuTempDir = env->GetStringUTFChars(tempDir, 0);
161 fmi1.currentTime = 0;
163 returnValue = FMI_CS_LOAD(fmuPath, fmuTempDir, &fmi1.fmu, &fmuVersion, &error);
165 if (returnValue != 0) {
166 string message = "Could not load FMU: ";
167 return throwFMILException(env, message += error);
170 string message = "No FMU loaded: ";
171 return throwFMILException(env, message += error);
174 fmi1.version = fmuVersion;
175 if (fmi1.version == 1) {
176 vars = FMI1_CS_GET_VARIABLES(fmi1.fmu, &variableCount, &error);
177 } else if (fmi1.version == 2) {
178 vars = FMI2_CS_GET_VARIABLES(fmi1.fmu, &variableCount, &error);
180 if (!isEmpty(error)) {
181 string message = "Could not get variables ";
182 return throwFMILException(env, message += error);
185 for(int i=0;i<variableCount;i++) {
186 fmi1.variables.push_back(string(vars[i].name));
187 if(vars[i].description)
188 fmi1.descriptions.push_back(string(vars[i].description));
190 fmi1.descriptions.push_back(string(""));
191 if(vars[i].declaredType)
192 fmi1.declaredTypes.push_back(string(vars[i].declaredType));
194 fmi1.declaredTypes.push_back(string(""));
195 fmi1.types.push_back(vars[i].type);
196 fmi1.causalities.push_back(vars[i].causality);
197 fmi1.variabilities.push_back(vars[i].variability);
198 fmi1.valueReferences.push_back(vars[i].vr);
201 if (fmi1.version == 1) {
202 types = FMI1_CS_GET_DECLARED_TYPES(fmi1.fmu, &typeCount, &error);
203 } else if (fmi1.version == 2) {
204 types = FMI2_CS_GET_DECLARED_TYPES(fmi1.fmu, &typeCount, &error);
206 if (!isEmpty(error)) {
207 string message = "Could not get declared types ";
208 return throwFMILException(env, message += error);
211 for(int i=0;i<typeCount;i++) {
212 fmi1.declaredTypeNames.push_back(string(types[i].name));
213 if(types[i].description)
214 fmi1.typeDescriptions.push_back(string(types[i].description));
216 fmi1.typeDescriptions.push_back(string(""));
217 if(types[i].quantity)
218 fmi1.quantities.push_back(string(types[i].quantity));
220 fmi1.quantities.push_back(string(""));
222 fmi1.units.push_back(string(types[i].unit));
224 fmi1.units.push_back(string(""));
228 fmus.push_back(fmi1);
230 env->ReleaseStringUTFChars(path, fmuPath);
231 env->ReleaseStringUTFChars(tempDir, fmuTempDir);
233 return fmus.size() - 1;
237 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setStepLength_1
238 (JNIEnv *env, jobject obj, jint id, jdouble stepLength) {
239 fmus[id].timeStep = stepLength;
243 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_subscribe_1
244 (JNIEnv *env, jobject obj, jint id, jintArray vrs) {
247 jint* elements = env -> GetIntArrayElements(vrs, &isCopy);
248 jsize n = env -> GetArrayLength(vrs);
251 for (i = 0; i < n; i++) {
252 fmus[id].subscription.push_back(elements[i]);
255 if (isCopy == JNI_TRUE) {
256 env -> ReleaseIntArrayElements(vrs, elements, 0);
263 bool referenceExists(FMUControlStruct fmuStruct, string variable) {
264 map<string,int>::iterator it = fmuStruct.indexes.find(variable);
265 if(it != fmuStruct.indexes.end()) {
272 // Remember to check if reference exists
273 fmiValueReference getReference(FMUControlStruct fmuStruct, string variable) {
274 return fmuStruct.fmiValueReferences[fmuStruct.indexes[variable]];
277 // Get string representation of a scalar variable type
278 string getTypeString(ScalarVariable* sv) {
279 switch (sv->typeSpec->type){
282 case elm_Enumeration:
283 return "Enumeration";
293 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setRealValue_1
294 (JNIEnv *env, jobject obj, jint id, jint vr, jdouble value) {
296 const char *error = "";
298 if (fmi.version == 1) {
299 FMI1_CS_SET_REAL(fmi.fmu, vr, value, &error);
300 } else if (fmi.version == 2) {
301 FMI2_CS_SET_REAL(fmi.fmu, vr, value, &error);
303 if (!isEmpty(error)) {
304 string message = "Could not set real value ";
305 return throwFMILException(env, message += error);
310 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setIntegerValue_1
311 (JNIEnv *env, jobject obj, jstring id, jstring parameter, jint value) {
313 const char *fmuId = env->GetStringUTFChars(id, 0);
315 FMUControlStruct& fmuStruct = fmus[fmuId];
316 const char *name = env->GetStringUTFChars(parameter, 0);
317 string nameString = name;
318 string modelId = fmuId;
319 if(!referenceExists(fmuStruct, name)) {
320 string errorMessage = "setIntegerValue: Model (id " + modelId + ") does not contain variable: " + nameString;
321 env->ReleaseStringUTFChars(parameter, name);
322 env->ReleaseStringUTFChars(id, fmuId);
323 return throwException(env, errorMessage);
325 // Check variable type
326 ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]];
327 switch (sv->typeSpec->type){
331 string errorMessage = "setIntegerValue: " + nameString + " is not of type Integer. (type: + " + getTypeString(sv) + ")";
332 env->ReleaseStringUTFChars(parameter, name);
333 env->ReleaseStringUTFChars(id, fmuId);
334 return throwException(env, errorMessage);
339 fmiValueReference vr = getReference(fmuStruct, name);
340 const int intValue = (int) value;
341 fmuStruct.fmu.setInteger(fmuStruct.c, &vr, 1, &intValue);
342 env->ReleaseStringUTFChars(parameter, name);
343 env->ReleaseStringUTFChars(id, fmuId);
347 string message = fmuId;
348 env->ReleaseStringUTFChars(id, fmuId);
349 return throwException(env, "setIntegerValue: Model id " + message + " not found");
355 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setBooleanValue_1
356 (JNIEnv *env, jobject obj, jstring id, jstring parameter, jboolean value) {
358 const char *fmuId = env->GetStringUTFChars(id, 0);
360 FMUControlStruct& fmuStruct = fmus[fmuId];
361 const char *name = env->GetStringUTFChars(parameter, 0);
362 string nameString = name;
363 string modelId = fmuId;
364 if(!referenceExists(fmuStruct, name)) {
365 string errorMessage = "setBooleanValue: Model (id " + modelId + ") does not contain variable: " + nameString;
366 env->ReleaseStringUTFChars(parameter, name);
367 env->ReleaseStringUTFChars(id, fmuId);
368 return throwException(env, errorMessage);
370 // Check variable type
371 ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]];
372 switch (sv->typeSpec->type){
376 string errorMessage = "setBooleanValue: " + nameString + " is not of type Boolean. (type: + " + getTypeString(sv) + ")";
377 env->ReleaseStringUTFChars(parameter, name);
378 env->ReleaseStringUTFChars(id, fmuId);
379 return throwException(env, errorMessage);
384 fmiValueReference vr = getReference(fmuStruct, name);
385 fmiBoolean result = 1;
388 fmuStruct.fmu.setBoolean(fmuStruct.c, &vr, 1, &result);
389 env->ReleaseStringUTFChars(parameter, name);
390 env->ReleaseStringUTFChars(id, fmuId);
394 string message = fmuId;
395 env->ReleaseStringUTFChars(id, fmuId);
396 return throwException(env, "setBooleanValue: Model id " + message + " not found");
401 JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_isInitialized_1
402 (JNIEnv *env, jobject obj, jstring id) {
404 const char *fmuId = env->GetStringUTFChars(id, 0);
406 FMUControlStruct& fmuStruct = fmus[fmuId];
407 env->ReleaseStringUTFChars(id, fmuId);
408 return fmuStruct.initialized;
410 env->ReleaseStringUTFChars(id, fmuId);
418 JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getTime_1
419 (JNIEnv *env, jobject obj, jint id) {
420 return fmus[id].currentTime;
423 double getRealValue(FMUControlStruct fmuStruct, int index) {
424 ScalarVariable *sv = fmuStruct.vars[index];
425 fmiValueReference vr = fmuStruct.fmiValueReferences[index];
430 switch (sv->typeSpec->type){
432 fmuStruct.fmu.getReal(fmuStruct.c, &vr, 1, &real);
435 case elm_Enumeration:
436 fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &integer);
437 real = (double)integer;
440 fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &fmibool);
441 if(fmibool == fmiTrue)
450 JNIEXPORT jdoubleArray JNICALL Java_org_simantics_fmil_core_FMIL_getSubscribedResults_1
451 (JNIEnv *env, jobject obj, jint id, jdoubleArray result) {
454 jdouble* resultElements = env -> GetDoubleArrayElements(result, &isCopy);
455 jsize n = env -> GetArrayLength(result);
457 const char *error = "";
462 vrs = &(fmus[id].subscription[0]);
463 if (fmi.version == 1) {
464 FMI1_CS_GET_REALS(fmi.fmu, vrs, resultElements, n, &error);
465 } else if (fmi.version == 2) {
466 FMI2_CS_GET_REALS(fmi.fmu, vrs, resultElements, n, &error);
469 if (isCopy == JNI_TRUE) {
470 env -> ReleaseDoubleArrayElements(result, resultElements, 0);
477 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_instantiateSimulation_1
478 (JNIEnv *env, jobject obj, jint id) {
481 const char *error = "";
483 FMI1 &fmi = fmus[id];
484 if (fmi.version == 1) {
485 returnValue = FMI1_CS_INSTANTIATE(fmi.fmu, "", &error);
486 } else if (fmi.version == 2) {
487 returnValue = FMI2_CS_INSTANTIATE(fmi.fmu, "", &error);
489 if(returnValue != 0) {
490 string message = "No FMU loaded: ";
491 return throwFMILException(env, message += error);
496 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_initializeSimulation_1
497 (JNIEnv *env, jobject obj, jint id) {
499 const char *error = "";
502 if (fmi.version == 1) {
503 returnValue = FMI1_CS_INITIALIZE(fmi.fmu, &error);
504 } else if (fmi.version == 2) {
505 returnValue = FMI2_CS_INITIALIZE(fmi.fmu, &error);
507 if(returnValue != 0) {
508 string message = "Could not initialize simulation: ";
509 return throwFMILException(env, message += error);
516 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setTime_1
517 (JNIEnv *env, jobject obj, jstring id, jdouble time) {
521 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariables_1
522 (JNIEnv *env, jobject obj, jint id) {
524 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].variables.size(),
525 env->FindClass("java/lang/String"),
526 env->NewStringUTF(""));
528 for(int i=0;i<fmus[id].variables.size();i++) {
529 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].variables[i].c_str()));
536 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDescriptions_1
537 (JNIEnv *env, jobject obj, jint id) {
539 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].descriptions.size(),
540 env->FindClass("java/lang/String"),
541 env->NewStringUTF(""));
543 for(int i=0;i<fmus[id].descriptions.size();i++) {
544 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].descriptions[i].c_str()));
551 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDeclaredTypes_1
552 (JNIEnv *env, jobject obj, jint id) {
554 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypes.size(),
555 env->FindClass("java/lang/String"),
556 env->NewStringUTF(""));
558 for(int i=0;i<fmus[id].declaredTypes.size();i++) {
559 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypes[i].c_str()));
566 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableReferences_1
567 (JNIEnv *env, jobject obj, jint id, jintArray result) {
570 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
571 jsize n = env -> GetArrayLength(result);
574 for (i = 0; i < n; i++) {
575 resultElements[i] = fmus[id].valueReferences[i];
578 if (isCopy == JNI_TRUE) {
579 env -> ReleaseIntArrayElements(result, resultElements, 0);
586 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableTypes_1
587 (JNIEnv *env, jobject obj, jint id, jintArray result) {
590 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
591 jsize n = env -> GetArrayLength(result);
594 for (i = 0; i < n; i++) {
595 resultElements[i] = fmus[id].types[i];
598 if (isCopy == JNI_TRUE) {
599 env -> ReleaseIntArrayElements(result, resultElements, 0);
606 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableVariabilities_1
607 (JNIEnv *env, jobject obj, jint id, jintArray result) {
610 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
611 jsize n = env -> GetArrayLength(result);
614 for (i = 0; i < n; i++) {
615 resultElements[i] = fmus[id].variabilities[i];
618 if (isCopy == JNI_TRUE) {
619 env -> ReleaseIntArrayElements(result, resultElements, 0);
626 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableCausalities_1
627 (JNIEnv *env, jobject obj, jint id, jintArray result) {
630 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
631 jsize n = env -> GetArrayLength(result);
634 for (i = 0; i < n; i++) {
635 resultElements[i] = fmus[id].causalities[i];
638 if (isCopy == JNI_TRUE) {
639 env -> ReleaseIntArrayElements(result, resultElements, 0);
646 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypes_1
647 (JNIEnv *env, jobject obj, jint id) {
649 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypeNames.size(),
650 env->FindClass("java/lang/String"),
651 env->NewStringUTF(""));
653 for(int i=0;i<fmus[id].declaredTypeNames.size();i++) {
654 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypeNames[i].c_str()));
661 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeDescriptions_1
662 (JNIEnv *env, jobject obj, jint id) {
664 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].typeDescriptions.size(),
665 env->FindClass("java/lang/String"),
666 env->NewStringUTF(""));
668 for(int i=0;i<fmus[id].typeDescriptions.size();i++) {
669 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].typeDescriptions[i].c_str()));
676 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeQuantities_1
677 (JNIEnv *env, jobject obj, jint id) {
679 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].quantities.size(),
680 env->FindClass("java/lang/String"),
681 env->NewStringUTF(""));
683 for(int i=0;i<fmus[id].quantities.size();i++) {
684 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].quantities[i].c_str()));
691 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeUnits_1
692 (JNIEnv *env, jobject obj, jint id) {
694 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].units.size(),
695 env->FindClass("java/lang/String"),
696 env->NewStringUTF(""));
698 for(int i=0;i<fmus[id].units.size();i++) {
699 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].units[i].c_str()));
707 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_filterVariables_1
708 (JNIEnv *env, jobject obj, jstring id, jstring regexp) {
709 const char *rx = env->GetStringUTFChars(regexp, 0);
710 jobjectArray result = filterVariables(env, obj, id, rx);
711 env->ReleaseStringUTFChars(regexp, rx);
716 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_simulateStep_1
717 (JNIEnv *env, jobject obj, jint id) {
720 const char *error = "";
722 FMI1 &fmi = fmus[id];
723 if (fmi.version == 1) {
724 returnValue = FMI1_CS_STEP(fmi.fmu, fmi.currentTime, fmi.timeStep, &error);
725 } else if (fmi.version == 2) {
726 returnValue = FMI2_CS_STEP(fmi.fmu, fmi.currentTime, fmi.timeStep, &error);
728 if(returnValue != 0) {
729 string message = "Could not simulate step: ";
730 return throwException(env, message += error);
733 fmi.currentTime += fmi.timeStep;
738 const char *fmuId = env->GetStringUTFChars(id, 0);
740 FMUControlStruct& fmuStruct = fmus[fmuId];
741 env->ReleaseStringUTFChars(id, fmuId);
743 if(&fmuStruct.fmu == NULL || fmuStruct.fmu.modelDescription == NULL || &fmuStruct.vars == NULL) {
744 return throwException(env, "Simulate step failed - fmu not loaded");
747 if(fmuStruct.x == NULL) {
748 return throwException(env, "Simulate step failed - fmu not instantiated");
751 if(fmuStruct.initialized == false) {
752 fmiBoolean toleranceControlled = fmiFalse;
753 fmuStruct.fmiFlag = fmuStruct.fmu.initialize(fmuStruct.c, toleranceControlled, fmuStruct.currentTime, &(fmuStruct.eventInfo));
754 if (fmuStruct.fmiFlag > fmiWarning) return throwException(env, "could not initialize model");
755 fmuStruct.initialized = true;
758 FMU& fmu = fmuStruct.fmu;
759 int debug = 0; // DEBUG ON = 1, OFF = 0
762 double dt, tPre, tEnd = fmuStruct.currentTime + fmuStruct.step;
764 fmiBoolean timeEvent, stateEvent, stepEvent;
765 fmiStatus fmiFlag; // return code of the fmu functions
766 fmiValueReference vr;
770 /* Simulate the duration of one step. The simulation may be done in
771 * multiple parts if events occur
773 while (fmuStruct.currentTime < tEnd) {
774 // get current state and derivatives
775 fmiFlag = fmu.getContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);
776 if (fmiFlag > fmiWarning)
777 return throwException(env, "could not retrieve states");
779 fmiFlag = fmu.getDerivatives(fmuStruct.c, fmuStruct.xdot, fmuStruct.nx);
780 if (fmiFlag > fmiWarning)
781 return throwException(env, "could not retrieve derivatives");
784 tPre = fmuStruct.currentTime;
785 fmuStruct.currentTime = min(fmuStruct.currentTime+fmuStruct.step, tEnd);
786 timeEvent = fmuStruct.eventInfo.upcomingTimeEvent && fmuStruct.eventInfo.nextEventTime < fmuStruct.currentTime;
788 if (timeEvent) fmuStruct.currentTime = fmuStruct.eventInfo.nextEventTime;
789 dt = fmuStruct.currentTime - tPre;
790 fmiFlag = fmu.setTime(fmuStruct.c, fmuStruct.currentTime);
791 if (fmiFlag > fmiWarning) throwException(env, "could not set time");
793 if(referenceExists(fmuStruct, "time")) {
794 vr = getReference(fmuStruct, "time");
796 fmu.setReal(fmuStruct.c, &vr, 1, &(fmuStruct.currentTime));
801 printf("Actual time: %lf\n", fmuStruct.currentTime);
803 if (fmiFlag > fmiWarning)
804 return throwException(env, "could not set time");
807 for (i=0; i<fmuStruct.nx; i++)
808 fmuStruct.x[i] += dt*fmuStruct.xdot[i]; // forward Euler method
810 fmiFlag = fmu.setContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);
811 if (fmiFlag > fmiWarning)
812 return throwException(env, "could not set states");
814 // Check for step event, e.g. dynamic state selection
815 fmiFlag = fmu.completedIntegratorStep(fmuStruct.c, &stepEvent);
816 if (fmiFlag > fmiWarning) return throwException(env, "could not complete intgrator step");
818 /* for (i=0; i<fmuStruct.nz; i++) fmuStruct.prez[i] = fmuStruct.z[i];
819 fmiFlag = fmu.getEventIndicators(fmuStruct.c, fmuStruct.z, fmuStruct.nz);
820 if (fmiFlag > fmiWarning) return throwException(env, "could not retrieve event indicators");
822 for (i=0; i<fmuStruct.nz; i++)
823 stateEvent = stateEvent || (fmuStruct.prez[i] * fmuStruct.z[i] < 0);
828 if (timeEvent || stateEvent || stepEvent) {
830 // event iteration in one step, ignoring intermediate results
831 fmiFlag = fmu.eventUpdate(fmuStruct.c, fmiFalse, &(fmuStruct.eventInfo));
832 if (fmiFlag > fmiWarning) return throwException(env, "could not perform event update");
843 string message = fmuId;
844 env->ReleaseStringUTFChars(id, fmuId);
845 return throwException(env, "simulateStep: Model id " + message + " not found");
850 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_unloadFMU_1
851 (JNIEnv *env, jobject obj, jint id) {
854 const char *error = "";
857 if (fmi.version == 1) {
858 returnValue = FMI1_CS_UNLOAD(fmi.fmu, &error);
859 } else if (fmi.version == 2) {
860 returnValue = FMI2_CS_UNLOAD(fmi.fmu, &error);
862 if(returnValue != 0) {
863 string message = "Could not unload FMU: ";
864 return throwException(env, message += error);
869 JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getRealValue_1
870 (JNIEnv *env, jobject obj, jint id, jint vr) {
873 const char *error = "";
876 if (fmi.version == 1) {
877 value = FMI1_CS_GET_REAL(fmi.fmu, vr, &error);
878 } else if (fmi.version == 2) {
879 value = FMI2_CS_GET_REAL(fmi.fmu, vr, &error);
881 if (!isEmpty(error)) {
882 string message = "Could not get real value: ";
883 return throwFMILException(env, message += error);
888 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_getIntegerValue_1
889 (JNIEnv *env, jobject obj, jstring id, jstring variable) {
891 const char *fmuId = env->GetStringUTFChars(id, 0);
893 FMUControlStruct fmuStruct = fmus[fmuId];
894 env->ReleaseStringUTFChars(id, fmuId);
895 const char *name = env->GetStringUTFChars(variable, 0);
897 if(referenceExists(fmuStruct, name)) {
898 fmiValueReference vr = getReference(fmuStruct, name);
900 fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &result);
901 env->ReleaseStringUTFChars(variable, name);
905 string nameString = name;
906 string message = "Variable " + nameString + " not found";
907 env->ReleaseStringUTFChars(variable, name);
908 return throwException(env, message);
912 string message = fmuId;
913 env->ReleaseStringUTFChars(id, fmuId);
914 return throwException(env, "unloadFMU: Model id " + message + " not found");
921 JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_getBooleanValue_1
922 (JNIEnv *env, jobject obj, jstring id, jstring variable) {
924 const char *fmuId = env->GetStringUTFChars(id, 0);
926 FMUControlStruct fmuStruct = fmus[fmuId];
927 env->ReleaseStringUTFChars(id, fmuId);
928 const char *name = env->GetStringUTFChars(variable, 0);
930 if(referenceExists(fmuStruct, name)) {
931 fmiValueReference vr = getReference(fmuStruct, name);
933 fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &result);
934 env->ReleaseStringUTFChars(variable, name);
938 string nameString = name;
939 string message = "Variable " + nameString + " not found";
940 env->ReleaseStringUTFChars(variable, name);
941 return throwException(env, message);
945 string message = fmuId;
946 env->ReleaseStringUTFChars(id, fmuId);
947 return throwException(env, "unloadFMU: Model id " + message + " not found");
953 JNIEXPORT jstring JNICALL Java_org_simantics_fmil_core_FMIL_getStringValue_1
954 (JNIEnv *env, jobject obj, jstring id, jstring variable) {
956 const char *fmuId = env->GetStringUTFChars(id, 0);
958 FMUControlStruct fmuStruct = fmus[fmuId];
959 env->ReleaseStringUTFChars(id, fmuId);
960 const char *name = env->GetStringUTFChars(variable, 0);
962 if(referenceExists(fmuStruct, name)) {
963 fmiValueReference vr = getReference(fmuStruct, name);
965 fmuStruct.fmu.getString(fmuStruct.c, &vr, 1, &result);
966 env->ReleaseStringUTFChars(variable, name);
967 return env->NewStringUTF(result);
970 string nameString = name;
971 string message = "Variable " + nameString + " not found";
972 env->ReleaseStringUTFChars(variable, name);
973 return 0; //throwException(env, message);
977 string message = fmuId;
978 env->ReleaseStringUTFChars(id, fmuId);
979 return 0; //throwException(env, "unloadFMU: Model id " + message + " not found");