Files
Entropyk/docs/audits/jacobian-killing-pattern-audit.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

8.8 KiB
Raw Blame History

Jacobian-Killing Pattern Audit

Date: 2026-07-18
Story: 0-1-jacobian-killing-pattern-audit-fd-test-harness (Epic 0)
Scope: Inventory of clamp / max / min (and related hard gates) on Newton residual/Jacobian paths in entropyk-components. Physics fixes are owned by Stories 0.20.4.

Failure-mode legend

Mode Meaning
zero-gradient Analytic ∂r/∂x (or helper derivative) hard-zeros in a region where physics should still inform Newton
discontinuity Hard clamp/step on a Newton unknown → C⁰ or worse residual; FD and analytic disagree near the edge
benign Floor/guard for division-by-zero, config validation, or non-Newton parameter — not a solver killer
already-regularized C¹ / phantom pattern already present (may still need unification)
Severity Meaning
P0 Confirmed FR19 killer; blocks convergence at domain edges
P1 Likely Newton-relevant clamp on live unknowns / quality
P2 Secondary / correlation-local; watch when that path is active
info Documented debt or missing API; not a clamp site

FR19 known-bad sites (confirmed 2026-07-18)

Site Failure mode Severity Fix owner
crates/components/src/valve_flow.rs — ΔP≤0 / opening clamps / dp_up hard zero already-regularized info Story 0.3 landedsmooth_max ΔP + smooth_clamp opening + valve_mass_flow_dp_down
crates/components/src/isenthalpic_expansion_valve.rs — orifice opening clamps + ΔP early-out already-regularized info Story 0.3 landed — shared smooth_clamp / smooth_max in residual and Jacobian
crates/components/src/heat_exchanger/two_phase_dp.rs — quality in homogeneous_density / friedel_multiplier already-regularized info Story 0.4 landedsmooth_clamp quality (QUALITY_WIDTH=1e-2)
crates/components/src/heat_exchanger/condenser.rs — fan φ / flood λ actuators already-regularized info Story 0.4 landedsmooth_clamp + Jacobian *_derivative chain rule
crates/components/src/heat_exchanger/two_phase_dp.rs — MSH Hermite blend near x→1 already-regularized info Story 0.4 verified — FD-bounded ∂g/∂x across X_BLEND=0.90

Evidence notes

  • Valve / EXV (Story 0.3): dp_eff = smooth_max(ΔP, 0, k) with k = 1e3 Pa; opening via smooth_clamp(..., width=1e-2); valve_mass_flow_dp_up / dp_down are chain-rule consistent; EXV residual and Jacobian share the same expression (no Jacobian-only DP_FLOOR split).
  • HX (Story 0.4): quality helpers use smooth_clamp; condenser fan/flood residual+Jacobian share smooth_clamp / smooth_clamp_derivative; MSH singularity blend kept and FD-verified. Evaporator has no fan/flood actuator clamps (consumes regularized two_phase_dp).

Broader catalogue (residual / Jacobian call graph)

Classified from a ripgrep sweep of .clamp( / .max( / .min( under crates/components/src. Not every hit is listed — config setters, test helpers, and pure numerical floors are collapsed into summary rows.

P0 / P1 — Newton-relevant

Location Pattern Mode Sev Notes / owner
valve_flow.rs smooth_max ΔP + smooth_clamp opening + dp_up/dp_down already-regularized info Story 0.3 landed
isenthalpic_expansion_valve.rs orifice shared smooth_clamp / smooth_max residual+Jacobian already-regularized info Story 0.3 landed
two_phase_dp.rs quality helpers smooth_clamp quality already-regularized info Story 0.4 landed
two_phase_dp.rs zivi_void_fraction hard x<=0 / x>=1 branches benign info Not on live Newton path (export/tests only) — left as-is in 0.4
two_phase_dp.rs msh_gradient Hermite blend near x→1 already-regularized info Story 0.4 verified (FD bounded)
condenser.rs fan / flood smooth_clamp + chain-rule J already-regularized info Story 0.4 landed
evaporator.rs no fan/flood actuator clamps benign info N/A — consumes regularized two_phase_dp
heat_exchanger/flow_regularization.rs smooth mass / activity already-regularized info Reference for Story 0.2 unification
heat_exchanger/sat_domain.rs:81 p_pa.clamp(p_min, p_max) already-regularized info Tube-ΔP path now uses a C¹ smooth_clamp with exposed derivative (heat_exchanger::tube_dp, 2026-07-19); the shared helper keeps the hard clamp for its other consumers
screw_economizer_compressor.rs:486 eco fraction .clamp(0.0, 0.4) discontinuity P1 If eco fraction is a Newton unknown
screw_economizer_compressor.rs:291,343 slide valve clamp discontinuity P1 Config vs state — verify call site
bphx_correlation.rs:588+ quality / p_reduced clamps discontinuity P2 Correlation internals on quality

Benign / info (not Epic-0 P0)

Pattern class Examples Mode Sev
Divisor floors .max(1e-9), .max(1e-12) on ρ, μ, D benign info
Builder / config clamps with_orifice_fixed opening clamp, UA scale .max(0) benign info
Registry JSON parsing registry.rs quality/RH clamps benign info
Air humidity RH clamp air_boundary.rs benign info
FD step sizing in tests (x.abs()*1e-6).max(1e-3) benign info
Item Issue Sev
heat_exchanger/exchanger.rs:854-897 4-port Jacobian is 100% central FD in production info (NFR9)
screw_economizer_compressor.rs Incomplete analytic Jacobian rows info
python_components.rs Empty jacobian_entries stubs info
Category-B solver tests (jacobian_freezing, inverse calibration) Deferred per plans/audit-2026-07-remediation-plan.md info
condenser.rs / evaporator.rs tube-ΔP momentum partials Resolved (2026-07-19): was whole-ΔP central FD through the backend (~72 CoolProp calls/assembly, straddling clamps/blends); now exact analytic composition in heat_exchanger::tube_dp with narrow domain-safe FDs only on individual saturation properties (thin FFI exposes no saturation derivatives). Friedel correlation partials use narrow FD of the pure correlation info (NFR9)

Harness usage (entropyk_components::jacobian_fd)

Central FD vs analytic at one state point:

use entropyk_components::jacobian_fd::{
    check_jacobian_health, JacobianFdConfig,
};

let report = check_jacobian_health(&component, &state, JacobianFdConfig::default())?;
// Story 0.5 gate (Epic-0 P0 surfaces):
assert!(report.is_clean());
// Or: assert_jacobian_healthy(&component, &state, cfg, surface, region, &[]);

Defaults (aligned with condenser FD tests)

Constant Default
rel_epsilon 1e-6
h_floor 1e-3
rel_tol 1e-4
analytic_atol 1e-12
fd_informative 1e-8

Do not call JacobianMatrix::numerical (solver) from this harness — that API is forward difference for Newton fallback.

Integration gate tests: crates/components/tests/jacobian_health_sweep.rs.


Story 0.5 CI gate (landed)

  1. Reuse check_jacobian_health / assert_jacobian_healthy over Epic-0 physical-domain grids (ΔP≤0, quality edges, opening 0/1, dome edges, actuator clamps).
  2. Fail CI on new zero_gradient_killers or mismatches outside an allow-list — Epic-0 P0 allow-list is empty.
  3. Committed per-surface / per-region report: jacobian-health-report.md (+ optional JSON twin).
  4. Explicit CI step: cargo test -p entropyk-components --test jacobian_health_sweep in .github/workflows/ci.yml.

Deferred work (explicit)

Work Owner
Standardize / document smooth_* ε guidance; declare flow_regularization as HX reference Story 0.2landed (docs/components/phantom-gradient-regularization.md; derivatives in crates/core/src/smoothing.rs)
Valve ΔP≤0 phantom + EXV opening smooth_clamp Story 0.3landed
Quality / condenserevaporator state clamps + MSH singularity Story 0.4landed
Full-envelope CI Jacobian health gate Story 0.5landed (see jacobian-health-report.md)
Replace production FD Jacobian in generic 4-port HX Separate NFR9 / remediation track

Severity ranking summary

  1. P0 (fixed): valve/EXV (0.3); two-phase quality + condenser fan/flood (0.4).
  2. P1: sat-domain pressure clamp; screw eco/slide clamps when unknowns.
  3. P2 / info: correlation floors, config clamps, unused zivi hard edges, NFR9 FD-in-production debt.