Main /
Functional Mock Up (FMU) Interface (FMI)This page contains notes about the Functional Mock Up interface Getting StartedSee the FMUImport javadoc for how to import a FMU into Ptolemy See AlsoJFMISee JFMI for a Java interface to FMI Debugging a Mac FMUDebugging an FMU from Java is like fighting drunk polar bears in a snowstorm. Soo... a debugger is useful. These instructions worked for me with Java 1.6.0_45 under Mac OS 10.7.5. Your mileage may vary. Under Mac OS X, to create a shared library that includes the line information for debugging, you must include the .c file in the link line (See http://stackoverflow.com/questions/584825/dsym-directories-while-compiling-c-code-in-macos) To compile the FMU, I used: cc -dynamiclib -g -o ../binaries/darwin64/stepCounterExtendedFMI.dylib stepCounterExtendedFMI.c In Ptolemy, the fmus include a build script in the source directory. To build a FMU under Mac OS X: cd $PTII/ptolemy/actor/lib/fmi/fmus/stepCounterExtendedFMI make make update The last step updates the FMU in ptolemy/actor/lib/fmi/test/auto, which is what the FMU we are going to run uses. The next step is to invoke gdb. I used bash-3.2$ cd $PTII/ptolemy/actor/lib/fmi bash-3.2$ which java /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java bash-3.2$ gdb /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java GNU gdb 6.3.50-20050815 (Apple version gdb-1752) (Sat Jan 28 03:02:46 UTC 2012) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries ...... done (gdb) The next step is to start up vergil from gdb. I used the following gdb command. You would need to adjust the classpath (gdb) r -classpath $PTII:${PTII}/lib/jna.jar ptolemy.vergil.VergilApplication test/auto/FMUStepCounterExtendedFMI.xml Starting program: /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java -classpath $PTII:${PTII}/lib/jna.jar ptolemy.vergil.VergilApplication test/auto/FMUStepCou\ nterExtendedFMI.xml Reading symbols for shared libraries .+++++............................................................... done Reading symbols for shared libraries .. done Reading symbols for shared libraries ....................................................................... done Reading symbols for shared libraries ......... done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Reading symbols for shared libraries . done FMUFile: Extracting to /private/var/folders/04/1dxv0z9j44n9jlwxtb3xl1sm0000gn/T/FMUFile7093856433674665174.tmp Reading symbols for shared libraries . done Jun 6 15:53:25 x945136 java[25749] <Error>: CGContextGetCTM: invalid context 0x0 Jun 6 15:53:25 x945136 java[25749] <Error>: CGContextSetBaseCTM: invalid context 0x0 Jun 6 15:53:25 x945136 java[25749] <Error>: CGContextGetCTM: invalid context 0x0 Jun 6 15:53:25 x945136 java[25749] <Error>: CGContextSetBaseCTM: invalid context 0x0 The next step is to stop gdb with Control-C and set a breakpoint C-c C-c Program received signal SIGINT, Interrupt. 0x00007fff8d3e267a in mach_msg_trap () (gdb) break stepCounterExtendedFMI_fmiInitializeSlave Function "stepCounterExtendedFMI_fmiInitializeSlave" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (stepCounterExtendedFMI_fmiInitializeSlave) pending. Then, type (gdb) cont Continuing. Reading symbols for shared libraries . done Reading symbols for shared libraries . done warning: Can't find backing file for "/private/var/folders/04/1dxv0z9j44n9jlwxtb3xl1sm0000gn/T/jna-cxh/jna614199732232814840.tmp". Breakpoint 1 at 0x107f1f765: file stepCounterExtendedFMI.c, line 328. Pending breakpoint 1 - "stepCounterExtendedFMI_fmiInitializeSlave" resolved FMUImport: FIXME: Disabling logging because of errors Foo Foo .FMUStepCounterExtendedFMI.stepCounterExtendedFMI: Invoked fmiInstantiateSlave. FMUImport: FIXME: Disabling logging because of errors Foo Foo .FMUStepCounterExtendedFMI.stepCounterExtendedFMI2: Invoked fmiInstantiateSlave. .FMUStepCounterExtendedFMI.stepCounterExtendedFMI: Setting real value with index 1 and value 0.3. [Switching to process 25749 thread 0x10413] Breakpoint 1, stepCounterExtendedFMI_fmiInitializeSlave (c=0x102070e10, relativeTolerance=0.0001, tStart=0, stopTimeDefined=1, tStop=3) at stepCounterExtendedFMI.c:328 328 ModelInstance* component = (ModelInstance *) c; (gdb) Use the typical gdb commands to step through the model and print variables: gdb) step Current language: auto; currently minimal 333 printf("%s: Invoked fmiIntializeSlave: start: %g, StopTimeDefined: %d, tStop: %g..\n", (gdb) print component $1 = (ModelInstance *) 0x102070e10 (gdb) print *component $2 = {currentCount = 0, period = 0.29999999999999999, lastSuccessfulTime = -1, atBreakpoint = 0, relativeTolerance = 0, functions = 0x102065280, instanceName = 0x102066780 ".FMUStepC\ ounterExtendedFMI.stepCounterExtendedFMI"} (gdb) cont Continuing. .FMUStepCounterExtendedFMI.stepCounterExtendedFMI: Invoked fmiIntializeSlave: start: 0, StopTimeDefined: 1, tStop: 3.. .FMUStepCounterExtendedFMI.stepCounterExtendedFMI2: Setting real value with index 1 and value 0.5. Breakpoint 1, stepCounterExtendedFMI_fmiInitializeSlave (c=0x102070270, relativeTolerance=0.0001, tStart=0, stopTimeDefined=1, tStop=3) at stepCounterExtendedFMI.c:328 328 ModelInstance* component = (ModelInstance *) c; (gdb) Running a Win-32 bit FMUDymola and OpenModelica produce 32-bit dlls, so we need to use a 32-bit JVM. 1. Get an account on 4. Use Christopher's tree, (or http://chess.eecs.berkeley.edu/ptexternal/ check out your own, be sure to use a 32-bit JVM, see below) export PTII=c:/Users/cxh.EECS/ptII 5. Dymola and OpenModelica produce 32-bit dlls, so we need to use a 32-bit JVM. export PATH=/cygdrive/c//Program\ Files\ \(x86\)/Java/jdk1.7.0_21/bin:${PATH} 6. Put $PTII/lib in your PATH export PATH=${PTII}/bin:${PATH} 7. cd to the demo and run it. Unfortunately, the scripts in $PTII/bin do not work under MinGW because MinGW does not understand Cygwin symbolic links and MinGW does not run .bat scripts. So, we run by hand cd $PTII/ptolemy/actor/lib/fmi/fmipp/demo/FMUModelExchange java -classpath $PTII ptolemy.vergil.VergilApplication FMUModelExchange.xml Problem: IncrementalFMU_wrap.dll: Can't find dependent librariesI used Dependency Walker from http://www.dependencywalker.com/ cd $PTII/bin /usr/local/bin/depends Inc*.dll LIBEXPAT-1.dll and LIBSTDC++.dll were missing. Solution: Be sure that you are running inside the MinGW Shell and not Cygwin. Linux Symbol Problems.Summary: Loading two different FMUs into Ptolemy II causes the JVM to crash if the shared libraries of the FMU files have functions with the same name. This is very odd, and points to a problem possibly with JNA. The fix is to 1. edit the .c file that defines the FMU and, before fmuTemplate.h is included, // We require that functions have prefixes for Linux. #if defined _WIN32 || defined __CYGWIN__ /* Note: both gcc & MSVC on Windows support this syntax. */ #define FMI_Export __declspec(dllexport) #else #if __GNUC__ >= 4 #define FMI_Export __attribute__ ((visibility ("default"))) #else #define FMI_Export #endif #endif // _WIN32 || defined __CYGWIN__ 2. For each method in the .c file, preface it with a #define: // Ptolemy specific define: #define initialize fmiFullName(initialize) void initialize(ModelInstance* comp, fmiEventInfo* eventInfo) { See The FMI2.0RC2 standard says: "The goal is that both textual and binary representations of FMUs are supported and that several FMUs might be present at the same time in an executable (for example FMU A may use an FMU B). In order for this to be possible, the names of the functions in different FMUs must be different or function pointers must be used. To support the first variant macros are provided in “fmi2Functions.h” to build the actual function names by using a function prefix that depends on how the FMU is shipped. Typically, FMU functions are used as follows:
// FMU is shipped with C source code, or with static link library #define FMI2_FUNCTION_PREFIX MyModel_ #include "fmi2Functions.h" < usage of the FMU functions > // FMU is shipped with DLL/SharedObject #include "fmi2Functions.h" < usage of the FMU functions > "A function that is defined as “fmi2GetReal” is changed by the macros to the following function name:"
"FMU is shipped with C source code, or with static link library:"
"The constructed function name is “MyModel_fmi2GetReal”, in other words the function name is prefixed with the model name and an “_”. As FMI2_FUNCTION_PREFIX the “modelIdentifier” ”attribute defined in <fmiModelDescription><ModelExchange>, or <fmiModelDescription><CoSimulation> is used, together with “_” at the end (see sections 3.3.1 and 4.3.1). A simulation environment can therefore construct the relevant function names by generating code for the actual function call. In case of a static link library, the name of the library is MyModel.lib on Windows, and libMyModel.a on Linux, in other words the “modelIdentifier” attribute is used as library name."
"FMU is shipped with DLL/SharedObject: "
"The constructed function name is “fmi2GetReal”, in other words it is not changed. A simulation environment will then dynamically load this library and will explicitly import the function symbols by providing the FMI function names as strings. The name of the library is MyModel.dll on Windows or MyModel.so on Linux, in other words the “modelIdentifier” attribute is used as library name."
"[An FMU can be optionally shipped so that it basically contains only the communication to another tool (needsExecutionTool = true, see section 4.3.1). This is particularily common for co-simulation tasks. In FMI 1.0, the function names are always prefixed with the model name and therefore a DLL/Shared Object has to be generated for every model. FMI 2.0 improves this situation since model names are no longer used as prefix in case of DLL/Shared Objects: Therefore one DLL/Shared Object can be used for all models in case of tool coupling. If an FMU is imported into a simulation environment, this is usually performed dynamically (based on the FMU name, the corresponding FMU is loaded during execution of the simulation environment) and then it does not matter whether a model name is prefixed or not.]"
"Since “modelIdentifier” is used as prefix of a C-function name it must fulfill the restrictions on C-function names (only letters, digits and/or underscores are allowed). [For example if modelName = “A.B.C“, then modelIdentifier might be “A_B_C“]. Since “modelIdentifier” is also used as name in a file system, it must also fulfill the restrictions of the targeted operating system. Basically, this means that it should be short. For example the Windows API only supports full path-names of a file up to 260 characters (see: http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx)."
Solution to the Linux Multiple FMUs problmeThe solution was to properly define the export. See Incorrect setting of FMU_Export in fmiFunctions.h for FMI2.0rc1, which states that fmiFunctions.h should be changed from #if !defined(FMI_Export) && !defined(FMI_FUNCTION_PREFIX) #if defined _WIN32 || defined __CYGWIN__ /* Note: both gcc & MSVC on Windows support this syntax. */ #define FMI_Export __declspec(dllexport) #else #if __GNUC__ >= 4 #define FMI_Export __attribute__ ((visibility ("default"))) #else #define FMI_Export #endif #endif #endif to #if !defined(FMI_Export) #if !defined(FMI_FUNCTION_PREFIX) #if defined _WIN32 || defined __CYGWIN__ /* Note: both gcc & MSVC on Windows support this syntax. */ #define FMI_Export __declspec(dllexport) #else #if __GNUC__ >= 4 #define FMI_Export __attribute__ ((visibility ("default"))) #else #define FMI_Export #endif #endif #else #define FMI_Export #endif #endif Also, it seems necessary to compile with, Complications with Linux SymbolsIn a nutshell, the problem is that if, under Linux, two FMUs are loaded, and they have functions with the same name, then there can be problems about which function is invoked. This indicates that it is best if the functions are not changed for the different FMUs. This also points out possible problems with using multiple FMUs from different versions of the FMU standard. DetailsWe had two FMUs:
If a Ptolemy model containing the tankOpen FMU was run first, then when the Ptolemy model containing the values20RC1 FMU would fail: Caused by: ptolemy.kernel.util.IllegalActionException: Test fails in iteration 0. Value was: "". Should have been: "jan" Adding a fprintf to tankOpen.c indicates that the fmiSetString() method in tankOpen.c is being called FMI_Export fmiStatus fmiSetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString value[]) { fprintf(stderr, "tankOpen.c: fmiSetString(): About to return fmiError!"); fflush(stderr); return fmiError; } This can be seen in the output: ------------------ testing $PTII/ptolemy/actor/lib/fmi/test/auto/FMUvalues20RC1.xml auto.tcl: Setting watchdog for 200 seconds at Thu Jul 10 19:18:18 PDT 2014 FMUFile: Extracting to /tmp/FMUFile5781659864485141019.tmp values20RC1 fmiInstantiate() about to call setStartValues values20RC1.c: setStartValues() start values20RC1 fmuTemplate.c setString(,,a string) tankOpen.c: fmiSetString(): About to return fmiError!values20RC1 fmuTemplate.c setString(,,jan) tankOpen.c: fmiSetString(): About to return fmiError!values20RC1.c: setStartValues() end values20RC1 fmiInstantiate() done calling setStartValues ok .FMUvalues20RC1.values20RC(logFmiCall): values20RC1 fmiInstantiate: GUID={8c4e810f-3df3-4a00-8276-176fa3c9a201} ok .FMUvalues20RC1.values20RC(logFmiCall): fmiSetupExperiment: toleranceDefined=0 tolerance=0.000100000 ok .FMUvalues20RC1.values20RC(logFmiCall): fmiEnterInitializationMode ok .FMUvalues20RC1.values20RC(logFmiCall): fmiExitInitializationMode ok .FMUvalues20RC1.values20RC(logFmiCall): fmiSetInteger: nvr = 1 ok .FMUvalues20RC1.values20RC(logFmiCall): fmiSetInteger: int_in = 0 ok .FMUvalues20RC1.values20RC(logFmiCall): fmiSetBoolean: nvr = 1 ok .FMUvalues20RC1.values20RC(logFmiCall): fmiSetBoolean: bool_in = true values20RC1 fmuTemplate.c fmiSetString() ok .FMUvalues20RC1.values20RC(logFmiCall): fmiSetString: nvr = 1 values20RC1 fmuTemplate.c setString 0 <January> ok .FMUvalues20RC1.values20RC(logFmiCall): fmiSetString: string_in = 'January' ok .FMUvalues20RC1.values20RC(logFmiCall): fmiGetInteger: int_out = 0 ok .FMUvalues20RC1.values20RC(logFmiCall): fmiGetBoolean: bool_out = false values20RC1 fmuTemplate.c getString 1 <(null)> ok .FMUvalues20RC1.values20RC(logFmiCall): fmiGetString: string_out = '<null>' 26 ms. Memory: 244608K Free: 231136K (94%) Exception in thread "Thread-8" java.lang.RuntimeException: Execution failed at ptolemy.moml.MoMLSimpleApplication$UnloadThread.run(MoMLSimpleApplication.java:347) Caused by: ptolemy.kernel.util.IllegalActionException: Test fails in iteration 0. Value was: "". Should have been: "jan" What's happening here is that values20RC1.c has: void setStartValues(ModelInstance *comp) { fprintf(stderr, "values20RC1.c: setStartValues() start\n"); r(x_) = 1; i(int_in_) = 2; i(int_out_) = 0; b(bool_in_) = fmiTrue; b(bool_out_) = fmiFalse; copy(string_in_, "a string"); copy(string_out_, month[0]); fprintf(stderr, "values20RC1.c: setStartValues() end\n"); } The fmiStatus setString(fmiComponent comp, fmiValueReference vr, fmiString value); #define copy(vr, value) setString(comp, vr, value)
fmiStatus setString(fmiComponent comp, fmiValueReference vr, fmiString value){ fprintf(stderr, "values20RC1 fmuTemplate.c setString(,,%s)\n", value); fflush(stderr); return fmiSetString(comp, &vr, 1, &value); } What is happening here is we properly invoke the correct This probably occurs because tankOpen was loaded with A few best practices for writing FMUs
8-Dec-2014: Ok, Incorrect behavior loading multi librarys has a similar problem and suggests: Map options = new HashMap(); options.put(Library.OPTION_OPEN_FLAGS, new Integer(1)); Native.register(getClass(), NativeLibrary.getInstance(library, options)); FMI++
Building FMI++ under WindowsMingwInstall Mingw from http://sourceforge.net/projects/mingw/files/MinGW/ When installing, be sure to select c++. I also selected the full development environment BoostInstall Boost in See https://code.google.com/p/pcxprj/wiki/BoostCompiledByMinGW Start up the mingw shell, and in the boost sources: bootstrap bjam install --prefix=c:\Tools\boost_1_53_0 --build-type=complete toolset=gcc link=static threading=single,multi runtime-link=static libexpatDownload libexpat*-dev.tar.gz from http://sourceforge.net/projects/mingw/files/MinGW/Extension/expat/expat-2.0.1-1/ cd c:/Tools mkdir expat-2.1.0 cd expat-2.1.0 and then tar -zxf the downloaded Building FMI++ under Mac OS XGet the FMI++ source: git clone git://git.code.sf.net/p/fmipp/code fmipp-code Get Boost, which contains odeintUnder Mac OS X, versions of Boost after 1.53 will include odeint. If bash-3.2$ ls /opt/local/include/boost/numeric/odeint algebra config.hpp external integrate stepper util version.hpp If If you have MacPorts installed, then use: port install boost If you don't have Mac Ports installed, then download boost from http://sourceforge.net/projects/boost/files/boost/1.53.0/ BTW - there are no instructions on how to build odeint? That's because it uses C++ templates and there is nothing to compile in advance. Building Boost Under LinuxUnder Linux, I did: yum install boost wget --no-check-certificate http://github.com/headmyshoulder/odeint-v2/tarball/master tar -zxf master mv headmyshoulder-odeint-v2-fe7afc4/include/boost/numeric/* /usr/include/boost/numeric/ However, that didn't work, there were missing files. As root: mkdir /usr/local/boost_1_57_0 chown yourlogin /usr/local/boost_1_57_0 cd /usr/local/include ln -s ../boost/include/boost . As yourself: Download from http://boost.org and untar, then run ./bootstrap.sh --prefix=/usr/local/boost_1_57_0 ./b2 install --build-dir=/tmp/build-boost --prefix=/usr/local/boost_1_57_0 Build SwigUnder Mac OS X port install swig-java Building Swig from sourceUnder Mac OS X, this is probably wrong, try mac ports instead. Under Linux, I had to build Swig Under Linux: download from http://www.swig.org/download.html wget http://prdownloads.sourceforge.net/swig/swig-2.0.9.tar.gz tar -zxf swig-2.0.9.tar.gz cd swig-2.0.9 ./configure make Under Linux as root: make install Building fmippEdit At the top: EXPAT_INCLUDE=/opt/local/include EXPAT_BIN=/opt/local/lib EXPAT_DLL=expat BOOST_INCLUDE=/opt/local/include/boost Add a build.macos rule build.macos: $(OBJECTS) mkdir -p lib $(CPP) -dynamiclib -o lib/libfmipp.so $(OBJECTS) -L$(EXPAT_BIN) -l$(EXPAT_DLL) -ldl make -f makefile.linux build.macos To build the Java/FMI++ interface, add the following rule: swig.macos:: swig -c++ -java -package ptolemy.actor.lib.fmipp.swig swig/IncrementalFMU.i $(CPP) $(INC) -c $(OPTFLAGS) $(CFLAGS) swig/IncrementalFMU_wrap.cxx -o swig/IncrementalFMU_wrap.o -I/Sy\ stem/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/../Headers $(CPP) -shared -o lib/libIncrementalFMU_wrap.so swig/IncrementalFMU_wrap.o -Llib -lfmipp -ldl -lexpat javac swig/*.java make -f makefile.linux swig.macos Running examples under FMI++It looks like the example requirea installing OpenModelica. How to test a FMUThere is a compatibility test on the FMU svn, but one quick test is to install FMU SDK and try loading the .fmu file that way. Another trick is to unzip the .fmu file and the use If you are getting missing symbols, try using the Invoking a 32-bit JavaIf you are using JFMI to invoke a FMU, then you will need to run a 32-bit JVM to invoke a 32-bit FMU or run a 64-bit JVM to invoke a 64-bit FMU. This only matters under Linux and Windows. Modern Mac OS X JVMs are typically 64-bit. To see what binaries are in your .fmu, unzip it. To run a 32-bit FMU, it is usually necessary to install a 32-bit JVM. Most platforms have the 64-bit JVM installed. To install a 32-bit JVM, go to the Oracle site and select a 32-bit JVM and install it. Locally, we have installed 32-bit JVMs in Set your path to include the 32-bit JVM and then reconfigure Ptolemy II. 32-bit JVM under LinuxThis is 64-bit JVM: bash-4.1$ java -version java version "1.7.0" Java(TM) SE Runtime Environment (build 1.7.0-b147) Java HotSpot(TM) 64-Bit Server VM (build 21.0-b17, mixed mode) This is a 32-bit JVM: bash-4.1$ export PATH=/usr/lib/jvm/jdk1.7.0_17x86/bin:${PATH} bash-4.1$ java -version java version "1.7.0_17" Java(TM) SE Runtime Environment (build 1.7.0_17-b02) Java HotSpot(TM) Server VM (build 23.7-b01, mixed mode) 32-bit JVM under Windows with CygwinThis is a 64-bit JVM: -bash-4.1$ java -version java version "1.7.0_17" Java(TM) SE Runtime Environment (build 1.7.0_17-b02) Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode) This is a 32-bit JVM -bash-4.1$ export PATH=/cygdrive/c/Program\ Files\ \(x86\)/Java/jdk1.7.0_03/bin:${PATH} -bash-4.1$ java -version java version "1.7.0_03" Java(TM) SE Runtime Environment (build 1.7.0_03-b05) Java HotSpot(TM) Client VM (build 22.1-b02, mixed mode, sharing) !!! Reconfiguring Ptolemy II to use a 32-bit JVM After setting your path to include the proper JVM, then run (:source:) cd $PTII ./configure cd bin make What does causuality local mean?One issue that is bothering me is that it is hard to know when something is an input or not. For example, ptolemy/actor/lib/fmi/fmus/dqME20/src/modelDescription.xml defines these ModelVariables <ModelVariables> <ScalarVariable name="x" valueReference="0" description="the only state" causality="local" variability="continuous" initial="exact"> <Real start="1"/> </ScalarVariable> <ScalarVariable name="der(x)" valueReference="1" causality="local" variability="continuous" initial="calculated"> <Real derivative="1"/> </ScalarVariable> <ScalarVariable name="k" valueReference="2" causality="parameter" variability="fixed" initial="exact"> <Real start="1"/> </ScalarVariable> </ModelVariables> <ModelStructure> <Derivatives> <Unknown index="2" /> </Derivatives> <InitialUnknowns> <Unknown index="2"/> </InitialUnknowns> </ModelStructure> Here, I think x is an input and der(x) is an output. The notion of causality=local is defined in the spec as: "local": Local variable that is calculated from other variables or is a continuoustime state (see section 2.2.8). It is not allowed to use the variable value in another model or slave. and "[causality = "calculatedParameter" and causality = "local" with variability = "fixed" or "tunable" are similar. The difference is that a calculatedParameter can be used in another model or slave, whereas a local variable cannot. For example, when importing an FMU in a Modelica environment, a "calculatedParameter" should be imported in a public section as final parameter, whereas a "local" variable should be imported in a protected section of the model.]" |