6.0 KiB
6.0 KiB
Story 1.9: Air Coils (EvaporatorCoil, CondenserCoil)
Status: done
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
-
EvaporatorCoil (AC: #1)
- 4 ports: refrigerant in/out, air in/out (via inner HeatExchanger; ports TODO in framework)
- UA configurable (geometry/fins deferred)
- Integrates with Fan for air flow (compatible FluidId::Air on air ports)
- Calib (f_ua, f_dp) applicable when Story 7.6 is done
-
CondenserCoil (AC: #2)
- Same structure as EvaporatorCoil
- Refrigerant condenses on hot side, air on cold side
- UA configurable
- Compatible with Fan
-
Component Trait (AC: #3)
- Both implement Component trait
- n_equations() = 3 (same as Evaporator/Condenser)
- Exported from heat_exchanger module
Tasks / Subtasks
- Create EvaporatorCoil (AC: #1)
- New type in
crates/components/src/heat_exchanger/evaporator_coil.rs - Wraps Evaporator with name "EvaporatorCoil"
- 4 ports: hot (air), cold (refrigerant) — refrigerant evaporates on cold side
- UA from constructor;
ua()accessor
- New type in
- Create CondenserCoil (AC: #2)
- New type in condenser_coil.rs wrapping Condenser
- Name "CondenserCoil"; refrigerant hot, air cold
- UA configurable
- Export and lib (AC: #3)
- Add to heat_exchanger/mod.rs
- Add to components lib.rs pub use
- Tests
- test_evaporator_coil_creation
- test_condenser_coil_creation
- test_coil_n_equations
- test_coil_ua_accessor
Dev Notes
Previous Story Intelligence
From Story 1-5 (Heat Exchanger Framework):
- HeatExchanger 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) etset_saturation_temp(Condenser) — parité API avec Evaporator/Condenser. - HIGH [FIXED]: Tests
compute_residualstrop faibles (seulementis_ok()) — ajout deassert!(residuals.iter().all(|r| r.is_finite())). - MEDIUM [FIXED]: Pas de test pour
jacobian_entries— ajout detest_*_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_entriestrop faibles — ajout deassert!(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.0and test added. - HIGH [FIXED]: Condenser quality validation logic correctly checks
quality <= 0.0and 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
- crates/components/src/heat_exchanger/evaporator_coil.rs - EvaporatorCoil
- crates/components/src/heat_exchanger/condenser_coil.rs - CondenserCoil
- crates/components/src/heat_exchanger/evaporator.rs - StateManageable (code review fix)
- crates/components/src/heat_exchanger/condenser.rs - StateManageable (code review fix)
- crates/components/src/heat_exchanger/mod.rs - exports
- 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