# FMPy: running FMU simulations from Python or the command line

> FMPy is a Python library that simulates Functional Mock-up Units, covering FMI 1.0, 2.0 and 3.0 in both Co-Simulation and Model Exchange, with a command line, a GUI, a Dash web app and a Jupyter notebook exporter. Its licence is the open question, since GitHub cannot classify it and the terms live in LICENSE.txt.

**CATIA-Systems/FMPy** — Simulate Functional Mock-up Units (FMUs) in Python

- Repository: https://github.com/CATIA-Systems/FMPy
- Stars: 599 · Forks: 144
- Language: Python
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/catia-systems-fmpy

## What FMPy is for and who reaches for it

FMPy is a free Python library to simulate Functional Mock-up Units. An FMU is a packaged model defined by the FMI standard, and the point of the library is to let you load one, run it and get results back without leaving Python.

The feature list in the project documentation is specific about coverage. It supports FMI 1.0, 2.0 and 3.0. It supports both Co-Simulation and Model Exchange, which are the two ways the standard lets a model be coupled. It runs on Windows, Linux and macOS. It offers a command line, a graphical user interface and a web app, it creates Jupyter Notebooks, and it compiles C code FMUs and generates CMake projects for debugging.

That last capability is the one that separates FMPy from a plain loader. Generating a CMake project for a C code FMU means you can open the model in a debugger, attach to a compiled binary, and step through the equations. For a co-simulation model that comes as source, that is the difference between a black box and something you can inspect.

The audience is engineers and scientists who already work in Python for data analysis, plotting and automation, and who need to drive simulation from a script or expose it to colleagues through a browser. The project is hosted under CATIA-Systems, which is the Dassault Systemes simulation business, so the code sits with a vendor that has a commercial interest in the FMI ecosystem rather than with a hobbyist.

The documentation also points commercial support to partners at LTX Simulation, reachable at support@ltx.de for a quote on projects, training and professional support.

## Installing from PyPI and the optional dependency groups

Installation is a single pip command with the complete extra:

```bash
python -m pip install fmpy[complete]
```

The extras exist because FMPy spans several kinds of use, and the packaging keeps the heavier pieces optional. The pyproject.toml in the repository lists the mandatory dependencies as attrs, cmake, jinja2, lark, lxml, msgpack, nbformat and numpy, with numpy required at 2.1.3 or newer and Python 3.10 as the floor.

The optional groups are named for what they enable. The gui group brings pyqtgraph and pyside6, plus pywin32 on Windows. The plot group brings plotly and scipy. The webapp group adds dash-bootstrap-components. The examples group adds dask with bag and requests. The complete group, which the installation command pulls in, combines the gui, plot, examples and webapp sets.

Two entry points are declared. The console script is fmpy, mapped to fmpy.cli:main, and the GUI script is fmpy-gui, mapped to fmpy.gui:main. That split is why the documentation starts the interface with a module invocation rather than a bare command name.

The build backend is Hatch, and the wheel packages the src/fmpy directory. The build also force-includes the container_fmu binaries for aarch64-darwin, x86_64-darwin, x86_64-linux and x86_64-windows, so the shared library that runs a container-wrapped FMU ships inside the wheel instead of being compiled on the user's machine.

## Dumping an FMU and simulating it in a Python session

The worked example uses a Rectifier FMU from the FMI cross-check repository, with separate downloads for Linux, macOS and Windows because the binary is platform specific. You change into the folder where you saved it, open a Python prompt, and start with the dump function:

```python
>>> from fmpy import *
>>> fmu = 'Rectifier.fmu'
>>> dump(fmu)  # get information
```

The output is the model description, and the documentation shows it in full: FMI version 2.0, model name Rectifier, platforms win64, 4 continuous states, 6 event indicators, 63 variables, generation tool MapleSim, generation date 2017-10-04. It also shows the default experiment with a stop time of 0.1 and a step size of 1e-07, and then a variables table with causality, start value, unit and description for the input and output variables.

Simulation is a second call, and plotting a third:

```python
>>> result = simulate_fmu(fmu)         # simulate the FMU
>>> from fmpy.util import plot_result  # import the plot function
>>> plot_result(result)                # plot two variables
```

The dump step is not optional ceremony. The step size in the default experiment is 1e-07, and the variables table tells you which quantities exist and in what unit. Running an FMU without reading its variable list first is how you end up plotting a voltage when you expected a current.

## The fmpy command line covers inspection, simulation and export

The command line entry point exposes the same functionality without a Python session. To get information about an FMU directly, change to the folder with the FMU and run:

```bash
fmpy info Rectifier.fmu
```

To simulate it and plot the results:

```bash
fmpy simulate Rectifier.fmu --show-plot
```

And to see the available options:

```bash
fmpy --help
```

The notebook exporter is a subcommand too:

```bash
fmpy create-jupyter-notebook Rectifier.fmu
```

You then open the result in Jupyter with:

```bash
jupyter notebook Rectifier.ipynb
```

The GUI can do the same thing from a menu, since the documentation says to open an FMU in the FMPy GUI and select Tools > Create Jupyter Notebook.

That combination is what makes FMPy useful for sharing. A model becomes a notebook that a colleague can run and read, without installing a modelling environment. The documentation mentions a screenshot of exactly that flow, and the GUI itself is started with:

```bash
python -m fmpy.gui
```

## Sharing an FMU through the Dash web app

The web app is the sharing path for people who should not install Python at all. It is built with Dash from Plotly, and the documentation describes it as a great way to share your FMUs with anyone that has a web browser.

Starting it is one command with the FMU as the argument:

```bash
python -m fmpy.webapp Rectifier.fmu
```

The same command accepts --help for the remaining options, which is where you would look for the host and port configuration if you needed to put it behind something.

The design here is deliberately narrow. This is not a general model repository with accounts and projects. It is a local Dash application bound to an FMU you name, which is exactly what you want for a quick demo or a lab session, and exactly what you do not want if you need multi user access control, saved experiment history or a deployment pipeline.

It is worth noting the dependency structure: dash-bootstrap-components is what the webapp extra pulls in, and plotly and scipy come from the plot extra. The web app therefore shares the plotting stack with the notebook and plot workflows, which is why a single complete install covers all three ways of working with a model.

## The three example scripts worth reading before writing your own

For anyone moving beyond the README example, the documentation points to three scripts in the source tree: coupled_clutches.py, custom_input.py and parameter_variation.py, all under src/fmpy/examples.

Those three cover the three things you invariably need. Coupled clutches is the multi-model case, where the point is connecting one FMU to another rather than running a single model in isolation. Custom input is the case where you want to drive a model with your own signal instead of its default experiment, which is how you feed a measured signal into a component model. Parameter variation is the sweep, where you change a parameter across a range and collect the results.

Between them they cover the bulk of what people build with FMUs outside a co-simulation master, and they are worth reading because they show the library's own idioms rather than a simplified tutorial version of them.

The examples optional dependency group, which adds dask with bag and requests, exists for these scripts. That tells you something about the intended scale of use: the design assumes parameter sweeps across many combinations may be worth distributing, which is a much more serious use of FMUs than the single simulation shown in the README.

## Where FMPy is the wrong tool

The clearest wrong case is a long running, scheduled simulation service. FMPy is a library and a set of local front ends. The web app takes one FMU on the command line, which is not a multi tenant model server, and the documentation does not describe authentication, persistence of experiment results or a queue.

The second wrong case is a team that needs an FMU to be portable across platforms it does not control. An FMU is a compiled binary, so the platform matters: the Rectifier example in the documentation ships as separate downloads for Linux, macOS and Windows, and the dump output shows platforms win64 for that particular model. FMPy runs on all three operating systems, but a given FMU may not.

The third is a project that needs the licence to be simple. GitHub cannot classify the licence on the repository page, and the terms live in the LICENSE.txt file at the root. That is not automatically a problem, but it is a real due diligence task, and a company with a procurement checklist around OSI approved licences will need to read it before the first commit. Read the file yourself and take your own advice on it.

The fourth is Model Exchange work that needs more than a simulation. The library supports Model Exchange, but the documented workflows are all about running a model and reading its outputs. Solving, Jacobian linearisation and custom solver control are not part of what is described here, so if your task is system identification or sensitivity analysis rather than a simulation run, this is not the tool doing that job.

Compare the alternative approach of using the modelling environment the FMU came from. Running a model natively in the tool that generated it gives you the solver settings, the model description and the debugging environment that FMPy deliberately abstracts away, and it avoids the binary portability question entirely. The trade is that you are then inside that tool's scripting environment rather than Python, and you give up the notebook and web sharing that FMPy provides.

## Licence, release cadence and the shape of the repository

FMPy is released under a custom licence that GitHub cannot classify, with the terms in the LICENSE.txt file at the repository root. The documentation describes the library as free and open source in the sense that it is available at no cost, but the licence text itself is the authoritative source and should be read before you commit it to a product. Your own review decides whether it suits your distribution model.

The release history is regular and slow enough to be predictable. v0.3.30 came on 2026-07-03, v0.3.31 on 2026-08-13 and v0.3.32 on 2026-09-09. The repository is not archived, and the last push was on 2026-10-13, roughly a month after the newest tag.

A 0.3.x version line with releases every few weeks means the API is still moving, though it has been stable enough to keep a 0.3 prefix for a long time. Pin an exact version if you care about reproducibility.

The tree shows the packaging story clearly. The source lives in src/, with a src/fmpy/examples directory holding the example scripts. There is a native/ directory for the native parts of the build, a docs/ directory with a mkdocs.yml alongside it, tests/ for the test suite, and a uv.lock file for the development environment. There is also a .python-version file, which tells you the interpreter version the maintainers work against, and a .gitmodules file, which is worth a look if you build the C code FMU path since it points at external sources.

## Conclusion

FMPy fits a Python engineer who needs to run an FMU in a script, a notebook or a web front end without leaving the Python ecosystem, and its FMI 1.0 to 3.0 coverage plus the bundled container_fmu binaries make it a workable bridge between simulation tools. It does not fit a team that needs a supported commercial product with a service contract, since the repository points to partners for paid support, nor a user who needs the licence to be one of the familiar permissive ones. Before adopting it, read LICENSE.txt yourself, since the platform cannot classify it, and confirm the FMU you plan to run is one of the FMI versions FMPy supports and that its binary matches your platform.

## FAQ

### How do I install FMPy and simulate an FMU?

Install it with python -m pip install fmpy[complete], then in Python call simulate_fmu on the path to your FMU and use plot_result from fmpy.util to plot the result. The command line equivalent is fmpy simulate Rectifier.fmu --show-plot.

### Which FMI versions and exchange types does FMPy support?

FMPy supports FMI 1.0, 2.0 and 3.0, in both Co-Simulation and Model Exchange, and it runs on Windows, Linux and macOS.

### How do I inspect an FMU before simulating it in FMPy?

Call dump on the FMU, or run fmpy info Rectifier.fmu on the command line. The dump lists the FMI version, platforms, state counts, the default experiment with its stop time and step size, and a table of variables with causality, start value, unit and description.

### Can I share an FMU with people who do not have Python?

Yes. The web app is built with Dash and is started with python -m fmpy.webapp Rectifier.fmu, which serves that FMU to anyone with a web browser. It is a local single model app rather than a multi user service.

### What licence does FMPy use?

GitHub cannot categorise the licence on the repository page, and the full terms are in the LICENSE.txt file at the repository root. Read that file yourself before relying on it, since the platform does not summarise it.

## Sources

- [CATIA-Systems/FMPy on GitHub](https://github.com/CATIA-Systems/FMPy)
- [Issues](https://github.com/CATIA-Systems/FMPy/issues)
- [README](https://github.com/CATIA-Systems/FMPy/blob/main/README.md)
- [Releases](https://github.com/CATIA-Systems/FMPy/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/catia-systems-fmpy
