Contact API Boundaries#
This page fixes terminology, ownership, and scope for contact APIs.
Object Model#
contact: geometric and pairing description of the interface. It owns master/slave surfaces, trace pairing/supermesh, normals, and interface quadrature.multiplier: discrete LM space definition for constraint-family assembly. It owns LM family (nodal/p0), side, value dimension, and optional facet connectivity.formulation: enforcement/formulation intent used by assembly routing. Typical values are multiplier-family (mortar/KKT) and penalty-family (Nitsche-like).ops: assembled operator bundle to pass into system builders. For constraint-family: coupling/B/Kuu (+ optional residual/jacobian metadata). For penalty-family: residual/jacobian (+ metadata).
Dependency Direction#
The intended dependency chain is:
contact -> multiplier -> formulation/assembly -> ops -> CoupledSystemBuilder
contact and multiplier are defined separately, but are coupled at assembly time.
Axes: family / enforcement / formulation#
Current public interpretation:
family: high-level route (constraintorpenalty)enforcement: concrete route (mortarornitsche)formulation: variant within the route (examples:multiplier/augmented_lagrangian/penalty_consistent)
Rule: keep one meaning per axis and use the same terms in builder/docstrings/tutorials.
Configuration Scope#
Settings are scoped as follows:
contactscope: geometry, pairing/supermesh, quadrature, backend and Jacobian assembly behavior.multiplierscope: LM discretization parameters (family/side/value_dim/facet_conn).formulationscope: enforcement-specific parameters and weak-form variant choices.builder.add_contact(...)call scope: routing choice and per-contact runtime options; each call can use different values.
For multiple contacts:
Separate
add_contact(...)calls can use different family/enforcement/formulation/multiplier choices.OneToManyContactSurfaceSpacegroups multiple pair contacts under one contact object; settings passed when creating that object are shared by that object.
Known Constraint: p0 Side#
ContactMultiplierSpace(family="p0") currently supports side="master" only.
This is an implementation limitation in the current code path, not a mathematical requirement.
Use side="master" for now and treat side="slave" for p0 as future work.
Guarantees Covered by Tests#
Current tests explicitly target these guarantees:
multiple contact contributions can be added to one coupled system,
mortar/KKT assembly remains valid when different contacts have different lambda sizes,
route consistency for penalty vs constraint contact operators.
Backend Direction#
The intended backend direction for contact is numpy/jax parity on the
main public paths.
The reason is split by use case:
numpyis the preferred lightweight reference/debug backendjaxis the preferred backend for autodiff, Jacobians, and nonlinear contact assembly
Implementation priority should follow this order:
pair contact
one-to-many contact
one-sided contact
full weak-form Jacobian parity
Until that work is complete, treat the auto-selected JAX path as the default
route for advanced contact assembly and use explicit backend="numpy"
primarily where parity has already been validated.
Coordinate Differentiation#
Coordinate differentiation is not yet a general guarantee for contact.
Current practical status:
volume assembly already has working JAX-based examples of differentiation with respect to coordinates
surface linear-form assembly also has direct coordinate-differentiation tests
contact assembly still contains several NumPy-only geometry conversion paths, so geometry tracing is not yet robust across the main contact routes
In particular, the current contact interface code still relies on NumPy geometry materialization in several places such as:
np.asarray(surface_a.coords, dtype=float)np.asarray(surface_b.coords, dtype=float)facet-area and facet-shape helper loops that build NumPy arrays from quadrature-point geometry data
So the current rule should be:
assume coordinate differentiation is available for JAX volume/surface paths
do not assume it for contact until the geometry pipeline is made tracer-safe
The natural implementation order is:
remove
np.asarray(...coords...)barriers from pair contact geometry prepreplace NumPy facet-shape/facet-area accumulation loops on the pair path
validate JAX coordinate gradients on pair contact before extending to one-to-many and one-sided paths