npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rumoca

v0.7.25

Published

Modelica compiler written in RUST

Readme

Rumoca

CI Crates.io PyPI Documentation License

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.

Quick Start

# 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-lint

Installation

Rust (Compiler, Formatter, Linter)

cargo install rumoca

Python

The Python package bundles the Rust compiler, so no separate Rust installation is needed:

pip install rumoca
import 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")

Rust Library

[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(())
}

Tools

| 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 |

MSL Compatibility & Performance

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.

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 |

Custom Code Generation

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.py

Example 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).

VSCode Extension

Search for "Rumoca Modelica" in the VSCode Extensions marketplace, or install from the marketplace page.

Rumoca VSCode Extension Demo

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.

WebAssembly (Browser)

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.html

The 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 --release

Using 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)

Integration with Cyecca

rumoca model.mo -m MyModel --json > model.json
from cyecca.io.rumoca import import_rumoca

model = import_rumoca('model.json')
# Use model for simulation, analysis, code generation, etc.

Architecture

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)

Development

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 files

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 indentation

Configuration (.rumoca_fmt.toml):

indent_size = 2
use_tabs = false
max_line_length = 100
blank_lines_between_classes = 1

Linter:

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 warnings

Available 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 = false

Caching

Rumoca 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.

Roadmap

Export Targets:

Import Targets:

Contributing

Contributions welcome! All contributions must be made under the Apache-2.0 license.

License

Apache-2.0 (LICENSE)

Citation

@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}
}

See Also