237 lines
7.9 KiB
Python
237 lines
7.9 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 fall back to the legacy IPM_DLL
|
|
# folder only if the packaged module cannot be imported. Import the module
|
|
# object and use getattr to avoid ImportError when optional symbols like
|
|
# `MockRefifc` are missing.
|
|
try:
|
|
import importlib
|
|
_sr = importlib.import_module('app.ipm.simple_refrig_api')
|
|
Refifc = getattr(_sr, 'Refifc')
|
|
MockRefifc = getattr(_sr, 'MockRefifc', None)
|
|
except Exception:
|
|
# Fall back to loading from IPM_DLL directory as before. Import the
|
|
# legacy module and pick attributes if present; older 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)
|