rumoca 0.7.1__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,3 @@
1
+ include README.md
2
+ # Templates are NOT installed - they are examples only in the source repository
3
+ # Users should use the --json flag for Base Modelica export
rumoca-0.7.1/PKG-INFO ADDED
@@ -0,0 +1,416 @@
1
+ Metadata-Version: 2.4
2
+ Name: rumoca
3
+ Version: 0.7.1
4
+ Summary: Python interface for the Rumoca Modelica compiler
5
+ Author: Rumoca Contributors
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/jgoppert/rumoca
8
+ Project-URL: Documentation, https://github.com/jgoppert/rumoca/blob/main/python/README.md
9
+ Project-URL: Repository, https://github.com/jgoppert/rumoca
10
+ Project-URL: Issues, https://github.com/jgoppert/rumoca/issues
11
+ Keywords: modelica,compiler,simulation,dae,code-generation
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Rust
22
+ Classifier: Topic :: Scientific/Engineering
23
+ Classifier: Topic :: Software Development :: Code Generators
24
+ Classifier: Topic :: Software Development :: Compilers
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
30
+ Requires-Dist: black>=23.0; extra == "dev"
31
+ Requires-Dist: mypy>=1.0; extra == "dev"
32
+ Provides-Extra: cyecca
33
+ Requires-Dist: cyecca>=0.1.0; extra == "cyecca"
34
+ Provides-Extra: notebook
35
+ Requires-Dist: jupyter>=1.0; extra == "notebook"
36
+ Requires-Dist: matplotlib>=3.5; extra == "notebook"
37
+ Requires-Dist: numpy>=1.20; extra == "notebook"
38
+ Provides-Extra: all
39
+ Requires-Dist: rumoca[cyecca,dev,notebook]; extra == "all"
40
+
41
+ # Rumoca Python Interface
42
+
43
+ Python wrapper for the [Rumoca](https://github.com/jgoppert/rumoca) Modelica compiler, enabling seamless integration with [Cyecca](https://github.com/cognipilot/cyecca) for code generation and simulation.
44
+
45
+ ## Installation
46
+
47
+ ### Prerequisites
48
+
49
+ 1. **Build Rumoca** (Rust toolchain required):
50
+ ```bash
51
+ cd /path/to/rumoca
52
+ cargo build --release
53
+ ```
54
+
55
+ 2. **Add to PATH** (optional but recommended):
56
+ ```bash
57
+ export PATH=$PATH:/path/to/rumoca/target/release
58
+ ```
59
+
60
+ ### Install Python Package
61
+
62
+ ```bash
63
+ # From source (development)
64
+ cd rumoca/python
65
+ pip install -e .
66
+
67
+ # With Cyecca integration
68
+ pip install -e ".[cyecca]"
69
+
70
+ # With Jupyter notebook support
71
+ pip install -e ".[notebook]"
72
+
73
+ # Everything
74
+ pip install -e ".[all]"
75
+ ```
76
+
77
+ ## Quick Start
78
+
79
+ ### Basic Usage
80
+
81
+ ```python
82
+ import rumoca
83
+
84
+ # Compile a Modelica model
85
+ result = rumoca.compile("bouncing_ball.mo")
86
+
87
+ # Export to Base Modelica JSON
88
+ result.export_base_modelica_json("bouncing_ball.json")
89
+
90
+ # Or get as string
91
+ json_str = result.to_base_modelica_json()
92
+
93
+ # Or get as Python dict
94
+ model_dict = result.to_base_modelica_dict()
95
+ ```
96
+
97
+ ### Integration with Cyecca
98
+
99
+ ```python
100
+ import rumoca
101
+ from cyecca.io import import_base_modelica
102
+
103
+ # Compile Modelica model
104
+ result = rumoca.compile("my_model.mo")
105
+ result.export_base_modelica_json("my_model.json")
106
+
107
+ # Import into Cyecca
108
+ model = import_base_modelica("my_model.json")
109
+
110
+ print(f"Model: {model.name}")
111
+ print(f"States: {[v.name for v in model.variables if v.is_state]}")
112
+ ```
113
+
114
+ ### Code Generation with Cyecca
115
+
116
+ ```python
117
+ import rumoca
118
+ from cyecca.io.base_modelica import import_base_modelica
119
+ from cyecca.backends.casadi import generate_casadi
120
+ from cyecca.backends.sympy import generate_sympy
121
+
122
+ # Compile to Base Modelica
123
+ result = rumoca.compile("my_model.mo")
124
+ result.export_base_modelica_json("my_model.json")
125
+
126
+ # Import with Cyecca
127
+ model = import_base_modelica("my_model.json")
128
+
129
+ # Generate CasADi code
130
+ casadi_code = generate_casadi(model)
131
+ with open("my_model_casadi.py", "w") as f:
132
+ f.write(casadi_code)
133
+
134
+ # Generate SymPy code
135
+ sympy_code = generate_sympy(model)
136
+ with open("my_model_sympy.py", "w") as f:
137
+ f.write(sympy_code)
138
+ ```
139
+
140
+ ## Jupyter Notebook Workflow
141
+
142
+ See [examples/bouncing_ball_demo.ipynb](../examples/notebooks/bouncing_ball_demo.ipynb) for a complete example.
143
+
144
+ ```python
145
+ # Cell 1: Compile
146
+ import rumoca
147
+ from cyecca.io import import_base_modelica
148
+ import matplotlib.pyplot as plt
149
+
150
+ result = rumoca.compile("bouncing_ball.mo")
151
+ result.export_base_modelica_json("bouncing_ball.json")
152
+
153
+ # Cell 2: Import and inspect
154
+ model = import_base_modelica("bouncing_ball.json")
155
+ print(f"States: {[v.name for v in model.variables if not v.is_parameter]}")
156
+
157
+ # Cell 3: Generate simulation code
158
+ from cyecca.codegen import generate_simulation_code
159
+ code = generate_simulation_code(model, backend="python")
160
+
161
+ # Cell 4: Simulate and plot
162
+ results = code.simulate(t_span=(0, 10), dt=0.01)
163
+ plt.plot(results['t'], results['h'], label='Height')
164
+ plt.plot(results['t'], results['v'], label='Velocity')
165
+ plt.legend()
166
+ plt.show()
167
+ ```
168
+
169
+ ## API Reference
170
+
171
+ ### `rumoca.compile(model_file, rumoca_bin=None)`
172
+
173
+ Compile a Modelica model file.
174
+
175
+ **Parameters:**
176
+ - `model_file` (str | Path): Path to the Modelica (.mo) file
177
+ - `rumoca_bin` (str | Path, optional): Path to rumoca binary (auto-detected if None)
178
+
179
+ **Returns:**
180
+ - `CompilationResult`: Object containing the compiled model
181
+
182
+ **Raises:**
183
+ - `FileNotFoundError`: If model file doesn't exist
184
+ - `RuntimeError`: If rumoca binary not found
185
+ - `CompilationError`: If compilation fails
186
+
187
+ **Example:**
188
+ ```python
189
+ result = rumoca.compile("bouncing_ball.mo")
190
+ ```
191
+
192
+ ### `CompilationResult`
193
+
194
+ Result of compiling a Modelica model.
195
+
196
+ #### Methods
197
+
198
+ ##### `to_base_modelica_json() -> str`
199
+
200
+ Export model to Base Modelica JSON format as a string.
201
+
202
+ **Returns:**
203
+ - `str`: JSON string containing Base Modelica representation (MCP-0031)
204
+
205
+ **Raises:**
206
+ - `CompilationError`: If export fails
207
+
208
+ **Example:**
209
+ ```python
210
+ result = rumoca.compile("model.mo")
211
+ json_str = result.to_base_modelica_json()
212
+ ```
213
+
214
+ ##### `export_base_modelica_json(output_file)`
215
+
216
+ Export model to Base Modelica JSON file.
217
+
218
+ **Parameters:**
219
+ - `output_file` (str | Path): Path where JSON file will be written
220
+
221
+ **Raises:**
222
+ - `CompilationError`: If export fails
223
+
224
+ **Example:**
225
+ ```python
226
+ result = rumoca.compile("model.mo")
227
+ result.export_base_modelica_json("model.json")
228
+ ```
229
+
230
+ ##### `to_base_modelica_dict() -> dict`
231
+
232
+ Get Base Modelica representation as Python dictionary.
233
+
234
+ **Returns:**
235
+ - `dict`: Dictionary containing Base Modelica model data
236
+
237
+ **Example:**
238
+ ```python
239
+ result = rumoca.compile("model.mo")
240
+ data = result.to_base_modelica_dict()
241
+ print(f"Parameters: {len(data['parameters'])}")
242
+ ```
243
+
244
+ ##### `export(template_file) -> str`
245
+
246
+ Advanced: Export using a custom template.
247
+
248
+ **Parameters:**
249
+ - `template_file` (str | Path): Path to custom Jinja2 template file
250
+
251
+ **Returns:**
252
+ - `str`: Generated code as string
253
+
254
+ **Note:** For standard code generation, use `to_base_modelica_json()` + Cyecca instead.
255
+
256
+ ## Examples
257
+
258
+ ### Example 1: Simple Compilation
259
+
260
+ ```python
261
+ import rumoca
262
+
263
+ # Compile and export in one go
264
+ result = rumoca.compile("integrator.mo")
265
+ result.export_base_modelica_json("integrator.json")
266
+ ```
267
+
268
+ ### Example 2: Inspect Model Structure
269
+
270
+ ```python
271
+ import rumoca
272
+
273
+ result = rumoca.compile("rover.mo")
274
+ model_data = result.to_base_modelica_dict()
275
+
276
+ print(f"Model: {model_data['model_name']}")
277
+ print(f"Parameters: {len(model_data['parameters'])}")
278
+ print(f"Variables: {len(model_data['variables'])}")
279
+ print(f"Equations: {len(model_data['equations'])}")
280
+ ```
281
+
282
+ ### Example 3: Full Workflow with Cyecca
283
+
284
+ ```python
285
+ import rumoca
286
+ from cyecca.io.base_modelica import import_base_modelica
287
+ from cyecca.backends.casadi import generate_casadi
288
+
289
+ # Step 1: Compile Modelica to Base Modelica
290
+ result = rumoca.compile("quadrotor.mo")
291
+ result.export_base_modelica_json("quadrotor.json")
292
+
293
+ # Step 2: Import with Cyecca
294
+ model = import_base_modelica("quadrotor.json")
295
+
296
+ # Step 3: Generate CasADi code
297
+ casadi_code = generate_casadi(model)
298
+
299
+ # Step 4: Save generated code
300
+ with open("quadrotor_casadi.py", "w") as f:
301
+ f.write(casadi_code)
302
+ ```
303
+
304
+ ### Example 4: Error Handling
305
+
306
+ ```python
307
+ import rumoca
308
+
309
+ try:
310
+ result = rumoca.compile("my_model.mo")
311
+ result.export_base_modelica_json("output.json")
312
+ except FileNotFoundError as e:
313
+ print(f"Model file not found: {e}")
314
+ except rumoca.CompilationError as e:
315
+ print(f"Compilation failed: {e}")
316
+ ```
317
+
318
+ ## Architecture
319
+
320
+ ### Subprocess-Based Wrapper
321
+
322
+ The current implementation uses a subprocess-based wrapper that:
323
+
324
+ 1. Calls the `rumoca` binary as a subprocess with `--json` flag
325
+ 2. Receives Base Modelica JSON via stdout
326
+ 3. Parses JSON into Python dictionaries
327
+ 4. Captures stderr for error reporting
328
+
329
+ **Advantages:**
330
+ - Simple implementation
331
+ - Easy to maintain
332
+ - Works with existing Rumoca binary
333
+ - Fast native JSON serialization in Rust
334
+
335
+ **Workflow:**
336
+ ```
337
+ Python → subprocess(rumoca --json) → Base Modelica JSON → Python dict
338
+
339
+ Cyecca
340
+
341
+ Generated Code
342
+ ```
343
+
344
+ ### Future: PyO3 Bindings
345
+
346
+ A future version may use [PyO3](https://pyo3.rs/) for native Rust-Python bindings:
347
+
348
+ - Direct access to Rumoca's DAE structures
349
+ - No subprocess overhead
350
+ - Zero-copy data transfer
351
+ - Tighter integration possibilities
352
+
353
+ ## Troubleshooting
354
+
355
+ ### "Rumoca binary not found"
356
+
357
+ **Solution 1:** Add rumoca to PATH:
358
+ ```bash
359
+ export PATH=$PATH:/path/to/rumoca/target/release
360
+ ```
361
+
362
+ **Solution 2:** Specify binary path explicitly:
363
+ ```python
364
+ result = rumoca.compile("model.mo", rumoca_bin="/path/to/rumoca")
365
+ ```
366
+
367
+ ### Compilation errors
368
+
369
+ Check the Modelica syntax by running rumoca directly:
370
+ ```bash
371
+ rumoca your_model.mo --json
372
+ ```
373
+
374
+ If successful, you should see Base Modelica JSON output.
375
+
376
+ ## Development
377
+
378
+ ### Running Tests
379
+
380
+ ```bash
381
+ cd rumoca/python
382
+ pip install -e ".[dev]"
383
+ pytest
384
+ ```
385
+
386
+ ### Type Checking
387
+
388
+ ```bash
389
+ mypy rumoca
390
+ ```
391
+
392
+ ### Code Formatting
393
+
394
+ ```bash
395
+ black rumoca tests
396
+ ```
397
+
398
+ ## Contributing
399
+
400
+ Contributions welcome! Please:
401
+
402
+ 1. Run tests: `pytest`
403
+ 2. Check types: `mypy rumoca`
404
+ 3. Format code: `black rumoca tests`
405
+ 4. Update documentation
406
+
407
+ ## License
408
+
409
+ Apache 2.0 (same as Rumoca)
410
+
411
+ ## See Also
412
+
413
+ - [Rumoca Compiler](https://github.com/jgoppert/rumoca)
414
+ - [Cyecca Code Generator](https://github.com/cognipilot/cyecca)
415
+ - [Base Modelica Specification (MCP-0031)](https://modelica.org/mcp/)
416
+ - [Modelica Language](https://www.modelica.org/)