https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MortarInterfaceWarehouse.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11#include "SubProblem.h"
12#include "MooseMesh.h"
13#include "MooseError.h"
14#include "MooseEnum.h"
15#include "MooseUtils.h"
18
19namespace
20{
22toTriangulationMode(const MooseEnum & triangulation)
23{
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")
33#endif
34 mooseError("Unsupported mortar triangulation option: ", triangulation);
35}
36}
37
39 : libMesh::ParallelObject(other), _mortar_initd(false)
40{
41}
42
43void
45 const std::pair<BoundaryID, BoundaryID> & boundary_key,
46 const std::pair<SubdomainID, SubdomainID> & subdomain_key,
47 SubProblem & subproblem,
48 bool on_displaced,
49 bool periodic,
50 const bool debug,
51 const bool correct_edge_dropping,
52 const Real minimum_projection_angle,
53 const Mortar3DSubpatchPlane mortar_3d_subpatch_plane,
54 const MooseEnum & triangulation,
55 const bool triangulate_triangles,
56 const Mortar3DQuadraturePointMapping mortar_3d_qp_mapping)
57{
58 _mortar_subdomain_coverage.insert(subdomain_key.first);
59 _mortar_subdomain_coverage.insert(subdomain_key.second);
60
61 _mortar_boundary_coverage.insert(boundary_key.first);
62 _mortar_boundary_coverage.insert(boundary_key.second);
63
64 MeshBase & mesh = subproblem.mesh().getMesh();
65
66 auto & mortar_interfaces = on_displaced ? _displaced_mortar_interfaces : _mortar_interfaces;
67 const auto triangulation_mode = toTriangulationMode(triangulation);
68
69 auto interface_iterator = mortar_interfaces.find(boundary_key);
70 if (interface_iterator != mortar_interfaces.end())
71 {
72 // Existing entry: every per-interface flag must agree across constraints sharing the same
73 // primary-secondary surface pair.
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.");
99 }
100 else
101 {
103 std::make_unique<AutomaticMortarGeneration>(subproblem.getMooseApp(),
104 mesh,
105 boundary_key,
106 subdomain_key,
107 on_displaced,
108 periodic,
109 debug,
110 correct_edge_dropping,
111 minimum_projection_angle,
112 mortar_3d_subpatch_plane,
113 triangulation_mode,
114 triangulate_triangles,
115 mortar_3d_qp_mapping),
116 periodic,
117 debug,
118 minimum_projection_angle,
119 mortar_3d_subpatch_plane,
120 triangulation_mode,
121 triangulate_triangles,
122 mortar_3d_qp_mapping};
123 config.amg->initOutput();
124 mortar_interfaces.emplace(boundary_key, std::move(config));
125 }
126
127 // See whether to query the mesh
128 SubdomainID key1 = subdomain_key.first;
129 SubdomainID key2 = subdomain_key.second;
130
131 // it(1,2) is a a pair consisting of an iterator to the inserted element (or to the element that
132 // prevented the insertion) and a bool denoting whether the insertion took place.
133 auto it1 = _lower_d_sub_to_higher_d_subs.insert(std::make_pair(key1, std::set<SubdomainID>{}));
134 auto it2 = _lower_d_sub_to_higher_d_subs.insert(std::make_pair(key2, std::set<SubdomainID>{}));
135
136 // Each entry in this vector will be a pair. The first member of the pair corresponds to
137 // the lower dimensional subomain ID. The second member of the pair corresponds to the higher
138 // dimensional subdomain ids of the lower dimeionsal interior parents
139 std::vector<std::pair<SubdomainID, std::set<SubdomainID> *>> subdomains_to_probe;
140
141 if (it1.second)
142 subdomains_to_probe.push_back(std::make_pair(key1, &it1.first->second));
143 if (it2.second)
144 subdomains_to_probe.push_back(std::make_pair(key2, &it2.first->second));
145
146 for (auto & pr : subdomains_to_probe)
147 {
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)))
150 {
151 const Elem * ip = lower_d_elem->interior_parent();
152 mooseAssert(
153 ip,
154 "Lower dimensional elements should always have an interior parent set when using mortar");
155 pr.second->insert(ip->subdomain_id());
156 }
157
158 // Make sure that we get this right in parallel
159 _communicator.set_union(*pr.second);
160 }
161}
162
165 const std::pair<BoundaryID, BoundaryID> & boundary_key,
166 const std::pair<SubdomainID, SubdomainID> & /*subdomain_key*/,
167 bool on_displaced) const
168{
169 auto & mortar_interfaces = on_displaced ? _displaced_mortar_interfaces : _mortar_interfaces;
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;
175}
176
179 const std::pair<BoundaryID, BoundaryID> & boundary_key,
180 const std::pair<SubdomainID, SubdomainID> & subdomain_key,
181 bool on_displaced)
182{
183 return const_cast<AutomaticMortarGeneration &>(
184 const_cast<const MortarInterfaceWarehouse *>(this)->getMortarInterface(
185 boundary_key, subdomain_key, on_displaced));
186}
187
188void
190{
191 for (auto & mortar_pair : _mortar_interfaces)
192 update(*mortar_pair.second.amg);
193 for (auto & mortar_pair : _displaced_mortar_interfaces)
194 update(*mortar_pair.second.amg);
195
196 _mortar_initd = true;
197}
198
199void
201{
202 for (auto & mortar_pair : _mortar_interfaces)
203 mortar_pair.second.amg->meshChanged();
204 for (auto & mortar_pair : _displaced_mortar_interfaces)
205 mortar_pair.second.amg->meshChanged();
206 update();
207}
208
209void
211{
212 // Clear exiting data
213 amg.clear();
214
215 const auto dim = amg.dim();
216
217 if (dim == 1)
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");
221
222 // Construct maps from nodes -> lower dimensional elements on the primary and secondary
223 // boundaries.
225
226 // Compute nodal geometry (normals and tangents).
228
229 if (dim == 2)
230 {
231 // Project secondary nodes (find xi^(2) values).
233
234 // Project primary nodes (find xi^(1) values).
236
237 // Build the mortar segment mesh on the secondary boundary.
239 }
240 else // dim == 3
242
245}
246
247const std::set<SubdomainID> &
249{
250 if (_lower_d_sub_to_higher_d_subs.find(lower_d_subdomain_id) ==
252 mooseError("The lower dimensional ID ",
253 lower_d_subdomain_id,
254 " has not been added to MortarInterfaceWarehouse yet");
255 return _lower_d_sub_to_higher_d_subs.at(lower_d_subdomain_id);
256}
257
258void
263
264void
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
MortarSegmentTriangulationMode
unsigned int dim
This class is a container/interface for the objects involved in automatic generation of mortar spaces...
void computeNodalGeometry()
Computes and stores the nodal normal/tangent vectors in a local data structure instead of using the E...
void buildMortarSegmentMesh()
Builds the mortar segment mesh once the secondary and primary node projections have been completed.
void projectSecondaryNodes()
Project secondary nodes (find xi^(2) values) to the closest points on the primary surface.
void buildMortarSegmentMesh3d()
Builds the mortar segment mesh once the secondary and primary node projections have been completed.
void computeInactiveLMElems()
Get list of secondary elems without any corresponding primary elements.
void buildNodeToElemMaps()
Once the secondary_requested_boundary_ids and primary_requested_boundary_ids containers have been fil...
void clear()
Clears the mortar segment mesh and accompanying data structures.
void projectPrimaryNodes()
(Inverse) project primary nodes to the points on the secondary surface where they would have come fro...
void computeInactiveLMNodes()
Get list of secondary nodes that don't contribute to interaction with any primary element.
void meshChanged()
Invalidates the cached MSM node/element ID starting offset so that the next call to buildMortarSegmen...
MooseApp & getMooseApp() const
Get the MooseApp this class is associated with.
Definition MooseBase.h:87
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition MooseMesh.C:3549
Interface for notifications that the mortar mesh has been setup.
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....
std::set< MortarExecutorInterface * > _mei_objs
A container of objects for whom the mortarSetup method will be called after the mortar mesh has been ...
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...
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...
void meshChanged()
Invalidates cached MSM node/element ID offsets on all mortar interfaces so they are recomputed on the...
void notifyWhenMortarSetup(MortarExecutorInterface *mei)
Adds mei to the container of objects that will have their mortarSetup method called as soon as the mo...
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...
std::unordered_map< MortarKey, MortarInterfaceConfig > _mortar_interfaces
Map from primary-secondary (in that order) boundary ID pair to the configuration of the undisplaced m...
MortarInterfaceWarehouse(const libMesh::ParallelObject &other)
std::set< SubdomainID > _mortar_subdomain_coverage
A set containing the subdomain ids covered by all the mortar interfaces in this MortarInterfaceWareho...
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 update()
Builds mortar segment meshes for each mortar interface.
bool _mortar_initd
Whether we have performed any mortar mesh construction.
std::set< BoundaryID > _mortar_boundary_coverage
A set containing the boundary ids covered by all the mortar interfaces in this MortarInterfaceWarehou...
void dontNotifyWhenMortarSetup(MortarExecutorInterface *mei)
Removes mei from the container of objects that will have their mortarSetup method called as soon as t...
Generic class for solving transient nonlinear problems.
Definition SubProblem.h:79
virtual MooseMesh & mesh()=0
void set_union(T &data, const unsigned int root_id) const
const Parallel::Communicator & _communicator
MeshBase & mesh
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
Per-mortar-interface configuration.
std::unique_ptr< AutomaticMortarGeneration > amg