113 lines
5.0 KiB
Markdown
113 lines
5.0 KiB
Markdown
# entropyk-fmi — Export FMI 2.0 Co-Simulation (FMU)
|
|
|
|
Compile un modèle Entropyk (JSON) en une archive `.fmu` conforme FMI 2.0 Co-Simulation, embarquable sur un PLC / contrôleur industriel (Beckhoff TwinCAT, B&R, Siemens TIA, Codesys) ou testable sur PC avec fmpy / OpenModelica.
|
|
|
|
## Principe
|
|
|
|
- Le moteur Entropyk (Rust) est compilé en `cdylib` et exporte l'ABI C standard `fmi2*`.
|
|
- Le modèle JSON + la carte d'entrées/sorties (`fmu_io.json`) sont **embarqués dans le binaire** à la build (codegen) — aucun accès fichier au runtime.
|
|
- L'hôte (PLC) pilote le scheduler temps réel ; chaque `fmi2DoStep` re-resout le cycle stationnaire aux entrées courantes (co-simulation quasi-stationnaire).
|
|
|
|
## Générer un FMU
|
|
|
|
```bash
|
|
# Cible hôte (PC courant) — pour test avec fmpy
|
|
cargo run -p entropyk-cli -- export-fmu \
|
|
-c crates/cli/examples/chiller_aircooled_r134a.json \
|
|
-i bindings/fmi/examples/chiller_aircooled_io.json \
|
|
-t host \
|
|
-o target/chiller.fmu
|
|
```
|
|
|
|
### Cross-compilation (arm / x86)
|
|
|
|
Installer les cibles Rust voulues, puis :
|
|
|
|
```bash
|
|
# Linux x86_64
|
|
rustup target add x86_64-unknown-linux-gnu
|
|
cargo run -p entropyk-cli -- export-fmu -c <model.json> -i <io.json> \
|
|
-t x86_64-unknown-linux-gnu -o target/model_linux64.fmu
|
|
|
|
# Linux ARM64 (aarch64)
|
|
rustup target add aarch64-unknown-linux-gnu
|
|
cargo run -p entropyk-cli -- export-fmu -c <model.json> -i <io.json> \
|
|
-t aarch64-unknown-linux-gnu -o target/model_aarch64.fmu
|
|
|
|
# Linux ARM32 (Cortex-A, hard-float)
|
|
rustup target add arm-unknown-linux-gnueabihf
|
|
cargo run -p entropyk-cli -- export-fmu -c <model.json> -i <io.json> \
|
|
-t arm-unknown-linux-gnueabihf -o target/model_arm32.fmu
|
|
|
|
# Windows x86_64 (PLC TwinCAT sur IPC Windows)
|
|
rustup target add x86_64-pc-windows-msvc
|
|
cargo run -p entropyk-cli -- export-fmu -c <model.json> -i <io.json> \
|
|
-t x86_64-pc-windows-msvc -o target/model_win64.fmu
|
|
```
|
|
|
|
Le dossier `binaries/<platform>/` est choisi automatiquement depuis le triple cible :
|
|
|
|
| Triple cible | Dossier FMI |
|
|
|--------------|-------------|
|
|
| `x86_64-unknown-linux-gnu` / `musl` | `linux64` |
|
|
| `aarch64-unknown-linux-gnu` / `musl` | `linuxaarch64` |
|
|
| `arm-unknown-linux-gnueabihf` | `linuxarm32` |
|
|
| `x86_64-pc-windows-msvc` / `gnu` | `win64` |
|
|
| `x86_64-apple-darwin` / `aarch64-apple-darwin` | `darwin64` |
|
|
|
|
> Cross-compiler Linux depuis Windows : installez les linkers croisés (ex. `aarch64-linux-gnu-gcc`) et configurez `[target.<triple>] linker = "..."` dans `~/.cargo/config.toml`. Le codegen du crate staged hérite de la config cargo de l'utilisateur.
|
|
|
|
## Contenu de l'archive `.fmu`
|
|
|
|
```
|
|
modelDescription.xml (déclare les entrées/sorties, le GUID, le modelIdentifier)
|
|
binaries/<platform>/entropyk_fmi.{so|dll|dylib}
|
|
resources/config.json (le modèle Entropyk, pour référence)
|
|
resources/fmu_io.json (la carte d'entrées/sorties)
|
|
```
|
|
|
|
## Carte d'entrées/sorties (`fmu_io.json`)
|
|
|
|
Déclare quelles variables le PLC peut écrire (entrées) et lire (sorties). Les `valueReference` sont attribués dans l'ordre : entrées d'abord (`0..n_inputs`), puis sorties (`n_inputs..`).
|
|
|
|
```json
|
|
{
|
|
"inputs": [
|
|
{ "name": "T_air_c", "component": "cond_air_in", "param": "t_dry_c", "kind": "input" },
|
|
{ "name": "m_air", "component": "cond_air_in", "param": "m_flow_kg_s", "kind": "input" }
|
|
],
|
|
"outputs": [
|
|
{ "name": "COP", "kind": "cop" },
|
|
{ "name": "Q_cool_kW", "kind": "q_cooling_kw" },
|
|
{ "name": "P_kW", "kind": "compressor_power_kw" },
|
|
{ "name": "P_evap_bar","kind": "pressure_bar", "edge": 3 }
|
|
]
|
|
}
|
|
```
|
|
|
|
`kind` pour les sorties : `cop`, `q_cooling_kw`, `q_heating_kw`, `compressor_power_kw`, `pressure_bar`, `enthalpy_kj_kg`, `mass_flow_kg_s`. Les trois derniers nécessitent `edge` (index d'arête).
|
|
|
|
## Mode dev (sans codegen)
|
|
|
|
Pour itérer sans recompiler le FMU à chaque changement de modèle, le runtime peut lire le modèle depuis des variables d'environnement au lieu de la version embarquée :
|
|
|
|
```bash
|
|
cargo build -p entropyk-fmi
|
|
export ENTROPYK_FMU_MODEL=crates/cli/examples/chiller_aircooled_r134a.json
|
|
export ENTROPYK_FMU_IO=bindings/fmi/examples/chiller_aircooled_io.json
|
|
# charger target/debug/entropyk_fmi.{so|dll} dans fmpy comme FMU Co-Sim
|
|
```
|
|
|
|
## Test rapide avec fmpy (Python)
|
|
|
|
```bash
|
|
uv pip install fmpy
|
|
uv run python -c "from fmpy import simulate_fmu; simulate_fmu('target/chiller.fmu', stop_time=1.0)"
|
|
```
|
|
|
|
## Limites actuelles (skeleton)
|
|
|
|
- **Pas de warm-start** : chaque `doStep` reconstruit le graphe `System` et relance un Newton à froid. Pour un cycle 100 ms c'est acceptable ; l'optimisation (réutiliser l'état précédent + le `System` construit) nécessite de scinder `execute_simulation` en `build_system` + `solve_warm` — TODO.
|
|
- **Backend fluide** : le FMU embarque actuellement le backend déclaré dans le JSON (CoolProp inclus). Pour un petit MCU, préférer le backend **tabulaire** (tables précalculées hors-ligne) ; vérifier la couverture de la plage de fonctionnement.
|
|
- **Itérations bornées** : à configurer via `solver.max_iterations` dans le modèle pour garantir un budget temps réel par pas.
|