Including a Julia model in Simulink

I wrote a nice dynamic model in Julia (https://github.com/ufechner7/KiteModels.jl) and now get the request to include it in Simulink because some people prefer to do control design with Simulink. Any idea what would be the best way to do this?

I would say the model works on a fixed time step, every 50ms it gets a new control input and provides a new system state (vector of vectors) as output. Shell I try to create a dll? Or rather use loose coupling with udp?

1 Like

JuliaSim’s FMU export is tested to work with Simulink

Well, but FMUs are something very special, and I do not think that my model can be exported as FMU… But I would be glad if you could share a link about how to export an FMU…

Do FMUs include a solver?

Ok, I found this link 404 · JuliaHub where it says FMUs can include their own solver. The point is, my model is using a DAE solver and not an ODE solver. Does that make a difference?

We could definitely extend it to DAEs. Cosimulation FMUs embed the solver into the binary and so that entire bit can be imported into Simulink as a box that just takes a dt and input values to spit out values of observables at t+dt. The API would just need to be able to take the initial du0 guess as well. Get in touch.

2 Likes

I have an init() function to calculate the du0.

But I read:

The Functional Mock-up Interface (FMI) is a free standard that defines a container and an interface to exchange dynamic models using a combination of XML files, binaries and C code zipped into a single file.

So you you generate C code und Julia code cannot be used in an FMU?

Julia code can be used in an FMU.

OK, as I understand it now an FMU consists of an XML interface definition and an .dll or .so file with the code. so I need to learn:

  • how to write the XML file
  • how to create a shared object file from Julia

I remember that at some point in time Julia crashed when embedded in Matlab/ Simulink due to signals that Matlab/Simulink sends. This issue is fixed?

I don’t know about the general case, but that crash at least does not happen for Julia-based FMUs in Simulink.

Based on experience in my field (power system dynamics), any effort to make models written in Julia exportable to other simulation software (such as Simulink/Modelica) by using FMI standard is well invested and can really contribute to wide adoption.

1 Like

Started to read the specification: https://fmi-standard.org/
Can anybody provide a simple example of an FMU written in C to understand better which functions need to be implemented?

As I see there are some Julia packages for FMI import and export: GitHub - traversaro/awesome-fmi: A curated list of Functional Mock-up Interface (FMI) libraries, tools and resources.

Need to find out if they support my use case already…

OK, there is a package for FMI export of Julia models (GitHub - ThummeTo/FMIExport.jl: FMIExport.jl is a free-to-use software library for the Julia programming language which allows for the export of FMUs (fmi-standard.org) from any Julia-Code. FMIExport.jl is completely integrated into FMI.jl.), but it does NOT support the export of models for co-simulation yet.

I created an issue: Support export of FMIs for cosimulation · Issue #10 · ThummeTo/FMIExport.jl · GitHub

1 Like

Indeed, and that’s why we targeted it as something for JuliaSim. See the FMU accelerator for details on the mix with surrogates:

Though indeed, you can use the FMU exporting directly with tutorials here:

1 Like

My model is not based on ModelingToolkit, so I do not think that these tutorials can be applied…

The FMU build point is on the *DEProblem, which IIRC you said you used a DAEProblem. And besides, models can be automatically converted to ModelingToolkit via the modelingtoolkitize function.

This is the way I initialize my problem:

    y0, yd0 = KiteModels.find_steady_state!(s; stiffness_factor=stiffness_factor, prn=prn)

    differential_vars = ones(Bool, length(y0))
    solver  = IDA(linear_solver=:GMRES, max_order = 4)
    tspan   = (0.0, t_end) 
    abstol  = s.set.abs_tol # max error in m/s and m
    prob    = DAEProblem(residual!, yd0, y0, tspan, s, differential_vars=differential_vars)
    integrator = Sundials.init(prob, solver, abstol=abstol, reltol=s.set.rel_tol)

Yeah it definitely would be possible to allow for a custom initialization function, probably as a function of parameters