Try Rumoca in your browser! - No installation required.
A Modelica compiler written in Rust. Rumoca parses Modelica source files and exports to the DAE IR Format (supporting both implicit and explicit model serialization), or via user-customizable templates using MiniJinja. The DAE IR format is consumed by Cyecca for model simulation, analysis, and Python library integration with CasADi, SymPy, and other backends.
Note: Rumoca is in early development. While already usable for many practical tasks, you may encounter issues. Please file bug reports to help improve the compiler.
# Install
cargo install rumoca
# Compile to DAE IR (JSON)
rumoca model.mo -m MyModel --json > model.json
# Format Modelica files
rumoca-fmt
# Lint Modelica files
rumoca-lintcargo install rumocaThe Python package bundles the Rust compiler, so no separate Rust installation is needed:
pip install rumocaimport rumoca
# Compile a Modelica file
result = rumoca.compile("model.mo")
# Get as JSON string or Python dict
json_str = result.to_base_modelica_json()
model_dict = result.to_base_modelica_dict()
# Compile from string
result = rumoca.compile_source("""
model Test
Real x(start=0);
equation
der(x) = 1;
end Test;
""", "Test")[dependencies]
rumoca = "0.7"use rumoca::Compiler;
fn main() -> anyhow::Result<()> {
let result = Compiler::new()
.model("MyModel")
.compile_file("model.mo")?;
let json = result.to_dae_ir_json()?;
println!("{}", json);
Ok(())
}| Tool | Description |
|---|---|
rumoca |
Main compiler - parses Modelica and exports DAE IR (JSON) |
rumoca-fmt |
Code formatter for Modelica files (like rustfmt) |
rumoca-lint |
Linter for Modelica files (like clippy) |
rumoca-lsp |
Language Server Protocol server for editor integration |
Rumoca is tested against the Modelica Standard Library 4.1.0.
| Metric | Result |
|---|---|
| Parse Rate | 100% (2551/2551 files) |
| Compile Rate | 92.1% (2102/2283 models) |
Benchmark (AMD Ryzen 9 7950X, 16 cores):
| Phase | Time | Throughput |
|---|---|---|
| Parsing | 0.99s | 2,586 files/sec |
| Balance Check (cold) | 31.07s | 73.5 models/sec |
| Balance Check (warm) | 0.01s | 263,242 models/sec |
Balance Check Results:
| Status | Count | Percentage | Description |
|---|---|---|---|
| Balanced | 669 | 29.3% | Fully determined (equations = unknowns) |
| Partial | 1177 | 51.6% | Under-determined by design (external connectors) |
| Unbalanced | 256 | 11.2% | Needs further work |
| Compile Errors | 181 | 7.9% | Missing type/class resolution |
Partial models have external connector flow variables that receive equations when connected in a larger system.
Detailed Compatibility Notes
Language Support:
| Category | Supported |
|---|---|
| Classes | model, class, block, connector, record, type, package, function |
| Equations | Simple, connect (flow/potential), if, for, when |
| Expressions | Binary/unary ops, function calls, if-expressions, arrays |
| Type prefixes | flow, discrete, parameter, constant, input, output |
| Packages | Nested packages, package.mo/package.order, MODELICAPATH |
| Imports | Qualified, renamed, unqualified (.*), selective ({a,b}) |
| Functions | Single/multi-output, tuple equations (a,b) = func() |
| Built-ins | der, pre, reinit, time, trig, array functions |
| Events | noEvent, smooth, sample, edge, change, initial, terminal |
Partial Support:
| Feature | Status |
|---|---|
| Algorithm sections | Parsed; assignments not yet counted in balance check |
| Connect equations | Flow/potential semantics; stream not supported |
| External functions | external recognized; no linking |
| Inner/outer | Basic resolution; nested scopes in progress |
| Complex type | Record expansion; operator overloading in progress |
Not Yet Implemented:
| Feature | Notes |
|---|---|
| Stream connectors | inStream, actualStream operators |
| Redeclarations | redeclare, replaceable parsed only |
| Overloaded operators | operator class prefix recognized only |
| State machines | Synchronous language elements (Ch. 17) |
| Expandable connectors | Dynamic connector sizing |
| Overconstrained connectors | Connections.root, branch, etc. |
What Works Well (92% of models compile successfully):
- Modelica.Thermal (97% success)
- Modelica.Magnetic (96% success)
- Modelica.Math (excellent coverage)
Problematic Areas:
- Modelica.Fluid (Medium type resolution)
- Modelica.ComplexBlocks (Complex type)
- Modelica.Electrical.Digital (algorithm sections)
- Modelica.Mechanics.MultiBody (StateSelect, algorithm sections)
- Modelica.Clocked (synchronous features)
Top Compile Errors (181 models):
| Count | Missing Type |
|---|---|
| 41 | Complex |
| 32 | StateSelect |
| 26 | Medium.AbsolutePressure |
| 17 | Medium.MassFlowRate |
| 16 | Medium.ThermodynamicState |
Known Limitations (256 unbalanced models):
| Category | Notes |
|---|---|
| Algorithm sections | Assignments not yet counted as equations |
| Stream connectors | inStream/actualStream not implemented |
| External functions | Functions without equation bodies |
| Operator records | Operator overloading not implemented |
Rumoca supports MiniJinja templates for custom code generation:
rumoca model.mo -m MyModel --template-file examples/templates/casadi.jinja > model.py
rumoca model.mo -m MyModel --template-file examples/templates/sympy.jinja > model.pyExample template:
# Generated from {{ dae.model_name }}
{% for name, comp in dae.x | items %}
{{ name }}: {{ comp.type_name }} (start={{ comp.start }})
{% endfor %}See examples/templates/ for complete examples (CasADi, SymPy, Base Modelica).
Search for "Rumoca Modelica" in the VSCode Extensions marketplace, or install from the marketplace page.
The extension includes a bundled rumoca-lsp language server - no additional installation required.
Features:
- Syntax highlighting (semantic tokens)
- Real-time diagnostics with type checking
- Autocomplete for keywords, built-in functions, and class members
- Go to definition / Find references
- Document symbols and outline
- Code formatting
- Hover information
- Signature help
- Code folding
- Inlay hints
- Code lens with reference counts
- Rename symbol
- Call hierarchy
- Document links
Configuring Library Paths:
{
"rumoca.modelicaPath": [
"/path/to/ModelicaStandardLibrary",
"/path/to/other/library"
]
}Alternatively, set the MODELICAPATH environment variable. See the extension documentation for details.
Rumoca compiles to WebAssembly, enabling browser-based Modelica compilation without a backend server.
Features:
- Parse and compile Modelica models in the browser
- DAE IR (JSON) generation
- Template rendering with MiniJinja
- Multi-threaded compilation using Web Workers
Try the Demo:
./tools/wasm-test.sh
# Open http://localhost:8080/examples/wasm_editor/index.htmlThe demo provides a Monaco-based editor with:
- Split-pane Modelica and Jinja2 template editing
- Real-time template preview
- DAE IR JSON export
- Autocomplete for template variables (
dae.x,dae.u, etc.)
Building WASM:
# Install wasm-pack
cargo install wasm-pack
# Build WASM package (outputs to pkg/)
wasm-pack build --target web --releaseUsing in JavaScript:
import init, { compile, render_template } from './pkg/rumoca.js';
await init();
const modelica = `
model Test
Real x(start=0);
equation
der(x) = 1;
end Test;
`;
// Compile to DAE IR JSON
const result = compile(modelica, "Test");
console.log(result);
// Render custom template
const template = "Model: {{ dae.model_name }}";
const output = render_template(modelica, "Test", template);
console.log(output);rumoca model.mo -m MyModel --json > model.jsonfrom cyecca.io.rumoca import import_rumoca
model = import_rumoca('model.json')
# Use model for simulation, analysis, code generation, etc.Modelica Source -> Parse -> Flatten -> BLT -> DAE -> DAE IR (JSON)
(AST) (Flat) (Match) (DAE)
|
Cyecca
|
CasADi/SymPy/JAX/etc.
Structural Analysis:
- Hopcroft-Karp matching (O(E√V)) for equation-variable assignment
- Tarjan's SCC algorithm for topological ordering and algebraic loop detection
- Pantelides algorithm for DAE index reduction (detects high-index systems)
- Tearing for algebraic loops (reduces nonlinear system size)
cargo build --release # Build
cargo test # Run tests
cargo fmt --check # Check Rust formatting
cargo clippy # Lint Rust code
rumoca-fmt --check # Check Modelica formatting
rumoca-lint # Lint Modelica filesFormatter & Linter Configuration
Formatter:
rumoca-fmt # Format all .mo files
rumoca-fmt --check # Check formatting (CI mode)
rumoca-fmt model.mo # Format specific files
rumoca-fmt --config indent_size=4 # Custom indentationConfiguration (.rumoca_fmt.toml):
indent_size = 2
use_tabs = false
max_line_length = 100
blank_lines_between_classes = 1Linter:
rumoca-lint # Lint all .mo files
rumoca-lint --level warning # Show only warnings and errors
rumoca-lint --format json # JSON output for CI
rumoca-lint --list-rules # List available rules
rumoca-lint --deny-warnings # Exit with error on warningsAvailable Rules:
| Rule | Level | Description |
|---|---|---|
naming-convention |
note | CamelCase for types, camelCase for variables |
missing-documentation |
note | Classes without documentation strings |
unused-variable |
warning | Declared but unused variables |
undefined-reference |
error | References to undefined variables |
parameter-no-default |
help | Parameters without default values |
empty-section |
note | Empty equation or algorithm sections |
magic-number |
help | Magic numbers that should be constants |
complex-expression |
note | Overly complex/deeply nested expressions |
inconsistent-units |
warning | Potential unit inconsistencies |
redundant-extends |
warning | Duplicate or circular extends |
Configuration (.rumoca_lint.toml):
min_level = "warning"
disabled_rules = ["magic-number", "missing-documentation"]
deny_warnings = falseRumoca uses multi-level caching: in-memory caches for session-level performance (parsed classes, resolved definitions), and a persistent disk cache (~/.cache/rumoca/dae/) that works like ccache for CI pipelines. The disk cache is invalidated when source files or the compiler version change.
Export Targets:
Import Targets:
- Base Modelica (MCP-0031) - interface with OpenModelica, Dymola, etc.
Contributions welcome! All contributions must be made under the Apache-2.0 license.
Apache-2.0 (LICENSE)
@inproceedings{condie2025rumoca,
title={Rumoca: Towards a Translator from Modelica to Algebraic Modeling Languages},
author={Condie, Micah and Woodbury, Abigaile and Goppert, James and Andersson, Joel},
booktitle={Modelica Conferences},
pages={1009--1016},
year={2025}
}- Modelica IR - DAE IR specification
- Cyecca - Model simulation, analysis, and code generation
- Modelica Language