5.0 KiB
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
cdylibet exporte l'ABI C standardfmi2*. - 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
fmi2DoStepre-resout le cycle stationnaire aux entrées courantes (co-simulation quasi-stationnaire).
Générer un FMU
# 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 :
# 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..).
{
"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 :
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)
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
doStepreconstruit le grapheSystemet relance un Newton à froid. Pour un cycle 100 ms c'est acceptable ; l'optimisation (réutiliser l'état précédent + leSystemconstruit) nécessite de scinderexecute_simulationenbuild_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_iterationsdans le modèle pour garantir un budget temps réel par pas.