# Phantom-Gradient Regularization Standard

Canonical toolkit for C¹ (or smoother) replacements of hard clamps, `max`/`min`,
and absolute-value kinks on Newton unknowns. Owned by Epic 0 / Story 0.2
(`epics-solver-hp.md`, FR19).

Source code: `crates/core/src/smoothing.rs` (`entropyk_core::smoothing`).

---

## Decisions

| Layer | Location | Role |
|-------|----------|------|
| **Canonical general toolkit** | `entropyk_core::smoothing` | `smooth_max` / `smooth_min` / `smooth_abs` / `smooth_clamp` (+ analytic derivatives) |
| **Reference specialized pattern** | `heat_exchanger::flow_regularization` | Mass-flow activity / duty / transport blend for zero-flow HX residuals — **not** duplicated into core |
| **Verification harness** | `entropyk_components::jacobian_fd` | Central FD vs analytic (Story 0.1); envelope CI gate Story 0.5 landed |

**Banned** in residual / Jacobian paths on Newton unknowns:

- bare `.clamp(...)` whose derivative jumps `0 ↔ 1`
- hard `.max(0)` / early `Ok(0.0)` that zeros informative physics derivatives

Physical clamp → smooth migrations:
- Story **0.3** (valve / EXV): `valve_flow.rs`, `isenthalpic_expansion_valve.rs` orifice path.
- Story **0.4** (HX consumer): `two_phase_dp` quality `smooth_clamp`, condenser fan/flood
  actuators + Jacobian chain rule, MSH Hermite blend near `x→1` verified.

DoF rule: regularization **must not** change `n_equations()`.

---

## API (core)

| Function | Continuity | Parameter |
|----------|------------|-----------|
| `smooth_max(a, b, k)` / `smooth_max_derivative` | C∞ | sharpness `k` (overshoot at equality = `k/2`) |
| `smooth_min(a, b, k)` / `smooth_min_derivative` | C∞ | same |
| `smooth_abs(x, eps)` / `smooth_abs_derivative` | C∞ | `eps` = value at `x=0` |
| `smooth_clamp(x, lo, hi, width)` / `smooth_clamp_derivative` | C¹ | transition `width` at each bound |
| `smoothstep` / `cubic_blend` / `quintic_blend` (+ derivatives) | C¹ / C² | correlation transition windows |

Degenerate parameters never panic: `k <= 0` → hard max/min; `eps <= 0` → hard `|x|`;
`width <= 0` or inverted bounds → hard clamp (bounds swapped if needed).

---

## ε / width selection guidance

| Primitive | Parameter | Physical meaning | Rule of thumb |
|-----------|-----------|------------------|---------------|
| `smooth_abs` | `eps` | Blend half-width; value at origin | ~1% of characteristic `\|x\|`, or smaller if the kink is far from the operating region |
| `smooth_max` / `smooth_min` | `k` | Softness; overshoot at equality = `k/2` | `k ≪ \|a − b\|` where you need the hard extremum; never large enough to shift equilibrium |
| `smooth_clamp` | `width` | Transition length at each bound | Prefer `width ≤ (hi − lo) / 2`. Keep Newton-visible band physically small |
| `flow_activity` | `m_eps` | Mass-flow activity scale | Keep HX default `DEFAULT_M_EPS_KG_S = 1e-4` (see [flow-regularization.md](./flow-regularization.md)) |

### Recommended starting widths (examples only)

| Quantity | Interval | Suggested `width` |
|----------|----------|-------------------|
| Valve / EXV opening | `[0, 1]` | `1e-3` … `1e-2` |
| Thermodynamic quality | `[0, 1]` | `1e-3` … `1e-2` |
| Fan actuator | `[0, 1.5]` | `~1e-2` |
| Flood level | `[0, 0.98]` | `~1e-2` (respect `width ≤ (hi−lo)/2`) |

Always pair value and derivative in both `compute_residuals` and `jacobian_entries`
(`smooth_clamp` + `smooth_clamp_derivative`, etc.).

---

## Relationship to flow regularization

`crates/components/src/heat_exchanger/flow_regularization.rs` is the **reference
implementation** for zero-flow-safe HX residuals. It builds on
`entropyk_core::smoothing::smooth_abs` and stays in `entropyk-components` because
it encodes residual units (watts) and characteristic mass-flow scales
(`m_scale`) that are HX-specific.

Do **not** move `flow_activity` / `blend_transport_residual` into core.
Do **not** invent a second smoothing module under `components/`.

Details: [flow-regularization.md](./flow-regularization.md).

---

## Verification

- Unit / FD continuity tests: `crates/core/src/smoothing.rs` (`#[cfg(test)]`).
- Component Jacobian health: `check_jacobian_health` (Story 0.1 audit harness).
- Envelope CI gate: Story **0.5 landed** — `cargo test -p entropyk-components --test jacobian_health_sweep` (see [`../audits/jacobian-health-report.md`](../audits/jacobian-health-report.md)).
