Library / SDK
MPh-py/MPh avatar
MPh-py/MPh

MPh: a Pythonic scripting interface for Comsol Multiphysics

Pythonic scripting interface for Comsol Multiphysics

604 stars104 forksPythonMIT

At a glance

What is it?
MPh is a MIT licensed Python wrapper that drives Comsol Multiphysics through the JPype Java bridge, covering the scripting tasks a simulation workflow actually needs: loading a model from a file, changing parameters, importing data, running the simulation, evaluating results and exporting them. It is a thin layer with two dependencies, and it requires a local Comsol installation to be useful at all.
Who is it for?
MPh suits the scientist or engineer who already uses Comsol and wants to sweep parameters, run a batch of cases or post-process results from Python instead of clicking through the graphical interface, and it suits teams that want their simulation scripts under version control and in a normal Python environment.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 54 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Python where Comsol only offers Java and Matlab

MPh is a Pythonic scripting interface for Comsol Multiphysics, and the problem it addresses is stated in the README in plain terms: it brings the missing power of Python to the world of Comsol.

Comsol is a commercial simulation package used across science and industry. The README describes it as excelling at modelling almost any multiphysics problem by solving the governing set of partial differential equations with the finite-element method, and it comes with a modern graphical interface for setting up models, and it can be scripted from Matlab or from its native Java API.

So the gap is real. A research group with a hundred parameter cases to run is doing that through a GUI and clicking, or through a Java or Matlab script that has to be written against an API designed for a Java application, not for a scientific script. MPh sits in that gap.

The Python wrapper covers what the README calls common scripting tasks: loading a model from a file, modifying parameters, importing data, running the simulation, evaluating the results and exporting them. That is the whole lifecycle of a parametric study, and it is deliberately not more than that.

The naming comes from Comsol's own file format. Models are marked by the .mph extension, which stands for multi-physics, and the library is named after it. The README is explicit that MPh is open source and in no way affiliated with Comsol Inc., the company that develops and sells the software. That matters for anyone in a commercial setting, and it is the reason the licence question is not as simple as it looks.

The audience is therefore the computational scientist and the simulation engineer, and the licence is MIT with a license.txt file in the repository.

JPype is the whole trick

The mechanism is not a reimplementation of anything. MPh uses the Java bridge provided by JPype to access the Comsol API, and then wraps that API in a layer of pythonic ease-of-use.

That is the entire architecture, and it is a good one to understand because it explains everything about the package, including its limits.

Comsol's scripting surface is its Java API. JPype is the standard way to reach a JVM from Python, and MPh uses it to start a JVM, load Comsol's Java classes and call the same methods the native API and the Matlab interface call. Nothing is emulated and no solver is reimplemented, which is why the dependency list is short and why the results match what the GUI produces.

The cost of that choice is that a JVM has to be there, and that a licensed Comsol installation has to be there, since the Java API ships with the product. MPh is a client, not an engine, and there is no way to install it and simulate anything without the commercial software underneath it.

The declared dependencies are exactly what that architecture needs:

toml
[project]
name = 'MPh'
authors = [{name='John Hennig'}]
version = '1.4.0'
requires-python = '>= 3.10'
dependencies = [
    'JPype1',
    'NumPy',
]

JPype1 for the bridge, and NumPy for the numeric side, which is what you want when results come back as arrays. Two dependencies is a small surface to audit and to keep working, and it also means the wrapper does not drag a numerical stack into your environment behind your back.

The task list, in the order you would run it

The feature description in the README is short, and it is best read as a workflow rather than a list of methods.

You load a model from a file. A .mph file is the artefact, and it holds the model tree, the physics interfaces and the solver configuration that a person would otherwise have built by hand in the GUI.

You then modify parameters. This is the step that matters for automation, because a parametric study is the same model with a different value in a parameter node, and doing that in a loop is the reason to script Comsol at all.

You import data, which is the case where the simulation is driven by measurements or by a table rather than by a closed-form model.

You run the simulation. This is the slow step, and the one where a script earns its keep, since the same code that runs one case can run a hundred.

You evaluate the results, which is where NumPy comes in, and then export them, which is what turns a simulation into an artefact somebody else can look at.

What the README does not do is enumerate the API. There is no method list, no parameter reference and no usage example in the text, so the surface area is what the documentation site and the source contain rather than what the README states. If you need a particular operation, the Read the Docs site is where the answer is, and the demos/ directory in the repository is the next place to look.

That is a real gap in the front door, but not in the project, and it is the kind of gap that a tool with one maintainer and a thorough documentation site can afford.

Two distributions of the same project, one for the store and one for the repo

The repository listing is short and shows something about how the project is packaged.

There is mph/ for the package, tests/ for the test suite, docs/ for the documentation sources, demos/ for example scripts, tools/ for helper scripts, and a .github/ directory for the workflows. Then there are two Markdown files, PyPI.md and ReadMe.md, and the pyproject.toml points its readme key at PyPI.md while the repository's own front page is ReadMe.md.

That is a deliberate split. The README you see on GitHub is the developer and reviewer facing document, describing what the project is and what it is not. The PyPI.md is the store facing document, which is what someone gets when they type pip install MPh and land on the package page. Keeping them separate means the store page can be about installation and usage while the repository page can be about the project and its scope.

The packaging metadata follows the same care. The classifiers are Development Status :: 5 - Production/Stable, Topic :: Scientific/Engineering :: Physics, and Intended Audience :: Science/Research, which is an unusual and useful thing for a package to declare, since it tells an institutional user whether this is a research prototype or something they can rely on. The build backend is uv_build, with a module name of mph and a module root of the repository root, and the licence is MIT with license.txt listed in license-files.

The project also carries a Zenodo badge for a scientific citation, which is the correct practice for a tool that appears in a paper's methods section, and the badges for the PyPI release, download statistics and the latest documentation version complete the picture of a package that takes its distribution seriously.

Linting configuration that reveals the house style

The Ruff configuration in pyproject.toml is worth reading, because a lint configuration is the clearest statement a project makes about its own conventions.

toml
[tool.ruff]
line-length    = 79
indent-width   = 4
target-version = 'py310'

A line length of 79 rather than the more common 88 or 100 is a deliberate choice, and it is consistent with a project that formats by hand or with Black's default. The include list is explicit, covering mph/*.py, tests/*.py, tools/*.py, demos/*.py and pyproject.toml, so the linter does not wander into the documentation directory.

Then there is a comment that says more about the project than any feature list:

toml
[tool.ruff.format]
# The project does not actually use the Ruff formatter (only the linter),
# but these settings would be used if it did.
quote-style = 'single'
line-ending = 'cr-lf'

So the formatter settings are aspirational, configured in case the project adopts it, and the project currently runs Ruff as a linter only. The single quote style and the cr-lf line endings tell you what the committed code looks like even though the tool that would enforce it is not in use.

The dependency groups are organised the same way. The test group has Ruff, basedPyright, pyTest and pyTest-cov, so the linting and type checking happen alongside the tests. The docs group is Sphinx with MyST-parser and Furo, so the documentation is Markdown based rather than reStructuredText. And the dev group simply includes the test and docs groups, which keeps the dependency lists from drifting apart.

The type checking choice is notable: basedPyright rather than mypy, in a package whose whole job is to wrap a Java API and therefore needs to be explicit about what it returns.

A steady release line, and the constraint nobody can engineer away

The release history is slow and recent. v1.3.1 is dated 2025-11-07, v1.3.2 on 2026-08-16, and v1.4.0 on 2026-08-30, with the last push to the repository on the same day as v1.4.0.

Two releases in nine months, and a 1.0 release number with a Production/Stable classifier, describes a project that has settled. It is not abandoned, the version numbering is conventional, and the pattern of a patch release followed by a minor feature release a fortnight later suggests a maintainer who ships when there is something to ship.

The limitation that matters is not the release pace. It is that this is a wrapper around a commercial product with its own release schedule, and the two are coupled. Comsol updates its Java API, and a wrapper has to catch up. A project can be perfectly maintained and still be a few months behind the vendor's newest release, and the user is the one who discovers the mismatch when a method behaves differently.

The second limitation is scope. The README describes the covered tasks as common scripting tasks, and the wrapper exists to make those pleasant, not to expose the entire Java API. A workflow that needs an obscure model tree operation, a custom solver configuration or a particular export format may find that the wrapper stops short, at which point the options are to file an issue, to add the method yourself, or to drop down to the Java API through the same JPype session.

The third is the one that decides who can use it at all. Comsol is commercial software with a licence, and MPh is a client for it. There is no free tier of the engine, so the practical audience is narrower than the audience for open source scientific tooling generally, and the README's line about not being affiliated with Comsol Inc. is the place where that constraint is stated.

Editorial conclusion

MPh suits the scientist or engineer who already uses Comsol and wants to sweep parameters, run a batch of cases or post-process results from Python instead of clicking through the graphical interface, and it suits teams that want their simulation scripts under version control and in a normal Python environment. It does not suit you if you do not have a Comsol licence, since the package is a client for a commercial installation, and it does not suit a workflow that needs a physics feature the wrapper has not exposed, because the API surface is whatever the maintainer has wrapped. Check three things before you adopt it: that your Comsol version is one this release of MPh works with, since the wrapper tracks the vendor's Java API, that the operations you need are covered, since the README summarises the scope rather than enumerating every method, and that your environment has a JVM that JPype can attach to. The newest release is 1.4.0 from 2026-08-30 and the last push to the repository was on the same day.

Frequently asked questions

What does MPh do and what does it require?

MPh is a Pythonic scripting interface for Comsol Multiphysics that covers loading a model from a file, modifying parameters, importing data, running the simulation, evaluating results and exporting them. It requires a local licensed Comsol installation, because it reaches the Comsol Java API through JPype.

Which Python version and dependencies does MPh need?

The package metadata requires Python 3.10 or newer and lists only two runtime dependencies, JPype1 for the Java bridge and NumPy for the numeric results. The build backend is uv_build, and the test group adds Ruff, basedPyright and pyTest.

Is MPh affiliated with Comsol?

No. The README states that MPh is open source and in no way affiliated with Comsol Inc., the company that develops and sells the simulation software. MPh itself is MIT licensed.

Where is the MPh documentation?

The full documentation is on Read the Docs at mph.readthedocs.io, with the repository holding the docs/ sources, a demos/ directory of example scripts, and a separate PyPI.md used as the package page on PyPI.

What are the recent MPh releases?

The recent versions are 1.3.1 from 2025-11-07, 1.3.2 from 2026-08-16 and 1.4.0 from 2026-08-30, and the last push to the repository was on 2026-08-30.

Official sources

  1. License: MIT
  2. MPh-py/MPh on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mph-py-mph.svg)](https://hysenlabs.com/projects/mph-py-mph)

Was this useful?