Snapshot WIP: solver HP epic progress, BPHX/HX physics, BMAD skill refresh.
Some checks failed
CI / check (push) Has been cancelled

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>
This commit is contained in:
2026-07-19 16:35:31 +02:00
parent 88620790d6
commit 5bd180b5b8
1363 changed files with 101041 additions and 58547 deletions

View File

@@ -26,20 +26,16 @@
| Site | Failure mode | Severity | Fix owner |
|------|--------------|----------|-----------|
| `crates/components/src/valve_flow.rs:105-107``valve_mass_flow_dp_up` returns `Ok(0.0)` when `dp <= 0 \|\| m <= 0` | `zero-gradient` | **P0** | Story 0.3 |
| `crates/components/src/isenthalpic_expansion_valve.rs:233``state[i].clamp(0.0, 1.0)` on orifice opening (residual path) | `discontinuity` | **P0** | Story 0.3 |
| `crates/components/src/isenthalpic_expansion_valve.rs:449``_state[i].clamp(0.0, 1.0)` on orifice opening (Jacobian path) | `discontinuity` | **P0** | Story 0.3 |
| `crates/components/src/heat_exchanger/two_phase_dp.rs:107``quality.clamp(0.0, 1.0)` in `homogeneous_density` | `discontinuity` | **P0** | Story 0.4 |
| `crates/components/src/heat_exchanger/two_phase_dp.rs:150``quality.clamp(0.0, 1.0)` in `friedel_multiplier` | `discontinuity` | **P0** | Story 0.4 |
| `crates/components/src/heat_exchanger/condenser.rs:492``state[idx].clamp(0.0, 1.5)` fan actuator φ | `discontinuity` | **P0** | Story 0.4 |
| `crates/components/src/heat_exchanger/condenser.rs:752``state[idx].clamp(0.0, 0.98)` flooded level λ | `discontinuity` | **P0** | Story 0.4 |
| `crates/components/src/valve_flow.rs` — ΔP≤0 / opening clamps / `dp_up` hard zero | `already-regularized` | info | Story **0.3 landed**`smooth_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 landed**`smooth_clamp` quality (`QUALITY_WIDTH=1e-2`) |
| `crates/components/src/heat_exchanger/condenser.rs` — fan φ / flood λ actuators | `already-regularized` | info | Story **0.4 landed**`smooth_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 ΔP≤0:** `valve_mass_flow` already forces `dp = ΔP.max(0)`, so ṁ=0 and `valve_mass_flow_dp_up` returns a hard zero — Newton gets no direction to restore positive ΔP.
- **EXV opening clamps:** same hard clamp appears in both residual helper and Jacobian branch; Story 0.2 `smooth_clamp` is the intended replacement (`entropyk_core::smoothing` already exists).
- **EXV phantom ΔP:** `DP_FLOOR` (~L396445) is a **partial** `already-regularized` mitigation for ΔP≤0 on the Jacobian only; residual still early-outs. Opening clamps remain P0.
- **Missing API:** Epic Story 0.3 text mentions `valve_mass_flow_dp_down`**only `valve_mass_flow_dp_up` exists** today (`lib.rs` re-export). Catalogue gap severity `info`; inventing `dp_down` is out of scope for Story 0.1.
- **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`).
---
@@ -51,17 +47,15 @@ Classified from a ripgrep sweep of `.clamp(` / `.max(` / `.min(` under `crates/c
| Location | Pattern | Mode | Sev | Notes / owner |
|----------|---------|------|-----|---------------|
| `valve_flow.rs:71,75,78,99` | `dp.max(0)`, `opening.clamp`, `m.max(0)` | `zero-gradient` / `discontinuity` | P0 | Feeds EXV/orifice; Story 0.3 |
| `valve_flow.rs:105-107` | hard `Ok(0.0)` on ∂ṁ/∂P_up | `zero-gradient` | P0 | FR19 |
| `isenthalpic_expansion_valve.rs:233,449` | opening clamp on state | `discontinuity` | P0 | FR19 → 0.3 |
| `isenthalpic_expansion_valve.rs:396-445` | `DP_FLOOR` phantom | `already-regularized` | info | Keep; unify with toolkit in 0.2/0.3 |
| `two_phase_dp.rs:107,150` | quality clamp | `discontinuity` | P0 | FR19 → 0.4 |
| `two_phase_dp.rs:118-131` | hard `x<=0` / `x>=1` branches in `zivi_void_fraction` | `discontinuity` | P1 | Story 0.4 (MSH/dome) |
| `two_phase_dp.rs:255-294` | Hermite blend near x→1 (`msh_gradient`) | `already-regularized` | info | Partial MSH fix; 0.4 completes |
| `condenser.rs:492,752` | fan / flood actuator clamps | `discontinuity` | P0 | FR19 → 0.4 |
| `evaporator.rs` | analogous secondary / property floors | `benign` / P2 | P2 | Re-check when evaporator actuators mirror condenser |
| `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)` | `discontinuity` | P1 | Intermediate iterate domain; Story 0.4 / sat path |
| `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 |
@@ -84,6 +78,7 @@ Classified from a ripgrep sweep of `.clamp(` / `.max(` / `.min(` under `crates/c
| `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) |
---
@@ -97,12 +92,9 @@ use entropyk_components::jacobian_fd::{
};
let report = check_jacobian_health(&component, &state, JacobianFdConfig::default())?;
assert!(
report.has_zero_gradient_killers(),
"expected clamp/zero-gradient signature, got clean report"
);
// After Stories 0.20.4 fixes, Story 0.5 flips the gate to:
// assert!(report.is_clean());
// 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)
@@ -117,15 +109,16 @@ assert!(
**Do not** call `JacobianMatrix::numerical` (solver) from this harness — that API is **forward** difference for Newton fallback.
Integration smoke tests: `crates/components/tests/jacobian_health_sweep.rs`.
Integration gate tests: `crates/components/tests/jacobian_health_sweep.rs`.
---
## Story 0.5 CI gate (future)
## Story 0.5 CI gate (landed)
1. Reuse `check_jacobian_health` over per-component physical-domain grids (ΔP≤0, quality 0/1, opening 0/1, dome edges, actuator clamps).
2. Fail CI on new `zero_gradient_killers` or mismatches outside an allow-list that shrinks to empty after 0.20.4.
3. Commit a per-component / per-region health report artifact (extend this file or generate JSON beside it).
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`](./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`.
---
@@ -134,15 +127,15 @@ Integration smoke tests: `crates/components/tests/jacobian_health_sweep.rs`.
| Work | Owner |
|------|-------|
| Standardize / document `smooth_*` ε guidance; declare `flow_regularization` as HX reference | Story **0.2****landed** (`docs/components/phantom-gradient-regularization.md`; derivatives in `crates/core/src/smoothing.rs`) |
| Valve ΔP≤0 phantom + EXV opening `smooth_clamp` | Story **0.3** |
| Quality / condenserevaporator state clamps + MSH singularity | Story **0.4** |
| Full-envelope CI Jacobian health gate | Story **0.5** |
| Valve ΔP≤0 phantom + EXV opening `smooth_clamp` | Story **0.3****landed** |
| Quality / condenserevaporator state clamps + MSH singularity | Story **0.4****landed** |
| Full-envelope CI Jacobian health gate | Story **0.5****landed** (see [`jacobian-health-report.md`](./jacobian-health-report.md)) |
| Replace production FD Jacobian in generic 4-port HX | Separate NFR9 / remediation track |
---
## Severity ranking summary
1. **P0 (fix in 0.30.4):** valve ΔP zero-gradient; EXV opening clamps; two-phase quality clamps; condenser fan/flood clamps.
2. **P1:** sat-domain pressure clamp; screw eco/slide clamps when unknowns; zivi hard edges.
3. **P2 / info:** correlation floors, config clamps, NFR9 FD-in-production debt.
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.