Entropyk/_bmad-output/implementation-artifacts/10-6-python-bindings-update.md

268 lines
6.5 KiB
Markdown

# Story 10.6: Mise à jour des Bindings Python
**Epic:** 10 - Enhanced Boundary Conditions
**Priorité:** P1-HIGH
**Estimation:** 2h
**Statut:** backlog
**Dépendances:** Stories 10-2, 10-3, 10-4
---
## Story
> En tant qu'utilisateur Python de la librairie Entropyk,
> Je veux accéder aux nouveaux types de conditions aux limites via l'API Python,
> Afin de pouvoir utiliser les fonctionnalités avancées (concentration glycol, titre, psychrométrie).
---
## Contexte
Les bindings Python (via PyO3) doivent être mis à jour pour exposer:
1. Les nouveaux types physiques (`Concentration`, `VolumeFlow`, `RelativeHumidity`, `VaporQuality`)
2. Les nouveaux composants (`RefrigerantSource`, `BrineSource`, `AirSource`, etc.)
---
## Spécifications Techniques
### 1. Exposer les Nouveaux Types Physiques
```python
# bindings/python/entropyk/core.py
class Concentration:
"""Concentration massique en % (0-100)"""
@staticmethod
def from_percent(value: float) -> 'Concentration':
"""Crée une concentration depuis un pourcentage."""
pass
def to_percent(self) -> float:
"""Retourne la concentration en pourcentage."""
pass
def to_mass_fraction(self) -> float:
"""Retourne la fraction massique (0-1)."""
pass
class VolumeFlow:
"""Débit volumique en m³/s"""
@staticmethod
def from_m3_per_s(value: float) -> 'VolumeFlow':
pass
@staticmethod
def from_l_per_min(value: float) -> 'VolumeFlow':
pass
def to_m3_per_s(self) -> float:
pass
def to_l_per_min(self) -> float:
pass
class RelativeHumidity:
"""Humidité relative en % (0-100)"""
@staticmethod
def from_percent(value: float) -> 'RelativeHumidity':
pass
def to_percent(self) -> float:
pass
def to_fraction(self) -> float:
pass
class VaporQuality:
"""Titre (vapor quality) pour fluides frigorigènes (0-1)"""
@staticmethod
def from_fraction(value: float) -> 'VaporQuality':
pass
def to_fraction(self) -> float:
pass
def to_percent(self) -> float:
pass
```
### 2. Exposer les Nouveaux Composants
```python
# bindings/python/entropyk/components.py
class RefrigerantSource:
"""Source pour fluides frigorigènes compressibles."""
@staticmethod
def new(
fluid_id: str,
pressure: Pressure,
enthalpy: Enthalpy,
outlet: ConnectedPort,
) -> 'RefrigerantSource':
"""Crée une source avec pression et enthalpie fixées."""
pass
@staticmethod
def with_vapor_quality(
fluid_id: str,
pressure: Pressure,
vapor_quality: VaporQuality,
outlet: ConnectedPort,
) -> 'RefrigerantSource':
"""Crée une source avec pression et titre fixés."""
pass
def set_mass_flow(self, mass_flow: MassFlow) -> None:
"""Définit le débit massique imposé."""
pass
class BrineSource:
"""Source pour fluides caloporteurs liquides."""
@staticmethod
def water(
temperature: Temperature,
pressure: Pressure,
outlet: ConnectedPort,
) -> 'BrineSource':
"""Crée une source d'eau pure."""
pass
@staticmethod
def glycol_mixture(
fluid_id: str,
concentration: Concentration,
temperature: Temperature,
pressure: Pressure,
outlet: ConnectedPort,
) -> 'BrineSource':
"""Crée une source de mélange eau-glycol."""
pass
class AirSource:
"""Source pour air humide."""
@staticmethod
def from_dry_bulb_rh(
temperature_dry: Temperature,
relative_humidity: RelativeHumidity,
pressure: Pressure,
outlet: ConnectedPort,
) -> 'AirSource':
"""Crée une source avec température sèche et humidité relative."""
pass
@staticmethod
def from_dry_and_wet_bulb(
temperature_dry: Temperature,
temperature_wet_bulb: Temperature,
pressure: Pressure,
outlet: ConnectedPort,
) -> 'AirSource':
"""Crée une source avec températures sèche et bulbe humide."""
pass
def specific_enthalpy(self) -> Enthalpy:
"""Retourne l'enthalpie spécifique de l'air humide."""
pass
def humidity_ratio(self) -> float:
"""Retourne le rapport d'humidité."""
pass
```
---
## Fichiers à Modifier
| Fichier | Action |
|---------|--------|
| `bindings/python/src/core.rs` | Ajouter bindings pour nouveaux types |
| `bindings/python/src/components.rs` | Ajouter bindings pour nouveaux composants |
| `bindings/python/src/lib.rs` | Exporter les nouveaux types |
| `bindings/python/tests/test_boundary.py` | Tests pour nouveaux types |
---
## Critères d'Acceptation
- [ ] `Concentration` accessible depuis Python
- [ ] `VolumeFlow` accessible depuis Python
- [ ] `RelativeHumidity` accessible depuis Python
- [ ] `VaporQuality` accessible depuis Python
- [ ] `RefrigerantSource` et `RefrigerantSink` accessibles
- [ ] `BrineSource` et `BrineSink` accessibles
- [ ] `AirSource` et `AirSink` accessibles
- [ ] Tests Python passent
- [ ] Documentation Python générée
---
## Tests Requis
```python
# bindings/python/tests/test_boundary.py
def test_concentration():
c = Concentration.from_percent(30.0)
assert c.to_percent() == 30.0
assert c.to_mass_fraction() == 0.3
def test_vapor_quality():
vq = VaporQuality.from_fraction(0.5)
assert vq.to_fraction() == 0.5
assert vq.to_percent() == 50.0
def test_refrigerant_source():
source = RefrigerantSource.new(
"R410A",
Pressure.from_pascals(1e6),
Enthalpy.from_joules_per_kg(280000),
port
)
assert source is not None
def test_brine_source_glycol():
source = BrineSource.glycol_mixture(
"MEG",
Concentration.from_percent(30.0),
Temperature.from_celsius(10.0),
Pressure.from_pascals(3e5),
port
)
assert source is not None
def test_air_source_psychrometrics():
source = AirSource.from_dry_bulb_rh(
Temperature.from_celsius(25.0),
RelativeHumidity.from_percent(50.0),
Pressure.from_pascals(101325),
port
)
h = source.specific_enthalpy()
w = source.humidity_ratio()
assert h is not None
assert w > 0
```
---
## Références
- [Architecture Document](../../plans/boundary-condition-refactoring-architecture.md)
- [Story 10-1: Nouveaux types physiques](./10-1-new-physical-types.md)
- [PyO3 Documentation](https://pyo3.rs/)