OpenModelica is an open-source compiler for the Modelica language. Modelica is a language for simulating systems (electrical, mechanical, and many more).
The files in this repository include some files to help OpenModelica compile models to JavaScript using Emscripten.
Thanks to Martin Sjölund (a core OpenModelica developer), OpenModelica has a backend that supports compilation with Emscripten.
Overall, the user experience works relatively well. All the calculations are done on the client. Here are several examples:
- Modelica.Blocks.Examples.PID_Controller
- Modelica.Electrical.Analog.Examples.ChuaCircuit
- Modelica.Electrical.Analog.Examples.Rectifier
- Modelica.Mechanics.MultiBody.Examples.Systems.RobotR3.fullRobot
See here for the source code for these examples. Here are examples from my area of work:
You wouldn't want to run complex Monte Carlo analysis with this, but many models should run sufficiently fast for use on the web. With advances in Emscripten and a few tweaks to OpenModelica, models in Firefox run within about 1.5X of native, and in the most recent Chrome, they run within 2X of native. The key to the speed is that Emscripten compiles to the asm.js format which can be optimized very well. The first run takes more time because the files need to be downloaded and compiled.
The JavaScript file generated by Emscripten is almost 2 MB (about 0.5 MB gzipped) for models with complexity similar to examples in the Modelica Standard Library. The most complex model I've tried is the MultiBody.Examples.Loops.EngineV6 that was about 8 MB. Some options to try to reduce the page size are:
- Look for more stuff to strip out (one could strip out all solvers but DASSL for example).
- Replace some of the system code with something already built in. For
example, it might be possible to replace
expat
with JavaScript's own XML processing functionality.
The gui for these pages was done using mdpad, another web technology I'm experimenting with. You can of course write your own JavaScript gui that interfaces with the simulation code.
To set up to compile your own model, here are the steps needed:
- Install Emscripten.
- Make sure Emscripten works and paths to
emcc
are set up right. - Install OpenModelica with at least SVN revision 18828.
- Copy all of the object files (*.so) and pre.js into the build
directory of OpenModelica at this location (you may need to create
the directory):
- build/lib/omc/emcc/
If you want to compile the Modelica libraries (as OpenModelica gets updated), you can run the following at the shell from your OpenModelica source location:
make -j4 -C SimulationRuntime/c emcc
make -j4 omc
This will update the following files:
- build/lib/omc/emcc/libf2c.so
- build/lib/omc/emcc/libSimulationRuntimeC.so
This repository also contains the Emscripten compiled code for LAPACK/BLAS and expat.
Note that I have only tested Emscripten compilation with Linux. I don't know if it will work out-of-the-box under Windows.
To compile your own model, create a modelica script (*.mos) file something like:
loadModel(Modelica);
setCommandLineOptions("+simCodeTarget=JavaScript");
buildModel(Modelica.Electrical.Analog.Examples.ChuaCircuit);
Run this in a shell with something like:
omc chua.mos
This will compile the model to JavaScript. This will generate many other files, too. The most important files are:
- Modelica.Electrical.Analog.Examples.ChuaCircuit.js
- Modelica.Electrical.Analog.Examples.ChuaCircuit_init.xml
- Modelica.Electrical.Analog.Examples.ChuaCircuit.md
The js
file is the JavaScript code. The xml
file is the
initialization file. You will likely want to modify some of the
defaults. The md
file is a Markdown file that describes a user
interface using mdpad.
To run your compiled JavaScript model in a browser, clone the mdpad files from here:
Copy the three files (js, xml, and md) created by the call to omc to your newly cloned mdpad directory.
Launch a web server from within your mdpad directory. I use python -m SimpleHTTPServer
which starts a webserver on port 8000.
Browse to your model, something like
http://localhost:8000/mdpad_local.html?Modelica.Electrical.Analog.Examples.ChuaCircuit.md
.
There are a few tweaks you will normally want to do. First, you can
edit the Markdown file to better describe your model. You can also
change the inputs and outputs in this file. Using the Chua circuit as
an example, the following Markdown code defines the form inputs on the
page. This is YAML code that describes the form elements. In this
example, L
, C1
, and C2
are inputs to the model that are specific
to this simulation, so modify these are add similar entries for your
model.
```yaml jquery=dform
class : form-horizontal
col1class : col-sm-7
col2class : col-sm-5
html:
- name: stopTime
type: number
bs3caption: Stop time, sec
value: 10000.0
- name: intervals
type: number
bs3caption: Output intervals
value: 500
- name: tolerance
type: number
bs3caption: Tolerance
value: 0.0001
- name: L
type: number
bs3caption: L, henries
value: 18.0
- name: C1
type: number
bs3caption: C1, farads
value: 10.0
- name: C2
type: number
bs3caption: C2, farads
value: 100.0
```
Next, you need to tie these input elements to model parameters in the xml file. Do this by changing a JavaScript block within the Markdown file. Here is an example for the three variables set in the Chua example:
// Set some model parameters
$xml.find("ScalarVariable[name = 'L.L']").find("Real").attr("start", L)
$xml.find("ScalarVariable[name = 'C1.C']").find("Real").attr("start", C1)
$xml.find("ScalarVariable[name = 'C2.C']").find("Real").attr("start", C2)
JavaScript uses the CSV outputFormat, and this can be quite slow in
Emscripten-compiled code. So, simulations run much faster if you
reduce the amount of output from the simulation. You can do that by
changing the variableFilter
input in the _init.xml
file. Here is
an example for the Chua circuit to just show two voltages and two
currents:
variableFilter = "C1.v|C2.v|L.i|Nr.i" />
You could also change this in the md
file by adding a line like the
following:
defex = $xml.find("DefaultExperiment")
defex.attr("variableFilter", "C1.v|C2.v|L.i|Nr.i")
Lastly, this interface shows an image of the model. You need to create
this image file as follows. In OMEdit, open your model. Right click in
the area with your model visible. Select "Export as an image". Save as
the full model name with an svg
extension in the mdpad directory.
Now, your model should be visible when you reload the model in the
browser.
Everything here is experimental at this point. I've tried this with several models. I've left off some system libraries like Sundials, so some solvers and functionality might not work.
All this code is free and open source. The OpenModelica code is under various licenses. The files that I made are granted to the public domain (or alternatively under the MIT license).