https://mooseframework.inl.gov
MortarData.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 
10 #include "MortarData.h"
11 #include "SubProblem.h"
12 #include "MooseMesh.h"
13 #include "MooseError.h"
15 
17  : libMesh::ParallelObject(other), _mortar_initd(false)
18 {
19 }
20 
21 void
22 MortarData::createMortarInterface(const std::pair<BoundaryID, BoundaryID> & boundary_key,
23  const std::pair<SubdomainID, SubdomainID> & subdomain_key,
24  SubProblem & subproblem,
25  bool on_displaced,
26  bool periodic,
27  const bool debug,
28  const bool correct_edge_dropping,
29  const Real minimum_projection_angle)
30 {
31  _mortar_subdomain_coverage.insert(subdomain_key.first);
32  _mortar_subdomain_coverage.insert(subdomain_key.second);
33 
34  _mortar_boundary_coverage.insert(boundary_key.first);
35  _mortar_boundary_coverage.insert(boundary_key.second);
36 
37  MeshBase & mesh = subproblem.mesh().getMesh();
38 
39  auto & periodic_map = on_displaced ? _displaced_periodic_map : _periodic_map;
40  auto & debug_flag_map = on_displaced ? _displaced_debug_flag_map : _debug_flag_map;
41  auto & mortar_interfaces = on_displaced ? _displaced_mortar_interfaces : _mortar_interfaces;
42 
43  // Periodic flag
44  auto periodic_map_iterator = periodic_map.find(boundary_key);
45  if (periodic_map_iterator != periodic_map.end() && periodic_map_iterator->second != periodic)
46  mooseError("We do not currently support enforcing both periodic and non-periodic constraints "
47  "on the same boundary primary-secondary pair");
48  else
49  periodic_map.insert(periodic_map_iterator, std::make_pair(boundary_key, periodic));
50 
51  // Debug mesh flag displaced
52  auto debug_flag_map_iterator = debug_flag_map.find(boundary_key);
53  if (debug_flag_map_iterator != debug_flag_map.end() && debug_flag_map_iterator->second != debug)
54  mooseError(
55  "We do not currently support generating and not generating debug output "
56  "on the same boundary primary-secondary surface pair. Please set debug_mesh = true for "
57  "all constraints sharing the same primary-secondary surface pairs");
58  else
59  debug_flag_map.insert(debug_flag_map_iterator, std::make_pair(boundary_key, debug));
60 
61  // Generate lower-d mesh
62  if (mortar_interfaces.find(boundary_key) == mortar_interfaces.end())
63  {
64  auto [it, inserted] =
65  mortar_interfaces.emplace(boundary_key,
67  mesh,
68  boundary_key,
69  subdomain_key,
70  on_displaced,
71  periodic,
72  debug,
73  correct_edge_dropping,
74  minimum_projection_angle));
75  if (inserted)
76  it->second.initOutput();
77  }
78 
79  // See whether to query the mesh
80  SubdomainID key1 = subdomain_key.first;
81  SubdomainID key2 = subdomain_key.second;
82 
83  // it(1,2) is a a pair consisting of an iterator to the inserted element (or to the element that
84  // prevented the insertion) and a bool denoting whether the insertion took place.
85  auto it1 = _lower_d_sub_to_higher_d_subs.insert(std::make_pair(key1, std::set<SubdomainID>{}));
86  auto it2 = _lower_d_sub_to_higher_d_subs.insert(std::make_pair(key2, std::set<SubdomainID>{}));
87 
88  // Each entry in this vector will be a pair. The first member of the pair corresponds to
89  // the lower dimensional subomain ID. The second member of the pair corresponds to the higher
90  // dimensional subdomain ids of the lower dimeionsal interior parents
91  std::vector<std::pair<SubdomainID, std::set<SubdomainID> *>> subdomains_to_probe;
92 
93  if (it1.second)
94  subdomains_to_probe.push_back(std::make_pair(key1, &it1.first->second));
95  if (it2.second)
96  subdomains_to_probe.push_back(std::make_pair(key2, &it2.first->second));
97 
98  for (auto & pr : subdomains_to_probe)
99  {
100  for (const Elem * lower_d_elem : as_range(mesh.active_local_subdomain_elements_begin(pr.first),
101  mesh.active_local_subdomain_elements_end(pr.first)))
102  {
103  const Elem * ip = lower_d_elem->interior_parent();
104  mooseAssert(
105  ip,
106  "Lower dimensional elements should always have an interior parent set when using mortar");
107  pr.second->insert(ip->subdomain_id());
108  }
109 
110  // Make sure that we get this right in parallel
111  _communicator.set_union(*pr.second);
112  }
113 }
114 
116 MortarData::getMortarInterface(const std::pair<BoundaryID, BoundaryID> & boundary_key,
117  const std::pair<SubdomainID, SubdomainID> & /*subdomain_key*/,
118  bool on_displaced) const
119 {
120  if (on_displaced)
121  {
122  if (_displaced_mortar_interfaces.find(boundary_key) == _displaced_mortar_interfaces.end())
123  mooseError(
124  "The requested mortar interface AutomaticMortarGeneration object does not yet exist!");
125 
126  return _displaced_mortar_interfaces.at(boundary_key);
127  }
128  else
129  {
130  if (_mortar_interfaces.find(boundary_key) == _mortar_interfaces.end())
131  mooseError(
132  "The requested mortar interface AutomaticMortarGeneration object does not yet exist!");
133 
134  return _mortar_interfaces.at(boundary_key);
135  }
136 }
137 
139 MortarData::getMortarInterface(const std::pair<BoundaryID, BoundaryID> & boundary_key,
140  const std::pair<SubdomainID, SubdomainID> & subdomain_key,
141  bool on_displaced)
142 {
143  return const_cast<AutomaticMortarGeneration &>(
144  const_cast<const MortarData *>(this)->getMortarInterface(
145  boundary_key, subdomain_key, on_displaced));
146 }
147 
148 void
150 {
151  for (auto & mortar_pair : _mortar_interfaces)
152  update(mortar_pair.second);
153  for (auto & mortar_pair : _displaced_mortar_interfaces)
154  update(mortar_pair.second);
155 
156  _mortar_initd = true;
157 }
158 
159 void
161 {
162  // Clear exiting data
163  amg.clear();
164 
165  // Construct maps from nodes -> lower dimensional elements on the primary and secondary
166  // boundaries.
167  amg.buildNodeToElemMaps();
168 
169  // Compute nodal geometry (normals and tangents).
170  amg.computeNodalGeometry();
171 
172  const auto dim = amg.dim();
173  if (dim == 2)
174  {
175  // Project secondary nodes (find xi^(2) values).
176  amg.projectSecondaryNodes();
177 
178  // Project primary nodes (find xi^(1) values).
179  amg.projectPrimaryNodes();
180 
181  // Build the mortar segment mesh on the secondary boundary.
183  }
184  else if (dim == 3)
186  else
187  mooseError("Invalid mesh dimension for mortar constraint");
188 
191 }
192 
193 const std::set<SubdomainID> &
195 {
196  if (_lower_d_sub_to_higher_d_subs.find(lower_d_subdomain_id) ==
198  mooseError(
199  "The lower dimensional ID ", lower_d_subdomain_id, " has not been added to MortarData yet");
200  return _lower_d_sub_to_higher_d_subs.at(lower_d_subdomain_id);
201 }
202 
203 void
205 {
206  _mei_objs.insert(mei_obj);
207 }
208 
209 void
211 {
212  _mei_objs.erase(mei_obj);
213 }
virtual MooseMesh & mesh()=0
void computeInactiveLMNodes()
Get list of secondary nodes that don&#39;t contribute to interaction with any primary element...
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...
Definition: MortarData.C:116
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...
Definition: MooseError.h:333
Interface for notifications that the mortar mesh has been setup.
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...
Definition: MortarData.C:194
std::unordered_map< MortarKey, AutomaticMortarGeneration > _displaced_mortar_interfaces
Map from primary-secondary (in that order) boundary ID pair to the corresponding displaced AutomaticM...
Definition: MortarData.h:143
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:159
const Parallel::Communicator & _communicator
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
MortarData(const libMesh::ParallelObject &other)
Definition: MortarData.C:16
MooseApp & getMooseApp() const
Get the MooseApp this class is associated with.
Definition: MooseBase.h:83
void projectSecondaryNodes()
Project secondary nodes (find xi^(2) values) to the closest points on the primary surface...
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...
Definition: MortarData.h:160
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...
Definition: MortarData.h:163
This class is a container/interface for the objects involved in automatic generation of mortar spaces...
void projectPrimaryNodes()
(Inverse) project primary nodes to the points on the secondary surface where they would have come fro...
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.
Definition: MortarData.C:22
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3448
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...
Definition: MortarData.h:167
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
std::unordered_map< MortarKey, bool > _displaced_periodic_map
Map from displaced AMG key to whether the displaced AMG object is enforcing periodic constraints...
Definition: MortarData.h:157
std::unordered_map< MortarKey, bool > _periodic_map
Map from undisplaced AMG key to whether the undisplaced AMG object is enforcing periodic constraints...
Definition: MortarData.h:154
void computeNodalGeometry()
Computes and stores the nodal normal/tangent vectors in a local data structure instead of using the E...
void notifyWhenMortarSetup(MortarExecutorInterface *mei)
Adds mei to the container of objects that will have their mortarSetup method called as soon as the mo...
Definition: MortarData.C:204
void buildMortarSegmentMesh3d()
Builds the mortar segment mesh once the secondary and primary node projections have been completed...
std::unordered_map< MortarKey, AutomaticMortarGeneration > _mortar_interfaces
Map from primary-secondary (in that order) boundary ID pair to the corresponding undisplaced Automati...
Definition: MortarData.h:139
void update()
Builds mortar segment meshes for each mortar interface.
Definition: MortarData.C:149
void dontNotifyWhenMortarSetup(MortarExecutorInterface *mei)
Removes mei from the container of objects that will have their mortarSetup method called as soon as t...
Definition: MortarData.C:210
Generic class for solving transient nonlinear problems.
Definition: SubProblem.h:78
std::set< BoundaryID > _mortar_boundary_coverage
A set containing the boundary ids covered by all the mortar interfaces in this MortarData object...
Definition: MortarData.h:151
std::set< MortarExecutorInterface * > _mei_objs
A container of objects for whom the mortarSetup method will be called after the mortar mesh has been ...
Definition: MortarData.h:171
std::set< SubdomainID > _mortar_subdomain_coverage
A set containing the subdomain ids covered by all the mortar interfaces in this MortarData object...
Definition: MortarData.h:147
void computeInactiveLMElems()
Get list of secondary elems without any corresponding primary elements.
void set_union(T &data, const unsigned int root_id) const
bool _mortar_initd
Whether we have performed any mortar mesh construction.
Definition: MortarData.h:174