Skip to content

Commit f00c24e

Browse files
authored
Merge pull request #31268 from lindsayad/mpai60-contact-input-30433
Avoid exceptions during projection of primary nodes when nodes are aligned
2 parents 2acb415 + a7e38e2 commit f00c24e

File tree

99 files changed

+1722
-872
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+1722
-872
lines changed

framework/doc/content/source/constraints/AutomaticMortarGeneration.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
# AutomaticMortarGeneration
22

33
The `AutomaticMortarGeneration` class is used to define mortar segment meshes to properly integrate discontinuities caused by normal projections of non-matching, faceted meshes.
4+
The mortar segment mesh is always replicated when the parent mesh is allowed to displace, otherwise
5+
its distribution type (replicated/distributed) is determined by the type of the parent mesh. The
6+
reason the mortar mesh is replicated during displacement is that we always build the mortar mesh by
7+
looping over all active elements associated with the secondary and primary interface, not just
8+
active local elements. When displacement is occurring we cannot know *a priori* what elements will
9+
project onto each other, so absent that knowledge we keep copies of all interface elements on each
10+
process. In the future we may eliminate this replication and implement communication patterns that
11+
occur during each residual and Jacobian evaluation to pull remote elements. This would improve
12+
memory scalability. Even for the current implementation where the interface of the parent mesh is
13+
replicated, one could legitimately ask why the mortar mesh needs to be so. The answer is that
14+
`MortarNodalAuxKernel` derived classes require access to all mortar segment elements, local or not,
15+
that have support from the shape function associated with a given node. In the future we may add
16+
ghosting functors to the mortar segment mesh, which would allow us to delete unnecessary non-local
17+
elements.
418

519
## 2D
620

@@ -25,7 +39,7 @@ While first-order, QUAD4 faces are (in general) not linear. The 'twisting' or 'p
2539
Elements defined on second order geometries are curvilinear so to simplify the 'clipping' procedure both secondary and primary face elements are subdivided into first-order face elements then subsequently linearized (illustrated below). The same clipping and triangularization routine is then applied on the linearized sub-elements to create the mortar segments. See [!cite](puso2008segment).
2640

2741
!media media/framework/constraints/Second-Order-Linearized.jpg
28-
style=display:block;margin:auto;width:70%
42+
style=display:block;margin:auto;width:70%
2943
alt=A second order quad element is converted to 4 first-order elements, which are then linearized and "clipped".
3044

3145
Quadrature points defined on mortar segments (which live on linearized elements) are mapped back to second order elements following an analogous but reverse procedure to the one illustrated above; points are mapped from linearized elements to first order sub-elements then subsequently transformed to the original second order elements.

framework/include/constraints/AutomaticMortarGeneration.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,18 @@ class AutomaticMortarGeneration : public ConsoleStreamInterface
474474
void
475475
householderOrthogolization(const Point & normal, Point & tangent_one, Point & tangent_two) const;
476476

477+
/**
478+
* Process aligned nodes
479+
* @returns whether mortar segment(s) were created
480+
*/
481+
bool processAlignedNodes(const Node & secondary_node,
482+
const Node & primary_node,
483+
const std::vector<const Elem *> * secondary_node_neighbors,
484+
const std::vector<const Elem *> * primary_node_neighbors,
485+
const VectorValue<Real> & nodal_normal,
486+
const Elem & candidate_element,
487+
std::set<const Elem *> & rejected_element_candidates);
488+
477489
/// Whether to print debug output
478490
const bool _debug;
479491

@@ -507,6 +519,13 @@ class AutomaticMortarGeneration : public ConsoleStreamInterface
507519
/// Storage for the input parameters used by the mortar nodal geometry output
508520
std::unique_ptr<InputParameters> _output_params;
509521

522+
/// Debugging container for printing information about fraction of successful projections for
523+
/// secondary nodes. If !_debug then this should always be empty
524+
std::unordered_set<dof_id_type> _projected_secondary_nodes;
525+
526+
/// Secondary nodes that failed to project
527+
std::unordered_set<dof_id_type> _failed_secondary_node_projections;
528+
510529
friend class MortarNodalGeometryOutput;
511530
friend class AugmentSparsityOnInterface;
512531
};

framework/include/constraints/MortarData.h

Lines changed: 1 addition & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -9,167 +9,4 @@
99

1010
#pragma once
1111

12-
#include "AutomaticMortarGeneration.h"
13-
#include "MooseHashing.h"
14-
15-
#include "libmesh/parallel_object.h"
16-
17-
#include <unordered_map>
18-
#include <set>
19-
20-
class SubProblem;
21-
class MortarExecutorInterface;
22-
23-
class MortarData : public libMesh::ParallelObject
24-
{
25-
public:
26-
MortarData(const libMesh::ParallelObject & other);
27-
28-
/**
29-
* Create mortar generation object
30-
* @param boundary_key The primary-secondary boundary pair on which the AMG objects lives
31-
* @param subdomain_key The primary-secondary subdomain pair on which the AMG objects lives
32-
* @param subproblem A reference to the subproblem
33-
* @param on_displaced Whether the AMG object lives on the displaced mesh
34-
* @param periodic Whether the AMG object will be used for enforcing periodic constraints. Note
35-
* that this changes the direction of the projection normals so one AMG object cannot be used to
36-
* enforce both periodic and non-periodic constraints
37-
* @param debug whether to output mortar segment mesh exodus file for debugging purposes
38-
* @param correct_edge_dropping edge dropping treatment selection
39-
* @param minimum_projection_angle minimum projection angle allowed for building mortar segment
40-
* mesh
41-
*/
42-
void createMortarInterface(const std::pair<BoundaryID, BoundaryID> & boundary_key,
43-
const std::pair<SubdomainID, SubdomainID> & subdomain_key,
44-
SubProblem & subproblem,
45-
bool on_displaced,
46-
bool periodic,
47-
const bool debug,
48-
const bool correct_edge_dropping,
49-
const Real minimum_projection_angle);
50-
51-
/**
52-
* Getter to retrieve the AutomaticMortarGeneration object corresponding to the boundary and
53-
* subdomain keys. If the AutomaticMortarGeneration object does not yet exist, then we error
54-
*/
55-
const AutomaticMortarGeneration &
56-
getMortarInterface(const std::pair<BoundaryID, BoundaryID> & boundary_key,
57-
const std::pair<SubdomainID, SubdomainID> & /*subdomain_key*/,
58-
bool on_displaced) const;
59-
60-
/**
61-
* Non-const getter to retrieve the AutomaticMortarGeneration object corresponding to the boundary
62-
* and subdomain keys. If the AutomaticMortarGeneration object does not yet exist, then we error
63-
*/
64-
AutomaticMortarGeneration &
65-
getMortarInterface(const std::pair<BoundaryID, BoundaryID> & boundary_key,
66-
const std::pair<SubdomainID, SubdomainID> & /*subdomain_key*/,
67-
bool on_displaced);
68-
69-
/**
70-
* Return all automatic mortar generation objects on either the displaced or undisplaced mesh
71-
*/
72-
const std::unordered_map<std::pair<BoundaryID, BoundaryID>, AutomaticMortarGeneration> &
73-
getMortarInterfaces(bool on_displaced) const
74-
{
75-
if (on_displaced)
76-
return _displaced_mortar_interfaces;
77-
else
78-
return _mortar_interfaces;
79-
}
80-
81-
/**
82-
* Returns the mortar covered subdomains
83-
*/
84-
const std::set<SubdomainID> & getMortarSubdomainIDs() const { return _mortar_subdomain_coverage; }
85-
86-
/**
87-
* Returns the mortar covered boundaries
88-
*/
89-
const std::set<BoundaryID> & getMortarBoundaryIDs() const { return _mortar_boundary_coverage; }
90-
91-
/**
92-
* Builds mortar segment meshes for each mortar interface
93-
*/
94-
void update();
95-
96-
/**
97-
* Returns whether any of the AutomaticMortarGeneration objects are running on a displaced mesh
98-
*/
99-
bool hasDisplacedObjects() const { return _displaced_mortar_interfaces.size(); }
100-
101-
/**
102-
* Returns whether we have **any** active AutomaticMortarGeneration objects
103-
*/
104-
bool hasObjects() const { return _mortar_interfaces.size(); }
105-
106-
/**
107-
* Returns the higher dimensional subdomain ids of the interior parents of the given lower-d
108-
* subdomain id
109-
*/
110-
const std::set<SubdomainID> & getHigherDimSubdomainIDs(SubdomainID lower_d_subdomain_id) const;
111-
112-
/**
113-
* \em Adds \p mei to the container of objects that will have their \p mortarSetup method called
114-
* as soon as the mortar mesh has been generated for the first time
115-
*/
116-
void notifyWhenMortarSetup(MortarExecutorInterface * mei);
117-
118-
/**
119-
* \em Removes \p mei from the container of objects that will have their \p mortarSetup method
120-
* called as soon as the mortar mesh has been generated for the first time
121-
*/
122-
void dontNotifyWhenMortarSetup(MortarExecutorInterface * mei);
123-
124-
/**
125-
* @return whether we have performed an initial mortar mesh construction
126-
*/
127-
bool initialized() const { return _mortar_initd; }
128-
129-
private:
130-
/**
131-
* Builds mortar segment mesh from specific AutomaticMortarGeneration object
132-
*/
133-
void update(AutomaticMortarGeneration & amg);
134-
135-
typedef std::pair<BoundaryID, BoundaryID> MortarKey;
136-
137-
/// Map from primary-secondary (in that order) boundary ID pair to the corresponding
138-
/// undisplaced AutomaticMortarGeneration object
139-
std::unordered_map<MortarKey, AutomaticMortarGeneration> _mortar_interfaces;
140-
141-
/// Map from primary-secondary (in that order) boundary ID pair to the corresponding
142-
/// displaced AutomaticMortarGeneration object
143-
std::unordered_map<MortarKey, AutomaticMortarGeneration> _displaced_mortar_interfaces;
144-
145-
/// A set containing the subdomain ids covered by all the mortar interfaces in this MortarData
146-
/// object
147-
std::set<SubdomainID> _mortar_subdomain_coverage;
148-
149-
/// A set containing the boundary ids covered by all the mortar interfaces in this MortarData
150-
/// object
151-
std::set<BoundaryID> _mortar_boundary_coverage;
152-
153-
/// Map from undisplaced AMG key to whether the undisplaced AMG object is enforcing periodic constraints
154-
std::unordered_map<MortarKey, bool> _periodic_map;
155-
156-
/// Map from displaced AMG key to whether the displaced AMG object is enforcing periodic constraints
157-
std::unordered_map<MortarKey, bool> _displaced_periodic_map;
158-
159-
/// Map from undisplaced AMG key to whether the undisplaced AMG object is to output mortar segment mesh
160-
std::unordered_map<MortarKey, bool> _debug_flag_map;
161-
162-
/// Map from displaced AMG key to whether the displaced AMG object is to output mortar segment mesh
163-
std::unordered_map<MortarKey, bool> _displaced_debug_flag_map;
164-
165-
/// Map from lower dimensional subdomain ids to corresponding higher simensional subdomain ids
166-
/// (e.g. the ids of the interior parents)
167-
std::unordered_map<SubdomainID, std::set<SubdomainID>> _lower_d_sub_to_higher_d_subs;
168-
169-
/// A container of objects for whom the \p mortarSetup method will be called after the mortar mesh
170-
/// has been setup for the first time
171-
std::set<MortarExecutorInterface *> _mei_objs;
172-
173-
/// Whether we have performed any mortar mesh construction
174-
bool _mortar_initd;
175-
};
12+
#include "MortarInterfaceWarehouse.h"

0 commit comments

Comments
 (0)