boundary_info.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // C++ includes
21 #include <iterator> // std::distance
22 
23 // Local includes
24 #include "libmesh/libmesh_config.h"
25 #include "libmesh/boundary_info.h"
26 #include "libmesh/elem.h"
27 #include "libmesh/mesh_data.h"
29 #include "libmesh/parallel.h"
30 #include "libmesh/partitioner.h"
32 
33 namespace libMesh
34 {
35 
36 
37 
38 //------------------------------------------------------
39 // BoundaryInfo static member initializations
41 
42 
43 
44 //------------------------------------------------------
45 // BoundaryInfo functions
47  ParallelObject(m.comm()),
48  _mesh (m)
49 {
50 }
51 
53 {
60  // Copy node boundary info
61  {
62  std::multimap<const Node*, boundary_id_type>::const_iterator it = other_boundary_info._boundary_node_id.begin();
63  const std::multimap<const Node*, boundary_id_type>::const_iterator end = other_boundary_info._boundary_node_id.end();
64 
65  for(; it != end; ++it)
66  {
67  const Node * other_node = it->first;
68  _boundary_node_id.insert
69  (std::pair<const Node*, boundary_id_type>
70  (_mesh.node_ptr(other_node->id()), it->second) );
71  }
72  }
73 
74  // Copy edge boundary info
75  {
76  std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
77  const_iterator it = other_boundary_info._boundary_edge_id.begin();
78  const std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
79  const_iterator end = other_boundary_info._boundary_edge_id.end();
80 
81  for(; it != end; ++it)
82  {
83  const Elem * other_elem = it->first;
84  _boundary_edge_id.insert
85  (std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> >
86  (_mesh.elem(other_elem->id()), it->second) );
87  }
88  }
89 
90  // Copy side boundary info
91  {
92  std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
93  const_iterator it = other_boundary_info._boundary_side_id.begin();
94  const std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
95  const_iterator end = other_boundary_info._boundary_side_id.end();
96 
97  for(; it != end; ++it)
98  {
99  const Elem * other_elem = it->first;
100  _boundary_side_id.insert
101  (std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> >
102  (_mesh.elem(other_elem->id()), it->second) );
103  }
104  }
105 
106  _boundary_ids = other_boundary_info._boundary_ids;
107  _side_boundary_ids = other_boundary_info._side_boundary_ids;
108  _node_boundary_ids = other_boundary_info._node_boundary_ids;
109 
110  return *this;
111 }
112 
113 
115 {
116  this->clear();
117 }
118 
119 
120 
122 {
123  _boundary_node_id.clear();
124  _boundary_side_id.clear();
125  _boundary_ids.clear();
126  _side_boundary_ids.clear();
127  _node_boundary_ids.clear();
128 }
129 
130 
131 
133  MeshData* boundary_mesh_data,
134  MeshData* this_mesh_data)
135 {
136  std::set<boundary_id_type> request_boundary_ids(_boundary_ids);
137  request_boundary_ids.insert(invalid_id);
138  if (!_mesh.is_serial())
139  this->comm().set_union(request_boundary_ids);
140 
141  this->sync(request_boundary_ids, boundary_mesh,
142  boundary_mesh_data, this_mesh_data);
143 }
144 
145 
146 
147 void BoundaryInfo::sync (const std::set<boundary_id_type> &requested_boundary_ids,
148  UnstructuredMesh& boundary_mesh,
149  MeshData* boundary_mesh_data,
150  MeshData* this_mesh_data)
151 {
152  START_LOG("sync()", "BoundaryInfo");
153 
154  boundary_mesh.clear();
155 
161  if (!_mesh.is_serial())
162  boundary_mesh.delete_remote_elements();
163 
170  MeshSerializer(const_cast<MeshBase&>(_mesh), boundary_mesh.is_serial());
171 
176  boundary_mesh.set_mesh_dimension(_mesh.mesh_dimension() - 1);
177 
182  boundary_mesh.set_n_partitions() = _mesh.n_partitions();
183 
184  std::map<dof_id_type, dof_id_type> node_id_map;
185  std::map<std::pair<dof_id_type, unsigned char>, dof_id_type> side_id_map;
186 
187  // We'll do the same modulus trick that ParallelMesh uses to avoid
188  // id conflicts between different processors
189  dof_id_type next_node_id = this->processor_id(),
190  next_elem_id = this->processor_id();
191 
192  // We'll pass through the mesh once first to build
193  // the maps and count boundary nodes and elements
194  // We have to examine all elements here rather than just local
195  // elements, because it's possible to have a local boundary node
196  // that's not on a local boundary element, e.g. at the tip of a
197  // triangle.
200  el != end_el; ++el)
201  {
202  const Elem *elem = *el;
203 
204  for (unsigned char s=0; s<elem->n_sides(); s++)
205  if (elem->neighbor(s) == NULL) // on the boundary
206  {
207  // Get the top-level parent for this element
208  const Elem* top_parent = elem->top_parent();
209 
210  // A convenient typedef
211  typedef
212  std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
213  const_iterator Iter;
214 
215  // Find the right id number for that side
216  std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(top_parent);
217 
218  bool add_this_side = false;
219  boundary_id_type this_bcid = invalid_id;
220 
221  for (; pos.first != pos.second; ++pos.first)
222  {
223  this_bcid = pos.first->second.second;
224 
225  // if this side is flagged with a boundary condition
226  // and the user wants this id
227  if ((pos.first->second.first == s) &&
228  (requested_boundary_ids.count(this_bcid)))
229  {
230  add_this_side = true;
231  break;
232  }
233  }
234 
235  // if side s wasn't found or doesn't have a boundary
236  // condition we may still want to add it
237  if (pos.first == pos.second)
238  {
239  this_bcid = invalid_id;
240  if (requested_boundary_ids.count(this_bcid))
241  add_this_side = true;
242  }
243 
244  if (add_this_side)
245  {
246  std::pair<dof_id_type, unsigned char> side_pair(elem->id(), s);
247  libmesh_assert (!side_id_map.count(side_pair));
248  side_id_map[side_pair] = next_elem_id;
249  next_elem_id += this->n_processors() + 1;
250 
251  // Use a proxy element for the side to query nodes
252  AutoPtr<Elem> side (elem->build_side(s));
253  for (unsigned int n = 0; n != side->n_nodes(); ++n)
254  {
255  Node *node = side->get_node(n);
256  libmesh_assert(node);
257 
258  // In parallel we only know enough to number our own nodes.
259  if (node->processor_id() != this->processor_id())
260  continue;
261 
262  dof_id_type node_id = node->id();
263  if (!node_id_map.count(node_id))
264  {
265  node_id_map[node_id] = next_node_id;
266  next_node_id += this->n_processors() + 1;
267  }
268  }
269  }
270  }
271  }
272 
273  // Join up the results from other processors
274  this->comm().set_union(side_id_map);
275  this->comm().set_union(node_id_map);
276 
277  // Finally we'll pass through any unpartitioned elements to add them
278  // to the maps and counts.
279  next_node_id = this->n_processors();
280  next_elem_id = this->n_processors();
281 
282  const MeshBase::const_element_iterator end_unpartitioned_el =
286  el != end_unpartitioned_el; ++el)
287  {
288  const Elem *elem = *el;
289 
290  for (unsigned char s=0; s<elem->n_sides(); s++)
291  if (elem->neighbor(s) == NULL) // on the boundary
292  {
293  // Get the top-level parent for this element
294  const Elem* top_parent = elem->top_parent();
295 
296  // A convenient typedef
297  typedef
298  std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
299  const_iterator Iter;
300 
301  // Find the right id number for that side
302  std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(top_parent);
303 
304  bool add_this_side = false;
305  boundary_id_type this_bcid = invalid_id;
306 
307  for (; pos.first != pos.second; ++pos.first)
308  {
309  this_bcid = pos.first->second.second;
310  // if this side is flagged with a boundary condition
311  // and the user wants this id
312  if ((pos.first->second.first == s) &&
313  (requested_boundary_ids.count(this_bcid)))
314  {
315  add_this_side = true;
316  break;
317  }
318  }
319 
320  // if side s doesn't have a boundary condition we may
321  // still want to add it
322  if (pos.first == pos.second)
323  {
324  this_bcid = invalid_id;
325  if (requested_boundary_ids.count(this_bcid))
326  add_this_side = true;
327  }
328 
329  if (add_this_side)
330  {
331  std::pair<dof_id_type, unsigned char> side_pair(elem->id(), s);
332  libmesh_assert (!side_id_map.count(side_pair));
333  side_id_map[side_pair] = next_elem_id;
334  next_elem_id += this->n_processors() + 1;
335 
336  // Use a proxy element for the side to query nodes
337  AutoPtr<Elem> side (elem->build_side(s));
338  for (unsigned int n = 0; n != side->n_nodes(); ++n)
339  {
340  Node *node = side->get_node(n);
341  libmesh_assert(node);
342  dof_id_type node_id = node->id();
343  if (!node_id_map.count(node_id))
344  {
345  node_id_map[node_id] = next_node_id;
346  next_node_id += this->n_processors() + 1;
347  }
348  }
349  }
350  }
351  }
352 
353  // FIXME: ought to renumber side/node_id_map image to be contiguous
354  // to save memory, also ought to reserve memory
355 
356  // Let's add all the nodes to the boundary mesh
357 
359 
361  n_it != n_end; ++n_it)
362  {
363  const Node* node = *n_it;
364  dof_id_type node_id = node->id();
365  if (node_id_map.count(node_id))
366  boundary_mesh.add_point(*node, node_id_map[node_id], node->processor_id());
367  }
368 
369 
370  // Finally let's add the elements
371 
372 
374  el != end_el; ++el)
375  {
376  const Elem* elem = *el;
377 
378  for (unsigned int s=0; s<elem->n_sides(); s++)
379  if (elem->neighbor(s) == NULL) // on the boundary
380  {
381  // Get the top-level parent for this element
382  const Elem* top_parent = elem->top_parent();
383 
384  // A convenient typedef
385  typedef
386  std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
387  const_iterator Iter;
388 
389  // Find the right id number for that side
390  std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(top_parent);
391 
392  bool add_this_side = false;
393  boundary_id_type this_bcid = invalid_id;
394 
395  for (; pos.first != pos.second; ++pos.first)
396  {
397  this_bcid = pos.first->second.second;
398 
399  // if this side is flagged with a boundary condition
400  // and the user wants this id
401  if ((pos.first->second.first == s) &&
402  (requested_boundary_ids.count(this_bcid)))
403  {
404  add_this_side = true;
405  break;
406  }
407  }
408 
409  // if side s wasn't found or doesn't have a boundary
410  // condition we may still want to add it
411  if (pos.first == pos.second)
412  {
413  this_bcid = invalid_id;
414  if (requested_boundary_ids.count(this_bcid))
415  add_this_side = true;
416  }
417 
418  if (add_this_side)
419  {
420  // Build the side - do not use a "proxy" element here:
421  // This will be going into the boundary_mesh and needs to
422  // stand on its own.
423  AutoPtr<Elem> side (elem->build_side(s, false));
424 
425  side->processor_id() = elem->processor_id();
426 
427  const std::pair<dof_id_type, unsigned char> side_pair(elem->id(), s);
428 
429  libmesh_assert(side_id_map.count(side_pair));
430 
431  side->set_id(side_id_map[side_pair]);
432 
433  // Add the side
434  Elem* new_elem = boundary_mesh.add_elem(side.release());
435 
436  // This side's Node pointers still point to the nodes of the original mesh.
437  // We need to re-point them to the boundary mesh's nodes! Since we copied *ALL* of
438  // the original mesh's nodes over, we should be guaranteed to have the same ordering.
439  for (unsigned int nn=0; nn<new_elem->n_nodes(); ++nn)
440  {
441  // Get the correct node pointer, based on the id()
442  Node* new_node = boundary_mesh.node_ptr(node_id_map[new_elem->node(nn)]);
443 
444  // sanity check: be sure that the new Node exists
445  // and its global id really matches
446  libmesh_assert (new_node);
447  libmesh_assert_equal_to (new_node->id(), node_id_map[new_elem->node(nn)]);
448 
449  // Assign the new node pointer
450  new_elem->set_node(nn) = new_node;
451  }
452 
453 #ifdef LIBMESH_ENABLE_AMR
454  // Finally, set the parent and interior_parent links
455  if (elem->parent())
456  {
457  const std::pair<dof_id_type, unsigned char> parent_side_pair(elem->parent()->id(), s);
458 
459  libmesh_assert(side_id_map.count(parent_side_pair));
460 
461  Elem* side_parent = boundary_mesh.elem(side_id_map[parent_side_pair]);
462 
463  libmesh_assert(side_parent);
464 
465  new_elem->set_parent(side_parent);
466 
467  side_parent->set_refinement_flag(Elem::INACTIVE);
468 
469  // Figuring out which child we are of our parent
470  // is a trick. Due to libMesh child numbering
471  // conventions, if we are an element on a vertex,
472  // then we share that vertex with our parent, with
473  // the same local index.
474  bool found_child = false;
475  for (unsigned int v=0; v != new_elem->n_vertices(); ++v)
476  if (new_elem->get_node(v) == side_parent->get_node(v))
477  {
478  side_parent->add_child(new_elem, v);
479  found_child = true;
480  }
481 
482  // If we don't share any vertex with our parent,
483  // then we're the fourth child (index 3) of a
484  // triangle.
485  if (!found_child)
486  {
487  libmesh_assert_equal_to (new_elem->n_vertices(), 3);
488  side_parent->add_child(new_elem, 3);
489  }
490  }
491 #endif
492 
493  new_elem->set_interior_parent (const_cast<Elem*>(elem));
494  }
495  }
496  }
497 
498  // When desired, copy the MeshData
499  // to the boundary_mesh
500  if ((boundary_mesh_data != NULL) && (this_mesh_data != NULL))
501  boundary_mesh_data->assign(*this_mesh_data);
502 
503  // Don't repartition this mesh; we want it to stay in sync with the
504  // interior partitioning.
505  boundary_mesh.partitioner().reset(NULL);
506 
507  // Make boundary_mesh nodes and elements contiguous
508  boundary_mesh.prepare_for_use(/*skip_renumber =*/ false);
509 
510  // and finally distribute element partitioning to the nodes
512 
513  STOP_LOG("sync()", "BoundaryInfo");
514 }
515 
516 
517 
519  const boundary_id_type id)
520 {
521  this->add_node (_mesh.node_ptr(node), id);
522 }
523 
524 
525 
526 void BoundaryInfo::add_node(const Node* node,
527  const boundary_id_type id)
528 {
529  if (id == invalid_id)
530  {
531  libMesh::err << "ERROR: You may not set a boundary ID of "
532  << invalid_id << std::endl
533  << " That is reserved for internal use.\n"
534  << std::endl;
535 
536  libmesh_error();
537  }
538 
539  // A convenient typedef
540  typedef std::multimap<const Node*, boundary_id_type>::const_iterator Iter;
541 
542  // Don't add the same ID twice
543  std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node);
544 
545  for (;pos.first != pos.second; ++pos.first)
546  if (pos.first->second == id)
547  return;
548 
549  std::pair<const Node*, boundary_id_type> kv (node, id);
550 
551  _boundary_node_id.insert(kv);
552  _boundary_ids.insert(id);
553  _node_boundary_ids.insert(id); // Also add this ID to the set of node boundary IDs
554 }
555 
556 void BoundaryInfo::add_node(const Node* node,
557  const std::vector<boundary_id_type>& ids)
558 {
559  if (ids.empty())
560  return;
561 
562  libmesh_assert(node);
563 
564  // A convenient typedef
565  typedef std::multimap<const Node*, boundary_id_type>::const_iterator Iter;
566 
567  // Don't add the same ID twice
568  std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node);
569 
570  for (unsigned int i=0; i!= ids.size(); ++i)
571  {
572  boundary_id_type id=ids[i];
573 
574  if (id == invalid_id)
575  {
576  libMesh::err << "ERROR: You may not set a boundary ID of "
577  << invalid_id << std::endl
578  << " That is reserved for internal use.\n"
579  << std::endl;
580 
581  libmesh_error();
582  }
583 
584  bool already_inserted = false;
585  for (Iter p = pos.first;p != pos.second; ++p)
586  if (p->second == id)
587  {
588  already_inserted = true;
589  break;
590  }
591  if (already_inserted)
592  continue;
593 
594  std::pair<const Node*, boundary_id_type> kv (node, id);
595 
596  _boundary_node_id.insert(kv);
597  _boundary_ids.insert(id);
598  _node_boundary_ids.insert(id); // Also add this ID to the set of node boundary IDs
599  }
600 }
601 
602 
604 {
605  _boundary_node_id.clear();
606 }
607 
609  const unsigned short int edge,
610  const boundary_id_type id)
611 {
612  this->add_edge (_mesh.elem(e), edge, id);
613 }
614 
615 
616 
617 void BoundaryInfo::add_edge(const Elem* elem,
618  const unsigned short int edge,
619  const boundary_id_type id)
620 {
621  libmesh_assert(elem);
622 
623  // Only add BCs for level-0 elements.
624  libmesh_assert_equal_to (elem->level(), 0);
625 
626  if (id == invalid_id)
627  {
628  libMesh::err << "ERROR: You may not set a boundary ID of "
629  << invalid_id << std::endl
630  << " That is reserved for internal use.\n"
631  << std::endl;
632 
633  libmesh_error();
634  }
635 
636  // A convenient typedef
637  typedef std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
638  const_iterator Iter;
639 
640  // Don't add the same ID twice
641  std::pair<Iter, Iter> pos = _boundary_edge_id.equal_range(elem);
642 
643  for (;pos.first != pos.second; ++pos.first)
644  if (pos.first->second.first == edge &&
645  pos.first->second.second == id)
646  return;
647 
648  std::pair<unsigned short int, boundary_id_type> p(edge,id);
649  std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> >
650  kv (elem, p);
651 
652  _boundary_edge_id.insert(kv);
653  _boundary_ids.insert(id);
654  _edge_boundary_ids.insert(id); // Also add this ID to the set of edge boundary IDs
655 }
656 
657 
658 
659 void BoundaryInfo::add_edge(const Elem* elem,
660  const unsigned short int edge,
661  const std::vector<boundary_id_type>& ids)
662 {
663  if (ids.empty())
664  return;
665 
666  libmesh_assert(elem);
667 
668  // Only add BCs for level-0 elements.
669  libmesh_assert_equal_to (elem->level(), 0);
670 
671  // A convenient typedef
672  typedef std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
673  const_iterator Iter;
674 
675  // Don't add the same ID twice
676  std::pair<Iter, Iter> pos = _boundary_edge_id.equal_range(elem);
677 
678  for (unsigned int i=0; i!= ids.size(); ++i)
679  {
680  boundary_id_type id=ids[i];
681 
682  if (id == invalid_id)
683  {
684  libMesh::err << "ERROR: You may not set a boundary ID of "
685  << invalid_id << std::endl
686  << " That is reserved for internal use.\n"
687  << std::endl;
688 
689  libmesh_error();
690  }
691 
692  bool already_inserted = false;
693  for (Iter p = pos.first;p != pos.second; ++p)
694  if (p->second.first == edge &&
695  p->second.second == id)
696  {
697  already_inserted = true;
698  break;
699  }
700  if (already_inserted)
701  continue;
702 
703  std::pair<unsigned short int, boundary_id_type> p(edge,id);
704  std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> >
705  kv (elem, p);
706 
707  _boundary_edge_id.insert(kv);
708  _boundary_ids.insert(id);
709  _edge_boundary_ids.insert(id); // Also add this ID to the set of edge boundary IDs
710  }
711 }
712 
714  const unsigned short int side,
715  const boundary_id_type id)
716 {
717  this->add_side (_mesh.elem(e), side, id);
718 }
719 
720 
721 
722 void BoundaryInfo::add_side(const Elem* elem,
723  const unsigned short int side,
724  const boundary_id_type id)
725 {
726  libmesh_assert(elem);
727 
728  // Only add BCs for level-0 elements.
729  libmesh_assert_equal_to (elem->level(), 0);
730 
731  if (id == invalid_id)
732  {
733  libMesh::err << "ERROR: You may not set a boundary ID of "
734  << invalid_id << std::endl
735  << " That is reserved for internal use.\n"
736  << std::endl;
737 
738  libmesh_error();
739  }
740 
741  // A convenient typedef
742  typedef std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
743  const_iterator Iter;
744 
745  // Don't add the same ID twice
746  std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(elem);
747 
748  for (;pos.first != pos.second; ++pos.first)
749  if (pos.first->second.first == side &&
750  pos.first->second.second == id)
751  return;
752 
753  std::pair<unsigned short int, boundary_id_type> p(side,id);
754  std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> >
755  kv (elem, p);
756 
757  _boundary_side_id.insert(kv);
758  _boundary_ids.insert(id);
759  _side_boundary_ids.insert(id); // Also add this ID to the set of side boundary IDs
760 }
761 
762 
763 
764 void BoundaryInfo::add_side(const Elem* elem,
765  const unsigned short int side,
766  const std::vector<boundary_id_type>& ids)
767 {
768  if (ids.empty())
769  return;
770 
771  libmesh_assert(elem);
772 
773  // Only add BCs for level-0 elements.
774  libmesh_assert_equal_to (elem->level(), 0);
775 
776  // A convenient typedef
777  typedef std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::
778  const_iterator Iter;
779 
780  // Don't add the same ID twice
781  std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(elem);
782 
783  for (unsigned int i=0; i!= ids.size(); ++i)
784  {
785  boundary_id_type id=ids[i];
786 
787  if (id == invalid_id)
788  {
789  libMesh::err << "ERROR: You may not set a boundary ID of "
790  << invalid_id << std::endl
791  << " That is reserved for internal use.\n"
792  << std::endl;
793 
794  libmesh_error();
795  }
796 
797  bool already_inserted = false;
798  for (Iter p = pos.first;p != pos.second; ++p)
799  if (p->second.first == side &&
800  p->second.second == id)
801  {
802  already_inserted = true;
803  break;
804  }
805  if (already_inserted)
806  continue;
807 
808  std::pair<unsigned short int, boundary_id_type> p(side,id);
809  std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> >
810  kv (elem, p);
811 
812  _boundary_side_id.insert(kv);
813  _boundary_ids.insert(id);
814  _side_boundary_ids.insert(id); // Also add this ID to the set of side boundary IDs
815  }
816 }
817 
818 
819 
820 bool BoundaryInfo::has_boundary_id(const Node* const node,
821  const boundary_id_type id) const
822 {
823  // A convenient typedef
824  typedef std::multimap<const Node*, boundary_id_type>::const_iterator Iter;
825 
826  std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node);
827 
828  for (;pos.first != pos.second; ++pos.first)
829  if (pos.first->second == id)
830  return true;
831 
832  return false;
833 }
834 
835 
836 
837 std::vector<boundary_id_type> BoundaryInfo::boundary_ids(const Node* node) const
838 {
839  std::vector<boundary_id_type> ids;
840 
841  // A convenient typedef
842  typedef std::multimap<const Node*, boundary_id_type>::const_iterator Iter;
843 
844  std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node);
845 
846  for (;pos.first != pos.second; ++pos.first)
847  ids.push_back(pos.first->second);
848 
849  return ids;
850 }
851 
852 
853 
854 unsigned int BoundaryInfo::n_boundary_ids(const Node* node) const
855 {
856  // A convenient typedef
857  typedef std::multimap<const Node*, boundary_id_type>::const_iterator Iter;
858 
859  std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node);
860 
861  return libmesh_cast_int<unsigned int>
862  (std::distance(pos.first, pos.second));
863 }
864 
865 
866 
867 std::vector<boundary_id_type> BoundaryInfo::edge_boundary_ids (const Elem* const elem,
868  const unsigned short int edge) const
869 {
870  libmesh_assert(elem);
871 
872  std::vector<boundary_id_type> ids;
873 
874  // Only level-0 elements store BCs. If this is not a level-0
875  // element get its level-0 parent and infer the BCs.
876  const Elem* searched_elem = elem;
877  if (elem->level() != 0)
878  {
879  // Find all the sides that contain edge. If one of those is a boundary
880  // side, then this must be a boundary edge. In that case, we just use the
881  // top-level parent.
882  bool found_boundary_edge = false;
883  for(unsigned int side=0; side<elem->n_sides(); side++)
884  {
885  if(elem->is_edge_on_side(edge,side))
886  {
887  if (elem->neighbor(side) == NULL)
888  {
889  searched_elem = elem->top_parent ();
890  found_boundary_edge = true;
891  break;
892  }
893  }
894  }
895 
896 #ifdef LIBMESH_ENABLE_AMR
897  if(!found_boundary_edge)
898  {
899  // Child element is not on external edge, but it may have internal
900  // "boundary" IDs. We will walk up the tree, at each level checking that
901  // the current child is actually on the same edge of the parent that is
902  // currently being searched for (i.e. that was passed in as "edge").
903  while (searched_elem->parent() != NULL)
904  {
905  const Elem * parent = searched_elem->parent();
906  if (parent->is_child_on_edge(parent->which_child_am_i(searched_elem), edge) == false)
907  return ids;
908  searched_elem = parent;
909  }
910  }
911 #endif
912  }
913 
914  std::pair<std::multimap<const Elem*,
915  std::pair<unsigned short int, boundary_id_type> >::const_iterator,
916  std::multimap<const Elem*,
917  std::pair<unsigned short int, boundary_id_type> >::const_iterator >
918  e = _boundary_edge_id.equal_range(searched_elem);
919 
920  // elem not in the data structure
921  if (e.first == e.second)
922  return ids;
923 
924  // elem is there, maybe multiple occurrences
925  for (; e.first != e.second; ++e.first)
926  // if this is true we found the requested edge of the element
927  if (e.first->second.first == edge)
928  ids.push_back(e.first->second.second);
929 
930  // Whether or not we found anything, return "ids". If it's empty, it
931  // means no valid bounary IDs were found for "edge"
932  return ids;
933 }
934 
935 
936 
937 unsigned int BoundaryInfo::n_edge_boundary_ids (const Elem* const elem,
938  const unsigned short int edge) const
939 {
940  libmesh_assert(elem);
941 
942  // Only level-0 elements store BCs. If this is not a level-0
943  // element get its level-0 parent and infer the BCs.
944  const Elem* searched_elem = elem;
945  if (elem->level() != 0)
946  {
947  // Find all the sides that contain edge. If one of those is a boundary
948  // side, then this must be a boundary edge. In that case, we just use the
949  // top-level parent.
950  bool found_boundary_edge = false;
951  for(unsigned int side=0; side<elem->n_sides(); side++)
952  {
953  if(elem->is_edge_on_side(edge,side))
954  {
955  if (elem->neighbor(side) == NULL)
956  {
957  searched_elem = elem->top_parent ();
958  found_boundary_edge = true;
959  break;
960  }
961  }
962  }
963 
964 #ifdef LIBMESH_ENABLE_AMR
965  if(!found_boundary_edge)
966  {
967  // Child element is not on external edge, but it may have internal
968  // "boundary" IDs. We will walk up the tree, at each level checking that
969  // the current child is actually on the same edge of the parent that is
970  // currently being searched for (i.e. that was passed in as "edge").
971  while (searched_elem->parent() != NULL)
972  {
973  const Elem * parent = searched_elem->parent();
974  if (parent->is_child_on_edge(parent->which_child_am_i(searched_elem), edge) == false)
975  return 0;
976  searched_elem = parent;
977  }
978  }
979 #endif
980  }
981 
982  std::pair<std::multimap<const Elem*,
983  std::pair<unsigned short int, boundary_id_type> >::const_iterator,
984  std::multimap<const Elem*,
985  std::pair<unsigned short int, boundary_id_type> >::const_iterator >
986  e = _boundary_edge_id.equal_range(searched_elem);
987 
988  unsigned int n_ids = 0;
989 
990  // elem is there, maybe multiple occurrences
991  for (; e.first != e.second; ++e.first)
992  // if this is true we found the requested edge of the element
993  if (e.first->second.first == edge)
994  n_ids++;
995 
996  return n_ids;
997 }
998 
999 
1000 
1001 std::vector<boundary_id_type> BoundaryInfo::raw_edge_boundary_ids (const Elem* const elem,
1002  const unsigned short int edge) const
1003 {
1004  libmesh_assert(elem);
1005 
1006  std::vector<boundary_id_type> ids;
1007 
1008  // Only level-0 elements store BCs.
1009  if (elem->parent())
1010  return ids;
1011 
1012  std::pair<std::multimap<const Elem*,
1013  std::pair<unsigned short int, boundary_id_type> >::const_iterator,
1014  std::multimap<const Elem*,
1015  std::pair<unsigned short int, boundary_id_type> >::const_iterator >
1016  e = _boundary_edge_id.equal_range(elem);
1017 
1018  // Check any occurrences
1019  for (; e.first != e.second; ++e.first)
1020  // if this is true we found the requested edge of the element
1021  if (e.first->second.first == edge)
1022  ids.push_back(e.first->second.second);
1023 
1024  // if nothing got pushed back, we didn't find elem in the data
1025  // structure with the requested edge, so return the default empty
1026  // vector
1027  return ids;
1028 }
1029 
1030 
1032  const unsigned short int side) const
1033 {
1034  // Asking for just one boundary id means your code isn't safe to use
1035  // on meshes with overlapping boundary ids. Try using
1036  // BoundaryInfo::boundary_ids or BoundaryInfo::has_boundary_id
1037  // instead.
1038  libmesh_deprecated();
1039 
1040  libmesh_assert(elem);
1041 
1042  // Only level-0 elements store BCs. If this is not a level-0
1043  // element, one of its parent elements may have either internal
1044  // or external boundary IDs. We find that parent now.
1045  const Elem* searched_elem = elem;
1046  if (elem->level() != 0)
1047  {
1048  // Child element on external side: the top_parent will have the BCs
1049  if (elem->neighbor(side) == NULL)
1050  searched_elem = elem->top_parent ();
1051 
1052 #ifdef LIBMESH_ENABLE_AMR
1053  // Child element is not on external side, but it may have internal
1054  // "boundary" IDs. We will walk up the tree, at each level checking that
1055  // the current child is actually on the same side of the parent that is
1056  // currently being searched for (i.e. that was passed in as "side").
1057  else
1058  while (searched_elem->parent() != NULL)
1059  {
1060  const Elem * parent = searched_elem->parent();
1061  if (parent->is_child_on_side(parent->which_child_am_i(searched_elem), side) == false)
1062  return invalid_id;
1063  searched_elem = parent;
1064  }
1065 #endif
1066  }
1067 
1068  std::pair<std::multimap<const Elem*,
1069  std::pair<unsigned short int, boundary_id_type> >::const_iterator,
1070  std::multimap<const Elem*,
1071  std::pair<unsigned short int, boundary_id_type> >::const_iterator >
1072  e = _boundary_side_id.equal_range(searched_elem);
1073 
1074  // elem not in the data structure
1075  if (e.first == e.second)
1076  return invalid_id;
1077 
1078  // elem is there, maybe multiple occurrences
1079  for (; e.first != e.second; ++e.first)
1080  // if this is true we found the requested side
1081  // of the element and want to return the id
1082  if (e.first->second.first == side)
1083  return e.first->second.second;
1084 
1085  // if we get here, we found elem in the data structure but not
1086  // the requested side, so return the default value
1087  return invalid_id;
1088 }
1089 
1090 
1091 
1092 bool BoundaryInfo::has_boundary_id(const Elem* const elem,
1093  const unsigned short int side,
1094  const boundary_id_type id) const
1095 {
1096  libmesh_assert(elem);
1097 
1098  // Only level-0 elements store BCs. If this is not a level-0
1099  // element get its level-0 parent and infer the BCs.
1100  const Elem* searched_elem = elem;
1101  if (elem->level() != 0)
1102  {
1103  if (elem->neighbor(side) == NULL)
1104  searched_elem = elem->top_parent ();
1105 #ifdef LIBMESH_ENABLE_AMR
1106  else
1107  while (searched_elem->parent() != NULL)
1108  {
1109  const Elem * parent = searched_elem->parent();
1110  if (parent->is_child_on_side(parent->which_child_am_i(searched_elem), side) == false)
1111  return false;
1112  searched_elem = parent;
1113  }
1114 #endif
1115  }
1116 
1117  std::pair<std::multimap<const Elem*,
1118  std::pair<unsigned short int, boundary_id_type> >::const_iterator,
1119  std::multimap<const Elem*,
1120  std::pair<unsigned short int, boundary_id_type> >::const_iterator >
1121  e = _boundary_side_id.equal_range(searched_elem);
1122 
1123  // elem is there, maybe multiple occurrences
1124  for (; e.first != e.second; ++e.first)
1125  // if this is true we found the requested id on this side of the element
1126  if (e.first->second.first == side &&
1127  e.first->second.second == id)
1128  return true;
1129 
1130  return false;
1131 }
1132 
1133 
1134 
1135 std::vector<boundary_id_type> BoundaryInfo::boundary_ids (const Elem* const elem,
1136  const unsigned short int side) const
1137 {
1138  libmesh_assert(elem);
1139 
1140  std::vector<boundary_id_type> ids;
1141 
1142  // Only level-0 elements store BCs. If this is not a level-0
1143  // element get its level-0 parent and infer the BCs.
1144  const Elem* searched_elem = elem;
1145  if (elem->level() != 0)
1146  {
1147  if (elem->neighbor(side) == NULL)
1148  searched_elem = elem->top_parent ();
1149 #ifdef LIBMESH_ENABLE_AMR
1150  else
1151  while (searched_elem->parent() != NULL)
1152  {
1153  const Elem * parent = searched_elem->parent();
1154  if (parent->is_child_on_side(parent->which_child_am_i(searched_elem), side) == false)
1155  return ids;
1156  searched_elem = parent;
1157  }
1158 #endif
1159  }
1160 
1161  std::pair<std::multimap<const Elem*,
1162  std::pair<unsigned short int, boundary_id_type> >::const_iterator,
1163  std::multimap<const Elem*,
1164  std::pair<unsigned short int, boundary_id_type> >::const_iterator >
1165  e = _boundary_side_id.equal_range(searched_elem);
1166 
1167  // elem not in the data structure
1168  if (e.first == e.second)
1169  return ids;
1170 
1171  // elem is there, maybe multiple occurrences
1172  for (; e.first != e.second; ++e.first)
1173  // if this is true we found the requested side of the element
1174  if (e.first->second.first == side)
1175  ids.push_back(e.first->second.second);
1176 
1177  // Whether or not we found anything, return "ids". If it's empty, it
1178  // means no valid bounary IDs were found for "side"
1179  return ids;
1180 }
1181 
1182 
1183 
1184 unsigned int BoundaryInfo::n_boundary_ids (const Elem* const elem,
1185  const unsigned short int side) const
1186 {
1187  libmesh_assert(elem);
1188 
1189  // Only level-0 elements store BCs. If this is not a level-0
1190  // element get its level-0 parent and infer the BCs.
1191  const Elem* searched_elem = elem;
1192  if (elem->level() != 0)
1193  {
1194  if (elem->neighbor(side) == NULL)
1195  searched_elem = elem->top_parent ();
1196 #ifdef LIBMESH_ENABLE_AMR
1197  else
1198  while (searched_elem->parent() != NULL)
1199  {
1200  const Elem * parent = searched_elem->parent();
1201  if (parent->is_child_on_side(parent->which_child_am_i(searched_elem), side) == false)
1202  return 0;
1203  searched_elem = parent;
1204  }
1205 #endif
1206  }
1207 
1208  std::pair<std::multimap<const Elem*,
1209  std::pair<unsigned short int, boundary_id_type> >::const_iterator,
1210  std::multimap<const Elem*,
1211  std::pair<unsigned short int, boundary_id_type> >::const_iterator >
1212  e = _boundary_side_id.equal_range(searched_elem);
1213 
1214  unsigned int n_ids = 0;
1215 
1216  // elem is there, maybe multiple occurrences
1217  for (; e.first != e.second; ++e.first)
1218  // if this is true we found the requested side of the element
1219  if (e.first->second.first == side)
1220  n_ids++;
1221 
1222  return n_ids;
1223 }
1224 
1225 
1226 
1227 std::vector<boundary_id_type> BoundaryInfo::raw_boundary_ids (const Elem* const elem,
1228  const unsigned short int side) const
1229 {
1230  libmesh_assert(elem);
1231 
1232  std::vector<boundary_id_type> ids;
1233 
1234  // Only level-0 elements store BCs.
1235  if (elem->parent())
1236  return ids;
1237 
1238  std::pair<std::multimap<const Elem*,
1239  std::pair<unsigned short int, boundary_id_type> >::const_iterator,
1240  std::multimap<const Elem*,
1241  std::pair<unsigned short int, boundary_id_type> >::const_iterator >
1242  e = _boundary_side_id.equal_range(elem);
1243 
1244  // Check any occurrences
1245  for (; e.first != e.second; ++e.first)
1246  // if this is true we found the requested side of the element
1247  if (e.first->second.first == side)
1248  ids.push_back(e.first->second.second);
1249 
1250  // if nothing got pushed back, we didn't find elem in the data
1251  // structure with the requested side, so return the default empty
1252  // vector
1253  return ids;
1254 }
1255 
1256 
1258  const unsigned short int edge)
1259 {
1260  libmesh_assert(elem);
1261 
1262  // The user shouldn't be trying to remove only one child's boundary
1263  // id
1264  libmesh_assert_equal_to (elem->level(), 0);
1265 
1266  std::pair<std::multimap<const Elem*,
1267  std::pair<unsigned short int, boundary_id_type> >::iterator,
1268  std::multimap<const Elem*,
1269  std::pair<unsigned short int, boundary_id_type> >::iterator >
1270  e = _boundary_edge_id.equal_range(elem);
1271 
1272  // elem may be there, maybe multiple occurrences
1273  while (e.first != e.second)
1274  {
1275  // if this is true we found the requested edge
1276  // of the element and want to erase the id
1277  if (e.first->second.first == edge)
1278  {
1279  // (postfix++ - increment the iterator before it's invalid)
1280  _boundary_edge_id.erase(e.first++);
1281  }
1282  else
1283  ++e.first;
1284  }
1285 }
1286 
1287 
1288 
1290  const unsigned short int edge,
1291  const boundary_id_type id)
1292 {
1293  libmesh_assert(elem);
1294 
1295  // The user shouldn't be trying to remove only one child's boundary
1296  // id
1297  libmesh_assert_equal_to (elem->level(), 0);
1298 
1299  std::pair<std::multimap<const Elem*,
1300  std::pair<unsigned short int, boundary_id_type> >::iterator,
1301  std::multimap<const Elem*,
1302  std::pair<unsigned short int, boundary_id_type> >::iterator >
1303  e = _boundary_edge_id.equal_range(elem);
1304 
1305  // elem may be there, maybe multiple occurrences
1306  while (e.first != e.second)
1307  {
1308  // if this is true we found the requested edge
1309  // of the element and want to erase the requested id
1310  if (e.first->second.first == edge &&
1311  e.first->second.second == id)
1312  {
1313  // (postfix++ - increment the iterator before it's invalid)
1314  _boundary_edge_id.erase(e.first++);
1315  }
1316  else
1317  ++e.first;
1318  }
1319 }
1320 
1322  const unsigned short int side)
1323 {
1324  libmesh_assert(elem);
1325 
1326  // The user shouldn't be trying to remove only one child's boundary
1327  // id
1328  libmesh_assert_equal_to (elem->level(), 0);
1329 
1330  std::pair<std::multimap<const Elem*,
1331  std::pair<unsigned short int, boundary_id_type> >::iterator,
1332  std::multimap<const Elem*,
1333  std::pair<unsigned short int, boundary_id_type> >::iterator >
1334  e = _boundary_side_id.equal_range(elem);
1335 
1336  // elem may be there, maybe multiple occurrences
1337  while (e.first != e.second)
1338  {
1339  // if this is true we found the requested side
1340  // of the element and want to erase the id
1341  if (e.first->second.first == side)
1342  {
1343  // (postfix++ - increment the iterator before it's invalid)
1344  _boundary_side_id.erase(e.first++);
1345  }
1346  else
1347  ++e.first;
1348  }
1349 }
1350 
1351 
1352 
1354  const unsigned short int side,
1355  const boundary_id_type id)
1356 {
1357  libmesh_assert(elem);
1358 
1359  // The user shouldn't be trying to remove only one child's boundary
1360  // id
1361  libmesh_assert_equal_to (elem->level(), 0);
1362 
1363  std::pair<std::multimap<const Elem*,
1364  std::pair<unsigned short int, boundary_id_type> >::iterator,
1365  std::multimap<const Elem*,
1366  std::pair<unsigned short int, boundary_id_type> >::iterator >
1367  e = _boundary_side_id.equal_range(elem);
1368 
1369  // elem may be there, maybe multiple occurrences
1370  while (e.first != e.second)
1371  {
1372  // if this is true we found the requested side
1373  // of the element and want to erase the requested id
1374  if (e.first->second.first == side &&
1375  e.first->second.second == id)
1376  {
1377  // (postfix++ - increment the iterator before it's invalid)
1378  _boundary_side_id.erase(e.first++);
1379  }
1380  else
1381  ++e.first;
1382  }
1383 }
1384 
1385 
1386 
1387 unsigned int BoundaryInfo::side_with_boundary_id(const Elem* const elem,
1388  const boundary_id_type boundary_id_in) const
1389 {
1390  const Elem* searched_elem = elem;
1391  if (elem->level() != 0)
1392  searched_elem = elem->top_parent();
1393 
1394  std::pair<std::multimap<const Elem*,
1395  std::pair<unsigned short int, boundary_id_type> >::const_iterator,
1396  std::multimap<const Elem*,
1397  std::pair<unsigned short int, boundary_id_type> >::const_iterator >
1398  e = _boundary_side_id.equal_range(searched_elem);
1399 
1400  // elem may have zero or multiple occurrences
1401  for (; e.first != e.second; ++e.first)
1402  {
1403  // if this is true we found the requested boundary_id
1404  // of the element and want to return the side
1405  if (e.first->second.second == boundary_id_in)
1406  {
1407  unsigned int side = e.first->second.first;
1408 
1409  // If we're on this external boundary then we share this
1410  // external boundary id
1411  if (elem->neighbor(side) == NULL)
1412  return side;
1413 
1414  // If we're on an internal boundary then we need to be sure
1415  // it's the same internal boundary as our top_parent
1416  const Elem *p = elem;
1417 
1418 #ifdef LIBMESH_ENABLE_AMR
1419 
1420  while (p != NULL)
1421  {
1422  const Elem *parent = p->parent();
1423  if (!parent->is_child_on_side(parent->which_child_am_i(p), side))
1424  break;
1425  p = parent;
1426  }
1427 #endif
1428  // We're on that side of our top_parent; return it
1429  if (!p)
1430  return side;
1431  }
1432  }
1433 
1434  // if we get here, we found elem in the data structure but not
1435  // the requested boundary id, so return the default value
1436  return libMesh::invalid_uint;
1437 }
1438 
1439 void BoundaryInfo::build_node_boundary_ids(std::vector<boundary_id_type> &b_ids)
1440 {
1441  b_ids.clear();
1442 
1443  std::multimap<const Node*, boundary_id_type>::const_iterator pos
1444  = _boundary_node_id.begin();
1445 
1446  for (; pos != _boundary_node_id.end(); ++pos)
1447  {
1448  boundary_id_type id = pos->second;
1449 
1450  if(std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end())
1451  b_ids.push_back(id);
1452  }
1453 }
1454 
1455 void BoundaryInfo::build_side_boundary_ids(std::vector<boundary_id_type> &b_ids)
1456 {
1457  b_ids.clear();
1458 
1459  std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::const_iterator pos
1460  = _boundary_side_id.begin();
1461 
1462  for (; pos != _boundary_side_id.end(); ++pos)
1463  {
1464  boundary_id_type id = pos->second.second;
1465 
1466  if(std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end())
1467  b_ids.push_back(id);
1468  }
1469 }
1470 
1472 {
1473  // in serial we know the number of bcs from the
1474  // size of the container
1475  if (_mesh.is_serial())
1476  return _boundary_side_id.size();
1477 
1478  // in parallel we need to sum the number of local bcs
1479  parallel_object_only();
1480 
1481  std::size_t nbcs=0;
1482 
1483  std::multimap<const Elem*,
1484  std::pair<unsigned short int,
1485  boundary_id_type> >::const_iterator pos;
1486 
1487  for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end(); ++pos)
1488  if (pos->first->processor_id() == this->processor_id())
1489  nbcs++;
1490 
1491  this->comm().sum (nbcs);
1492 
1493  return nbcs;
1494 }
1495 
1496 std::size_t BoundaryInfo::n_edge_conds () const
1497 {
1498  // in serial we know the number of nodesets from the
1499  // size of the container
1500  if (_mesh.is_serial())
1501  return _boundary_edge_id.size();
1502 
1503  // in parallel we need to sum the number of local nodesets
1504  parallel_object_only();
1505 
1506  std::size_t n_edge_bcs=0;
1507 
1508  std::multimap<const Elem*,
1509  std::pair<unsigned short int,
1510  boundary_id_type> >::const_iterator pos;
1511 
1512  for (pos=_boundary_edge_id.begin(); pos != _boundary_edge_id.end(); ++pos)
1513  if (pos->first->processor_id() == this->processor_id())
1514  n_edge_bcs++;
1515 
1516  this->comm().sum (n_edge_bcs);
1517 
1518  return n_edge_bcs;
1519 }
1520 
1521 
1522 std::size_t BoundaryInfo::n_nodeset_conds () const
1523 {
1524  // in serial we know the number of nodesets from the
1525  // size of the container
1526  if (_mesh.is_serial())
1527  return _boundary_node_id.size();
1528 
1529  // in parallel we need to sum the number of local nodesets
1530  parallel_object_only();
1531 
1532  std::size_t n_nodesets=0;
1533 
1534  std::multimap<const Node*, boundary_id_type>::const_iterator pos;
1535 
1536  for (pos=_boundary_node_id.begin(); pos != _boundary_node_id.end(); ++pos)
1537  if (pos->first->processor_id() == this->processor_id())
1538  n_nodesets++;
1539 
1540  this->comm().sum (n_nodesets);
1541 
1542  return n_nodesets;
1543 }
1544 
1545 
1546 
1547 void BoundaryInfo::build_node_list (std::vector<dof_id_type>& nl,
1548  std::vector<boundary_id_type>& il) const
1549 {
1550  // Reserve the size, then use push_back
1551  nl.reserve (_boundary_node_id.size());
1552  il.reserve (_boundary_node_id.size());
1553 
1554  std::multimap<const Node*, boundary_id_type>::const_iterator pos
1555  = _boundary_node_id.begin();
1556 
1557  for (; pos != _boundary_node_id.end(); ++pos)
1558  {
1559  nl.push_back (pos->first->id());
1560  il.push_back (pos->second);
1561  }
1562 }
1563 
1564 
1565 void
1567 {
1568  std::multimap<const Elem*,
1569  std::pair<unsigned short int,
1570  boundary_id_type> >::const_iterator pos;
1571 
1572  //Loop over the side list
1573  for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end(); ++pos)
1574  {
1575  // Don't add remote sides
1576  if(pos->first->is_remote())
1577  continue;
1578 
1579  //Need to loop over the sides of any possible children
1580  std::vector< const Elem * > family;
1581 #ifdef LIBMESH_ENABLE_AMR
1582  pos->first->active_family_tree_by_side (family, pos->second.first);
1583 #else
1584  family.push_back(pos->first);
1585 #endif
1586 
1587  for(std::size_t elem_it=0; elem_it < family.size(); elem_it++)
1588  {
1589  const Elem * cur_elem = family[elem_it];
1590 
1591  AutoPtr<Elem> side = cur_elem->build_side(pos->second.first);
1592 
1593  //Add each node node on the side with the side's boundary id
1594  for(unsigned int i=0; i<side->n_nodes(); i++)
1595  {
1596  Node * node = side->get_node(i);
1597 
1598  this->add_node(node, pos->second.second);
1599  }
1600  }
1601  }
1602 }
1603 
1604 
1605 
1606 
1608 {
1609  // Check for early return
1610  if (_boundary_node_id.empty())
1611  {
1612  libMesh::out << "No boundary node IDs have been added: cannot build side list!" << std::endl;
1613  return;
1614  }
1615 
1616  // typedef for less typing!
1617  typedef std::multimap<const Node*, boundary_id_type>::const_iterator iterator_t;
1618 
1619  // Return value and iterator for equal_range()
1620  iterator_t pos;
1621  std::pair<iterator_t, iterator_t> range;
1622 
1625 
1626  for (; el != end_el; ++el)
1627  {
1628  const Elem* elem = *el;
1629 
1630  for (unsigned side=0; side<elem->n_sides(); ++side)
1631  {
1632  AutoPtr<Elem> side_elem = elem->build_side(side);
1633 
1634  // map from nodeset_id to count for that ID
1635  std::map<dof_id_type, unsigned> nodesets_node_count;
1636  for (unsigned node_num=0; node_num < side_elem->n_nodes(); ++node_num)
1637  {
1638  Node* node = side_elem->get_node(node_num);
1639  range = _boundary_node_id.equal_range(node);
1640 
1641  // For each nodeset that this node is a member of, increment the associated
1642  // nodeset ID count
1643  for (pos = range.first; pos != range.second; ++pos)
1644  {
1645  nodesets_node_count[pos->second]++;
1646  }
1647  }
1648 
1649  // Now check to see what nodeset_counts have the correct number of nodes in them
1650  for (std::map<dof_id_type, unsigned>::const_iterator nodesets = nodesets_node_count.begin();
1651  nodesets != nodesets_node_count.end(); ++nodesets)
1652  {
1653  if (nodesets->second == side_elem->n_nodes())
1654  {
1655  // Add this side to the sideset
1656  add_side(elem, side, nodesets->first);
1657  }
1658  }
1659  } // end for side
1660  } // end for el
1661 }
1662 
1663 
1664 
1665 
1666 void BoundaryInfo::build_side_list (std::vector<dof_id_type>& el,
1667  std::vector<unsigned short int>& sl,
1668  std::vector<boundary_id_type>& il) const
1669 {
1670  // Reserve the size, then use push_back
1671  el.reserve (_boundary_side_id.size());
1672  sl.reserve (_boundary_side_id.size());
1673  il.reserve (_boundary_side_id.size());
1674 
1675  std::multimap<const Elem*,
1676  std::pair<unsigned short int,
1677  boundary_id_type> >::const_iterator pos;
1678 
1679  for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end();
1680  ++pos)
1681  {
1682  el.push_back (pos->first->id());
1683  sl.push_back (pos->second.first);
1684  il.push_back (pos->second.second);
1685  }
1686 }
1687 
1688 
1689 
1690 void BoundaryInfo::print_info(std::ostream& out_stream) const
1691 {
1692  // Print out the nodal BCs
1693  if (!_boundary_node_id.empty())
1694  {
1695  out_stream << "Nodal Boundary conditions:" << std::endl
1696  << "--------------------------" << std::endl
1697  << " (Node No., ID) " << std::endl;
1698 
1699 // std::for_each(_boundary_node_id.begin(),
1700 // _boundary_node_id.end(),
1701 // PrintNodeInfo());
1702 
1703  std::multimap<const Node*, boundary_id_type>::const_iterator it = _boundary_node_id.begin();
1704  const std::multimap<const Node*, boundary_id_type>::const_iterator end = _boundary_node_id.end();
1705 
1706  for (; it != end; ++it)
1707  out_stream << " (" << (*it).first->id()
1708  << ", " << (*it).second
1709  << ")" << std::endl;
1710  }
1711 
1712  // Print out the element edge BCs
1713  if (!_boundary_edge_id.empty())
1714  {
1715  out_stream << std::endl
1716  << "Edge Boundary conditions:" << std::endl
1717  << "-------------------------" << std::endl
1718  << " (Elem No., Edge No., ID) " << std::endl;
1719 
1720 // std::for_each(_boundary_edge_id.begin(),
1721 // _boundary_edge_id.end(),
1722 // PrintSideInfo());
1723 
1724  std::multimap<const Elem*,
1725  std::pair<unsigned short int, boundary_id_type> >::const_iterator it = _boundary_edge_id.begin();
1726  const std::multimap<const Elem*,
1727  std::pair<unsigned short int, boundary_id_type> >::const_iterator end = _boundary_edge_id.end();
1728 
1729  for (; it != end; ++it)
1730  out_stream << " (" << (*it).first->id()
1731  << ", " << (*it).second.first
1732  << ", " << (*it).second.second
1733  << ")" << std::endl;
1734  }
1735 
1736  // Print out the element side BCs
1737  if (!_boundary_side_id.empty())
1738  {
1739  out_stream << std::endl
1740  << "Side Boundary conditions:" << std::endl
1741  << "-------------------------" << std::endl
1742  << " (Elem No., Side No., ID) " << std::endl;
1743 
1744 // std::for_each(_boundary_side_id.begin(),
1745 // _boundary_side_id.end(),
1746 // PrintSideInfo());
1747 
1748  std::multimap<const Elem*,
1749  std::pair<unsigned short int, boundary_id_type> >::const_iterator it = _boundary_side_id.begin();
1750  const std::multimap<const Elem*,
1751  std::pair<unsigned short int, boundary_id_type> >::const_iterator end = _boundary_side_id.end();
1752 
1753  for (; it != end; ++it)
1754  out_stream << " (" << (*it).first->id()
1755  << ", " << (*it).second.first
1756  << ", " << (*it).second.second
1757  << ")" << std::endl;
1758  }
1759 }
1760 
1761 
1762 
1763 void BoundaryInfo::print_summary(std::ostream& out_stream) const
1764 {
1765  // Print out the nodal BCs
1766  if (!_boundary_node_id.empty())
1767  {
1768  out_stream << "Nodal Boundary conditions:" << std::endl
1769  << "--------------------------" << std::endl
1770  << " (ID, number of nodes) " << std::endl;
1771 
1772  std::map<boundary_id_type, std::size_t> ID_counts;
1773 
1774  std::multimap<const Node*, boundary_id_type>::const_iterator it = _boundary_node_id.begin();
1775  const std::multimap<const Node*, boundary_id_type>::const_iterator end = _boundary_node_id.end();
1776 
1777  for (; it != end; ++it)
1778  ID_counts[(*it).second]++;
1779 
1780  std::map<boundary_id_type, std::size_t>::const_iterator ID_it = ID_counts.begin();
1781  const std::map<boundary_id_type, std::size_t>::const_iterator ID_end = ID_counts.end();
1782 
1783  for (; ID_it != ID_end; ++ID_it)
1784  out_stream << " (" << (*ID_it).first
1785  << ", " << (*ID_it).second
1786  << ")" << std::endl;
1787  }
1788 
1789  // Print out the element edge BCs
1790  if (!_boundary_edge_id.empty())
1791  {
1792  out_stream << std::endl
1793  << "Edge Boundary conditions:" << std::endl
1794  << "-------------------------" << std::endl
1795  << " (ID, number of edges) " << std::endl;
1796 
1797  std::map<boundary_id_type, std::size_t> ID_counts;
1798 
1799  std::multimap<const Elem*,
1800  std::pair<unsigned short int, boundary_id_type> >::const_iterator it = _boundary_edge_id.begin();
1801  const std::multimap<const Elem*,
1802  std::pair<unsigned short int, boundary_id_type> >::const_iterator end = _boundary_edge_id.end();
1803 
1804  for (; it != end; ++it)
1805  ID_counts[(*it).second.second]++;
1806 
1807  std::map<boundary_id_type, std::size_t>::const_iterator ID_it = ID_counts.begin();
1808  const std::map<boundary_id_type, std::size_t>::const_iterator ID_end = ID_counts.end();
1809 
1810  for (; ID_it != ID_end; ++ID_it)
1811  out_stream << " (" << (*ID_it).first
1812  << ", " << (*ID_it).second
1813  << ")" << std::endl;
1814  }
1815 
1816  // Print out the element side BCs
1817  if (!_boundary_side_id.empty())
1818  {
1819  out_stream << std::endl
1820  << "Side Boundary conditions:" << std::endl
1821  << "-------------------------" << std::endl
1822  << " (ID, number of sides) " << std::endl;
1823 
1824  std::map<boundary_id_type, std::size_t> ID_counts;
1825 
1826  std::multimap<const Elem*,
1827  std::pair<unsigned short int, boundary_id_type> >::const_iterator it = _boundary_side_id.begin();
1828  const std::multimap<const Elem*,
1829  std::pair<unsigned short int, boundary_id_type> >::const_iterator end = _boundary_side_id.end();
1830 
1831  for (; it != end; ++it)
1832  ID_counts[(*it).second.second]++;
1833 
1834  std::map<boundary_id_type, std::size_t>::const_iterator ID_it = ID_counts.begin();
1835  const std::map<boundary_id_type, std::size_t>::const_iterator ID_end = ID_counts.end();
1836 
1837  for (; ID_it != ID_end; ++ID_it)
1838  out_stream << " (" << (*ID_it).first
1839  << ", " << (*ID_it).second
1840  << ")" << std::endl;
1841  }
1842 }
1843 
1845 {
1846  return _ss_id_to_name[id];
1847 }
1848 
1850 {
1851  return _ns_id_to_name[id];
1852 }
1853 
1855 {
1856  // This function is searching the keys of the map
1857  // We might want to make this more efficient
1858  std::map<boundary_id_type, std::string>::const_iterator iter = _ss_id_to_name.begin();
1859  std::map<boundary_id_type, std::string>::const_iterator end_iter = _ss_id_to_name.end();
1860 
1861  for ( ; iter != end_iter; ++iter)
1862  {
1863  if (iter->second == name)
1864  return iter->first;
1865  }
1866 
1867  // Loop over nodesets
1868  iter = _ns_id_to_name.begin();
1869  end_iter = _ns_id_to_name.end();
1870  for ( ; iter != end_iter; ++iter)
1871  {
1872  if (iter->second == name)
1873  return iter->first;
1874  }
1875 
1876  libMesh::err << "The sideset/nodeset named " << name << " does not exist in mesh!" << std::endl;
1877  libmesh_error();
1878 }
1879 
1880 } // namespace libMesh

Site Created By: libMesh Developers
Last modified: February 07 2014 16:57:04 UTC

Hosted By:
SourceForge.net Logo