22 toTriangulationMode(
const MooseEnum & triangulation)
24 if (triangulation ==
"vertex")
26 if (triangulation ==
"centroid")
28 if (triangulation ==
"ear_clipping")
30 #if defined(LIBMESH_HAVE_TRIANGLE) || defined(LIBMESH_HAVE_POLY2TRI) 31 if (triangulation ==
"delaunay")
34 mooseError(
"Unsupported mortar triangulation option: ", triangulation);
39 :
libMesh::ParallelObject(other), _mortar_initd(false)
45 const std::pair<BoundaryID, BoundaryID> & boundary_key,
46 const std::pair<SubdomainID, SubdomainID> & subdomain_key,
51 const bool correct_edge_dropping,
52 const Real minimum_projection_angle,
53 const Mortar3DSubpatchPlane mortar_3d_subpatch_plane,
55 const bool triangulate_triangles,
56 const Mortar3DQuadraturePointMapping mortar_3d_qp_mapping)
67 const auto triangulation_mode = toTriangulationMode(triangulation);
69 auto interface_iterator = mortar_interfaces.find(boundary_key);
70 if (interface_iterator != mortar_interfaces.end())
74 const auto & existing = interface_iterator->second;
75 if (existing.periodic != periodic)
76 mooseError(
"We do not currently support enforcing both periodic and non-periodic constraints " 77 "on the same boundary primary-secondary pair");
78 if (existing.debug != debug)
80 "We do not currently support generating and not generating debug output " 81 "on the same boundary primary-secondary surface pair. Please set debug_mesh = true for " 82 "all constraints sharing the same primary-secondary surface pairs");
83 if (!MooseUtils::absoluteFuzzyEqual(existing.minimum_projection_angle,
84 minimum_projection_angle))
85 mooseError(
"We do not currently support multiple values of 'minimum_projection_angle' on " 86 "the same boundary primary-secondary surface pair.");
87 if (existing.mortar_3d_subpatch_plane != mortar_3d_subpatch_plane)
88 mooseError(
"Mortar constraints sharing the same primary/secondary mortar interface must use " 89 "the same 'mortar_3d_subpatch_plane' value.");
90 if (existing.triangulation != triangulation_mode)
91 mooseError(
"We do not currently support multiple values of 'triangulation' on the same " 92 "boundary primary-secondary surface pair.");
93 if (existing.triangulate_triangles != triangulate_triangles)
94 mooseError(
"We do not currently support multiple values of 'triangulate_triangles' on the " 95 "same boundary primary-secondary surface pair.");
96 if (existing.mortar_3d_qp_mapping != mortar_3d_qp_mapping)
97 mooseError(
"We do not currently support multiple values of 'mortar_3d_qp_mapping' on the " 98 "same boundary primary-secondary surface pair.");
103 std::make_unique<AutomaticMortarGeneration>(subproblem.
getMooseApp(),
110 correct_edge_dropping,
111 minimum_projection_angle,
112 mortar_3d_subpatch_plane,
114 triangulate_triangles,
115 mortar_3d_qp_mapping),
118 minimum_projection_angle,
119 mortar_3d_subpatch_plane,
121 triangulate_triangles,
122 mortar_3d_qp_mapping};
123 config.
amg->initOutput();
124 mortar_interfaces.emplace(boundary_key, std::move(config));
139 std::vector<std::pair<SubdomainID, std::set<SubdomainID> *>> subdomains_to_probe;
142 subdomains_to_probe.push_back(std::make_pair(key1, &it1.first->second));
144 subdomains_to_probe.push_back(std::make_pair(key2, &it2.first->second));
146 for (
auto & pr : subdomains_to_probe)
148 for (
const Elem * lower_d_elem :
as_range(
mesh.active_local_subdomain_elements_begin(pr.first),
149 mesh.active_local_subdomain_elements_end(pr.first)))
151 const Elem * ip = lower_d_elem->interior_parent();
154 "Lower dimensional elements should always have an interior parent set when using mortar");
155 pr.second->insert(ip->subdomain_id());
165 const std::pair<BoundaryID, BoundaryID> & boundary_key,
166 const std::pair<SubdomainID, SubdomainID> & ,
167 bool on_displaced)
const 170 auto it = mortar_interfaces.find(boundary_key);
171 if (it == mortar_interfaces.end())
173 "The requested mortar interface AutomaticMortarGeneration object does not yet exist!");
174 return *it->second.amg;
179 const std::pair<BoundaryID, BoundaryID> & boundary_key,
180 const std::pair<SubdomainID, SubdomainID> & subdomain_key,
185 boundary_key, subdomain_key, on_displaced));
192 update(*mortar_pair.second.amg);
194 update(*mortar_pair.second.amg);
203 mortar_pair.second.amg->meshChanged();
205 mortar_pair.second.amg->meshChanged();
215 const auto dim = amg.
dim();
218 mooseError(
"Mortar constraints are not currently supported for 1D meshes");
219 else if (
dim != 2 &&
dim != 3)
220 mooseError(
"Invalid mesh dimension for mortar constraint");
247 const std::set<SubdomainID> &
253 lower_d_subdomain_id,
254 " has not been added to MortarInterfaceWarehouse yet");
virtual MooseMesh & mesh()=0
void dontNotifyWhenMortarSetup(MortarExecutorInterface *mei)
Removes mei from the container of objects that will have their mortarSetup method called as soon as t...
void createMortarInterface(const std::pair< BoundaryID, BoundaryID > &boundary_key, const std::pair< SubdomainID, SubdomainID > &subdomain_key, SubProblem &subproblem, bool on_displaced, bool periodic, const bool debug, const bool correct_edge_dropping, const Real minimum_projection_angle, const Mortar3DSubpatchPlane mortar_3d_subpatch_plane, const MooseEnum &triangulation, const bool triangulate_triangles, const Mortar3DQuadraturePointMapping mortar_3d_qp_mapping=Mortar3DQuadraturePointMapping::NORMAL_PROJECTION)
Create mortar generation object.
void computeInactiveLMNodes()
Get list of secondary nodes that don't contribute to interaction with any primary element...
void clear()
Clears the mortar segment mesh and accompanying data structures.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Interface for notifications that the mortar mesh has been setup.
std::set< MortarExecutorInterface * > _mei_objs
A container of objects for whom the mortarSetup method will be called after the mortar mesh has been ...
void buildMortarSegmentMesh()
Builds the mortar segment mesh once the secondary and primary node projections have been completed...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
const Parallel::Communicator & _communicator
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
bool _mortar_initd
Whether we have performed any mortar mesh construction.
MooseApp & getMooseApp() const
Get the MooseApp this class is associated with.
void projectSecondaryNodes()
Project secondary nodes (find xi^(2) values) to the closest points on the primary surface...
Per-mortar-interface configuration.
This class is a container/interface for the objects involved in automatic generation of mortar spaces...
MortarSegmentTriangulationMode
void notifyWhenMortarSetup(MortarExecutorInterface *mei)
Adds mei to the container of objects that will have their mortarSetup method called as soon as the mo...
void projectPrimaryNodes()
(Inverse) project primary nodes to the points on the secondary surface where they would have come fro...
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
const std::set< SubdomainID > & getHigherDimSubdomainIDs(SubdomainID lower_d_subdomain_id) const
Returns the higher dimensional subdomain ids of the interior parents of the given lower-d subdomain i...
void buildNodeToElemMaps()
Once the secondary_requested_boundary_ids and primary_requested_boundary_ids containers have been fil...
std::unordered_map< SubdomainID, std::set< SubdomainID > > _lower_d_sub_to_higher_d_subs
Map from lower dimensional subdomain ids to corresponding higher simensional subdomain ids (e...
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
std::unordered_map< MortarKey, MortarInterfaceConfig > _mortar_interfaces
Map from primary-secondary (in that order) boundary ID pair to the configuration of the undisplaced m...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
void computeNodalGeometry()
Computes and stores the nodal normal/tangent vectors in a local data structure instead of using the E...
void buildMortarSegmentMesh3d()
Builds the mortar segment mesh once the secondary and primary node projections have been completed...
void update()
Builds mortar segment meshes for each mortar interface.
Generic class for solving transient nonlinear problems.
std::set< SubdomainID > _mortar_subdomain_coverage
A set containing the subdomain ids covered by all the mortar interfaces in this MortarInterfaceWareho...
std::unordered_map< MortarKey, MortarInterfaceConfig > _displaced_mortar_interfaces
Map from primary-secondary (in that order) boundary ID pair to the configuration of the displaced mor...
const AutomaticMortarGeneration & getMortarInterface(const std::pair< BoundaryID, BoundaryID > &boundary_key, const std::pair< SubdomainID, SubdomainID > &, bool on_displaced) const
Getter to retrieve the AutomaticMortarGeneration object corresponding to the boundary and subdomain k...
void meshChanged()
Invalidates cached MSM node/element ID offsets on all mortar interfaces so they are recomputed on the...
std::set< BoundaryID > _mortar_boundary_coverage
A set containing the boundary ids covered by all the mortar interfaces in this MortarInterfaceWarehou...
std::unique_ptr< AutomaticMortarGeneration > amg
MortarInterfaceWarehouse(const libMesh::ParallelObject &other)
void computeInactiveLMElems()
Get list of secondary elems without any corresponding primary elements.
void set_union(T &data, const unsigned int root_id) const