-
-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Is your feature request related to a problem? Please describe.
Currently around 37 models from the MSL are failing with an error about missing functions for Modelica Standard Tables. These functions are especially difficult, since they involve function calls to external C functions like ModelicaStandardTables_CombiTimeTable_minimumTime, ModelicaStandardTables_CombiTimeTable_maximumTime or ModelicaStandardTables_CombiTimeTable_nextTimeEvent.
Describe the solution you’d like
There are two options:
a) Use https://github.com/OpenModelica/OMRuntimeExternalC.jl
b) Implement it directly in BaseModelica.jl.
For b) BaseModelica.jl needs to:
-
Collect which C functions are needed and where the C sources / compiled libraries are located. E.g. the following Base Modelica specifies function
ModelicaStandardTables_CombiTimeTable_minimumTime:function 'Modelica.Blocks.Tables.Internal.getTimeTableTmin' "Return minimum abscissa value of 1-dim. table where first column is time" input 'Modelica.Blocks.Types.ExternalCombiTimeTable' 'tableID'; output Real 'timeMin'; external "C" 'timeMin' = ModelicaStandardTables_CombiTimeTable_minimumTime('tableID') annotation(Library = {"ModelicaStandardTables", "ModelicaIO", "ModelicaMatIO", "zlib"}, LibraryDirectory = "modelica://Modelica/Resources/Library"); end 'Modelica.Blocks.Tables.Internal.getTimeTableTmin';
-
Compile the C sources into a shared library or have a precompiled version of shared library ModelicaStandardTables for the target system. OpenModelica uses a pre-compiled version of libModelicaStandardTables.so (or DLL, or static lib) that gets shipped with the installer, located in e.g.
lib/x86_64-linux-gnu/omc/ffi/libModelicaStandardTables.so. But compiling libModelicaStandardTables isn't hard.run(`gcc -O2 -shared -fPIC -o libModelicaStandardTables.so ModelicaStandardTables.c`)
-
Load the library
using Libdl const libModelicaStandardTables = Libdl.dlopen("path/to/libModelicaStandardTables.so")
-
Create Julia wrappers for all C functions needed by the model. E.g. for
ModelicaStandardTables_CombiTimeTable_minimumTime:function ModelicaStandardTables_CombiTimeTable_minimumTime(tableID::Ptr{Cvoid})::Float64 ccall( Libdl.dlsym(libModelicaStandardTables, :ModelicaStandardTables), Cdouble, # return type: double (Ptr{Cvoid},), # argument types: void* tableID # argument value ) end
Simple example
Here is a simpler example with a very basic external C function:
//! base 0.1.0
package 'ExponentialGrowth'
function 'mult' "Multiply two doubles via external C function"
input Real 'a';
input Real 'b';
output Real 'result';
external "C" 'result' = mult('a', 'b') annotation(Library = {"mult"});
end 'mult';
model 'ExponentialGrowth' "dy/dt = p * y — exponential growth using external C mult"
parameter Real 'p' = 0.5 "Growth rate";
Real 'y'(start = 1.0) "State variable";
equation
der('y') = 'mult'('p', 'y');
end 'ExponentialGrowth';
end 'ExponentialGrowth';mult.c
double mult(double a, double b) {
return a * b;
}Additional context
Sub-issue of #24.