MAST
mesh_coupling_base.cpp
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2019 Manav Bhatia
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 
21 // MAST includes
24 #include "base/nonlinear_system.h"
25 
26 // libMesh includes
27 #include "libmesh/mesh_base.h"
28 #include "libmesh/boundary_info.h"
29 #include "libmesh/point_locator_tree.h"
30 
31 
32 
34 _sys_init(sys_init) {
35 
36 
37 }
38 
39 
41 
42 
43 }
44 
45 
46 
47 
48 void
50 add_master_and_slave_boundary_coupling(unsigned int master_b_id,
51  unsigned int slave_b_id,
52  Real tol) {
53 
54  // iterate on all nodes and check with boundary info about
55  // current ids on it.
56  libMesh::MeshBase& mesh = _sys_init.system().get_mesh();
57 
58  std::unique_ptr<libMesh::PointLocatorBase>
59  pt_locator(mesh.sub_point_locator());
60 
61  libMesh::PointLocatorTree
62  &locator_tree = dynamic_cast<libMesh::PointLocatorTree&>(*pt_locator);
63 
64  libMesh::MeshBase::const_element_iterator
65  e_it = mesh.local_elements_begin(),
66  e_end = mesh.local_elements_end();
67 
68  std::set<const libMesh::Node*> slave_nodes;
69 
70  for ( ; e_it != e_end; e_it++) {
71 
72  // iterate on sides and check if it is on specified boundary id
73  for (unsigned int slave_side=0;
74  slave_side < (*e_it)->n_sides();
75  slave_side++) {
76 
77  // check if the side is on the specified boundary
78  if (_check_if_side_on_boundary(mesh, **e_it, slave_side, slave_b_id)) {
79 
80  std::unique_ptr<const libMesh::Elem>
81  slave_side_ptr((*e_it)->side_ptr(slave_side));
82 
83  // check for coupling of nodes on this side
84  for (unsigned int slave_n_id=0;
85  slave_n_id < slave_side_ptr->n_nodes();
86  slave_n_id++) {
87 
88  const libMesh::Node*
89  slave_node = slave_side_ptr->node_ptr(slave_n_id);
90 
91  // if the node has not already been constrained, then
92  // identify the constraint on it
93  if (!slave_nodes.count(slave_node)) {
94 
95  std::set<const libMesh::Node*> master_nodes;
96 
97  std::set<const libMesh::Elem*>
98  elems = locator_tree.perform_fuzzy_linear_search(*slave_node, nullptr, tol);
99 
100  // make sure some elements were found for this node
101  libmesh_assert(elems.size());
102 
103  // now check which of these elements have sides on
104  // the boundary.
105  std::set<const libMesh::Elem*>::const_iterator
106  master_e_it = elems.begin(),
107  master_e_end = elems.end();
108 
109  for (; master_e_it!=master_e_end; master_e_it++) {
110 
111 
112  for (unsigned int master_side=0;
113  master_side < (*master_e_it)->n_sides();
114  master_side++) {
115 
117  **master_e_it,
118  master_side,
119  master_b_id)) {
120 
121  std::unique_ptr<const libMesh::Elem>
122  master_side_ptr((*master_e_it)->side_ptr(master_side));
123 
124  // check for coupling of nodes on this side
125  for (unsigned int master_n_id=0;
126  master_n_id < master_side_ptr->n_nodes();
127  master_n_id++)
128  master_nodes.insert(master_side_ptr->node_ptr(master_n_id));
129  }
130  }
131  }
132 
133  // add this slave/master information to the data
134  _node_couplings.push_back
135  (std::pair<const libMesh::Node*, std::set<const libMesh::Node*>>
136  (slave_node, master_nodes));
137 
138  // register this slave node as having been processed
139  slave_nodes.insert(slave_node);
140  }
141  }
142  }
143  }
144  }
145 }
146 
147 
148 void
151  unsigned int slave_b_id,
152  Real tol) {
153 
154  // iterate on all nodes and check with boundary info about
155  // current ids on it.
156  libMesh::MeshBase& mesh = _sys_init.system().get_mesh();
157 
158  std::unique_ptr<libMesh::PointLocatorBase>
159  pt_locator(mesh.sub_point_locator());
160 
161  libMesh::PointLocatorTree
162  &locator_tree = dynamic_cast<libMesh::PointLocatorTree&>(*pt_locator);
163 
164  libMesh::MeshBase::const_element_iterator
165  e_it = mesh.local_elements_begin(),
166  e_end = mesh.local_elements_end();
167 
168  std::set<const libMesh::Node*> slave_nodes;
169 
170  for ( ; e_it != e_end; e_it++) {
171 
172  // iterate on sides and check if it is on specified boundary id
173  for (unsigned int slave_side=0;
174  slave_side < (*e_it)->n_sides();
175  slave_side++) {
176 
177  // check if the side is on the specified boundary
178  if (_check_if_side_on_boundary(mesh, **e_it, slave_side, slave_b_id)) {
179 
180  std::unique_ptr<const libMesh::Elem>
181  slave_side_ptr((*e_it)->side_ptr(slave_side));
182 
183  // check for coupling of nodes on this side
184  for (unsigned int slave_n_id=0;
185  slave_n_id < slave_side_ptr->n_nodes();
186  slave_n_id++) {
187 
188  const libMesh::Node*
189  slave_node = slave_side_ptr->node_ptr(slave_n_id);
190 
191  // if the node has not already been constrained, then
192  // identify the constraint on it
193  if (!slave_nodes.count(slave_node)) {
194 
195  std::set<const libMesh::Node*> master_nodes;
196 
197  std::set<const libMesh::Elem*>
198  elems = locator_tree.perform_fuzzy_linear_search(*slave_node, nullptr, tol);
199 
200  // make sure some elements were found for this node
201  libmesh_assert(elems.size());
202 
203  // now check which of these elements have the master
204  // subdomain id.
205  std::set<const libMesh::Elem*>::const_iterator
206  master_e_it = elems.begin(),
207  master_e_end = elems.end();
208 
209  for (; master_e_it!=master_e_end; master_e_it++) {
210 
211  const libMesh::Elem* master_e = *master_e_it;
212 
213  if (master_e->subdomain_id() == master_id) {
214 
215  // check for coupling of nodes on this side
216  for (unsigned int master_n_id=0;
217  master_n_id < master_e->n_nodes();
218  master_n_id++) {
219 
220  libMesh::Point
221  d = *master_e->node_ptr(master_n_id) - *slave_node;
222 
223  if (d.norm() <= tol)
224  master_nodes.insert(master_e->node_ptr(master_n_id));
225  }
226  }
227  }
228 
229  // add this slave/master information to the data
230  _node_couplings.push_back
231  (std::pair<const libMesh::Node*, std::set<const libMesh::Node*>>
232  (slave_node, master_nodes));
233 
234  // register this slave node as having been processed
235  slave_nodes.insert(slave_node);
236  }
237  }
238  }
239  }
240  }
241 }
242 
243 
244 
245 bool
247 _check_if_side_on_boundary(libMesh::MeshBase& mesh,
248  const libMesh::Elem& elem,
249  unsigned int side,
250  unsigned int b_id) {
251 
252  std::vector<libMesh::boundary_id_type> bc_ids;
253  mesh.boundary_info->boundary_ids(&elem, side, bc_ids);
254 
255  bool
256  on_side = false;
257  for (unsigned int i=0; i<bc_ids.size(); i++)
258  if (bc_ids[i] == b_id)
259  on_side = true;
260 
261  return on_side;
262 }
MAST::NonlinearSystem & system()
void add_slave_boundary_and_master_subdomain_coupling(unsigned int master_id, unsigned int slave_b_id, Real tol)
bool _check_if_side_on_boundary(libMesh::MeshBase &mesh, const libMesh::Elem &elem, unsigned int side, unsigned int b_id)
libMesh::Real Real
MAST::SystemInitialization & _sys_init
std::vector< std::pair< const libMesh::Node *, std::set< const libMesh::Node * > > > _node_couplings
void add_master_and_slave_boundary_coupling(unsigned int master_b_id, unsigned int slave_b_id, Real tol)
MeshCouplingBase(MAST::SystemInitialization &sys_init)