170 lines
5.7 KiB
Markdown
170 lines
5.7 KiB
Markdown
# 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 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```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
|