Include nodal normal derivatives in mortar contact Jacobians - #33390
Include nodal normal derivatives in mortar contact Jacobians#33390Andreas-Lepak wants to merge 9 commits into
Conversation
|
Job Documentation, step Docs: sync website on 250e9c7 wanted to post the following: View the site here This comment will be updated on new commits. |
99aaad9 to
8d19377
Compare
lindsayad
left a comment
There was a problem hiding this comment.
It appears that you're able to make tests pass by simply changing the comparison tolerance which is good and makes sense. If we'd needed a bunch of regolds (which would be an indication of something problematic) I would've suggested also doing #33422 at this time ... but let's not
| exodiff = 'frictional-nodal-min-normal-lm-mortar-pdass-tangential-lm-mortar-disp_out.e' | ||
| detail = 'using verbose input file' | ||
| cli_args = "Postprocessors/active=''" | ||
| # The nodal-normal Jacobian changes the PJFNK path while preserving the converged solution. |
There was a problem hiding this comment.
we need to modify AGENTS.md or something so that agents stop adding comments based in historical context. I don't think this comment nor other comments like it will be helpful outside of this pull request and may even add confusion to future readers of the test spec
8d19377 to
9a778ca
Compare
c979c00 to
a9eba82
Compare
|
Distributed LM contact can still cause local-local PETSc reallocations under strict preallocation. Fixing this properly requires a new mortar-specific extra-sparsity registration mechanism; the relationship manager cannot return locally owned elements. I left that out because it is not causing these CIVET failures and the attempted shortcuts either violated libMesh ownership rules or substantially over-densified the matrix. I do not recommend restoring structural-zero insertion. (generated by GPT-5 via Codex) |
refs idaholab#33378 Co-authored-by: Andreas Henrik Frederiksen <andreas.frederiksen@inl.gov> Co-authored-by: OpenAI Codex <codex@openai.com>
refs idaholab#33378 Co-authored-by: Andreas Henrik Frederiksen <andreas.frederiksen@inl.gov> Co-authored-by: OpenAI Codex <codex@openai.com>
refs idaholab#33378 Co-authored-by: Andreas Henrik Frederiksen <andreas.frederiksen@inl.gov> Co-authored-by: OpenAI Codex <codex@openai.com>
refs idaholab#33378 Co-authored-by: Andreas Henrik Frederiksen <andreas.frederiksen@inl.gov> Co-authored-by: OpenAI Codex <codex@openai.com>
a9eba82 to
250e9c7
Compare
|
You can use hash table matrix assembly to avoid relying on preallocated sparsity patterns |
| // MetaPhysicL stores sparse derivative indices in sorted order, so equal index arrays identify | ||
| // rows with the same derivative support regardless of insertion order. | ||
| if (current_dofs.size() != first_dofs.size() || | ||
| !std::equal(first_dofs.begin(), first_dofs.end(), current_dofs.begin())) |
There was a problem hiding this comment.
This is quite a disruptive change. We have never failed this assertion before, sometimes with dof set sizes of several hundred. This has now introduced an O(several hundred) comparison for those dense sparsity cases roughly per element in all compilation methods. I think we should try very hard not to do this
|
Job Test, step Results summary on 250e9c7 wanted to post the following: Framework test summaryCompared against 846a5c4 in job civet.inl.gov/job/4025777. Added tests
Modules test summaryCompared against 846a5c4 in job civet.inl.gov/job/4025777. Added tests
|
lindsayad
left a comment
There was a problem hiding this comment.
I have left line-level comments on the remaining correctness and SQA issues.
Design note: I do not think static preallocation can be made reliable for moving-mesh contact. The contact sparsity pattern may change at the first nonlinear iteration, and coupling functors and matrix preallocation will not be rerun at every nonlinear iteration. If the goal is to avoid new nonzero allocations, hash-table matrix assembly is the appropriate mechanism.
Suggested: add a July 2026 newsletter entry because this changes default Jacobian behavior and the assembly implications are important for users.
Review generated by GPT-5 via Codex, at the request of @lindsayad.
|
|
||
| /// Enable derivatives during construction of a supported quasistatic contact constraint. | ||
| /// Dynamic contact uses the same user object classes and intentionally leaves this disabled. | ||
| void includeNodalNormalDerivatives() const; |
There was a problem hiding this comment.
Required: includeNodalNormalDerivatives() changes observable behavior by setting _use_nodal_normal_derivatives, so this is configuration state rather than a logical cache. Please avoid configuring it through a const method and mutable flag. Make this construction-time state, or use an explicit non-const configuration path.
(generated by GPT-5 via Codex)
| "Face nodal geometry vectors and quadrature weights must have the same size."); | ||
|
|
||
| // Use the parent-side map rather than a standalone lower-dimensional basis. This preserves | ||
| // enriched mappings such as the TET14-to-TRI7 face. |
There was a problem hiding this comment.
Required: Add a TET14/TRI7 contact regression that exercises this enriched parent-side mapping. The new tests cover TET10/TRI6 and HEX27/QUAD9, but not the exceptional mapping singled out here; without that test, this branch’s stated design rationale is not covered by an SQA requirement.
(generated by GPT-5 via Codex)
| return; | ||
|
|
||
| if (!_allow_nodal_normal_derivatives) | ||
| mooseError("Nodal-normal derivatives are not supported by user object '", name(), "'."); |
There was a problem hiding this comment.
Required: Add RunException coverage for the new validation paths: an unsupported weighted-gap user object, a non-nodal displacement variable, and a displacement variable in a different nonlinear system. The current interpolated_normals_rejected test exercises only the interpolation check.
(generated by GPT-5 via Codex)
|
|
||
| auto nodal_normal = weighted_area_vector.unit(); | ||
| const auto & stored_normal = libmesh_map_find(_secondary_node_to_nodal_normal, secondary_node); | ||
| mooseAssert((MetaPhysicL::raw_value(nodal_normal) - stored_normal).norm() < 100 * TOLERANCE, |
There was a problem hiding this comment.
Required: Add nearby rationale for why 100 * TOLERANCE is the appropriate equivalence threshold here. AGENTS.md requires the source or numerical rationale for non-obvious tolerances so future changes can distinguish numerical intent from an arbitrary allowance.
(generated by GPT-5 via Codex)
| TEST(MortarNodalGeometryTest, weightedNormalAndHouseholderTangents) | ||
| { | ||
| constexpr dof_id_type derivative_index = 0; | ||
| constexpr Real epsilon = 1e-7; |
There was a problem hiding this comment.
Required: Add a nearby comment explaining the finite-difference step and how it supports the 1e-8 derivative and 1e-14 orthogonality tolerances below, including the relevant truncation or roundoff rationale.
(generated by GPT-5 via Codex)
|
Job Coverage, step Generate coverage on 250e9c7 wanted to post the following: Framework coverage
Modules coverageContact
Full coverage reportsReports
This comment will be updated on new commits. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
closes #33378
Reason
Mechanical mortar contact updates its averaged secondary nodal normals as the displaced geometry changes, but their coordinate variation is currently omitted from the Jacobian. This leaves out normal-direction and tangent-basis contributions on curved interfaces.
Design
Include derivatives of the normalized, nodal-JxW-weighted secondary normals and their Householder
tangent basis by default for quasistatic frictionless and Coulomb contact using the
mortarandnon-augmented
mortar_penaltyformulations. Residual-only evaluations retain the stored geometryvalues.
The implementation shares the oriented face-area construction used by
Assembly::computeFaceMap().It forms the JxW-weighted nodal area-vector sum directly from nodal coordinates,
and lets AD differentiate the edge rotation or face cross product, averaging, normalization, and
Householder tangent construction. The stored residual normals and their Jacobian derivatives use
this same construction.
The nodal-normal derivatives span the secondary face one-ring, so the existing mortar relationship
manager path adds the corresponding ghosting and sparsity couplings. Because different contact
residual rows can then have different sparse AD supports,
Assembly::cacheJacobian()forms theirunion column layout before applying constraints. Its common-support path remains unchanged.
The mortar segment topology, projection coordinates, integration measures, moving overlap boundaries, and active-set changes remain frozen. Dynamic mortar, augmented-Lagrangian penalty contact, Cartesian-LM, cohesive-zone, and nonmortar formulations retain their existing behavior.
Impact
Contact values and residual equations are unchanged, but supported quasistatic mortar inputs gain additional Jacobian entries and one-ring sparsity couplings by default. This can change nonlinear convergence and adds setup, storage, and assembly cost. The required AD capacity depends on the valence of the secondary node star; high-order or highly connected interfaces may require configuring MOOSE with a larger derivative size.
Direct dynamic-contact inputs now use dedicated dynamic weighted-gap and weighted-velocity objects
so their frozen-normal behavior remains explicit.
ContactActionselects these objectsautomatically.