- 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.
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
examples/simple_cycle.py— Build and solve a refrigeration cycleexamples/migration_from_tespy.py— TESPy → Entropyk migration guide