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

6.5 KiB

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

# 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

# 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

# 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