Sepehr fa480ed303 feat: implement mass balance validation for Story 7.1
- Added port_mass_flows to Component trait and implements for core components.
- Added System::check_mass_balance and integrated it into the solver.
- Restored connect methods for ExpansionValve, Compressor, and Pipe to fix integration tests.
- Updated Python and C bindings for validation errors.
- Updated sprint status and story documentation.
2026-02-21 23:21:34 +01:00

4.9 KiB

Entropyk — Python Bindings

High-performance Python bindings for the Entropyk thermodynamic simulation library, built with PyO3 and Maturin.

Quickstart

Installation (Development)

# From the bindings/python directory:
pip install maturin
maturin develop --release

# Verify installation:
python -c "import entropyk; print(entropyk.Pressure(bar=1.0))"

Basic Usage

import entropyk

# ── 1. Physical Types (type-safe units) ──

p = entropyk.Pressure(bar=12.0)
print(p.to_kpa())        # 1200.0 kPa
print(p.to_pascals())    # 1200000.0 Pa

t = entropyk.Temperature(celsius=45.0)
print(t.to_kelvin())     # 318.15 K

h = entropyk.Enthalpy(kj_per_kg=420.0)
m = entropyk.MassFlow(kg_per_s=0.05)

# Arithmetic
dp = entropyk.Pressure(bar=10.0) - entropyk.Pressure(bar=3.0)


# ── 2. Build a Refrigeration Cycle ──

system = entropyk.System()

comp = system.add_component(entropyk.Compressor(efficiency=0.85))
cond = system.add_component(entropyk.Condenser(ua=5000.0))
exv  = system.add_component(entropyk.ExpansionValve())
evap = system.add_component(entropyk.Evaporator(ua=3000.0))

system.add_edge(comp, cond)
system.add_edge(cond, exv)
system.add_edge(exv, evap)
system.add_edge(evap, comp)
system.finalize()


# ── 3. Solve ──

config = entropyk.FallbackConfig(
    newton=entropyk.NewtonConfig(max_iterations=200, tolerance=1e-6),
    picard=entropyk.PicardConfig(max_iterations=500, relaxation=0.5),
)

try:
    result = config.solve(system)
    print(f"Converged in {result.iterations} iterations")
    print(f"State: {result.state_vector}")
except entropyk.TimeoutError:
    print("Solver timed out")
except entropyk.SolverError as e:
    print(f"Solver failed: {e}")

Recompiling after Rust Changes

Because the Python bindings rely on the Rust source code (crates/components, crates/solver, etc.), you must recompile the Python package if you modify the underlying Rust physics engine.

To recompile the bindings manually, simply use Maturin from the bindings/python directory with your virtual environment activated:

cd bindings/python
source .venv/bin/activate
maturin develop --release

Note: If you added a new structural field in Rust (e.g. adding a size parameter to a Component struct), make sure to also update the Python wrapper class in bindings/python/src/ so the macro #[pyclass] reflects the new shape before recompiling. You can use the /update-python-bindings agent workflow to do this automatically.

API Reference

Physical Types

Type Constructors Conversions
Pressure pa=, bar=, kpa=, psi= to_pascals(), to_bar(), to_kpa(), to_psi()
Temperature kelvin=, celsius=, fahrenheit= to_kelvin(), to_celsius(), to_fahrenheit()
Enthalpy j_per_kg=, kj_per_kg= to_j_per_kg(), to_kj_per_kg()
MassFlow kg_per_s=, g_per_s= to_kg_per_s(), to_g_per_s()

All types support: __repr__, __str__, __float__, __eq__, __add__, __sub__

Components

Component Constructor Description
Compressor (m1..m10, speed_rpm, displacement, efficiency, fluid) AHRI 540 performance model
Condenser (ua) Heat rejection coil
Evaporator (ua) Heat absorption coil
Economizer (ua) Internal heat exchanger
ExpansionValve (fluid, opening) Isenthalpic throttling
Pipe (length, diameter, fluid, density, viscosity, roughness) Darcy-Weisbach pressure drop
Pump (pressure_rise_pa, efficiency) Liquid pump
Fan (pressure_rise_pa, efficiency) Air fan
FlowSplitter (n_outlets) Flow distribution
FlowMerger (n_inlets) Flow recombination
FlowSource (pressure_pa, temperature_k) Boundary source
FlowSink () Boundary sink

Solver

# Newton-Raphson (fast convergence)
config = entropyk.NewtonConfig(max_iterations=100, tolerance=1e-6, line_search=True)

# Picard / Sequential Substitution (more robust)
config = entropyk.PicardConfig(max_iterations=500, tolerance=1e-4, relaxation=0.5)

# Fallback (Newton → Picard on divergence)
config = entropyk.FallbackConfig(newton=newton_cfg, picard=picard_cfg)

result = config.solve(system)  # Returns ConvergedState

Exceptions

EntropykError (base)
├── SolverError
│   ├── TimeoutError
│   └── ControlSaturationError
├── FluidError
├── ComponentError
├── TopologyError
└── ValidationError

Running Tests

cd bindings/python
maturin develop
pytest tests/ -v

Examples