https://mooseframework.inl.gov
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"
16 
18  : libMesh::ParallelObject(other), _mortar_initd(false)
19 {
20 }
21 
22 void
24  const std::pair<BoundaryID, BoundaryID> & boundary_key,
25  const std::pair<SubdomainID, SubdomainID> & subdomain_key,
26  SubProblem & subproblem,
27  bool on_displaced,
28  bool periodic,
29  const bool debug,
30  const bool correct_edge_dropping,
31  const Real minimum_projection_angle)
32 {
33  _mortar_subdomain_coverage.insert(subdomain_key.first);
34  _mortar_subdomain_coverage.insert(subdomain_key.second);
35 
36  _mortar_boundary_coverage.insert(boundary_key.first);
37  _mortar_boundary_coverage.insert(boundary_key.second);
38 
39  MeshBase & mesh = subproblem.mesh().getMesh();
40 
41  auto & periodic_map = on_displaced ? _displaced_periodic_map : _periodic_map;
42  auto & debug_flag_map = on_displaced ? _displaced_debug_flag_map : _debug_flag_map;
43  auto & mortar_interfaces = on_displaced ? _displaced_mortar_interfaces : _mortar_interfaces;
44 
45  // Periodic flag
46  auto periodic_map_iterator = periodic_map.find(boundary_key);
47  if (periodic_map_iterator != periodic_map.end() && periodic_map_iterator->second != periodic)
48  mooseError("We do not currently support enforcing both periodic and non-periodic constraints "
49  "on the same boundary primary-secondary pair");
50  else
51  periodic_map.insert(periodic_map_iterator, std::make_pair(boundary_key, periodic));
52 
53  // Debug mesh flag displaced
54  auto debug_flag_map_iterator = debug_flag_map.find(boundary_key);
55  if (debug_flag_map_iterator != debug_flag_map.end() && debug_flag_map_iterator->second != debug)
56  mooseError(
57  "We do not currently support generating and not generating debug output "
58  "on the same boundary primary-secondary surface pair. Please set debug_mesh = true for "
59  "all constraints sharing the same primary-secondary surface pairs");
60  else
61  debug_flag_map.insert(debug_flag_map_iterator, std::make_pair(boundary_key, debug));
62 
63  // Generate lower-d mesh
64  if (mortar_interfaces.find(boundary_key) == mortar_interfaces.end())
65  {
66  auto [it, inserted] = mortar_interfaces.emplace(
67  boundary_key,
68  std::make_unique<AutomaticMortarGeneration>(subproblem.getMooseApp(),
69  mesh,
70  boundary_key,
71  subdomain_key,
72  on_displaced,
73  periodic,
74  debug,
75  correct_edge_dropping,
76  minimum_projection_angle));
77  if (inserted)
78  it->second->initOutput();
79  }
80 
81  // See whether to query the mesh
82  SubdomainID key1 = subdomain_key.first;
83  SubdomainID key2 = subdomain_key.second;
84 
85  // it(1,2) is a a pair consisting of an iterator to the inserted element (or to the element that
86  // prevented the insertion) and a bool denoting whether the insertion took place.
87  auto it1 = _lower_d_sub_to_higher_d_subs.insert(std::make_pair(key1, std::set<SubdomainID>{}));
88  auto it2 = _lower_d_sub_to_higher_d_subs.insert(std::make_pair(key2, std::set<SubdomainID>{}));
89 
90  // Each entry in this vector will be a pair. The first member of the pair corresponds to
91  // the lower dimensional subomain ID. The second member of the pair corresponds to the higher
92  // dimensional subdomain ids of the lower dimeionsal interior parents
93  std::vector<std::pair<SubdomainID, std::set<SubdomainID> *>> subdomains_to_probe;
94 
95  if (it1.second)
96  subdomains_to_probe.push_back(std::make_pair(key1, &it1.first->second));
97  if (it2.second)
98  subdomains_to_probe.push_back(std::make_pair(key2, &it2.first->second));
99 
100  for (auto & pr : subdomains_to_probe)
101  {
102  for (const Elem * lower_d_elem : as_range(mesh.active_local_subdomain_elements_begin(pr.first),
103  mesh.active_local_subdomain_elements_end(pr.first)))
104  {
105  const Elem * ip = lower_d_elem->interior_parent();
106  mooseAssert(
107  ip,
108  "Lower dimensional elements should always have an interior parent set when using mortar");
109  pr.second->insert(ip->subdomain_id());
110  }
111 
112  // Make sure that we get this right in parallel
113  _communicator.set_union(*pr.second);
114  }
115 }
116 
119  const std::pair<BoundaryID, BoundaryID> & boundary_key,
120  const std::pair<SubdomainID, SubdomainID> & /*subdomain_key*/,
121  bool on_displaced) const
122 {
123  auto & mortar_interfaces = on_displaced ? _displaced_mortar_interfaces : _mortar_interfaces;
124  auto it = mortar_interfaces.find(boundary_key);
125  if (it == mortar_interfaces.end())
126  mooseError(
127  "The requested mortar interface AutomaticMortarGeneration object does not yet exist!");
128  return *it->second;
129 }
130 
133  const std::pair<BoundaryID, BoundaryID> & boundary_key,
134  const std::pair<SubdomainID, SubdomainID> & subdomain_key,
135  bool on_displaced)
136 {
137  return const_cast<AutomaticMortarGeneration &>(
138  const_cast<const MortarInterfaceWarehouse *>(this)->getMortarInterface(
139  boundary_key, subdomain_key, on_displaced));
140 }
141 
142 void
144 {
145  for (auto & mortar_pair : _mortar_interfaces)
146  update(*mortar_pair.second);
147  for (auto & mortar_pair : _displaced_mortar_interfaces)
148  update(*mortar_pair.second);
149 
150  _mortar_initd = true;
151 }
152 
153 void
155 {
156  for (auto & mortar_pair : _mortar_interfaces)
157  mortar_pair.second->meshChanged();
158  for (auto & mortar_pair : _displaced_mortar_interfaces)
159  mortar_pair.second->meshChanged();
160  update();
161 }
162 
163 void
165 {
166  // Clear exiting data
167  amg.clear();
168 
169  const auto dim = amg.dim();
170 
171  if (dim == 1)
172  mooseError("Mortar constraints are not currently supported for 1D meshes");
173  else if (dim != 2 && dim != 3)
174  mooseError("Invalid mesh dimension for mortar constraint");
175 
176  // Construct maps from nodes -> lower dimensional elements on the primary and secondary
177  // boundaries.
178  amg.buildNodeToElemMaps();
179 
180  // Compute nodal geometry (normals and tangents).
181  amg.computeNodalGeometry();
182 
183  if (dim == 2)
184  {
185  // Project secondary nodes (find xi^(2) values).
186  amg.projectSecondaryNodes();
187 
188  // Project primary nodes (find xi^(1) values).
189  amg.projectPrimaryNodes();
190 
191  // Build the mortar segment mesh on the secondary boundary.
193  }
194  else // dim == 3
196 
199 }
200 
201 const std::set<SubdomainID> &
203 {
204  if (_lower_d_sub_to_higher_d_subs.find(lower_d_subdomain_id) ==
206  mooseError("The lower dimensional ID ",
207  lower_d_subdomain_id,
208  " has not been added to MortarInterfaceWarehouse yet");
209  return _lower_d_sub_to_higher_d_subs.at(lower_d_subdomain_id);
210 }
211 
212 void
214 {
215  _mei_objs.insert(mei_obj);
216 }
217 
218 void
220 {
221  _mei_objs.erase(mei_obj);
222 }
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)
Create mortar generation object.
void computeInactiveLMNodes()
Get list of secondary nodes that don&#39;t contribute to interaction with any primary element...
std::unordered_map< MortarKey, std::unique_ptr< AutomaticMortarGeneration > > _displaced_mortar_interfaces
Map from primary-secondary (in that order) boundary ID pair to the corresponding displaced AutomaticM...
void clear()
Clears the mortar segment mesh and accompanying data structures.
std::unordered_map< MortarKey, bool > _debug_flag_map
Map from undisplaced AMG key to whether the undisplaced AMG object is to output mortar segment mesh...
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
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 ...
MeshBase & mesh
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.
Definition: Moose.h:163
std::unordered_map< MortarKey, bool > _displaced_periodic_map
Map from displaced AMG key to whether the displaced AMG object is enforcing periodic constraints...
std::unordered_map< MortarKey, bool > _periodic_map
Map from undisplaced AMG key to whether the undisplaced AMG object is enforcing periodic constraints...
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.
Definition: MooseBase.h:87
void projectSecondaryNodes()
Project secondary nodes (find xi^(2) values) to the closest points on the primary surface...
This class is a container/interface for the objects involved in automatic generation of mortar spaces...
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.
Definition: MooseMesh.C:3575
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)
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...
std::unordered_map< MortarKey, std::unique_ptr< AutomaticMortarGeneration > > _mortar_interfaces
Map from primary-secondary (in that order) boundary ID pair to the corresponding undisplaced Automati...
void update()
Builds mortar segment meshes for each mortar interface.
std::unordered_map< MortarKey, bool > _displaced_debug_flag_map
Map from displaced AMG key to whether the displaced AMG object is to output mortar segment mesh...
Generic class for solving transient nonlinear problems.
Definition: SubProblem.h:78
std::set< SubdomainID > _mortar_subdomain_coverage
A set containing the subdomain ids covered by all the mortar interfaces in this MortarInterfaceWareho...
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...
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