diagram_ph/app/core/refrigerant_loader.py

232 lines
7.7 KiB
Python

"""
Module de chargement des refrigerants - Utilise directement IPM_DLL/simple_refrig_api.py
"""
import sys
import os
from pathlib import Path
from typing import Dict, Optional, List
# Prefer the packaged app.ipm module, but keep a fallback to the legacy
# IPM_DLL folder for development compatibility.
try:
from app.ipm.simple_refrig_api import Refifc, MockRefifc # type: ignore
except Exception:
# Fall back to loading from IPM_DLL directory as before. Import the
# module and pick attributes if present; older legacy wrappers may not
# define MockRefifc.
_current_dir = Path(__file__).parent.parent.parent
_ipm_dll_dir = _current_dir / "IPM_DLL"
if str(_ipm_dll_dir) not in sys.path:
sys.path.insert(0, str(_ipm_dll_dir))
import simple_refrig_api as _sr # type: ignore
Refifc = getattr(_sr, 'Refifc')
MockRefifc = getattr(_sr, 'MockRefifc', None)
class RefrigerantLibrary:
"""
Wrapper autour de Refifc pour compatibilite avec l'API.
Utilise directement la classe Refifc qui fonctionne dans le code original.
"""
def __init__(self, refrig_name: str, libs_dir: Optional[Path] = None):
"""
Initialise le chargement du refrigerant.
Args:
refrig_name: Nom du refrigerant (ex: "R134a", "R290")
libs_dir: Repertoire contenant les bibliotheques (optionnel, non utilise car Refifc gere ca)
"""
self.refrig_name = refrig_name
# Utiliser Refifc directement - c'est la classe qui fonctionne dans le code original
self._refifc = Refifc(refrig_name)
# Exposer toutes les methodes de Refifc avec la meme signature
def T_px(self, p: float, x: float) -> float:
"""Température à partir de pression (Pa) et qualité (retourne K).
Note: les méthodes de bas niveau attendent et retournent des unités SI
(pression en Pa, température en K, enthalpie en J/kg, entropie en J/kg.K).
"""
return self._refifc.T_px(p, x)
def h_px(self, p: float, x: float) -> float:
"""Enthalpie à partir de pression (Pa) et qualité (retourne J/kg)"""
return self._refifc.h_px(p, x)
def h_pT(self, p: float, T: float) -> float:
"""Enthalpie à partir de pression (Pa) et température (K) (retourne J/kg)"""
return self._refifc.h_pT(p, T)
def x_ph(self, p: float, h: float) -> float:
"""Qualité à partir de pression (Pa) et enthalpie (J/kg)"""
return self._refifc.x_ph(p, h)
def p_Tx(self, T: float, x: float) -> float:
"""Pression à partir de température (K) et qualité (retourne Pa)."""
return self._refifc.p_Tx(T, x)
def Ts_px(self, p: float, x: float) -> float:
"""Température de saturation à partir de pression (Pa) et qualité (retourne K)"""
return self._refifc.Ts_px(p, x)
def rho_px(self, p: float, x: float) -> float:
"""Densité à partir de pression (Pa) et qualité"""
return self._refifc.rho_px(p, x)
def s_px(self, p: float, x: float) -> float:
"""Entropie à partir de pression (Pa) et qualité (retourne J/kg.K)"""
return self._refifc.s_px(p, x)
def hsl_px(self, p: float, x: float) -> float:
"""Enthalpie liquide saturée (retourne J/kg)"""
return self._refifc.hsl_px(p, x)
def hsv_px(self, p: float, x: float) -> float:
"""Enthalpie vapeur saturée (retourne J/kg)"""
return self._refifc.hsv_px(p, x)
def rhosl_px(self, p: float, x: float) -> float:
"""Densité liquide saturée"""
return self._refifc.rhosl_px(p, x)
def rhosv_px(self, p: float, x: float) -> float:
"""Densité vapeur saturée"""
return self._refifc.rhosv_px(p, x)
def p_begin(self) -> float:
"""Pression minimale du refrigerant (Pa)"""
return self._refifc.p_begin()
def p_end(self) -> float:
"""Pression maximale du refrigerant (Pa)"""
return self._refifc.p_end()
class RefrigerantManager:
"""Gestionnaire central pour tous les refrigerants disponibles"""
# Liste des refrigerants supportes
SUPPORTED_REFRIGERANTS = [
"R12", "R22", "R32", "R134a", "R290", "R404A", "R410A",
"R452A", "R454A", "R454B", "R502", "R507A", "R513A",
"R515B", "R717", "R744", "R1233zd", "R1234ze"
]
def __init__(self, libs_dir: Optional[Path] = None):
"""
Initialise le gestionnaire
Args:
libs_dir: Repertoire contenant les bibliotheques
"""
self.libs_dir = libs_dir
self._loaded_refrigerants: Dict[str, RefrigerantLibrary] = {}
def get_available_refrigerants(self) -> List[Dict[str, str]]:
"""
Retourne la liste des refrigerants disponibles
Returns:
Liste de dictionnaires avec nom et disponibilite
"""
available = []
for refrig in self.SUPPORTED_REFRIGERANTS:
try:
# Tenter de charger pour verifier disponibilite
if refrig not in self._loaded_refrigerants:
self.load_refrigerant(refrig)
available.append({
"name": refrig,
"available": True,
"loaded": refrig in self._loaded_refrigerants
})
except Exception as e:
available.append({
"name": refrig,
"available": False,
"error": str(e)
})
return available
def load_refrigerant(self, refrig_name: str) -> RefrigerantLibrary:
"""
Charge un refrigerant specifique
Args:
refrig_name: Nom du refrigerant
Returns:
Instance RefrigerantLibrary
Raises:
ValueError: Si le refrigerant n'est pas supporte
RuntimeError: Si le chargement echoue
"""
if refrig_name not in self.SUPPORTED_REFRIGERANTS:
raise ValueError(
f"Refrigerant non supporte: {refrig_name}. "
f"Supportes: {', '.join(self.SUPPORTED_REFRIGERANTS)}"
)
if refrig_name in self._loaded_refrigerants:
return self._loaded_refrigerants[refrig_name]
try:
lib = RefrigerantLibrary(refrig_name, self.libs_dir)
self._loaded_refrigerants[refrig_name] = lib
return lib
except Exception as e:
raise RuntimeError(
f"Erreur chargement {refrig_name}: {e}"
)
def get_refrigerant(self, refrig_name: str) -> RefrigerantLibrary:
"""
Obtient un refrigerant (le charge si necessaire)
Args:
refrig_name: Nom du refrigerant
Returns:
Instance RefrigerantLibrary
"""
if refrig_name not in self._loaded_refrigerants:
return self.load_refrigerant(refrig_name)
return self._loaded_refrigerants[refrig_name]
def unload_all(self):
"""Decharge tous les refrigerants"""
self._loaded_refrigerants.clear()
# Instance globale du gestionnaire
_manager: Optional[RefrigerantManager] = None
def get_manager() -> RefrigerantManager:
"""Obtient l'instance globale du gestionnaire"""
global _manager
if _manager is None:
_manager = RefrigerantManager()
return _manager
def get_refrigerant(name: str) -> RefrigerantLibrary:
"""
Fonction helper pour obtenir un refrigerant
Args:
name: Nom du refrigerant
Returns:
Instance RefrigerantLibrary
"""
return get_manager().get_refrigerant(name)