$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 // C++ includes 00021 #include <iterator> // std::distance 00022 00023 // Local includes 00024 #include "libmesh/libmesh_config.h" 00025 #include "libmesh/boundary_info.h" 00026 #include "libmesh/elem.h" 00027 #include "libmesh/mesh_data.h" 00028 #include "libmesh/mesh_serializer.h" 00029 #include "libmesh/parallel.h" 00030 #include "libmesh/partitioner.h" 00031 #include "libmesh/unstructured_mesh.h" 00032 00033 namespace libMesh 00034 { 00035 00036 00037 00038 //------------------------------------------------------ 00039 // BoundaryInfo static member initializations 00040 const boundary_id_type BoundaryInfo::invalid_id = -123; 00041 00042 00043 00044 //------------------------------------------------------ 00045 // BoundaryInfo functions 00046 BoundaryInfo::BoundaryInfo(const MeshBase& m) : 00047 ParallelObject(m.comm()), 00048 _mesh (m) 00049 { 00050 } 00051 00052 BoundaryInfo& BoundaryInfo::operator=(const BoundaryInfo& other_boundary_info) 00053 { 00060 // Copy node boundary info 00061 { 00062 std::multimap<const Node*, boundary_id_type>::const_iterator it = other_boundary_info._boundary_node_id.begin(); 00063 const std::multimap<const Node*, boundary_id_type>::const_iterator end = other_boundary_info._boundary_node_id.end(); 00064 00065 for(; it != end; ++it) 00066 { 00067 const Node * other_node = it->first; 00068 _boundary_node_id.insert 00069 (std::pair<const Node*, boundary_id_type> 00070 (_mesh.node_ptr(other_node->id()), it->second) ); 00071 } 00072 } 00073 00074 // Copy edge boundary info 00075 { 00076 std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00077 const_iterator it = other_boundary_info._boundary_edge_id.begin(); 00078 const std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00079 const_iterator end = other_boundary_info._boundary_edge_id.end(); 00080 00081 for(; it != end; ++it) 00082 { 00083 const Elem * other_elem = it->first; 00084 _boundary_edge_id.insert 00085 (std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> > 00086 (_mesh.elem(other_elem->id()), it->second) ); 00087 } 00088 } 00089 00090 // Copy side boundary info 00091 { 00092 std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00093 const_iterator it = other_boundary_info._boundary_side_id.begin(); 00094 const std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00095 const_iterator end = other_boundary_info._boundary_side_id.end(); 00096 00097 for(; it != end; ++it) 00098 { 00099 const Elem * other_elem = it->first; 00100 _boundary_side_id.insert 00101 (std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> > 00102 (_mesh.elem(other_elem->id()), it->second) ); 00103 } 00104 } 00105 00106 _boundary_ids = other_boundary_info._boundary_ids; 00107 _side_boundary_ids = other_boundary_info._side_boundary_ids; 00108 _node_boundary_ids = other_boundary_info._node_boundary_ids; 00109 00110 return *this; 00111 } 00112 00113 00114 BoundaryInfo::~BoundaryInfo() 00115 { 00116 this->clear(); 00117 } 00118 00119 00120 00121 void BoundaryInfo::clear() 00122 { 00123 _boundary_node_id.clear(); 00124 _boundary_side_id.clear(); 00125 _boundary_ids.clear(); 00126 _side_boundary_ids.clear(); 00127 _node_boundary_ids.clear(); 00128 } 00129 00130 00131 00132 void BoundaryInfo::sync (UnstructuredMesh& boundary_mesh, 00133 MeshData* boundary_mesh_data, 00134 MeshData* this_mesh_data) 00135 { 00136 std::set<boundary_id_type> request_boundary_ids(_boundary_ids); 00137 request_boundary_ids.insert(invalid_id); 00138 if (!_mesh.is_serial()) 00139 this->comm().set_union(request_boundary_ids); 00140 00141 this->sync(request_boundary_ids, boundary_mesh, 00142 boundary_mesh_data, this_mesh_data); 00143 } 00144 00145 00146 00147 void BoundaryInfo::sync (const std::set<boundary_id_type> &requested_boundary_ids, 00148 UnstructuredMesh& boundary_mesh, 00149 MeshData* boundary_mesh_data, 00150 MeshData* this_mesh_data) 00151 { 00152 START_LOG("sync()", "BoundaryInfo"); 00153 00154 boundary_mesh.clear(); 00155 00161 if (!_mesh.is_serial()) 00162 boundary_mesh.delete_remote_elements(); 00163 00170 MeshSerializer serializer 00171 (const_cast<MeshBase&>(_mesh), boundary_mesh.is_serial()); 00172 00186 boundary_mesh.set_n_partitions() = _mesh.n_partitions(); 00187 00188 std::map<dof_id_type, dof_id_type> node_id_map; 00189 std::map<std::pair<dof_id_type, unsigned char>, dof_id_type> side_id_map; 00190 00191 // We'll do the same modulus trick that ParallelMesh uses to avoid 00192 // id conflicts between different processors 00193 dof_id_type next_node_id = this->processor_id(), 00194 next_elem_id = this->processor_id(); 00195 00196 // We'll pass through the mesh once first to build 00197 // the maps and count boundary nodes and elements 00198 // We have to examine all elements here rather than just local 00199 // elements, because it's possible to have a local boundary node 00200 // that's not on a local boundary element, e.g. at the tip of a 00201 // triangle. 00202 const MeshBase::const_element_iterator end_el = _mesh.elements_end(); 00203 for (MeshBase::const_element_iterator el = _mesh.elements_begin(); 00204 el != end_el; ++el) 00205 { 00206 const Elem *elem = *el; 00207 00208 for (unsigned char s=0; s<elem->n_sides(); s++) 00209 if (elem->neighbor(s) == NULL) // on the boundary 00210 { 00211 // Get the top-level parent for this element 00212 const Elem* top_parent = elem->top_parent(); 00213 00214 // A convenient typedef 00215 typedef 00216 std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00217 const_iterator Iter; 00218 00219 // Find the right id number for that side 00220 std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(top_parent); 00221 00222 bool add_this_side = false; 00223 boundary_id_type this_bcid = invalid_id; 00224 00225 for (; pos.first != pos.second; ++pos.first) 00226 { 00227 this_bcid = pos.first->second.second; 00228 00229 // if this side is flagged with a boundary condition 00230 // and the user wants this id 00231 if ((pos.first->second.first == s) && 00232 (requested_boundary_ids.count(this_bcid))) 00233 { 00234 add_this_side = true; 00235 break; 00236 } 00237 } 00238 00239 // if side s wasn't found or doesn't have a boundary 00240 // condition we may still want to add it 00241 if (pos.first == pos.second) 00242 { 00243 this_bcid = invalid_id; 00244 if (requested_boundary_ids.count(this_bcid)) 00245 add_this_side = true; 00246 } 00247 00248 if (add_this_side) 00249 { 00250 std::pair<dof_id_type, unsigned char> side_pair(elem->id(), s); 00251 libmesh_assert (!side_id_map.count(side_pair)); 00252 side_id_map[side_pair] = next_elem_id; 00253 next_elem_id += this->n_processors() + 1; 00254 00255 // Use a proxy element for the side to query nodes 00256 UniquePtr<Elem> side (elem->build_side(s)); 00257 for (unsigned int n = 0; n != side->n_nodes(); ++n) 00258 { 00259 Node *node = side->get_node(n); 00260 libmesh_assert(node); 00261 00262 // In parallel we only know enough to number our own nodes. 00263 if (node->processor_id() != this->processor_id()) 00264 continue; 00265 00266 dof_id_type node_id = node->id(); 00267 if (!node_id_map.count(node_id)) 00268 { 00269 node_id_map[node_id] = next_node_id; 00270 next_node_id += this->n_processors() + 1; 00271 } 00272 } 00273 } 00274 } 00275 } 00276 00277 // Join up the results from other processors 00278 this->comm().set_union(side_id_map); 00279 this->comm().set_union(node_id_map); 00280 00281 // Finally we'll pass through any unpartitioned elements to add them 00282 // to the maps and counts. 00283 next_node_id = this->n_processors(); 00284 next_elem_id = this->n_processors(); 00285 00286 const MeshBase::const_element_iterator end_unpartitioned_el = 00287 _mesh.pid_elements_end(DofObject::invalid_processor_id); 00288 for (MeshBase::const_element_iterator el = 00289 _mesh.pid_elements_begin(DofObject::invalid_processor_id); 00290 el != end_unpartitioned_el; ++el) 00291 { 00292 const Elem *elem = *el; 00293 00294 for (unsigned char s=0; s<elem->n_sides(); s++) 00295 if (elem->neighbor(s) == NULL) // on the boundary 00296 { 00297 // Get the top-level parent for this element 00298 const Elem* top_parent = elem->top_parent(); 00299 00300 // A convenient typedef 00301 typedef 00302 std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00303 const_iterator Iter; 00304 00305 // Find the right id number for that side 00306 std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(top_parent); 00307 00308 bool add_this_side = false; 00309 boundary_id_type this_bcid = invalid_id; 00310 00311 for (; pos.first != pos.second; ++pos.first) 00312 { 00313 this_bcid = pos.first->second.second; 00314 // if this side is flagged with a boundary condition 00315 // and the user wants this id 00316 if ((pos.first->second.first == s) && 00317 (requested_boundary_ids.count(this_bcid))) 00318 { 00319 add_this_side = true; 00320 break; 00321 } 00322 } 00323 00324 // if side s doesn't have a boundary condition we may 00325 // still want to add it 00326 if (pos.first == pos.second) 00327 { 00328 this_bcid = invalid_id; 00329 if (requested_boundary_ids.count(this_bcid)) 00330 add_this_side = true; 00331 } 00332 00333 if (add_this_side) 00334 { 00335 std::pair<dof_id_type, unsigned char> side_pair(elem->id(), s); 00336 libmesh_assert (!side_id_map.count(side_pair)); 00337 side_id_map[side_pair] = next_elem_id; 00338 next_elem_id += this->n_processors() + 1; 00339 00340 // Use a proxy element for the side to query nodes 00341 UniquePtr<Elem> side (elem->build_side(s)); 00342 for (unsigned int n = 0; n != side->n_nodes(); ++n) 00343 { 00344 Node *node = side->get_node(n); 00345 libmesh_assert(node); 00346 dof_id_type node_id = node->id(); 00347 if (!node_id_map.count(node_id)) 00348 { 00349 node_id_map[node_id] = next_node_id; 00350 next_node_id += this->n_processors() + 1; 00351 } 00352 } 00353 } 00354 } 00355 } 00356 00357 // FIXME: ought to renumber side/node_id_map image to be contiguous 00358 // to save memory, also ought to reserve memory 00359 00360 // Let's add all the nodes to the boundary mesh 00361 00362 MeshBase::const_node_iterator n_end = _mesh.nodes_end(); 00363 00364 for(MeshBase::const_node_iterator n_it = _mesh.nodes_begin(); 00365 n_it != n_end; ++n_it) 00366 { 00367 const Node* node = *n_it; 00368 dof_id_type node_id = node->id(); 00369 if (node_id_map.count(node_id)) 00370 boundary_mesh.add_point(*node, node_id_map[node_id], node->processor_id()); 00371 } 00372 00373 00374 // Finally let's add the elements 00375 00376 00377 for (MeshBase::const_element_iterator el = _mesh.elements_begin(); 00378 el != end_el; ++el) 00379 { 00380 const Elem* elem = *el; 00381 00382 for (unsigned int s=0; s<elem->n_sides(); s++) 00383 if (elem->neighbor(s) == NULL) // on the boundary 00384 { 00385 // Get the top-level parent for this element 00386 const Elem* top_parent = elem->top_parent(); 00387 00388 // A convenient typedef 00389 typedef 00390 std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00391 const_iterator Iter; 00392 00393 // Find the right id number for that side 00394 std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(top_parent); 00395 00396 bool add_this_side = false; 00397 boundary_id_type this_bcid = invalid_id; 00398 00399 for (; pos.first != pos.second; ++pos.first) 00400 { 00401 this_bcid = pos.first->second.second; 00402 00403 // if this side is flagged with a boundary condition 00404 // and the user wants this id 00405 if ((pos.first->second.first == s) && 00406 (requested_boundary_ids.count(this_bcid))) 00407 { 00408 add_this_side = true; 00409 break; 00410 } 00411 } 00412 00413 // if side s wasn't found or doesn't have a boundary 00414 // condition we may still want to add it 00415 if (pos.first == pos.second) 00416 { 00417 this_bcid = invalid_id; 00418 if (requested_boundary_ids.count(this_bcid)) 00419 add_this_side = true; 00420 } 00421 00422 if (add_this_side) 00423 { 00424 // Build the side - do not use a "proxy" element here: 00425 // This will be going into the boundary_mesh and needs to 00426 // stand on its own. 00427 UniquePtr<Elem> side (elem->build_side(s, false)); 00428 00429 side->processor_id() = elem->processor_id(); 00430 00431 const std::pair<dof_id_type, unsigned char> side_pair(elem->id(), s); 00432 00433 libmesh_assert(side_id_map.count(side_pair)); 00434 00435 side->set_id(side_id_map[side_pair]); 00436 00437 // Add the side 00438 Elem* new_elem = boundary_mesh.add_elem(side.release()); 00439 00440 // This side's Node pointers still point to the nodes of the original mesh. 00441 // We need to re-point them to the boundary mesh's nodes! Since we copied *ALL* of 00442 // the original mesh's nodes over, we should be guaranteed to have the same ordering. 00443 for (unsigned int nn=0; nn<new_elem->n_nodes(); ++nn) 00444 { 00445 // Get the correct node pointer, based on the id() 00446 Node* new_node = boundary_mesh.node_ptr(node_id_map[new_elem->node(nn)]); 00447 00448 // sanity check: be sure that the new Node exists 00449 // and its global id really matches 00450 libmesh_assert (new_node); 00451 libmesh_assert_equal_to (new_node->id(), node_id_map[new_elem->node(nn)]); 00452 00453 // Assign the new node pointer 00454 new_elem->set_node(nn) = new_node; 00455 } 00456 00457 #ifdef LIBMESH_ENABLE_AMR 00458 // Finally, set the parent and interior_parent links 00459 if (elem->parent()) 00460 { 00461 const std::pair<dof_id_type, unsigned char> parent_side_pair(elem->parent()->id(), s); 00462 00463 libmesh_assert(side_id_map.count(parent_side_pair)); 00464 00465 Elem* side_parent = boundary_mesh.elem(side_id_map[parent_side_pair]); 00466 00467 libmesh_assert(side_parent); 00468 00469 new_elem->set_parent(side_parent); 00470 00471 side_parent->set_refinement_flag(Elem::INACTIVE); 00472 00473 // Figuring out which child we are of our parent 00474 // is a trick. Due to libMesh child numbering 00475 // conventions, if we are an element on a vertex, 00476 // then we share that vertex with our parent, with 00477 // the same local index. 00478 bool found_child = false; 00479 for (unsigned int v=0; v != new_elem->n_vertices(); ++v) 00480 if (new_elem->get_node(v) == side_parent->get_node(v)) 00481 { 00482 side_parent->add_child(new_elem, v); 00483 found_child = true; 00484 } 00485 00486 // If we don't share any vertex with our parent, 00487 // then we're the fourth child (index 3) of a 00488 // triangle. 00489 if (!found_child) 00490 { 00491 libmesh_assert_equal_to (new_elem->n_vertices(), 3); 00492 side_parent->add_child(new_elem, 3); 00493 } 00494 } 00495 #endif 00496 00497 new_elem->set_interior_parent (const_cast<Elem*>(elem)); 00498 } 00499 } 00500 } 00501 00502 // When desired, copy the MeshData 00503 // to the boundary_mesh 00504 if ((boundary_mesh_data != NULL) && (this_mesh_data != NULL)) 00505 boundary_mesh_data->assign(*this_mesh_data); 00506 00507 // Don't repartition this mesh; we want it to stay in sync with the 00508 // interior partitioning. 00509 boundary_mesh.partitioner().reset(NULL); 00510 00511 // Make boundary_mesh nodes and elements contiguous 00512 boundary_mesh.prepare_for_use(/*skip_renumber =*/ false); 00513 00514 // and finally distribute element partitioning to the nodes 00515 Partitioner::set_node_processor_ids(boundary_mesh); 00516 00517 STOP_LOG("sync()", "BoundaryInfo"); 00518 } 00519 00520 00521 00522 void BoundaryInfo::add_node(const dof_id_type node, 00523 const boundary_id_type id) 00524 { 00525 this->add_node (_mesh.node_ptr(node), id); 00526 } 00527 00528 00529 00530 void BoundaryInfo::add_node(const Node* node, 00531 const boundary_id_type id) 00532 { 00533 if (id == invalid_id) 00534 libmesh_error_msg("ERROR: You may not set a boundary ID of " \ 00535 << invalid_id \ 00536 << "\n That is reserved for internal use."); 00537 00538 // A convenient typedef 00539 typedef std::multimap<const Node*, boundary_id_type>::const_iterator Iter; 00540 00541 // Don't add the same ID twice 00542 std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node); 00543 00544 for (;pos.first != pos.second; ++pos.first) 00545 if (pos.first->second == id) 00546 return; 00547 00548 std::pair<const Node*, boundary_id_type> kv (node, id); 00549 00550 _boundary_node_id.insert(kv); 00551 _boundary_ids.insert(id); 00552 _node_boundary_ids.insert(id); // Also add this ID to the set of node boundary IDs 00553 } 00554 00555 void BoundaryInfo::add_node(const Node* node, 00556 const std::vector<boundary_id_type>& ids) 00557 { 00558 if (ids.empty()) 00559 return; 00560 00561 libmesh_assert(node); 00562 00563 // A convenient typedef 00564 typedef std::multimap<const Node*, boundary_id_type>::const_iterator Iter; 00565 00566 // Don't add the same ID twice 00567 std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node); 00568 00569 for (unsigned int i=0; i!= ids.size(); ++i) 00570 { 00571 boundary_id_type id=ids[i]; 00572 00573 if (id == invalid_id) 00574 libmesh_error_msg("ERROR: You may not set a boundary ID of " \ 00575 << invalid_id \ 00576 << "\n That is reserved for internal use."); 00577 00578 bool already_inserted = false; 00579 for (Iter p = pos.first;p != pos.second; ++p) 00580 if (p->second == id) 00581 { 00582 already_inserted = true; 00583 break; 00584 } 00585 if (already_inserted) 00586 continue; 00587 00588 std::pair<const Node*, boundary_id_type> kv (node, id); 00589 00590 _boundary_node_id.insert(kv); 00591 _boundary_ids.insert(id); 00592 _node_boundary_ids.insert(id); // Also add this ID to the set of node boundary IDs 00593 } 00594 } 00595 00596 00597 void BoundaryInfo::clear_boundary_node_ids() 00598 { 00599 _boundary_node_id.clear(); 00600 } 00601 00602 void BoundaryInfo::add_edge(const dof_id_type e, 00603 const unsigned short int edge, 00604 const boundary_id_type id) 00605 { 00606 this->add_edge (_mesh.elem(e), edge, id); 00607 } 00608 00609 00610 00611 void BoundaryInfo::add_edge(const Elem* elem, 00612 const unsigned short int edge, 00613 const boundary_id_type id) 00614 { 00615 libmesh_assert(elem); 00616 00617 // Only add BCs for level-0 elements. 00618 libmesh_assert_equal_to (elem->level(), 0); 00619 00620 if (id == invalid_id) 00621 libmesh_error_msg("ERROR: You may not set a boundary ID of " \ 00622 << invalid_id \ 00623 << "\n That is reserved for internal use."); 00624 00625 // A convenient typedef 00626 typedef std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00627 const_iterator Iter; 00628 00629 // Don't add the same ID twice 00630 std::pair<Iter, Iter> pos = _boundary_edge_id.equal_range(elem); 00631 00632 for (;pos.first != pos.second; ++pos.first) 00633 if (pos.first->second.first == edge && 00634 pos.first->second.second == id) 00635 return; 00636 00637 std::pair<unsigned short int, boundary_id_type> p(edge,id); 00638 std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> > 00639 kv (elem, p); 00640 00641 _boundary_edge_id.insert(kv); 00642 _boundary_ids.insert(id); 00643 _edge_boundary_ids.insert(id); // Also add this ID to the set of edge boundary IDs 00644 } 00645 00646 00647 00648 void BoundaryInfo::add_edge(const Elem* elem, 00649 const unsigned short int edge, 00650 const std::vector<boundary_id_type>& ids) 00651 { 00652 if (ids.empty()) 00653 return; 00654 00655 libmesh_assert(elem); 00656 00657 // Only add BCs for level-0 elements. 00658 libmesh_assert_equal_to (elem->level(), 0); 00659 00660 // A convenient typedef 00661 typedef std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00662 const_iterator Iter; 00663 00664 // Don't add the same ID twice 00665 std::pair<Iter, Iter> pos = _boundary_edge_id.equal_range(elem); 00666 00667 for (unsigned int i=0; i!= ids.size(); ++i) 00668 { 00669 boundary_id_type id=ids[i]; 00670 00671 if (id == invalid_id) 00672 libmesh_error_msg("ERROR: You may not set a boundary ID of " \ 00673 << invalid_id \ 00674 << "\n That is reserved for internal use."); 00675 00676 bool already_inserted = false; 00677 for (Iter p = pos.first;p != pos.second; ++p) 00678 if (p->second.first == edge && 00679 p->second.second == id) 00680 { 00681 already_inserted = true; 00682 break; 00683 } 00684 if (already_inserted) 00685 continue; 00686 00687 std::pair<unsigned short int, boundary_id_type> p(edge,id); 00688 std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> > 00689 kv (elem, p); 00690 00691 _boundary_edge_id.insert(kv); 00692 _boundary_ids.insert(id); 00693 _edge_boundary_ids.insert(id); // Also add this ID to the set of edge boundary IDs 00694 } 00695 } 00696 00697 void BoundaryInfo::add_side(const dof_id_type e, 00698 const unsigned short int side, 00699 const boundary_id_type id) 00700 { 00701 this->add_side (_mesh.elem(e), side, id); 00702 } 00703 00704 00705 00706 void BoundaryInfo::add_side(const Elem* elem, 00707 const unsigned short int side, 00708 const boundary_id_type id) 00709 { 00710 libmesh_assert(elem); 00711 00712 // Only add BCs for level-0 elements. 00713 libmesh_assert_equal_to (elem->level(), 0); 00714 00715 if (id == invalid_id) 00716 libmesh_error_msg("ERROR: You may not set a boundary ID of " \ 00717 << invalid_id \ 00718 << "\n That is reserved for internal use."); 00719 00720 // A convenient typedef 00721 typedef std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00722 const_iterator Iter; 00723 00724 // Don't add the same ID twice 00725 std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(elem); 00726 00727 for (;pos.first != pos.second; ++pos.first) 00728 if (pos.first->second.first == side && 00729 pos.first->second.second == id) 00730 return; 00731 00732 std::pair<unsigned short int, boundary_id_type> p(side,id); 00733 std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> > 00734 kv (elem, p); 00735 00736 _boundary_side_id.insert(kv); 00737 _boundary_ids.insert(id); 00738 _side_boundary_ids.insert(id); // Also add this ID to the set of side boundary IDs 00739 } 00740 00741 00742 00743 void BoundaryInfo::add_side(const Elem* elem, 00744 const unsigned short int side, 00745 const std::vector<boundary_id_type>& ids) 00746 { 00747 if (ids.empty()) 00748 return; 00749 00750 libmesh_assert(elem); 00751 00752 // Only add BCs for level-0 elements. 00753 libmesh_assert_equal_to (elem->level(), 0); 00754 00755 // A convenient typedef 00756 typedef std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >:: 00757 const_iterator Iter; 00758 00759 // Don't add the same ID twice 00760 std::pair<Iter, Iter> pos = _boundary_side_id.equal_range(elem); 00761 00762 for (unsigned int i=0; i!= ids.size(); ++i) 00763 { 00764 boundary_id_type id=ids[i]; 00765 00766 if (id == invalid_id) 00767 libmesh_error_msg("ERROR: You may not set a boundary ID of " \ 00768 << invalid_id \ 00769 << "\n That is reserved for internal use."); 00770 00771 bool already_inserted = false; 00772 for (Iter p = pos.first;p != pos.second; ++p) 00773 if (p->second.first == side && 00774 p->second.second == id) 00775 { 00776 already_inserted = true; 00777 break; 00778 } 00779 if (already_inserted) 00780 continue; 00781 00782 std::pair<unsigned short int, boundary_id_type> p(side,id); 00783 std::pair<const Elem*, std::pair<unsigned short int, boundary_id_type> > 00784 kv (elem, p); 00785 00786 _boundary_side_id.insert(kv); 00787 _boundary_ids.insert(id); 00788 _side_boundary_ids.insert(id); // Also add this ID to the set of side boundary IDs 00789 } 00790 } 00791 00792 00793 00794 bool BoundaryInfo::has_boundary_id(const Node* const node, 00795 const boundary_id_type id) const 00796 { 00797 // A convenient typedef 00798 typedef std::multimap<const Node*, boundary_id_type>::const_iterator Iter; 00799 00800 std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node); 00801 00802 for (;pos.first != pos.second; ++pos.first) 00803 if (pos.first->second == id) 00804 return true; 00805 00806 return false; 00807 } 00808 00809 00810 00811 std::vector<boundary_id_type> BoundaryInfo::boundary_ids(const Node* node) const 00812 { 00813 std::vector<boundary_id_type> ids; 00814 00815 // A convenient typedef 00816 typedef std::multimap<const Node*, boundary_id_type>::const_iterator Iter; 00817 00818 std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node); 00819 00820 for (;pos.first != pos.second; ++pos.first) 00821 ids.push_back(pos.first->second); 00822 00823 return ids; 00824 } 00825 00826 00827 00828 unsigned int BoundaryInfo::n_boundary_ids(const Node* node) const 00829 { 00830 // A convenient typedef 00831 typedef std::multimap<const Node*, boundary_id_type>::const_iterator Iter; 00832 00833 std::pair<Iter, Iter> pos = _boundary_node_id.equal_range(node); 00834 00835 return cast_int<unsigned int> 00836 (std::distance(pos.first, pos.second)); 00837 } 00838 00839 00840 00841 std::vector<boundary_id_type> BoundaryInfo::edge_boundary_ids (const Elem* const elem, 00842 const unsigned short int edge) const 00843 { 00844 libmesh_assert(elem); 00845 00846 std::vector<boundary_id_type> ids; 00847 00848 // Only level-0 elements store BCs. If this is not a level-0 00849 // element get its level-0 parent and infer the BCs. 00850 const Elem* searched_elem = elem; 00851 #ifdef LIBMESH_ENABLE_AMR 00852 if (elem->level() != 0) 00853 { 00854 // Find all the sides that contain edge. If one of those is a boundary 00855 // side, then this must be a boundary edge. In that case, we just use the 00856 // top-level parent. 00857 bool found_boundary_edge = false; 00858 for(unsigned int side=0; side<elem->n_sides(); side++) 00859 { 00860 if(elem->is_edge_on_side(edge,side)) 00861 { 00862 if (elem->neighbor(side) == NULL) 00863 { 00864 searched_elem = elem->top_parent (); 00865 found_boundary_edge = true; 00866 break; 00867 } 00868 } 00869 } 00870 00871 if(!found_boundary_edge) 00872 { 00873 // Child element is not on external edge, but it may have internal 00874 // "boundary" IDs. We will walk up the tree, at each level checking that 00875 // the current child is actually on the same edge of the parent that is 00876 // currently being searched for (i.e. that was passed in as "edge"). 00877 while (searched_elem->parent() != NULL) 00878 { 00879 const Elem * parent = searched_elem->parent(); 00880 if (parent->is_child_on_edge(parent->which_child_am_i(searched_elem), edge) == false) 00881 return ids; 00882 searched_elem = parent; 00883 } 00884 } 00885 } 00886 #endif 00887 00888 std::pair<std::multimap<const Elem*, 00889 std::pair<unsigned short int, boundary_id_type> >::const_iterator, 00890 std::multimap<const Elem*, 00891 std::pair<unsigned short int, boundary_id_type> >::const_iterator > 00892 e = _boundary_edge_id.equal_range(searched_elem); 00893 00894 // elem not in the data structure 00895 if (e.first == e.second) 00896 return ids; 00897 00898 // elem is there, maybe multiple occurrences 00899 for (; e.first != e.second; ++e.first) 00900 // if this is true we found the requested edge of the element 00901 if (e.first->second.first == edge) 00902 ids.push_back(e.first->second.second); 00903 00904 // Whether or not we found anything, return "ids". If it's empty, it 00905 // means no valid bounary IDs were found for "edge" 00906 return ids; 00907 } 00908 00909 00910 00911 unsigned int BoundaryInfo::n_edge_boundary_ids (const Elem* const elem, 00912 const unsigned short int edge) const 00913 { 00914 libmesh_assert(elem); 00915 00916 // Only level-0 elements store BCs. If this is not a level-0 00917 // element get its level-0 parent and infer the BCs. 00918 const Elem* searched_elem = elem; 00919 #ifdef LIBMESH_ENABLE_AMR 00920 if (elem->level() != 0) 00921 { 00922 // Find all the sides that contain edge. If one of those is a boundary 00923 // side, then this must be a boundary edge. In that case, we just use the 00924 // top-level parent. 00925 bool found_boundary_edge = false; 00926 for(unsigned int side=0; side<elem->n_sides(); side++) 00927 { 00928 if(elem->is_edge_on_side(edge,side)) 00929 { 00930 if (elem->neighbor(side) == NULL) 00931 { 00932 searched_elem = elem->top_parent (); 00933 found_boundary_edge = true; 00934 break; 00935 } 00936 } 00937 } 00938 00939 if(!found_boundary_edge) 00940 { 00941 // Child element is not on external edge, but it may have internal 00942 // "boundary" IDs. We will walk up the tree, at each level checking that 00943 // the current child is actually on the same edge of the parent that is 00944 // currently being searched for (i.e. that was passed in as "edge"). 00945 while (searched_elem->parent() != NULL) 00946 { 00947 const Elem * parent = searched_elem->parent(); 00948 if (parent->is_child_on_edge(parent->which_child_am_i(searched_elem), edge) == false) 00949 return 0; 00950 searched_elem = parent; 00951 } 00952 } 00953 } 00954 #endif 00955 00956 std::pair<std::multimap<const Elem*, 00957 std::pair<unsigned short int, boundary_id_type> >::const_iterator, 00958 std::multimap<const Elem*, 00959 std::pair<unsigned short int, boundary_id_type> >::const_iterator > 00960 e = _boundary_edge_id.equal_range(searched_elem); 00961 00962 unsigned int n_ids = 0; 00963 00964 // elem is there, maybe multiple occurrences 00965 for (; e.first != e.second; ++e.first) 00966 // if this is true we found the requested edge of the element 00967 if (e.first->second.first == edge) 00968 n_ids++; 00969 00970 return n_ids; 00971 } 00972 00973 00974 00975 std::vector<boundary_id_type> BoundaryInfo::raw_edge_boundary_ids (const Elem* const elem, 00976 const unsigned short int edge) const 00977 { 00978 libmesh_assert(elem); 00979 00980 std::vector<boundary_id_type> ids; 00981 00982 // Only level-0 elements store BCs. 00983 if (elem->parent()) 00984 return ids; 00985 00986 std::pair<std::multimap<const Elem*, 00987 std::pair<unsigned short int, boundary_id_type> >::const_iterator, 00988 std::multimap<const Elem*, 00989 std::pair<unsigned short int, boundary_id_type> >::const_iterator > 00990 e = _boundary_edge_id.equal_range(elem); 00991 00992 // Check any occurrences 00993 for (; e.first != e.second; ++e.first) 00994 // if this is true we found the requested edge of the element 00995 if (e.first->second.first == edge) 00996 ids.push_back(e.first->second.second); 00997 00998 // if nothing got pushed back, we didn't find elem in the data 00999 // structure with the requested edge, so return the default empty 01000 // vector 01001 return ids; 01002 } 01003 01004 01005 boundary_id_type BoundaryInfo::boundary_id(const Elem* const elem, 01006 const unsigned short int side) const 01007 { 01008 // Asking for just one boundary id means your code isn't safe to use 01009 // on meshes with overlapping boundary ids. Try using 01010 // BoundaryInfo::boundary_ids or BoundaryInfo::has_boundary_id 01011 // instead. 01012 libmesh_deprecated(); 01013 01014 libmesh_assert(elem); 01015 01016 // Only level-0 elements store BCs. If this is not a level-0 01017 // element, one of its parent elements may have either internal 01018 // or external boundary IDs. We find that parent now. 01019 const Elem* searched_elem = elem; 01020 if (elem->level() != 0) 01021 { 01022 // Child element on external side: the top_parent will have the BCs 01023 if (elem->neighbor(side) == NULL) 01024 searched_elem = elem->top_parent (); 01025 01026 #ifdef LIBMESH_ENABLE_AMR 01027 // Child element is not on external side, but it may have internal 01028 // "boundary" IDs. We will walk up the tree, at each level checking that 01029 // the current child is actually on the same side of the parent that is 01030 // currently being searched for (i.e. that was passed in as "side"). 01031 else 01032 while (searched_elem->parent() != NULL) 01033 { 01034 const Elem * parent = searched_elem->parent(); 01035 if (parent->is_child_on_side(parent->which_child_am_i(searched_elem), side) == false) 01036 return invalid_id; 01037 searched_elem = parent; 01038 } 01039 #endif 01040 } 01041 01042 std::pair<std::multimap<const Elem*, 01043 std::pair<unsigned short int, boundary_id_type> >::const_iterator, 01044 std::multimap<const Elem*, 01045 std::pair<unsigned short int, boundary_id_type> >::const_iterator > 01046 e = _boundary_side_id.equal_range(searched_elem); 01047 01048 // elem not in the data structure 01049 if (e.first == e.second) 01050 return invalid_id; 01051 01052 // elem is there, maybe multiple occurrences 01053 for (; e.first != e.second; ++e.first) 01054 // if this is true we found the requested side 01055 // of the element and want to return the id 01056 if (e.first->second.first == side) 01057 return e.first->second.second; 01058 01059 // if we get here, we found elem in the data structure but not 01060 // the requested side, so return the default value 01061 return invalid_id; 01062 } 01063 01064 01065 01066 bool BoundaryInfo::has_boundary_id(const Elem* const elem, 01067 const unsigned short int side, 01068 const boundary_id_type id) const 01069 { 01070 libmesh_assert(elem); 01071 01072 // Only level-0 elements store BCs. If this is not a level-0 01073 // element get its level-0 parent and infer the BCs. 01074 const Elem* searched_elem = elem; 01075 if (elem->level() != 0) 01076 { 01077 if (elem->neighbor(side) == NULL) 01078 searched_elem = elem->top_parent (); 01079 #ifdef LIBMESH_ENABLE_AMR 01080 else 01081 while (searched_elem->parent() != NULL) 01082 { 01083 const Elem * parent = searched_elem->parent(); 01084 if (parent->is_child_on_side(parent->which_child_am_i(searched_elem), side) == false) 01085 return false; 01086 searched_elem = parent; 01087 } 01088 #endif 01089 } 01090 01091 std::pair<std::multimap<const Elem*, 01092 std::pair<unsigned short int, boundary_id_type> >::const_iterator, 01093 std::multimap<const Elem*, 01094 std::pair<unsigned short int, boundary_id_type> >::const_iterator > 01095 e = _boundary_side_id.equal_range(searched_elem); 01096 01097 // elem is there, maybe multiple occurrences 01098 for (; e.first != e.second; ++e.first) 01099 // if this is true we found the requested id on this side of the element 01100 if (e.first->second.first == side && 01101 e.first->second.second == id) 01102 return true; 01103 01104 return false; 01105 } 01106 01107 01108 01109 std::vector<boundary_id_type> BoundaryInfo::boundary_ids (const Elem* const elem, 01110 const unsigned short int side) const 01111 { 01112 libmesh_assert(elem); 01113 01114 std::vector<boundary_id_type> ids; 01115 01116 // Only level-0 elements store BCs. If this is not a level-0 01117 // element get its level-0 parent and infer the BCs. 01118 const Elem* searched_elem = elem; 01119 if (elem->level() != 0) 01120 { 01121 if (elem->neighbor(side) == NULL) 01122 searched_elem = elem->top_parent (); 01123 #ifdef LIBMESH_ENABLE_AMR 01124 else 01125 while (searched_elem->parent() != NULL) 01126 { 01127 const Elem * parent = searched_elem->parent(); 01128 if (parent->is_child_on_side(parent->which_child_am_i(searched_elem), side) == false) 01129 return ids; 01130 searched_elem = parent; 01131 } 01132 #endif 01133 } 01134 01135 std::pair<std::multimap<const Elem*, 01136 std::pair<unsigned short int, boundary_id_type> >::const_iterator, 01137 std::multimap<const Elem*, 01138 std::pair<unsigned short int, boundary_id_type> >::const_iterator > 01139 e = _boundary_side_id.equal_range(searched_elem); 01140 01141 // elem not in the data structure 01142 if (e.first == e.second) 01143 return ids; 01144 01145 // elem is there, maybe multiple occurrences 01146 for (; e.first != e.second; ++e.first) 01147 // if this is true we found the requested side of the element 01148 if (e.first->second.first == side) 01149 ids.push_back(e.first->second.second); 01150 01151 // Whether or not we found anything, return "ids". If it's empty, it 01152 // means no valid bounary IDs were found for "side" 01153 return ids; 01154 } 01155 01156 01157 01158 unsigned int BoundaryInfo::n_boundary_ids (const Elem* const elem, 01159 const unsigned short int side) const 01160 { 01161 libmesh_assert(elem); 01162 01163 // Only level-0 elements store BCs. If this is not a level-0 01164 // element get its level-0 parent and infer the BCs. 01165 const Elem* searched_elem = elem; 01166 if (elem->level() != 0) 01167 { 01168 if (elem->neighbor(side) == NULL) 01169 searched_elem = elem->top_parent (); 01170 #ifdef LIBMESH_ENABLE_AMR 01171 else 01172 while (searched_elem->parent() != NULL) 01173 { 01174 const Elem * parent = searched_elem->parent(); 01175 if (parent->is_child_on_side(parent->which_child_am_i(searched_elem), side) == false) 01176 return 0; 01177 searched_elem = parent; 01178 } 01179 #endif 01180 } 01181 01182 std::pair<std::multimap<const Elem*, 01183 std::pair<unsigned short int, boundary_id_type> >::const_iterator, 01184 std::multimap<const Elem*, 01185 std::pair<unsigned short int, boundary_id_type> >::const_iterator > 01186 e = _boundary_side_id.equal_range(searched_elem); 01187 01188 unsigned int n_ids = 0; 01189 01190 // elem is there, maybe multiple occurrences 01191 for (; e.first != e.second; ++e.first) 01192 // if this is true we found the requested side of the element 01193 if (e.first->second.first == side) 01194 n_ids++; 01195 01196 return n_ids; 01197 } 01198 01199 01200 01201 std::vector<boundary_id_type> BoundaryInfo::raw_boundary_ids (const Elem* const elem, 01202 const unsigned short int side) const 01203 { 01204 libmesh_assert(elem); 01205 01206 std::vector<boundary_id_type> ids; 01207 01208 // Only level-0 elements store BCs. 01209 if (elem->parent()) 01210 return ids; 01211 01212 std::pair<std::multimap<const Elem*, 01213 std::pair<unsigned short int, boundary_id_type> >::const_iterator, 01214 std::multimap<const Elem*, 01215 std::pair<unsigned short int, boundary_id_type> >::const_iterator > 01216 e = _boundary_side_id.equal_range(elem); 01217 01218 // Check any occurrences 01219 for (; e.first != e.second; ++e.first) 01220 // if this is true we found the requested side of the element 01221 if (e.first->second.first == side) 01222 ids.push_back(e.first->second.second); 01223 01224 // if nothing got pushed back, we didn't find elem in the data 01225 // structure with the requested side, so return the default empty 01226 // vector 01227 return ids; 01228 } 01229 01230 01231 void BoundaryInfo::remove_edge (const Elem* elem, 01232 const unsigned short int edge) 01233 { 01234 libmesh_assert(elem); 01235 01236 // The user shouldn't be trying to remove only one child's boundary 01237 // id 01238 libmesh_assert_equal_to (elem->level(), 0); 01239 01240 std::pair<std::multimap<const Elem*, 01241 std::pair<unsigned short int, boundary_id_type> >::iterator, 01242 std::multimap<const Elem*, 01243 std::pair<unsigned short int, boundary_id_type> >::iterator > 01244 e = _boundary_edge_id.equal_range(elem); 01245 01246 // elem may be there, maybe multiple occurrences 01247 while (e.first != e.second) 01248 { 01249 // if this is true we found the requested edge 01250 // of the element and want to erase the id 01251 if (e.first->second.first == edge) 01252 { 01253 // (postfix++ - increment the iterator before it's invalid) 01254 _boundary_edge_id.erase(e.first++); 01255 } 01256 else 01257 ++e.first; 01258 } 01259 } 01260 01261 01262 01263 void BoundaryInfo::remove_edge (const Elem* elem, 01264 const unsigned short int edge, 01265 const boundary_id_type id) 01266 { 01267 libmesh_assert(elem); 01268 01269 // The user shouldn't be trying to remove only one child's boundary 01270 // id 01271 libmesh_assert_equal_to (elem->level(), 0); 01272 01273 std::pair<std::multimap<const Elem*, 01274 std::pair<unsigned short int, boundary_id_type> >::iterator, 01275 std::multimap<const Elem*, 01276 std::pair<unsigned short int, boundary_id_type> >::iterator > 01277 e = _boundary_edge_id.equal_range(elem); 01278 01279 // elem may be there, maybe multiple occurrences 01280 while (e.first != e.second) 01281 { 01282 // if this is true we found the requested edge 01283 // of the element and want to erase the requested id 01284 if (e.first->second.first == edge && 01285 e.first->second.second == id) 01286 { 01287 // (postfix++ - increment the iterator before it's invalid) 01288 _boundary_edge_id.erase(e.first++); 01289 } 01290 else 01291 ++e.first; 01292 } 01293 } 01294 01295 void BoundaryInfo::remove_side (const Elem* elem, 01296 const unsigned short int side) 01297 { 01298 libmesh_assert(elem); 01299 01300 // The user shouldn't be trying to remove only one child's boundary 01301 // id 01302 libmesh_assert_equal_to (elem->level(), 0); 01303 01304 std::pair<std::multimap<const Elem*, 01305 std::pair<unsigned short int, boundary_id_type> >::iterator, 01306 std::multimap<const Elem*, 01307 std::pair<unsigned short int, boundary_id_type> >::iterator > 01308 e = _boundary_side_id.equal_range(elem); 01309 01310 // elem may be there, maybe multiple occurrences 01311 while (e.first != e.second) 01312 { 01313 // if this is true we found the requested side 01314 // of the element and want to erase the id 01315 if (e.first->second.first == side) 01316 { 01317 // (postfix++ - increment the iterator before it's invalid) 01318 _boundary_side_id.erase(e.first++); 01319 } 01320 else 01321 ++e.first; 01322 } 01323 } 01324 01325 01326 01327 void BoundaryInfo::remove_side (const Elem* elem, 01328 const unsigned short int side, 01329 const boundary_id_type id) 01330 { 01331 libmesh_assert(elem); 01332 01333 // The user shouldn't be trying to remove only one child's boundary 01334 // id 01335 libmesh_assert_equal_to (elem->level(), 0); 01336 01337 std::pair<std::multimap<const Elem*, 01338 std::pair<unsigned short int, boundary_id_type> >::iterator, 01339 std::multimap<const Elem*, 01340 std::pair<unsigned short int, boundary_id_type> >::iterator > 01341 e = _boundary_side_id.equal_range(elem); 01342 01343 // elem may be there, maybe multiple occurrences 01344 while (e.first != e.second) 01345 { 01346 // if this is true we found the requested side 01347 // of the element and want to erase the requested id 01348 if (e.first->second.first == side && 01349 e.first->second.second == id) 01350 { 01351 // (postfix++ - increment the iterator before it's invalid) 01352 _boundary_side_id.erase(e.first++); 01353 } 01354 else 01355 ++e.first; 01356 } 01357 } 01358 01359 01360 01361 unsigned int BoundaryInfo::side_with_boundary_id(const Elem* const elem, 01362 const boundary_id_type boundary_id_in) const 01363 { 01364 const Elem* searched_elem = elem; 01365 if (elem->level() != 0) 01366 searched_elem = elem->top_parent(); 01367 01368 std::pair<std::multimap<const Elem*, 01369 std::pair<unsigned short int, boundary_id_type> >::const_iterator, 01370 std::multimap<const Elem*, 01371 std::pair<unsigned short int, boundary_id_type> >::const_iterator > 01372 e = _boundary_side_id.equal_range(searched_elem); 01373 01374 // elem may have zero or multiple occurrences 01375 for (; e.first != e.second; ++e.first) 01376 { 01377 // if this is true we found the requested boundary_id 01378 // of the element and want to return the side 01379 if (e.first->second.second == boundary_id_in) 01380 { 01381 unsigned int side = e.first->second.first; 01382 01383 // If we're on this external boundary then we share this 01384 // external boundary id 01385 if (elem->neighbor(side) == NULL) 01386 return side; 01387 01388 // If we're on an internal boundary then we need to be sure 01389 // it's the same internal boundary as our top_parent 01390 const Elem *p = elem; 01391 01392 #ifdef LIBMESH_ENABLE_AMR 01393 01394 while (p != NULL) 01395 { 01396 const Elem *parent = p->parent(); 01397 if (!parent->is_child_on_side(parent->which_child_am_i(p), side)) 01398 break; 01399 p = parent; 01400 } 01401 #endif 01402 // We're on that side of our top_parent; return it 01403 if (!p) 01404 return side; 01405 } 01406 } 01407 01408 // if we get here, we found elem in the data structure but not 01409 // the requested boundary id, so return the default value 01410 return libMesh::invalid_uint; 01411 } 01412 01413 void 01414 BoundaryInfo::build_node_boundary_ids(std::vector<boundary_id_type> &b_ids) const 01415 { 01416 b_ids.clear(); 01417 01418 std::multimap<const Node*, boundary_id_type>::const_iterator pos 01419 = _boundary_node_id.begin(); 01420 01421 for (; pos != _boundary_node_id.end(); ++pos) 01422 { 01423 boundary_id_type id = pos->second; 01424 01425 if(std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end()) 01426 b_ids.push_back(id); 01427 } 01428 } 01429 01430 void 01431 BoundaryInfo::build_side_boundary_ids(std::vector<boundary_id_type> &b_ids) const 01432 { 01433 b_ids.clear(); 01434 01435 std::multimap<const Elem*, std::pair<unsigned short int, boundary_id_type> >::const_iterator pos 01436 = _boundary_side_id.begin(); 01437 01438 for (; pos != _boundary_side_id.end(); ++pos) 01439 { 01440 boundary_id_type id = pos->second.second; 01441 01442 if(std::find(b_ids.begin(),b_ids.end(),id) == b_ids.end()) 01443 b_ids.push_back(id); 01444 } 01445 } 01446 01447 std::size_t BoundaryInfo::n_boundary_conds () const 01448 { 01449 // in serial we know the number of bcs from the 01450 // size of the container 01451 if (_mesh.is_serial()) 01452 return _boundary_side_id.size(); 01453 01454 // in parallel we need to sum the number of local bcs 01455 parallel_object_only(); 01456 01457 std::size_t nbcs=0; 01458 01459 std::multimap<const Elem*, 01460 std::pair<unsigned short int, 01461 boundary_id_type> >::const_iterator pos; 01462 01463 for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end(); ++pos) 01464 if (pos->first->processor_id() == this->processor_id()) 01465 nbcs++; 01466 01467 this->comm().sum (nbcs); 01468 01469 return nbcs; 01470 } 01471 01472 std::size_t BoundaryInfo::n_edge_conds () const 01473 { 01474 // in serial we know the number of nodesets from the 01475 // size of the container 01476 if (_mesh.is_serial()) 01477 return _boundary_edge_id.size(); 01478 01479 // in parallel we need to sum the number of local nodesets 01480 parallel_object_only(); 01481 01482 std::size_t n_edge_bcs=0; 01483 01484 std::multimap<const Elem*, 01485 std::pair<unsigned short int, 01486 boundary_id_type> >::const_iterator pos; 01487 01488 for (pos=_boundary_edge_id.begin(); pos != _boundary_edge_id.end(); ++pos) 01489 if (pos->first->processor_id() == this->processor_id()) 01490 n_edge_bcs++; 01491 01492 this->comm().sum (n_edge_bcs); 01493 01494 return n_edge_bcs; 01495 } 01496 01497 01498 std::size_t BoundaryInfo::n_nodeset_conds () const 01499 { 01500 // in serial we know the number of nodesets from the 01501 // size of the container 01502 if (_mesh.is_serial()) 01503 return _boundary_node_id.size(); 01504 01505 // in parallel we need to sum the number of local nodesets 01506 parallel_object_only(); 01507 01508 std::size_t n_nodesets=0; 01509 01510 std::multimap<const Node*, boundary_id_type>::const_iterator pos; 01511 01512 for (pos=_boundary_node_id.begin(); pos != _boundary_node_id.end(); ++pos) 01513 if (pos->first->processor_id() == this->processor_id()) 01514 n_nodesets++; 01515 01516 this->comm().sum (n_nodesets); 01517 01518 return n_nodesets; 01519 } 01520 01521 01522 01523 void BoundaryInfo::build_node_list (std::vector<dof_id_type>& nl, 01524 std::vector<boundary_id_type>& il) const 01525 { 01526 // Reserve the size, then use push_back 01527 nl.reserve (_boundary_node_id.size()); 01528 il.reserve (_boundary_node_id.size()); 01529 01530 std::multimap<const Node*, boundary_id_type>::const_iterator pos 01531 = _boundary_node_id.begin(); 01532 01533 for (; pos != _boundary_node_id.end(); ++pos) 01534 { 01535 nl.push_back (pos->first->id()); 01536 il.push_back (pos->second); 01537 } 01538 } 01539 01540 01541 void 01542 BoundaryInfo::build_node_list_from_side_list() 01543 { 01544 std::multimap<const Elem*, 01545 std::pair<unsigned short int, 01546 boundary_id_type> >::const_iterator pos; 01547 01548 //Loop over the side list 01549 for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end(); ++pos) 01550 { 01551 // Don't add remote sides 01552 if(pos->first->is_remote()) 01553 continue; 01554 01555 //Need to loop over the sides of any possible children 01556 std::vector< const Elem * > family; 01557 #ifdef LIBMESH_ENABLE_AMR 01558 pos->first->active_family_tree_by_side (family, pos->second.first); 01559 #else 01560 family.push_back(pos->first); 01561 #endif 01562 01563 for(std::size_t elem_it=0; elem_it < family.size(); elem_it++) 01564 { 01565 const Elem * cur_elem = family[elem_it]; 01566 01567 UniquePtr<Elem> side = cur_elem->build_side(pos->second.first); 01568 01569 //Add each node node on the side with the side's boundary id 01570 for(unsigned int i=0; i<side->n_nodes(); i++) 01571 { 01572 Node * node = side->get_node(i); 01573 01574 this->add_node(node, pos->second.second); 01575 } 01576 } 01577 } 01578 } 01579 01580 01581 01582 01583 void BoundaryInfo::build_side_list_from_node_list() 01584 { 01585 // Check for early return 01586 if (_boundary_node_id.empty()) 01587 { 01588 libMesh::out << "No boundary node IDs have been added: cannot build side list!" << std::endl; 01589 return; 01590 } 01591 01592 // typedef for less typing! 01593 typedef std::multimap<const Node*, boundary_id_type>::const_iterator iterator_t; 01594 01595 // Return value and iterator for equal_range() 01596 iterator_t pos; 01597 std::pair<iterator_t, iterator_t> range; 01598 01599 MeshBase::const_element_iterator el = _mesh.active_elements_begin(); 01600 const MeshBase::const_element_iterator end_el = _mesh.active_elements_end(); 01601 01602 for (; el != end_el; ++el) 01603 { 01604 const Elem* elem = *el; 01605 01606 for (unsigned short side=0; side<elem->n_sides(); ++side) 01607 { 01608 UniquePtr<Elem> side_elem = elem->build_side(side); 01609 01610 // map from nodeset_id to count for that ID 01611 std::map<boundary_id_type, unsigned> nodesets_node_count; 01612 for (unsigned node_num=0; node_num < side_elem->n_nodes(); ++node_num) 01613 { 01614 Node* node = side_elem->get_node(node_num); 01615 range = _boundary_node_id.equal_range(node); 01616 01617 // For each nodeset that this node is a member of, increment the associated 01618 // nodeset ID count 01619 for (pos = range.first; pos != range.second; ++pos) 01620 nodesets_node_count[pos->second]++; 01621 } 01622 01623 // Now check to see what nodeset_counts have the correct 01624 // number of nodes in them. For any that do, add this side to 01625 // the sideset, making sure the sideset inherits the 01626 // nodeset's name, if there is one. 01627 std::map<boundary_id_type, unsigned>::const_iterator nodesets = nodesets_node_count.begin(); 01628 for (; nodesets != nodesets_node_count.end(); ++nodesets) 01629 if (nodesets->second == side_elem->n_nodes()) 01630 { 01631 add_side(elem, side, nodesets->first); 01632 01633 // Let the sideset inherit any non-empty name from the nodeset 01634 std::string& nset_name = nodeset_name(nodesets->first); 01635 01636 if (nset_name != "") 01637 sideset_name(nodesets->first) = nset_name; 01638 } 01639 } // end for side 01640 } // end for el 01641 } 01642 01643 01644 01645 01646 void BoundaryInfo::build_side_list (std::vector<dof_id_type>& el, 01647 std::vector<unsigned short int>& sl, 01648 std::vector<boundary_id_type>& il) const 01649 { 01650 // Reserve the size, then use push_back 01651 el.reserve (_boundary_side_id.size()); 01652 sl.reserve (_boundary_side_id.size()); 01653 il.reserve (_boundary_side_id.size()); 01654 01655 std::multimap<const Elem*, 01656 std::pair<unsigned short int, 01657 boundary_id_type> >::const_iterator pos; 01658 01659 for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end(); 01660 ++pos) 01661 { 01662 el.push_back (pos->first->id()); 01663 sl.push_back (pos->second.first); 01664 il.push_back (pos->second.second); 01665 } 01666 } 01667 01668 void BoundaryInfo::build_active_side_list (std::vector<dof_id_type>& el, 01669 std::vector<unsigned short int>& sl, 01670 std::vector<boundary_id_type>& il) const 01671 { 01672 std::multimap<const Elem*, 01673 std::pair<unsigned short int, 01674 boundary_id_type> >::const_iterator pos; 01675 01676 for (pos=_boundary_side_id.begin(); pos != _boundary_side_id.end(); 01677 ++pos) 01678 { 01679 // Don't add remote sides 01680 if (pos->first->is_remote()) 01681 continue; 01682 01683 // Loop over the sides of possible children 01684 std::vector< const Elem * > family; 01685 #ifdef LIBMESH_ENABLE_AMR 01686 pos->first->active_family_tree_by_side(family, pos->second.first); 01687 #else 01688 family.push_back(pos->first); 01689 #endif 01690 01691 // Populate the list items 01692 for (std::vector<const Elem *>::iterator elem_it = family.begin(); elem_it != family.end(); elem_it++) 01693 { 01694 el.push_back ((*elem_it)->id()); 01695 sl.push_back (pos->second.first); 01696 il.push_back (pos->second.second); 01697 } 01698 } 01699 } 01700 01701 01702 void BoundaryInfo::build_edge_list (std::vector<dof_id_type>& el, 01703 std::vector<unsigned short int>& sl, 01704 std::vector<boundary_id_type>& il) const 01705 { 01706 // Reserve the size, then use push_back 01707 el.reserve (_boundary_side_id.size()); 01708 sl.reserve (_boundary_side_id.size()); 01709 il.reserve (_boundary_side_id.size()); 01710 01711 std::multimap<const Elem*, 01712 std::pair<unsigned short int, 01713 boundary_id_type> >::const_iterator pos; 01714 01715 for (pos=_boundary_edge_id.begin(); pos != _boundary_edge_id.end(); 01716 ++pos) 01717 { 01718 el.push_back (pos->first->id()); 01719 sl.push_back (pos->second.first); 01720 il.push_back (pos->second.second); 01721 } 01722 } 01723 01724 01725 void BoundaryInfo::print_info(std::ostream& out_stream) const 01726 { 01727 // Print out the nodal BCs 01728 if (!_boundary_node_id.empty()) 01729 { 01730 out_stream << "Nodal Boundary conditions:" << std::endl 01731 << "--------------------------" << std::endl 01732 << " (Node No., ID) " << std::endl; 01733 01734 // std::for_each(_boundary_node_id.begin(), 01735 // _boundary_node_id.end(), 01736 // PrintNodeInfo()); 01737 01738 std::multimap<const Node*, boundary_id_type>::const_iterator it = _boundary_node_id.begin(); 01739 const std::multimap<const Node*, boundary_id_type>::const_iterator end = _boundary_node_id.end(); 01740 01741 for (; it != end; ++it) 01742 out_stream << " (" << (*it).first->id() 01743 << ", " << (*it).second 01744 << ")" << std::endl; 01745 } 01746 01747 // Print out the element edge BCs 01748 if (!_boundary_edge_id.empty()) 01749 { 01750 out_stream << std::endl 01751 << "Edge Boundary conditions:" << std::endl 01752 << "-------------------------" << std::endl 01753 << " (Elem No., Edge No., ID) " << std::endl; 01754 01755 // std::for_each(_boundary_edge_id.begin(), 01756 // _boundary_edge_id.end(), 01757 // PrintSideInfo()); 01758 01759 std::multimap<const Elem*, 01760 std::pair<unsigned short int, boundary_id_type> >::const_iterator it = _boundary_edge_id.begin(); 01761 const std::multimap<const Elem*, 01762 std::pair<unsigned short int, boundary_id_type> >::const_iterator end = _boundary_edge_id.end(); 01763 01764 for (; it != end; ++it) 01765 out_stream << " (" << (*it).first->id() 01766 << ", " << (*it).second.first 01767 << ", " << (*it).second.second 01768 << ")" << std::endl; 01769 } 01770 01771 // Print out the element side BCs 01772 if (!_boundary_side_id.empty()) 01773 { 01774 out_stream << std::endl 01775 << "Side Boundary conditions:" << std::endl 01776 << "-------------------------" << std::endl 01777 << " (Elem No., Side No., ID) " << std::endl; 01778 01779 // std::for_each(_boundary_side_id.begin(), 01780 // _boundary_side_id.end(), 01781 // PrintSideInfo()); 01782 01783 std::multimap<const Elem*, 01784 std::pair<unsigned short int, boundary_id_type> >::const_iterator it = _boundary_side_id.begin(); 01785 const std::multimap<const Elem*, 01786 std::pair<unsigned short int, boundary_id_type> >::const_iterator end = _boundary_side_id.end(); 01787 01788 for (; it != end; ++it) 01789 out_stream << " (" << (*it).first->id() 01790 << ", " << (*it).second.first 01791 << ", " << (*it).second.second 01792 << ")" << std::endl; 01793 } 01794 } 01795 01796 01797 01798 void BoundaryInfo::print_summary(std::ostream& out_stream) const 01799 { 01800 // Print out the nodal BCs 01801 if (!_boundary_node_id.empty()) 01802 { 01803 out_stream << "Nodal Boundary conditions:" << std::endl 01804 << "--------------------------" << std::endl 01805 << " (ID, number of nodes) " << std::endl; 01806 01807 std::map<boundary_id_type, std::size_t> ID_counts; 01808 01809 std::multimap<const Node*, boundary_id_type>::const_iterator it = _boundary_node_id.begin(); 01810 const std::multimap<const Node*, boundary_id_type>::const_iterator end = _boundary_node_id.end(); 01811 01812 for (; it != end; ++it) 01813 ID_counts[(*it).second]++; 01814 01815 std::map<boundary_id_type, std::size_t>::const_iterator ID_it = ID_counts.begin(); 01816 const std::map<boundary_id_type, std::size_t>::const_iterator ID_end = ID_counts.end(); 01817 01818 for (; ID_it != ID_end; ++ID_it) 01819 out_stream << " (" << (*ID_it).first 01820 << ", " << (*ID_it).second 01821 << ")" << std::endl; 01822 } 01823 01824 // Print out the element edge BCs 01825 if (!_boundary_edge_id.empty()) 01826 { 01827 out_stream << std::endl 01828 << "Edge Boundary conditions:" << std::endl 01829 << "-------------------------" << std::endl 01830 << " (ID, number of edges) " << std::endl; 01831 01832 std::map<boundary_id_type, std::size_t> ID_counts; 01833 01834 std::multimap<const Elem*, 01835 std::pair<unsigned short int, boundary_id_type> >::const_iterator it = _boundary_edge_id.begin(); 01836 const std::multimap<const Elem*, 01837 std::pair<unsigned short int, boundary_id_type> >::const_iterator end = _boundary_edge_id.end(); 01838 01839 for (; it != end; ++it) 01840 ID_counts[(*it).second.second]++; 01841 01842 std::map<boundary_id_type, std::size_t>::const_iterator ID_it = ID_counts.begin(); 01843 const std::map<boundary_id_type, std::size_t>::const_iterator ID_end = ID_counts.end(); 01844 01845 for (; ID_it != ID_end; ++ID_it) 01846 out_stream << " (" << (*ID_it).first 01847 << ", " << (*ID_it).second 01848 << ")" << std::endl; 01849 } 01850 01851 // Print out the element side BCs 01852 if (!_boundary_side_id.empty()) 01853 { 01854 out_stream << std::endl 01855 << "Side Boundary conditions:" << std::endl 01856 << "-------------------------" << std::endl 01857 << " (ID, number of sides) " << std::endl; 01858 01859 std::map<boundary_id_type, std::size_t> ID_counts; 01860 01861 std::multimap<const Elem*, 01862 std::pair<unsigned short int, boundary_id_type> >::const_iterator it = _boundary_side_id.begin(); 01863 const std::multimap<const Elem*, 01864 std::pair<unsigned short int, boundary_id_type> >::const_iterator end = _boundary_side_id.end(); 01865 01866 for (; it != end; ++it) 01867 ID_counts[(*it).second.second]++; 01868 01869 std::map<boundary_id_type, std::size_t>::const_iterator ID_it = ID_counts.begin(); 01870 const std::map<boundary_id_type, std::size_t>::const_iterator ID_end = ID_counts.end(); 01871 01872 for (; ID_it != ID_end; ++ID_it) 01873 out_stream << " (" << (*ID_it).first 01874 << ", " << (*ID_it).second 01875 << ")" << std::endl; 01876 } 01877 } 01878 01879 01880 const std::string& BoundaryInfo::get_sideset_name(boundary_id_type id) const 01881 { 01882 static const std::string empty_string; 01883 std::map<boundary_id_type, std::string>::const_iterator it = 01884 _ss_id_to_name.find(id); 01885 if (it == _ss_id_to_name.end()) 01886 return empty_string; 01887 else 01888 return it->second; 01889 } 01890 01891 01892 std::string& BoundaryInfo::sideset_name(boundary_id_type id) 01893 { 01894 return _ss_id_to_name[id]; 01895 } 01896 01897 const std::string& BoundaryInfo::get_nodeset_name(boundary_id_type id) const 01898 { 01899 static const std::string empty_string; 01900 std::map<boundary_id_type, std::string>::const_iterator it = 01901 _ns_id_to_name.find(id); 01902 if (it == _ns_id_to_name.end()) 01903 return empty_string; 01904 else 01905 return it->second; 01906 } 01907 01908 std::string& BoundaryInfo::nodeset_name(boundary_id_type id) 01909 { 01910 return _ns_id_to_name[id]; 01911 } 01912 01913 boundary_id_type BoundaryInfo::get_id_by_name(const std::string& name) const 01914 { 01915 // Search sidesets 01916 std::map<boundary_id_type, std::string>::const_iterator 01917 iter = _ss_id_to_name.begin(), 01918 end_iter = _ss_id_to_name.end(); 01919 01920 for (; iter != end_iter; ++iter) 01921 if (iter->second == name) 01922 return iter->first; 01923 01924 // Search nodesets 01925 iter = _ns_id_to_name.begin(); 01926 end_iter = _ns_id_to_name.end(); 01927 for (; iter != end_iter; ++iter) 01928 if (iter->second == name) 01929 return iter->first; 01930 01931 // If we made it here without returning, we don't have a sideset or 01932 // nodeset by the requested name, so return invalid_id 01933 return invalid_id; 01934 } 01935 01936 } // namespace libMesh