Skip to content

fix(interpolation): P2 phase 0 prerequisites (bugs 3, 4, 5, 6, 11, F1) - #345

Merged
lachlangrose merged 9 commits into
masterfrom
worktree-p2-phase0-prereqs
Oct 20, 2026
Merged

lachlangrose merged 9 commits into
masterfrom
worktree-p2-phase0-prereqs

Conversation

@lachlangrose

@lachlangrose lachlangrose commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Summary

Phase 0 tasks from agent/p2_fold/phase0_prereqs/tasks.md. One commit per task.

  • 0.1 (F1): P2UnstructuredTetMesh stores origin, step_vector, nsteps_cells. inside() and the diagnostics now work for P2.
  • 0.2 (bug 5): the P2 grad-steepness mask is neighbours >= 0. P2 fields move by at most 2.3e-3.
  • 0.3 (bug 4): P2 weights are applied after row normalisation. npw 1 to 100 now moves the field by 7.4e-4 (was 1e-7).
  • 0.4 (bug 3): CG returns False at the iteration limit. The default rtol is now 1e-8 when the caller gives no tol, rtol or atol. This applies to all CG users, not only P2. On planar_dip, P2 error goes from 0.65 to 2.5e-4. P1 error goes from 1.8e-2 to 5e-7.
  • 0.5 (bug 11): update() replays the kwargs of the last setup_interpolator call (fold_weights, regularisation, directional_regularisation).
  • 0.6 (bug 6): NaN rows are dropped from a constraint family. The rest of the family is kept. The log shows the number of dropped rows. Fold families use the same function.
  • 0.7: golden README.md known-bugs table updated.

Former test_known_* xfail tests are now normal tests.

Notes

  • Only P2 golden files changed (0.2). Golden files for the other engines are unchanged.
  • Three tests in test_p0_nan_constraints_skipped.py asserted the old "skip the whole family" behaviour. They now assert row-level dropping.
  • Seven tests in tests/unit/interpolator/test_2d_p1_p2_support.py fail on master too. They are not related to this PR.

Test plan

  • pytest packages/loop_interpolation/tests with PYTHONPATH=src:../loop_common/src: 533 passed, 34 skipped, 2 xfailed (F2)
  • root tests/: 714 passed, 7 failed (the same 7 as master)

…nstructuredTetMesh

inside() and the setup diagnostics need these. Remove the workaround in the golden engines.
The border mask used neighbours > 3, which dropped interior tets whose
neighbour index was 0 to 3. Use neighbours >= 0 (-1 marks a border).
P2 golden change: max |dv| 2.3e-3 (refolded_sparse), 1e-6 on planar_dip.
P2 multiplied w into A and B before add_constraints_to_least_squares
normalised the rows, so npw had no effect. Pass w through the w argument,
as P1 does. npw 1 -> 100 now moves the field by 7.4e-4 (was 1e-7).
Element size is dropped from the weight: it cancelled in the normalisation.
No P2 golden change (default weights are 1).
solve_with_cg and solve_with_cg_normal_equations returned True after
hitting the iteration limit. They now return res[1] == 0, so up_to_date
is False for an unconverged solve. Only DiscreteInterpolator.update() and
the builders' interpolator.up_to_date check read it; builder.update() is
guarded by its own flag, so no re-solve loop.

P2 default: scipy's rtol 1e-5 (not maxiter) caused the error on planar_dip
(P2 off by 0.65, P1 by 0.018). Default is now rtol=1e-8 when the caller
gives no tol, rtol or atol: P2 error 2.5e-4, P1 4.9e-7, about 0.7 s.
maxiter stays at the scipy default (10 n).
…_regularisation

setup_interpolator stored these only as call arguments, so update() rebuilt
the system with defaults (fold orientation weight 50 -> 10, field moved by
0.28 on DFI/FDFold). Each setup now records its kwargs in _setup_kwargs and
update() replays them. DFI and FDFold golden files are unchanged.
…mily

add_constraints_to_least_squares returned without adding anything when any
row had a nan. It now drops the bad rows (A, B, idc and per-row w together),
and logs how many of how many. Fold constraint families (DFI, FDFold) go
through the same function, so they get the filter too; a test covers a nan
fold-orientation element.
A_rowmoment cancels to about 1e-9, below the 1e-10 atol, so numpy/BLAS
ordering on CI python 3.10/3.11 changed it. master CI fails the same way.
Use atol 1e-6 for this key only.
_init_face_table sorted row, then called argsort on the sorted row to
reorder col. The default sort is not stable, so the node order of each
shared face depended on the numpy/CPU. P2 shared-element-jump quadrature
points moved between runs: golden fingerprints failed on CI python
3.10/3.11 (master too). Use one stable argsort for both arrays.
@lachlangrose
lachlangrose merged commit 4194616 into master Oct 20, 2026
45 checks passed
@lachlangrose
lachlangrose deleted the worktree-p2-phase0-prereqs branch October 20, 2026 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant