# Entropyk — Python Bindings High-performance Python bindings for the [Entropyk](../../README.md) thermodynamic simulation library, built with [PyO3](https://pyo3.rs/) and [Maturin](https://www.maturin.rs/). ## Quickstart ### Installation (Development) ```bash # 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 ```python 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: ```bash 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 ```python # 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 ```bash cd bindings/python maturin develop pytest tests/ -v ``` ## Examples - [`examples/simple_cycle.py`](examples/simple_cycle.py) — Build and solve a refrigeration cycle - [`examples/migration_from_tespy.py`](examples/migration_from_tespy.py) — TESPy → Entropyk migration guide