Capture uncommitted solver robustness work (regularization, domain errors, linear solver lifecycle, tube DP/MSH), web workbench updates, and synced BMAD skills across IDE agent folders before starting BPHX pressure-drop. Co-authored-by: Cursor <cursoragent@cursor.com>
14 KiB
Entropyk — Simulation Capabilities & Modelica Comparison / Capacités de simulation & comparaison Modelica
Bilingual document (English first, French below) / Document bilingue (anglais d'abord, français ensuite).
This analysis is code-grounded: every claim is traceable to the Rust sources in
crates/. Cette analyse est fondée sur le code : chaque affirmation est traçable dans les sources Rust decrates/.
EN — What Entropyk can simulate
1. Nature of the tool
Entropyk is a steady-state, equation-based thermodynamic-cycle simulator for refrigeration, heat-pump and HVAC systems. It is not a general-purpose DAE engine (like OpenModelica); it is a domain-specific algebraic solver built around a component graph.
- Solving paradigm: each component contributes residual equations
r(x) = 0and an analytic Jacobian. The global systemF(x) = 0is solved with Newton–Raphson, Picard (sequential substitution), a Newton-homotopy continuation, and aFallbackSolverthat chains them. (crates/solver/src/strategies/) - State vector: per flow edge
(ṁ, P, h); series branches share a single mass-flow unknown after a topology presolve (|B| + 2·|E|layout). (crates/solver/src/system.rs) - Fluid properties:
CoolPropBackend(production),TestBackend(mock/ideal), plusTabularBackendandIncompressibleBackendin the library. (crates/fluids/)
2. System-level capabilities
| Capability | Status | Evidence |
|---|---|---|
| Coupled algebraic solving with analytic Jacobian | ✅ | Component::jacobian_entries, System::assemble_jacobian |
| Explicit degrees-of-freedom balancing | ✅ | System::validate_inverse_control_dof, mass-flow presolve |
| Emergent pressures (SST/SDT float from HX↔secondary balance) | ✅ | Condenser::with_emergent_pressure, Evaporator superheat_regulated |
| Multi-circuit networks (up to 5) | ✅ | CircuitId 0..4, per-circuit flow edges |
Inter-circuit thermal coupling (thermal_couplings) |
✅ physical mode | Set hot_component (duty provider, e.g. an ε-NTU Condenser) + cold_component (a ThermalLoad receiver): the coupling owns one unknown Q closed against the hot component's measured duty (Q = η·duty_hot) and injects Q into the cold loop's energy balance — First Law closes across circuits (chiller_r410a_coupled_water_loop.json). Entries without both fields are inert (Q pinned to 0, CLI warns). |
| Secondary-stream heat exchange (air/water, ε-NTU) | ✅ | Condenser/Evaporator secondary_inlet_temp_c + secondary_mass_flow_kg_s + secondary_cp_j_per_kgk; emergent capacity/COP (e.g. chiller_r410a_full_physics.json → COP≈4.98, First Law closes) |
| Steady-state supervisory control, co-solved | ✅ | SaturatedController (offset-free PI, anti-windup) |
| Override / selector priority (min/max) | ✅ | override_network.rs, smoothed softMin/softMax, activation continuation |
| Inverse / one-shot calibration | ✅ | inverse/calibration.rs, Z-factors z_flow, z_dp, z_ua, z_power, z_etav |
| Free actuators (e.g. EXV orifice opening) | ✅ | System free-actuator DoF (+1 unknown / +1 component eq) |
| Reusable parameterized subsystems (flattened) | ✅ | CLI subsystems/instances/connections → flatten_instances() |
| Hierarchical composition in Rust | ⚠️ partial | MacroComponent couples P/h at ports; ṁ continuity not yet coupled |
| Normative seasonal rating (IPLV/ESEER/SCOP/SEER) | ✅ | CLI rate, scop, seer (re-solves the cycle per load point/bin) |
| ON/OFF/BYPASS staging | ✅ (pre-solve) | OperationalState, circuits[].enabled |
| BOLT-style inline spec/probe nodes | ✅ | Anchor (= BOLT BoundaryNode.Refrigerant.Node): probe mode (DoF-neutral) or one imposed spec — signed superheat_k (dTsh, <0 = subcooling), quality, t_c/t_k, p_bar (docs/components/anchor-heat-source.md) |
| Inline heat injection (fixed or coupling-linked) | ✅ | HeatSource (= BOLT BoundaryNode.Heat.Source): q_w fixed duty + optional coupling-driven Q (motor-cooling pattern), exact Jacobian, excluded from COP aggregation (chiller_r410a_bolt_nodes.json) |
| Boundary-imposed loop flow | ✅ | BrineSource/BrineSink m_flow_kg_s (= BOLT Vd_fixed=true) |
3. Can we build models as complex as Modelica?
Yes for the targeted domain, with caveats. Entropyk reproduces the ideas that make Modelica HVAC libraries powerful:
- equation-based components with a coupled solve,
- reusable parameterized subsystems,
- co-solved supervisory control (setpoint tracking + min/max override priority, exactly the "BOLT"-style chiller control referenced in the code),
- inverse calibration and normative rating.
You can assemble multi-circuit chillers/heat-pumps with emergent pressures, secondary-fluid–coupled heat exchangers, economizer screw compressors, liquid injection, head-pressure control, free-cooling, and a supervisory control tree — comparable in structural complexity to a Modelica chiller model.
4. Gaps vs Modelica (be precise)
- Steady-state only — no time integration, no
der(x), no dynamic states (thermal masses, sensor lags). Everything targetsF(x)=0. - No event handling — no zero-crossing / reinit;
ModeSwitch(hysteresis, min-runtime) lives outside the Newton solve and is time-based. - Causal edge connectors — state is carried on edges/branches as
(ṁ,P,h); continuity is enforced by component residuals referencing state indices (a TESPy-like pattern), not Modelica acausal connectors with shared variables and language-level connection equations. - Hierarchy is mostly compile-time / flattened — the CLI flattens subsystems before solving; nested subsystems inside the solver require Rust
MacroComponent, whose port ṁ-continuity is still incomplete. thermal_couplingstransfers a measured duty, not a UA·ΔT law — the physical mode closesQ = η·duty_hot(the hot component's ε-NTU duty) into aThermalLoadreceiver; theuafield is not used as a coupling conductance. For a genuinely two-sided UA·LMTD interface exchanger, use a two-sidedHeatExchanger/BPHX or a secondary stream instead. Legacy entries withouthot_component/cold_componentare inert (Q pinned to 0, CLI warns).- CLI fluids limited to CoolProp/Test (Tabular/Incompressible exist in the lib but are not wired to the CLI).
- No user-authored arbitrary equations — new behaviour requires implementing the
Componenttrait in Rust.
5. One-sentence verdict
Entropyk is closer to a TESPy/BOLT-style steady-state cycle solver with co-solved algebraic supervisory control and inverse calibration than to a general Modelica DAE engine: excellent structural parity for HVAC/refrigeration cycles, but without transients, events, or acausal language-level connectors.
FR — Ce qu'Entropyk permet de simuler
1. Nature de l'outil
Entropyk est un simulateur de cycles thermodynamiques en régime permanent (steady-state), basé sur les équations, pour la réfrigération, les pompes à chaleur et le CVC. Ce n'est pas un moteur DAE généraliste (comme OpenModelica) : c'est un solveur algébrique dédié au domaine, organisé autour d'un graphe de composants.
- Paradigme de résolution : chaque composant fournit des équations résiduelles
r(x) = 0et un Jacobien analytique. Le système globalF(x) = 0est résolu par Newton–Raphson, Picard (substitution séquentielle), une continuation par homotopie de Newton, et unFallbackSolverqui les enchaîne. (crates/solver/src/strategies/) - Vecteur d'état : par arête de flux
(ṁ, P, h); les branches en série partagent un seul inconnu de débit après un presolve topologique (layout|B| + 2·|E|). (crates/solver/src/system.rs) - Propriétés fluides :
CoolPropBackend(production),TestBackend(mock/gaz idéal), plusTabularBackendetIncompressibleBackenddans la bibliothèque. (crates/fluids/)
2. Capacités au niveau système
| Capacité | État | Preuve (code) |
|---|---|---|
| Résolution algébrique couplée + Jacobien analytique | ✅ | Component::jacobian_entries, System::assemble_jacobian |
| Équilibrage explicite des degrés de liberté (DoF) | ✅ | System::validate_inverse_control_dof, presolve débit |
| Pressions émergentes (SST/SDT flottent selon l'équilibre HX↔secondaire) | ✅ | Condenser::with_emergent_pressure, Evaporator superheat_regulated |
| Réseaux multi-circuits (jusqu'à 5) | ✅ | CircuitId 0..4, arêtes de flux par circuit |
Couplage thermique inter-circuits (thermal_couplings) |
✅ mode physique | Renseigner hot_component (fournisseur de puissance, ex. Condenser ε-NTU) + cold_component (récepteur ThermalLoad) : le couplage porte un inconnu Q fermé sur la puissance mesurée du composant chaud (Q = η·duty_hot) et injecte Q dans le bilan d'énergie de la boucle froide — le 1er principe ferme entre circuits (chiller_r410a_coupled_water_loop.json). Les entrées sans ces deux champs sont inertes (Q épinglé à 0, la CLI avertit). |
| Échange par flux secondaire (air/eau, ε-NTU) | ✅ | Condenser/Evaporator secondary_inlet_temp_c + secondary_mass_flow_kg_s + secondary_cp_j_per_kgk ; capacité/COP émergents (ex. chiller_r410a_full_physics.json → COP≈4.98, 1er principe fermé) |
| Contrôle supervisoire steady-state, co-résolu | ✅ | SaturatedController (PI offset-free, anti-windup) |
| Priorité par override / sélecteur (min/max) | ✅ | override_network.rs, softMin/softMax lissés, continuation d'activation |
| Calibration inverse / one-shot | ✅ | inverse/calibration.rs, facteurs Z z_flow, z_dp, z_ua, z_power, z_etav |
| Actuateurs libres (ex. ouverture orifice EXV) | ✅ | DoF free-actuator (+1 inconnu / +1 éq. composant) |
| Sous-systèmes paramétrés réutilisables (aplatis) | ✅ | CLI subsystems/instances/connections → flatten_instances() |
| Composition hiérarchique en Rust | ⚠️ partiel | MacroComponent couple P/h aux ports ; continuité ṁ pas encore couplée |
| Rating saisonnier normatif (IPLV/ESEER/SCOP/SEER) | ✅ | CLI rate, scop, seer (re-résout le cycle par point/bin) |
| Staging ON/OFF/BYPASS | ✅ (pré-solve) | OperationalState, circuits[].enabled |
| Nœuds spec/sonde inline style BOLT | ✅ | Anchor (= BoundaryNode.Refrigerant.Node de BOLT) : mode sonde (neutre en DoF) ou une spec imposée — superheat_k signé (dTsh, <0 = sous-refroidissement), quality, t_c/t_k, p_bar (docs/components/anchor-heat-source.md) |
| Injection de chaleur inline (fixe ou liée à un couplage) | ✅ | HeatSource (= BoundaryNode.Heat.Source de BOLT) : puissance fixe q_w + Q optionnel piloté par couplage (pattern refroidissement moteur), Jacobien exact, exclu de l'agrégation COP (chiller_r410a_bolt_nodes.json) |
| Débit de boucle imposé à la frontière | ✅ | BrineSource/BrineSink m_flow_kg_s (= Vd_fixed=true de BOLT) |
3. Peut-on bâtir des modèles aussi complexes que Modelica ?
Oui pour le domaine visé, avec des réserves. Entropyk reproduit les idées qui font la puissance des bibliothèques HVAC Modelica :
- composants basés équations, résolus de façon couplée ;
- sous-systèmes paramétrés réutilisables ;
- contrôle supervisoire co-résolu (suivi de consigne + priorité min/max, exactement le style de contrôle chiller « BOLT » référencé dans le code) ;
- calibration inverse et rating normatif.
On peut assembler des groupes froids / PAC multi-circuits avec pressions émergentes, échangeurs couplés au fluide secondaire, compresseurs à vis avec économiseur, injection liquide, contrôle de pression de refoulement, free-cooling et un arbre de contrôle supervisoire — d'une complexité structurelle comparable à un modèle chiller Modelica.
4. Écarts vs Modelica (précis)
- Régime permanent uniquement — pas d'intégration temporelle, pas de
der(x), pas d'états dynamiques (masses thermiques, retards capteurs). Tout viseF(x)=0. - Pas de gestion d'événements — pas de zero-crossing / reinit ;
ModeSwitch(hystérésis, durée min) est hors du Newton et basé sur le temps. - Connecteurs causaux par arête — l'état est porté par les arêtes/branches en
(ṁ,P,h); la continuité est imposée par des résidus composants référençant des indices d'état (motif type TESPy), pas des connecteurs acausaux Modelica à variables partagées. - Hiérarchie surtout compile-time / aplatie — la CLI aplatit les sous-systèmes avant résolution ; l'imbrication dans le solveur passe par
MacroComponent(Rust), dont la continuité ṁ aux ports est incomplète. thermal_couplingstransfère une puissance mesurée, pas une loi UA·ΔT — le mode physique fermeQ = η·duty_hot(la puissance ε-NTU du composant chaud) dans un récepteurThermalLoad; le champuane sert pas de conductance de couplage. Pour un échangeur d'interface UA·LMTD réellement à deux flux, utiliser unHeatExchanger/BPHX à deux flux ou un flux secondaire. Les entrées legacy sanshot_component/cold_componentsont inertes (Q épinglé à 0, la CLI avertit).- Fluides CLI limités à CoolProp/Test (Tabular/Incompressible existent dans la lib mais ne sont pas branchés à la CLI).
- Pas d'équations utilisateur arbitraires — tout nouveau comportement nécessite d'implémenter le trait
Componenten Rust.
5. Verdict en une phrase
Entropyk se rapproche d'un solveur de cycles steady-state type TESPy/BOLT avec contrôle supervisoire algébrique co-résolu et calibration inverse, plutôt que d'un moteur DAE Modelica généraliste : excellente parité structurelle pour les cycles CVC/réfrigération, mais sans transitoire, sans événements, ni connecteurs acausaux au niveau langage.
Component catalog / Catalogue des composants
See per-component bilingual documentation in docs/components/.
Voir la documentation bilingue par composant dans docs/components/.