$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 <algorithm> // for std::sort 00022 #include <iterator> // for std::ostream_iterator 00023 #include <sstream> 00024 #include <limits> // for std::numeric_limits<> 00025 #include <cmath> // for std::sqrt() 00026 00027 // Local includes 00028 #include "libmesh/elem.h" 00029 #include "libmesh/fe_type.h" 00030 #include "libmesh/fe_interface.h" 00031 #include "libmesh/node_elem.h" 00032 #include "libmesh/edge_edge2.h" 00033 #include "libmesh/edge_edge3.h" 00034 #include "libmesh/edge_edge4.h" 00035 #include "libmesh/edge_inf_edge2.h" 00036 #include "libmesh/face_tri3.h" 00037 #include "libmesh/face_tri3_subdivision.h" 00038 #include "libmesh/face_tri6.h" 00039 #include "libmesh/face_quad4.h" 00040 #include "libmesh/face_quad8.h" 00041 #include "libmesh/face_quad9.h" 00042 #include "libmesh/face_inf_quad4.h" 00043 #include "libmesh/face_inf_quad6.h" 00044 #include "libmesh/cell_tet4.h" 00045 #include "libmesh/cell_tet10.h" 00046 #include "libmesh/cell_hex8.h" 00047 #include "libmesh/cell_hex20.h" 00048 #include "libmesh/cell_hex27.h" 00049 #include "libmesh/cell_inf_hex8.h" 00050 #include "libmesh/cell_inf_hex16.h" 00051 #include "libmesh/cell_inf_hex18.h" 00052 #include "libmesh/cell_prism6.h" 00053 #include "libmesh/cell_prism15.h" 00054 #include "libmesh/cell_prism18.h" 00055 #include "libmesh/cell_inf_prism6.h" 00056 #include "libmesh/cell_inf_prism12.h" 00057 #include "libmesh/cell_pyramid5.h" 00058 #include "libmesh/cell_pyramid13.h" 00059 #include "libmesh/cell_pyramid14.h" 00060 #include "libmesh/fe_base.h" 00061 #include "libmesh/mesh_base.h" 00062 #include "libmesh/quadrature_gauss.h" 00063 #include "libmesh/remote_elem.h" 00064 #include "libmesh/reference_elem.h" 00065 #include "libmesh/string_to_enum.h" 00066 00067 #ifdef LIBMESH_ENABLE_PERIODIC 00068 #include "libmesh/mesh.h" 00069 #include "libmesh/periodic_boundaries.h" 00070 #include "libmesh/boundary_info.h" 00071 #endif 00072 00073 namespace libMesh 00074 { 00075 00076 const subdomain_id_type Elem::invalid_subdomain_id = std::numeric_limits<subdomain_id_type>::max(); 00077 00078 // Initialize static member variables 00079 const unsigned int Elem::type_to_n_nodes_map [] = 00080 { 00081 2, // EDGE2 00082 3, // EDGE3 00083 4, // EDGE4 00084 00085 3, // TRI3 00086 6, // TRI6 00087 00088 4, // QUAD4 00089 8, // QUAD8 00090 9, // QUAD9 00091 00092 4, // TET4 00093 10, // TET10 00094 00095 8, // HEX8 00096 20, // HEX20 00097 27, // HEX27 00098 00099 6, // PRISM6 00100 15, // PRISM15 00101 18, // PRISM18 00102 00103 5, // PYRAMID5 00104 13, // PYRAMID13 00105 14, // PYRAMID14 00106 00107 2, // INFEDGE2 00108 00109 4, // INFQUAD4 00110 6, // INFQUAD6 00111 00112 8, // INFHEX8 00113 16, // INFHEX16 00114 18, // INFHEX18 00115 00116 6, // INFPRISM6 00117 16, // INFPRISM12 00118 00119 1, // NODEELEM 00120 00121 3, // TRI3SUBDIVISION 00122 }; 00123 00124 const unsigned int Elem::type_to_n_sides_map [] = 00125 { 00126 2, // EDGE2 00127 2, // EDGE3 00128 2, // EDGE4 00129 00130 3, // TRI3 00131 3, // TRI6 00132 00133 4, // QUAD4 00134 4, // QUAD8 00135 4, // QUAD9 00136 00137 4, // TET4 00138 4, // TET10 00139 00140 6, // HEX8 00141 6, // HEX20 00142 6, // HEX27 00143 00144 5, // PRISM6 00145 5, // PRISM15 00146 5, // PRISM18 00147 00148 5, // PYRAMID5 00149 5, // PYRAMID13 00150 5, // PYRAMID14 00151 00152 2, // INFEDGE2 00153 00154 3, // INFQUAD4 00155 3, // INFQUAD6 00156 00157 5, // INFHEX8 00158 5, // INFHEX16 00159 5, // INFHEX18 00160 00161 4, // INFPRISM6 00162 4, // INFPRISM12 00163 00164 0, // NODEELEM 00165 }; 00166 00167 const unsigned int Elem::type_to_n_edges_map [] = 00168 { 00169 0, // EDGE2 00170 0, // EDGE3 00171 0, // EDGE4 00172 00173 3, // TRI3 00174 3, // TRI6 00175 00176 4, // QUAD4 00177 4, // QUAD8 00178 4, // QUAD9 00179 00180 6, // TET4 00181 6, // TET10 00182 00183 12, // HEX8 00184 12, // HEX20 00185 12, // HEX27 00186 00187 9, // PRISM6 00188 9, // PRISM15 00189 9, // PRISM18 00190 00191 8, // PYRAMID5 00192 8, // PYRAMID13 00193 8, // PYRAMID14 00194 00195 0, // INFEDGE2 00196 00197 4, // INFQUAD4 00198 4, // INFQUAD6 00199 00200 8, // INFHEX8 00201 8, // INFHEX16 00202 8, // INFHEX18 00203 00204 6, // INFPRISM6 00205 6, // INFPRISM12 00206 00207 0, // NODEELEM 00208 }; 00209 00210 // ------------------------------------------------------------ 00211 // Elem class member funcions 00212 UniquePtr<Elem> Elem::build(const ElemType type, 00213 Elem* p) 00214 { 00215 Elem* elem = NULL; 00216 00217 switch (type) 00218 { 00219 // 0D elements 00220 case NODEELEM: 00221 { 00222 elem = new NodeElem(p); 00223 break; 00224 } 00225 00226 // 1D elements 00227 case EDGE2: 00228 { 00229 elem = new Edge2(p); 00230 break; 00231 } 00232 case EDGE3: 00233 { 00234 elem = new Edge3(p); 00235 break; 00236 } 00237 case EDGE4: 00238 { 00239 elem = new Edge4(p); 00240 break; 00241 } 00242 00243 00244 00245 // 2D elements 00246 case TRI3: 00247 { 00248 elem = new Tri3(p); 00249 break; 00250 } 00251 case TRI3SUBDIVISION: 00252 { 00253 elem = new Tri3Subdivision(p); 00254 break; 00255 } 00256 case TRI6: 00257 { 00258 elem = new Tri6(p); 00259 break; 00260 } 00261 case QUAD4: 00262 { 00263 elem = new Quad4(p); 00264 break; 00265 } 00266 case QUAD8: 00267 { 00268 elem = new Quad8(p); 00269 break; 00270 } 00271 case QUAD9: 00272 { 00273 elem = new Quad9(p); 00274 break; 00275 } 00276 00277 00278 // 3D elements 00279 case TET4: 00280 { 00281 elem = new Tet4(p); 00282 break; 00283 } 00284 case TET10: 00285 { 00286 elem = new Tet10(p); 00287 break; 00288 } 00289 case HEX8: 00290 { 00291 elem = new Hex8(p); 00292 break; 00293 } 00294 case HEX20: 00295 { 00296 elem = new Hex20(p); 00297 break; 00298 } 00299 case HEX27: 00300 { 00301 elem = new Hex27(p); 00302 break; 00303 } 00304 case PRISM6: 00305 { 00306 elem = new Prism6(p); 00307 break; 00308 } 00309 case PRISM15: 00310 { 00311 elem = new Prism15(p); 00312 break; 00313 } 00314 case PRISM18: 00315 { 00316 elem = new Prism18(p); 00317 break; 00318 } 00319 case PYRAMID5: 00320 { 00321 elem = new Pyramid5(p); 00322 break; 00323 } 00324 case PYRAMID13: 00325 { 00326 elem = new Pyramid13(p); 00327 break; 00328 } 00329 case PYRAMID14: 00330 { 00331 elem = new Pyramid14(p); 00332 break; 00333 } 00334 00335 00336 00337 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00338 00339 // 1D infinite elements 00340 case INFEDGE2: 00341 { 00342 elem = new InfEdge2(p); 00343 break; 00344 } 00345 00346 00347 // 2D infinite elements 00348 case INFQUAD4: 00349 { 00350 elem = new InfQuad4(p); 00351 break; 00352 } 00353 case INFQUAD6: 00354 { 00355 elem = new InfQuad6(p); 00356 break; 00357 } 00358 00359 00360 // 3D infinite elements 00361 case INFHEX8: 00362 { 00363 elem = new InfHex8(p); 00364 break; 00365 } 00366 case INFHEX16: 00367 { 00368 elem = new InfHex16(p); 00369 break; 00370 } 00371 case INFHEX18: 00372 { 00373 elem = new InfHex18(p); 00374 break; 00375 } 00376 case INFPRISM6: 00377 { 00378 elem = new InfPrism6(p); 00379 break; 00380 } 00381 case INFPRISM12: 00382 { 00383 elem = new InfPrism12(p); 00384 break; 00385 } 00386 00387 #endif 00388 00389 default: 00390 libmesh_error_msg("ERROR: Undefined element type!"); 00391 } 00392 00393 return UniquePtr<Elem>(elem); 00394 } 00395 00396 00397 00398 const Elem* Elem::reference_elem () const 00399 { 00400 return &(ReferenceElem::get(this->type())); 00401 } 00402 00403 00404 00405 Point Elem::centroid() const 00406 { 00407 Point cp; 00408 00409 for (unsigned int n=0; n<this->n_vertices(); n++) 00410 cp.add (this->point(n)); 00411 00412 return (cp /= static_cast<Real>(this->n_vertices())); 00413 } 00414 00415 00416 00417 Real Elem::hmin() const 00418 { 00419 Real h_min=std::numeric_limits<Real>::max(); 00420 00421 for (unsigned int n_outer=0; n_outer<this->n_vertices(); n_outer++) 00422 for (unsigned int n_inner=n_outer+1; n_inner<this->n_vertices(); n_inner++) 00423 { 00424 const Point diff = (this->point(n_outer) - this->point(n_inner)); 00425 00426 h_min = std::min(h_min,diff.size_sq()); 00427 } 00428 00429 return std::sqrt(h_min); 00430 } 00431 00432 00433 00434 Real Elem::hmax() const 00435 { 00436 Real h_max=0; 00437 00438 for (unsigned int n_outer=0; n_outer<this->n_vertices(); n_outer++) 00439 for (unsigned int n_inner=n_outer+1; n_inner<this->n_vertices(); n_inner++) 00440 { 00441 const Point diff = (this->point(n_outer) - this->point(n_inner)); 00442 00443 h_max = std::max(h_max,diff.size_sq()); 00444 } 00445 00446 return std::sqrt(h_max); 00447 } 00448 00449 00450 00451 Real Elem::length(const unsigned int n1, 00452 const unsigned int n2) const 00453 { 00454 libmesh_assert_less ( n1, this->n_vertices() ); 00455 libmesh_assert_less ( n2, this->n_vertices() ); 00456 00457 return (this->point(n1) - this->point(n2)).size(); 00458 } 00459 00460 00461 00462 bool Elem::operator == (const Elem& rhs) const 00463 { 00464 00465 // Cast rhs to an Elem* 00466 // const Elem* rhs_elem = dynamic_cast<const Elem*>(&rhs); 00467 const Elem* rhs_elem = &rhs; 00468 00469 // If we cannot cast to an Elem*, rhs must be a Node 00470 // if(rhs_elem == static_cast<const Elem*>(NULL)) 00471 // return false; 00472 00473 // libmesh_assert (n_nodes()); 00474 // libmesh_assert (rhs.n_nodes()); 00475 00476 // // Elements can only be equal if they 00477 // // contain the same number of nodes. 00478 // if (this->n_nodes() == rhs.n_nodes()) 00479 // { 00480 // // Create a set that contains our global 00481 // // node numbers and those of our neighbor. 00482 // // If the set is the same size as the number 00483 // // of nodes in both elements then they must 00484 // // be connected to the same nodes. 00485 // std::set<unsigned int> nodes_set; 00486 00487 // for (unsigned int n=0; n<this->n_nodes(); n++) 00488 // { 00489 // nodes_set.insert(this->node(n)); 00490 // nodes_set.insert(rhs.node(n)); 00491 // } 00492 00493 // // If this passes the elements are connected 00494 // // to the same global nodes 00495 // if (nodes_set.size() == this->n_nodes()) 00496 // return true; 00497 // } 00498 00499 // // If we get here it is because the elements either 00500 // // do not have the same number of nodes or they are 00501 // // connected to different nodes. Either way they 00502 // // are not the same element 00503 // return false; 00504 00505 // Useful typedefs 00506 typedef std::vector<dof_id_type>::iterator iterator; 00507 00508 00509 // Elements can only be equal if they 00510 // contain the same number of nodes. 00511 // However, we will only test the vertices, 00512 // which is sufficient & cheaper 00513 if (this->n_nodes() == rhs_elem->n_nodes()) 00514 { 00515 // The number of nodes in the element 00516 const unsigned int nn = this->n_nodes(); 00517 00518 // Create a vector that contains our global 00519 // node numbers and those of our neighbor. 00520 // If the sorted, unique vector is the same size 00521 // as the number of nodes in both elements then 00522 // they must be connected to the same nodes. 00523 // 00524 // The vector will be no larger than 2*n_nodes(), 00525 // so we might as well reserve the space. 00526 std::vector<dof_id_type> common_nodes; 00527 common_nodes.reserve (2*nn); 00528 00529 // Add the global indices of the nodes 00530 for (unsigned int n=0; n<nn; n++) 00531 { 00532 common_nodes.push_back (this->node(n)); 00533 common_nodes.push_back (rhs_elem->node(n)); 00534 } 00535 00536 // Sort the vector and find out how long 00537 // the sorted vector is. 00538 std::sort (common_nodes.begin(), common_nodes.end()); 00539 00540 iterator new_end = std::unique (common_nodes.begin(), 00541 common_nodes.end()); 00542 00543 const int new_size = cast_int<int> 00544 (std::distance (common_nodes.begin(), new_end)); 00545 00546 // If this passes the elements are connected 00547 // to the same global vertex nodes 00548 if (new_size == static_cast<int>(nn)) 00549 return true; 00550 } 00551 00552 // If we get here it is because the elements either 00553 // do not have the same number of nodes or they are 00554 // connected to different nodes. Either way they 00555 // are not the same element 00556 return false; 00557 } 00558 00559 00560 00561 bool Elem::is_semilocal(const processor_id_type my_pid) const 00562 { 00563 std::set<const Elem *> point_neighbors; 00564 00565 this->find_point_neighbors(point_neighbors); 00566 00567 std::set<const Elem*>::const_iterator it = point_neighbors.begin(); 00568 const std::set<const Elem*>::const_iterator end = point_neighbors.end(); 00569 00570 for (; it != end; ++it) 00571 { 00572 const Elem* elem = *it; 00573 if (elem->processor_id() == my_pid) 00574 return true; 00575 } 00576 00577 return false; 00578 } 00579 00580 00581 00582 bool Elem::contains_vertex_of(const Elem *e) const 00583 { 00584 // Our vertices are the first numbered nodes 00585 for (unsigned int n = 0; n != e->n_vertices(); ++n) 00586 if (this->contains_point(e->point(n))) 00587 return true; 00588 return false; 00589 } 00590 00591 00592 00593 bool Elem::contains_edge_of(const Elem *e) const 00594 { 00595 unsigned int num_contained_edges = 0; 00596 00597 // Our vertices are the first numbered nodes 00598 for (unsigned int n = 0; n != e->n_vertices(); ++n) 00599 { 00600 if (this->contains_point(e->point(n))) 00601 { 00602 num_contained_edges++; 00603 if(num_contained_edges>=2) 00604 { 00605 return true; 00606 } 00607 } 00608 } 00609 return false; 00610 } 00611 00612 00613 00614 void Elem::find_point_neighbors(const Point &p, 00615 std::set<const Elem *> &neighbor_set) const 00616 { 00617 libmesh_assert(this->contains_point(p)); 00618 00619 neighbor_set.clear(); 00620 neighbor_set.insert(this); 00621 00622 std::set<const Elem *> untested_set, next_untested_set; 00623 untested_set.insert(this); 00624 00625 while (!untested_set.empty()) 00626 { 00627 // Loop over all the elements in the patch that haven't already 00628 // been tested 00629 std::set<const Elem*>::const_iterator it = untested_set.begin(); 00630 const std::set<const Elem*>::const_iterator end = untested_set.end(); 00631 00632 for (; it != end; ++it) 00633 { 00634 const Elem* elem = *it; 00635 00636 for (unsigned int s=0; s<elem->n_sides(); s++) 00637 { 00638 const Elem* current_neighbor = elem->neighbor(s); 00639 if (current_neighbor && 00640 current_neighbor != remote_elem) // we have a real neighbor on this side 00641 { 00642 if (current_neighbor->active()) // ... if it is active 00643 { 00644 if (current_neighbor->contains_point(p)) // ... and touches p 00645 { 00646 // Make sure we'll test it 00647 if (!neighbor_set.count(current_neighbor)) 00648 next_untested_set.insert (current_neighbor); 00649 00650 // And add it 00651 neighbor_set.insert (current_neighbor); 00652 } 00653 } 00654 #ifdef LIBMESH_ENABLE_AMR 00655 else // ... the neighbor is *not* active, 00656 { // ... so add *all* neighboring 00657 // active children that touch p 00658 std::vector<const Elem*> active_neighbor_children; 00659 00660 current_neighbor->active_family_tree_by_neighbor 00661 (active_neighbor_children, elem); 00662 00663 std::vector<const Elem*>::const_iterator 00664 child_it = active_neighbor_children.begin(); 00665 const std::vector<const Elem*>::const_iterator 00666 child_end = active_neighbor_children.end(); 00667 for (; child_it != child_end; ++child_it) 00668 { 00669 const Elem *current_child = *child_it; 00670 if (current_child->contains_point(p)) 00671 { 00672 // Make sure we'll test it 00673 if (!neighbor_set.count(current_child)) 00674 next_untested_set.insert (current_child); 00675 00676 neighbor_set.insert (current_child); 00677 } 00678 } 00679 } 00680 #endif // #ifdef LIBMESH_ENABLE_AMR 00681 } 00682 } 00683 } 00684 untested_set.swap(next_untested_set); 00685 next_untested_set.clear(); 00686 } 00687 } 00688 00689 00690 00691 void Elem::find_point_neighbors(std::set<const Elem *> &neighbor_set) const 00692 { 00693 neighbor_set.clear(); 00694 neighbor_set.insert(this); 00695 00696 std::set<const Elem *> untested_set, next_untested_set; 00697 untested_set.insert(this); 00698 00699 while (!untested_set.empty()) 00700 { 00701 // Loop over all the elements in the patch that haven't already 00702 // been tested 00703 std::set<const Elem*>::const_iterator it = untested_set.begin(); 00704 const std::set<const Elem*>::const_iterator end = untested_set.end(); 00705 00706 for (; it != end; ++it) 00707 { 00708 const Elem* elem = *it; 00709 00710 for (unsigned int s=0; s<elem->n_sides(); s++) 00711 { 00712 const Elem* current_neighbor = elem->neighbor(s); 00713 if (current_neighbor && 00714 current_neighbor != remote_elem) // we have a real neighbor on this side 00715 { 00716 if (current_neighbor->active()) // ... if it is active 00717 { 00718 if (this->contains_vertex_of(current_neighbor) // ... and touches us 00719 || current_neighbor->contains_vertex_of(this)) 00720 { 00721 // Make sure we'll test it 00722 if (!neighbor_set.count(current_neighbor)) 00723 next_untested_set.insert (current_neighbor); 00724 00725 // And add it 00726 neighbor_set.insert (current_neighbor); 00727 } 00728 } 00729 #ifdef LIBMESH_ENABLE_AMR 00730 else // ... the neighbor is *not* active, 00731 { // ... so add *all* neighboring 00732 // active children 00733 std::vector<const Elem*> active_neighbor_children; 00734 00735 current_neighbor->active_family_tree_by_neighbor 00736 (active_neighbor_children, elem); 00737 00738 std::vector<const Elem*>::const_iterator 00739 child_it = active_neighbor_children.begin(); 00740 const std::vector<const Elem*>::const_iterator 00741 child_end = active_neighbor_children.end(); 00742 for (; child_it != child_end; ++child_it) 00743 { 00744 const Elem *current_child = *child_it; 00745 if (this->contains_vertex_of(current_child) || 00746 (current_child)->contains_vertex_of(this)) 00747 { 00748 // Make sure we'll test it 00749 if (!neighbor_set.count(current_child)) 00750 next_untested_set.insert (current_child); 00751 00752 neighbor_set.insert (current_child); 00753 } 00754 } 00755 } 00756 #endif // #ifdef LIBMESH_ENABLE_AMR 00757 } 00758 } 00759 } 00760 untested_set.swap(next_untested_set); 00761 next_untested_set.clear(); 00762 } 00763 } 00764 00765 00766 00767 void Elem::find_edge_neighbors(const Point& p1, 00768 const Point& p2, 00769 std::set<const Elem *> &neighbor_set) const 00770 { 00771 // Simple but perhaps suboptimal code: find elements containing the 00772 // first point, then winnow this set down by removing elements which 00773 // don't also contain the second point 00774 00775 libmesh_assert(this->contains_point(p2)); 00776 this->find_point_neighbors(p1, neighbor_set); 00777 00778 std::set<const Elem*>::iterator it = neighbor_set.begin(); 00779 const std::set<const Elem*>::iterator end = neighbor_set.end(); 00780 00781 while(it != end) { 00782 std::set<const Elem*>::iterator current = it++; 00783 00784 const Elem* elem = *current; 00785 // This won't invalidate iterator it, because it is already 00786 // pointing to the next element 00787 if (!elem->contains_point(p2)) 00788 neighbor_set.erase(current); 00789 } 00790 } 00791 00792 00793 00794 void Elem::find_edge_neighbors(std::set<const Elem *> &neighbor_set) const 00795 { 00796 neighbor_set.clear(); 00797 neighbor_set.insert(this); 00798 00799 std::set<const Elem *> untested_set, next_untested_set; 00800 untested_set.insert(this); 00801 00802 while (!untested_set.empty()) 00803 { 00804 // Loop over all the elements in the patch that haven't already 00805 // been tested 00806 std::set<const Elem*>::const_iterator it = untested_set.begin(); 00807 const std::set<const Elem*>::const_iterator end = untested_set.end(); 00808 00809 for (; it != end; ++it) 00810 { 00811 const Elem* elem = *it; 00812 00813 for (unsigned int s=0; s<elem->n_sides(); s++) 00814 { 00815 const Elem* current_neighbor = elem->neighbor(s); 00816 if (current_neighbor && 00817 current_neighbor != remote_elem) // we have a real neighbor on this side 00818 { 00819 if (current_neighbor->active()) // ... if it is active 00820 { 00821 if (this->contains_edge_of(current_neighbor) // ... and touches us 00822 || current_neighbor->contains_edge_of(this)) 00823 { 00824 // Make sure we'll test it 00825 if (!neighbor_set.count(current_neighbor)) 00826 next_untested_set.insert (current_neighbor); 00827 00828 // And add it 00829 neighbor_set.insert (current_neighbor); 00830 } 00831 } 00832 #ifdef LIBMESH_ENABLE_AMR 00833 else // ... the neighbor is *not* active, 00834 { // ... so add *all* neighboring 00835 // active children 00836 std::vector<const Elem*> active_neighbor_children; 00837 00838 current_neighbor->active_family_tree_by_neighbor 00839 (active_neighbor_children, elem); 00840 00841 std::vector<const Elem*>::const_iterator 00842 child_it = active_neighbor_children.begin(); 00843 const std::vector<const Elem*>::const_iterator 00844 child_end = active_neighbor_children.end(); 00845 for (; child_it != child_end; ++child_it) 00846 { 00847 const Elem *current_child = *child_it; 00848 if (this->contains_edge_of(*child_it) || 00849 (*child_it)->contains_edge_of(this)) 00850 { 00851 // Make sure we'll test it 00852 if (!neighbor_set.count(current_child)) 00853 next_untested_set.insert (current_child); 00854 00855 neighbor_set.insert (current_child); 00856 } 00857 } 00858 } 00859 #endif // #ifdef LIBMESH_ENABLE_AMR 00860 } 00861 } 00862 } 00863 untested_set.swap(next_untested_set); 00864 next_untested_set.clear(); 00865 } 00866 } 00867 00868 #ifdef LIBMESH_ENABLE_PERIODIC 00869 00870 Elem* Elem::topological_neighbor (const unsigned int i, 00871 MeshBase & mesh, 00872 const PointLocatorBase& point_locator, 00873 const PeriodicBoundaries * pb) 00874 { 00875 libmesh_assert_less (i, this->n_neighbors()); 00876 00877 Elem * neighbor_i = this->neighbor(i); 00878 if (neighbor_i != NULL) 00879 return neighbor_i; 00880 00881 if (pb) 00882 { 00883 // Since the neighbor is NULL it must be on a boundary. We need 00884 // see if this is a periodic boundary in which case it will have a 00885 // topological neighbor 00886 00887 std::vector<boundary_id_type> boundary_ids = 00888 mesh.get_boundary_info().boundary_ids(this, cast_int<unsigned short>(i)); 00889 for (std::vector<boundary_id_type>::iterator j = boundary_ids.begin(); j != boundary_ids.end(); ++j) 00890 if (pb->boundary(*j)) 00891 { 00892 // Since the point locator inside of periodic boundaries 00893 // returns a const pointer we will retrieve the proper 00894 // pointer directly from the mesh object. Also since coarse 00895 // elements do not have more refined neighbors we need to make 00896 // sure that we don't return one of these types of neighbors. 00897 neighbor_i = mesh.elem(pb->neighbor(*j, point_locator, this, i)->id()); 00898 if (level() < neighbor_i->level()) 00899 neighbor_i = neighbor_i->parent(); 00900 return neighbor_i; 00901 } 00902 } 00903 00904 return NULL; 00905 } 00906 00907 00908 00909 const Elem* Elem::topological_neighbor (const unsigned int i, 00910 const MeshBase & mesh, 00911 const PointLocatorBase& point_locator, 00912 const PeriodicBoundaries * pb) const 00913 { 00914 libmesh_assert_less (i, this->n_neighbors()); 00915 00916 const Elem * neighbor_i = this->neighbor(i); 00917 if (neighbor_i != NULL) 00918 return neighbor_i; 00919 00920 if (pb) 00921 { 00922 // Since the neighbor is NULL it must be on a boundary. We need 00923 // see if this is a periodic boundary in which case it will have a 00924 // topological neighbor 00925 00926 std::vector<boundary_id_type> boundary_ids = 00927 mesh.get_boundary_info().boundary_ids(this, cast_int<unsigned short>(i)); 00928 for (std::vector<boundary_id_type>::iterator j = boundary_ids.begin(); j != boundary_ids.end(); ++j) 00929 if (pb->boundary(*j)) 00930 { 00931 // Since the point locator inside of periodic boundaries 00932 // returns a const pointer we will retrieve the proper 00933 // pointer directly from the mesh object. Also since coarse 00934 // elements do not have more refined neighbors we need to make 00935 // sure that we don't return one of these types of neighbors. 00936 neighbor_i = mesh.elem(pb->neighbor(*j, point_locator, this, i)->id()); 00937 if (level() < neighbor_i->level()) 00938 neighbor_i = neighbor_i->parent(); 00939 return neighbor_i; 00940 } 00941 } 00942 00943 return NULL; 00944 } 00945 00946 00947 bool Elem::has_topological_neighbor (const Elem* elem, 00948 const MeshBase & mesh, 00949 const PointLocatorBase& point_locator, 00950 PeriodicBoundaries * pb) const 00951 { 00952 // First see if this is a normal "interior" neighbor 00953 if (has_neighbor(elem)) 00954 return true; 00955 00956 for (unsigned int n=0; n<this->n_neighbors(); n++) 00957 if (this->topological_neighbor(n, mesh, point_locator, pb)) 00958 return true; 00959 00960 return false; 00961 } 00962 00963 00964 #endif 00965 00966 #ifdef DEBUG 00967 00968 void Elem::libmesh_assert_valid_node_pointers() const 00969 { 00970 libmesh_assert(this->valid_id()); 00971 for (unsigned int n=0; n != this->n_nodes(); ++n) 00972 { 00973 libmesh_assert(this->get_node(n)); 00974 libmesh_assert(this->get_node(n)->valid_id()); 00975 } 00976 } 00977 00978 00979 00980 void Elem::libmesh_assert_valid_neighbors() const 00981 { 00982 for (unsigned int s=0; s<this->n_neighbors(); s++) 00983 { 00984 const Elem *neigh = this->neighbor(s); 00985 00986 // Any element might have a remote neighbor; checking 00987 // to make sure that's not inaccurate is tough. 00988 if (neigh == remote_elem) 00989 continue; 00990 00991 if (neigh) 00992 { 00993 // Only subactive elements have subactive neighbors 00994 libmesh_assert (this->subactive() || !neigh->subactive()); 00995 00996 const Elem *elem = this; 00997 00998 // If we're subactive but our neighbor isn't, its 00999 // return neighbor link will be to our first active 01000 // ancestor OR to our inactive ancestor of the same 01001 // level as neigh, 01002 if (this->subactive() && !neigh->subactive()) 01003 { 01004 for (elem = this; !elem->active(); 01005 elem = elem->parent()) 01006 libmesh_assert(elem); 01007 } 01008 else 01009 { 01010 unsigned int rev = neigh->which_neighbor_am_i(elem); 01011 libmesh_assert_less (rev, neigh->n_neighbors()); 01012 01013 if (this->subactive() && !neigh->subactive()) 01014 { 01015 while (neigh->neighbor(rev) != elem) 01016 { 01017 libmesh_assert(elem->parent()); 01018 elem = elem->parent(); 01019 } 01020 } 01021 else 01022 { 01023 Elem *nn = neigh->neighbor(rev); 01024 libmesh_assert(nn); 01025 01026 for (; elem != nn; elem = elem->parent()) 01027 libmesh_assert(elem); 01028 } 01029 } 01030 } 01031 // If we don't have a neighbor and we're not subactive, our 01032 // ancestors shouldn't have any neighbors in this same 01033 // direction. 01034 else if (!this->subactive()) 01035 { 01036 const Elem *my_parent = this->parent(); 01037 if (my_parent && 01038 // A parent with a different dimension isn't really one of 01039 // our ancestors, it means we're on a boundary mesh and this 01040 // is an interior mesh element for which we're on a side. 01041 // Nothing to test for in that case. 01042 (my_parent->dim() == this->dim())) 01043 libmesh_assert (!my_parent->neighbor(s)); 01044 } 01045 } 01046 } 01047 01048 #endif // DEBUG 01049 01050 01051 01052 void Elem::make_links_to_me_local(unsigned int n) 01053 { 01054 Elem *neigh = this->neighbor(n); 01055 01056 // Don't bother calling this function unless it's necessary 01057 libmesh_assert(neigh); 01058 libmesh_assert(!neigh->is_remote()); 01059 01060 // We never have neighbors more refined than us 01061 libmesh_assert_less_equal (neigh->level(), this->level()); 01062 01063 // We never have subactive neighbors of non subactive elements 01064 libmesh_assert(!neigh->subactive() || this->subactive()); 01065 01066 // If we have a neighbor less refined than us then it must not 01067 // have any more refined active descendants we could have 01068 // pointed to instead. 01069 libmesh_assert(neigh->level() == this->level() || 01070 neigh->active()); 01071 01072 // If neigh is at our level, then its family might have 01073 // remote_elem neighbor links which need to point to us 01074 // instead, but if not, then we're done. 01075 if (neigh->level() != this->level()) 01076 return; 01077 01078 // If neigh is subactive then we're not updating its neighbor links 01079 // FIXME - this needs to change when we start using subactive 01080 // elements for more than just the two-phase 01081 // restriction/prolongation projections. 01082 if (neigh->subactive()) 01083 return; 01084 01085 // What side of neigh are we on? We can't use the usual Elem 01086 // method because we're in the middle of restoring topology 01087 const UniquePtr<Elem> my_side = this->side(n); 01088 unsigned int nn = 0; 01089 for (; nn != neigh->n_sides(); ++nn) 01090 { 01091 const UniquePtr<Elem> neigh_side = neigh->side(nn); 01092 if (*my_side == *neigh_side) 01093 break; 01094 } 01095 01096 // we had better be on *some* side of neigh 01097 libmesh_assert_less (nn, neigh->n_sides()); 01098 01099 // Find any elements that ought to point to elem 01100 std::vector<const Elem*> neigh_family; 01101 #ifdef LIBMESH_ENABLE_AMR 01102 if (this->active()) 01103 neigh->family_tree_by_side(neigh_family, nn); 01104 else 01105 #endif 01106 neigh_family.push_back(neigh); 01107 01108 // And point them to elem 01109 for (unsigned int i = 0; i != neigh_family.size(); ++i) 01110 { 01111 Elem* neigh_family_member = const_cast<Elem*>(neigh_family[i]); 01112 01113 // Ideally, the neighbor link ought to either be correct 01114 // already or ought to be to remote_elem. 01115 // 01116 // However, if we're redistributing a newly created elem, 01117 // after an AMR step but before find_neighbors has fixed up 01118 // neighbor links, we might have an out of date neighbor 01119 // link to elem's parent instead. 01120 #ifdef LIBMESH_ENABLE_AMR 01121 libmesh_assert((neigh_family_member->neighbor(nn) == this) || 01122 (neigh_family_member->neighbor(nn) == remote_elem) 01123 || ((this->refinement_flag() == JUST_REFINED) && 01124 (this->parent() != NULL) && 01125 (neigh_family_member->neighbor(nn) == this->parent()))); 01126 #else 01127 libmesh_assert((neigh_family_member->neighbor(nn) == this) || 01128 (neigh_family_member->neighbor(nn) == remote_elem)); 01129 #endif 01130 01131 neigh_family_member->set_neighbor(nn, this); 01132 } 01133 } 01134 01135 01136 void Elem::make_links_to_me_remote() 01137 { 01138 libmesh_assert_not_equal_to (this, remote_elem); 01139 01140 // We need to have handled any children first 01141 #if defined(LIBMESH_ENABLE_AMR) && defined(DEBUG) 01142 if (this->has_children()) 01143 for (unsigned int c = 0; c != this->n_children(); ++c) 01144 { 01145 Elem *current_child = this->child(c); 01146 libmesh_assert_equal_to (current_child, remote_elem); 01147 } 01148 #endif 01149 01150 // Remotify any neighbor links to non-subactive elements 01151 if (!this->subactive()) 01152 { 01153 for (unsigned int s = 0; s != this->n_sides(); ++s) 01154 { 01155 Elem *neigh = this->neighbor(s); 01156 if (neigh && neigh != remote_elem && !neigh->subactive()) 01157 { 01158 // My neighbor should never be more refined than me; my real 01159 // neighbor would have been its parent in that case. 01160 libmesh_assert_greater_equal (this->level(), neigh->level()); 01161 01162 if (this->level() == neigh->level() && 01163 neigh->has_neighbor(this)) 01164 { 01165 #ifdef LIBMESH_ENABLE_AMR 01166 // My neighbor may have descendants which also consider me a 01167 // neighbor 01168 std::vector<const Elem*> family; 01169 neigh->family_tree_by_neighbor (family, this); 01170 01171 // FIXME - There's a lot of ugly const_casts here; we 01172 // may want to make remote_elem non-const and create 01173 // non-const versions of the family_tree methods 01174 for (unsigned int i=0; i != family.size(); ++i) 01175 { 01176 Elem *n = const_cast<Elem*>(family[i]); 01177 libmesh_assert (n); 01178 if (n == remote_elem) 01179 continue; 01180 unsigned int my_s = n->which_neighbor_am_i(this); 01181 libmesh_assert_less (my_s, n->n_neighbors()); 01182 libmesh_assert_equal_to (n->neighbor(my_s), this); 01183 n->set_neighbor(my_s, const_cast<RemoteElem*>(remote_elem)); 01184 } 01185 #else 01186 unsigned int my_s = neigh->which_neighbor_am_i(this); 01187 libmesh_assert_less (my_s, neigh->n_neighbors()); 01188 libmesh_assert_equal_to (neigh->neighbor(my_s), this); 01189 neigh->set_neighbor(my_s, const_cast<RemoteElem*>(remote_elem)); 01190 #endif 01191 } 01192 #ifdef LIBMESH_ENABLE_AMR 01193 // Even if my neighbor doesn't link back to me, it might 01194 // have subactive descendants which do 01195 else if (neigh->has_children()) 01196 { 01197 // If my neighbor at the same level doesn't have me as a 01198 // neighbor, I must be subactive 01199 libmesh_assert(this->level() > neigh->level() || 01200 this->subactive()); 01201 01202 // My neighbor must have some ancestor of mine as a 01203 // neighbor 01204 Elem *my_ancestor = this->parent(); 01205 libmesh_assert(my_ancestor); 01206 while (!neigh->has_neighbor(my_ancestor)) 01207 { 01208 my_ancestor = my_ancestor->parent(); 01209 libmesh_assert(my_ancestor); 01210 } 01211 01212 // My neighbor may have descendants which consider me a 01213 // neighbor 01214 std::vector<const Elem*> family; 01215 neigh->family_tree_by_subneighbor (family, my_ancestor, this); 01216 01217 // FIXME - There's a lot of ugly const_casts here; we 01218 // may want to make remote_elem non-const and create 01219 // non-const versions of the family_tree methods 01220 for (unsigned int i=0; i != family.size(); ++i) 01221 { 01222 Elem *n = const_cast<Elem*>(family[i]); 01223 libmesh_assert (n); 01224 if (n == remote_elem) 01225 continue; 01226 unsigned int my_s = n->which_neighbor_am_i(this); 01227 libmesh_assert_less (my_s, n->n_neighbors()); 01228 libmesh_assert_equal_to (n->neighbor(my_s), this); 01229 n->set_neighbor(my_s, const_cast<RemoteElem*>(remote_elem)); 01230 } 01231 } 01232 #endif 01233 } 01234 } 01235 } 01236 01237 #ifdef LIBMESH_ENABLE_AMR 01238 // Remotify parent's child link 01239 Elem *my_parent = this->parent(); 01240 if (my_parent && 01241 // As long as it's not already remote 01242 my_parent != remote_elem && 01243 // And it's a real parent, not an interior parent 01244 this->dim() == my_parent->dim()) 01245 { 01246 unsigned int me = my_parent->which_child_am_i(this); 01247 libmesh_assert_equal_to (my_parent->child(me), this); 01248 my_parent->set_child(me, const_cast<RemoteElem*>(remote_elem)); 01249 } 01250 #endif 01251 } 01252 01253 01254 01255 void Elem::write_connectivity (std::ostream& out_stream, 01256 const IOPackage iop) const 01257 { 01258 libmesh_assert (out_stream.good()); 01259 libmesh_assert(_nodes); 01260 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE); 01261 01262 switch (iop) 01263 { 01264 case TECPLOT: 01265 { 01266 // This connectivity vector will be used repeatedly instead 01267 // of being reconstructed inside the loop. 01268 std::vector<dof_id_type> conn; 01269 for (unsigned int sc=0; sc <this->n_sub_elem(); sc++) 01270 { 01271 this->connectivity(sc, TECPLOT, conn); 01272 01273 std::copy(conn.begin(), 01274 conn.end(), 01275 std::ostream_iterator<dof_id_type>(out_stream, " ")); 01276 01277 out_stream << '\n'; 01278 } 01279 return; 01280 } 01281 01282 case UCD: 01283 { 01284 for (unsigned int i=0; i<this->n_nodes(); i++) 01285 out_stream << this->node(i)+1 << "\t"; 01286 01287 out_stream << '\n'; 01288 return; 01289 } 01290 01291 default: 01292 libmesh_error_msg("Unsupported IO package " << iop); 01293 } 01294 } 01295 01296 01297 01298 Real Elem::quality (const ElemQuality q) const 01299 { 01300 switch (q) 01301 { 01305 default: 01306 { 01307 libmesh_do_once( libmesh_here(); 01308 01309 libMesh::err << "ERROR: unknown quality metric: " 01310 << Utility::enum_to_string(q) 01311 << std::endl 01312 << "Cowardly returning 1." 01313 << std::endl; ); 01314 01315 return 1.; 01316 } 01317 } 01318 01319 libmesh_error_msg("We'll never get here!"); 01320 return 0.; 01321 } 01322 01323 01324 01325 bool Elem::ancestor() const 01326 { 01327 #ifdef LIBMESH_ENABLE_AMR 01328 01329 if (this->active()) 01330 return false; 01331 01332 if (!this->has_children()) 01333 return false; 01334 if (this->child(0)->active()) 01335 return true; 01336 01337 return this->child(0)->ancestor(); 01338 #else 01339 return false; 01340 #endif 01341 } 01342 01343 01344 01345 #ifdef LIBMESH_ENABLE_AMR 01346 01347 void Elem::add_child (Elem* elem) 01348 { 01349 if(_children == NULL) 01350 { 01351 _children = new Elem*[this->n_children()]; 01352 01353 for (unsigned int c=0; c<this->n_children(); c++) 01354 this->set_child(c, NULL); 01355 } 01356 01357 for (unsigned int c=0; c<this->n_children(); c++) 01358 { 01359 if(this->_children[c] == NULL || this->_children[c] == remote_elem) 01360 { 01361 libmesh_assert_equal_to (this, elem->parent()); 01362 this->set_child(c, elem); 01363 return; 01364 } 01365 } 01366 01367 libmesh_error_msg("Error: Tried to add a child to an element with full children array"); 01368 } 01369 01370 01371 01372 void Elem::add_child (Elem* elem, unsigned int c) 01373 { 01374 if(!this->has_children()) 01375 { 01376 _children = new Elem*[this->n_children()]; 01377 01378 for (unsigned int i=0; i<this->n_children(); i++) 01379 this->set_child(i, NULL); 01380 } 01381 01382 libmesh_assert (this->_children[c] == NULL || this->child(c) == remote_elem); 01383 libmesh_assert (elem == remote_elem || this == elem->parent()); 01384 01385 this->set_child(c, elem); 01386 } 01387 01388 01389 01390 void Elem::replace_child (Elem* elem, unsigned int c) 01391 { 01392 libmesh_assert(this->has_children()); 01393 01394 libmesh_assert(this->child(c)); 01395 01396 this->set_child(c, elem); 01397 } 01398 01399 01400 01401 bool Elem::is_child_on_edge(const unsigned int libmesh_dbg_var(c), 01402 const unsigned int e) const 01403 { 01404 libmesh_assert_less (c, this->n_children()); 01405 libmesh_assert_less (e, this->n_edges()); 01406 01407 UniquePtr<Elem> my_edge = this->build_edge(e); 01408 UniquePtr<Elem> child_edge = this->build_edge(e); 01409 01410 // We're assuming that an overlapping child edge has the same 01411 // number and orientation as its parent 01412 return (child_edge->node(0) == my_edge->node(0) || 01413 child_edge->node(1) == my_edge->node(1)); 01414 } 01415 01416 01417 void Elem::family_tree (std::vector<const Elem*>& family, 01418 const bool reset) const 01419 { 01420 // The "family tree" doesn't include subactive elements 01421 libmesh_assert(!this->subactive()); 01422 01423 // Clear the vector if the flag reset tells us to. 01424 if (reset) 01425 family.clear(); 01426 01427 // Add this element to the family tree. 01428 family.push_back(this); 01429 01430 // Recurse into the elements children, if it has them. 01431 // Do not clear the vector any more. 01432 if (!this->active()) 01433 for (unsigned int c=0; c<this->n_children(); c++) 01434 if (!this->child(c)->is_remote()) 01435 this->child(c)->family_tree (family, false); 01436 } 01437 01438 01439 01440 void Elem::total_family_tree (std::vector<const Elem*>& family, 01441 const bool reset) const 01442 { 01443 // Clear the vector if the flag reset tells us to. 01444 if (reset) 01445 family.clear(); 01446 01447 // Add this element to the family tree. 01448 family.push_back(this); 01449 01450 // Recurse into the elements children, if it has them. 01451 // Do not clear the vector any more. 01452 if (this->has_children()) 01453 for (unsigned int c=0; c<this->n_children(); c++) 01454 if (!this->child(c)->is_remote()) 01455 this->child(c)->total_family_tree (family, false); 01456 } 01457 01458 01459 01460 void Elem::active_family_tree (std::vector<const Elem*>& active_family, 01461 const bool reset) const 01462 { 01463 // The "family tree" doesn't include subactive elements 01464 libmesh_assert(!this->subactive()); 01465 01466 // Clear the vector if the flag reset tells us to. 01467 if (reset) 01468 active_family.clear(); 01469 01470 // Add this element to the family tree if it is active 01471 if (this->active()) 01472 active_family.push_back(this); 01473 01474 // Otherwise recurse into the element's children. 01475 // Do not clear the vector any more. 01476 else 01477 for (unsigned int c=0; c<this->n_children(); c++) 01478 if (!this->child(c)->is_remote()) 01479 this->child(c)->active_family_tree (active_family, false); 01480 } 01481 01482 01483 01484 void Elem::family_tree_by_side (std::vector<const Elem*>& family, 01485 const unsigned int s, 01486 const bool reset) const 01487 { 01488 // The "family tree" doesn't include subactive elements 01489 libmesh_assert(!this->subactive()); 01490 01491 // Clear the vector if the flag reset tells us to. 01492 if (reset) 01493 family.clear(); 01494 01495 libmesh_assert_less (s, this->n_sides()); 01496 01497 // Add this element to the family tree. 01498 family.push_back(this); 01499 01500 // Recurse into the elements children, if it has them. 01501 // Do not clear the vector any more. 01502 if (!this->active()) 01503 for (unsigned int c=0; c<this->n_children(); c++) 01504 if (!this->child(c)->is_remote() && this->is_child_on_side(c, s)) 01505 this->child(c)->family_tree_by_side (family, s, false); 01506 } 01507 01508 01509 01510 void Elem::active_family_tree_by_side (std::vector<const Elem*>& family, 01511 const unsigned int s, 01512 const bool reset) const 01513 { 01514 // The "family tree" doesn't include subactive elements 01515 libmesh_assert(!this->subactive()); 01516 01517 // Clear the vector if the flag reset tells us to. 01518 if (reset) 01519 family.clear(); 01520 01521 libmesh_assert_less (s, this->n_sides()); 01522 01523 // Add an active element to the family tree. 01524 if (this->active()) 01525 family.push_back(this); 01526 01527 // Or recurse into an ancestor element's children. 01528 // Do not clear the vector any more. 01529 else 01530 for (unsigned int c=0; c<this->n_children(); c++) 01531 if (!this->child(c)->is_remote() && this->is_child_on_side(c, s)) 01532 this->child(c)->active_family_tree_by_side (family, s, false); 01533 } 01534 01535 01536 01537 void Elem::family_tree_by_neighbor (std::vector<const Elem*>& family, 01538 const Elem* neighbor_in, 01539 const bool reset) const 01540 { 01541 // The "family tree" doesn't include subactive elements 01542 libmesh_assert(!this->subactive()); 01543 01544 // Clear the vector if the flag reset tells us to. 01545 if (reset) 01546 family.clear(); 01547 01548 // This only makes sense if we're already a neighbor 01549 libmesh_assert (this->has_neighbor(neighbor_in)); 01550 01551 // Add this element to the family tree. 01552 family.push_back(this); 01553 01554 // Recurse into the elements children, if it's not active. 01555 // Do not clear the vector any more. 01556 if (!this->active()) 01557 for (unsigned int c=0; c<this->n_children(); c++) 01558 { 01559 Elem *current_child = this->child(c); 01560 if (current_child != remote_elem && current_child->has_neighbor(neighbor_in)) 01561 current_child->family_tree_by_neighbor (family, neighbor_in, false); 01562 } 01563 } 01564 01565 01566 01567 void Elem::family_tree_by_subneighbor (std::vector<const Elem*>& family, 01568 const Elem* neighbor_in, 01569 const Elem* subneighbor, 01570 const bool reset) const 01571 { 01572 // The "family tree" doesn't include subactive elements 01573 libmesh_assert(!this->subactive()); 01574 01575 // Clear the vector if the flag reset tells us to. 01576 if (reset) 01577 family.clear(); 01578 01579 // To simplifly this function we need an existing neighbor 01580 libmesh_assert (neighbor_in); 01581 libmesh_assert_not_equal_to (neighbor_in, remote_elem); 01582 libmesh_assert (this->has_neighbor(neighbor_in)); 01583 01584 // This only makes sense if subneighbor descends from neighbor 01585 libmesh_assert (subneighbor); 01586 libmesh_assert_not_equal_to (subneighbor, remote_elem); 01587 libmesh_assert (neighbor_in->is_ancestor_of(subneighbor)); 01588 01589 // Add this element to the family tree if applicable. 01590 if (neighbor_in == subneighbor) 01591 family.push_back(this); 01592 01593 // Recurse into the elements children, if it's not active. 01594 // Do not clear the vector any more. 01595 if (!this->active()) 01596 for (unsigned int c=0; c != this->n_children(); ++c) 01597 { 01598 Elem *current_child = this->child(c); 01599 if (current_child != remote_elem) 01600 for (unsigned int s=0; s != current_child->n_sides(); ++s) 01601 { 01602 Elem *child_neigh = current_child->neighbor(s); 01603 if (child_neigh && 01604 (child_neigh == neighbor_in || 01605 (child_neigh->parent() == neighbor_in && 01606 child_neigh->is_ancestor_of(subneighbor)))) 01607 current_child->family_tree_by_subneighbor (family, child_neigh, 01608 subneighbor, false); 01609 } 01610 } 01611 } 01612 01613 01614 01615 void Elem::active_family_tree_by_neighbor (std::vector<const Elem*>& family, 01616 const Elem* neighbor_in, 01617 const bool reset) const 01618 { 01619 // The "family tree" doesn't include subactive elements 01620 libmesh_assert(!this->subactive()); 01621 01622 // Clear the vector if the flag reset tells us to. 01623 if (reset) 01624 family.clear(); 01625 01626 // This only makes sense if we're already a neighbor 01627 if (this->level() >= neighbor_in->level()) 01628 libmesh_assert (this->has_neighbor(neighbor_in)); 01629 01630 // Add an active element to the family tree. 01631 if (this->active()) 01632 family.push_back(this); 01633 01634 // Or recurse into an ancestor element's children. 01635 // Do not clear the vector any more. 01636 else if (!this->active()) 01637 for (unsigned int c=0; c<this->n_children(); c++) 01638 { 01639 Elem *current_child = this->child(c); 01640 if (current_child != remote_elem && current_child->has_neighbor(neighbor_in)) 01641 current_child->active_family_tree_by_neighbor (family, neighbor_in, false); 01642 } 01643 } 01644 01645 01646 01647 unsigned int Elem::min_p_level_by_neighbor(const Elem* neighbor_in, 01648 unsigned int current_min) const 01649 { 01650 libmesh_assert(!this->subactive()); 01651 libmesh_assert(neighbor_in->active()); 01652 01653 // If we're an active element this is simple 01654 if (this->active()) 01655 return std::min(current_min, this->p_level()); 01656 01657 libmesh_assert(has_neighbor(neighbor_in)); 01658 01659 // The p_level() of an ancestor element is already the minimum 01660 // p_level() of its children - so if that's high enough, we don't 01661 // need to examine any children. 01662 if (current_min <= this->p_level()) 01663 return current_min; 01664 01665 unsigned int min_p_level = current_min; 01666 01667 for (unsigned int c=0; c<this->n_children(); c++) 01668 { 01669 const Elem* const current_child = this->child(c); 01670 if (current_child != remote_elem && current_child->has_neighbor(neighbor_in)) 01671 min_p_level = 01672 current_child->min_p_level_by_neighbor(neighbor_in, 01673 min_p_level); 01674 } 01675 01676 return min_p_level; 01677 } 01678 01679 01680 unsigned int Elem::min_new_p_level_by_neighbor(const Elem* neighbor_in, 01681 unsigned int current_min) const 01682 { 01683 libmesh_assert(!this->subactive()); 01684 libmesh_assert(neighbor_in->active()); 01685 01686 // If we're an active element this is simple 01687 if (this->active()) 01688 { 01689 unsigned int new_p_level = this->p_level(); 01690 if (this->p_refinement_flag() == Elem::REFINE) 01691 new_p_level += 1; 01692 if (this->p_refinement_flag() == Elem::COARSEN) 01693 { 01694 libmesh_assert_greater (new_p_level, 0); 01695 new_p_level -= 1; 01696 } 01697 return std::min(current_min, new_p_level); 01698 } 01699 01700 libmesh_assert(has_neighbor(neighbor_in)); 01701 01702 unsigned int min_p_level = current_min; 01703 01704 for (unsigned int c=0; c<this->n_children(); c++) 01705 { 01706 const Elem* const current_child = this->child(c); 01707 if (current_child && current_child != remote_elem) 01708 if (current_child->has_neighbor(neighbor_in)) 01709 min_p_level = 01710 current_child->min_new_p_level_by_neighbor(neighbor_in, 01711 min_p_level); 01712 } 01713 01714 return min_p_level; 01715 } 01716 01717 #endif // #ifdef LIBMESH_ENABLE_AMR 01718 01719 01720 01721 01722 bool Elem::contains_point (const Point& p, Real tol) const 01723 { 01724 // We currently allow the user to enlarge the bounding box by 01725 // providing a tol > TOLERANCE (so this routine is identical to 01726 // Elem::close_to_point()), but print a warning so that the 01727 // user can eventually switch his code over to calling close_to_point() 01728 // instead, which is intended to be used for this purpose. 01729 if ( tol > TOLERANCE ) 01730 { 01731 libmesh_do_once(libMesh::err 01732 << "WARNING: Resizing bounding box to match user-specified tolerance!\n" 01733 << "In the future, calls to Elem::contains_point() with tol > TOLERANCE\n" 01734 << "will be more optimized, but should not be used\n" 01735 << "to search for points 'close to' elements!\n" 01736 << "Instead, use Elem::close_to_point() for this purpose.\n" 01737 << std::endl;); 01738 return this->point_test(p, tol, tol); 01739 } 01740 else 01741 return this->point_test(p, TOLERANCE, tol); 01742 } 01743 01744 01745 01746 01747 bool Elem::close_to_point (const Point& p, Real tol) const 01748 { 01749 // This test uses the user's passed-in tolerance for the 01750 // bounding box test as well, thereby allowing the routine to 01751 // find points which are not only "in" the element, but also 01752 // "nearby" to within some tolerance. 01753 return this->point_test(p, tol, tol); 01754 } 01755 01756 01757 01758 01759 bool Elem::point_test(const Point& p, Real box_tol, Real map_tol) const 01760 { 01761 libmesh_assert_greater (box_tol, 0.); 01762 libmesh_assert_greater (map_tol, 0.); 01763 01764 // This is a great optimization on first order elements, but it 01765 // could return false negatives on higher orders 01766 if (this->default_order() == FIRST) 01767 { 01768 // Check to make sure the element *could* contain this point, so we 01769 // can avoid an expensive inverse_map call if it doesn't. 01770 bool 01771 #if LIBMESH_DIM > 2 01772 point_above_min_z = false, 01773 point_below_max_z = false, 01774 #endif 01775 #if LIBMESH_DIM > 1 01776 point_above_min_y = false, 01777 point_below_max_y = false, 01778 #endif 01779 point_above_min_x = false, 01780 point_below_max_x = false; 01781 01782 // For relative bounding box checks in physical space 01783 const Real my_hmax = this->hmax(); 01784 01785 for (unsigned int n=0; n != this->n_nodes(); ++n) 01786 { 01787 Point pe = this->point(n); 01788 point_above_min_x = point_above_min_x || (pe(0) - my_hmax*box_tol <= p(0)); 01789 point_below_max_x = point_below_max_x || (pe(0) + my_hmax*box_tol >= p(0)); 01790 #if LIBMESH_DIM > 1 01791 point_above_min_y = point_above_min_y || (pe(1) - my_hmax*box_tol <= p(1)); 01792 point_below_max_y = point_below_max_y || (pe(1) + my_hmax*box_tol >= p(1)); 01793 #endif 01794 #if LIBMESH_DIM > 2 01795 point_above_min_z = point_above_min_z || (pe(2) - my_hmax*box_tol <= p(2)); 01796 point_below_max_z = point_below_max_z || (pe(2) + my_hmax*box_tol >= p(2)); 01797 #endif 01798 } 01799 01800 if ( 01801 #if LIBMESH_DIM > 2 01802 !point_above_min_z || 01803 !point_below_max_z || 01804 #endif 01805 #if LIBMESH_DIM > 1 01806 !point_above_min_y || 01807 !point_below_max_y || 01808 #endif 01809 !point_above_min_x || 01810 !point_below_max_x) 01811 return false; 01812 } 01813 01814 // Declare a basic FEType. Will be a Lagrange 01815 // element by default. 01816 FEType fe_type(this->default_order()); 01817 01818 // To be on the safe side, we converge the inverse_map() iteration 01819 // to a slightly tighter tolerance than that requested by the 01820 // user... 01821 const Point mapped_point = FEInterface::inverse_map(this->dim(), 01822 fe_type, 01823 this, 01824 p, 01825 0.1*map_tol, // <- this is |dx| tolerance, the Newton residual should be ~ |dx|^2 01826 /*secure=*/ false); 01827 01828 // Check that the refspace point maps back to p! This is only necessary 01829 // for 1D and 2D elements, 3D elements always live in 3D. 01830 // 01831 // TODO: The contains_point() function could most likely be implemented 01832 // more efficiently in the element sub-classes themselves, at least for 01833 // the linear element types. 01834 if (this->dim() < 3) 01835 { 01836 Point xyz = FEInterface::map(this->dim(), 01837 fe_type, 01838 this, 01839 mapped_point); 01840 01841 // Compute the distance between the original point and the re-mapped point. 01842 // They should be in the same place. 01843 Real dist = (xyz - p).size(); 01844 01845 01846 // If dist is larger than some fraction of the tolerance, then return false. 01847 // This can happen when e.g. a 2D element is living in 3D, and 01848 // FEInterface::inverse_map() maps p onto the projection of the element, 01849 // effectively "tricking" FEInterface::on_reference_element(). 01850 if (dist > this->hmax() * map_tol) 01851 return false; 01852 } 01853 01854 01855 01856 return FEInterface::on_reference_element(mapped_point, this->type(), map_tol); 01857 } 01858 01859 01860 01861 01862 void Elem::print_info (std::ostream& os) const 01863 { 01864 os << this->get_info() 01865 << std::endl; 01866 } 01867 01868 01869 01870 std::string Elem::get_info () const 01871 { 01872 std::ostringstream oss; 01873 01874 oss << " Elem Information" << '\n' 01875 << " id()="; 01876 01877 if (this->valid_id()) 01878 oss << this->id(); 01879 else 01880 oss << "invalid"; 01881 01882 oss << ", processor_id()=" << this->processor_id() << '\n'; 01883 01884 oss << " type()=" << Utility::enum_to_string(this->type()) << '\n' 01885 << " dim()=" << this->dim() << '\n' 01886 << " n_nodes()=" << this->n_nodes() << '\n'; 01887 01888 for (unsigned int n=0; n != this->n_nodes(); ++n) 01889 oss << " " << n << *this->get_node(n); 01890 01891 oss << " n_sides()=" << this->n_sides() << '\n'; 01892 01893 for (unsigned int s=0; s != this->n_sides(); ++s) 01894 { 01895 oss << " neighbor(" << s << ")="; 01896 if (this->neighbor(s)) 01897 oss << this->neighbor(s)->id() << '\n'; 01898 else 01899 oss << "NULL\n"; 01900 } 01901 01902 oss << " hmin()=" << this->hmin() 01903 << ", hmax()=" << this->hmax() << '\n' 01904 << " volume()=" << this->volume() << '\n' 01905 << " active()=" << this->active() 01906 << ", ancestor()=" << this->ancestor() 01907 << ", subactive()=" << this->subactive() 01908 << ", has_children()=" << this->has_children() << '\n' 01909 << " parent()="; 01910 if (this->parent()) 01911 oss << this->parent()->id() << '\n'; 01912 else 01913 oss << "NULL\n"; 01914 oss << " level()=" << this->level() 01915 << ", p_level()=" << this->p_level() << '\n' 01916 #ifdef LIBMESH_ENABLE_AMR 01917 << " refinement_flag()=" << Utility::enum_to_string(this->refinement_flag()) << '\n' 01918 << " p_refinement_flag()=" << Utility::enum_to_string(this->p_refinement_flag()) << '\n' 01919 #endif 01920 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 01921 << " infinite()=" << this->infinite() << '\n'; 01922 if (this->infinite()) 01923 oss << " origin()=" << this->origin() << '\n' 01924 #endif 01925 ; 01926 01927 oss << " DoFs="; 01928 for (unsigned int s=0; s != this->n_systems(); ++s) 01929 for (unsigned int v=0; v != this->n_vars(s); ++v) 01930 for (unsigned int c=0; c != this->n_comp(s,v); ++c) 01931 oss << '(' << s << '/' << v << '/' << this->dof_number(s,v,c) << ") "; 01932 01933 01934 return oss.str(); 01935 } 01936 01937 01938 01939 void Elem::nullify_neighbors () 01940 { 01941 // Tell any of my neighbors about my death... 01942 // Looks strange, huh? 01943 for (unsigned int n=0; n<this->n_neighbors(); n++) 01944 { 01945 Elem* current_neighbor = this->neighbor(n); 01946 if (current_neighbor && current_neighbor != remote_elem) 01947 { 01948 // Note: it is possible that I see the neighbor 01949 // (which is coarser than me) 01950 // but they don't see me, so avoid that case. 01951 if (current_neighbor->level() == this->level()) 01952 { 01953 const unsigned int w_n_a_i = current_neighbor->which_neighbor_am_i(this); 01954 libmesh_assert_less (w_n_a_i, current_neighbor->n_neighbors()); 01955 current_neighbor->set_neighbor(w_n_a_i, NULL); 01956 this->set_neighbor(n, NULL); 01957 } 01958 } 01959 } 01960 } 01961 01962 01963 01964 01965 unsigned int Elem::n_second_order_adjacent_vertices (const unsigned int) const 01966 { 01967 // for linear elements, always return 0 01968 return 0; 01969 } 01970 01971 01972 01973 unsigned short int Elem::second_order_adjacent_vertex (const unsigned int, 01974 const unsigned int) const 01975 { 01976 // for linear elements, always return 0 01977 return 0; 01978 } 01979 01980 01981 01982 std::pair<unsigned short int, unsigned short int> 01983 Elem::second_order_child_vertex (const unsigned int) const 01984 { 01985 // for linear elements, always return 0 01986 return std::pair<unsigned short int, unsigned short int>(0,0); 01987 } 01988 01989 01990 01991 ElemType Elem::first_order_equivalent_type (const ElemType et) 01992 { 01993 switch (et) 01994 { 01995 case EDGE2: 01996 case EDGE3: 01997 case EDGE4: 01998 return EDGE2; 01999 case TRI3: 02000 case TRI6: 02001 return TRI3; 02002 case QUAD4: 02003 case QUAD8: 02004 case QUAD9: 02005 return QUAD4; 02006 case TET4: 02007 case TET10: 02008 return TET4; 02009 case HEX8: 02010 case HEX27: 02011 case HEX20: 02012 return HEX8; 02013 case PRISM6: 02014 case PRISM15: 02015 case PRISM18: 02016 return PRISM6; 02017 case PYRAMID5: 02018 case PYRAMID13: 02019 case PYRAMID14: 02020 return PYRAMID5; 02021 02022 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 02023 02024 case INFQUAD4: 02025 case INFQUAD6: 02026 return INFQUAD4; 02027 case INFHEX8: 02028 case INFHEX16: 02029 case INFHEX18: 02030 return INFHEX8; 02031 case INFPRISM6: 02032 case INFPRISM12: 02033 return INFPRISM6; 02034 02035 #endif 02036 02037 default: 02038 // unknown element 02039 return INVALID_ELEM; 02040 } 02041 } 02042 02043 02044 02045 ElemType Elem::second_order_equivalent_type (const ElemType et, 02046 const bool full_ordered) 02047 { 02048 /* for second-order elements, always return \p INVALID_ELEM 02049 * since second-order elements should not be converted 02050 * into something else. Only linear elements should 02051 * return something sensible here 02052 */ 02053 switch (et) 02054 { 02055 case EDGE2: 02056 { 02057 // full_ordered not relevant 02058 return EDGE3; 02059 } 02060 02061 case TRI3: 02062 { 02063 // full_ordered not relevant 02064 return TRI6; 02065 } 02066 02067 case QUAD4: 02068 { 02069 if (full_ordered) 02070 return QUAD9; 02071 else 02072 return QUAD8; 02073 } 02074 02075 case TET4: 02076 { 02077 // full_ordered not relevant 02078 return TET10; 02079 } 02080 02081 case HEX8: 02082 { 02083 // see below how this correlates with INFHEX8 02084 if (full_ordered) 02085 return HEX27; 02086 else 02087 return HEX20; 02088 } 02089 02090 case PRISM6: 02091 { 02092 if (full_ordered) 02093 return PRISM18; 02094 else 02095 return PRISM15; 02096 } 02097 02098 case PYRAMID5: 02099 { 02100 if (full_ordered) 02101 return PYRAMID14; 02102 else 02103 return PYRAMID13; 02104 02105 return INVALID_ELEM; 02106 } 02107 02108 02109 02110 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 02111 02112 // infinite elements 02113 case INFEDGE2: 02114 { 02115 return INVALID_ELEM; 02116 } 02117 02118 case INFQUAD4: 02119 { 02120 // full_ordered not relevant 02121 return INFQUAD6; 02122 } 02123 02124 case INFHEX8: 02125 { 02126 /* 02127 * Note that this matches with \p Hex8: 02128 * For full-ordered, \p InfHex18 and \p Hex27 02129 * belong together, and for not full-ordered, 02130 * \p InfHex16 and \p Hex20 belong together. 02131 */ 02132 if (full_ordered) 02133 return INFHEX18; 02134 else 02135 return INFHEX16; 02136 } 02137 02138 case INFPRISM6: 02139 { 02140 // full_ordered not relevant 02141 return INFPRISM12; 02142 } 02143 02144 #endif 02145 02146 02147 default: 02148 { 02149 // second-order element 02150 return INVALID_ELEM; 02151 } 02152 } 02153 } 02154 02155 02156 02157 Elem::side_iterator Elem::boundary_sides_begin() 02158 { 02159 Predicates::BoundarySide<SideIter> bsp; 02160 return side_iterator(this->_first_side(), this->_last_side(), bsp); 02161 } 02162 02163 02164 02165 02166 Elem::side_iterator Elem::boundary_sides_end() 02167 { 02168 Predicates::BoundarySide<SideIter> bsp; 02169 return side_iterator(this->_last_side(), this->_last_side(), bsp); 02170 } 02171 02172 02173 02174 02175 Real Elem::volume () const 02176 { 02177 // The default implementation builds a finite element of the correct 02178 // order and sums up the JxW contributions. This can be expensive, 02179 // so the various element types can overload this method and compute 02180 // the volume more efficiently. 02181 FEType fe_type (this->default_order() , LAGRANGE); 02182 02183 UniquePtr<FEBase> fe (FEBase::build(this->dim(), 02184 fe_type)); 02185 02186 const std::vector<Real>& JxW = fe->get_JxW(); 02187 02188 // The default quadrature rule should integrate the mass matrix, 02189 // thus it should be plenty to compute the area 02190 QGauss qrule (this->dim(), fe_type.default_quadrature_order()); 02191 02192 fe->attach_quadrature_rule(&qrule); 02193 02194 fe->reinit(this); 02195 02196 Real vol=0.; 02197 for (unsigned int qp=0; qp<qrule.n_points(); ++qp) 02198 vol += JxW[qp]; 02199 02200 return vol; 02201 02202 } 02203 02204 02205 02206 unsigned int Elem::opposite_side(const unsigned int /*s*/) const 02207 { 02208 // If the subclass didn't rederive this, using it is an error 02209 libmesh_not_implemented(); 02210 } 02211 02212 02213 02214 unsigned int Elem::opposite_node(const unsigned int /*n*/, 02215 const unsigned int /*s*/) const 02216 { 02217 // If the subclass didn't rederive this, using it is an error 02218 libmesh_not_implemented(); 02219 } 02220 02221 } // namespace libMesh