Repository navigation
Extremum Sum Potential - #259
Merged
Merged
Conversation
…till has problems, could be numerical issues
…edge-edge and 2D point-edge
…rner cases in parallel edge-edge
- Take ConstRef in the ESP vertex helpers and builders so passing a Ref no longer deep-copies the whole vertex matrix on every call - Make VertexMatrixView honor row/column strides so blocks, strided maps and row-major matrices read the right coordinates - Reject view arguments that would need a temporary copy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Weight each edge and vertex by its valence instead of the closed-mesh signs, sharing the rule with ArbitraryPointESP - Integrate the 3D potential over edges in no face and isolated vertices - Build vertex collisions for every vertex near a primitive Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Build ESP dict DOFs in VERTEX_DERIVATIVE_LAYOUT order and pass the vertex count to every ESP Hessian scatter - Hash integers, pairs and arrays generically in the non-Abseil fallback - Make the ESP tests layout-aware Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Keep NearFarBarrier's far part exactly 0 below alpha*dhat/2 so contact gives near = +inf instead of inf*0 = NaN - Reject non-positive or non-finite NearFarBarrier alpha - Return zero unsquared-distance barrier derivatives at d = 0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Shrink ESPCollision::ELEMENT_SIZE from 120 to 12 DOF (Face3P1-Vertex3) - Build near/far results in place instead of copying named locals - Test that the ESP Hessian runs on a 512 KiB thread stack Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Solve with cross products so the denominator stays positive for every pair the parallel filter keeps - Clamp the virtual vertex to the edge in the normal and friction builds Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Make log_and_throw_error a template over the exception type - Replace explicit throws with log_and_throw_error
- Treat edges and faces with any dynamic vertex as dynamic instead of throwing - Check ee_set too when skipping 2D obstacle edges in NORMAL mode - Never query obstacle flags under BRUTE_FORCE - Throw std::invalid_argument for a wrongly sized obstacle mask Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ArbitraryPointBVH walked the tree with a 64-entry stack guarded only by an assert, but a Morton-code tree can be up to 96 levels deep, so graded geometry overflowed it in Release builds. Reuse details::traverse_lbvh, whose stack fits the deepest valid tree and throws on overflow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ESP overload of TangentialCollisions::build took normalize_weights in the slot where the normal and GCP overloads take blend_mu, so a blend function passed positionally converted to true and was dropped. A bool in that slot now fails to compile.
- to_string now lists the 2D edge quadrature collisions - 2D builds now set num_quadrature_collision_pairs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Other translation units used the ESPCollisionTemplate specializations, including the id-sorting vertex-vertex constructor, with only the primary template visible, which is ill-formed (no diagnostic required). - Declare every ESPCollisionTemplate specialization after the class - Replace the two identical _near gradient specializations with one template and explicit instantiations Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The per-collision overload (formerly smooth_contact_force_jacobian) was declared but never defined. Define it as the Jacobian of the per-collision gcp_force with the cached normal force held fixed, and add the deprecated smooth_contact_force_jacobian alias. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Add a scalar template parameter so both support float, double, and SIMD batches like the other barriers - Hold the NearFarBarrier base in one shared_ptr, aliasing a borrowed raw pointer - Add numext::pow and a SIMD lane-wise agreement test Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Replace the per-id std::set maps with compressed sparse row arrays built by a counting sort, and return sorted AdjList ranges instead of std::set copies from the Candidates::*_set queries - Return views of the stored lists for ve_set and vf_set, which need no mesh topology and so allocate nothing - Add a behavioral test of every adjacency query against a reference built from the candidate lists and the mesh - Add an ESP benchmark that tracks the build, value, gradient, and Hessian cost of the lists On cloth-ball (1 thread), ESPCollisions::build drops from 1027 to about 490 ms and the ESP value and gradient get about 3x faster. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Candidates::operator[] subtracts each list's size from the index as it walks the candidate lists, so the out-of-range error printed the leftover offset instead of the index the caller passed. Keep the requested index for the message and update the two tests that still expected the old message text. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Rename AdjacencyCsr to AdjacencyCSR and give Relation a char underlying type - Define AdjacencyList after Candidates, forward declared above it, and move the adjacency code in candidates.cpp under its own section
- Query the built trees with a box around a point, so ESP no longer needs its own wrapper around LBVH - Build ArbitraryPointESP's tree with zero inflation directly through LBVH Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
zfergus
approved these changes
Oct 21, 2026
Member
|
Hi @fsichetti, I pushed a batch of commits directly to 💥 Changes that affect callers
🐛 Bug fixesESP
Elsewhere
Validation
⚡ Performance
Tests & housekeeping
PR descriptionThree parts of the description are now stale:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds the Extremum Sum Proximity Potential (ESP) as a new
ipc/esp/module, with supporting changes to barriers, candidates, collision meshes, friction and distance-type classification; also renamessmooth_contacttogcpwith appropriate compatibility aliases.Mechanism
ESPParameters:dhat, the near/far split parameterdbar_factorin [0, 2], the barrier (defaultNormalizedClampedLogBarrier), the 2Dquad_order, an optional 3D face quadrature rule,area_weightsandintegration_type.ESPCollisions: builds the quadrature collision set from broad-phase candidates.ESPPotential: value, gradient and Hessian, with PSD projection.use_near_far = true(the default), the 3D quadrature weights are normalized to sum to 1, split into near and far parts (NearFarBarrier) whendbar_factor > 0.ArbitraryPointESP<dim>: value, gradient and Hessian of the potential at an arbitrary point, with inclusion-exclusion weights for open and codimensional input.TangentialCollisions::buildoverload that takesESPCollisions; the existingFrictionPotentialconsumes the result.point_edge_distance_type_exact,point_triangle_distance_type_exact,edge_edge_distance_type_exact) built on three shared sign predicates, so their classifications agree.Impact
smooth_contact→gcprename removes most old header paths (see below).ESPParameters(without the barrier and face-rule settings),ESPCollisions,ESPPotential, theGCP*names andCandidates.build(..., all_types=False); the rest of the new API is C++ only.API changes
New public types outside
ipc/esp/InversePowerBarrier(p): b(d) = h(d) / d^p, where h is a cubic B-spline that vanishes atdhat.NearFarBarrier(base, alpha): splits a barrier into a near and a far part, with a smooth step betweenalpha * dhat / 2andalpha * dhat.DistanceTypeConfig, the*_distance_type_exactfunctions andis_parallel_edge_edge.Additions to existing classes
Candidates::build(..., all_types = false)andBroadPhase::detect_collision_candidates(..., all_types = false): in 3D,all_typesalso collects vertex-vertex, edge-vertex, edge-face and face-face candidates, for ESP only.Candidates: newef_candidates,ff_candidatesand adjacency sets (convert_candidates_to_sets(),vv_set()…ff_set()).CollisionMesh: a constructor overload with anobstacle_vertexmask;is_obstacle_vertex/edge/face();face_areas().NormalCollisions::set_skip_obstacles(bool), defaultfalse.BarrierPotential(..., use_squared_distance = true):falseevaluates the barrier on the unsquared distance, whereforce_magnitude()throws.CollisionStencil::name().💥 Breaking changes
ipc/smooth_contact/is renamed toipc/gcp/, and its classes toGCP*.SmoothCollision,SmoothCollisionTemplate,SmoothCollisions,SmoothCollisionsBuilder,SmoothContactParameters,SmoothContactPotential.TangentialPotential::smooth_contact_force*is renamed togcp_force*, with deprecated forwarders.smooth_contact/smooth_collisions.hppandsmooth_contact/smooth_contact_potential.hppremain, as forwarding headers; the other 15 old headers (and two.tppfiles) are gone.TangentialCollision::smooth_collisionis renamed togcp_collision, without an alias.Candidates::buildorBroadPhase::detect_collision_candidateswith the old parameter list (e.g.py::overload_cast) must add thebool.Known limitations
gcp_force_jacobian, always area-weights, and ignores theInversePowerBarrierpower thatESPPotentialapplies to edge-edge weights.integration_typehas no effect there.New dependencies
IPC_TOOLKIT_WITH_GEOGRAM(defaultON).PRIVATEand used only indistance_type_exact.cpp; no public header includes it.ipctkmodule there needlibgeogramat run time.tbb, and OpenMP when built with GCC.libgeogram; no PR check builds a wheel.OFF, the classifiers use floating-point predicates and log a warning once; no CI job builds this configuration.Other changes
FindSIMD.cmakeno longer emits both/arch:AVX2and/arch:AVX.Type of change
How Has This Been Tested?
New test files
test_esp_potential.cpp(30 cases, one hidden): FD derivatives, PSD projection, zero potential on closed meshes, bounded edge-edge terms near edge endpoints, and continuity indbar_factor.test_arbitrary_point_esp.cpp(8 cases): zero beyonddhat, FD derivatives, and inclusion-exclusion weights on open input.test_obstacles.cpp(5 cases): obstacle flags, obstacle skipping inNormalCollisions, and ESP integration types.test_vertex_matrix_view.cpp(5 cases).New cases in existing files
test_distance_type.cpp(+6): four random tests (10,000 samples each, geogram builds only) compare the classifiers with an exact geogram reference; two check mutual consistency and theuse_standardfallback.test_force_jacobian.cpp(+4): ESP friction force against −∇D and friction Hessian against finite differences, in 2D and 3D.test_candidates.cpp(+1, adjacency sets),test_barrier_potential.cpp(+1, unsquared distance),test_barrier.cpp(InversePowerBarriersections).TestESPPotentialandTestGCPAliases.Reproduce
cmake --preset=test && cmake --build --preset=test -j 8 && cd build/test && ctestpip install . && pytest python/tests/test_potentials.pyCI on
03c39d2Test Configuration:
IPC_TOOLKIT_WITH_GEOGRAM=ON,IPC_TOOLKIT_WITH_CUDA=OFFChecklist