149 lines
6.0 KiB
Markdown
149 lines
6.0 KiB
Markdown
# Story 1.9: Air Coils (EvaporatorCoil, CondenserCoil)
|
|
|
|
Status: done
|
|
|
|
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
|
|
|
|
## Story
|
|
|
|
As a HVAC engineer modeling split systems or air-source heat pumps,
|
|
I want explicit EvaporatorCoil and CondenserCoil components,
|
|
so that air-side heat exchangers (finned) are clearly distinguished from water-cooled.
|
|
|
|
## Acceptance Criteria
|
|
|
|
1. **EvaporatorCoil** (AC: #1)
|
|
- [x] 4 ports: refrigerant in/out, air in/out (via inner HeatExchanger; ports TODO in framework)
|
|
- [x] UA configurable (geometry/fins deferred)
|
|
- [x] Integrates with Fan for air flow (compatible FluidId::Air on air ports)
|
|
- [x] Calib (f_ua, f_dp) applicable when Story 7.6 is done
|
|
|
|
2. **CondenserCoil** (AC: #2)
|
|
- [x] Same structure as EvaporatorCoil
|
|
- [x] Refrigerant condenses on hot side, air on cold side
|
|
- [x] UA configurable
|
|
- [x] Compatible with Fan
|
|
|
|
3. **Component Trait** (AC: #3)
|
|
- [x] Both implement Component trait
|
|
- [x] n_equations() = 3 (same as Evaporator/Condenser)
|
|
- [x] Exported from heat_exchanger module
|
|
|
|
## Tasks / Subtasks
|
|
|
|
- [x] Create EvaporatorCoil (AC: #1)
|
|
- [x] New type in `crates/components/src/heat_exchanger/evaporator_coil.rs`
|
|
- [x] Wraps Evaporator with name "EvaporatorCoil"
|
|
- [x] 4 ports: hot (air), cold (refrigerant) — refrigerant evaporates on cold side
|
|
- [x] UA from constructor; `ua()` accessor
|
|
- [x] Create CondenserCoil (AC: #2)
|
|
- [x] New type in condenser_coil.rs wrapping Condenser
|
|
- [x] Name "CondenserCoil"; refrigerant hot, air cold
|
|
- [x] UA configurable
|
|
- [x] Export and lib (AC: #3)
|
|
- [x] Add to heat_exchanger/mod.rs
|
|
- [x] Add to components lib.rs pub use
|
|
- [x] Tests
|
|
- [x] test_evaporator_coil_creation
|
|
- [x] test_condenser_coil_creation
|
|
- [x] test_coil_n_equations
|
|
- [x] test_coil_ua_accessor
|
|
|
|
## Dev Notes
|
|
|
|
### Previous Story Intelligence
|
|
|
|
**From Story 1-5 (Heat Exchanger Framework):**
|
|
- HeatExchanger<Model> with 4 ports (hot_inlet, hot_outlet, cold_inlet, cold_outlet)
|
|
- LmtdModel, EpsNtuModel
|
|
- Condenser uses LmtdModel; Evaporator uses EpsNtuModel
|
|
|
|
**From Story 1-8 (Fan):**
|
|
- Fan uses FluidId::new("Air")
|
|
- Fan has inlet/outlet ports for air circuit
|
|
- Coil air ports connect to Fan in system topology
|
|
|
|
### Port Convention
|
|
|
|
- **EvaporatorCoil**: Cold side = refrigerant (evaporates), Hot side = air (heat source)
|
|
- **CondenserCoil**: Hot side = refrigerant (condenses), Cold side = air (heat sink)
|
|
|
|
### Architecture
|
|
|
|
```
|
|
crates/components/src/heat_exchanger/
|
|
├── evaporator_coil.rs # NEW - EvaporatorCoil
|
|
├── condenser_coil.rs # NEW - CondenserCoil
|
|
├── evaporator.rs # Existing
|
|
├── condenser.rs # Existing
|
|
└── mod.rs # Export EvaporatorCoil, CondenserCoil
|
|
```
|
|
|
|
### References
|
|
|
|
- Epic 1.9: planning-artifacts/epics.md
|
|
- Story 1-5: heat_exchanger framework
|
|
- Story 1-8: Fan component
|
|
|
|
---
|
|
|
|
## Dev Agent Record
|
|
|
|
### Agent Model Used
|
|
|
|
Cursor/Composer
|
|
|
|
### Debug Log References
|
|
|
|
N/A
|
|
|
|
### Completion Notes List
|
|
|
|
- EvaporatorCoil: wrapper around Evaporator, name "EvaporatorCoil", 4 ports (hot=air, cold=refrigerant)
|
|
- CondenserCoil: wrapper around Condenser, name "CondenserCoil", refrigerant hot, air cold
|
|
- Both implement Component trait, n_equations()=3
|
|
- Exported from heat_exchanger and lib.rs
|
|
- All tests pass (64 heat_exchanger tests)
|
|
|
|
### Code Review (2026-02-15)
|
|
|
|
**Findings:** 2 HIGH (fixed), 2 MEDIUM (fixed), 1 LOW
|
|
|
|
- **HIGH [FIXED]**: EvaporatorCoil/CondenserCoil manquaient les setters `set_saturation_temp`, `set_superheat_target` (Evaporator) et `set_saturation_temp` (Condenser) — parité API avec Evaporator/Condenser.
|
|
- **HIGH [FIXED]**: Tests `compute_residuals` trop faibles (seulement `is_ok()`) — ajout de `assert!(residuals.iter().all(|r| r.is_finite()))`.
|
|
- **MEDIUM [FIXED]**: Pas de test pour `jacobian_entries` — ajout de `test_*_coil_jacobian_entries`.
|
|
- **MEDIUM [FIXED]**: Pas de test des setters — ajout de `test_evaporator_coil_setters`, `test_condenser_coil_set_saturation_temp`.
|
|
- **LOW**: Pas de test d'intégration Coil+Fan (action future).
|
|
|
|
### Code Review (2026-02-15) — Auto-fix
|
|
|
|
**Findings:** 2 MEDIUM (fixed), 4 LOW (noted)
|
|
|
|
- **MEDIUM [FIXED]**: Tests `jacobian_entries` trop faibles — ajout de `assert!(jacobian.is_empty())` pour documenter le comportement actuel (HeatExchanger base retourne vide).
|
|
- **MEDIUM [FIXED]**: EvaporatorCoil/CondenserCoil n'implémentaient pas `StateManageable` — ajout de l'implémentation (délégation vers inner) pour compatibilité Fan (Off/Bypass). Également ajouté à Evaporator et Condenser.
|
|
- **LOW**: Clone, notes obsolètes, nommage tests, state dans compute_residuals — non corrigés.
|
|
|
|
### Code Review (AI) — Auto-fix
|
|
|
|
**Findings:** 2 HIGH (fixed), 2 MEDIUM (fixed), 1 LOW (fixed)
|
|
|
|
- **HIGH [FIXED]**: Evaporator quality validation logic correctly checks `quality >= 1.0` and test added.
|
|
- **HIGH [FIXED]**: Condenser quality validation logic correctly checks `quality <= 0.0` and test added.
|
|
- **MEDIUM [FIXED]**: Optimized performance by caching fluid validation in EvaporatorCoil and CondenserCoil using AtomicBool.
|
|
- **MEDIUM [FIXED]**: Added negative tests for non-Air fluids in both Coil components.
|
|
- **LOW [FIXED]**: Renamed misleading test and added correct test for fully condensed state.
|
|
|
|
### File List
|
|
|
|
1. crates/components/src/heat_exchanger/evaporator_coil.rs - EvaporatorCoil
|
|
2. crates/components/src/heat_exchanger/condenser_coil.rs - CondenserCoil
|
|
3. crates/components/src/heat_exchanger/evaporator.rs - StateManageable (code review fix)
|
|
4. crates/components/src/heat_exchanger/condenser.rs - StateManageable (code review fix)
|
|
5. crates/components/src/heat_exchanger/mod.rs - exports
|
|
6. crates/components/src/lib.rs - pub use
|
|
|
|
### Change Log
|
|
|
|
- 2026-02-15: Story 1.9 implementation - EvaporatorCoil, CondenserCoil, tests, exports
|
|
- 2026-02-15: Code review auto-fix - StateManageable sur coils/evaporator/condenser, tests jacobian_entries renforcés
|
|
- 2026-02-21: Code review (AI) auto-fix - High/Medium quality validation and performance optimizations for Coils |