chore: sync project state and current artifacts

This commit is contained in:
Sepehr
2026-02-22 23:27:31 +01:00
parent 1b6415776e
commit dd77089b22
232 changed files with 37056 additions and 4296 deletions

View File

@@ -0,0 +1,277 @@
# Story 1.8: Auxiliary & Transport Components
Status: ready-for-dev
## Story
As a system integrator,
I want to model Pumps, VFDs, and Pipes with complete HVAC transport components,
So that I can simulate complete HVAC systems with water, glycol, and air circuits.
## Acceptance Criteria
1. **Pump Component** (AC: #1) ✅ IMPLEMENTED
- [x] Pump with polynomial performance curves (head, efficiency)
- [x] Affinity laws for variable speed operation (Q ∝ N, H ∝ N², P ∝ N³)
- [x] Component trait implementation with compute_residuals, jacobian_entries
- [x] StateManageable trait (ON/OFF/BYPASS states)
- [x] Hydraulic power calculation: P = Q × ΔP / η
2. **Pipe Component** (AC: #2) ✅ IMPLEMENTED
- [x] Darcy-Weisbach pressure drop calculation
- [x] Haaland friction factor (laminar + turbulent)
- [x] `for_incompressible()` and `for_refrigerant()` constructors
- [x] PipeGeometry with roughness constants
- [x] Calib (f_dp) for calibration
- [x] Component and StateManageable traits
3. **Fan Component** (AC: #3) ✅ IMPLEMENTED
- [x] Fan with polynomial performance curves (static pressure, efficiency)
- [x] Affinity laws for variable speed operation
- [x] Static pressure and total pressure (with velocity pressure)
- [x] Component and StateManageable traits
4. **VFD Abstraction** (AC: #4) 🔴 NOT IMPLEMENTED
- [ ] Create Vfd component that wraps Pump/Fan/Compressor
- [ ] Vfd exposes speed_ratio as controllable parameter
- [ ] Vfd implements Component trait (delegates to wrapped component)
- [ ] Vfd speed is bounded [0.0, 1.0] for inverse control
5. **Integration Tests** (AC: #5) ⚠️ PARTIAL
- [x] Pump unit tests (20+ tests in pump.rs)
- [x] Pipe unit tests (25+ tests in pipe.rs)
- [x] Fan unit tests (15+ tests in fan.rs)
- [ ] VFD integration tests
- [ ] Full circuit simulation with Pump + Pipe + VFD
## Tasks / Subtasks
- [x] Pump Implementation (AC: #1)
- [x] Create PumpCurves struct with quadratic/cubic curves
- [x] Implement AffinityLaws scaling in pump.rs
- [x] Add Component trait for Pump<Connected>
- [x] Add StateManageable trait for Pump<Connected>
- [x] Implement compute_residuals with ON/OFF/BYPASS handling
- [x] Write 20+ unit tests
- [x] Pipe Implementation (AC: #2)
- [x] Create PipeGeometry struct with roughness constants
- [x] Implement Darcy-Weisbach equation
- [x] Implement Haaland friction factor
- [x] Add `for_incompressible()` and `for_refrigerant()` constructors
- [x] Add Component and StateManageable traits
- [x] Write 25+ unit tests
- [x] Fan Implementation (AC: #3)
- [x] Create FanCurves struct with polynomial curves
- [x] Implement static_pressure_rise and total_pressure_rise
- [x] Add Component and StateManageable traits
- [x] Write 15+ unit tests
- [ ] VFD Abstraction (AC: #4)
- [ ] Create Vfd<T> generic wrapper in new file vfd.rs
- [ ] Implement Vfd::new(wrapped_component, initial_speed)
- [ ] Implement speed() and set_speed() methods
- [ ] Implement Component trait (delegates to wrapped)
- [ ] Implement BoundedVariable for speed [0.0, 1.0]
- [ ] Write unit tests for Vfd
- [ ] Integration Tests (AC: #5)
- [ ] Test Pump + Pipe circuit
- [ ] Test Fan in air handling system
- [ ] Test Vfd controlling Pump speed
## Dev Notes
### 🔥 CRITICAL: Most Components Already Implemented!
**This story is mostly COMPLETE.** The following components already exist:
| Component | File | Lines | Tests | Status |
|-----------|------|-------|-------|--------|
| Pump | `pump.rs` | 780 | 20+ | ✅ Done |
| Pipe | `pipe.rs` | 1010 | 25+ | ✅ Done |
| Fan | `fan.rs` | 636 | 15+ | ✅ Done |
| Polynomials | `polynomials.rs` | 702 | 15+ | ✅ Done |
| **VFD** | - | - | - | 🔴 **Not Implemented** |
### Remaining Work: VFD Abstraction
The only missing piece is the **VFD (Variable Frequency Drive)** abstraction. Currently:
- Pump, Fan have `speed_ratio` field (0.0 to 1.0)
- `set_speed_ratio()` method exists
- But no Vfd component that wraps these for inverse control
### VFD Implementation Approach
**Option A: Wrapper Component (Recommended)**
```rust
pub struct Vfd<T: Component> {
wrapped: T,
speed: BoundedVariable, // [0.0, 1.0]
}
```
- Wraps Pump, Fan, or Compressor
- Delegates Component trait methods
- Exposes speed as BoundedVariable for inverse control
**Option B: Trait-based Approach**
```rust
pub trait SpeedControllable: Component {
fn speed_ratio(&self) -> f64;
fn set_speed_ratio(&mut self, ratio: f64) -> Result<(), ComponentError>;
}
```
- Pump, Fan, Compressor implement this trait
- Vfd uses dynamic dispatch
### Architecture Context
**FR Coverage:**
- FR6-FR8: Component states ON/OFF/BYPASS ✅
- FR40: Incompressible fluids support (via `for_incompressible`) ✅
**Component Trait Pattern:**
All components follow the same pattern:
```rust
impl Component for Xxx<Connected> {
fn compute_residuals(&self, state: &SystemState, residuals: &mut ResidualVector) -> Result<(), ComponentError>;
fn jacobian_entries(&self, state: &SystemState, jacobian: &mut JacobianBuilder) -> Result<(), ComponentError>;
fn n_equations(&self) -> usize;
fn get_ports(&self) -> &[ConnectedPort];
}
impl StateManageable for Xxx<Connected> {
fn state(&self) -> OperationalState;
fn set_state(&mut self, state: OperationalState) -> Result<(), ComponentError>;
// ...
}
```
### Pump Details
**Performance Curves:**
```
Head: H = a₀ + a₁Q + a₂Q² + a₃Q³
Efficiency: η = b₀ + b₁Q + b₂Q²
Power: P_hydraulic = ρ × g × Q × H / η
```
**Affinity Laws (implemented in polynomials.rs):**
```rust
AffinityLaws::scale_flow(flow, speed_ratio) // Q₂ = Q₁ × (N₂/N₁)
AffinityLaws::scale_head(head, speed_ratio) // H₂ = H₁ × (N₂/N₁)²
AffinityLaws::scale_power(power, speed_ratio) // P₂ = P₁ × (N₂/N₁)³
```
### Pipe Details
**Darcy-Weisbach Equation:**
```
ΔP = f × (L/D) × (ρ × v² / 2)
```
**Haaland Friction Factor:**
```
1/√f = -1.8 × log10[(ε/D/3.7)^1.11 + 6.9/Re]
```
**Roughness Constants (pipe.rs:roughness):**
```rust
SMOOTH: 1.5e-6 // Copper, plastic
STEEL_COMMERCIAL: 4.5e-5
GALVANIZED_IRON: 1.5e-4
CAST_IRON: 2.6e-4
CONCRETE: 1.0e-3
PLASTIC: 1.5e-6
```
**Zero-Flow Regularization:**
- Re clamped to MIN_REYNOLDS = 1.0 (prevents division by zero)
- Consistent with Story 3.5 zero-flow branch handling
### Fan Details
**Standard Air Properties (fan.rs:standard_air):**
```rust
DENSITY: 1.204 kg/m³ // at 20°C, 101325 Pa
CP: 1005.0 J/(kg·K)
```
**Total Pressure:**
```
P_total = P_static + P_velocity = P_static + ½ρ
```
### File Locations
```
crates/components/src/
├── pump.rs # ✅ DONE - 780 lines
├── pipe.rs # ✅ DONE - 1010 lines
├── fan.rs # ✅ DONE - 636 lines
├── polynomials.rs # ✅ DONE - 702 lines
├── vfd.rs # 🔴 TODO - NEW FILE
└── lib.rs # Add pub mod vfd; and re-exports
```
### Testing Requirements
**Existing Tests (do not modify):**
- `pump.rs`: 20+ unit tests covering curves, affinity laws, residuals
- `pipe.rs`: 25+ unit tests covering geometry, friction, pressure drop
- `fan.rs`: 15+ unit tests covering curves, pressure, power
**New Tests Required for VFD:**
- Vfd creation and wrapping
- Speed bounds enforcement
- Component trait delegation
- Integration: Vfd + Pump circuit
### Common Pitfalls to Avoid
- ❌ Do NOT reimplement Pump, Pipe, Fan - they are complete
- ❌ Do NOT use bare f64 for physical quantities
- ❌ Do NOT use unwrap/expect in production code
- ❌ Do NOT break existing tests
- ❌ Ensure Vfd is object-safe (if using trait objects)
### References
- **FR6-FR8:** Operational states ON/OFF/BYPASS [Source: epics.md#Story 1.7]
- **FR40:** Incompressible fluids support [Source: epics.md#Story 2.7]
- **Component Model:** Trait-based with Type-State [Source: architecture.md#Component Model]
- **Zero-Panic Policy:** Result<T, ThermoError> [Source: architecture.md#Error Handling Strategy]
- **Story 1.7:** StateManageable trait (implemented in Pump, Pipe, Fan)
- **Story 3.5:** Zero-flow branch handling (implemented in pipe.rs)
### Previous Story Intelligence
**From Story 1.7 (Component State Machine):**
- StateManageable trait with state(), set_state(), can_transition_to()
- OperationalState enum: On, Off, Bypass
- State history for debugging
- All implemented correctly in Pump, Pipe, Fan
**From Story 4.2 (Newton-Raphson):**
- Components provide jacobian_entries()
- Pump, Pipe, Fan already provide numerical Jacobians
**From Story 5.2 (Bounded Control Variables):**
- BoundedVariable with clip_step()
- Vfd speed should use BoundedVariable for inverse control
## Dev Agent Record
### Agent Model Used
{{agent_model_name_version}}
### Debug Log References
### Completion Notes List
### File List
- `crates/components/src/vfd.rs` - NEW: Vfd wrapper component
- `crates/components/src/lib.rs` - Add vfd module and re-exports