Files
Entropyk/_bmad-output/implementation-artifacts/0-2-phantom-gradient-regularization-standard.md
sepehr 88620790d6 Complete Story 0.2 phantom-gradient regularization standard.
Add analytic derivatives and C1 tests for smooth_max/min/clamp, document epsilon/width guidance, and declare flow_regularization as the HX reference pattern without changing component physics.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-18 16:33:48 +02:00

17 KiB
Raw Blame History

story_key, epic, story, source, baseline_commit, depends_on
story_key epic story source baseline_commit depends_on
0-2-phantom-gradient-regularization-standard 0 2 _bmad-output/planning-artifacts/epics-solver-hp.md f88cd7f7d8 0-1-jacobian-killing-pattern-audit-fd-test-harness

Story 0.2: Phantom-Gradient Regularization Standard

Status: review

Story

As a component developer, I want a standardized C¹ regularization toolkit (smooth max/min/clamp with documented ε) generalizing the existing flow_regularization.rs pattern, so that fixes are uniform and derivative-safe instead of ad-hoc.

Acceptance Criteria

  1. Core C¹ toolkit is complete, tested, and derivative-safe.

    • Given the entropyk-core crate
    • When the toolkit lands (or is completed if already present)
    • Then smooth_max / smooth_min / smooth_clamp (C¹ or smoother, parameterized sharpness/width) are available alongside existing smooth_abs, with derivative-continuity unit tests
    • And ε / width selection guidance is documented (physical scale of the blended region)
  2. flow_regularization.rs relationship is resolved without physics churn.

    • Given the existing crates/components/src/heat_exchanger/flow_regularization.rs
    • When reviewed
    • Then it is either unified into the toolkit or documented as the reference implementation for mass-flow activity / zero-flow blending
    • And no existing component behavior changes in this story (toolkit + docs only)

Tasks / Subtasks

  • Task 1: Inventory what already exists — do not reinvent (AC: #1, #2)

    • 1.1 Confirm primitives in crates/core/src/smoothing.rs: smooth_max, smooth_min, smooth_abs (+ derivative), smooth_clamp, plus smoothstep / cubic_blend family.
    • 1.2 Confirm HX-specific adapters in flow_regularization.rs already call smooth_abs — keep them in entropyk-components (domain-specific, not core).
    • 1.3 Gap check (expected at story creation):
      Gap Expected action
      No public smooth_clamp_derivative Add analytic ∂/∂x (+ FD unit test) — required by Stories 0.3/0.4 Jacobian paths
      smooth_max / smooth_min derivatives only inline in tests Add public smooth_max_da / smooth_min_da (or named *_derivative w.r.t. first arg) + FD tests
      No dedicated C¹ join tests for smooth_clamp Add FD slope continuity at the four junctions (lo, lo+width, hi-width, hi)
      No general ε/width guidance doc Add rustdoc module section + short markdown standard (see Task 3)
      flow_regularization not formally declared “reference” Document — do not move into core
  • Task 2: Complete the toolkit APIs in entropyk-core (AC: #1)

    • 2.1 Add analytic derivatives needed by consumers:
      • smooth_clamp_derivative(x, lo, hi, width) -> f64
      • smooth_max / smooth_min first-arg (or both-arg) derivatives — match existing formulas already verified in unit tests
    • 2.2 Keep APIs pure f64, #[inline], zero-alloc, no new crate deps.
    • 2.3 Guard invalid parameters without panic: width <= 0, hi < lo, k <= 0, eps <= 0 — document degenerate behavior (hard clamp / hard max / hard abs) and cover with tests. Prefer non-panicking fallbacks consistent with existing normalize zero-width handling.
    • 2.4 Re-export path unchanged: entropyk_core::smoothing::* via existing pub mod smoothing in crates/core/src/lib.rs. No facade/entropyk re-export required unless already present.
  • Task 3: Document the Phantom-Gradient Regularization Standard (AC: #1, #2)

    • 3.1 Add a focused doc (preferred path): docs/components/phantom-gradient-regularization.md OR expand docs/components/flow-regularization.md with a top-level “Standard” section that links to smoothing.rs. Prefer a dedicated short doc if the flow doc stays HX-specific.

    • 3.2 Document ε / width selection guidance with physical meaning:

      Primitive Parameter Meaning Rule of thumb
      smooth_abs(x, eps) eps value at x=0; blend half-width ~1% of characteristic |x| scale, or smaller if kink is far from operating region
      smooth_max / smooth_min k overshoot at equality = k/2 k ≪ |ab| in the region you care about; never so large it shifts equilibrium
      smooth_clamp width transition length at each bound width ≤ (hilo)/2; pick so Newton steps near bound still see ∂/∂x ∈ (0,1) over a physically small band (e.g. opening width 1e-31e-2 for [0,1])
      flow_activity m_eps mass-flow activity scale keep DEFAULT_M_EPS_KG_S = 1e-4 as HX reference; do not change the constant in this story
    • 3.3 Explicit decision (write it into the doc):

      • Canonical general toolkit: entropyk_core::smoothing
      • Reference specialized pattern: heat_exchanger::flow_regularization (activity / duty / transport blend) — not duplicated into core
      • Banned in residual/Jacobian paths on Newton unknowns: bare .clamp( / hard .max(0) / early Ok(0.0) that zeros informative derivatives (fixes deferred to 0.3/0.4)
    • 3.4 Cross-link from docs/audits/jacobian-killing-pattern-audit.md deferred table: mark Story 0.2 standard as landed when done (update the “deferred” row only — do not re-audit).

    • 3.5 English technical docs; keep code comments English.

  • Task 4: Derivative-continuity unit tests (AC: #1)

    • 4.1 Extend crates/core/src/smoothing.rs #[cfg(test)]:
      • FD match for smooth_clamp_derivative across interior, both ramps, and far exterior.
      • Slope continuity of smooth_clamp across junctions (sample FD slope just inside/outside joins; assert small jump).
      • FD match for new smooth_max / smooth_min derivative helpers.
    • 4.2 Do not require check_jacobian_health for this story — that harness is component-level (Story 0.1). Core unit FD helpers already in smoothing.rs tests are the right layer.
    • 4.3 Keep using relative/absolute tolerances consistent with existing tests (~1e-5 FD match for analytic derivatives).
  • Task 5: Hard scope boundary — toolkit only (AC: #2)

    • 5.1 DO NOT modify production residual/Jacobian physics in:
      • valve_flow.rs
      • isenthalpic_expansion_valve.rs
      • heat_exchanger/two_phase_dp.rs
      • heat_exchanger/condenser.rs
      • any other component clamp site
    • 5.2 DO NOT change DEFAULT_M_EPS_KG_S / DEFAULT_M_SCALE_KG_S or HX residual formulas.
    • 5.3 DO NOT change n_equations() anywhere.
    • 5.4 Allowed touch list is essentially: smoothing.rs (+ tests), docs under docs/components/ and a small audit cross-link, optional rustdoc polish on flow_regularization.rs module docs pointing to the standard.
  • Task 6: Validation (AC: #1, #2)

    • 6.1 cargo test -p entropyk-core green (includes new smoothing tests / doctests).
    • 6.2 cargo test -p entropyk-components green — proves no accidental physics regressions from doc-only / non-touch policy.
    • 6.3 Diff review: production component residual files should show zero physics diffs attributable to this story.

Dev Notes

Context & Positioning

  • Epic 0 — Physical Regularization & Jacobian Health. Prerequisite for primary KPI NFR11 (≥95% first-try convergence). Robustness before speed.
  • FR19 — informative non-zero C¹ Jacobians across the full physical domain via standardized phantom-gradient regularization.
  • FR20 — FD harness (already delivered in Story 0.1); CI gate is Story 0.5.
  • This story owns the standard + toolkit completeness. Stories 0.3 (valve/EXV) and 0.4 (HX quality/actuators/MSH) consume smooth_clamp / smooth_max / smooth_abs to fix P0 killers.
  • Source of truth for solver-HP scope: _bmad-output/planning-artifacts/epics-solver-hp.md (supersedes legacy PRD/architecture for this epic).

CRITICAL: Toolkit already largely exists — complete, don't recreate

CANONICAL LOCATION (reuse):
  crates/core/src/smoothing.rs
    smooth_max(a, b, k)
    smooth_min(a, b, k)
    smooth_abs(x, eps) + smooth_abs_derivative
    smooth_clamp(x, lo, hi, width)          // value exists; derivative API missing
    smoothstep / smootherstep / cubic_blend / quintic_blend (+ derivatives)

HX REFERENCE PATTERN (keep in components — do not move to core):
  crates/components/src/heat_exchanger/flow_regularization.rs
    flow_activity / effective_duty / blend_transport_residual
    uses entropyk_core::smoothing::smooth_abs

VERIFICATION HARNESS (Story 0.1 — do not reimplement):
  crates/components/src/jacobian_fd.rs
  docs/audits/jacobian-killing-pattern-audit.md

Anti-patterns to prevent:

  • Creating a second smoothing / regularization module under components/
  • Copy-pasting tanh / LogSumExp soft-max when smooth_max already exists
  • “Unifying” by moving flow_activity into core (wrong layer — HX residual units / m_scale)
  • Replacing component clamps in this story (that is 0.3/0.4)
  • Calling JacobianMatrix::numerical (forward FD Newton fallback) for anything here

Architecture Compliance

  • Exact analytic Jacobians (project-context.md / AGENTS.md): production assembly stays analytic; FD only in tests.
  • C¹ residual policy: any clamp/branch on a Newton unknown must use toolkit primitives so ∂R/∂x stays informative and continuous.
  • DoF invariant: regularization never changes n_equations().
  • Zero panic in library code; public APIs need rustdoc + examples.
  • Hot path: pure functions, no allocation, no dynamic dispatch.
  • Layering: entropyk-core must not depend on entropyk-components.

Technical Requirements

  • Language: Rust edition 2021, crate entropyk-core (+ docs only elsewhere).
  • Deps: no new crates. Existing workspace/approx patterns for tests as already used in core.
  • smooth_clamp construction (already implemented — preserve semantics):
    // Lower ramp then upper ramp via smoothstep — output always in [lo, hi], C¹ joins.
    let lower = lo + (x - lo) * smoothstep(lo, lo + width, x);
    hi + (lower - hi) * smoothstep(hi, hi - width, lower)
    
    Derivative must follow the chain rule through both ramps; unit-test against central FD.
  • smooth_max analytic ∂/∂a (already proven in tests):
    0.5 * (1 + (a-b) / sqrt((a-b)² + k²))
    
  • Prefer exporting named derivative functions over forcing callers to re-derive formulas (Story 0.3 will clamp EXV opening in both residual and Jacobian).

Current toolkit gaps (verified 2026-07-18)

Item Status
smooth_max / smooth_min / smooth_abs / smooth_clamp values Present
smooth_abs_derivative Present
Public smooth_clamp_derivative Missing — add
Public smooth_max/smooth_min derivatives Missing — add (formulas exist in tests)
FD C¹ junction tests for smooth_clamp Missing — add (current test only saturates/bounds)
General ε/width selection doc Missing — add (flow-regularization.md covers HX m_eps only)
Formal “reference vs unify” decision for flow_regularization Missing — document as reference

Downstream contract (write APIs for these consumers)

Future story Will need
0.3 Valve / EXV smooth_clamp + derivative for opening ∈ [0,1]; smooth ΔP blend (may use smooth_max/smooth_abs)
0.4 HX smooth_clamp for quality / fan / flood; reuse flow_regularization patterns
0.5 CI gate Assumes toolkit stable; no API churn after this story

Recommended default widths for docs/examples (not applied to components here):

  • Opening / quality ∈ [0,1]: width = 1e-31e-2
  • Fan actuator ∈ [0, 1.5]: width ≈ 1e-2
  • Flood level ∈ [0, 0.98]: width ≈ 1e-2 (keep width ≤ (hilo)/2)

File Structure Requirements

File Action
crates/core/src/smoothing.rs UPDATE — add missing derivative APIs + C¹/FD tests; expand module rustdoc with ε guidance
crates/core/src/lib.rs UPDATE only if export changes needed (likely unchanged)
docs/components/phantom-gradient-regularization.md CREATE (preferred) — standard + ε table + reference decision
docs/components/flow-regularization.md UPDATE — link to standard; declare HX module as specialized reference
crates/components/src/heat_exchanger/flow_regularization.rs UPDATE docs only (optional module-doc pointer) — no formula changes
docs/audits/jacobian-killing-pattern-audit.md UPDATE — mark 0.2 standard row as done / link to new doc
valve_flow.rs / EXV / two_phase_dp.rs / condenser.rs DO NOT CHANGE physics

Testing Requirements

  • Unit tests live next to primitives in smoothing.rs (existing pattern with local fd helper).
  • Must prove:
    1. Analytic derivatives match central FD.
    2. smooth_clamp slope is continuous at bound joins (C¹).
    3. Degenerate parameters do not panic.
  • Run:
    cargo test -p entropyk-core
    cargo test -p entropyk-components
    
  • Do not flip Story 0.1 detection tests to “must be clean” — killers remain until 0.3/0.4.

Previous Story Intelligence

From 0-1-jacobian-killing-pattern-audit-fd-test-harness (status: review):

  • Shared harness: jacobian_fd::check_jacobian_health — central FD, flags analytic≈0 while FD informative.
  • Audit catalogue confirms P0 killers; maps EXV opening clamps → Story 0.2 smooth_clamp as the intended replacement API, applied later in 0.3.
  • Explicitly noted: smooth_* already in core — Story 0.2 is unify/document/ε-guidance, not greenfield.
  • Scope discipline that worked: observe/fix tooling without changing production physics. Reuse that discipline here.
  • Epic typo note still valid for 0.3: only valve_mass_flow_dp_up exists (no dp_down).
  • Numbering collision: 0-1-fix-failing-tests is a different, already-done DoF story — ignore for this work.

Git Intelligence

  • Recent commits are FMI/docs-heavy (f88cd7f baseline). Smoothing + flow_regularization landed earlier (3358b74 lineage) — brownfield completion, not invention.
  • No commit yet closes the ε-standard doc or smooth_clamp_derivative gap.

Project Context Reference

  • project-context.md / AGENTS.md: exact Jacobians; Component trait; English technical docs; zero panic.
  • Epic/FRs: _bmad-output/planning-artifacts/epics-solver-hp.md — Epic 0, Story 0.2, FR19, FR20, NFR11.
  • Supporting: docs/audits/jacobian-killing-pattern-audit.md, docs/components/flow-regularization.md, docs/adr/ADR-0001-multi-circuit-heat-exchanger-architecture.md (smooth_abs / no hard zero-flow branch).

References

  • [Source: _bmad-output/planning-artifacts/epics-solver-hp.md — Epic 0, Story 0.2, FR19, NFR11]
  • [Source: crates/core/src/smoothing.rs — existing C¹/C∞ toolkit]
  • [Source: crates/components/src/heat_exchanger/flow_regularization.rs — HX reference pattern]
  • [Source: docs/components/flow-regularization.md — m_eps defaults, DoF rule]
  • [Source: docs/audits/jacobian-killing-pattern-audit.md — deferred 0.2 work + P0 map]
  • [Source: _bmad-output/implementation-artifacts/0-1-jacobian-killing-pattern-audit-fd-test-harness.md — prior story learnings]
  • [Source: crates/components/src/jacobian_fd.rs — verification harness (do not reimplement)]

Dev Agent Record

Agent Model Used

Cursor Grok 4.5 (bmad-dev-story)

Debug Log References

  • cargo test -p entropyk-core — 164 lib + 41 doctests passed (incl. new smoothing derivative / C¹ / degenerate tests)
  • cargo test -p entropyk-components — lib 910 passed; jacobian_health_sweep 8 passed; doctests 70 passed
  • Story-owned production touch limited to flow_regularization.rs module docs (+4 lines); no clamp→smooth physics changes

Completion Notes List

  • Added public smooth_max_derivative, smooth_min_derivative, smooth_clamp_derivative with chain-rule / analytic formulas; FD-matched in unit tests.
  • Documented ε/width guidance in module rustdoc and docs/components/phantom-gradient-regularization.md.
  • Declared flow_regularization as HX reference pattern (not moved to core); linked from flow-regularization.md + audit deferred table (0.2 landed).
  • Degenerate parameters (k/eps/width <= 0, inverted bounds) fall back to hard max/min/abs/clamp without panic.
  • Scope held: valve/EXV/HX clamp physics untouched for Stories 0.3/0.4.

File List

  • crates/core/src/smoothing.rs (UPDATE)
  • crates/components/src/heat_exchanger/flow_regularization.rs (UPDATE — module docs only)
  • docs/components/phantom-gradient-regularization.md (NEW)
  • docs/components/flow-regularization.md (UPDATE)
  • docs/audits/jacobian-killing-pattern-audit.md (UPDATE — deferred table)
  • _bmad-output/implementation-artifacts/sprint-status.yaml (UPDATE — story status)
  • _bmad-output/implementation-artifacts/0-2-phantom-gradient-regularization-standard.md (UPDATE — this file)

Change Log

  • 2026-07-18: Completed phantom-gradient regularization standard — derivative APIs, C¹ tests, ε docs, flow_regularization reference decision; status → review

Story Completion Status

  • Status: review
  • Note: All tasks complete; ACs satisfied; ready for code-review