Files
Entropyk/docs/adr/ADR-0001-multi-circuit-heat-exchanger-architecture.md
sepehr 5bd180b5b8
Some checks failed
CI / check (push) Has been cancelled
Snapshot WIP: solver HP epic progress, BPHX/HX physics, BMAD skill refresh.
Capture uncommitted solver robustness work (regularization, domain errors, linear solver lifecycle, tube DP/MSH), web workbench updates, and synced BMAD skills across IDE agent folders before starting BPHX pressure-drop.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-19 16:35:31 +02:00

149 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-0001: Multi-Circuit Heat-Exchanger Architecture (DRAFT — Phase A)
**Status:** Proposed (draft produced during Phase A audit)
**Date:** 2026-07-16
**Decider:** Sepehr (architect review pending)
**Supersedes:** none
**Related:** `docs/audits/heat_exchanger_architecture_audit.md` (2026-07-16),
`docs/audits/montluel_machine_coverage.md` (2026-07-16)
## Context
The Phase A audit established that Entropyk has **no shared-vessel / multi-circuit
heat-exchanger primitive**:
- `FloodedEvaporator` is single-circuit (one inlet edge, one outlet edge;
`flooded_evaporator.rs:57`).
- The solver **rejects cross-circuit edges** (`TopologyError::CrossCircuitConnection`;
`multi_circuit.rs:111`), so two refrigerant circuits cannot share a fluid volume.
- The only inter-circuit heat mechanism is `ThermalCoupling` (`coupling.rs:52`), which
transfers **duty via an external Q unknown**, not a shared volume.
- `tests/multi_circuit.rs` validates only topology bookkeeping with zero-returning mocks —
it does **not** test shared-vessel thermodynamics.
Carrier reference (mission §5.1) describes a shared-vessel flooded evaporator
(`61XWHVZE`-class): one vessel, two independent refrigerant circuits separated by an
intermediate tube sheet, one common water circuit, standard 2-pass water with 1-/3-pass
options. This topology cannot be represented today. Product geometry was **not provided**;
this ADR fixes the architecture, not the fixture data.
The audit also confirmed four reusable assets that constrain the design:
`correlation_registry.rs` (evidence-aware registry), `bphx_geometry.rs` (typed geometry
pattern), `bphx_correlation.rs` (formula↔registry binding), `two_phase_dp.rs` (analytic DP),
and `entropyk_core::smoothing` (C¹/C² regularization with derivatives).
## Decision (proposed)
Adopt a **dedicated multi-circuit exchanger component** with a shared secondary path,
built on the existing registry/geometry/correlation pattern, rather than overloading the
single-circuit component or faking a shared vessel with `ThermalCoupling`.
### 1. New component: `MultiCircuitFloodedEvaporator`
```rust
pub struct MultiCircuitFloodedEvaporator {
geometry: ShellAndTubeGeometry, // new typed geometry (Phase B)
circuits: Vec<FloodedCircuit>, // N >= 1
secondary: SharedSecondaryPath,
sizing: HeatExchangerSizing, // NominalUa | GeometryRated | CalibratedGeometry
control: FloodedEvaporatorControl, // replaces target_quality=0.7 default
calibration: MultiCircuitCalibration,
}
```
- Refrigerant mass/energy conserved **independently per circuit** (no A↔B mixing).
- Common secondary energy balance = `Σ Q_circuit`.
- An OFF circuit has zero refrigerant flow and zero duty but does **not** make the active
circuit singular (zero-flow-safe residuals, mission §7).
- Allocated heat-transfer area follows physical partitioning.
### 2. New domain types (Phase B prerequisites, in `entropyk-core`)
`Length`, `Mass`, `Area`, `TemperatureDifference`, `ThermalConductivity`, `Volume` (currently
absent — audit §1.5). Plus `ShellAndTubeGeometry`, `RefrigerantPartition`,
`TubeEnhancement`, `WaterBoxGeometry`, `FoulingResistances` (in `components`), validated per
mission §6.1/§12.1.
### 3. Secondary layout is explicit and configurable
```rust
pub enum SharedSecondaryLayout { CommonMixed, SequentialPartitions{..}, ParallelPartitions{..} }
```
The water path through refrigerant partitions is **not** chosen for Carrier equipment
without evidence (audit; mission §6.4). Default to configurable; flag required product input.
### 4. Control semantics corrected (mission §3)
Replace the `target_quality = 0.7` default with an explicit enum:
`FloodedEvaporatorControl::{FixedLevel, Pinch, OutletSuperheat, FixedRefrigerantCharge,
External}`. The outlet port's physical meaning (suction vs. recirculation vs. separator
inlet) is documented per variant. A legacy quality-control mode is retained only behind a
documented migration flag (audit §3.1).
### 5. Zero-flow handling via smooth blending (mission §7.2)
Build on `entropyk_core::smoothing` (`smooth_abs`, `cubic_blend`, `smooth_max`). No hard
`if |m| < ε { Q = 0 }` branches. Analytic derivatives verified at `m = 0`, near-zero, and
normal flow. Pressure drop uses a regularized odd function of flow.
### 6. Jacobian
Analytic throughout, including the zero-flow blending and `dT_sat/dP`. Because the backend
exposes no `dT_sat/dP` (audit §7), add a single documented central-FD backend method
`saturation_temperature_derivative_dp` (cacheable) as the single source of truth, with an
optional CoolProp analytic-derivative upgrade later.
### 7. Correlations via the existing registry
Extend `correlation_registry` + a new `shell_tube_correlation` module (pool boiling
Cooper/Gorenflo baseline; tube-bundle condensation; Gnielinski water-side; Darcy-Weisbach +
water-box minor losses). **Do not** apply internal-flow boiling correlations to shell-side
flooded boiling without documented justification (mission §6.2).
## Alternatives considered
- **A. Overload single-circuit `FloodedEvaporator` with two refrigerant port pairs.**
Rejected: breaks the edge model (solver rejects cross-circuit edges), conflates suction
outlet with shared-volume representation, and cannot guarantee independent A/B mass
conservation.
- **B. Compose two `FloodedEvaporator`s + a `ThermalCoupling`.** Rejected as the *primary*
model: `ThermalCoupling` transfers duty, not a shared water inventory; the common water
energy balance and shared geometry/partitioning would be lost. This composition remains
valid for **dual-module** machines (mission §5.2, separate modules) — handled in Phase E.
- **C. Defer to a generic N-port exchanger.** Rejected: the shared-vessel physics (common
secondary, partitioned area, flooded boiling) is specific enough to deserve a typed
component; a generic N-port wrapper would re-introduce the current ambiguities.
## Consequences
- **Positive:** unblocks Montluel archetypes M2, M4-dual, M12; enables circuit-specific
calibration and one-circuit-off operation; aligns flooded exchangers with the
registry/geometry pattern already proven for BPHX.
- **Negative:** new public API surface (migration path required — `from_nominal_ua` helper);
larger equation count per component (residual scaling needed — mission §9.5); requires the
Phase B geometry/correlation foundations first.
- **Risk:** zero-flow blending Jacobian correctness — mitigated by Jacobian-vs-FD parity
tests across all modes (mission §9.4) as a hard gate.
## Open questions (block finalization)
1. Carrier water-path layout through refrigerant partitions (drives `SharedSecondaryLayout`
default) — **data not provided**.
2. Whether a legacy `target_quality` control mode has any real supported use case (mission
§3.6) — needs Sepehr's confirmation before deprecation.
3. CoolProp analytic-derivative wiring priority vs. central-FD fallback sufficiency.
## Phasing
- Phase B: domain types + geometry + correlation extension + `dT_sat/dP` method +
zero-flow regularization utility.
- Phase C: single-circuit `FloodedEvaporator` rewrite (rating vs coupled, geometry UA,
control semantics, zero-flow-safe analytic Jacobian, migration).
- Phase D: `MultiCircuitFloodedEvaporator` + shared secondary + one-circuit-off.
- Phase E: dual-module composition (alternative B, for separate modules) + dual-circuit BPHX.
- Phase F: CLI/bindings/examples/fixtures + validation.
This ADR is **draft** until architect review and until the Phase A blockers (B1B5 in the
audit) are resolved enough to validate the implementation.