# Story 7.1: mass-balance-validation

Status: done

<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->

## Story

As a simulation engineer,
I want automatic mass conservation verification,
so that I trust physical correctness of the system simulation.

## Acceptance Criteria

1. **Given** converged solution **When** computing mass balance **Then** error Σ ṁ_in - Σ ṁ_out < 1e-9 kg/s
2. **Given** converged solution **When** computing mass balance **Then** violations trigger a validation error
3. **Given** converged solution **When** computing mass balance **Then** check performed after every solve

## Tasks / Subtasks

- [x] Task 1: Add Mass Balance Method (AC: 1, 3)
  - [x] Add a `check_mass_balance` method to `System` (or similar orchestrator).
  - [x] Method should iterate through all nodes/components and verify that the sum of mass flows leaving equals the sum of mass flows entering.
  - [x] Establish `1e-9` kg/s as the threshold for mass balance violation.
- [x] Task 2: Validation Error Definition (AC: 2)
  - [x] Ensure `ThermoError::Validation { mass_error: f64, energy_error: f64 }` exists in `crates/core/src/errors.rs` (ensure it handles isolated mass error check or create a specific mass validation error variant if suitable, though PRD says `Validation { mass_error, energy_error }`).
- [x] Task 3: Hook into Solver (AC: 3)
  - [x] Update `solve` / `solve_with_fallback` in `crates/solver/src/lib.rs` (or relevant logic) to perform the mass balance check after convergence.
  - [x] Return the validation error if criteria are not met.
- [x] Task 4: Unit Testing
  - [x] Implement tests in `tests/validation/energy_balance.rs` or `crates/solver/src/system.rs` for a system that converges successfully to verify validation passes.
  - [x] Add a mock case where mass balance fails to verify error is raised.

## Dev Notes

### Architecture Patterns & Constraints
- **Zero-Panic Policy**: Return `ThermoError::Validation` if mass balance fails. Never panic.
- **Scientific Testing Patterns**: Use `approx::assert_relative_eq!(..., epsilon = 1e-9)` for testing mass tolerance.
- **Physical Types (NewType Pattern)**: Remember to handle `MassFlow(f64)` unwrapping properly when computing sums or errors.
- **Error Handling Strategy**: Use existing `ThermoError` in `crates/core/src/errors.rs`.
- Do not add dynamic allocations in the checks if they run in hot paths, although this runs strictly *after* convergence, so it's less critical but ideally iterate over existing graph structure without allocating new vectors.

### Source Tree Components to Touch
- `crates/core/src/errors.rs` (if `ThermoError::Validation` needs tweaking)
- `crates/solver/src/system.rs` (for `check_mass_balance` logic)
- `crates/solver/src/strategies/mod.rs` or `fallback.rs` (to call validation logic post-solve)
- `tests/validation/` (to add validation check tests)

### Testing Standards Summary
- Use `approx` crate with explicit tolerance `1e-9` kg/s.
- `cargo clippy -- -D warnings` must pass.
- `cargo test --workspace` must pass.

### References
- [Source: _bmad-output/planning-artifacts/epics.md#Epic-7] - Epic 7 Requirements and Story 7.1
- [Source: _bmad-output/planning-artifacts/architecture.md#Error-Handling-Strategy] - Error Handling
- [Source: _bmad-output/planning-artifacts/architecture.md#Scientific-Testing-Patterns] - Testing Patterns definition

## Dev Agent Record

### Agent Model Used

BMad Create Story Workflow

### Debug Log References

### Completion Notes List
- Implemented `port_mass_flows` for all core components to standardize mass flow retrieval.
- Integrated `check_mass_balance` into `System` and hooked it into the `SolverStrategy::solve` entry point.
- Updated `thermo_error_to_pyerr` and C error mappings to handle the new `Validation` error type.
- Fixed severe architectural issue in integration tests where `connect` methods were missing, by implementing them for `ExpansionValve`, `Compressor`, and `Pipe`.
- Verified violation detection with passing unit test `test_mass_balance_violation`.

### File List
- crates/entropyk/src/error.rs (Validation error variant)
- crates/components/src/lib.rs (port_mass_flows trait method)
- crates/components/src/compressor.rs (port_mass_flows implementation)
- crates/components/src/expansion_valve.rs (port_mass_flows implementation)
- crates/components/src/pipe.rs (port_mass_flows implementation)
- crates/components/src/pump.rs (port_mass_flows implementation)
- crates/components/src/fan.rs (port_mass_flows implementation)
- crates/components/src/refrigerant_boundary.rs (port_mass_flows for RefrigerantSource, RefrigerantSink)
- crates/components/src/flow_junction.rs (port_mass_flows for FlowSplitter, FlowMerger)
- crates/components/src/heat_exchanger/evaporator.rs (delegation to inner)
- crates/components/src/heat_exchanger/evaporator_coil.rs (delegation to inner)
- crates/components/src/heat_exchanger/condenser.rs (delegation to inner)
- crates/components/src/heat_exchanger/condenser_coil.rs (delegation to inner)
- crates/components/src/heat_exchanger/economizer.rs (delegation to inner)
- crates/components/src/heat_exchanger/exchanger.rs (port_mass_flows base implementation)
- crates/solver/src/solver.rs (post-solve validation hook)
- crates/solver/src/system.rs (check_mass_balance method, tests, logging)
- bindings/python/src/errors.rs (ValidationError mapping)

### Review Follow-ups (AI)
- [x] [AI-Review][HIGH] Implement `port_mass_flows` for remaining components: RefrigerantSource, RefrigerantSink, Pump, Fan, Evaporator, Condenser, CondenserCoil, EvaporatorCoil, Economizer, FlowSplitter, FlowMerger
- [x] [AI-Review][MEDIUM] Add integration test with full refrigeration cycle to verify mass balance validation end-to-end
