https://mooseframework.inl.gov
MeshAlignment.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 "MeshAlignment.h"
11 #include "Assembly.h"
12 #include "KDTree.h"
13 
14 #include "libmesh/elem.h"
15 
17  : MeshAlignmentBase(mesh), _meshes_are_coincident(false)
18 {
19 }
20 
21 void
23  const std::vector<dof_id_type> & primary_elem_ids,
24  const std::vector<std::tuple<dof_id_type, unsigned short int>> & secondary_boundary_info)
25 {
26  _primary_elem_ids = primary_elem_ids;
29 
30  extractFromBoundaryInfo(secondary_boundary_info,
36 
37  buildMapping();
38 }
39 
40 void
42  const std::vector<std::tuple<dof_id_type, unsigned short int>> & primary_boundary_info,
43  const std::vector<std::tuple<dof_id_type, unsigned short int>> & secondary_boundary_info)
44 {
45  extractFromBoundaryInfo(primary_boundary_info,
51 
52  extractFromBoundaryInfo(secondary_boundary_info,
58 
59  buildMapping();
60 }
61 
62 void
64 {
66  std::vector<unsigned int> primary_elem_pairing_count(_primary_elem_ids.size(), 0);
67 
68  // Build the element mapping
69  if (_primary_elem_points.size() > 0 && _secondary_elem_points.size() > 0)
70  {
71  // find the primary elements that are nearest to the secondary elements
73  for (std::size_t i_secondary = 0; i_secondary < _secondary_elem_points.size(); i_secondary++)
74  {
75  unsigned int patch_size = 1;
76  std::vector<std::size_t> return_index(patch_size);
77  kd_tree.neighborSearch(_secondary_elem_points[i_secondary], patch_size, return_index);
78  const std::size_t i_primary = return_index[0];
79 
80  // Flip flag if any pair of points are not coincident
82  _primary_elem_points[i_primary]))
83  _meshes_are_coincident = false;
84 
85  const auto primary_elem_id = _primary_elem_ids[i_primary];
86  const auto secondary_elem_id = _secondary_elem_ids[i_secondary];
87 
88  _coupled_elem_ids.insert({primary_elem_id, secondary_elem_id});
89  _coupled_elem_ids.insert({secondary_elem_id, primary_elem_id});
90 
91  primary_elem_pairing_count[i_primary]++;
92  }
93  }
94 
95  // Check if meshes are aligned: all primary boundary elements have exactly one pairing
96  _meshes_are_aligned = true;
97  for (std::size_t i_primary = 0; i_primary < _primary_elem_ids.size(); i_primary++)
98  if (primary_elem_pairing_count[i_primary] != 1)
99  _meshes_are_aligned = false;
100 
101  // Build the node mapping
102  if (_primary_node_points.size() > 0 && _secondary_node_points.size() > 0)
103  {
104  // find the primary nodes that are nearest to the secondary nodes
106  for (std::size_t i_secondary = 0; i_secondary < _secondary_node_points.size(); i_secondary++)
107  {
108  unsigned int patch_size = 1;
109  std::vector<std::size_t> return_index(patch_size);
110  kd_tree.neighborSearch(_secondary_node_points[i_secondary], patch_size, return_index);
111  const std::size_t i_primary = return_index[0];
112 
113  // Flip flag if any pair of points are not coincident
115  _primary_node_points[i_primary]))
116  _meshes_are_coincident = false;
117 
118  const auto primary_node_id = _primary_node_ids[i_primary];
119  const auto secondary_node_id = _secondary_node_ids[i_secondary];
120 
121  _coupled_node_ids.insert({primary_node_id, secondary_node_id});
122  _coupled_node_ids.insert({secondary_node_id, primary_node_id});
123  }
124  }
125 }
126 
127 void
129 {
130  // get local quadrature point maps on each side
131  std::map<dof_id_type, std::vector<Point>> primary_qp_map =
133  std::map<dof_id_type, std::vector<Point>> secondary_qp_map =
135 
136  // build mapping
137  for (const auto & primary_elem_id : _primary_elem_ids)
138  {
139  const Elem * primary_elem = _mesh.queryElemPtr(primary_elem_id);
140  // The PID check is needed to exclude ghost elements, since those don't
141  // necessarily have a coupled element on this processor:
142  if (primary_elem && primary_elem->processor_id() == _mesh.processor_id())
143  {
144  std::vector<Point> & primary_qps = primary_qp_map[primary_elem_id];
145 
146  const dof_id_type secondary_elem_id = getCoupledElemID(primary_elem_id);
147  std::vector<Point> & secondary_qps = secondary_qp_map[secondary_elem_id];
148 
149  mooseAssert(primary_qps.size() == secondary_qps.size(),
150  "The numbers of quadrature points for each element must be the same");
151 
152  _coupled_elem_qp_indices[primary_elem_id].resize(primary_qps.size());
153  KDTree kd_tree_qp(secondary_qps, _mesh.getMaxLeafSize());
154  for (std::size_t i = 0; i < primary_qps.size(); i++)
155  {
156  unsigned int patch_size = 1;
157  std::vector<std::size_t> return_index(patch_size);
158  kd_tree_qp.neighborSearch(primary_qps[i], patch_size, return_index);
159  _coupled_elem_qp_indices[primary_elem_id][i] = return_index[0];
160  }
161  }
162  }
163 }
164 
165 std::map<dof_id_type, std::vector<Point>>
167  const std::vector<dof_id_type> & elem_ids,
168  const std::vector<unsigned short int> & side_ids) const
169 {
170  std::map<dof_id_type, std::vector<Point>> elem_id_to_qps;
171  for (unsigned int i = 0; i < elem_ids.size(); i++)
172  {
173  const auto elem_id = elem_ids[i];
174  const Elem * elem = _mesh.queryElemPtr(elem_id);
175  if (elem)
176  {
177  assembly.setCurrentSubdomainID(elem->subdomain_id());
178 
179  MooseArray<Point> q_points;
180  if (side_ids.size() > 0)
181  {
182  assembly.reinit(elem, side_ids[i]);
183  q_points = assembly.qPointsFace();
184  }
185  else
186  {
187  assembly.reinit(elem);
188  q_points = assembly.qPoints();
189  }
190 
191  for (std::size_t i = 0; i < q_points.size(); i++)
192  elem_id_to_qps[elem_id].push_back(q_points[i]);
193  }
194  }
195 
196  return elem_id_to_qps;
197 }
198 
199 bool
201 {
202  return _coupled_elem_ids.find(elem_id) != _coupled_elem_ids.end();
203 }
204 
205 const dof_id_type &
207 {
208  mooseAssert(hasCoupledElemID(elem_id), "The element ID has no coupled element.");
209  return _coupled_elem_ids.find(elem_id)->second;
210 }
211 
212 bool
214 {
215  return _coupled_node_ids.find(node_id) != _coupled_node_ids.end();
216 }
217 
218 const dof_id_type &
220 {
221  mooseAssert(hasCoupledNodeID(node_id), "The node ID has no coupled node.");
222  return _coupled_node_ids.find(node_id)->second;
223 }
224 
225 unsigned int
226 MeshAlignment::getCoupledElemQpIndex(const dof_id_type & elem_id, const unsigned int & qp) const
227 {
228  auto it = _coupled_elem_qp_indices.find(elem_id);
229  mooseAssert(it != _coupled_elem_qp_indices.end(),
230  "The element ID has no coupled quadrature point indices.");
231  mooseAssert(qp < it->second.size(), "The quadrature index does not exist in the map.");
232  return it->second[qp];
233 }
void extractFrom1DElements(const std::vector< dof_id_type > &elem_ids, std::vector< Point > &elem_points, std::vector< dof_id_type > &node_ids, std::vector< Point > &node_points) const
Extracts mesh information from 1D elements.
std::map< dof_id_type, std::vector< Point > > getLocalQuadraturePointMap(Assembly &assembly, const std::vector< dof_id_type > &elem_ids, const std::vector< unsigned short int > &side_ids) const
Gets the local quadrature point map for the primary or secondary side.
void buildMapping()
Builds the mapping using the extracted mesh information.
Definition: MeshAlignment.C:63
std::vector< Point > _secondary_elem_points
List of secondary element points.
Builds mapping between two aligned subdomains/boundaries.
std::map< dof_id_type, dof_id_type > _coupled_node_ids
Map of node ID to coupled node ID.
bool hasCoupledNodeID(const dof_id_type &node_id) const
Returns true if the node ID has a coupled node ID.
const MooseMesh & _mesh
Mesh.
bool _meshes_are_aligned
Flag that meshes are aligned.
MeshBase & mesh
void initialize(const std::vector< dof_id_type > &primary_elem_ids, const std::vector< std::tuple< dof_id_type, unsigned short int >> &secondary_boundary_info)
Extracts mesh information and builds the mapping.
Definition: MeshAlignment.C:22
std::vector< dof_id_type > _secondary_elem_ids
List of secondary element IDs.
const MooseArray< Point > & qPoints() const
std::vector< dof_id_type > _secondary_node_ids
List of secondary node IDs.
std::vector< unsigned short int > _secondary_side_ids
List of secondary side IDs (if any)
void reinit(const Elem *elem)
virtual Elem * queryElemPtr(const dof_id_type i)
const dof_id_type & getCoupledNodeID(const dof_id_type &node_id) const
Gets the coupled node ID for a given node ID.
const dof_id_type & getCoupledElemID(const dof_id_type &elem_id) const
Gets the coupled element ID for a given element ID.
unsigned int size() const
unsigned int getMaxLeafSize() const
std::vector< dof_id_type > _primary_node_ids
List of primary node IDs.
std::vector< Point > _primary_elem_points
List of primary element points.
MeshAlignment(const MooseMesh &mesh)
Constructor.
Definition: MeshAlignment.C:16
void buildCoupledElemQpIndexMap(Assembly &assembly)
Builds the map used for getting the coupled quadrature point index.
std::vector< Point > _primary_node_points
List of primary node points.
bool absolute_fuzzy_equals(const T &var1, const T2 &var2, const Real tol=TOLERANCE *TOLERANCE)
void setCurrentSubdomainID(SubdomainID i)
const MooseArray< Point > & qPointsFace() const
std::map< dof_id_type, std::vector< unsigned int > > _coupled_elem_qp_indices
Map of element ID to vector of coupled quadrature points.
std::vector< unsigned short int > _primary_side_ids
List of primary side IDs (if any)
void extractFromBoundaryInfo(const std::vector< std::tuple< dof_id_type, unsigned short int >> &boundary_info, std::vector< dof_id_type > &elem_ids, std::vector< unsigned short int > &side_ids, std::vector< Point > &side_points, std::vector< dof_id_type > &node_ids, std::vector< Point > &node_points) const
Extracts mesh information from boundary info.
std::vector< dof_id_type > _primary_elem_ids
List of primary element IDs.
std::map< dof_id_type, dof_id_type > _coupled_elem_ids
Map of element ID to coupled element ID.
processor_id_type processor_id() const
unsigned int getCoupledElemQpIndex(const dof_id_type &elem_id, const unsigned int &qp) const
Gets the quadrature point index on the coupled element corresponding to the quadrature point index on...
bool _meshes_are_coincident
Flag that meshes are coincident.
uint8_t dof_id_type
bool hasCoupledElemID(const dof_id_type &elem_id) const
Returns true if the element ID has a coupled element ID.
std::vector< Point > _secondary_node_points
List of secondary node points.