fmuloader 0.1.1rc0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,168 @@
1
+ Metadata-Version: 2.3
2
+ Name: fmuloader
3
+ Version: 0.1.1rc0
4
+ Summary: a lightweight fmu loader for python
5
+ Author: coder
6
+ Author-email: coder <coder@timeintegral.ai>
7
+ Requires-Python: >=3.11
8
+ Project-URL: Repository, https://github.com/time-integral/fmuloader
9
+ Description-Content-Type: text/markdown
10
+
11
+ # fmuloader ⚙️
12
+
13
+ A lightweight, **zero-dependency** Python library for loading and calling FMI 2.0
14
+ and 3.0 shared-library binaries via ctypes.
15
+
16
+ [![PyPI version](https://badge.fury.io/py/fmuloader.svg)](https://badge.fury.io/py/fmuloader)
17
+
18
+ ## Installation 📦
19
+
20
+ Add `fmuloader` to your project with `uv`:
21
+
22
+ ```bash
23
+ uv add fmuloader
24
+ ```
25
+
26
+ > To install `uv`, see <https://docs.astral.sh/uv/getting-started/installation/>
27
+
28
+ ## How to use 🚀
29
+
30
+ ### FMI 2.0 Co-Simulation
31
+
32
+ ```python
33
+ from fmuloader.fmi2 import Fmi2Slave, Fmi2Type
34
+
35
+ slave = Fmi2Slave("model.fmu", model_identifier="MyModel")
36
+
37
+ slave.instantiate("instance1", Fmi2Type.CO_SIMULATION, guid="{...}")
38
+ slave.setup_experiment(start_time=0.0, stop_time=10.0)
39
+ slave.enter_initialization_mode()
40
+ slave.exit_initialization_mode()
41
+
42
+ t, dt = 0.0, 0.01
43
+ while t < 10.0:
44
+ slave.do_step(t, dt)
45
+ t += dt
46
+
47
+ values = slave.get_real([1, 2])
48
+ slave.terminate()
49
+ slave.free_instance()
50
+ ```
51
+
52
+ ### FMI 3.0 Co-Simulation
53
+
54
+ ```python
55
+ from fmuloader.fmi3 import Fmi3Slave
56
+
57
+ slave = Fmi3Slave("model.fmu", model_identifier="MyModel")
58
+
59
+ slave.instantiate_co_simulation("instance1", instantiation_token="{...}")
60
+ slave.enter_initialization_mode(start_time=0.0, stop_time=10.0)
61
+ slave.exit_initialization_mode()
62
+
63
+ t, dt = 0.0, 0.01
64
+ while t < 10.0:
65
+ result = slave.do_step(t, dt)
66
+ t += dt
67
+
68
+ values = slave.get_float64([1, 2])
69
+ slave.terminate()
70
+ slave.free_instance()
71
+ ```
72
+
73
+ ### FMI 3.0 Model Exchange
74
+
75
+ ```python
76
+ from fmuloader.fmi3 import Fmi3Slave
77
+
78
+ slave = Fmi3Slave("model.fmu", model_identifier="MyModel")
79
+
80
+ slave.instantiate_model_exchange("instance1", instantiation_token="{...}")
81
+ slave.enter_initialization_mode(start_time=0.0)
82
+ slave.exit_initialization_mode()
83
+
84
+ result = slave.update_discrete_states()
85
+ while result.discrete_states_need_update:
86
+ result = slave.update_discrete_states()
87
+ slave.enter_continuous_time_mode()
88
+
89
+ nx = slave.get_number_of_continuous_states()
90
+ slave.set_time(0.0)
91
+ derivs = slave.get_continuous_state_derivatives(nx)
92
+
93
+ slave.terminate()
94
+ slave.free_instance()
95
+ ```
96
+
97
+ ### FMI 3.0 Scheduled Execution
98
+
99
+ ```python
100
+ from fmuloader.fmi3 import Fmi3Slave
101
+
102
+ slave = Fmi3Slave("model.fmu", model_identifier="MyModel")
103
+
104
+ slave.instantiate_scheduled_execution("instance1", instantiation_token="{...}")
105
+ slave.enter_initialization_mode(start_time=0.0)
106
+ slave.exit_initialization_mode()
107
+
108
+ slave.activate_model_partition(clock_reference=1001, activation_time=0.0)
109
+
110
+ slave.terminate()
111
+ slave.free_instance()
112
+ ```
113
+
114
+ ## Features ✨
115
+
116
+ - Load and call FMI **2.0** and **3.0** shared-library binaries via ctypes
117
+ - Full Co-Simulation, Model Exchange, and Scheduled Execution support
118
+ - All FMI 3.0 data types: `Float32`, `Float64`, `Int8`–`Int64`, `UInt8`–`UInt64`, `Boolean`, `String`, `Binary`, `Clock`
119
+ - FMU state management: get, set, serialize, and deserialize
120
+ - Directional and adjoint derivatives
121
+ - Clock interval and shift functions
122
+ - Context manager support for automatic cleanup
123
+ - Automatic platform detection (macOS, Linux, Windows; x86, x86_64, aarch64)
124
+
125
+ ## Design philosophy 💡
126
+
127
+ **fmuloader intentionally separates binary loading from modelDescription.xml parsing.**
128
+
129
+ Most FMI libraries tightly couple XML parsing with binary invocation, pulling in
130
+ heavy dependencies and making it hard to use one without the other. fmuloader
131
+ takes a different approach:
132
+
133
+ - **fmuloader** handles only the **binary loading** — extracting the shared
134
+ library from an `.fmu` archive, binding every C function via ctypes, and
135
+ exposing thin Python wrappers.
136
+ - **modelDescription.xml parsing** is left to the user or to a dedicated library
137
+ like [fmureader](https://github.com/time-integral/fmureader).
138
+
139
+ This means:
140
+
141
+ - **Zero runtime dependencies** — fmuloader uses only the Python standard library.
142
+ - **Bring your own parser** — use fmureader, FMPy, lxml, or anything else to
143
+ read GUIDs, value references, and variable metadata. Then pass them straight
144
+ to fmuloader.
145
+ - **Minimal surface area** — each module (`fmi2`, `fmi3`) is a single file you
146
+ can vendor into your own project if needed.
147
+
148
+ ```python
149
+ # Example: combine fmureader (parsing) with fmuloader (execution)
150
+ import fmureader.fmi3 as reader
151
+ from fmuloader.fmi3 import Fmi3Slave
152
+
153
+ md = reader.read_model_description("model.fmu")
154
+
155
+ slave = Fmi3Slave("model.fmu", model_identifier=md.co_simulation.model_identifier)
156
+ slave.instantiate_co_simulation("inst", instantiation_token=md.instantiation_token)
157
+ # ... use md.model_variables to look up value references, then call slave.get_float64() etc.
158
+ ```
159
+
160
+ ## Related projects 🔗
161
+
162
+ - [fmureader](https://github.com/time-integral/fmureader) — Lightweight Pydantic-based modelDescription.xml parser for FMI 2.0 and 3.0
163
+ - [FMPy](https://github.com/CATIA-Systems/FMPy) — Full-featured FMI library with simulation, GUI, and more
164
+
165
+ ## Licensing 📄
166
+
167
+ The code in this project is licensed under MIT license.
168
+ See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,158 @@
1
+ # fmuloader ⚙️
2
+
3
+ A lightweight, **zero-dependency** Python library for loading and calling FMI 2.0
4
+ and 3.0 shared-library binaries via ctypes.
5
+
6
+ [![PyPI version](https://badge.fury.io/py/fmuloader.svg)](https://badge.fury.io/py/fmuloader)
7
+
8
+ ## Installation 📦
9
+
10
+ Add `fmuloader` to your project with `uv`:
11
+
12
+ ```bash
13
+ uv add fmuloader
14
+ ```
15
+
16
+ > To install `uv`, see <https://docs.astral.sh/uv/getting-started/installation/>
17
+
18
+ ## How to use 🚀
19
+
20
+ ### FMI 2.0 Co-Simulation
21
+
22
+ ```python
23
+ from fmuloader.fmi2 import Fmi2Slave, Fmi2Type
24
+
25
+ slave = Fmi2Slave("model.fmu", model_identifier="MyModel")
26
+
27
+ slave.instantiate("instance1", Fmi2Type.CO_SIMULATION, guid="{...}")
28
+ slave.setup_experiment(start_time=0.0, stop_time=10.0)
29
+ slave.enter_initialization_mode()
30
+ slave.exit_initialization_mode()
31
+
32
+ t, dt = 0.0, 0.01
33
+ while t < 10.0:
34
+ slave.do_step(t, dt)
35
+ t += dt
36
+
37
+ values = slave.get_real([1, 2])
38
+ slave.terminate()
39
+ slave.free_instance()
40
+ ```
41
+
42
+ ### FMI 3.0 Co-Simulation
43
+
44
+ ```python
45
+ from fmuloader.fmi3 import Fmi3Slave
46
+
47
+ slave = Fmi3Slave("model.fmu", model_identifier="MyModel")
48
+
49
+ slave.instantiate_co_simulation("instance1", instantiation_token="{...}")
50
+ slave.enter_initialization_mode(start_time=0.0, stop_time=10.0)
51
+ slave.exit_initialization_mode()
52
+
53
+ t, dt = 0.0, 0.01
54
+ while t < 10.0:
55
+ result = slave.do_step(t, dt)
56
+ t += dt
57
+
58
+ values = slave.get_float64([1, 2])
59
+ slave.terminate()
60
+ slave.free_instance()
61
+ ```
62
+
63
+ ### FMI 3.0 Model Exchange
64
+
65
+ ```python
66
+ from fmuloader.fmi3 import Fmi3Slave
67
+
68
+ slave = Fmi3Slave("model.fmu", model_identifier="MyModel")
69
+
70
+ slave.instantiate_model_exchange("instance1", instantiation_token="{...}")
71
+ slave.enter_initialization_mode(start_time=0.0)
72
+ slave.exit_initialization_mode()
73
+
74
+ result = slave.update_discrete_states()
75
+ while result.discrete_states_need_update:
76
+ result = slave.update_discrete_states()
77
+ slave.enter_continuous_time_mode()
78
+
79
+ nx = slave.get_number_of_continuous_states()
80
+ slave.set_time(0.0)
81
+ derivs = slave.get_continuous_state_derivatives(nx)
82
+
83
+ slave.terminate()
84
+ slave.free_instance()
85
+ ```
86
+
87
+ ### FMI 3.0 Scheduled Execution
88
+
89
+ ```python
90
+ from fmuloader.fmi3 import Fmi3Slave
91
+
92
+ slave = Fmi3Slave("model.fmu", model_identifier="MyModel")
93
+
94
+ slave.instantiate_scheduled_execution("instance1", instantiation_token="{...}")
95
+ slave.enter_initialization_mode(start_time=0.0)
96
+ slave.exit_initialization_mode()
97
+
98
+ slave.activate_model_partition(clock_reference=1001, activation_time=0.0)
99
+
100
+ slave.terminate()
101
+ slave.free_instance()
102
+ ```
103
+
104
+ ## Features ✨
105
+
106
+ - Load and call FMI **2.0** and **3.0** shared-library binaries via ctypes
107
+ - Full Co-Simulation, Model Exchange, and Scheduled Execution support
108
+ - All FMI 3.0 data types: `Float32`, `Float64`, `Int8`–`Int64`, `UInt8`–`UInt64`, `Boolean`, `String`, `Binary`, `Clock`
109
+ - FMU state management: get, set, serialize, and deserialize
110
+ - Directional and adjoint derivatives
111
+ - Clock interval and shift functions
112
+ - Context manager support for automatic cleanup
113
+ - Automatic platform detection (macOS, Linux, Windows; x86, x86_64, aarch64)
114
+
115
+ ## Design philosophy 💡
116
+
117
+ **fmuloader intentionally separates binary loading from modelDescription.xml parsing.**
118
+
119
+ Most FMI libraries tightly couple XML parsing with binary invocation, pulling in
120
+ heavy dependencies and making it hard to use one without the other. fmuloader
121
+ takes a different approach:
122
+
123
+ - **fmuloader** handles only the **binary loading** — extracting the shared
124
+ library from an `.fmu` archive, binding every C function via ctypes, and
125
+ exposing thin Python wrappers.
126
+ - **modelDescription.xml parsing** is left to the user or to a dedicated library
127
+ like [fmureader](https://github.com/time-integral/fmureader).
128
+
129
+ This means:
130
+
131
+ - **Zero runtime dependencies** — fmuloader uses only the Python standard library.
132
+ - **Bring your own parser** — use fmureader, FMPy, lxml, or anything else to
133
+ read GUIDs, value references, and variable metadata. Then pass them straight
134
+ to fmuloader.
135
+ - **Minimal surface area** — each module (`fmi2`, `fmi3`) is a single file you
136
+ can vendor into your own project if needed.
137
+
138
+ ```python
139
+ # Example: combine fmureader (parsing) with fmuloader (execution)
140
+ import fmureader.fmi3 as reader
141
+ from fmuloader.fmi3 import Fmi3Slave
142
+
143
+ md = reader.read_model_description("model.fmu")
144
+
145
+ slave = Fmi3Slave("model.fmu", model_identifier=md.co_simulation.model_identifier)
146
+ slave.instantiate_co_simulation("inst", instantiation_token=md.instantiation_token)
147
+ # ... use md.model_variables to look up value references, then call slave.get_float64() etc.
148
+ ```
149
+
150
+ ## Related projects 🔗
151
+
152
+ - [fmureader](https://github.com/time-integral/fmureader) — Lightweight Pydantic-based modelDescription.xml parser for FMI 2.0 and 3.0
153
+ - [FMPy](https://github.com/CATIA-Systems/FMPy) — Full-featured FMI library with simulation, GUI, and more
154
+
155
+ ## Licensing 📄
156
+
157
+ The code in this project is licensed under MIT license.
158
+ See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,35 @@
1
+ [project]
2
+ name = "fmuloader"
3
+ version = "0.1.1rc0"
4
+ description = "a lightweight fmu loader for python"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "coder", email = "coder@timeintegral.ai" }
8
+ ]
9
+ requires-python = ">=3.11"
10
+ dependencies = []
11
+
12
+ [project.urls]
13
+ Repository = "https://github.com/time-integral/fmuloader"
14
+
15
+ [build-system]
16
+ requires = ["uv_build>=0.10.0,<0.11.0"]
17
+ build-backend = "uv_build"
18
+
19
+ [dependency-groups]
20
+ dev = [
21
+ "httpx>=0.28.1",
22
+ "pyright>=1.1.407",
23
+ "pytest>=9.0.2",
24
+ "pytest-cov>=7.0.0",
25
+ ]
26
+
27
+
28
+ [tool.pyright]
29
+ include = [
30
+ "src",
31
+ ]
32
+
33
+ [tool.uv]
34
+ default-groups = ["dev"]
35
+ package = true
@@ -0,0 +1 @@
1
+ __version__ = "0.1.1rc0"