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 * -------------------------------------------------------------------------
24 #include <org_simantics_fmil_FMILJNI.h>
28 #include "sim_support.h"
33 #define PRINT(fmt,args) { FILE *fp = fopen("R:\\Simantics\\Sysdyn\\log.txt", "ab"); fprintf(fp, fmt, args); fclose(fp); }
37 static std::atomic<int> instanceNameID;
40 return instanceNameID++;
47 vector<string> variables;
48 vector<string> descriptions;
49 vector<string> declaredTypes;
50 vector<int> valueReferences;
52 vector<int> variabilities;
53 vector<int> causalities;
55 vector<string> declaredTypeNames;
56 vector<string> typeDescriptions;
57 vector<string> quantities;
60 vector<int> subscription;
68 struct FMUControlStruct {
69 double step; // simulation step length
70 fmiReal currentTime; // current simulation time
72 fmiComponent c; // instance of the fmu
73 ScalarVariable** vars; // model variables
75 fmiEventInfo eventInfo; // updated by calls to initialize and eventUpdate
76 const char* guid; // global unique id of the fmu
77 fmiCallbackFunctions callbacks; // called by the model during simulation
78 fmiStatus fmiFlag; // return code of the fmu functions
80 map<string,int> indexes; // indexes for variable names in vars-table
81 map<string,int>::iterator it;
83 int nx; // number of state variables
84 double *x; // continuous states
85 double *xdot; // the crresponding derivatives in same order
86 int nz; // number of state event indicators
87 double *z; // state event indicators
88 double *prez; // previous values of state event indicators
90 bool initialized; // has the fmu been initialized
92 vector<fmiValueReference> subscription; // result subscriptions
93 vector<string> allVariables; // all variables in an initialized model
94 vector<fmiValueReference> fmiValueReferences; // all value references
96 string lastErrorMessage;
103 //map<string,FMUControlStruct> fmus; // indexes for variable names in vars-table
105 int throwFMILException(JNIEnv *env, string message) {
107 newExcCls = env->FindClass("org/simantics/fmil/core/FMILException");
108 if (newExcCls == NULL) {
109 newExcCls = env->FindClass("java/lang/Exception");
111 if (newExcCls == NULL) {
112 /* Unable to find the exception class, give up. */
115 env->ThrowNew(newExcCls, message.c_str());
119 int throwException(JNIEnv *env, string message) {
120 return throwFMILException(env, message);
123 bool isEmpty(const char *c) {
134 bool exists(string id) {
135 map<string,FMUControlStruct>::iterator it = fmus.find(id);
136 if(it != fmus.end()) {
146 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_loadFMUFile_1
147 (JNIEnv *env, jobject obj, jstring path, jstring tempDir) {
151 FMIL_DeclaredType *types;
155 int variableCount = 0;
159 const char *error = "";
161 const char *fmuPath = env->GetStringUTFChars(path, 0);
162 const char *fmuTempDir = env->GetStringUTFChars(tempDir, 0);
164 fmi1.currentTime = 0;
166 returnValue = FMI_CS_LOAD(fmuPath, fmuTempDir, &fmi1.fmu, &fmuVersion, &error);
168 if (returnValue != 0) {
169 string message = "Could not load FMU: ";
170 return throwFMILException(env, message += error);
173 string message = "No FMU loaded: ";
174 return throwFMILException(env, message += error);
177 fmi1.version = fmuVersion;
178 if (fmi1.version == 1) {
179 vars = FMI1_CS_GET_VARIABLES(fmi1.fmu, &variableCount, &error);
180 } else if (fmi1.version == 2) {
181 vars = FMI2_CS_GET_VARIABLES(fmi1.fmu, &variableCount, &error);
183 if (!isEmpty(error)) {
184 string message = "Could not get variables ";
185 return throwFMILException(env, message += error);
188 for(int i=0;i<variableCount;i++) {
189 fmi1.variables.push_back(string(vars[i].name));
190 if(vars[i].description)
191 fmi1.descriptions.push_back(string(vars[i].description));
193 fmi1.descriptions.push_back(string(""));
194 if(vars[i].declaredType)
195 fmi1.declaredTypes.push_back(string(vars[i].declaredType));
197 fmi1.declaredTypes.push_back(string(""));
198 fmi1.types.push_back(vars[i].type);
199 fmi1.causalities.push_back(vars[i].causality);
200 fmi1.variabilities.push_back(vars[i].variability);
201 fmi1.valueReferences.push_back(vars[i].vr);
204 if (fmi1.version == 1) {
205 types = FMI1_CS_GET_DECLARED_TYPES(fmi1.fmu, &typeCount, &error);
206 } else if (fmi1.version == 2) {
207 types = FMI2_CS_GET_DECLARED_TYPES(fmi1.fmu, &typeCount, &error);
209 if (!isEmpty(error)) {
210 string message = "Could not get declared types ";
211 return throwFMILException(env, message += error);
214 for(int i=0;i<typeCount;i++) {
215 fmi1.declaredTypeNames.push_back(string(types[i].name));
216 if(types[i].description)
217 fmi1.typeDescriptions.push_back(string(types[i].description));
219 fmi1.typeDescriptions.push_back(string(""));
220 if(types[i].quantity)
221 fmi1.quantities.push_back(string(types[i].quantity));
223 fmi1.quantities.push_back(string(""));
225 fmi1.units.push_back(string(types[i].unit));
227 fmi1.units.push_back(string(""));
231 fmus.push_back(fmi1);
233 env->ReleaseStringUTFChars(path, fmuPath);
234 env->ReleaseStringUTFChars(tempDir, fmuTempDir);
236 return (jint)fmus.size() - 1;
240 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setStepLength_1
241 (JNIEnv *env, jobject obj, jint id, jdouble stepLength) {
242 fmus[id].timeStep = stepLength;
246 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_subscribe_1
247 (JNIEnv *env, jobject obj, jint id, jintArray vrs) {
250 jint* elements = env -> GetIntArrayElements(vrs, &isCopy);
251 jsize n = env -> GetArrayLength(vrs);
254 for (i = 0; i < n; i++) {
255 fmus[id].subscription.push_back(elements[i]);
258 if (isCopy == JNI_TRUE) {
259 env -> ReleaseIntArrayElements(vrs, elements, 0);
266 bool referenceExists(FMUControlStruct fmuStruct, string variable) {
267 map<string,int>::iterator it = fmuStruct.indexes.find(variable);
268 if(it != fmuStruct.indexes.end()) {
275 // Remember to check if reference exists
276 fmiValueReference getReference(FMUControlStruct fmuStruct, string variable) {
277 return fmuStruct.fmiValueReferences[fmuStruct.indexes[variable]];
280 // Get string representation of a scalar variable type
281 string getTypeString(ScalarVariable* sv) {
282 switch (sv->typeSpec->type){
285 case elm_Enumeration:
286 return "Enumeration";
296 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setRealValue_1
297 (JNIEnv *env, jobject obj, jint id, jint vr, jdouble value) {
299 const char *error = "";
300 FMI1 &fmi = fmus[id];
301 if (fmi.version == 1) {
302 FMI1_CS_SET_REAL(fmi.fmu, vr, value, &error);
304 else if (fmi.version == 2) {
305 FMI2_CS_SET_REAL(fmi.fmu, vr, value, &error);
307 if (!isEmpty(error)) {
308 string message = "Could not set real value: ";
309 return throwFMILException(env, message += error);
314 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setIntegerValue_1
315 (JNIEnv *env, jobject obj, jint id, jint vr, jint value) {
317 const char *error = "";
319 if (fmi.version == 1) {
320 FMI1_CS_SET_INTEGER(fmi.fmu, vr, value, &error);
322 else if (fmi.version == 2) {
323 FMI2_CS_SET_INTEGER(fmi.fmu, vr, value, &error);
325 if (!isEmpty(error)) {
326 string message = "Could not set integer value: ";
327 return throwFMILException(env, message += error);
332 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setBooleanValue_1
333 (JNIEnv *env, jobject obj, jint id, jint vr, jboolean value) {
335 const char *error = "";
337 if (fmi.version == 1) {
338 FMI1_CS_SET_BOOLEAN(fmi.fmu, vr, value != 0, &error);
340 else if (fmi.version == 2) {
341 FMI2_CS_SET_BOOLEAN(fmi.fmu, vr, value != 0, &error);
343 if (!isEmpty(error)) {
344 string message = "Could not set boolean value: ";
345 return throwFMILException(env, message += error);
350 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setStringValue_1
351 (JNIEnv *env, jobject obj, jint id, jint vr, jstring value) {
353 const char *error = "";
354 const char *valueChars = env->GetStringUTFChars(value, 0);
356 if (fmi.version == 1) {
357 FMI1_CS_SET_STRING(fmi.fmu, vr, valueChars, &error);
359 else if (fmi.version == 2) {
360 FMI2_CS_SET_STRING(fmi.fmu, vr, valueChars, &error);
362 env->ReleaseStringUTFChars(value, valueChars);
363 if (!isEmpty(error)) {
364 string message = "Could not set string value: ";
365 return throwFMILException(env, message += error);
370 JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_isInitialized_1
371 (JNIEnv *env, jobject obj, jstring id) {
373 const char *fmuId = env->GetStringUTFChars(id, 0);
375 FMUControlStruct& fmuStruct = fmus[fmuId];
376 env->ReleaseStringUTFChars(id, fmuId);
377 return fmuStruct.initialized;
379 env->ReleaseStringUTFChars(id, fmuId);
387 JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getTime_1
388 (JNIEnv *env, jobject obj, jint id) {
389 return fmus[id].currentTime;
392 double getRealValue(FMUControlStruct fmuStruct, int index) {
393 ScalarVariable *sv = fmuStruct.vars[index];
394 fmiValueReference vr = fmuStruct.fmiValueReferences[index];
399 switch (sv->typeSpec->type){
401 fmuStruct.fmu.getReal(fmuStruct.c, &vr, 1, &real);
404 case elm_Enumeration:
405 fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &integer);
406 real = (double)integer;
409 fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &fmibool);
410 if(fmibool == fmiTrue)
419 JNIEXPORT jdoubleArray JNICALL Java_org_simantics_fmil_core_FMIL_getSubscribedResults_1
420 (JNIEnv *env, jobject obj, jint id, jdoubleArray result) {
423 jdouble* resultElements = env -> GetDoubleArrayElements(result, &isCopy);
424 jsize n = env -> GetArrayLength(result);
426 const char *error = "";
430 vrs = &(fmus[id].subscription[0]);
431 if (fmi.version == 1) {
432 FMI1_CS_GET_REALS(fmi.fmu, vrs, resultElements, n, &error);
433 } else if (fmi.version == 2) {
434 FMI2_CS_GET_REALS(fmi.fmu, vrs, resultElements, n, &error);
437 if (isCopy == JNI_TRUE) {
438 env -> ReleaseDoubleArrayElements(result, resultElements, 0);
445 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_instantiateSimulation_1
446 (JNIEnv *env, jobject obj, jint id) {
448 int uniqueId = create_id();
449 std::string instanceName = std::to_string(uniqueId);
451 const char *error = "";
453 FMI1 &fmi = fmus[id];
454 if (fmi.version == 1) {
455 returnValue = FMI1_CS_INSTANTIATE(fmi.fmu, instanceName.c_str(), &error);
456 } else if (fmi.version == 2) {
457 returnValue = FMI2_CS_INSTANTIATE(fmi.fmu, instanceName.c_str(), &error);
459 if(returnValue != 0) {
460 string message = "No FMU loaded: ";
461 return throwFMILException(env, message += error);
466 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_initializeSimulation_1
467 (JNIEnv *env, jobject obj, jint id) {
469 const char *error = "";
472 if (fmi.version == 1) {
473 returnValue = FMI1_CS_INITIALIZE(fmi.fmu, &error);
474 } else if (fmi.version == 2) {
475 returnValue = FMI2_CS_INITIALIZE(fmi.fmu, &error);
477 if(returnValue != 0) {
478 string message = "Could not initialize simulation: ";
479 return throwFMILException(env, message += error);
486 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setTime_1
487 (JNIEnv *env, jobject obj, jstring id, jdouble time) {
491 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariables_1
492 (JNIEnv *env, jobject obj, jint id) {
494 jobjectArray ret= (jobjectArray)env->NewObjectArray((jsize)fmus[id].variables.size(),
495 env->FindClass("java/lang/String"),
496 env->NewStringUTF(""));
498 for(unsigned int i=0;i<fmus[id].variables.size();i++) {
499 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].variables[i].c_str()));
506 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDescriptions_1
507 (JNIEnv *env, jobject obj, jint id) {
509 jobjectArray ret= (jobjectArray)env->NewObjectArray((jsize)fmus[id].descriptions.size(),
510 env->FindClass("java/lang/String"),
511 env->NewStringUTF(""));
513 for(unsigned int i=0;i<fmus[id].descriptions.size();i++) {
514 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].descriptions[i].c_str()));
521 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDeclaredTypes_1
522 (JNIEnv *env, jobject obj, jint id) {
524 jobjectArray ret= (jobjectArray)env->NewObjectArray((jsize)fmus[id].declaredTypes.size(),
525 env->FindClass("java/lang/String"),
526 env->NewStringUTF(""));
528 for(unsigned int i=0;i<fmus[id].declaredTypes.size();i++) {
529 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypes[i].c_str()));
536 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableReferences_1
537 (JNIEnv *env, jobject obj, jint id, jintArray result) {
540 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
541 jsize n = env -> GetArrayLength(result);
544 for (i = 0; i < n; i++) {
545 resultElements[i] = fmus[id].valueReferences[i];
548 if (isCopy == JNI_TRUE) {
549 env -> ReleaseIntArrayElements(result, resultElements, 0);
556 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableTypes_1
557 (JNIEnv *env, jobject obj, jint id, jintArray result) {
560 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
561 jsize n = env -> GetArrayLength(result);
564 for (i = 0; i < n; i++) {
565 resultElements[i] = fmus[id].types[i];
568 if (isCopy == JNI_TRUE) {
569 env -> ReleaseIntArrayElements(result, resultElements, 0);
576 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableVariabilities_1
577 (JNIEnv *env, jobject obj, jint id, jintArray result) {
580 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
581 jsize n = env -> GetArrayLength(result);
583 for (jsize i = 0; i < n; i++) {
584 resultElements[i] = fmus[id].variabilities[i];
587 if (isCopy == JNI_TRUE) {
588 env -> ReleaseIntArrayElements(result, resultElements, 0);
595 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableCausalities_1
596 (JNIEnv *env, jobject obj, jint id, jintArray result) {
599 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
600 jsize n = env -> GetArrayLength(result);
602 for (jsize i = 0; i < n; i++) {
603 resultElements[i] = fmus[id].causalities[i];
606 if (isCopy == JNI_TRUE) {
607 env -> ReleaseIntArrayElements(result, resultElements, 0);
614 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypes_1
615 (JNIEnv *env, jobject obj, jint id) {
617 jobjectArray ret= (jobjectArray)env->NewObjectArray((jsize)fmus[id].declaredTypeNames.size(),
618 env->FindClass("java/lang/String"),
619 env->NewStringUTF(""));
621 for(unsigned int i=0;i<fmus[id].declaredTypeNames.size();i++) {
622 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypeNames[i].c_str()));
629 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeDescriptions_1
630 (JNIEnv *env, jobject obj, jint id) {
632 jobjectArray ret= (jobjectArray)env->NewObjectArray((jsize)fmus[id].typeDescriptions.size(),
633 env->FindClass("java/lang/String"),
634 env->NewStringUTF(""));
636 for(unsigned int i=0;i<fmus[id].typeDescriptions.size();i++) {
637 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].typeDescriptions[i].c_str()));
644 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeQuantities_1
645 (JNIEnv *env, jobject obj, jint id) {
647 jobjectArray ret= (jobjectArray)env->NewObjectArray((jsize)fmus[id].quantities.size(),
648 env->FindClass("java/lang/String"),
649 env->NewStringUTF(""));
651 for(unsigned int i=0;i<fmus[id].quantities.size();i++) {
652 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].quantities[i].c_str()));
659 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeUnits_1
660 (JNIEnv *env, jobject obj, jint id) {
662 jobjectArray ret= (jobjectArray)env->NewObjectArray((jsize)fmus[id].units.size(),
663 env->FindClass("java/lang/String"),
664 env->NewStringUTF(""));
666 for(unsigned int i=0;i<fmus[id].units.size();i++) {
667 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].units[i].c_str()));
675 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_filterVariables_1
676 (JNIEnv *env, jobject obj, jstring id, jstring regexp) {
677 const char *rx = env->GetStringUTFChars(regexp, 0);
678 jobjectArray result = filterVariables(env, obj, id, rx);
679 env->ReleaseStringUTFChars(regexp, rx);
684 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_simulateStep_1
685 (JNIEnv *env, jobject obj, jint id) {
688 const char *error = "";
690 FMI1 &fmi = fmus[id];
691 if (fmi.version == 1) {
692 returnValue = FMI1_CS_STEP(fmi.fmu, fmi.currentTime, fmi.timeStep, &error);
693 } else if (fmi.version == 2) {
694 returnValue = FMI2_CS_STEP(fmi.fmu, fmi.currentTime, fmi.timeStep, &error);
696 if(returnValue == 1) {
697 string message = "Could not simulate step: ";
698 return throwException(env, message += error);
701 fmi.currentTime += fmi.timeStep;
703 return returnValue; //Pass return value up. 0 is OK, 1 is error, 2 is pending
706 const char *fmuId = env->GetStringUTFChars(id, 0);
708 FMUControlStruct& fmuStruct = fmus[fmuId];
709 env->ReleaseStringUTFChars(id, fmuId);
711 if(&fmuStruct.fmu == NULL || fmuStruct.fmu.modelDescription == NULL || &fmuStruct.vars == NULL) {
712 return throwException(env, "Simulate step failed - fmu not loaded");
715 if(fmuStruct.x == NULL) {
716 return throwException(env, "Simulate step failed - fmu not instantiated");
719 if(fmuStruct.initialized == false) {
720 fmiBoolean toleranceControlled = fmiFalse;
721 fmuStruct.fmiFlag = fmuStruct.fmu.initialize(fmuStruct.c, toleranceControlled, fmuStruct.currentTime, &(fmuStruct.eventInfo));
722 if (fmuStruct.fmiFlag > fmiWarning) return throwException(env, "could not initialize model");
723 fmuStruct.initialized = true;
726 FMU& fmu = fmuStruct.fmu;
727 int debug = 0; // DEBUG ON = 1, OFF = 0
730 double dt, tPre, tEnd = fmuStruct.currentTime + fmuStruct.step;
732 fmiBoolean timeEvent, stateEvent, stepEvent;
733 fmiStatus fmiFlag; // return code of the fmu functions
734 fmiValueReference vr;
738 /* Simulate the duration of one step. The simulation may be done in
739 * multiple parts if events occur
741 while (fmuStruct.currentTime < tEnd) {
742 // get current state and derivatives
743 fmiFlag = fmu.getContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);
744 if (fmiFlag > fmiWarning)
745 return throwException(env, "could not retrieve states");
747 fmiFlag = fmu.getDerivatives(fmuStruct.c, fmuStruct.xdot, fmuStruct.nx);
748 if (fmiFlag > fmiWarning)
749 return throwException(env, "could not retrieve derivatives");
752 tPre = fmuStruct.currentTime;
753 fmuStruct.currentTime = min(fmuStruct.currentTime+fmuStruct.step, tEnd);
754 timeEvent = fmuStruct.eventInfo.upcomingTimeEvent && fmuStruct.eventInfo.nextEventTime < fmuStruct.currentTime;
756 if (timeEvent) fmuStruct.currentTime = fmuStruct.eventInfo.nextEventTime;
757 dt = fmuStruct.currentTime - tPre;
758 fmiFlag = fmu.setTime(fmuStruct.c, fmuStruct.currentTime);
759 if (fmiFlag > fmiWarning) throwException(env, "could not set time");
761 if(referenceExists(fmuStruct, "time")) {
762 vr = getReference(fmuStruct, "time");
764 fmu.setReal(fmuStruct.c, &vr, 1, &(fmuStruct.currentTime));
769 printf("Actual time: %lf\n", fmuStruct.currentTime);
771 if (fmiFlag > fmiWarning)
772 return throwException(env, "could not set time");
775 for (i=0; i<fmuStruct.nx; i++)
776 fmuStruct.x[i] += dt*fmuStruct.xdot[i]; // forward Euler method
778 fmiFlag = fmu.setContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);
779 if (fmiFlag > fmiWarning)
780 return throwException(env, "could not set states");
782 // Check for step event, e.g. dynamic state selection
783 fmiFlag = fmu.completedIntegratorStep(fmuStruct.c, &stepEvent);
784 if (fmiFlag > fmiWarning) return throwException(env, "could not complete intgrator step");
786 /* for (i=0; i<fmuStruct.nz; i++) fmuStruct.prez[i] = fmuStruct.z[i];
787 fmiFlag = fmu.getEventIndicators(fmuStruct.c, fmuStruct.z, fmuStruct.nz);
788 if (fmiFlag > fmiWarning) return throwException(env, "could not retrieve event indicators");
790 for (i=0; i<fmuStruct.nz; i++)
791 stateEvent = stateEvent || (fmuStruct.prez[i] * fmuStruct.z[i] < 0);
796 if (timeEvent || stateEvent || stepEvent) {
798 // event iteration in one step, ignoring intermediate results
799 fmiFlag = fmu.eventUpdate(fmuStruct.c, fmiFalse, &(fmuStruct.eventInfo));
800 if (fmiFlag > fmiWarning) return throwException(env, "could not perform event update");
811 string message = fmuId;
812 env->ReleaseStringUTFChars(id, fmuId);
813 return throwException(env, "simulateStep: Model id " + message + " not found");
818 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_unloadFMU_1
819 (JNIEnv *env, jobject obj, jint id) {
822 const char *error = "";
825 if (fmi.version == 1) {
826 returnValue = FMI1_CS_UNLOAD(fmi.fmu, &error);
827 } else if (fmi.version == 2) {
828 returnValue = FMI2_CS_UNLOAD(fmi.fmu, &error);
830 if(returnValue != 0) {
831 string message = "Could not unload FMU: ";
832 return throwException(env, message += error);
837 JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getRealValue_1
838 (JNIEnv *env, jobject obj, jint id, jint vr) {
841 const char *error = "";
844 if (fmi.version == 1) {
845 value = FMI1_CS_GET_REAL(fmi.fmu, vr, &error);
846 } else if (fmi.version == 2) {
847 value = FMI2_CS_GET_REAL(fmi.fmu, vr, &error);
849 if (!isEmpty(error)) {
850 string message = "Could not get real value: ";
851 throwFMILException(env, message += error);
857 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_getIntegerValue_1
858 (JNIEnv *env, jobject obj, jint id, jint vr) {
861 const char *error = "";
864 if (fmi.version == 1) {
865 value = FMI1_CS_GET_INTEGER(fmi.fmu, vr, &error);
867 else if (fmi.version == 2) {
868 value = FMI2_CS_GET_INTEGER(fmi.fmu, vr, &error);
870 if (!isEmpty(error)) {
871 string message = "Could not get integer value: ";
872 throwFMILException(env, message += error);
878 JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_getBooleanValue_1
879 (JNIEnv *env, jobject obj, jint id, jint vr) {
882 const char *error = "";
885 if (fmi.version == 1) {
886 value = FMI1_CS_GET_BOOLEAN(fmi.fmu, vr, &error);
888 else if (fmi.version == 2) {
889 value = FMI2_CS_GET_BOOLEAN(fmi.fmu, vr, &error);
891 if (!isEmpty(error)) {
892 string message = "Could not get boolean value: ";
893 throwFMILException(env, message += error);
900 JNIEXPORT jstring JNICALL Java_org_simantics_fmil_core_FMIL_getStringValue_1
901 (JNIEnv *env, jobject obj, jint id, jint vr) {
904 const char *error = "";
907 if (fmi.version == 1) {
908 value = FMI1_CS_GET_STRING(fmi.fmu, vr, &error);
910 else if (fmi.version == 2) {
911 value = FMI2_CS_GET_STRING(fmi.fmu, vr, &error);
913 if (!isEmpty(error)) {
914 string message = "Could not get string value: ";
915 throwFMILException(env, message += error);
919 return env->NewStringUTF(value);