Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e0f9f67
Re-structured project to the standard src/pythonfmu3/ structure and m…
eisDNV Aug 4, 2026
f8cb221
Fixed tests so that ============================= test session starts…
eisDNV Aug 4, 2026
c042b82
Added the PID-controller example to /examples. Needed fixes. Changed …
eisDNV Aug 4, 2026
914b037
Added the implementation of EnterEventMode fmi3 function to the Cpp c…
eisDNV Aug 6, 2026
4e078bb
Updated the documentation of ModelVariables class and added since th…
eisDNV Aug 6, 2026
65ab30d
Added a variable type 'Clock' to ModelVariables. Added some documenta…
eisDNV Aug 6, 2026
c3673ee
Implemented all event-related functions in cppfmu/ and pythonfmu/. Co…
eisDNV Aug 9, 2026
ae48cae
Added the function EnterStepMode, which was completely missing, such …
eisDNV Aug 14, 2026
200a59e
In order to receive results from UpdateDiscreteStates() a dedicated N…
eisDNV Aug 14, 2026
e78660d
Ensure all FMI3 model options, so that the system can work with FMI3 …
eisDNV Aug 18, 2026
bfc7144
Change in builder.py to include model options properly
eisDNV Aug 19, 2026
7432e2d
Corrected errors in fmi3slave.py and variables.py leading to errors i…
eisDNV Aug 19, 2026
bdc012a
Added an FMI3 FMU 'function'. Tested basic usage.
eisDNV Aug 19, 2026
1f96296
Adapted function signatures to be as close as possible to FMI3 standa…
eisDNV Aug 28, 2026
8581c7c
Added the arguments 'eventModeUsed' and 'earlyReturnAllowed' in Insta…
eisDNV Sep 7, 2026
fd4ab83
Some last changes as part of moving back to windows. Windows compilat…
eisDNV Oct 9, 2026
5075170
Added windows support to the package. The dynamic libraries and the g…
eisDNV Oct 9, 2026
44bada4
Minor updates within the example FMUs to support discrete_event mode
eisDNV Oct 12, 2026
77dec22
Added CHANGELOG.md to the package
eisDNV Oct 26, 2026
d3fc9a3
Fixed issues detected in verification + Python syntax for event_mode_…
eisDNV Oct 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

# binaries
*.dll
*.dll.manifest
*.so
#*.dll
#*.dll.manifest
#*.so

# pythonfmu binaries folder
/**/pythonfmu3/resources/binaries
#/**/pythonfmu3/resources/binaries

# CLion
/**/cmake-build-debug
Expand All @@ -27,7 +27,7 @@ build/
# test and examples artifacts
/**/*_log.txt
/**/*_result.mat
/**/*.fmu
#/**/*.fmu

# Generated TensorFlow model
/examples/tensorflow-model-export/stored-model/
Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Changelog

All notable changes to the [PythonFMU3s] project from version 0.4.0 will be documented in this file.<br>
The changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]

* -/-



## [0.4.0] - 2026-11
The main goal was the inclusion of event-related functions in the package.
In addition also other functions have been implemented, but there are still some pending FMI3 functions.
All changes where implemented in the branch *eis*

* Re-structured project to the standard src/pythonfmu3/ structure and moving tests/ out. Ran ruff check --fix and ruff format on project
* Fixed tests so that ============================= test session starts ==============================
* Added the PID-controller example to /examples. Needed fixes. Changed therefore docs/usage.md and adapted the documentation build process (adding conf.py, /_static and /_templates)
* Added the implementation of EnterEventMode fmi3 function to the Cpp code. Successfull compilation. Added a basic discrete event example.
* Updated the documentation of ModelVariables class and added since this is not only in use for ME, but also for CS in event mode. It is set to True per default as per FMI spec
* Added a variable type 'Clock' to ModelVariables. Added some documentation also to other variable types and added ModelVariables.to_str as formatter for python types to xml strings
* Implemented all event-related functions in cppfmu/ and pythonfmu/. Code compiles, but is so far not yet tested.
* Added the function EnterStepMode, which was completely missing, such that no switch back to step mode was possible. Compilation ok.
* In order to receive results from UpdateDiscreteStates() a dedicated NamedTuple needs to be defined and used.
* Ensure all FMI3 model options, so that the system can work with FMI3 features. Options are now implemented as dataclass and it is possible to provide options directly to the Slave (not only through cli). Tested features.
* Change in builder.py to include model options properly
* Corrected errors in fmi3slave.py and variables.py leading to errors in FMU building and FMU usage with respect to variables with dimensions
* Added an FMI3 FMU 'function' as an example for a *pass-through* event-based FMU. Tested basic usage.
* Adapted function signatures to be as close as possible to FMI3 standard. SetupExperiment deprecated, EnterInitializationMode updated, EnterContinuousTimeMode and CompletedIntegratorStep added. Recompiled and basic tests.
* Added the arguments 'eventModeUsed' and 'earlyReturnAllowed' in InstantiateCosimulation, which where so far not included. Related changes in fmi3slave are also implemented. Compiles and test works. IntermediateUpdate management is still not included.
* Some last changes as part of moving back to windows. Windows compilation not yet included.
* Added windows support to the package. The dynamic libraries and the generated FMUs have been added to the git package (.gitignore changed).
* Minor updates within the example FMUs to support discrete_event mode
* Added a CHANGELOG.md file to the package and included this point list from the git commit messages.
* Fixed findings from verification. Mainly PySlaveInstance.cpp fixes and adaptations in some .py files. test_cli.py has been removed, since it needs complete re-write
* Changed eventModeUsed -> event_mode_used and earlyReturnAllowed -> early_return_allowed within Python. All examples and tests adapted.




68 changes: 52 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,10 @@ optional arguments:
#### Write the script

```python

from pythonfmu3 import Fmi3Causality, Fmi3Slave, Boolean, Int32, Float64, String


class PythonSlave(Fmi3Slave):

def __init__(self, **kwargs):
super().__init__(**kwargs)

Expand All @@ -114,16 +112,17 @@ class PythonSlave(Fmi3Slave):
self.register_variable(Float64("time", causality=Fmi3Causality.independent))
self.register_variable(Int32("intOut", causality=Fmi3Causality.output))
self.register_variable(Float64("realOut", causality=Fmi3Causality.output))
self.register_variable(Boolean("booleanVariable", causality=Fmi3Causality.local))
self.register_variable(
Boolean("booleanVariable", causality=Fmi3Causality.local)
)
self.register_variable(String("stringVariable", causality=Fmi3Causality.local))

# Note:
# it is also possible to explicitly define getters and setters as lambdas in case the variable is not backed by a Python field.
# self.register_variable(Float64("myReal", causality=Fmi3Causality.output, getter=lambda: self.realOut, setter=lambda v: set_real_out(v))

def do_step(self, current_time, step_size):
return True

```

#### Create the FMU
Expand All @@ -144,13 +143,11 @@ To create a model exchange FMU you must inherit from `Fmi3SlaveBase` and one of
#### Write the script

```python

from pythonfmu3 import Fmi3Causality, Fmi3SlaveBase, Float64, ModelExchange
from typing import List


class PythonSlaveMX(Fmi3SlaveBase, ModelExchange):

def __init__(self, **kwargs):
super().__init__(**kwargs)

Expand All @@ -164,20 +161,59 @@ class PythonSlaveMX(Fmi3SlaveBase, ModelExchange):
self.derx0 = 0.0
self.derx1 = 0.0

self.register_variable(Float64("time", causality=Fmi3Causality.independent, variability=Fmi3Variability.continuous))
self.register_variable(Float64("x0", causality=Fmi3Causality.output, start=2, variability=Fmi3Variability.continuous, initial=Fmi3Initial.exact))
self.register_variable(Float64("x1", causality=Fmi3Causality.output, start=0, variability=Fmi3Variability.continuous, initial=Fmi3Initial.exact))
self.register_variable(Float64("derx0", causality=Fmi3Causality.local, variability=Fmi3Variability.continuous, derivative=1))
self.register_variable(Float64("derx1", causality=Fmi3Causality.local, variability=Fmi3Variability.continuous, derivative=2))
self.register_variable(Float64("mu", causality=Fmi3Causality.parameter, variability=Fmi3Variability.fixed))

self.register_variable(
Float64(
"time",
causality=Fmi3Causality.independent,
variability=Fmi3Variability.continuous,
)
)
self.register_variable(
Float64(
"x0",
causality=Fmi3Causality.output,
start=2,
variability=Fmi3Variability.continuous,
initial=Fmi3Initial.exact,
)
)
self.register_variable(
Float64(
"x1",
causality=Fmi3Causality.output,
start=0,
variability=Fmi3Variability.continuous,
initial=Fmi3Initial.exact,
)
)
self.register_variable(
Float64(
"derx0",
causality=Fmi3Causality.local,
variability=Fmi3Variability.continuous,
derivative=1,
)
)
self.register_variable(
Float64(
"derx1",
causality=Fmi3Causality.local,
variability=Fmi3Variability.continuous,
derivative=2,
)
)
self.register_variable(
Float64(
"mu",
causality=Fmi3Causality.parameter,
variability=Fmi3Variability.fixed,
)
)

def get_continuous_state_derivatives(self) -> List[float]:
self.derx0 = self.x1
self.derx1 = self.mu * ((1 - self.x0**2) * self.x1) - self.x0
return [self.derx0, self.derx1]


```

Note: There is a hard requirement that we have a `self.time` member in the derived class.
Expand Down
56 changes: 56 additions & 0 deletions docs/_static/PythonFMU3.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions docs/_templates/custom-class.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{{ name | escape | underline}}

.. currentmodule:: {{ module }}

.. autoclass:: {{ objname }}
:members:
:show-inheritance:


{% block methods %}
.. automethod:: __init__
{% if methods %}
.. rubric:: {{ _('Methods') }}
.. autosummary::
{% for item in methods %}
~{{ name }}.{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}


{% block attributes %}
{% if attributes %}
.. rubric:: {{ _('Attributes') }}
.. autosummary::
{% for item in attributes %}
~{{ name }}.{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}
67 changes: 67 additions & 0 deletions docs/_templates/custom-module.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{{ fullname | escape | underline}}

.. automodule:: {{ fullname }}
:members:
{%- if classes %}
:exclude-members: {% for item in classes %}{{ item }}{{','}}{%- endfor %}
{% endif %}


{% block attributes %}
{%- if attributes %}
.. rubric:: {{ _('Module Attributes') }}
.. autosummary::
{% for item in attributes %}
{{ item }}
{%- endfor %}
{% endif %}
{%- endblock %}


{%- block functions %}
{%- if functions %}
.. rubric:: {{ _('Functions') }}
.. autosummary::
{% for item in functions %}
{{ item }}
{%- endfor %}
{% endif %}
{%- endblock %}


{%- block classes %}
{%- if classes %}
.. rubric:: {{ _('Classes') }}
.. autosummary::
:toctree:
:template: custom-class.rst
{% for item in classes %}
{{ item }}
{%- endfor %}
{% endif %}
{%- endblock %}


{%- block exceptions %}
{%- if exceptions %}
.. rubric:: {{ _('Exceptions') }}
.. autosummary::
{% for item in exceptions %}
{{ item }}
{%- endfor %}
{% endif %}
{%- endblock %}


{%- block modules %}
{%- if modules %}
.. rubric:: Modules
.. autosummary::
:toctree:
:template: custom-module.rst
:recursive:
{% for item in modules %}
{{ item }}
{%- endfor %}
{% endif %}
{%- endblock %}
Loading
Loading