Skip to content

Have ContactFormulation-derived classes own search - #276

Merged
ebchin merged 17 commits into
developfrom
feature/ebchin/contact-search
Oct 28, 2026
Merged

ebchin merged 17 commits into
developfrom
feature/ebchin/contact-search

Conversation

@ebchin

@ebchin ebchin commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

This PR moves coarse search and formulation-specific candidate filtering into ContactFormulation-derived classes.

  • The formulation factory constructs and injects owned CoarseSearch and RefinedSearch strategies.
  • Formulation operations receive current mesh views, and Energy Mortar finds candidate pairs for each gap or force calculation rather than retaining mesh views or a fixed pair list.
  • ProjectedEdgeSearch refines two-dimensional linear-edge candidates by rejecting exact self-pairs, optionally rejecting shared-node pairs, and requiring nondegenerate edge normals separated by at least 90 degrees. It leaves projected-overlap construction to Energy Mortar quadrature generation.
  • InterfacePairChecks provides the reusable topology and edge-orientation checks without requiring face-data preprocessing.
  • Search inputs remain unchanged, and refined search returns owned retained candidates in the input allocator for sequential, OpenMP, CUDA, or HIP execution.
  • Mesh 1 is consistently the non-mortar integration side and mesh 2 is the mortar side, including MFEM field registration and Energy Mortar assembly.
  • The effective binning proximity scale is computed from the configured scale and current mesh length instead of being cached.
  • Penalty configuration is applied through the formulation factory rather than a method-specific base-class setter.
  • Regression coverage includes filtering, ownership, current mesh coordinates, mesh ordering, unequal surface meshes, disjoint projected intervals, and zero-width integration intervals.

Validation: tribol_refined_search and tribol_interface_pair_checks pass with LLVM 19 in Debug with Enzyme. Release validation also covered Energy Mortar penalty/LM patch and finite-difference suites. Sequential and OpenMP execution were exercised; CUDA/HIP remain for CI.

This is the first PR in the replacement stack. Replaces #275.

Move projection configuration and coordinate-only geometry into the search branch. Construct the configured projection once and retain it in ProjectedEdgeSearch, while preserving the existing Energy Mortar interface.

Keep projection bounds independent of quadrature storage so downstream quadrature generators can reuse them without introducing a dependency into contact search.
Remove the projection template and configuration from refined edge search, retaining self-pair, shared-node, and opposing-normal checks. Restore its implementation to a source file and remove unused projection strategies from this branch.

Treat empty penalty integration intervals as inactive. Cover retained disjoint pairs, current orientation, and zero quadrature contributions in regression tests.

@srwopschall srwopschall left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly all good. Per our 3 hour convo today this stuff and the new language we are developing can be confusing. It can also be a little more difficult to review knowing that the design is actively changing PR to PR. A lot of my comments reflect this and ask for more clarity.

Comment thread src/tests/tribol_mfem_jacobian.cpp Outdated
int mesh1_id = 100;
int mesh2_id = 101;
tribol::registerMfemCouplingScheme( cs_id, mesh1_id, mesh2_id, mesh, coords, mortar_attrs, nonmortar_attrs,
tribol::registerMfemCouplingScheme( cs_id, mesh1_id, mesh2_id, mesh, coords, nonmortar_attrs, mortar_attrs,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need a helpful comment about mesh id ordering?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, added. Renamed meshes to mortar/nonmortar.

}
}

TEST( InterfacePairChecks, rejects_degenerate_projection_edges )

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify any test that relies on that old projection bounds check in 2d is removed or updated.

Comment thread src/tests/tribol_refined_search.cpp Outdated
* @file
* @brief Test how ProjectedEdgeSearch filters candidate pairs and returns the accepted pairs.
*
* These tests check that filtering keeps only accepted pairs, leaves the input unchanged, and returns a separate array.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clarify what "filtering" means exactly here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarified what filtering removes and returns

Comment thread src/tests/tribol_refined_search.cpp Outdated
* @brief Test how ProjectedEdgeSearch filters candidate pairs and returns the accepted pairs.
*
* These tests check that filtering keeps only accepted pairs, leaves the input unchanged, and returns a separate array.
* They also check shared-node rejection, deferred overlap calculation, updated coordinates, and empty results.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify that the "interface_pair" checks don't overlap or duplicate any of the checks here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, verified. This is more verifying the composition, execution backends, array ownership, etc.

Comment thread src/tests/tribol_refined_search.cpp Outdated
*
* These tests check that filtering keeps only accepted pairs, leaves the input unchanged, and returns a separate array.
* They also check shared-node rejection, deferred overlap calculation, updated coordinates, and empty results.
* Individual geometry checks are tested in tribol_interface_pair_checks.cpp.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does individual geometry checks mean? It looks like checks here are going through the full CG on actual topology.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good point, there are still projections in InterfacePairChecks that aren't being used anymore. I removed those and cleaned up related tests and restored the projection in EnergyMortar for now (it will be removed in the quadrature PR). Also, make the comment specific.

* space. Candidates and both meshes must use the same allocator, accessible from the selected execution mode.
* No face-data preprocessing is required. Temporary storage scales with the candidate count, not all possible pairs.
*/
class ProjectedEdgeSearch final : public RefinedSearch {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is basically a 2D cg filter? But is this responsible for computing overlaps?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it filters candidates. Quadrature computes the overlap.


/**
* @file
* @brief Filter edge candidates by topology and orientation without calculating projected overlap.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify that this does not compute overlaps. Should it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not, that will be done in the quadrature (next PR).

* @param mesh2 Current target mesh view.
* @return Owned accepted pairs in the input allocator; their order is unspecified.
*/
ArrayT<InterfacePair> filterCandidatePairs( const ArrayT<InterfacePair>& candidate_pairs, MeshData::Viewer mesh1,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that the refined search should compute overlap pairs. This is somewhat different than what we talked about. Does energy mortar just compute and store that info differently than in legacy common plane and mortar? As in, this does not use CompGeom stuff? If that is the case, these approaches will have to be merged and refactored per our discussion on the purpose of a refined search and when/where overlaps are computed using comp geom machinery so all the CG stuff is unified.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No CompGeom stuff for 2D energy mortar. It's simple enough to not need it. 3D common plane should use it, but 2D likely will not either.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a 3D common plane refined search class, we can include CompGeom

Comment thread src/tribol/search/RefinedSearch.hpp Outdated
virtual ~RefinedSearch() = default;

/**
* @brief Filter current candidates and return an owned array of accepted pairs

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this does not or is not intended to compute overlaps with the comp geom machinery perhaps make this very clear since all of this is in some sort of flux. If this is just meant to be a geomFilter() type operation, clarify what "accepted pairs" means as this point. This looks like it is probably further refinement of the candidate pair list to exclude self-pairs or pairs that share a node etc. "Accepted pairs" isn't clear as to what that means.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the language here and elsewhere. Generally, accepted -> retained

Comment thread RELEASE-NOTES.md
## [Version 0.2.0] - Release date YYYY-MM-DD

### Added
- Added `ProjectedEdgeSearch` to reject self-pairs, optionally reject shared-node pairs, and require opposing edge

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider "Added ProjectedEdgeSearch as a derived refined search to reject....

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should discuss what belongs here, more generally. I think this is too verbose. We should keep it to user-facing changes or underlying changes that give new behavior that would be noticeable to users. We can encode that in e.g. CONTRIBUTING.md.

@ebchin
ebchin merged commit 1c123f0 into develop Oct 28, 2026
14 checks passed
@ebchin
ebchin deleted the feature/ebchin/contact-search branch October 28, 2026 20:54
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.

2 participants