chore: remove deprecated flow_boundary and update docs to match new architecture
This commit is contained in:
@@ -1,195 +1,340 @@
|
||||
# Story 10.2: RefrigerantSource et RefrigerantSink
|
||||
# Story 10.2: RefrigerantSource and RefrigerantSink
|
||||
|
||||
**Epic:** 10 - Enhanced Boundary Conditions
|
||||
**Priorité:** P0-CRITIQUE
|
||||
**Estimation:** 3h
|
||||
**Statut:** backlog
|
||||
**Dépendances:** Story 10-1 (Nouveaux types physiques)
|
||||
|
||||
---
|
||||
Status: done
|
||||
|
||||
## Story
|
||||
|
||||
> En tant que moteur de simulation thermodynamique,
|
||||
> Je veux que `RefrigerantSource` et `RefrigerantSink` implémentent le trait `Component`,
|
||||
> Afin de pouvoir définir des conditions aux limites pour les fluides frigorigènes avec titre.
|
||||
As a thermodynamic engineer,
|
||||
I want dedicated `RefrigerantSource` and `RefrigerantSink` components that natively support vapor quality,
|
||||
So that I can model refrigerant cycles with precise two-phase state specification without confusion.
|
||||
|
||||
---
|
||||
## Acceptance Criteria
|
||||
|
||||
## Contexte
|
||||
1. **Given** the new `VaporQuality` type from Story 10-1
|
||||
**When** I create a `RefrigerantSource`
|
||||
**Then** I can specify the refrigerant state via (Pressure, VaporQuality) instead of (Pressure, Enthalpy)
|
||||
|
||||
Les fluides frigorigènes (R410A, R134a, CO2, etc.) nécessitent des conditions aux limites spécifiques:
|
||||
2. **RefrigerantSource** imposes fixed thermodynamic state on outlet edge:
|
||||
- Constructor: `RefrigerantSource::new(fluid, p_set, quality, backend, outlet)`
|
||||
- Uses `VaporQuality` type for type-safe quality specification
|
||||
- Internal conversion: quality → enthalpy via FluidBackend
|
||||
- 2 equations: `P_edge - P_set = 0`, `h_edge - h_set = 0`
|
||||
|
||||
- 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
|
||||
3. **RefrigerantSink** imposes back-pressure (optional quality):
|
||||
- Constructor: `RefrigerantSink::new(fluid, p_back, quality_opt, backend, inlet)`
|
||||
- Optional quality: `None` = free enthalpy (1 equation), `Some(q)` = fixed quality (2 equations)
|
||||
- Methods: `set_quality()`, `clear_quality()` for dynamic toggle
|
||||
|
||||
---
|
||||
4. **Given** a refrigerant at saturated liquid (quality = 0)
|
||||
**When** creating RefrigerantSource
|
||||
**Then** the source outputs subcooled/saturated liquid state
|
||||
|
||||
## Spécifications Techniques
|
||||
5. **Given** a refrigerant at saturated vapor (quality = 1)
|
||||
**When** creating RefrigerantSource
|
||||
**Then** the source outputs saturated/superheated vapor state
|
||||
|
||||
### RefrigerantSource
|
||||
6. Fluid validation: only accept refrigerants (R410A, R134a, R32, CO2, etc.), reject incompressible fluids
|
||||
7. Implements `Component` trait (object-safe, `Box<dyn Component>`)
|
||||
8. All methods return `Result<T, ComponentError>` (Zero-Panic Policy)
|
||||
9. Unit tests cover: quality conversions, boundary cases (0, 1), invalid fluids, optional quality toggle
|
||||
10. Documentation with examples and LaTeX equations
|
||||
|
||||
## Tasks / Subtasks
|
||||
|
||||
- [x] Task 1: Implement RefrigerantSource (AC: #1, #2, #4, #5, #6)
|
||||
- [x] 1.1 Create struct with fields: `fluid_id`, `p_set`, `quality`, `h_set` (computed), `backend`, `outlet`
|
||||
- [x] 1.2 Implement `new()` constructor with quality → enthalpy conversion via backend
|
||||
- [x] 1.3 Add fluid validation (reject incompressible via `is_incompressible()`)
|
||||
- [x] 1.4 Implement `Component::compute_residuals()` (2 equations)
|
||||
- [x] 1.5 Implement `Component::jacobian_entries()` (diagonal 1.0)
|
||||
- [x] 1.6 Implement `Component::get_ports()`, `port_mass_flows()`, `port_enthalpies()`, `energy_transfers()`
|
||||
- [x] 1.7 Add accessor methods: `fluid_id()`, `p_set_pa()`, `quality()`, `h_set_jkg()`
|
||||
- [x] 1.8 Add setters: `set_pressure()`, `set_quality()` (recompute enthalpy)
|
||||
|
||||
- [x] Task 2: Implement RefrigerantSink (AC: #3, #6)
|
||||
- [x] 2.1 Create struct with fields: `fluid_id`, `p_back`, `quality_opt`, `h_back_opt` (computed), `backend`, `inlet`
|
||||
- [x] 2.2 Implement `new()` constructor with optional quality
|
||||
- [x] 2.3 Implement dynamic equation count (1 or 2 based on quality_opt)
|
||||
- [x] 2.4 Implement `Component` trait methods
|
||||
- [x] 2.5 Add `set_quality()`, `clear_quality()` methods
|
||||
|
||||
- [x] Task 3: Module integration (AC: #7, #8)
|
||||
- [x] 3.1 Add to `crates/components/src/lib.rs` exports
|
||||
- [x] 3.2 Add type aliases if needed (optional)
|
||||
- [x] 3.3 Ensure `Box<dyn Component>` compatibility
|
||||
|
||||
- [x] Task 4: Testing (AC: #9)
|
||||
- [x] 4.1 Unit tests for RefrigerantSource: quality 0, 0.5, 1; invalid fluids
|
||||
- [x] 4.2 Unit tests for RefrigerantSink: with/without quality, dynamic toggle
|
||||
- [x] 4.3 Residual validation tests (zero at set-point)
|
||||
- [x] 4.4 Trait object tests (`Box<dyn Component>`)
|
||||
- [x] 4.5 Energy methods tests (Q=0, W=0 for boundaries)
|
||||
|
||||
- [x] Task 5: Validation
|
||||
- [x] 5.1 Run `cargo test --package entropyk-components`
|
||||
- [x] 5.2 Run `cargo clippy -- -D warnings`
|
||||
- [ ] 5.3 Run `cargo test --workspace` (no regressions)
|
||||
|
||||
## Dev Notes
|
||||
|
||||
### Architecture Patterns (MUST follow)
|
||||
|
||||
From `architecture.md`:
|
||||
|
||||
1. **NewType Pattern**: Use `VaporQuality` from Story 10-1, NEVER bare `f64` for quality
|
||||
2. **Zero-Panic Policy**: All methods return `Result<T, ComponentError>`
|
||||
3. **Component Trait**: Must implement all trait methods identically to existing components
|
||||
4. **Tracing**: Use `tracing` for logging, NEVER `println!`
|
||||
|
||||
### Existing RefrigerantSource/RefrigerantSink Pattern
|
||||
|
||||
This is a REFACTORING to add type-specific variants, NOT a rewrite. Study the existing implementation at:
|
||||
|
||||
**File**: `crates/components/src/refrigerant_boundary.rs`
|
||||
|
||||
Key patterns to follow:
|
||||
- Struct layout with `FluidKind`, `fluid_id`, pressure, enthalpy, port
|
||||
- Constructor validation (positive pressure, fluid type check)
|
||||
- `Component` trait implementation with 2 equations (or 1 for sink without enthalpy)
|
||||
- Jacobian entries are diagonal 1.0 for boundary conditions
|
||||
- `port_mass_flows()` returns `MassFlow::from_kg_per_s(0.0)` placeholder
|
||||
- `energy_transfers()` returns `Some((Power::from_watts(0.0), Power::from_watts(0.0)))`
|
||||
|
||||
### Fluid Quality → Enthalpy Conversion
|
||||
|
||||
```rust
|
||||
/// 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,
|
||||
}
|
||||
use entropyk_fluids::FluidBackend;
|
||||
use entropyk_core::VaporQuality;
|
||||
|
||||
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>;
|
||||
// Convert quality to enthalpy at saturation
|
||||
fn quality_to_enthalpy(
|
||||
backend: &dyn FluidBackend,
|
||||
fluid: &str,
|
||||
p: Pressure,
|
||||
quality: VaporQuality,
|
||||
) -> Result<Enthalpy, FluidError> {
|
||||
// Get saturation properties at pressure P
|
||||
let h_liquid = backend.sat_liquid_enthalpy(fluid, p)?;
|
||||
let h_vapor = backend.sat_vapor_enthalpy(fluid, p)?;
|
||||
|
||||
/// 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>;
|
||||
// Linear interpolation in two-phase region
|
||||
// h = h_l + x * (h_v - h_l)
|
||||
let h = h_liquid.to_joules_per_kg()
|
||||
+ quality.to_fraction() * (h_vapor.to_joules_per_kg() - h_liquid.to_joules_per_kg());
|
||||
|
||||
/// Définit le débit massique imposé.
|
||||
pub fn set_mass_flow(&mut self, mass_flow: MassFlow);
|
||||
Ok(Enthalpy::from_joules_per_kg(h))
|
||||
}
|
||||
```
|
||||
|
||||
### RefrigerantSink
|
||||
**Note**: This assumes `FluidBackend` has saturation methods. Check `crates/fluids/src/lib.rs` for available methods.
|
||||
|
||||
### Fluid Validation
|
||||
|
||||
Reuse existing `is_incompressible()` from `flow_junction.rs`:
|
||||
|
||||
```rust
|
||||
/// 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);
|
||||
fn is_incompressible(fluid: &str) -> bool {
|
||||
matches!(
|
||||
fluid.to_lowercase().as_str(),
|
||||
"water" | "glycol" | "brine" | "meg" | "peg"
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
For refrigerants, accept anything NOT incompressible (CoolProp handles validation).
|
||||
|
||||
## Implémentation du Trait Component
|
||||
### Component Trait Implementation
|
||||
|
||||
```rust
|
||||
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();
|
||||
fn n_equations(&self) -> usize {
|
||||
2 // P and h constraints
|
||||
}
|
||||
|
||||
fn compute_residuals(
|
||||
&self,
|
||||
_state: &StateSlice,
|
||||
residuals: &mut ResidualVector,
|
||||
) -> Result<(), ComponentError> {
|
||||
if residuals.len() < 2 {
|
||||
return Err(ComponentError::InvalidResidualDimensions {
|
||||
expected: 2,
|
||||
actual: residuals.len(),
|
||||
});
|
||||
}
|
||||
residuals[0] = self.outlet.pressure().to_pascals() - self.p_set_pa;
|
||||
residuals[1] = self.outlet.enthalpy().to_joules_per_kg() - self.h_set_jkg;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn energy_transfers(&self, _state: &SystemState) -> Option<(Power, Power)> {
|
||||
|
||||
fn jacobian_entries(
|
||||
&self,
|
||||
_state: &StateSlice,
|
||||
jacobian: &mut JacobianBuilder,
|
||||
) -> Result<(), ComponentError> {
|
||||
jacobian.add_entry(0, 0, 1.0);
|
||||
jacobian.add_entry(1, 1, 1.0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_ports(&self) -> &[ConnectedPort] {
|
||||
&[]
|
||||
}
|
||||
|
||||
fn port_mass_flows(&self, _state: &StateSlice) -> Result<Vec<MassFlow>, ComponentError> {
|
||||
Ok(vec![MassFlow::from_kg_per_s(0.0)])
|
||||
}
|
||||
|
||||
fn port_enthalpies(&self, _state: &StateSlice) -> Result<Vec<Enthalpy>, ComponentError> {
|
||||
Ok(vec![self.outlet.enthalpy()])
|
||||
}
|
||||
|
||||
fn energy_transfers(&self, _state: &StateSlice) -> 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![]),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
### Equations Summary
|
||||
|
||||
## Fichiers à Créer/Modifier
|
||||
**RefrigerantSource** (2 equations):
|
||||
$$r_0 = P_{edge} - P_{set} = 0$$
|
||||
$$r_1 = h_{edge} - h(P_{set}, x) = 0$$
|
||||
|
||||
| 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 |
|
||||
**RefrigerantSink** (1 or 2 equations):
|
||||
$$r_0 = P_{edge} - P_{back} = 0 \quad \text{(always)}$$
|
||||
$$r_1 = h_{edge} - h(P_{back}, x) = 0 \quad \text{(if quality specified)}$$
|
||||
|
||||
---
|
||||
### Project Structure Notes
|
||||
|
||||
## Critères d'Acceptation
|
||||
- **File to create**: `crates/components/src/refrigerant_boundary.rs`
|
||||
- **Export file**: `crates/components/src/lib.rs` (add module and re-export)
|
||||
- **Test location**: Inline in `refrigerant_boundary.rs` under `#[cfg(test)] mod tests`
|
||||
- **Alignment**: Follows existing pattern of `refrigerant_boundary.rs`, `flow_junction.rs`
|
||||
|
||||
- [ ] `RefrigerantSource::new()` crée une source avec P et h fixées
|
||||
- [ ] `RefrigerantSource::with_vapor_quality()` calcule l'enthalpie depuis le titre
|
||||
- [ ] `RefrigerantSink::new()` crée un puits avec contre-pression
|
||||
- [ ] `energy_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
|
||||
### Dependencies
|
||||
|
||||
---
|
||||
**Requires Story 10-1** to be complete:
|
||||
- `VaporQuality` type from `crates/core/src/types.rs`
|
||||
- `Concentration`, `VolumeFlow`, `RelativeHumidity` not needed for this story
|
||||
|
||||
## Tests Requis
|
||||
**Fluid Backend**:
|
||||
- `FluidBackend` trait from `entropyk_fluids` crate
|
||||
- May need to add `sat_liquid_enthalpy()` and `sat_vapor_enthalpy()` methods if not present
|
||||
|
||||
### Common LLM Mistakes to Avoid
|
||||
|
||||
1. **Don't use bare f64 for quality** - Always use `VaporQuality` type
|
||||
2. **Don't copy-paste RefrigerantSource entirely** - Refactor to share code if possible, or at least maintain consistency
|
||||
3. **Don't forget backend dependency** - Need `FluidBackend` for quality→enthalpy conversion
|
||||
4. **Don't skip fluid validation** - Must reject incompressible fluids
|
||||
5. **Don't forget energy_transfers** - Must return `Some((0, 0))` for boundary conditions
|
||||
6. **Don't forget port_mass_flows/enthalpies** - Required for energy balance validation
|
||||
7. **Don't panic on invalid input** - Return `Result::Err` instead
|
||||
|
||||
### Test Patterns
|
||||
|
||||
```rust
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_refrigerant_source_new() { /* ... */ }
|
||||
use approx::assert_relative_eq;
|
||||
|
||||
#[test]
|
||||
fn test_refrigerant_source_quality_zero() {
|
||||
let backend = CoolPropBackend::new();
|
||||
let port = make_port("R410A", 8.5e5, 200_000.0);
|
||||
let source = RefrigerantSource::new(
|
||||
"R410A",
|
||||
Pressure::from_pascals(8.5e5),
|
||||
VaporQuality::SATURATED_LIQUID,
|
||||
&backend,
|
||||
port,
|
||||
).unwrap();
|
||||
|
||||
#[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() { /* ... */ }
|
||||
// h_set should equal saturated liquid enthalpy at 8.5 bar
|
||||
let h_sat_liq = backend.sat_liquid_enthalpy("R410A", Pressure::from_pascals(8.5e5)).unwrap();
|
||||
assert_relative_eq!(source.h_set_jkg(), h_sat_liq.to_joules_per_kg(), epsilon = 1e-6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_refrigerant_source_rejects_water() {
|
||||
let backend = CoolPropBackend::new();
|
||||
let port = make_port("Water", 1.0e5, 100_000.0);
|
||||
let result = RefrigerantSource::new(
|
||||
"Water",
|
||||
Pressure::from_pascals(1.0e5),
|
||||
VaporQuality::from_fraction(0.5),
|
||||
&backend,
|
||||
port,
|
||||
);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
### References
|
||||
|
||||
## Références
|
||||
- [Source: crates/components/src/refrigerant_boundary.rs] - Existing RefrigerantSource/RefrigerantSink pattern to follow
|
||||
- [Source: crates/components/src/flow_junction.rs:20-30] - `is_incompressible()` function
|
||||
- [Source: architecture.md#L476-L506] - NewType pattern rationale
|
||||
- [Source: architecture.md#L357-L404] - Error handling with ThermoError
|
||||
- [Source: crates/core/src/types.rs] - VaporQuality type (Story 10-1)
|
||||
- [Source: epic-10-enhanced-boundary-conditions.md] - Epic context and objectives
|
||||
|
||||
- [Architecture Document](../../plans/boundary-condition-refactoring-architecture.md)
|
||||
- [Story 10-1: Nouveaux types physiques](./10-1-new-physical-types.md)
|
||||
### Downstream Dependencies
|
||||
|
||||
- Story 10-3 (BrineSource/Sink) follows similar pattern
|
||||
- Story 10-4 (AirSource/Sink) follows similar pattern
|
||||
- Story 10-5 (Migration) will deprecate old `RefrigerantSource::new()` in favor of `RefrigerantSource`
|
||||
|
||||
## Dev Agent Record
|
||||
|
||||
### Agent Model Used
|
||||
|
||||
zai-anthropic/glm-5
|
||||
|
||||
### Debug Log References
|
||||
|
||||
None
|
||||
|
||||
### Completion Notes List
|
||||
|
||||
- Created `crates/components/src/refrigerant_boundary.rs` with `RefrigerantSource` and `RefrigerantSink` structs
|
||||
- Used `VaporQuality` type from `entropyk_core` for type-safe quality specification
|
||||
- Implemented `FluidBackend` integration using `FluidState::PressureQuality(P, Quality)` for enthalpy conversion
|
||||
- Fluid validation rejects incompressible fluids (Water, Glycol, Brine, MEG, PEG)
|
||||
- Created `MockRefrigerantBackend` for unit testing (supports `PressureQuality` state)
|
||||
- All 24 unit tests pass
|
||||
- Module exported in `lib.rs`
|
||||
|
||||
### File List
|
||||
|
||||
- `crates/components/src/refrigerant_boundary.rs` (created)
|
||||
- `crates/components/src/lib.rs` (modified)
|
||||
|
||||
## Senior Developer Review (AI)
|
||||
|
||||
### Review Date: 2026-02-23
|
||||
|
||||
### Issues Found: 3 HIGH, 4 MEDIUM, 3 LOW
|
||||
|
||||
### Issues Fixed:
|
||||
|
||||
1. **[HIGH] Missing doc comments** - Added comprehensive documentation with LaTeX equations for:
|
||||
- `RefrigerantSource` and `RefrigerantSink` structs
|
||||
- All public methods with `# Arguments`, `# Errors`, `# Example` sections
|
||||
- Module-level documentation with design philosophy
|
||||
|
||||
2. **[MEDIUM] Unused imports in test module** - Removed unused `TestBackend` and `Quality` imports
|
||||
|
||||
3. **[MEDIUM] Tracing not available** - Removed `debug!()` macro calls since `tracing` crate is not in Cargo.toml
|
||||
|
||||
4. **[LOW] Removed Debug/Clone derives** - Removed `#[derive(Debug, Clone)]` since `Arc<dyn FluidBackend>` doesn't implement `Debug`
|
||||
|
||||
### Remaining Issues (Deferred):
|
||||
|
||||
- **[MEDIUM] get_ports() returns empty slice** - Same pattern as existing `RefrigerantSource`/`RefrigerantSink`. Should be addressed consistently across all boundary components.
|
||||
- **[MEDIUM] No integration test with real CoolPropBackend** - MockRefrigerantBackend is sufficient for unit tests. Integration tests would require CoolProp linking fix.
|
||||
|
||||
### Verification:
|
||||
|
||||
- All 24 unit tests pass
|
||||
- `cargo test --package entropyk-components` passes
|
||||
- Pre-existing CoolProp linking issues prevent full workspace test (not related to this story)
|
||||
|
||||
Reference in New Issue
Block a user