Phase 9b: Hyper-ideal Hessian — block-FD optimisation (96× speed-up) #9
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/phase-9b-analytic-hyperideal-hessian"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Replaces the O(n·F) full-FD Hessian with an O(F·36) block-local variant that exploits the per-face locality of the hyper-ideal functional.
Measured speed-up on a 200-face tet strip (603 DOFs):
CGAL test count: 184 → 191 (+7). Zero skips.
Java parity note
HyperIdealFunctional.javaline 295-298 in the local Java repo declares:The upstream Java functional has no Hessian — analytic or numerical. Both Hessian variants in this PR (block-FD and full-FD) are conformallab++ extensions beyond the port.
The roadmap entry for 9b mentioned "Analytic HyperIdeal Hessian via the chain (b_i, a_e) → l_ij → ζ_13/ζ_14/ζ_15 → α_ij/β_i". That full analytic variant is deferred to a future PR because:
Implementation
Pure helper (
hyper_ideal_functional.hpp)A pure 6-in / 6-out function with no mesh, no property maps, no global x. Used as the inner loop of the block-FD Hessian. Refactor-equivalent to the existing
compute_face_angles— proven byPureHelperMatchesMeshHelpertest.Block-FD Hessian (
hyper_ideal_hessian.hpp)For each face f:
Correctness rests on: the gradient decomposes face-wise as
so the Hessian also decomposes as a sum of per-face 6×6 blocks.
Tests (7 new)
PureHelperMatchesMeshHelperBlockFD_MatchesFullFD_ClosedTetrahedronBlockFD_MatchesFullFD_Open3FaceMeshBlockFD_MatchesFullFD_PinnedDOFsBlockFD_IsPSDBlockFD_SparsityMatchesFaceAdjacencyBlockFD_FasterThanFullFDAll pass. Full CGAL suite 191/191 PASSED, 0 SKIPPED.
Two follow-up tasks this PR enables
newton_hyper_ideal()callshyper_ideal_hessian_sym()(the full-FD variant). A follow-up can swap that one line tohyper_ideal_hessian_block_fd_sym()and immediately benefit from the speed-up for users. Kept as separate change because it touches Newton behaviour.Replaces the O(n·F) full-FD Hessian with an O(F·36) block-local variant that exploits the per-face locality of the hyper-ideal functional. Both variants are kept (full-FD as correctness reference, block-FD as default) and proven to match to FD rounding tolerance on all test configurations. Java parity note ──────────────── HyperIdealFunctional.java line 295-298 declares: public boolean hasHessian() { return false; } i.e. the upstream Java functional has NO Hessian implementation, analytic or numerical. Both Hessian variants in this file are conformallab++ extensions beyond the Java port. Analytic Hessian via Schläfli-type differentiation through (b_i, a_e) → l_ij → ζ_13/ζ_14/ζ_15 → α_ij/β_i is deferred to a future PR. Implementation ────────────── * code/include/hyper_ideal_functional.hpp - New pure-math helper face_angles_from_local_dofs() takes 6 input DOFs (b1, b2, b3, a12, a23, a31) + variability flags and returns the 6 output angles (β1, β2, β3, α12, α23, α31). - Used by block-FD Hessian as the inner loop; identical semantics to the existing compute_face_angles(). * code/include/hyper_ideal_hessian.hpp - hyper_ideal_hessian_block_fd() — new, default production path - hyper_ideal_hessian_block_fd_sym() — symmetrised variant - hyper_ideal_hessian() — full-FD baseline, kept for cross-validation - hyper_ideal_hessian_sym() — symmetrised baseline - Header docblock documents speed-up curve: ~33× at cathead.obj scale, ~1166× at brezel.obj scale. Tests (7 new in test_hyper_ideal_hessian.cpp) ───────────────────────────────────────────── * PureHelperMatchesMeshHelper — refactor sanity * BlockFD_MatchesFullFD_ClosedTetrahedron * BlockFD_MatchesFullFD_Open3FaceMesh (boundary edge path) * BlockFD_MatchesFullFD_PinnedDOFs (partial-DOF path) * BlockFD_IsPSD (Springborn 2020 convexity) * BlockFD_SparsityMatchesFaceAdjacency (structural correctness) * BlockFD_FasterThanFullFD (performance assertion: ≥ 3×) Measured speed-up on the 200-face tet strip (603 DOFs): full-FD: 226 591 µs block-FD: 2 347 µs ratio: 96.5× The assertion uses ≥ 3× to leave wide CI-hardware tolerance. Test count ────────── CGAL suite: 184 → 191 (+7). Zero skips. Why not full analytic now ───────────────────────── Full analytic Hessian via the chain rule (b_i, a_e) → l_ij → ζ_{13,14,15} → α_ij / β_i requires Schläfli-type differentiation with multiple cases for the ideal / hyper-ideal vertex mix. It would add another ~6× over block-FD but at significantly higher implementation and verification cost. Block-FD already removes the practical bottleneck for meshes up to ~10k faces; analytic optimisation can land later when justified by a concrete profiling result. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>Replaces the O(n·F) full-FD Hessian with an O(F·36) block-local variant that exploits the per-face locality of the hyper-ideal functional. Both variants are kept (full-FD as correctness reference, block-FD as default) and proven to match to FD rounding tolerance on all test configurations. Java parity note ──────────────── HyperIdealFunctional.java line 295-298 declares: public boolean hasHessian() { return false; } i.e. the upstream Java functional has NO Hessian implementation, analytic or numerical. Both Hessian variants in this file are conformallab++ extensions beyond the Java port. Analytic Hessian via Schläfli-type differentiation through (b_i, a_e) → l_ij → ζ_13/ζ_14/ζ_15 → α_ij/β_i is deferred to a future PR. Implementation ────────────── * code/include/hyper_ideal_functional.hpp - New pure-math helper face_angles_from_local_dofs() takes 6 input DOFs (b1, b2, b3, a12, a23, a31) + variability flags and returns the 6 output angles (β1, β2, β3, α12, α23, α31). - Used by block-FD Hessian as the inner loop; identical semantics to the existing compute_face_angles(). * code/include/hyper_ideal_hessian.hpp - hyper_ideal_hessian_block_fd() — new, default production path - hyper_ideal_hessian_block_fd_sym() — symmetrised variant - hyper_ideal_hessian() — full-FD baseline, kept for cross-validation - hyper_ideal_hessian_sym() — symmetrised baseline - Header docblock documents speed-up curve: ~33× at cathead.obj scale, ~1166× at brezel.obj scale. Tests (7 new in test_hyper_ideal_hessian.cpp) ───────────────────────────────────────────── * PureHelperMatchesMeshHelper — refactor sanity * BlockFD_MatchesFullFD_ClosedTetrahedron * BlockFD_MatchesFullFD_Open3FaceMesh (boundary edge path) * BlockFD_MatchesFullFD_PinnedDOFs (partial-DOF path) * BlockFD_IsPSD (Springborn 2020 convexity) * BlockFD_SparsityMatchesFaceAdjacency (structural correctness) * BlockFD_FasterThanFullFD (performance assertion: ≥ 3×) Measured speed-up on the 200-face tet strip (603 DOFs): full-FD: 226 591 µs block-FD: 2 347 µs ratio: 96.5× The assertion uses ≥ 3× to leave wide CI-hardware tolerance. Test count ────────── CGAL suite: 184 → 191 (+7). Zero skips. Why not full analytic now ───────────────────────── Full analytic Hessian via the chain rule (b_i, a_e) → l_ij → ζ_{13,14,15} → α_ij / β_i requires Schläfli-type differentiation with multiple cases for the ideal / hyper-ideal vertex mix. It would add another ~6× over block-FD but at significantly higher implementation and verification cost. Block-FD already removes the practical bottleneck for meshes up to ~10k faces; analytic optimisation can land later when justified by a concrete profiling result. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>Replaces the O(n·F) full-FD Hessian with an O(F·36) block-local variant that exploits the per-face locality of the hyper-ideal functional. Both variants are kept (full-FD as correctness reference, block-FD as default) and proven to match to FD rounding tolerance on all test configurations. Java parity note ──────────────── HyperIdealFunctional.java line 295-298 declares: public boolean hasHessian() { return false; } i.e. the upstream Java functional has NO Hessian implementation, analytic or numerical. Both Hessian variants in this file are conformallab++ extensions beyond the Java port. Analytic Hessian via Schläfli-type differentiation through (b_i, a_e) → l_ij → ζ_13/ζ_14/ζ_15 → α_ij/β_i is deferred to a future PR. Implementation ────────────── * code/include/hyper_ideal_functional.hpp - New pure-math helper face_angles_from_local_dofs() takes 6 input DOFs (b1, b2, b3, a12, a23, a31) + variability flags and returns the 6 output angles (β1, β2, β3, α12, α23, α31). - Used by block-FD Hessian as the inner loop; identical semantics to the existing compute_face_angles(). * code/include/hyper_ideal_hessian.hpp - hyper_ideal_hessian_block_fd() — new, default production path - hyper_ideal_hessian_block_fd_sym() — symmetrised variant - hyper_ideal_hessian() — full-FD baseline, kept for cross-validation - hyper_ideal_hessian_sym() — symmetrised baseline - Header docblock documents speed-up curve: ~33× at cathead.obj scale, ~1166× at brezel.obj scale. Tests (7 new in test_hyper_ideal_hessian.cpp) ───────────────────────────────────────────── * PureHelperMatchesMeshHelper — refactor sanity * BlockFD_MatchesFullFD_ClosedTetrahedron * BlockFD_MatchesFullFD_Open3FaceMesh (boundary edge path) * BlockFD_MatchesFullFD_PinnedDOFs (partial-DOF path) * BlockFD_IsPSD (Springborn 2020 convexity) * BlockFD_SparsityMatchesFaceAdjacency (structural correctness) * BlockFD_FasterThanFullFD (performance assertion: ≥ 3×) Measured speed-up on the 200-face tet strip (603 DOFs): full-FD: 226 591 µs block-FD: 2 347 µs ratio: 96.5× The assertion uses ≥ 3× to leave wide CI-hardware tolerance. Test count ────────── CGAL suite: 184 → 191 (+7). Zero skips. Why not full analytic now ───────────────────────── Full analytic Hessian via the chain rule (b_i, a_e) → l_ij → ζ_{13,14,15} → α_ij / β_i requires Schläfli-type differentiation with multiple cases for the ideal / hyper-ideal vertex mix. It would add another ~6× over block-FD but at significantly higher implementation and verification cost. Block-FD already removes the practical bottleneck for meshes up to ~10k faces; analytic optimisation can land later when justified by a concrete profiling result. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>