Contributions of all kinds are welcome, including code, documentation, examples, models, bug reports and reviews. Open a pull request or get in touch through GitHub Discussions.
These pages cover the process. For how the code is organised and the conventions it follows, see the developer guide.
Quick start
Fork the repository and clone your fork.
Run
pre-commit installto activate the automated checks (formatting, notebook output stripping).Create a branch with a descriptive prefix (
feature/,fix/,docs/).Commit with a sign-off, using the conventional commit style:
git commit -s -m "fix: correct node voltage initialization in DiakopticsSolver"Keep your branch up to date by rebasing; do not merge the target branch into your branch:
git fetch upstream git rebase upstream/master git push --force-with-leaseOpen a pull request from your fork against
sogno-platform/dpsim:master.
Pull Requests
There are no strict formal requirements besides the following:
Developer Certificate of Origin (DCO)
We require a Developer Certificate of Origin. See more here.
Code Formatting with
pre-commitWe enforce code formatting automatically using
pre-commit. Please runpre-commit installthe first time you clone the repository to runpre-commitbefore each commit automatically. If you forgot to do this, you will need to use the commandpre-commit run --all-filesone time to format your changes.Development in Forks Only
We accept contributions made in forks only. The main repository is not intended for contributor-specific branches.
SPDX Headers
Use SPDX headers to indicate copyright and licensing information, especially when introducing new files to the codebase. For example:
/* Author: John Smith <John.Smith@example.com> * SPDX-FileCopyrightText: 2025 Example.com * SPDX-License-Identifier: MPL-2.0 */Keep the SPDX tags on adjacent lines with no blank line between them, as the tooling reads them as a block.
Linear History (no merge commits)
DPsim maintains a linear git history. Never merge the target branch into your feature branch; rebase instead:
git rebase upstream/master git push --force-with-leaseNo Saved Notebook Outputs
Jupyter notebooks must be committed without saved cell outputs (images, plots, printed text). Saved outputs bloat diffs and can break the notebook test collector, which re-executes notebooks and re-extracts their outputs. Strip outputs before committing:
jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace <notebook.ipynb>A
pre-commithook does this automatically once you have runpre-commit install; CI also rejects a pull request that changes a notebook still carrying saved outputs.
Creating New Releases (info for maintainers)
DPsim currently uses Semantic Versioning. The periodic creation of new versions can help to mark significant changes and to analyze new portions of code using tools like SonarCloud.
A new version of DPsim has to be indicated as follows:
- Update
versioninpyproject.toml - Update
VERSIONin the top levelCMakeLists.txt - Update
sonar.projectVersioninsonar-project.properties - Update
CHANGELOG.mdand include all the unreleased changes in the list - Create a new tag with an increased version number, which can be done during the release in GitHub
Python Packages
Due to the creation of a new tag, a new PyPi package will be deployed automatically.
Only Linux packages are currently available, other platforms will be supported in the future.
Container Images
To release an updated Docker image, the container workflow needs to be triggered manually.
If a Pull Request changes a container image, this is not updated automatically in the container image register.
Planning
Short-term planning for new features is done on the GitHub Project board.
You can also check the Issues List or the Pull Requests on GitHub.
Provenance and responsibility
Parts of this documentation were drafted with the help of large language models. The maintainers edit and curate that output; they do not vouch for every line as if it were written from first-hand knowledge, and the documentation carries no warranty.
That is a statement about how it is produced, not an excuse. The working rules exist precisely because generated prose is confidently wrong in ways that read well:
- A page is written after running its code, never from reading the API. Every tutorial has a script in the repository and quotes it; if the two disagree, the page is wrong.
- A claim about the code is traced to where the value is used before it is written down. Two hazard notes here described correct code as broken because a line was read in isolation; both were corrected once the value was followed through.
- Anything measurable is measured by a script that reads the source, not asserted from having read a
lot of it. That is what
generate_model_availability.py,check_docs_pairing.pyandcheck_docs_hazards.pyare for. - No reference is cited that the repository does not already contain. Invented citations look exactly like real ones.
A notice in the site footer says the same to readers. If you find something wrong, open an issue. That is more useful than assuming a page is authoritative because it is detailed.
How the documentation is organised
Six sections, split by what the reader is trying to do rather than by topic. Putting a page in the right one is most of the work; the rest is deciding which half of the subject it covers.
| Section | For someone who wants to | Names C++ classes |
|---|---|---|
| User Guide | install DPsim and run a simulation | no |
| Tutorials | learn by working through one idea at a time | only Python API calls |
| Developer Guide | change DPsim, or understand how it works inside | yes |
| Concepts | know the mathematics behind a model or method | never |
| Reference | look up what exists and where | generated |
| Contributing | contribute to the project | n/a |
Every subject is written twice
Concepts carries the mathematics: what the model represents, the equations, and what they assume. It names no class, no file and no example, so a reader could follow it while implementing the model in something else entirely.
Developer Guide carries the arrangement in code: the class hierarchy, how the component interfaces with the solver, its attributes and state layout, the traps in configuring it, and links to the source and examples.
The two link to each other. scripts/docs/check_docs_pairing.py reports any Concepts page without a
counterpart and exits non-zero, with an exemption list for method pages that have no single
implementation behind them.
What is generated rather than written
Do not hand-edit these.
- The model availability matrix comes from the component headers via
scripts/docs/generate_model_availability.py. A model class it does not recognise makes it fail rather than silently omit the model. - The Python and C++ API references are generated by Sphinx and Doxygen from the source, so they are improved by writing better doc comments, not by editing the site.
- Tutorial figures come from
scripts/docs/generate_tutorial_figures.py. The architecture diagrams do not: they are editable draw.io SVGs and must be edited in draw.io.
Conventions
Every page carries a description, which appears under its title in section listings, and a
weight, which sets its order in the sidebar. A page without a weight falls to alphabetical, which
is how sections drift into arbitrary order.
Terminology follows standard electrical engineering usage. Avoid words that collide with class
names: “signal” reads as SimSignalComp rather than as a recorded quantity, so prefer “attribute”.
Highlighting what a reader must not miss
Documentation prose is read in order, so anything that will silently cost someone an afternoon has
to break out of the prose. Use the Docsy alert shortcode, with one of four titles, and keep the
vocabulary small so the colours stay meaningful.
{{% alert title="Requires a build with VILLASnode" color="info" %}}
Something the reader must have before this page works at all.
{{% /alert %}}
| Colour | Use it for | Title starts with |
|---|---|---|
info | a prerequisite: a build flag, an optional dependency, a package that is not installed by default | Requires |
warning | a trap: correct code that silently does the wrong thing, a parameter that means two things, an ordering that matters | Watch out: |
danger | a known defect in DPsim itself, not something the reader can avoid by being careful | Defect: or Suspected defect: |
primary | a genuine aside that is neither a prerequisite nor a hazard | Note |
Use exactly these four prefixes. Earlier pages mixed Trap:, Watch out: and Gap: for the same
colour, which made the severity unreadable: if two words mean one thing, neither means anything.
Three rules keep this useful. Mark a hazard where the reader meets it, not only in a reference page
they may never open, so the same trap can appear on a tutorial and on an implementation page. Reserve danger for defects: if a reader can avoid the problem by knowing about it, it is a
warning, and a page full of red stops being read. And a missing capability is a Note, not a
Watch out:, because there is no hazard to avoid, only something that cannot be done.
Do not use blockquotes for this. They carry no colour and no title, so they read as ordinary text.