5.5 KiB
5.5 KiB
Story 10.2: RefrigerantSource et RefrigerantSink
Epic: 10 - Enhanced Boundary Conditions
Priorité: P0-CRITIQUE
Estimation: 3h
Statut: backlog
Dépendances: Story 10-1 (Nouveaux types physiques)
Story
En tant que moteur de simulation thermodynamique,
Je veux queRefrigerantSourceetRefrigerantSinkimplémentent le traitComponent,
Afin de pouvoir définir des conditions aux limites pour les fluides frigorigènes avec titre.
Contexte
Les fluides frigorigènes (R410A, R134a, CO2, etc.) nécessitent des conditions aux limites spécifiques:
- Possibilité de spécifier le titre (vapor quality) au lieu de l'enthalpie
- Validation que le fluide est bien un réfrigérant
- Support des propriétés thermodynamiques via CoolProp
Spécifications Techniques
RefrigerantSource
/// Source pour fluides frigorigènes compressibles.
///
/// Impose une pression et une enthalpie (ou titre) fixées sur le port de sortie.
#[derive(Debug, Clone)]
pub struct RefrigerantSource {
/// Identifiant du fluide frigorigène (ex: "R410A", "R134a", "CO2")
fluid_id: String,
/// Pression de set-point [Pa]
p_set: Pressure,
/// Enthalpie de set-point [J/kg]
h_set: Enthalpy,
/// Titre optionnel (vapor quality, 0-1)
vapor_quality: Option<VaporQuality>,
/// Débit massique optionnel [kg/s]
mass_flow: Option<MassFlow>,
/// Port de sortie connecté
outlet: ConnectedPort,
}
impl RefrigerantSource {
/// Crée une source réfrigérant avec pression et enthalpie fixées.
pub fn new(
fluid_id: impl Into<String>,
pressure: Pressure,
enthalpy: Enthalpy,
outlet: ConnectedPort,
) -> Result<Self, ComponentError>;
/// Crée une source réfrigérant avec pression et titre fixés.
/// L'enthalpie est calculée automatiquement via CoolProp.
pub fn with_vapor_quality(
fluid_id: impl Into<String>,
pressure: Pressure,
vapor_quality: VaporQuality,
outlet: ConnectedPort,
) -> Result<Self, ComponentError>;
/// Définit le débit massique imposé.
pub fn set_mass_flow(&mut self, mass_flow: MassFlow);
}
RefrigerantSink
/// Puits pour fluides frigorigènes compressibles.
///
/// Impose une contre-pression fixe sur le port d'entrée.
#[derive(Debug, Clone)]
pub struct RefrigerantSink {
/// Identifiant du fluide frigorigène
fluid_id: String,
/// Contre-pression [Pa]
p_back: Pressure,
/// Enthalpie de retour optionnelle [J/kg]
h_back: Option<Enthalpy>,
/// Port d'entrée connecté
inlet: ConnectedPort,
}
impl RefrigerantSink {
/// Crée un puits réfrigérant avec contre-pression fixe.
pub fn new(
fluid_id: impl Into<String>,
pressure: Pressure,
inlet: ConnectedPort,
) -> Result<Self, ComponentError>;
/// Définit une enthalpie de retour fixe.
pub fn set_return_enthalpy(&mut self, enthalpy: Enthalpy);
}
Implémentation du Trait Component
impl Component for RefrigerantSource {
fn n_equations(&self) -> usize { 2 }
fn compute_residuals(&self, _state: &SystemState, residuals: &mut ResidualVector)
-> Result<(), ComponentError>
{
residuals[0] = self.outlet.pressure().to_pascals() - self.p_set.to_pascals();
residuals[1] = self.outlet.enthalpy().to_joules_per_kg() - self.h_set.to_joules_per_kg();
Ok(())
}
fn energy_transfers(&self, _state: &SystemState) -> Option<(Power, Power)> {
Some((Power::from_watts(0.0), Power::from_watts(0.0)))
}
fn port_enthalpies(&self, _state: &SystemState) -> Result<Vec<Enthalpy>, ComponentError> {
Ok(vec![self.h_set])
}
fn port_mass_flows(&self, _state: &SystemState) -> Result<Vec<MassFlow>, ComponentError> {
match self.mass_flow {
Some(mdot) => Ok(vec![MassFlow::from_kg_per_s(-mdot.to_kg_per_s())]),
None => Ok(vec![]),
}
}
}
Fichiers à Créer/Modifier
| Fichier | Action |
|---|---|
crates/components/src/flow_boundary/mod.rs |
Créer module avec ré-exports |
crates/components/src/flow_boundary/refrigerant.rs |
Créer RefrigerantSource, RefrigerantSink |
crates/components/src/lib.rs |
Exporter les nouveaux types |
Critères d'Acceptation
RefrigerantSource::new()crée une source avec P et h fixéesRefrigerantSource::with_vapor_quality()calcule l'enthalpie depuis le titreRefrigerantSink::new()crée un puits avec contre-pressionenergy_transfers()retourne(Power(0), Power(0))port_enthalpies()retourne[h_set]port_mass_flows()retourne le débit si spécifié- Validation que le fluide est un réfrigérant valide
- Tests unitaires complets
Tests Requis
#[cfg(test)]
mod tests {
#[test]
fn test_refrigerant_source_new() { /* ... */ }
#[test]
fn test_refrigerant_source_with_vapor_quality() { /* ... */ }
#[test]
fn test_refrigerant_source_energy_transfers_zero() { /* ... */ }
#[test]
fn test_refrigerant_source_port_enthalpies() { /* ... */ }
#[test]
fn test_refrigerant_sink_new() { /* ... */ }
#[test]
fn test_refrigerant_sink_with_return_enthalpy() { /* ... */ }
}