..

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 Configurations

Config Constructor Description
NewtonConfig (max_iterations, tolerance, line_search, timeout_ms, initial_state, use_numerical_jacobian, jacobian_freezing, convergence_criteria, timeout_config, previous_state, ...) Newton-Raphson settings
PicardConfig (max_iterations, tolerance, relaxation, initial_state, timeout_ms, convergence_criteria) Picard / Seq. Substitution settings
FallbackConfig (newton, picard) Fallback behavior
ConvergenceCriteria (pressure_tolerance_pa, mass_balance_tolerance_kgs, energy_balance_tolerance_w) Detailed component criteria
JacobianFreezingConfig (max_frozen_iters, threshold) Speeds up Newton-Raphson
TimeoutConfig (return_best_state_on_timeout, zoh_fallback) Behavior on timeout limit

Solver Running

# Strategy Enum approach
strategy = entropyk.SolverStrategy.newton(max_iterations=100, tolerance=1e-6)
# Or
strategy = entropyk.SolverStrategy.picard(relaxation=0.5)

result = strategy.solve(system)  # Returns ConvergedState

# Legacy Config approach
config = entropyk.FallbackConfig(
    newton=entropyk.NewtonConfig(max_iterations=100),
    picard=entropyk.PicardConfig(max_iterations=500)
)
result = config.solve(system)

Exceptions

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

Running Tests

cd bindings/python
maturin develop
pytest tests/ -v

Examples