fix(domain): apply the full prescribed flux in the thermal reference solve - #145
fix(domain): apply the full prescribed flux in the thermal reference solve#145singhharsh1708 wants to merge 2 commits into
Conversation
…solve _approx_target_temperature added one corner-weight share to each unique marked face node, so it applied (ny+1)(nz+1)/(4*ny*nz) of the prescribed flux: 0.5625 on the configured 16x8x1 mesh, and a different fraction at every other resolution. The reference therefore solved a different problem than the solvers it is the ground truth for, and was not mesh-converged. Accumulate per face element instead, which is what torch-fem-thermal already documents and does, so an interior face node picks up four shares, an edge node two and a corner one. Mirroring it element for element also keeps hot_spot mode consistent, where the mask covers only part of the face. At uniform density the problem reduces to a 1D slab with a closed form, T_hot = Q*Lx/(k*Ly*Lz). The reference now matches it to 1e-6 at 16x8x1, 8x4x1, 32x16x1 and 16x8x2, where before it sat at 0.565 of analytic and moved with the mesh. Refs pasteurlabs#144
|
The red check is the label gate, not a test failure: this touches Small thing spotted on the way: the missing-label error at |
📊 View the full benchmark resultsThe rendered docs preview has every plot for this run (forward accuracy, gradients, cost, optimization) merged with existing baseline results on Coverage: partial run — some cells are shown from the baseline rather than measured this run. Status diff vs baseLegend · ✅ ok · 🟠 anom · ❌ fail · · missing · 🚫 excluded (permanent — out of score denominator) · ⚪ excluded (work-to-do) · * stale — result predates current benchmark run 0 regression(s) · 0 improvement(s) · 12 metric change(s) · 0 other transition(s) · 0 resource-frontier shift(s) · 0 new row(s) · 0 removed row(s) · score 0.95 → 0.95 📊 Metric changes
Full Mosaic statusMosaic statusLegend · ✅ ok · 🟠 anom · ❌ fail · · missing · 🚫 excluded (permanent — out of score denominator) · ⚪ excluded (work-to-do) · * stale — result predates current benchmark run Each solver is run against every experiment in the suite. ok = produced valid results; fail = crashed or returned invalid data; anom = ran successfully but tripped an automated quality check (e.g. poor gradient accuracy, outlier wall-clock time, or diverged optimisation). Thresholds are defined per-problem in the problem config.
Failures & anomalies
ns-3d-grid — 16 experiment(s)
ns-grid — 20 experiment(s)
structural-mesh — 10 experiment(s)
thermal-mesh — 14 experiment(s)
|
|
Reading the benchmark run, since the metric column is mostly red. No status transitions: 0 regressions, 0 improvements, score 0.95 unchanged. All 12 changes are thermal-mesh metrics, which is the churn this PR was always going to cause, since it changes the ground truth those metrics are measured against. Part of the movement is just magnitude. The corrected target is 1.77x larger, and
So scaling alone does not account for it, and the residual is worth being explicit about rather than glossing. The two solvers that moved most are the two that previously fit best in absolute terms. My reading is that the old target was close to reachable by a near-uniform conductivity rescale, because the flux deficit was almost a pure scalar on the load and SIMP conductivity is a free multiplier, so an accurate solver could sit very near it without recovering the right density field. The corrected target removes that shortcut. On that reading a higher residual is the benchmark asking a harder and more meaningful question, not the recovery getting worse. I want to be clear that is an interpretation, not something this run establishes. The measurement that would settle it is recovered rho against rho_truth before and after, rather than the loss against the target. If you would like, I can add that as a diagnostic, though it needs the solver containers so it is not something I can produce from a local run. On Happy to hold this until #85 and #93 land if you would rather review the objective-consistency changes together. |
|
Thanks for the contribution @singhharsh1708. Your reasoning makes sense but I don't have the bandwidth to dig in here at the moment. Pending further analysis I'm ok with letting this sit, e.g. until @andrinr can have a closer look. |
Fixes #144.
The reference solve applied one corner-weight share per unique marked face node instead of one per face element, so it only ever applied
(ny+1)(nz+1) / (4*ny*nz)of the prescribed flux. On the configured 16x8x1 mesh that is 0.5625, and it changes with resolution, sotarget_temperaturewas both wrong and not mesh-converged.Fixed by accumulating per face element, which is what
torch-fem-thermalalready documents and does. Mirroring it element for element rather than writing an independently correct quadrature keeps the reference consistent with the solvers inhot_spotmode too, where the mask covers only part of the face.Verification
At uniform density the problem reduces to a 1D slab with a closed form,
T_hot = Q*Lx/(k*Ly*Lz). Before and after, at rho=0.5 andQ_total=100:Ratio to analytic is 1.00000 at every resolution now, so the reference is mesh-independent as well as correct.
tests/test_thermal_reference.pypins both properties against the closed form rather than golden values, so it stays meaningful if the mesh or the material model changes. All five fail onmain.Full suite is 555 passed against 550 before, ruff clean.
Results churn
This moves published
identification_errorandfinal_ic_errorfor thermal-meshoptimization/conductivity_recovery_bfgs, so it wants thebenchmark:domaintreatment and a re-run. It is the same objective-consistency question as #85 and #93, and those two probably want reviewing alongside this.I would not overstate the damage it was doing. The deficit is close to a pure rescale of the load and SIMP conductivity is a free multiplier, so the optimiser could still approach the stored target by inflating density: the recovered field was biased, not unreachable, and the bias moved with resolution.
gradient/source_fd_checkandgradient/source_width_sweepare AD-versus-FD consistency checks that need a target rather than a physical one, so they were not invalidated.optimization/conductivity_recoverysits behindif False:atconfig.py:428and is unaffected.