chore: sync project state and current artifacts
This commit is contained in:
218
_bmad-output/implementation-artifacts/10-3-brine-source-sink.md
Normal file
218
_bmad-output/implementation-artifacts/10-3-brine-source-sink.md
Normal file
@@ -0,0 +1,218 @@
|
||||
# Story 10.3: BrineSource et BrineSink avec Support Glycol
|
||||
|
||||
**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 que `BrineSource` et `BrineSink` supportent les mélanges eau-glycol avec concentration,
|
||||
> Afin de pouvoir simuler des circuits de caloporteurs avec propriétés thermophysiques correctes.
|
||||
|
||||
---
|
||||
|
||||
## Contexte
|
||||
|
||||
Les caloporteurs liquides (eau, PEG, MEG, saumures) sont utilisés dans:
|
||||
|
||||
- Circuits primaire/secondaire de chillers
|
||||
- Systèmes de chauffage urbain
|
||||
- Applications basse température avec protection antigel
|
||||
|
||||
La **concentration en glycol** affecte:
|
||||
- Viscosité (perte de charge)
|
||||
- Chaleur massique (capacité thermique)
|
||||
- Point de congélation (protection antigel)
|
||||
|
||||
---
|
||||
|
||||
## Spécifications Techniques
|
||||
|
||||
### BrineSource
|
||||
|
||||
```rust
|
||||
/// Source pour fluides caloporteurs liquides (eau, PEG, MEG, saumures).
|
||||
///
|
||||
/// Impose une température et une pression fixées sur le port de sortie.
|
||||
/// La concentration en glycol est prise en compte pour les propriétés.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BrineSource {
|
||||
/// Identifiant du fluide (ex: "Water", "MEG", "PEG")
|
||||
fluid_id: String,
|
||||
/// Concentration en glycol (% massique, 0 = eau pure)
|
||||
concentration: Concentration,
|
||||
/// Température de set-point [K]
|
||||
t_set: Temperature,
|
||||
/// Pression de set-point [Pa]
|
||||
p_set: Pressure,
|
||||
/// Enthalpie calculée depuis T et concentration [J/kg]
|
||||
h_set: Enthalpy,
|
||||
/// Débit massique optionnel [kg/s]
|
||||
mass_flow: Option<MassFlow>,
|
||||
/// Débit volumique optionnel [m³/s]
|
||||
volume_flow: Option<VolumeFlow>,
|
||||
/// Port de sortie connecté
|
||||
outlet: ConnectedPort,
|
||||
}
|
||||
|
||||
impl BrineSource {
|
||||
/// Crée une source d'eau pure.
|
||||
pub fn water(
|
||||
temperature: Temperature,
|
||||
pressure: Pressure,
|
||||
outlet: ConnectedPort,
|
||||
) -> Result<Self, ComponentError>;
|
||||
|
||||
/// Crée une source de mélange eau-glycol.
|
||||
pub fn glycol_mixture(
|
||||
fluid_id: impl Into<String>,
|
||||
concentration: Concentration,
|
||||
temperature: Temperature,
|
||||
pressure: Pressure,
|
||||
outlet: ConnectedPort,
|
||||
) -> Result<Self, ComponentError>;
|
||||
|
||||
/// Définit le débit massique imposé.
|
||||
pub fn set_mass_flow(&mut self, mass_flow: MassFlow);
|
||||
|
||||
/// Définit le débit volumique imposé.
|
||||
/// Le débit massique est calculé avec la masse volumique du mélange.
|
||||
pub fn set_volume_flow(&mut self, volume_flow: VolumeFlow, density: f64);
|
||||
}
|
||||
```
|
||||
|
||||
### BrineSink
|
||||
|
||||
```rust
|
||||
/// Puits pour fluides caloporteurs liquides.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BrineSink {
|
||||
/// Identifiant du fluide
|
||||
fluid_id: String,
|
||||
/// Concentration en glycol
|
||||
concentration: Concentration,
|
||||
/// Contre-pression [Pa]
|
||||
p_back: Pressure,
|
||||
/// Température de retour optionnelle [K]
|
||||
t_back: Option<Temperature>,
|
||||
/// Port d'entrée connecté
|
||||
inlet: ConnectedPort,
|
||||
}
|
||||
|
||||
impl BrineSink {
|
||||
/// Crée un puits pour eau pure.
|
||||
pub fn water(
|
||||
pressure: Pressure,
|
||||
inlet: ConnectedPort,
|
||||
) -> Result<Self, ComponentError>;
|
||||
|
||||
/// Crée un puits pour mélange eau-glycol.
|
||||
pub fn glycol_mixture(
|
||||
fluid_id: impl Into<String>,
|
||||
concentration: Concentration,
|
||||
pressure: Pressure,
|
||||
inlet: ConnectedPort,
|
||||
) -> Result<Self, ComponentError>;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Calcul des Propriétés
|
||||
|
||||
### Enthalpie depuis Température et Concentration
|
||||
|
||||
```rust
|
||||
/// Calcule l'enthalpie d'un mélange eau-glycol.
|
||||
///
|
||||
/// Utilise CoolProp avec la syntaxe de mélange:
|
||||
/// - Eau pure: "Water"
|
||||
/// - Mélange MEG: "MEG-MASS%" ou "INCOMP::MEG-MASS%"
|
||||
fn calculate_enthalpy(
|
||||
fluid_id: &str,
|
||||
concentration: Concentration,
|
||||
temperature: Temperature,
|
||||
pressure: Pressure,
|
||||
) -> Result<Enthalpy, ComponentError> {
|
||||
// Pour CoolProp, utiliser:
|
||||
// PropsSI("H", "T", T, "P", P, fluid_string)
|
||||
// où fluid_string = format!("INCOMP::{}-{}", fluid_id, concentration.to_percent())
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fichiers à Créer/Modifier
|
||||
|
||||
| Fichier | Action |
|
||||
|---------|--------|
|
||||
| `crates/components/src/flow_boundary/brine.rs` | Créer `BrineSource`, `BrineSink` |
|
||||
| `crates/components/src/flow_boundary/mod.rs` | Ajouter ré-exports |
|
||||
|
||||
---
|
||||
|
||||
## Critères d'Acceptation
|
||||
|
||||
- [ ] `BrineSource::water()` crée une source d'eau pure
|
||||
- [ ] `BrineSource::glycol_mixture()` crée une source avec concentration
|
||||
- [ ] L'enthalpie est calculée correctement depuis T et concentration
|
||||
- [ ] `BrineSink::water()` crée un puits pour eau
|
||||
- [ ] `BrineSink::glycol_mixture()` crée un puits avec concentration
|
||||
- [ ] `energy_transfers()` retourne `(Power(0), Power(0))`
|
||||
- [ ] `port_enthalpies()` retourne `[h_set]`
|
||||
- [ ] Validation de la concentration (0-100%)
|
||||
- [ ] Tests unitaires avec différents pourcentages de glycol
|
||||
|
||||
---
|
||||
|
||||
## Tests Requis
|
||||
|
||||
```rust
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_brine_source_water() { /* ... */ }
|
||||
|
||||
#[test]
|
||||
fn test_brine_source_meg_30_percent() { /* ... */ }
|
||||
|
||||
#[test]
|
||||
fn test_brine_source_enthalpy_calculation() { /* ... */ }
|
||||
|
||||
#[test]
|
||||
fn test_brine_source_volume_flow_conversion() { /* ... */ }
|
||||
|
||||
#[test]
|
||||
fn test_brine_sink_water() { /* ... */ }
|
||||
|
||||
#[test]
|
||||
fn test_brine_sink_meg_mixture() { /* ... */ }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes d'Implémentation
|
||||
|
||||
### Support CoolProp pour Mélanges
|
||||
|
||||
CoolProp supporte les mélanges incompressibles via la syntaxe:
|
||||
```
|
||||
INCOMP::MEG-30 // MEG à 30% massique
|
||||
INCOMP::PEG-40 // PEG à 40% massique
|
||||
```
|
||||
|
||||
Vérifier que le backend CoolProp utilisé dans le projet supporte cette syntaxe.
|
||||
|
||||
---
|
||||
|
||||
## Références
|
||||
|
||||
- [Architecture Document](../../plans/boundary-condition-refactoring-architecture.md)
|
||||
- [Story 10-1: Nouveaux types physiques](./10-1-new-physical-types.md)
|
||||
- [CoolProp Incompressible Fluids](http://www.coolprop.org/fluid_properties/Incompressibles.html)
|
||||
Reference in New Issue
Block a user