Skip to content

feelpp/mo2fmu

Repository files navigation

Feel++ mo2fmu converter

Modelica to FMU converter with Dymola and OpenModelica support.

Features

  • Multiple backends: Supports both Dymola and OpenModelica compilers
  • Automatic backend selection: Automatically detects available compilers
  • FMI 1.0, 2.0, and 3.0 support: Generate Co-Simulation and Model Exchange FMUs
  • Python API: Programmatic access for integration into workflows
  • Command-line interface: Simple CLI with compile and check subcommands

Installation

From PyPI (Recommended)

Install the latest stable release from PyPI using uv:

uv pip install feelpp-mo2fmu

With OpenModelica Support

To use OpenModelica as a backend, install with the optional dependency:

uv pip install "feelpp-mo2fmu[openmodelica]"

This will install OMPython for Python integration with OpenModelica.

With Simulation Support

To run simulations and validate FMUs (useful for testing):

uv pip install "feelpp-mo2fmu[simulation]"

This will install FMPy for FMU simulation and validation.

From Source

For development or to use the latest unreleased features:

git clone https://github.com/feelpp/mo2fmu.git
cd mo2fmu
uv venv .venv-mo2fmu
source .venv-mo2fmu/bin/activate  # On Windows: .venv-mo2fmu\Scripts\activate
uv pip install -e ".[all]"

Configuration

Dymola Location

The Dymola installation location can be configured via environment variables:

export DYMOLA_ROOT=/opt/dymola-2025xRefresh1-x86_64/
export DYMOLA_EXECUTABLE=/usr/local/bin/dymola
export DYMOLA_WHL=Modelica/Library/python_interface/dymola-2025.1-py3-none-any.whl

Environment Variables:

  • DYMOLA_ROOT: Path to Dymola installation root directory (default: /opt/dymola-2025xRefresh1-x86_64/)
  • DYMOLA_EXECUTABLE: Path to Dymola executable binary (default: /usr/local/bin/dymola)
  • DYMOLA_WHL: Relative path to Dymola Python wheel from DYMOLA_ROOT (default: Modelica/Library/python_interface/dymola-2025.1-py3-none-any.whl)
  • DYMOLA_STARTUP_RETRY_TIMEOUT: Time in seconds to wait for a shareable Dymola seat before failing (default: 0)
  • DYMOLA_STARTUP_RETRY_INTERVAL: Delay in seconds between startup retries while waiting for a seat (default: 30)

OpenModelica Location

OpenModelica can be configured via environment variables:

export OPENMODELICA_HOME=/usr/lib/omc

Environment Variables:

  • OPENMODELICA_HOME: Path to OpenModelica installation (default: auto-detected)

Command Line Interface

The mo2fmu CLI provides two subcommands: compile and check.

Main Help

$ mo2fmu --help
Usage: mo2fmu [OPTIONS] COMMAND [ARGS]...

  mo2fmu - Convert Modelica models to Functional Mock-up Units (FMUs).

  Use 'mo2fmu compile' to generate FMUs or 'mo2fmu check' to verify compilers.

Options:
  -v, --version  Show version information.
  --help         Show this message and exit.

Commands:
  check    Check availability of Modelica compilers and their FMI support.
  compile  Compile a Modelica model to FMU.

Compile Command

Generate FMUs from Modelica models:

$ mo2fmu compile --help
Usage: mo2fmu compile [OPTIONS] MO OUTDIR

  Compile a Modelica model to FMU.

Options:
  --name TEXT                     Custom name for the FMU (default: .mo file stem).
  -l, --load TEXT                 Load one or more Modelica packages.
  --flags TEXT                    Compiler-specific flags for FMU translation.
  -t, --type [all|cs|me|csSolver] FMI type: cs (Co-Simulation), me (Model Exchange),
                                  all, or csSolver.
  --fmi-version [1|2|3]           FMI version. FMI 3.0 requires Dymola 2024+
                                  or OpenModelica 1.21+.
  -b, --backend [dymola|openmodelica|auto]
                                  Modelica compiler backend (default: auto-detect).
  --dymola PATH                   Path to Dymola root directory.
  --dymola-exec PATH              Path to Dymola executable.
  --dymola-whl PATH               Path to Dymola wheel file (relative to Dymola root).
  -v, --verbose                   Enable verbose output.
  -f, --force                     Overwrite existing FMU.
  --help                          Show this message and exit.

Compile Examples:

# Basic compilation (auto-detect backend)
mo2fmu compile model.mo ./output

# Compile with OpenModelica backend
mo2fmu compile --backend openmodelica model.mo ./output

# Compile FMI 3.0 Co-Simulation FMU with verbose output
mo2fmu compile -v --fmi-version 3 --type cs model.mo ./output

# Force overwrite existing FMU
mo2fmu compile -f model.mo ./output

# Load additional Modelica packages
mo2fmu compile --load package1.mo --load package2.mo model.mo ./output

Check Command

Verify compiler availability and FMI support:

$ mo2fmu check --help
Usage: mo2fmu check [OPTIONS]

  Check availability of Modelica compilers and their FMI support.

Options:
  --dymola PATH       Path to Dymola root directory.
  --dymola-exec PATH  Path to Dymola executable.
  --dymola-whl PATH   Path to Dymola wheel file (relative to Dymola root).
  --json              Output results as JSON.
  --help              Show this message and exit.

Check Examples:

# Check all available compilers
mo2fmu check

# Output as JSON (for scripting)
mo2fmu check --json

# Check with custom Dymola path
mo2fmu check --dymola /opt/dymola-2024x

Python API

Recommended API

The recommended API provides a clean interface with automatic backend selection:

from feelpp.mo2fmu import CompilationRequest, checkCompilers, compileFmu, compileFmus, getCompiler

# Auto-detect and use available compiler
result = compileFmu("path/to/model.mo", "./output")
if result.success:
    print(f"FMU created at {result.fmu_path}")
else:
    print(f"Error: {result.error_message}")

# Explicitly use OpenModelica
result = compileFmu("path/to/model.mo", "./output", backend="openmodelica")

# Compile FMI 3.0 Model Exchange FMU
result = compileFmu(
    "path/to/model.mo",
    "./output",
    fmiType="me",
    fmiVersion="3",
    verbose=True,
)

# Check available compilers
available = checkCompilers()
for name, info in available.items():
    print(f"{name}: available={info['available']}, fmiSupport={info.get('fmiSupport', [])}")

# Get a specific compiler instance for more control
compiler = getCompiler("openmodelica")
if compiler.is_available:
    print(f"Using {compiler.name}")

# Batch compilation with one Dymola session
requests = [
    CompilationRequest(
        mo="path/to/model_a.mo",
        outdir="./output/a",
        fmu_model_name="ModelA",
        force=True,
    ),
    CompilationRequest(
        mo="path/to/model_b.mo",
        outdir="./output/b",
        fmu_model_name="ModelB",
        force=True,
    ),
]
results = compileFmus(requests, backend="dymola")

Using Compiler Classes Directly

For full control, use the compiler classes directly:

from feelpp.mo2fmu import (
    DymolaCompiler,
    OpenModelicaCompiler,
    ModelicaModel,
    CompilationConfig,
)
from pathlib import Path

# Using OpenModelica
compiler = OpenModelicaCompiler()
if compiler.is_available:
    model = ModelicaModel(Path("path/to/model.mo"))
    config = CompilationConfig(
        fmi_type="cs",      # Co-Simulation
        fmi_version="3",    # FMI 3.0
        verbose=True,
    )
    result = compiler.compile(model, Path("./output"), config)

    if result.success:
        print(f"FMU created: {result.fmu_path}")
    else:
        print(f"Compilation failed: {result.error_message}")

# Using Dymola
compiler = DymolaCompiler()
if compiler.is_available:
    result = compiler.compile(model, Path("./output"), config)

Legacy API

The original API is still available for backward compatibility:

from feelpp.mo2fmu import mo2fmu

mo2fmu(
    mo="path/to/model.mo",
    outdir="path/to/output/dir",
    fmumodelname="MyFMUModel",
    load=("Modelica", "SomePackage"),
    flags=("-d=initialization",),
    type="cs",
    version="2",
    dymola_root="/path/to/dymola/root",
    dymolapath="/path/to/dymola/executable",
    dymolawhl="path/to/dymola.whl",
    verbose=True,
    force=False,
    backend="dymola",  # or "openmodelica", "auto"
)

Backend Comparison

Feature Dymola OpenModelica
License Commercial Open Source (GPL)
FMI 1.0
FMI 2.0
FMI 3.0 ✓ (2024+) ✓ (v1.21+)
Co-Simulation
Model Exchange
csSolver type
Modelica Standard Library
BuildingSystems Partial
Buildings Library

Running Tests

The test suite includes unit tests and FMU simulation tests:

# Run all tests
uv run pytest

# Run with verbose output
uv run pytest -v

# Run only unit tests (no simulation)
uv run pytest tests/test_compilers.py tests/test_mo2fmu.py

# Run simulation tests (requires FMPy)
uv run pytest tests/test_fmu_simulation.py

Continuous Integration

Our GitHub Actions workflow (.github/workflows/ci.yml) includes:

  • build_wheel: code-quality checks, Python tests, wheel build, and artifact upload
  • build_docs: Antora site build and GitHub Pages deployment on main
  • release: on tags vX.Y.Z, downloads the built wheel, creates a GitHub release, and publishes to PyPI

Versioning & Release

The release being prepared is 1.0.0.

Release metadata is maintained in:

Documentation metadata under docs/ and package.json should be kept aligned when needed, but they are not the authoritative Python package version.

Release process:

  1. Update pyproject.toml and CHANGELOG.md.
  2. Push the release branch to GitHub.
  3. Create and push a tag such as v1.0.0.
  4. Let .github/workflows/ci.yml run the release job to publish the wheel to GitHub Releases and PyPI.

Contributing

We welcome contributions! Please:

  • Fork the repository and create a feature branch.
  • Adhere to existing coding conventions; add python tests where appropriate.
  • Update documentation (docs/) for any new features.
  • Submit a pull request with a clear description of your changes.

License

This project is licensed under the MIT License. See LICENSE for full details.

About

Modelica to FMU converter using Dymola

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors