]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMUSimulator/src/fmu_control.cpp
13272f1ac3657965abde7a1cb7c3d58e4c2eb433
[simantics/fmil.git] / org.simantics.fmil.core / native / FMUSimulator / src / fmu_control.cpp
1 /* ------------------------------------------------------------------------- 
2  * fmu_control.c
3  * Simulation controls for fmus
4  *
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  * -------------------------------------------------------------------------
12  */
13
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <map>
18 #include <string>
19 #include <vector>
20 #include <iostream>
21 #include <regex>
22 #include <atomic>
23
24 #include <org_simantics_fmil_FMILJNI.h>
25
26 extern "C" {
27         #include "fmi_me.h"
28         #include "sim_support.h"
29 }
30
31 #include "fmi1_cs.h"
32
33 #define PRINT(fmt,args) { FILE *fp = fopen("R:\\Simantics\\Sysdyn\\log.txt", "ab"); fprintf(fp, fmt, args); fclose(fp); }
34
35 using namespace std;
36
37 static std::atomic<int> instanceNameID;
38
39 int create_id() {
40     return instanceNameID++;
41 }
42
43 struct FMI1 {
44
45         void *fmu;
46
47         vector<string> variables;
48         vector<string> descriptions;
49         vector<string> declaredTypes;
50         vector<int> valueReferences;
51         vector<int> types;
52         vector<int> variabilities;
53         vector<int> causalities;
54
55         vector<string> declaredTypeNames;
56         vector<string> typeDescriptions;
57         vector<string> quantities;
58         vector<string> units;
59
60         vector<int> subscription;
61         double currentTime;
62         double timeStep;
63
64         int version;
65
66 };
67
68 struct FMUControlStruct {
69         double step;                                    // simulation step length
70         fmiReal currentTime;                    // current simulation time
71
72         fmiComponent c;                                 // instance of the fmu 
73         ScalarVariable** vars;                  // model variables
74
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
79
80         map<string,int> indexes;                // indexes for variable names in vars-table
81         map<string,int>::iterator it;
82
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
89         
90         bool initialized;                               // has the fmu been initialized
91
92         vector<fmiValueReference> subscription;         // result subscriptions
93         vector<string> allVariables;    // all variables in an initialized model
94         vector<fmiValueReference> fmiValueReferences;           // all value references
95
96         string lastErrorMessage;
97
98         FMU fmu;
99 };
100
101 vector<FMI1> fmus;
102
103 //map<string,FMUControlStruct> fmus;            // indexes for variable names in vars-table
104
105 int throwFMILException(JNIEnv *env, string message) {
106         jclass newExcCls;
107     newExcCls = env->FindClass("org/simantics/fmil/core/FMILException");
108     if (newExcCls == NULL) {
109             newExcCls = env->FindClass("java/lang/Exception");
110     }
111     if (newExcCls == NULL) {
112         /* Unable to find the exception class, give up. */
113         return 1;
114     }
115         env->ThrowNew(newExcCls, message.c_str());
116         return 1;
117 }
118
119 int throwException(JNIEnv *env, string message) {
120         return throwFMILException(env, message);
121 }
122
123 bool isEmpty(const char *c) {
124         if (c == NULL) {
125                 return true;
126         }
127         if (c[0] == '\0') {
128                 return true;
129         }
130         return false;
131 }
132
133 /*
134 bool exists(string id) {
135         map<string,FMUControlStruct>::iterator it = fmus.find(id);
136         if(it != fmus.end()) {
137                 return true;
138         } else {
139                 return false;
140         }
141 }
142 */
143
144
145
146 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_loadFMUFile_1 
147         (JNIEnv *env, jobject obj, jstring path, jstring tempDir) {
148
149         FMI1 fmi1;
150         FMIL_Variable *vars;
151         FMIL_DeclaredType *types;
152
153         int returnValue;
154
155         int variableCount = 0;
156         int typeCount = 0;
157
158         int fmuVersion = 0;
159         const char *error = "";
160
161     const char *fmuPath = env->GetStringUTFChars(path, 0);
162         const char *fmuTempDir = env->GetStringUTFChars(tempDir, 0);
163
164         fmi1.currentTime = 0;
165         fmi1.timeStep = 0.1;
166         returnValue = FMI_CS_LOAD(fmuPath, fmuTempDir, &fmi1.fmu, &fmuVersion, &error);
167
168         if (returnValue != 0) {
169                 string message = "Could not load FMU: ";
170                 return throwFMILException(env, message += error);
171         }
172         if(!fmi1.fmu) {
173                 string message = "No FMU loaded: ";
174                 return throwFMILException(env, message += error);
175         }
176
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);
182         }
183         if (!isEmpty(error)) {
184                 string message = "Could not get variables ";
185                 return throwFMILException(env, message += error);
186         }
187
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));
192            else
193                         fmi1.descriptions.push_back(string(""));
194            if(vars[i].declaredType)
195                         fmi1.declaredTypes.push_back(string(vars[i].declaredType));
196            else
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);
202    }
203
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);
208    }
209    if (!isEmpty(error)) {
210                 string message = "Could not get declared types ";
211                 return throwFMILException(env, message += error);
212         }
213
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));
218            else
219                         fmi1.typeDescriptions.push_back(string(""));
220            if(types[i].quantity)
221                         fmi1.quantities.push_back(string(types[i].quantity));
222            else
223                         fmi1.quantities.push_back(string(""));
224            if(types[i].unit)
225                         fmi1.units.push_back(string(types[i].unit));
226            else
227                         fmi1.units.push_back(string(""));
228    }
229
230
231    fmus.push_back(fmi1);
232
233         env->ReleaseStringUTFChars(path, fmuPath);
234         env->ReleaseStringUTFChars(tempDir, fmuTempDir);
235
236         return fmus.size() - 1;
237
238 }
239
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;
243         return 0;
244 }
245
246 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_subscribe_1
247   (JNIEnv *env, jobject obj, jint id, jintArray vrs) {
248
249         jboolean isCopy;
250         jint* elements = env -> GetIntArrayElements(vrs, &isCopy);
251         jsize n = env -> GetArrayLength(vrs);
252
253         int i;
254         for (i = 0; i < n; i++) {
255                 fmus[id].subscription.push_back(elements[i]);
256         } 
257           
258         if (isCopy == JNI_TRUE) {
259                 env -> ReleaseIntArrayElements(vrs, elements, 0);
260         }
261
262         return 0;
263
264 }
265
266 bool referenceExists(FMUControlStruct fmuStruct, string variable) {
267         map<string,int>::iterator it = fmuStruct.indexes.find(variable);
268         if(it != fmuStruct.indexes.end()) {
269                 return true;
270         } else {
271                 return false;
272         }
273 }
274
275 // Remember to check if reference exists
276 fmiValueReference getReference(FMUControlStruct fmuStruct, string variable) {
277         return fmuStruct.fmiValueReferences[fmuStruct.indexes[variable]];
278 }
279
280 // Get string representation of a scalar variable type
281 string getTypeString(ScalarVariable* sv) {
282         switch (sv->typeSpec->type){
283                 case elm_Integer:
284                         return "Integer";
285                 case elm_Enumeration:
286                         return "Enumeration";
287                 case elm_Real:
288                         return "Real";
289                 case elm_Boolean:
290                         return "Boolean";
291                 default:
292                         return "No type";
293         }
294 }
295
296 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setRealValue_1
297   (JNIEnv *env, jobject obj, jint id, jint vr, jdouble value) {
298
299           const char *error = "";
300           FMI1 fmi = fmus[id];
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);
305           }
306           if (!isEmpty(error)) {
307                   string message = "Could not set real value ";
308                   return throwFMILException(env, message += error);
309       }
310           return 0;
311 }
312
313 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setIntegerValue_1
314   (JNIEnv *env, jobject obj, jstring id, jstring parameter, jint value) {
315           /*
316         const char *fmuId = env->GetStringUTFChars(id, 0);
317         if(exists(fmuId)) {
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);
327                 } else {
328                         // Check variable type
329                         ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]];
330                         switch (sv->typeSpec->type){
331                                 case elm_Integer:
332                                         break; // ok
333                                 default: {
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);
338                                 }
339                         }
340
341                         // Change value
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);
347                         return 1;
348                 }
349         }  else {
350                 string message = fmuId;
351                 env->ReleaseStringUTFChars(id, fmuId);
352                 return throwException(env, "setIntegerValue: Model id " + message + " not found");
353         }
354         */
355           return 1;
356 }
357
358 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setBooleanValue_1
359   (JNIEnv *env, jobject obj, jstring id, jstring parameter, jboolean value) {
360           /*
361         const char *fmuId = env->GetStringUTFChars(id, 0);
362         if(exists(fmuId)) {
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);
372                 } else {
373                         // Check variable type
374                         ScalarVariable* sv = fmuStruct.vars[fmuStruct.indexes[name]];
375                         switch (sv->typeSpec->type){
376                                 case elm_Boolean:
377                                         break; // ok
378                                 default: {
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);
383                                 }
384                         }
385
386                         // Change value
387                         fmiValueReference vr = getReference(fmuStruct, name);
388                         fmiBoolean result = 1;
389                         if(value == 0)
390                                 result = 0;
391                         fmuStruct.fmu.setBoolean(fmuStruct.c, &vr, 1, &result);
392                         env->ReleaseStringUTFChars(parameter, name);
393                         env->ReleaseStringUTFChars(id, fmuId);
394                         return 1;
395                 }
396         }  else {
397                 string message = fmuId;
398                 env->ReleaseStringUTFChars(id, fmuId);
399                 return throwException(env, "setBooleanValue: Model id " + message + " not found");
400         }*/
401           return 1;
402 }
403
404 JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_isInitialized_1
405   (JNIEnv *env, jobject obj, jstring id) {
406           /*
407         const char *fmuId = env->GetStringUTFChars(id, 0);
408         if(exists(fmuId)) {
409                 FMUControlStruct& fmuStruct = fmus[fmuId];
410                 env->ReleaseStringUTFChars(id, fmuId);
411                 return fmuStruct.initialized;
412         } else {
413                 env->ReleaseStringUTFChars(id, fmuId);
414                 return false;
415         }
416         */
417           return 1;
418 }
419
420
421 JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getTime_1
422   (JNIEnv *env, jobject obj, jint id) {
423           return fmus[id].currentTime;
424 }
425
426 double getRealValue(FMUControlStruct fmuStruct, int index) {
427         ScalarVariable *sv = fmuStruct.vars[index];
428         fmiValueReference vr = fmuStruct.fmiValueReferences[index];
429         double real;
430         fmiInteger integer;
431         fmiBoolean fmibool;
432
433         switch (sv->typeSpec->type){
434         case elm_Real:
435                         fmuStruct.fmu.getReal(fmuStruct.c, &vr, 1, &real);
436             break;
437         case elm_Integer:
438         case elm_Enumeration:
439             fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &integer);
440                         real = (double)integer;
441             break;
442         case elm_Boolean:
443             fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &fmibool);
444                         if(fmibool == fmiTrue)
445                                 real = 1.0;
446                         else
447                                 real = 0.0;
448             break;
449         }
450         return real;
451 }
452
453 JNIEXPORT jdoubleArray JNICALL Java_org_simantics_fmil_core_FMIL_getSubscribedResults_1
454   (JNIEnv *env, jobject obj, jint id, jdoubleArray result) {
455
456         jboolean isCopy;
457         jdouble* resultElements = env -> GetDoubleArrayElements(result, &isCopy);
458         jsize n = env -> GetArrayLength(result);
459         int *vrs;
460         const char *error = "";
461
462         FMI1 fmi = fmus[id];
463         if(n > 0) {
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);
469                 }
470         }
471         if (isCopy == JNI_TRUE) {
472                 env -> ReleaseDoubleArrayElements(result, resultElements, 0);
473         }
474
475         return result;
476         
477 }
478
479 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_instantiateSimulation_1
480   (JNIEnv *env, jobject obj, jint id) {
481
482           int uniqueId = create_id();
483           std::string instanceName = std::to_string(uniqueId);
484           int returnValue;
485           const char *error = "";
486
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);
492           }
493           if(returnValue != 0) {
494                 string message = "No FMU loaded: ";
495                 return throwFMILException(env, message += error);
496           }
497           return 0;
498 }
499
500 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_initializeSimulation_1
501   (JNIEnv *env, jobject obj, jint id) {
502         
503         const char *error = "";
504         int returnValue;
505         FMI1 fmi = fmus[id];
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);
510         }
511         if(returnValue != 0) {
512                 string message = "Could not initialize simulation: ";
513                 return throwFMILException(env, message += error);
514         }
515
516         return 0;
517
518 }
519
520 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_setTime_1
521   (JNIEnv *env, jobject obj, jstring id, jdouble time) {
522           return 0;
523 }
524
525 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariables_1
526   (JNIEnv *env, jobject obj, jint id) {
527
528         jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].variables.size(),  
529                         env->FindClass("java/lang/String"),  
530                         env->NewStringUTF(""));  
531    
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()));  
534         }  
535
536         return ret;  
537
538 }
539
540 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDescriptions_1
541   (JNIEnv *env, jobject obj, jint id) {
542
543         jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].descriptions.size(),  
544                         env->FindClass("java/lang/String"),  
545                         env->NewStringUTF(""));  
546    
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()));  
549         }  
550
551         return ret;  
552
553 }
554
555 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableDeclaredTypes_1
556   (JNIEnv *env, jobject obj, jint id) {
557
558         jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypes.size(),  
559                         env->FindClass("java/lang/String"),  
560                         env->NewStringUTF(""));
561    
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()));  
564         }  
565
566         return ret;  
567
568 }
569
570 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableReferences_1
571   (JNIEnv *env, jobject obj, jint id, jintArray result) {
572
573         jboolean isCopy;
574         jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
575         jsize n = env -> GetArrayLength(result);
576
577         int i;
578         for (i = 0; i < n; i++) {
579                 resultElements[i] = fmus[id].valueReferences[i];
580         } 
581           
582         if (isCopy == JNI_TRUE) {
583                 env -> ReleaseIntArrayElements(result, resultElements, 0);
584         }
585
586         return result;
587
588 }
589
590 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableTypes_1
591   (JNIEnv *env, jobject obj, jint id, jintArray result) {
592
593         jboolean isCopy;
594         jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
595         jsize n = env -> GetArrayLength(result);
596
597         int i;
598         for (i = 0; i < n; i++) {
599                 resultElements[i] = fmus[id].types[i];
600         } 
601           
602         if (isCopy == JNI_TRUE) {
603                 env -> ReleaseIntArrayElements(result, resultElements, 0);
604         }
605
606         return result;
607
608 }
609
610 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableVariabilities_1
611   (JNIEnv *env, jobject obj, jint id, jintArray result) {
612
613         jboolean isCopy;
614         jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
615         jsize n = env -> GetArrayLength(result);
616
617         for (jsize i = 0; i < n; i++) {
618                 resultElements[i] = fmus[id].variabilities[i];
619         } 
620           
621         if (isCopy == JNI_TRUE) {
622                 env -> ReleaseIntArrayElements(result, resultElements, 0);
623         }
624
625         return result;
626
627 }
628
629 JNIEXPORT jintArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllVariableCausalities_1
630   (JNIEnv *env, jobject obj, jint id, jintArray result) {
631
632         jboolean isCopy;
633         jint* resultElements = env -> GetIntArrayElements(result, &isCopy);
634         jsize n = env -> GetArrayLength(result);
635
636         for (jsize i = 0; i < n; i++) {
637                 resultElements[i] = fmus[id].causalities[i];
638         } 
639           
640         if (isCopy == JNI_TRUE) {
641                 env -> ReleaseIntArrayElements(result, resultElements, 0);
642         }
643
644         return result;
645
646 }
647
648 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypes_1
649   (JNIEnv *env, jobject obj, jint id) {
650
651         jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].declaredTypeNames.size(),  
652                         env->FindClass("java/lang/String"),  
653                         env->NewStringUTF(""));
654    
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()));  
657         }  
658
659         return ret;  
660
661 }
662
663 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeDescriptions_1
664   (JNIEnv *env, jobject obj, jint id) {
665
666         jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].typeDescriptions.size(),  
667                         env->FindClass("java/lang/String"),  
668                         env->NewStringUTF(""));
669    
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()));  
672         }  
673
674         return ret;  
675
676 }
677
678 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeQuantities_1
679   (JNIEnv *env, jobject obj, jint id) {
680
681         jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].quantities.size(),  
682                         env->FindClass("java/lang/String"),  
683                         env->NewStringUTF(""));
684    
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()));  
687         }  
688
689         return ret;  
690
691 }
692
693 JNIEXPORT jobjectArray JNICALL Java_org_simantics_fmil_core_FMIL_getAllDeclaredTypeUnits_1
694   (JNIEnv *env, jobject obj, jint id) {
695
696         jobjectArray ret= (jobjectArray)env->NewObjectArray(fmus[id].units.size(),  
697                         env->FindClass("java/lang/String"),  
698                         env->NewStringUTF(""));
699    
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()));  
702         }  
703
704         return ret;  
705
706 }
707
708 /*
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);
714          return result;
715 }
716 */
717
718 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_simulateStep_1
719   (JNIEnv *env, jobject obj, jint id) {
720
721           int returnValue;
722           const char *error = "";
723
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);
729           }
730           if(returnValue != 0) {
731                   string message = "Could not simulate step: ";
732                   return throwException(env,  message += error);
733           }
734
735           fmi.currentTime += fmi.timeStep;
736
737           return 0;
738
739           /*
740         const char *fmuId = env->GetStringUTFChars(id, 0);
741         if(exists(fmuId)) {
742                 FMUControlStruct& fmuStruct = fmus[fmuId];
743                 env->ReleaseStringUTFChars(id, fmuId);
744
745                 if(&fmuStruct.fmu == NULL || fmuStruct.fmu.modelDescription == NULL || &fmuStruct.vars == NULL) {
746                         return throwException(env, "Simulate step failed - fmu not loaded");
747                 }
748
749                 if(fmuStruct.x == NULL) {
750                         return throwException(env, "Simulate step failed - fmu not instantiated");
751                 }
752
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;
758                 }
759
760                 FMU& fmu = fmuStruct.fmu;
761                 int debug = 0; // DEBUG ON = 1, OFF = 0
762
763                 int i;
764                 double dt, tPre, tEnd = fmuStruct.currentTime + fmuStruct.step;
765
766                 fmiBoolean timeEvent, stateEvent, stepEvent;
767                 fmiStatus fmiFlag;                      // return code of the fmu functions
768                 fmiValueReference vr;
769
770
771                 */
772                 /* Simulate the duration of one step. The simulation may be done in 
773                  * multiple parts if events occur
774                  */ /*
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");
780
781                         fmiFlag = fmu.getDerivatives(fmuStruct.c, fmuStruct.xdot, fmuStruct.nx);
782                         if (fmiFlag > fmiWarning) 
783                                 return throwException(env, "could not retrieve derivatives");
784
785                          // advance time
786                         tPre = fmuStruct.currentTime;
787                         fmuStruct.currentTime = min(fmuStruct.currentTime+fmuStruct.step, tEnd);
788                         timeEvent = fmuStruct.eventInfo.upcomingTimeEvent && fmuStruct.eventInfo.nextEventTime < fmuStruct.currentTime;  
789                 
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");
794
795                         if(referenceExists(fmuStruct, "time")) {
796                                 vr = getReference(fmuStruct, "time");
797                                 if(vr != NULL) {
798                                         fmu.setReal(fmuStruct.c, &vr, 1, &(fmuStruct.currentTime));
799                                 }
800                         }
801
802                         if(debug)
803                                 printf("Actual time: %lf\n", fmuStruct.currentTime);
804
805                         if (fmiFlag > fmiWarning) 
806                                 return throwException(env, "could not set time");
807
808                         // perform one step
809                         for (i=0; i<fmuStruct.nx; i++) 
810                                 fmuStruct.x[i] += dt*fmuStruct.xdot[i]; // forward Euler method
811
812                         fmiFlag = fmu.setContinuousStates(fmuStruct.c, fmuStruct.x, fmuStruct.nx);
813                         if (fmiFlag > fmiWarning) 
814                                 return throwException(env, "could not set states");
815
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");
819                         */
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");
823                         stateEvent = FALSE;
824                         for (i=0; i<fmuStruct.nz; i++) 
825                                 stateEvent = stateEvent || (fmuStruct.prez[i] * fmuStruct.z[i] < 0);  
826      
827
828                         stepEvent = fmiTrue;
829                         // handle events
830                         if (timeEvent || stateEvent || stepEvent) {
831         
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");
835       
836                         } // if event
837                         */
838         
839 /*              }
840
841                 fflush(stdout);
842                 return 1;
843
844         } else {
845                 string message = fmuId;
846                 env->ReleaseStringUTFChars(id, fmuId);
847                 return throwException(env, "simulateStep: Model id " + message + " not found");
848         }*/
849         return 1;
850 }
851
852 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_unloadFMU_1
853   (JNIEnv *env, jobject obj, jint id) {
854
855           int returnValue;
856           const char *error = "";
857
858           FMI1 fmi = fmus[id];
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);
863           }
864           if(returnValue != 0) {
865                 string message = "Could not unload FMU: ";
866                 return throwException(env, message += error);
867           }
868           return returnValue;
869 }
870
871 JNIEXPORT jdouble JNICALL Java_org_simantics_fmil_core_FMIL_getRealValue_1
872   (JNIEnv *env, jobject obj, jint id, jint vr) {
873
874           double value;
875           const char *error = "";
876
877           FMI1 fmi = fmus[id];
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);
882           }
883           if (!isEmpty(error)) {
884                   string message = "Could not get real value: ";
885                   return throwFMILException(env, message += error);
886           }
887           return value;
888 }
889
890 JNIEXPORT jint JNICALL Java_org_simantics_fmil_core_FMIL_getIntegerValue_1
891   (JNIEnv *env, jobject obj, jstring id, jstring variable) {
892           /*
893         const char *fmuId = env->GetStringUTFChars(id, 0);
894         if(exists(fmuId)) {
895                 FMUControlStruct fmuStruct = fmus[fmuId];
896                 env->ReleaseStringUTFChars(id, fmuId);
897                 const char *name = env->GetStringUTFChars(variable, 0);
898
899                 if(referenceExists(fmuStruct, name)) {
900                         fmiValueReference vr = getReference(fmuStruct, name);
901                         int result;
902                         fmuStruct.fmu.getInteger(fmuStruct.c, &vr, 1, &result);
903                         env->ReleaseStringUTFChars(variable, name);
904                         return result;
905
906                 } else {
907                          string nameString = name;
908                          string message = "Variable " + nameString + " not found";
909                          env->ReleaseStringUTFChars(variable, name);
910                          return throwException(env, message);
911                 }
912
913         } else {
914                 string message = fmuId;
915                 env->ReleaseStringUTFChars(id, fmuId);
916                 return throwException(env, "unloadFMU: Model id " + message + " not found");
917         }
918         */
919           return 1;
920
921 }
922
923 JNIEXPORT jboolean JNICALL Java_org_simantics_fmil_core_FMIL_getBooleanValue_1
924   (JNIEnv *env, jobject obj, jstring id, jstring variable) {
925           /*
926         const char *fmuId = env->GetStringUTFChars(id, 0);
927         if(exists(fmuId)) {
928                 FMUControlStruct fmuStruct = fmus[fmuId];
929                 env->ReleaseStringUTFChars(id, fmuId);
930                 const char *name = env->GetStringUTFChars(variable, 0);
931
932                 if(referenceExists(fmuStruct, name)) {
933                         fmiValueReference vr = getReference(fmuStruct, name);
934                         fmiBoolean result;
935                         fmuStruct.fmu.getBoolean(fmuStruct.c, &vr, 1, &result);
936                         env->ReleaseStringUTFChars(variable, name);
937                         return result;
938
939                 } else {
940                          string nameString = name;
941                          string message = "Variable " + nameString + " not found";
942                          env->ReleaseStringUTFChars(variable, name);
943                          return throwException(env, message);
944                 }
945
946         } else {
947                 string message = fmuId;
948                 env->ReleaseStringUTFChars(id, fmuId);
949                 return throwException(env, "unloadFMU: Model id " + message + " not found");
950         }*/
951           return 1;
952
953 }
954
955 JNIEXPORT jstring JNICALL Java_org_simantics_fmil_core_FMIL_getStringValue_1
956   (JNIEnv *env, jobject obj, jstring id, jstring variable) {
957           /*
958         const char *fmuId = env->GetStringUTFChars(id, 0);
959         if(exists(fmuId)) {
960                 FMUControlStruct fmuStruct = fmus[fmuId];
961                 env->ReleaseStringUTFChars(id, fmuId);
962                 const char *name = env->GetStringUTFChars(variable, 0);
963
964                 if(referenceExists(fmuStruct, name)) {
965                         fmiValueReference vr = getReference(fmuStruct, name);
966                         fmiString result;
967                         fmuStruct.fmu.getString(fmuStruct.c, &vr, 1, &result);
968                         env->ReleaseStringUTFChars(variable, name);
969                         return env->NewStringUTF(result);
970
971                 } else {
972                          string nameString = name;
973                          string message = "Variable " + nameString + " not found";
974                          env->ReleaseStringUTFChars(variable, name);
975                          return 0; //throwException(env, message);
976                 }
977
978         } else {
979                 string message = fmuId;
980                 env->ReleaseStringUTFChars(id, fmuId);
981                 return 0; //throwException(env, "unloadFMU: Model id " + message + " not found");
982         }
983         */
984           return 0;
985
986 }