Repository navigation
Conversation
…egration on new potential
test_avx_availability() emitted /arch:AVX2 and /arch:AVX from two independent ifs, so a host detecting both got "/arch:AVX2 /arch:AVX". /arch: is single-valued on MSVC and the last one wins, so every AVX2-capable Windows build was compiled as plain AVX. CI reported this as "SIMD support found: /arch:AVX2;/arch:AVX". This is not only a performance loss. MSVC has no separate FMA flag -- the FMA probe adds -mfma only on the GCC/Clang branch -- so /arch:AVX2 is the only way MSVC enables fused multiply-add. Dropping to /arch:AVX removes FMA, which changes rounding: a*b+c rounds twice instead of once, so results differ from the AVX2 build rather than merely being computed more slowly. Use if/elseif so AVX2 wins when detected, matching the AVX_VERSION selection a few lines above, which already does this. AVX-only hosts still get /arch:AVX and hosts with neither still get no flag. Co-Authored-By: Claude Opus 5 <[email protected]>
Brings in the GPU LBVH broad phase (ipc-sim#260), its profiling (ipc-sim#263), a scalable_ccd pin bump (ipc-sim#261), and a docs/output fix (ipc-sim#264). One conflict, in BroadPhase::detect_collision_candidates: upstream documented that the candidates are cleared first, while this branch had added the all_types parameter that ESP contact needs. The merged implementation already contains both -- candidates.clear() and the all_types branch -- so the declaration keeps our signature with upstream's wording, and documents all_types, which had no @PARAM entry before. Co-Authored-By: Claude Opus 5 <[email protected]>
Each predicate wrapper contained its exact-arithmetic fallback, which kept it from being inlined, so every classification made one out-of-line call per filter (~8-10) plus nested public point-edge calls. - Move the exact fallbacks out of line so the filtered fast path of every predicate inlines into the classifier. - Pass raw coordinate pointers and the dimension as a template parameter. - Check DistanceTypeConfig and initialize geogram's PCK once per classification instead of once per nested point-edge test. - Fix the trace message of the cross_dot_cross_2 fallback. Same filters in the same order; classifications are bitwise identical. Exact classification is 1.5-2x faster on real scenes (e.g., cloth-ball edge-edge 80 -> 52 ns), with no measurable change at the ESP level. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ocation Per-query allocation (a make_shared per collision, a hash map, a collision dict with its own std::set/std::map, full-stencil gradient and Hessian arrays) was ~30% of the run time of wildmeshing's smooth offset, which evaluates this potential millions of times per run. - Collisions are kept by value in per-thread lists, one per collision type (the types ESPCollisionDict stores), cleared between queries. - The symbolic cancellation is unchanged: same sub-feature reduction, same distance-type classification, same integer-weight merge by typed hash, done by linear search over the few collisions of one type. - Only the query vertex's block of each collision's gradient and Hessian is accumulated, instead of assembling the whole stencil and extracting it. Measured on the previous base (3a76d75, before the rename): value, gradient and Hessian agree with the old code to 3.6e-16 relative (summation order), no NaN/inf, including points 1e-9 delta above shared edges; ~2.4x faster per call; wildmeshing's cube offset run 456 s -> 337 s with a bit-identical output mesh. On this branch: the six [arbitrary_point_esp] tests pass; [esp_potential] fails the same 17 assertions with and without this commit (test data not downloaded here). Co-Authored-By: Claude Opus 5.5 <[email protected]>
ESP sums b(distance to each element) with one weight per element. The weights were fixed at the closed-mesh signs (3D: faces +1, edges -1, vertices +1; 2D: edges +1, vertices -1), which are right only for a closed manifold. On an open sheet the potential was exactly 0 beyond a boundary edge, and an edge in no face or a 2D isolated vertex entered as a negative barrier. The weights now follow the counting rule of the ESP supplemental (S2): for every point of the input, the weights of the elements containing it sum to one. They are computed once from the connectivity: - face: 1 - edge: 1 - (faces on it) - vertex: 1 - (edges at it) + (faces at it) This gives: - closed mesh: +1/-1/+1 as before, so results there are unchanged - boundary edge or vertex of an open sheet, end of an open polyline: 0 (S4) - edge in no face: 1; vertex between two such edges: -1 - isolated vertex: 1 - edge shared by k faces, 2D vertex with k edges: 1 - k Elements of weight 0 are skipped. Tests: on an open sheet, an open polyline, a 3D polyline in no face, isolated vertices and a 2D junction, the potential equals the barrier of the distance, and on the sheet its gradient matches finite differences. With the old weights the new test fails 18 assertions. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The search-and-replace in the smooth_contact -> gcp rename rewrote
historical release notes ("Rename GCPPotential to GCPPotential") and
turned the Python naming test into a contradiction: it asserted that
GCPPotential both exists and does not exist.
5f301a2 dropped the std:: prefix, relying on ipc::unordered_map being reachable through collision_mesh.hpp. It no longer is, so the Python module failed to compile. Matches upstream again.
ESPCollisions stored its four maps as ipc::unordered_map members and ESPCollisionDict::initialize took one as a parameter, so the public esp_collisions.hpp included utils/unordered_map_and_set.hpp and with it Abseil, a private dependency. tangential_collisions.hpp includes esp_collisions.hpp, so every friction user needed Abseil on its include path; the Python bindings failed to compile. - ESPCollisions holds the maps in ESPCollisions::Maps, behind a unique_ptr and a maps() accessor, as Candidates does with AdjacencySets. Only library code used the maps. - initialize() takes a named ESPCollisionPairMap, the same map type as before, so iteration order and results are unchanged. - Both types are defined in the internal esp/esp_collision_maps.hpp. Also drops an unused map.begin().value() that only compiled with robin_map, a pair map keyed by std::array<int, 3> instead of index_t, and a stray Abseil include in quadrature_potential.cpp. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The bindings still targeted the old high-order contact API and no longer compiled: they bound a use_adaptive_dhat overload of build(), an operator[] ESPCollisions no longer has, the removed QuadraturePotential class, and an ESPParameters constructor without area_weights. - ESPCollisions.build takes (mesh, vertices, param, broad_phase). - ESPParameters takes area_weights, and its defaults now match C++ (integration_type NORMAL). - ESPPotential takes use_near_far. Add Python tests for the parameter defaults, the gradient against central finite differences, and the Hessian shape. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The smooth_contact -> gcp rename broke every downstream user of the released names (e.g. polyfem uses SmoothCollisions, SmoothContactParameters and SmoothContactPotential). - C++: [[deprecated]] aliases SmoothContactParameters, SmoothCollisions, SmoothContactPotential, SmoothCollision and SmoothCollisionsBuilder. - Forwarding headers at ipc/smooth_contact/smooth_collisions.hpp and ipc/smooth_contact/smooth_contact_potential.hpp. - Python: SmoothCollision2, SmoothCollisions, SmoothContactParameters and SmoothContactPotential alias the GCP classes. Replace the SmoothPotential naming test with a check of the aliases. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Remove dead and experimental code: - Remove ProfileRegistry. Nothing reads it, and the ESP Hessian locked its global mutex once per quadrature point. - Restore gcp/ to main's content plus the deprecated aliases. The ESP-only distance helpers move to esp/esp_distance.hpp; half_edge_edge_mollifier had no callers. gcp_collisions_builder.cpp matches main again: upstream ipc-sim#188 had already reverted the by-value shared_ptr parameters. - Remove ESP adaptive support (AdaptiveSupport, smooth_clamp and their tests). It stays on the esp-adaptive-support branch. - Delete dead code: pair_distance.{hpp,tpp}, smoothed_offset_potential_linear.h, math/span.hpp (ESPPrimitive gets vertex_id(i)), Math::log_barrier (superseded by ESPParameters::barrier in c02cc43), CollisionMesh::is_watertight() and its edge-face adjacency, whose non-manifold check could never fire, and ESP debug counters and helpers. Fix: - 3D ESP with default parameters (quad_order 1, empty face rule) built neither vertex nor face collisions, keeping only edge-edge contact: the build keyed on quad_order and the potential on face_quad_rule. Both now key on face_quad_rule; quad_order only sets the 2D rule. - Revert the EA_EB parallel-edge fallback in core edge_edge_distance and the srand(0) added to its test. Its absolute 1e-20 threshold made d² 26x too large for perpendicular edges 1e-6 long. ESP keeps the fallback in edge_edge_distance_parallel_safe. - Candidates::build no longer copies the CollisionMesh; the adjacency-set queries take the mesh instead, and clear() resets them. ESPCollisions::build converts its own copy of the candidates instead of const_casting the caller's. - Move ESP friction to esp/esp_tangential_collisions.cpp, and attribute edge-edge mollifier weights through edges_to_faces instead of scanning every face per pair. - Only look up obstacle edges when skip_obstacles is set. - Build: drop the duplicated CUDA block, the tests' Abseil/robin_map links and the Eigen recipe's EIGEN_DONT_VECTORIZE default (define it on ipc_toolkit with or without SIMD instead), and link geogram privately. - Python: nest IntegrationType under ESPParameters and fix the ESP docstrings. Tests: - Restore the two commented-out codim normal-collision tests. - Fix the FV mollification test's cube.obj path; it always skipped. - Add tests for obstacle flags, skip_obstacles, the ESP integration types, BarrierPotential with unsquared distances, and the 3D ESP quadrature default. - Test the exact distance-type classifiers against the reference (renamed *_reference), with 100k samples instead of 1M. - Hide the 15-minute ESP "Expensive" test in every build, and drop the assertion-free "Number of Pairs" test and the benchmark_eigen experiment. Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Deprecated aliases for SmoothCollisionTemplate and
TangentialPotential::smooth_contact_force{,_jacobian,_jacobian_unit}.
- Fix the warnings in the PR's code: lambdas captured structured
bindings (a C++20 extension), an old-style cast, a switch without a
default, and the assert-only total_p_far.
Without geogram, point_edge_distance_type_exact, point_triangle_distance_type_exact and edge_edge_distance_type_exact fell back to the standard analytic routines. Those are separate floating-point formulas, so near a region boundary they can disagree with each other: the ESP builder classified a face-vertex pair as P_E0 and the Edge3P1-Vertex3 collision then asserted P_E on that edge. With geogram off, ESP's debug assertions failed and the potential on a convex sphere was a round-off value instead of exactly zero. - Without geogram, evaluate the same sign predicates (dot3, cross_dot_cross_1/2) in double precision and keep the shared classifiers. Each predicate is out of line, so it returns the same sign for the same arguments at every call site, and the three classifications agree with each other by construction. - Log a one-time warning that the predicates are not exact. - ArbitraryPointESP built its collisions with the standard classifiers while the collision templates assert with the exact ones; at exact ties (e.g. a query point above a boundary vertex) they disagreed, with or without geogram. Use the exact classifiers there too. - Test that the classifiers are mutually consistent near region boundaries, in builds with and without geogram. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
- Define EIGEN_DONT_VECTORIZE only with IPC_TOOLKIT_WITH_SIMD again, as on main. Defining it unconditionally changed Eigen's object layout for every SIMD-off build (including the Linux Python wheels) and disagreed with MeshFEMSparse, which still defines it only with SIMD. - Remove the ESPCollisionTemplate static_assert that required Eigen vectorization to be off. The ESP primitives hold no Eigen members, and the ESP tests pass with vectorization on. - Default IPC_TOOLKIT_WITH_GEOGRAM to OFF, so the new dependency is opt-in. Without it, the distance-type classifiers use consistent floating-point predicates. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
tests-data's cube.ply is the same unit cube as the cube.obj this PR committed under tests/src/tests/potential/ (same vertices and triangles, only the vertex and face order differ), so load it with tests::load_mesh like the other tests and delete the copy. The old path reached it through DATA_DIR / "../src/...", which only worked with the default IPC_TOOLKIT_TESTS_DATA_DIR. Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
ESP collisions encode their distance type in their class and assert it when evaluated (Vertex2-Edge2P1 only at P_E), so evaluating the set built at V at an FD stencil point across a switch aborted in Debug, with or without geogram (mesh_1: a P_E pair 3.8e-10 inside its region, FD step 1e-8). - Gradient: rebuild the collisions at each perturbed configuration. The potential is C1 across switches, so the FD may cross one. mesh_1 (880 DOFs) checks a directional derivative, as the 3D tests do, because a full FD with a rebuild per evaluation is too slow. - Hessian: keep the FD of the analytic gradient on the set built at V. Rebuilding does not work there: the potential is only C1 across a switch, so a central difference averages two one-sided Hessians. Following the GCP tests, the Hessian is checked only where no stored P_E pair is within the FD step of a switch. Rounding leaves pairs about 1e-17 from one in the squares (order 14) and mesh_2 (orders 7 and 14), so those sections check the gradient only. Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
- Use the near/far split for every 0 < dbar_factor <= 2 (was (0, 1)). The far part of NearFarBarrier vanishes identically at 2, so the potential is continuous in dbar_factor, and dbar_factor = 1 is now a real split. The normalized unsplit branch is only reached at 0, where edge-edge terms are skipped, so the combined per-face PSD projection covers every case with indefinite weight-derivative terms. - Cap the edge-edge weight support at dhat: the mollifier and the edge-edge cutoff use min(dbar, dhat) (ESPParameters::ee_support()), also in the tangential collisions. - Keep edge-edge collision sets that cancel to empty, so their mollifier weight still counts in the face's weighted average; the potential jumped when a set changed between empty and non-empty. - ESPParameters throws std::invalid_argument for dbar_factor outside [0, 2] and warns at 0. Default dbar_factor 1.0 -> 0.2 (C++ and Python). - IPC_TOOLKIT_WITH_GEOGRAM defaults to ON again. - Tests: dbar_factor range, NearFarBarrier far part at alpha = 2, continuity in dbar_factor at 1 and 2, cancelled edge-edge sets; both Hessian PSD tests also run on two-cubes-close. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
- ESPParameters::face_quad_rule is now private. Set it with set_quad_rule(), which throws std::invalid_argument for a negative or non-finite weight, or for weights that sum to zero. A negative weight makes that point's barrier term unbounded below as it approaches contact (and broke the PSD projection of the per-stencil Hessian branches). get_quad_rule() is unchanged. - Breaking: callers that assigned params.face_quad_rule must call params.set_quad_rule() instead. - Remove the quad_order 6/8 and 10-12 log messages from ESPParameters: they describe a downstream triangle-rule table, while here quad_order only selects the 2D Gauss-Lobatto rule, whose weights are positive. - Tests: rule validation; the 3D friction force-jacobian test uses set_quad_rule(). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
- set_quad_rule() also throws std::invalid_argument for a negative or non-finite barycentric coordinate (point outside the face). Points whose coordinates do not sum to 1 (within 1e-10) only log a warning. - Remove the quad_order > 14 check from ESPParameters: quad_order n selects the (n + 1)-point Gauss-Lobatto rule, which is tabulated up to 19 points and computed beyond, and get_rule() already throws for n < 1 when the 2D rule is used. quad_order is unused in 3D. - Tests: coordinate checks and the warning; Gauss-Lobatto weights are positive and sum to 1 for orders 1-25. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
- Each rejected coordinate case now has exactly one bad coordinate, so +inf is tested on its own (it was previously rejected via -inf). - Capture the expected warning by swapping the logger's sinks, so it no longer prints to stdout. Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
Drop the infinite-coordinate case and the warning-capture block; keep the negative and NaN coordinate cases. Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #259 +/- ##
==========================================
- Coverage 96.92% 93.21% -3.72%
==========================================
Files 194 221 +27
Lines 17349 22605 +5256
Branches 944 1570 +626
==========================================
+ Hits 16816 21071 +4255
- Misses 533 1534 +1001
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- MSVC: the generic operator_nearfar, gradient_nearfar and hessian_nearfar were defined inline in the ESPCollisionTemplate class body, while the 3D versions are explicit specializations in the .cpp that the header does not declare. MSVC put the zero stubs in the vtable, so every ESP energy on the near/far path was 0.0 on Windows. Define the stubs out of line in the .cpp, as operator(), gradient() and hessian() already are. - clang-tidy: ESPCollisions::build takes const ESPParameters& (performance-unnecessary-value-param); the Python binding's overload_cast follows. - Debug timeouts: the Hessian PSD tests compute eigenvalues only on the DOFs with nonzero Hessian entries (the others are exact zeros). Convergent Quadrature Hessian PSD: 555 s -> 15 s locally in Debug. - The face quadrature tests looped over quad_order, which 3D ignores. They now set positive-weight face rules with set_quad_rule(); the PSD test covers dbar_factor 1, 0.4 and 0 (48 runs instead of 96; 1691 s -> 46 s locally in Debug). - Docs of ESPCollisions::build and the compute_minimum_distance docstring (squared distance) ride along in the touched files. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
- Dependencies page: geogram row (IPC_TOOLKIT_WITH_GEOGRAM, BSD-3) and a note on the floating-point fallback; geogram node in dependencies.dot (dependencies.svg still needs regenerating). - Barrier API reference: InversePowerBarrier and NearFarBarrier pages. - NearFarBarrier: document alpha, the near/far split and the near/far methods. - ESP doc comments: ESPCollision and ESPCollisionDict no longer describe GCP, fixed vertex counts or finish_insertion(); the barrier, area_weights, use_near_far, normalize_weights and the remaining build/hessian parameters are documented; stale comments about quad_order, Gauss-Lobatto point counts and "HOP" are fixed. Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
The unsquared branches of operator(), gradient() and hessian() returned the barrier without the stiffness factor, which upstream moved into BarrierPotential. They now scale by stiffness() as the squared branches do. The test runs with stiffness 1 and 3.5, with and without the physical barrier, and checks that force_magnitude_gradient() throws. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
The continuous overload accepted all_types but never passed it to the broad phase. Only the discrete overload, which ESP uses, needs it. The signature and its Python binding match upstream again. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
Fixes: - The ESP TangentialCollisions::build never reset the lagged friction coefficients, which default to 0, so ESP friction was identically zero. It now calls reset_lagged_anisotropic_friction_coefficients() like the other overloads, and the friction test requires a nonzero force. - ESPPotential::hessian returned a 0x0 matrix on a 3D mesh without faces. - ESPCollisions::to_string read the face quadrature point, a virtual vertex, out of bounds. Face collisions now print ids and weights only. Dead code (each removal verified against its callers): - Edge-edge guards for non-EA_EB types and shared vertices, which the builder already filters out, become asserts. The ESP edge-edge distance helpers keep only the EA_EB case. - Zero-weight fallbacks of the near/far normalization, the dbar_factor = 0 edge-edge terms (the edge-edge pairs are skipped there), skips that ee_set/ef_set already guarantee, the obstacle-edge candidate check that was always true, the deep copies of the TBB exemplar and the unused copy assignment of QuadratureCollisionsBuilder, the uninstantiated Edge3P1-Edge3P1 distance and the ESPCollision near/far default bodies (now pure virtual). - The 20-point Gauss-Lobatto rule now uses its table. Tests: ESP friction with edge-edge contact, two cubes and zero stiffness; obstacle integration types with a face rule, in 2D and with dynamic vertex-vertex candidates; dbar_factor = 0; a 3D mesh without faces; 2D Hessian projection; an edge-midpoint face rule; collision accessors and stencils; distance helpers; candidate adjacency sets; and error paths. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
Rename the ESPParameters constructor parameter dbar_factor_value, which shadowed the member of the same name, to _dbar_factor like the other parameters, and use static_cast in ESPCollisionTemplate::vertex_id. Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
Remove PointPotential::build_collisions_at_face_center and the gradient and Hessian at the face center, with and without the near/far split. Nothing in the library or the Python bindings called them; ESPPotential uses the face-interior-point versions. The test that only checked them against each other goes with them. The two value functions stay: they evaluate the potential at every face quadrature point. Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
evaluate_potential_at_face_center_with_cached_collisions and its _nearfar version evaluate at any face quadrature point, not only the center. They now match the gradient, Hessian and build functions, which already use face_interior_point. Claude-Session: https://claude.ai/code/session_01R7sJzFKyZAgyK7X4Vs6mXf
This branch has not been deployed
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
Implementation of the SigAsia paper "Extremum Sum Proximity Potential".
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Built and ran the test suite locally on macOS/arm64.
This branch adds the following tests, all passing locally:
New test files
tests/src/tests/potential/test_esp_potential.cpp(19 cases,[esp_potential])ESP potential in 2D and 3D: convergent-quadrature edge-edge limits under
three barriers, gradient/Hessian finite differences, Hessian PSD-ness,
codimensional collisions, adaptive support, NearFarBarrier decomposition.
tests/src/tests/potential/test_arbitrary_point_esp.cpp(6 cases,[arbitrary_point_esp]) Evaluating the ESP at an arbitrary off-mesh pointin 2D/3D: zero beyond dhat, FD gradient/Hessian, and that
evaluate()agrees with
operator()/gradient()/hessian().tests/src/tests/potential/test_smooth_clamp.cpp(12 cases,[smooth_clamp])smooth_clamp01andsmooth_clamp_simplex: anchorvalues, saturation, monotonicity, C0/C1 continuity at knots, FD-vs-analytic
derivatives, and simplex partition-of-unity.
tests/src/tests/utils/test_vertex_matrix_view.cpp(5 cases,[vertex_matrix_view]) Non-owning two-matrix vertex view: concatenationagainst a naive vstack, aliasing semantics, empty-matrix edge case.
New cases in existing files
test_distance_type.cpp: four randomized tests comparing the analyticdistance-type classifiers against a geogram exact-predicate reference
(new
distance_type_reference.hpp), including the near-parallel edge-edge case.test_force_jacobian.cpp: ESP friction force-Jacobian in 2D and 3D(
[friction-esp]).test_barrier.cpp: log barrier derivatives.Test Configuration:
IPC_TOOLKIT_WITH_GEOGRAM=ON,IPC_TOOLKIT_WITH_CUDA=OFFChecklist