# 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 (B1–B5 in the
audit) are resolved enough to validate the implementation.
