40 KiB
Raw Blame History

stepsCompleted inputDocuments
step-01-validate-prerequisites
step-02-design-epics
step-03-create-stories
/Users/sepehr/dev/Entropyk/_bmad-output/planning-artifacts/prd.md
/Users/sepehr/dev/Entropyk/_bmad-output/planning-artifacts/architecture.md

Entropyk - Epic Breakdown

Overview

This document provides the complete epic and story breakdown for Entropyk, decomposing the requirements from the PRD and Architecture requirements into implementable stories.

Requirements Inventory

Functional Requirements

FR1: The system can model a Compressor according to AHRI 540 standard with manufacturer coefficients

FR2: The system can model a Condenser with heat transfer calculation

FR3: The system can model an Expansion Valve (isenthalpic expansion)

FR4: The system can model an Evaporator with phase change

FR5: The system can model an Economizer (internal heat exchanger) with Bypass mode

FR6: Each component can be in OperationalState (On, Off, Bypass)

FR7: In Off mode, an active component contributes zero mass flow to the system

FR8: In Bypass mode, a component behaves as an adiabatic pipe (P_in = P_out, h_in = h_out)

FR9: User can define a Machine containing N independent fluid circuits

FR10: User can connect components via Ports (inlet/outlet)

FR11: System supports connections between circuits (thermal coupling)

FR12: System can solve N circuits simultaneously or sequentially

FR13: System mathematically handles zero-flow branches without division by zero

FR14: System can solve equations using Newton-Raphson method

FR15: System can solve equations using Sequential Substitution (Picard) method

FR16: Solver automatically switches to Sequential Substitution if Newton-Raphson diverges

FR17: Solver respects configurable time budget (timeout)

FR18: On timeout, solver returns best known state with NonConverged status

FR19: Solver can freeze Jacobian calculation to accelerate (Jacobian Freezing)

FR20: Convergence criterion checks Delta Pressure < 1 Pa (1e-5 bar)

FR21: For multi-circuits, global convergence is achieved when ALL circuits converge

FR22: User can define output constraints (e.g., Superheat = 5K)

FR23: System calculates necessary inputs (e.g., valve opening) respecting Bounded Constraints (0.0 ≤ Valve ≤ 1.0). If solution is out of bounds, solver returns "Saturation" or "ControlLimitReached" error

FR24: Inverse Control is solved simultaneously with cycle equations (One-Shot)

FR25: System can load fluid properties via CoolProp

FR26: System supports Tabular Interpolation tables for 100x performance

FR27: System handles pure fluids and mixtures (R32/R125, R454B)

FR28: System handles Temperature Glide for zeotropic mixtures

FR29: System uses automatic damping near critical point (CO2 R744)

FR30: Native Rust API with types and ownership safety

FR31: Python bindings via PyO3 with tespy-compatible API

FR32: C FFI for integration with external systems (PLC, LabView)

FR33: WebAssembly compilation support for web interfaces

FR34: CLI for batch simulation execution

FR35: System automatically checks mass balance (Σ ṁ_in - Σ ṁ_out < 1e-9 kg/s)

FR36: System automatically checks energy balance (Σ Q̇ + Ẇ - Σ (ṁ · h) < 1e-6 kW)

FR37: Each result contains traceability metadata (solver version, fluid version, SHA-256 input hash)

FR38: Debug Verbose mode to display residuals and convergence history

FR39: Error handling via Result<T, ThermoError> (Zero-Panic Policy)

FR40: System handles Incompressible Fluids (Water, Glycol, Humid Air simplified) via lightweight models (constant Cp or polynomial) for heat sources and sinks

FR41: Complete graph (Topology + Parameters + Fluid State) is serializable/deserializable to JSON (or TOML)

FR42: System includes Automatic Initialization Heuristic (Smart Guesser) proposing coherent initial pressure values based on source/sink temperatures

FR43: Components support calibration parameters (Calib: f_m, f_dp, f_ua, f_power, f_etav) to match simulation to real machine test data

FR44: System can validate results against ASHRAE 140 / BESTEST test cases (post-MVP)

FR45: System supports inverse calibration (parameter estimation from test bench data)

FR46: Explicit Air Coil components (EvaporatorCoil, CondenserCoil) for finned air heat exchangers (post-MVP)

FR47: Each refrigeration component natively exposes a complete thermodynamic state (Pressure, Temperature, T_sat, Quality, Superheat, Subcooling, Mass flow, Reynolds, Enthalpy, Entropy) easily accessible without complex recalculations.

NonFunctional Requirements

NFR1: Steady State convergence time < 1 second for standard cycle in Cold Start

NFR2: Simple cycle (Single-stage) solved in < 100 ms

NFR3: Complex cycle (Multi-circuits) solved in < 1 second

NFR4: No dynamic allocation in solver loop (pre-calculated allocation only)

NFR5: Guaranteed determinism: same inputs → same results within 1e-9 precision on all platforms (x86, ARM, WASM)

NFR6: HIL latency < 20 ms for real-time integration with PLC

NFR7: Zero-Panic Policy: no crash even with invalid inputs or impossible states

NFR8: Memory Safety guaranteed by Rust ownership system (no memory leaks, no use-after-free)

NFR9: Capability to run 48h+ without interruption or degradation (HIL/Embedded)

NFR10: Graceful error handling: timeout, non-convergence, saturation return explicit Result<T, Error>

NFR11: CoolProp 6.4+ compatibility for fluid properties

NFR12: Stable C FFI: auto-generated .h headers via cbindgen, C99/C++ compatible

NFR13: Deterministic WebAssembly: same behavior as native, no non-determinism sources

NFR14: Python bindings PyO3: tespy-compatible API for facilitated migration

NFR15: 100% documentation of public APIs (rustdoc)

NFR16: Automated CI/CD: tests, benchmarks, memory checks (Valgrind + Miri)

NFR17: Zero tolerance warnings: cargo clippy -- -D warnings

Additional Requirements

Architecture Requirements:

  • Workspace-based multi-crate architecture with 4 crates (core, solver, components, fluids) and 3 bindings (python, c, wasm)
  • Trait-based static polymorphism with enum dispatch for zero-cost abstraction
  • NewType pattern for all physical quantities (Pressure, Temperature, Enthalpy, MassFlow) - never bare f64 in public APIs
  • Type-State pattern for connection safety at compile-time
  • Pre-allocated buffers only - no heap allocation in hot paths
  • #![deny(warnings)] in lib.rs for all crates
  • KaTeX configuration in .cargo/config.toml for mathematical documentation
  • tracing for structured logging (never println!)
  • thiserror for error handling with ThermoError enum
  • approx crate for floating-point assertions with explicit tolerances
  • Sys-crate pattern for CoolProp C++ integration
  • cbindgen for C header generation
  • Miri validation in CI for undefined behavior detection
  • Mass balance tolerance: 1e-9 kg/s
  • Energy balance tolerance: 1e-6 kW
  • Convergence pressure tolerance: 1 Pa

Standards Compliance:

  • AHRI 540 standard implementation for compressor modeling with manufacturer coefficients (Bitzer, Copeland, Danfoss)
  • NIST REFPROP as gold standard for fluid properties
  • CoolProp as open-source reference
  • Tabular interpolation achieving < 0.01% deviation from NIST while being 100x faster than direct EOS calls

Domain-Specific Requirements:

  • Critical Point handling (CO2 R744) with automatic damping to prevent NaN in partial derivatives
  • Temperature Glide handling for zeotropic mixtures (R454B, R32/R125) integrating Bubble Point → Dew Point without approximation
  • Traçability: Each SimulationResult contains solver_version, fluid_backend version, input_hash (SHA-256)
  • Smart initialization heuristic for initial pressure guesses based on source/sink temperatures

CI/CD Requirements:

  • cargo test: Unit tests
  • cargo bench: Performance regression (failure if > 5% degradation)
  • valgrind: Memory leaks (FFI)
  • cargo clippy -- -D warnings: Zero tolerance style
  • miri test: Undefined behavior detection
  • 100% public documentation coverage
  • Compiled and tested examples in CI

Packaging & Distribution:

  • Rust: crates.io
  • Python: pip install rust-thermo-cycle (Wheels PyPI, manylinux)
  • C/C++: Headers + dynamic libraries
  • Docker: Image rust-thermo-lab (JupyterLab + Rust kernel + CoolProp)

FR Coverage Map

FR Epic Description
FR1 Epic 1 Compressor AHRI 540 modeling
FR2 Epic 1 Condenser heat transfer
FR3 Epic 1 Expansion valve isenthalpic
FR4 Epic 1 Evaporator phase change
FR5 Epic 1 Economizer with bypass
FR6 Epic 1 Component states ON/OFF/BYPASS
FR7 Epic 1 Zero mass flow in OFF mode
FR8 Epic 1 Adiabatic pipe in BYPASS mode
FR9 Epic 3 Multi-circuit machine definition
FR10 Epic 3 Component connection via Ports
FR11 Epic 3 Thermal coupling between circuits
FR12 Epic 3 Simultaneous/sequential circuit solving
FR13 Epic 3 Zero-flow branch handling
FR14 Epic 4 Newton-Raphson solver
FR15 Epic 4 Sequential Substitution solver
FR16 Epic 4 Auto-fallback solver switching
FR17 Epic 4 Configurable timeout
FR18 Epic 4 Best state on timeout
FR19 Epic 4 Jacobian freezing
FR20 Epic 4 Delta Pressure < 1 Pa convergence
FR21 Epic 4 Global multi-circuit convergence
FR22 Epic 5 Output constraints definition
FR23 Epic 5 Bounded input calculation
FR24 Epic 5 One-shot inverse control
FR25 Epic 2 CoolProp integration
FR26 Epic 2 Tabular interpolation tables
FR27 Epic 2 Pure fluids and mixtures support
FR28 Epic 2 Temperature glide handling
FR29 Epic 2 Critical point damping
FR30 Epic 6 Native Rust API
FR31 Epic 6 Python PyO3 bindings
FR32 Epic 6 C FFI bindings
FR33 Epic 6 WebAssembly support
FR34 Epic 6 CLI for batch execution
FR35 Epic 7 Mass balance validation
FR36 Epic 7 Energy balance validation
FR37 Epic 7 Traceability metadata
FR38 Epic 7 Debug verbose mode
FR39 Epic 7 Zero-panic error handling
FR40 Epic 2 Incompressible fluids support
FR41 Epic 7 JSON serialization
FR42 Epic 4 Smart initialization heuristic
FR43 Epic 7 Component calibration parameters (Calib)
FR44 Epic 7 ASHRAE 140 / BESTEST validation
FR45 Epic 7 Inverse calibration (parameter estimation)
FR46 Epic 1 Air Coils (EvaporatorCoil, CondenserCoil)
FR47 Epic 2 Rich Thermodynamic State Abstraction
FR48 Epic 3 Hierarchical Subsystems (MacroComponents)

Epic List

Epic 1: Extensible Component Framework

Goal: Create the foundation that allows adding any component (VFD, Battery, Pump, Pipe) by simply implementing a Rust Trait, without touching the calculation engine.

Innovation: Trait-based "Lego" architecture to add Compressors, Pumps, VFDs, Pipes, etc.

FRs covered: FR1, FR2, FR3, FR4, FR5, FR6, FR7, FR8, FR46


Epic 2: Fluid Properties Backend

Goal: Provide precise thermodynamic properties via CoolProp, tabular tables, mixture handling, and critical point management.

Innovation: 100x performance with tabular tables, automatic CO2 damping.

FRs covered: FR25, FR26, FR27, FR28, FR29, FR40, FR47


Epic 3: System Topology (Graph)

Goal: Enable component assembly via Ports and manage multi-circuits with thermal coupling, and support hierarchical subsystems.

Innovation: Multi-fluid directed graph in a single model, with natively supported hierarchical sub-blocks.

FRs covered: FR9, FR10, FR11, FR12, FR13, FR48


Epic 4: Intelligent Solver Engine

Goal: Solve any system with < 1s guarantee, Newton-Raphson ↔ Sequential Substitution fallback.

Innovation: Solver-agnostic with intelligent fallback - guaranteed convergence.

FRs covered: FR14, FR15, FR16, FR17, FR18, FR19, FR20, FR21, FR42


Epic 5: Inverse Control & Optimization

Goal: Transform component parameters (VFD speed, Valve position) into simultaneously solved unknowns.

Innovation: Native Inverse Control via Residual Embedding - "One-Shot".

FRs covered: FR22, FR23, FR24


Epic 6: Multi-Platform APIs

Goal: Distribute the library via Python (PyO3), WebAssembly, C FFI, and CLI.

Innovation: Multi-target without code duplication (Rust → Python/WASM/C).

FRs covered: FR30, FR31, FR32, FR33, FR34


Epic 7: Validation & Persistence

Goal: Guarantee trust via mass/energy balances, SHA-256 traceability, and JSON persistence.

Innovation: Complete traceability and scientific reproducibility.

FRs covered: FR35, FR36, FR37, FR38, FR39, FR41, FR43, FR44, FR45


Epic 8: Component-Fluid Integration

Goal: Integrate real thermodynamic fluid properties directly into component Residual calculation models.

Innovation: True physical interaction between solver mathematics and state equations.

FRs covered: FR47


Epic 1: Extensible Component Framework

Story 1.1: Component Trait Definition

As a library developer, I want to define a generic Component trait with methods for residuals, ports, and state management, So that future components can be implemented by simply implementing this trait.

Acceptance Criteria:

Given a new component struct When it implements the Component trait Then it must provide compute_residuals(), get_ports(), and get_state() methods And the trait must be object-safe for dynamic dispatch


Story 1.2: Physical Types (NewType Pattern)

As a simulation user, I want type-safe physical quantities (Pressure, Temperature, Enthalpy, MassFlow), So that I cannot accidentally mix units.

Acceptance Criteria:

Given a function accepting Pressure and Temperature When I try to pass Temperature where Pressure is expected Then the code must not compile (compile-time safety) And conversions must be explicit (e.g., pressure_bar.to_pascals())


Story 1.3: Port and Connection System

As a system modeler, I want to define inlet/outlet ports for components and connect them bidirectionally, So that I can build fluid circuit topologies.

Acceptance Criteria:

Given two components with compatible ports When I call connect(port_a, port_b) Then the connection is established with state validation And attempting to connect incompatible ports fails at compile-time


Story 1.4: Compressor Component (AHRI 540)

As a thermodynamic engineer, I want to model a compressor using AHRI 540 standard coefficients, So that I can simulate real compressor behavior with manufacturer data.

Acceptance Criteria:

Given a compressor with 10 AHRI 540 coefficients When I compute residuals for a given operating point Then the power consumption and mass flow are calculated per AHRI 540 equations And the result matches certified AHRI test data within 1%


Story 1.5: Generic Heat Exchanger Framework

As a thermal systems engineer, I want a pluggable heat exchanger framework supporting multiple calculation models (Pinch point, LMTD, ε-NTU), So that I can add new exchanger types without modifying the solver.

Acceptance Criteria:

Given a heat exchanger component When I plug in a calculation model (Pinch, LMTD, or ε-NTU) Then the residuals are computed using the selected model And new models can be added by implementing a HeatTransferModel trait And Condenser, Evaporator, and Economizer are implemented as specific configurations


Story 1.6: Expansion Valve Component

As a control engineer, I want to model an expansion valve with isenthalpic expansion, So that I can simulate pressure reduction in the refrigeration cycle.

Acceptance Criteria:

Given an expansion valve with inlet subcooled liquid at high pressure When I compute residuals Then the outlet is two-phase or saturated liquid at lower pressure And enthalpy is conserved (h_in = h_out)


Story 1.7: Component State Machine

As a simulation user, I want components to support ON, OFF, and BYPASS states, So that I can simulate system configurations and failures.

Acceptance Criteria:

Given a component in ON state When I switch it to OFF Then it contributes zero mass flow to the system And when in BYPASS, it behaves as an adiabatic pipe (P_in = P_out, h_in = h_out)


Story 1.8: Auxiliary & Transport Components

As a system integrator, I want to model Pumps, VFDs, and Pipes, So that I can simulate complete HVAC systems.

Acceptance Criteria:

Given a Pump with specified hydraulic efficiency When I compute residuals Then power consumption and pressure rise match the pump curve And a VFD can modify Pump or Compressor speed via affinity laws And a Pipe calculates pressure drop via Darcy-Weisbach


Epic 2: Fluid Properties Backend

Story 2.1: Fluid Backend Trait Abstraction

As a library developer, I want to define a FluidBackend trait, So that the solver can switch between CoolProp, tabular, and mock backends.

Acceptance Criteria:

Given a fluid property query When I call backend.property(fluid, property, state) Then it returns correct values regardless of backend implementation And CoolPropBackend, TabularBackend, and TestBackend all implement the trait


Story 2.2: CoolProp Integration (sys-crate)

As a simulation user, I want CoolProp as the primary backend, So that I get NIST-quality thermodynamic data.

Acceptance Criteria:

Given a refrigerant and thermodynamic state When I query via CoolPropBackend Then results match CoolProp 6.4+ within machine precision And C++ CoolProp is statically linked via sys-crate


Story 2.3: Tabular Interpolation Backend

As a performance-critical user, I want pre-computed NIST tables with fast interpolation, So that queries are 100x faster than direct EOS.

Acceptance Criteria:

Given a tabular data file for a fluid When I query via TabularBackend Then results deviate < 0.01% from NIST REFPROP And query time is < 1μs


Story 2.4: LRU Cache for Fluid Properties

As a solver developer, I want lock-free or thread-local caching, So that redundant calculations are avoided without mutex contention.

Acceptance Criteria:

Given repeated property queries When cache is enabled Then Thread-Local or lock-free (dashmap) caching is used And no mutex contention under high parallelism (Rayon) And cache invalidates on state changes


Story 2.5: Mixture and Temperature Glide Support

As a refrigeration engineer, I want robust (P, h) and (P, x) inputs for zeotropic mixtures, So that the solver handles temperature glide reliably.

Acceptance Criteria:

Given a zeotropic mixture at constant pressure When calculating evaporation Then temperature glide from bubble to dew point is correct And backend supports (P, h) and (P, x) inputs robustly And (P, h) is preferred over (P, T) for two-phase mixtures


Story 2.6: Critical Point Damping (CO2 R744)

As a CO2 systems designer, I want smooth, differentiable damping near critical point, So that Newton-Raphson converges without discontinuities.

Acceptance Criteria:

Given CO2 near critical point (Tc=304.13K, Pc=7.3773 MPa) When querying within 5% of critical point Then damping is applied to partial derivatives And no NaN values And damping function is C1-continuous (sigmoid transition)


Story 2.7: Incompressible Fluids Support

As a HVAC engineer, I want water, glycol, and moist air as incompressible fluids, So that heat sources/sinks are fast to compute.

Acceptance Criteria:

Given an incompressible fluid When querying density, Cp, or enthalpy Then lightweight polynomial models are used And results match references within 0.1% And computation is 1000x faster than compressible EOS


Story 2.8: Rich Thermodynamic State Abstraction

As a system engineer, I want components to expose a comprehensive ThermoState structure (P, T, T_sat, Quality, tsh, Reynolds, Enthalpy, Entropy, etc.), So that I don't have to manually calculate these from raw state arrays after solver convergence.

Acceptance Criteria:

Given a converged component (e.g., Compressor or Condenser) When I call component.outlet_thermo_state() Then it returns a ThermoState object And the object contains dynamically resolved saturated temperature, vapor quality, superheat, and phase And FluidBackend natively supports resolving this full snapshot in one trait call full_state(p, h)


Epic 3: System Topology (Graph)

Story 3.1: System Graph Structure

As a system modeler, I want edges to index the solver's state vector, So that P and h unknowns assemble into the Jacobian.

Acceptance Criteria:

Given components with ports When adding to System graph Then edges serve as indices into solver's state vector And each flow edge represents P and h unknowns And solver traverses graph to assemble Jacobian And cycles are detected and validated


Story 3.2: Port Compatibility Validation

As a system designer, I want port connection validation at build time, So that incompatible connections are caught early.

Acceptance Criteria:

Given two ports with incompatible fluids When attempting to connect Then connection fails with clear error And valid connections are accepted And pressure/enthalpy continuity is enforced


Story 3.3: Multi-Circuit Machine Definition

As a R&D engineer (Marie), I want machines with N independent circuits, So that I simulate complex heat pumps.

Acceptance Criteria:

Given a machine with 2+ circuits When defining topology Then each circuit is tracked independently And circuits can be solved simultaneously or sequentially And supports up to N=5 circuits


Story 3.4: Thermal Coupling Between Circuits

As a systems engineer, I want thermal coupling with circular dependency detection, So that solver knows to solve simultaneously vs sequentially.

Acceptance Criteria:

Given two circuits with a heat exchanger When defining thermal coupling Then heat transfer equations link circuits And energy is conserved (Q_hot = -Q_cold) And circular dependencies force simultaneous solving And coupling represented as additional residuals


Story 3.5: Zero-Flow Branch Handling

As a simulation user, I want zero-flow handling with regularization, So that OFF components don't cause numerical instabilities.

Acceptance Criteria:

Given a branch with mass flow = 0 When computing residuals Then no division-by-zero And regularization applied (ε minimum in divisions) And auto-switch to pressure continuity when OFF And Jacobian remains well-conditioned


Story 3.6: Hierarchical Subsystems (MacroComponents)

As a system designer, I want to encapsulate a complete system (e.g., a Chiller with compressor, condenser, valve, evaporator) into a single reusable block, So that I can compose larger models (like buildings or parallel chiller plants) using these blocks, just like in Modelica.

Acceptance Criteria:

Given a fully defined System with internal components and connections When I wrap it in a MacroComponent Then I can expose specific internal ports (e.g., Evaporator Water In/Out, Condenser Water In/Out) as the MacroComponent's external ports And this MacroComponent implements the Component trait And I can add it to a higher-level System just like any regular component And the global solver correctly flattens or delegates the residual and jacobian computations down to the nested components.


Epic 4: Intelligent Solver Engine

Story 4.1: Solver Trait Abstraction

As a numerical developer, I want a generic Solver trait, So that strategies are interchangeable.

Acceptance Criteria:

Given a system of equations When instantiating solver strategies Then all implement common Solver trait And provides solve() and with_timeout() methods And zero-cost abstraction via enum dispatch


Story 4.2: Newton-Raphson Implementation

As a simulation engineer, I want Newton-Raphson with analytical Jacobian support, So that HIL performance is optimized.

Acceptance Criteria:

Given a system with residuals When running Newton-Raphson Then quadratic convergence near solution And line search prevents overshooting And supports both numerical and analytical Jacobian And components provide analytical Jacobian entries


Story 4.3: Sequential Substitution (Picard) Implementation

As a fallback solver user, I want Sequential Substitution for robust convergence, So that when Newton diverges, I have a stable alternative.

Acceptance Criteria:

Given a system where Newton diverges When using Sequential Substitution Then it converges reliably And variables updated sequentially And relaxation factors configurable


Story 4.4: Intelligent Fallback Strategy

As a simulation user, I want automatic fallback with smart return conditions, So that convergence is guaranteed without solver oscillation.

Acceptance Criteria:

Given Newton-Raphson diverging When divergence detected (> 3 increasing residuals) Then auto-switch to Sequential Substitution And return to Newton ONLY when convergence radius reached And prevent oscillation by requiring stable Picard first


Story 4.5: Time-Budgeted Solving

As a HIL engineer (Sarah), I want strict timeout with graceful degradation, So that real-time constraints are never violated.

Acceptance Criteria:

Given solver with timeout = 1000ms When time budget exceeded Then solver stops immediately And returns best state with ComputationStatus::Timeout And for HIL, returns previous state with ZOH


Story 4.6: Smart Initialization Heuristic

As a R&D engineer (Marie), I want automatic initial guesses from temperatures, So that cold start convergence is fast.

Acceptance Criteria:

Given source and sink temperatures When initializing system Then pressures estimated via Antoine equation And evaporator pressure < P_critical And condenser pressure from T_sink + ΔT_approach


Story 4.7: Convergence Criteria & Validation

As a simulation user, I want strict criteria with sparse Jacobian for multi-circuit, So that large systems remain tractable.

Acceptance Criteria:

Given system approaching solution When checking convergence Then max |ΔP| < 1 Pa And mass error < 1e-9 kg/s, energy < 1e-6 kW And ALL circuits converge for global convergence And Jacobian uses sparse/block structure And uncoupled circuits give block-diagonal


Story 4.8: Jacobian-Freezing Optimization

As a performance-critical user, I want to freeze Jacobian updates, So that CPU time is reduced.

Acceptance Criteria:

Given nearly-converged system When Jacobian freezing enabled Then Jacobian computed once, reused And speed increases ~80% And auto-disabled if residuals increase


Epic 5: Inverse Control & Optimization

Story 5.1: Constraint Definition Framework

As a control engineer, I want to define output constraints, So that I specify target operating conditions.

Acceptance Criteria:

Given measurable outputs When defining constraint (output - target = 0) Then constraint added to residuals And can reference any component output And multiple constraints supported


Story 5.2: Bounded Control Variables

As a control engineer, I want Box Constraints or Step Clipping, So that Newton steps stay physically possible.

Acceptance Criteria:

Given control variable with bounds [min, max] When computing Newton step (Δx) Then step scaled/clipped if exceeding bounds And variable never outside bounds during iterations And ControlSaturation error if converged solution exceeds bounds


Story 5.3: Residual Embedding for Inverse Control

As a systems engineer, I want constraints embedded with DoF validation, So that system is well-posed.

Acceptance Criteria:

Given constraint and control variable When solving system Then residual added to residual vector And control variable added to unknowns And solved simultaneously (one-shot) And Jacobian includes ∂constraint/∂control And DoF validated (equations = unknowns) And OverConstrainedSystem error if mismatch


Story 5.4: Multi-Variable Control

As a control engineer, I want to control multiple outputs simultaneously, So that I optimize complete operation.

Acceptance Criteria:

Given multiple constraints When defining control problem Then each constraint maps to one control variable And all solved simultaneously And all constraints satisfied within tolerance


Epic 6: Multi-Platform APIs

Story 6.1: Rust Native API

As a Rust developer, I want clean, idiomatic Rust API, So that I integrate into Rust applications.

Acceptance Criteria:

Given a Rust application When using entropyk crate Then builder pattern for systems And all functions return Result<T, ThermoError> And follows Rust conventions And KaTeX documentation


Story 6.2: Python Bindings (PyO3)

As a Python data scientist (Alice), I want zero-copy NumPy support, So that 100x speedup isn't wasted on conversion.

Acceptance Criteria:

Given Python script with rust_thermo_cycle When creating components Then API similar to tespy And errors mapped to Python exceptions And wheels on PyPI (manylinux) And Buffer Protocol and NumPy arrays supported And zero-copy for 10k+ element vectors And 100x faster than tespy


Story 6.3: C FFI Bindings (cbindgen)

As a HIL engineer (Sarah), I want C headers with explicit memory management, So that PLC integration has no memory leaks.

Acceptance Criteria:

Given C/C++ application When including headers Then extern "C" interface available And headers auto-generated via cbindgen And error codes as enum values And opaque pointers for complex types And every allocation has free function (e.g., entropyk_free_system) And latency < 20ms


Story 6.4: WebAssembly Compilation

As a web developer (Charlie), I want WASM with TabularBackend default, So that it works without CoolProp in browser.

Acceptance Criteria:

Given web application When importing WASM module Then can create and solve in browser And results JSON-serializable And deterministic performance And package on npm And defaults to TabularBackend (CoolProp unavailable in WASM) And works out-of-box in Chrome/Edge And cycle time < 100ms


Story 6.5: CLI for Batch Execution

As a data engineer (David), I want CLI for batch simulations, So that I process millions of scenarios.

Acceptance Criteria:

Given JSON config file When running entropyk-cli run config.json Then simulation executes And outputs results to JSON And batch mode supports parallel execution And progress reported And exit codes indicate success/failure


Epic 7: Validation & Persistence

Story 7.1: Mass Balance Validation

As a simulation engineer, I want automatic mass conservation verification, So that I trust physical correctness.

Acceptance Criteria:

Given converged solution When computing mass balance Then error Σ ṁ_in - Σ ṁ_out < 1e-9 kg/s And violations trigger validation error And check performed after every solve


Story 7.2: Energy Balance Validation

As a simulation engineer, I want First AND Second Law verification, So that thermodynamic consistency is guaranteed.

Acceptance Criteria:

Given converged solution When computing balances Then energy error < 1e-6 kW And violations trigger error with breakdown And Second Law check: entropy generation ≥ 0 And warning if negative entropy destruction And violations flagged


Story 7.3: Traceability Metadata

As a researcher (Robert), I want complete traceability metadata, So that simulations are reproducible.

Acceptance Criteria:

Given simulation result When accessing metadata Then includes solver_version, fluid_backend_version, input_hash (SHA-256) And SHA-256 uniquely identifies input And metadata in structured JSON


Story 7.4: Debug Verbose Mode

As a researcher (Robert), I want detailed convergence diagnostics, So that I debug non-converging systems.

Acceptance Criteria:

Given non-converging system When verbose mode enabled Then residuals logged each iteration And Jacobian condition number reported And solver switches logged And final state dumped


Story 7.5: JSON Serialization & Deserialization

As a system designer, I want complete system serialization with backend definition, So that models are reproducible across machines.

Acceptance Criteria:

Given system with components, connections, parameters When serializing to JSON Then complete state saved (Topology + Parameters + Fluid State) And fluid backend fully included (version, hash) And deserialization reconstructs identical system And round-trip produces identical results And human-readable, versioned format And explicit error if backend missing on load And error specifies required backend version


Story 7.6: Component Calibration Parameters (Calib)

As a R&D engineer matching simulation to real machine test data, I want calibration factors (Calib: f_m, f_dp, f_ua, f_power, f_etav) on components, So that simulation results align with manufacturer test data and field measurements.

Acceptance Criteria:

Given a component with nominal model parameters When Calib (calibration factors) are set (default 1.0 = no correction) Then f_m scales mass flow: ṁ_eff = f_m × ṁ_nominal (Compressor, Expansion Valve) And f_dp scales pressure drop: ΔP_eff = f_dp × ΔP_nominal (Pipe, Heat Exchanger) And f_ua scales thermal conductance: UA_eff = f_ua × UA_nominal (Evaporator, Condenser) And f_power scales compressor power: Ẇ_eff = f_power × Ẇ_nominal (Compressor) And f_etav scales volumetric efficiency: η_v,eff = f_etav × η_v,nominal (Compressor, displacement models)

Given calibration factors from test data optimization When running simulation with calibrated components Then results match test data within configurable tolerance (e.g., capacity ±2%, power ±3%) And Calib values are serializable in JSON (persisted with system definition) And calibration workflow order documented: f_m → f_dp → f_ua, then f_power (prevents parameter fighting)

Given a calibrated system When loading from JSON Then Calib parameters are restored And traceability metadata includes calibration source (test data hash or identifier)


Story 7.7: ASHRAE 140 / BESTEST Validation (post-MVP)

As a simulation engineer seeking industrial credibility, I want to validate Entropyk against ASHRAE Standard 140 and BESTEST test cases, So that results are comparable to EnergyPlus, TRNSYS, and Modelica.

Acceptance Criteria:

Given ASHRAE 140 / Airside HVAC BESTEST (AE101AE445) test case definitions When running Entropyk on equivalent cycle configurations Then results fall within documented tolerance bands vs reference And discrepancies are documented (algorithmic, modeling assumptions) And CI includes regression tests for selected cases

Given a new Entropyk release When running validation suite Then no regression beyond tolerance And validation report generated (JSON or markdown)


Story 7.8: Inverse Calibration (Parameter Estimation)

As a R&D engineer with test bench data, I want to estimate Calib (or component) parameters from measured data, So that the model matches my machine without manual tuning.

Acceptance Criteria:

Given test data (P, T, ṁ, Ẇ, Q at multiple operating points) When running inverse calibration Then optimizer minimizes error (e.g., MAPE) between model and data And estimated Calib (or coefficients) are returned And supports constraints (e.g., 0.8 ≤ f_ua ≤ 1.2) And calibration order respected (f_m → f_dp → f_ua → f_power)

Given calibrated parameters When saving system Then Calib values and calibration_source (data hash) persisted in JSON


Epic 8: Component-Fluid Integration

Story 8.1: Fluid Backend Component Integration

As a systems engineer, I want the thermodynamic components (Compressor, Condenser, etc.) to use the real FluidBackend, So that the residuals sent to the solver reflect accurate physical states.

Acceptance Criteria:

Given a component needing physical properties When the solver computes its residuals Then it natively references the configured FluidBackend And returns real values vs placeholders And handles missing backends gracefully with fallbacks


Story 1.9: Air Coils (EvaporatorCoil, CondenserCoil) (post-MVP)

As a HVAC engineer modeling split systems or air-source heat pumps, I want explicit EvaporatorCoil and CondenserCoil components, So that air-side heat exchangers (finned) are clearly distinguished from water-cooled.

Acceptance Criteria:

Given an EvaporatorCoil (refrigerant + air) When defining the component Then 4 ports: refrigerant in/out, air in/out And UA or geometry (fins, tubes) configurable And integrates with Fan for air flow And Calib (f_ua, f_dp) applicable

Given a CondenserCoil Then same structure as EvaporatorCoil And refrigerant condenses on hot side, air on cold side


Story 1.10: Pipe Helpers for Water and Refrigerant

As a HVAC engineer modeling refrigerant and incompressible fluid circuits (water, seawater, glycol), I want convenient constructors Pipe::for_incompressible() and Pipe::for_refrigerant() with explicit ρ/μ from a fluid backend, So that I can create pipes without hardcoding fluid properties in the component.

Acceptance Criteria:

Given an incompressible fluid circuit (water, seawater, glycol) When calling Pipe::for_incompressible(geometry, port_inlet, port_outlet, density, viscosity) Then accepts explicit ρ, μ obtained from IncompressibleBackend (Story 2.7) And no hardcoded fluid properties in components crate And doc examples show water and glycol usage

Given a refrigerant circuit (R134a, R410A, CO2, etc.) When calling Pipe::for_refrigerant(geometry, port_inlet, port_outlet, density, viscosity) Then accepts explicit ρ, μ (from CoolProp/tabular at design point) And doc examples show refrigerant circuit usage And doc states that ρ, μ vary with P,T — design-point values are typical

Given the Pipe module documentation When reading the crate-level and Pipe docs Then explicitly states that Pipe serves for both refrigerant and incompressible fluids And includes a "Fluid Support" section: refrigerant (ρ/μ from backend) vs incompressible (ρ/μ from IncompressibleBackend)


Future Epics (Vision littérature HVAC)

Non planifiés alignement avec EnergyPlus, Modelica, TRNSYS :

Epic Thème Référence littérature
Transient Simulation dynamique, start-up/shutdown, ODEs Reddy, Purdue IIAR
Part-load Courbes PLF, pertes de cyclage EnergyPlus PLF
Frost/Defrost Givre, dégivrage, enthalpy method arXiv 2412.00017
Moving Boundary Échangeurs discretisés, zones phase Modelica Buildings, TIL Suite
Export ML Données synthétiques pour surrogates arXiv 2505.15041