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 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 = "";
301 if (fmi.version == 1) {
302 FMI1_CS_SET_REAL(fmi.fmu, vr, value, &error);
303 } else if (fmi.version == 2) {
304 FMI2_CS_SET_REAL(fmi.fmu, vr, value, &error);
306 if (!isEmpty(error)) {
307 string message = "Could not set real value ";
308 return throwFMILException(env, message += error);
313 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setIntegerValue_1
314 (JNIEnv *env, jobject obj, jstring id, jstring parameter, jint value) {
316 const char *fmuId = env->GetStringUTFChars(id, 0);
318 FMUControlStruct& fmuStruct = fmus[fmuId];
319 const char *name = env->GetStringUTFChars(parameter, 0);
320 string nameString = name;
321 string modelId = fmuId;
322 if(!referenceExists(fmuStruct, name)) {
323 string errorMessage = "setIntegerValue: Model (id " + modelId + ") does not contain variable: " + nameString;
324 env->ReleaseStringUTFChars(parameter, name);
325 env->ReleaseStringUTFChars(id, fmuId);
326 return throwException(env, errorMessage);
328 // Check variable type
329 ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]];
330 switch (sv->typeSpec->type){
334 string errorMessage = "setIntegerValue: " + nameString + " is not of type Integer. (type: + " + getTypeString(sv) + ")";
335 env->ReleaseStringUTFChars(parameter, name);
336 env->ReleaseStringUTFChars(id, fmuId);
337 return throwException(env, errorMessage);
342 fmiValueReference vr = getReference(fmuStruct, name);
343 const int intValue = (int) value;
344 fmuStruct.fmu.setInteger(fmuStruct.c, &vr, 1, &intValue);
345 env->ReleaseStringUTFChars(parameter, name);
346 env->ReleaseStringUTFChars(id, fmuId);
350 string message = fmuId;
351 env->ReleaseStringUTFChars(id, fmuId);
352 return throwException(env, "setIntegerValue: Model id " + message + " not found");
358 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setBooleanValue_1
359 (JNIEnv *env, jobject obj, jstring id, jstring parameter, jboolean value) {
361 const char *fmuId = env->GetStringUTFChars(id, 0);
363 FMUControlStruct& fmuStruct = fmus[fmuId];
364 const char *name = env->GetStringUTFChars(parameter, 0);
365 string nameString = name;
366 string modelId = fmuId;
367 if(!referenceExists(fmuStruct, name)) {
368 string errorMessage = "setBooleanValue: Model (id " + modelId + ") does not contain variable: " + nameString;
369 env->ReleaseStringUTFChars(parameter, name);
370 env->ReleaseStringUTFChars(id, fmuId);
371 return throwException(env, errorMessage);
373 // Check variable type
374 ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]];
375 switch (sv->typeSpec->type){
379 string errorMessage = "setBooleanValue: " + nameString + " is not of type Boolean. (type: + " + getTypeString(sv) + ")";
380 env->ReleaseStringUTFChars(parameter, name);
381 env->ReleaseStringUTFChars(id, fmuId);
382 return throwException(env, errorMessage);
387 fmiValueReference vr = getReference(fmuStruct, name);
388 fmiBoolean result = 1;
391 fmuStruct.fmu.setBoolean(fmuStruct.c, &vr, 1, &result);
392 env->ReleaseStringUTFChars(parameter, name);
393 env->ReleaseStringUTFChars(id, fmuId);
397 string message = fmuId;
398 env->ReleaseStringUTFChars(id, fmuId);
399 return throwException(env, "setBooleanValue: Model id " + message + " not found");
404 JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_isInitialized_1
405 (JNIEnv *env, jobject obj, jstring id) {
407 const char *fmuId = env->GetStringUTFChars(id, 0);
409 FMUControlStruct& fmuStruct = fmus[fmuId];
410 env->ReleaseStringUTFChars(id, fmuId);
411 return fmuStruct.initialized;
413 env->ReleaseStringUTFChars(id, fmuId);
421 JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getTime_1
422 (JNIEnv *env, jobject obj, jint id) {
423 return fmus[id].currentTime;
426 double getRealValue(FMUControlStruct fmuStruct, int index) {
427 ScalarVariable *sv = fmuStruct.vars[index];
428 fmiValueReference vr = fmuStruct.fmiValueReferences[index];
433 switch (sv->typeSpec->type){
435 fmuStruct.fmu.getReal(fmuStruct.c, &vr, 1, &real);
438 case elm_Enumeration:
439 fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &integer);
440 real = (double)integer;
443 fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &fmibool);
444 if(fmibool == fmiTrue)
453 JNIEXPORT jdoubleArray JNICALL Java_org_simantics_fmil_core_FMIL_getSubscribedResults_1
454 (JNIEnv *env, jobject obj, jint id, jdoubleArray result) {
457 jdouble* resultElements = env -> GetDoubleArrayElements(result, &isCopy);
458 jsize n = env -> GetArrayLength(result);
460 const char *error = "";
464 vrs = &(fmus[id].subscription[0]);
465 if (fmi.version == 1) {
466 FMI1_CS_GET_REALS(fmi.fmu, vrs, resultElements, n, &error);
467 } else if (fmi.version == 2) {
468 FMI2_CS_GET_REALS(fmi.fmu, vrs, resultElements, n, &error);
471 if (isCopy == JNI_TRUE) {
472 env -> ReleaseDoubleArrayElements(result, resultElements, 0);
479 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_instantiateSimulation_1
480 (JNIEnv *env, jobject obj, jint id) {
482 int uniqueId = create_id();
483 std::string instanceName = std::to_string(uniqueId);
485 const char *error = "";
487 FMI1 &fmi = fmus[id];
488 if (fmi.version == 1) {
489 returnValue = FMI1_CS_INSTANTIATE(fmi.fmu, instanceName.c_str(), &error);
490 } else if (fmi.version == 2) {
491 returnValue = FMI2_CS_INSTANTIATE(fmi.fmu, instanceName.c_str(), &error);
493 if(returnValue != 0) {
494 string message = "No FMU loaded: ";
495 return throwFMILException(env, message += error);
500 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_initializeSimulation_1
501 (JNIEnv *env, jobject obj, jint id) {
503 const char *error = "";
506 if (fmi.version == 1) {
507 returnValue = FMI1_CS_INITIALIZE(fmi.fmu, &error);
508 } else if (fmi.version == 2) {
509 returnValue = FMI2_CS_INITIALIZE(fmi.fmu, &error);
511 if(returnValue != 0) {
512 string message = "Could not initialize simulation: ";
513 return throwFMILException(env, message += error);
520 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setTime_1
521 (JNIEnv *env, jobject obj, jstring id, jdouble time) {
525 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariables_1
526 (JNIEnv *env, jobject obj, jint id) {
528 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].variables.size(),
529 env->FindClass("java/lang/String"),
530 env->NewStringUTF(""));
532 for(unsigned int i=0;i<fmus[id].variables.size();i++) {
533 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].variables[i].c_str()));
540 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDescriptions_1
541 (JNIEnv *env, jobject obj, jint id) {
543 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].descriptions.size(),
544 env->FindClass("java/lang/String"),
545 env->NewStringUTF(""));
547 for(unsigned int i=0;i<fmus[id].descriptions.size();i++) {
548 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].descriptions[i].c_str()));
555 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDeclaredTypes_1
556 (JNIEnv *env, jobject obj, jint id) {
558 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypes.size(),
559 env->FindClass("java/lang/String"),
560 env->NewStringUTF(""));
562 for(unsigned int i=0;i<fmus[id].declaredTypes.size();i++) {
563 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypes[i].c_str()));
570 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableReferences_1
571 (JNIEnv *env, jobject obj, jint id, jintArray result) {
574 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
575 jsize n = env -> GetArrayLength(result);
578 for (i = 0; i < n; i++) {
579 resultElements[i] = fmus[id].valueReferences[i];
582 if (isCopy == JNI_TRUE) {
583 env -> ReleaseIntArrayElements(result, resultElements, 0);
590 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableTypes_1
591 (JNIEnv *env, jobject obj, jint id, jintArray result) {
594 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
595 jsize n = env -> GetArrayLength(result);
598 for (i = 0; i < n; i++) {
599 resultElements[i] = fmus[id].types[i];
602 if (isCopy == JNI_TRUE) {
603 env -> ReleaseIntArrayElements(result, resultElements, 0);
610 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableVariabilities_1
611 (JNIEnv *env, jobject obj, jint id, jintArray result) {
614 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
615 jsize n = env -> GetArrayLength(result);
617 for (jsize i = 0; i < n; i++) {
618 resultElements[i] = fmus[id].variabilities[i];
621 if (isCopy == JNI_TRUE) {
622 env -> ReleaseIntArrayElements(result, resultElements, 0);
629 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableCausalities_1
630 (JNIEnv *env, jobject obj, jint id, jintArray result) {
633 jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
634 jsize n = env -> GetArrayLength(result);
636 for (jsize i = 0; i < n; i++) {
637 resultElements[i] = fmus[id].causalities[i];
640 if (isCopy == JNI_TRUE) {
641 env -> ReleaseIntArrayElements(result, resultElements, 0);
648 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypes_1
649 (JNIEnv *env, jobject obj, jint id) {
651 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypeNames.size(),
652 env->FindClass("java/lang/String"),
653 env->NewStringUTF(""));
655 for(unsigned int i=0;i<fmus[id].declaredTypeNames.size();i++) {
656 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].declaredTypeNames[i].c_str()));
663 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeDescriptions_1
664 (JNIEnv *env, jobject obj, jint id) {
666 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].typeDescriptions.size(),
667 env->FindClass("java/lang/String"),
668 env->NewStringUTF(""));
670 for(unsigned int i=0;i<fmus[id].typeDescriptions.size();i++) {
671 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].typeDescriptions[i].c_str()));
678 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeQuantities_1
679 (JNIEnv *env, jobject obj, jint id) {
681 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].quantities.size(),
682 env->FindClass("java/lang/String"),
683 env->NewStringUTF(""));
685 for(unsigned int i=0;i<fmus[id].quantities.size();i++) {
686 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].quantities[i].c_str()));
693 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeUnits_1
694 (JNIEnv *env, jobject obj, jint id) {
696 jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].units.size(),
697 env->FindClass("java/lang/String"),
698 env->NewStringUTF(""));
700 for(unsigned int i=0;i<fmus[id].units.size();i++) {
701 env->SetObjectArrayElement(ret,i,env->NewStringUTF(fmus[id].units[i].c_str()));
709 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_filterVariables_1
710 (JNIEnv *env, jobject obj, jstring id, jstring regexp) {
711 const char *rx = env->GetStringUTFChars(regexp, 0);
712 jobjectArray result = filterVariables(env, obj, id, rx);
713 env->ReleaseStringUTFChars(regexp, rx);
718 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_simulateStep_1
719 (JNIEnv *env, jobject obj, jint id) {
722 const char *error = "";
724 FMI1 &fmi = fmus[id];
725 if (fmi.version == 1) {
726 returnValue = FMI1_CS_STEP(fmi.fmu, fmi.currentTime, fmi.timeStep, &error);
727 } else if (fmi.version == 2) {
728 returnValue = FMI2_CS_STEP(fmi.fmu, fmi.currentTime, fmi.timeStep, &error);
730 if(returnValue != 0) {
731 string message = "Could not simulate step: ";
732 return throwException(env, message += error);
735 fmi.currentTime += fmi.timeStep;
740 const char *fmuId = env->GetStringUTFChars(id, 0);
742 FMUControlStruct& fmuStruct = fmus[fmuId];
743 env->ReleaseStringUTFChars(id, fmuId);
745 if(&fmuStruct.fmu == NULL || fmuStruct.fmu.modelDescription == NULL || &fmuStruct.vars == NULL) {
746 return throwException(env, "Simulate step failed - fmu not loaded");
749 if(fmuStruct.x == NULL) {
750 return throwException(env, "Simulate step failed - fmu not instantiated");
753 if(fmuStruct.initialized == false) {
754 fmiBoolean toleranceControlled = fmiFalse;
755 fmuStruct.fmiFlag = fmuStruct.fmu.initialize(fmuStruct.c, toleranceControlled, fmuStruct.currentTime, &(fmuStruct.eventInfo));
756 if (fmuStruct.fmiFlag > fmiWarning) return throwException(env, "could not initialize model");
757 fmuStruct.initialized = true;
760 FMU& fmu = fmuStruct.fmu;
761 int debug = 0; // DEBUG ON = 1, OFF = 0
764 double dt, tPre, tEnd = fmuStruct.currentTime + fmuStruct.step;
766 fmiBoolean timeEvent, stateEvent, stepEvent;
767 fmiStatus fmiFlag; // return code of the fmu functions
768 fmiValueReference vr;
772 /* Simulate the duration of one step. The simulation may be done in
773 * multiple parts if events occur
775 while (fmuStruct.currentTime < tEnd) {
776 // get current state and derivatives
777 fmiFlag = fmu.getContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);
778 if (fmiFlag > fmiWarning)
779 return throwException(env, "could not retrieve states");
781 fmiFlag = fmu.getDerivatives(fmuStruct.c, fmuStruct.xdot, fmuStruct.nx);
782 if (fmiFlag > fmiWarning)
783 return throwException(env, "could not retrieve derivatives");
786 tPre = fmuStruct.currentTime;
787 fmuStruct.currentTime = min(fmuStruct.currentTime+fmuStruct.step, tEnd);
788 timeEvent = fmuStruct.eventInfo.upcomingTimeEvent && fmuStruct.eventInfo.nextEventTime < fmuStruct.currentTime;
790 if (timeEvent) fmuStruct.currentTime = fmuStruct.eventInfo.nextEventTime;
791 dt = fmuStruct.currentTime - tPre;
792 fmiFlag = fmu.setTime(fmuStruct.c, fmuStruct.currentTime);
793 if (fmiFlag > fmiWarning) throwException(env, "could not set time");
795 if(referenceExists(fmuStruct, "time")) {
796 vr = getReference(fmuStruct, "time");
798 fmu.setReal(fmuStruct.c, &vr, 1, &(fmuStruct.currentTime));
803 printf("Actual time: %lf\n", fmuStruct.currentTime);
805 if (fmiFlag > fmiWarning)
806 return throwException(env, "could not set time");
809 for (i=0; i<fmuStruct.nx; i++)
810 fmuStruct.x[i] += dt*fmuStruct.xdot[i]; // forward Euler method
812 fmiFlag = fmu.setContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);
813 if (fmiFlag > fmiWarning)
814 return throwException(env, "could not set states");
816 // Check for step event, e.g. dynamic state selection
817 fmiFlag = fmu.completedIntegratorStep(fmuStruct.c, &stepEvent);
818 if (fmiFlag > fmiWarning) return throwException(env, "could not complete intgrator step");
820 /* for (i=0; i<fmuStruct.nz; i++) fmuStruct.prez[i] = fmuStruct.z[i];
821 fmiFlag = fmu.getEventIndicators(fmuStruct.c, fmuStruct.z, fmuStruct.nz);
822 if (fmiFlag > fmiWarning) return throwException(env, "could not retrieve event indicators");
824 for (i=0; i<fmuStruct.nz; i++)
825 stateEvent = stateEvent || (fmuStruct.prez[i] * fmuStruct.z[i] < 0);
830 if (timeEvent || stateEvent || stepEvent) {
832 // event iteration in one step, ignoring intermediate results
833 fmiFlag = fmu.eventUpdate(fmuStruct.c, fmiFalse, &(fmuStruct.eventInfo));
834 if (fmiFlag > fmiWarning) return throwException(env, "could not perform event update");
845 string message = fmuId;
846 env->ReleaseStringUTFChars(id, fmuId);
847 return throwException(env, "simulateStep: Model id " + message + " not found");
852 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_unloadFMU_1
853 (JNIEnv *env, jobject obj, jint id) {
856 const char *error = "";
859 if (fmi.version == 1) {
860 returnValue = FMI1_CS_UNLOAD(fmi.fmu, &error);
861 } else if (fmi.version == 2) {
862 returnValue = FMI2_CS_UNLOAD(fmi.fmu, &error);
864 if(returnValue != 0) {
865 string message = "Could not unload FMU: ";
866 return throwException(env, message += error);
871 JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getRealValue_1
872 (JNIEnv *env, jobject obj, jint id, jint vr) {
875 const char *error = "";
878 if (fmi.version == 1) {
879 value = FMI1_CS_GET_REAL(fmi.fmu, vr, &error);
880 } else if (fmi.version == 2) {
881 value = FMI2_CS_GET_REAL(fmi.fmu, vr, &error);
883 if (!isEmpty(error)) {
884 string message = "Could not get real value: ";
885 return throwFMILException(env, message += error);
890 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_getIntegerValue_1
891 (JNIEnv *env, jobject obj, jstring id, jstring variable) {
893 const char *fmuId = env->GetStringUTFChars(id, 0);
895 FMUControlStruct fmuStruct = fmus[fmuId];
896 env->ReleaseStringUTFChars(id, fmuId);
897 const char *name = env->GetStringUTFChars(variable, 0);
899 if(referenceExists(fmuStruct, name)) {
900 fmiValueReference vr = getReference(fmuStruct, name);
902 fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &result);
903 env->ReleaseStringUTFChars(variable, name);
907 string nameString = name;
908 string message = "Variable " + nameString + " not found";
909 env->ReleaseStringUTFChars(variable, name);
910 return throwException(env, message);
914 string message = fmuId;
915 env->ReleaseStringUTFChars(id, fmuId);
916 return throwException(env, "unloadFMU: Model id " + message + " not found");
923 JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_getBooleanValue_1
924 (JNIEnv *env, jobject obj, jstring id, jstring variable) {
926 const char *fmuId = env->GetStringUTFChars(id, 0);
928 FMUControlStruct fmuStruct = fmus[fmuId];
929 env->ReleaseStringUTFChars(id, fmuId);
930 const char *name = env->GetStringUTFChars(variable, 0);
932 if(referenceExists(fmuStruct, name)) {
933 fmiValueReference vr = getReference(fmuStruct, name);
935 fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &result);
936 env->ReleaseStringUTFChars(variable, name);
940 string nameString = name;
941 string message = "Variable " + nameString + " not found";
942 env->ReleaseStringUTFChars(variable, name);
943 return throwException(env, message);
947 string message = fmuId;
948 env->ReleaseStringUTFChars(id, fmuId);
949 return throwException(env, "unloadFMU: Model id " + message + " not found");
955 JNIEXPORT jstring JNICALL Java_org_simantics_fmil_core_FMIL_getStringValue_1
956 (JNIEnv *env, jobject obj, jstring id, jstring variable) {
958 const char *fmuId = env->GetStringUTFChars(id, 0);
960 FMUControlStruct fmuStruct = fmus[fmuId];
961 env->ReleaseStringUTFChars(id, fmuId);
962 const char *name = env->GetStringUTFChars(variable, 0);
964 if(referenceExists(fmuStruct, name)) {
965 fmiValueReference vr = getReference(fmuStruct, name);
967 fmuStruct.fmu.getString(fmuStruct.c, &vr, 1, &result);
968 env->ReleaseStringUTFChars(variable, name);
969 return env->NewStringUTF(result);
972 string nameString = name;
973 string message = "Variable " + nameString + " not found";
974 env->ReleaseStringUTFChars(variable, name);
975 return 0; //throwException(env, message);
979 string message = fmuId;
980 env->ReleaseStringUTFChars(id, fmuId);
981 return 0; //throwException(env, "unloadFMU: Model id " + message + " not found");