mesh_tools.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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 <limits> 00022 #include <numeric> // for std::accumulate 00023 #include <set> 00024 00025 // Local includes 00026 #include "libmesh/elem.h" 00027 #include "libmesh/elem_range.h" 00028 #include "libmesh/location_maps.h" 00029 #include "libmesh/mesh_base.h" 00030 #include "libmesh/mesh_communication.h" 00031 #include "libmesh/mesh_tools.h" 00032 #include "libmesh/node_range.h" 00033 #include "libmesh/parallel.h" 00034 #include "libmesh/parallel_mesh.h" 00035 #include "libmesh/serial_mesh.h" 00036 #include "libmesh/sphere.h" 00037 #include "libmesh/threads.h" 00038 00039 #ifdef DEBUG 00040 # include "libmesh/remote_elem.h" 00041 #endif 00042 00043 00044 00045 // ------------------------------------------------------------ 00046 // anonymous namespace for helper classes 00047 namespace { 00048 00049 using namespace libMesh; 00050 00058 class SumElemWeight 00059 { 00060 public: 00061 SumElemWeight () : 00062 _weight(0) 00063 {} 00064 00065 SumElemWeight (SumElemWeight &, Threads::split) : 00066 _weight(0) 00067 {} 00068 00069 void operator()(const ConstElemRange &range) 00070 { 00071 for (ConstElemRange::const_iterator it = range.begin(); it !=range.end(); ++it) 00072 _weight += (*it)->n_nodes(); 00073 } 00074 00075 dof_id_type weight() const 00076 { return _weight; } 00077 00078 // If we don't have threads we never need a join, and icpc yells a 00079 // warning if it sees an anonymous function that's never used 00080 #ifdef LIBMESH_HAVE_TBB_API 00081 void join (const SumElemWeight &other) 00082 { _weight += other.weight(); } 00083 #endif 00084 00085 private: 00086 dof_id_type _weight; 00087 }; 00088 00089 00096 class FindBBox 00097 { 00098 public: 00099 FindBBox () : 00100 _vmin(LIBMESH_DIM, std::numeric_limits<Real>::max()), 00101 _vmax(LIBMESH_DIM, -std::numeric_limits<Real>::max()) 00102 {} 00103 00104 FindBBox (FindBBox &other, Threads::split) : 00105 _vmin(other._vmin), 00106 _vmax(other._vmax) 00107 {} 00108 00109 std::vector<Real> & min() { return _vmin; } 00110 std::vector<Real> & max() { return _vmax; } 00111 00112 void operator()(const ConstNodeRange &range) 00113 { 00114 for (ConstNodeRange::const_iterator it = range.begin(); it != range.end(); ++it) 00115 { 00116 const Node *node = *it; 00117 libmesh_assert(node); 00118 00119 for (unsigned int i=0; i<LIBMESH_DIM; i++) 00120 { 00121 _vmin[i] = std::min(_vmin[i], (*node)(i)); 00122 _vmax[i] = std::max(_vmax[i], (*node)(i)); 00123 } 00124 } 00125 } 00126 00127 void operator()(const ConstElemRange &range) 00128 { 00129 for (ConstElemRange::const_iterator it = range.begin(); it != range.end(); ++it) 00130 { 00131 const Elem *elem = *it; 00132 libmesh_assert(elem); 00133 00134 for (unsigned int n=0; n<elem->n_nodes(); n++) 00135 { 00136 const Point &point = elem->point(n); 00137 00138 for (unsigned int i=0; i<LIBMESH_DIM; i++) 00139 { 00140 _vmin[i] = std::min(_vmin[i], point(i)); 00141 _vmax[i] = std::max(_vmax[i], point(i)); 00142 } 00143 } 00144 } 00145 } 00146 00147 // If we don't have threads we never need a join, and icpc yells a 00148 // warning if it sees an anonymous function that's never used 00149 #ifdef LIBMESH_HAVE_TBB_API 00150 void join (const FindBBox &other) 00151 { 00152 for (unsigned int i=0; i<LIBMESH_DIM; i++) 00153 { 00154 _vmin[i] = std::min(_vmin[i], other._vmin[i]); 00155 _vmax[i] = std::max(_vmax[i], other._vmax[i]); 00156 } 00157 } 00158 #endif 00159 00160 MeshTools::BoundingBox bbox () const 00161 { 00162 Point pmin(_vmin[0] 00163 #if LIBMESH_DIM > 1 00164 , _vmin[1] 00165 #endif 00166 #if LIBMESH_DIM > 2 00167 , _vmin[2] 00168 #endif 00169 ); 00170 Point pmax(_vmax[0] 00171 #if LIBMESH_DIM > 1 00172 , _vmax[1] 00173 #endif 00174 #if LIBMESH_DIM > 2 00175 , _vmax[2] 00176 #endif 00177 ); 00178 00179 const MeshTools::BoundingBox ret_val(pmin, pmax); 00180 00181 return ret_val; 00182 } 00183 00184 private: 00185 std::vector<Real> _vmin; 00186 std::vector<Real> _vmax; 00187 }; 00188 00189 #ifdef DEBUG 00190 void assert_semiverify_dofobj(const DofObject *d) 00191 { 00192 if (d) 00193 { 00194 const unsigned int n_sys = d->n_systems(); 00195 00196 std::vector<unsigned int> n_vars (n_sys, 0); 00197 for (unsigned int s = 0; s != n_sys; ++s) 00198 n_vars[s] = d->n_vars(s); 00199 00200 const unsigned int tot_n_vars = 00201 std::accumulate(n_vars.begin(), n_vars.end(), 0); 00202 00203 std::vector<unsigned int> n_comp (tot_n_vars, 0); 00204 std::vector<dof_id_type> first_dof (tot_n_vars, 0); 00205 00206 for (unsigned int s = 0, i=0; s != n_sys; ++s) 00207 for (unsigned int v = 0; v != n_vars[s]; ++v, ++i) 00208 { 00209 n_comp[i] = d->n_comp(s,v); 00210 first_dof[i] = n_comp[i] ? d->dof_number(s,v,0) : libMesh::invalid_uint; 00211 } 00212 00213 libmesh_assert(CommWorld.semiverify(&n_sys)); 00214 libmesh_assert(CommWorld.semiverify(&n_vars)); 00215 libmesh_assert(CommWorld.semiverify(&n_comp)); 00216 libmesh_assert(CommWorld.semiverify(&first_dof)); 00217 } 00218 else 00219 { 00220 const unsigned int* p_ui = NULL; 00221 const std::vector<unsigned int>* p_vui = NULL; 00222 00223 libmesh_assert(CommWorld.semiverify(p_ui)); 00224 libmesh_assert(CommWorld.semiverify(p_vui)); 00225 libmesh_assert(CommWorld.semiverify(p_vui)); 00226 libmesh_assert(CommWorld.semiverify(p_vui)); 00227 } 00228 } 00229 #endif // DEBUG 00230 00231 } 00232 00233 00234 namespace libMesh 00235 { 00236 // Small helper function to make intersect more readable. 00237 bool is_between(Real min, Real check, Real max) 00238 { 00239 return min <= check && check <= max; 00240 } 00241 00242 bool MeshTools::BoundingBox::intersect (const BoundingBox & other_box) const 00243 { 00244 // Make local variables first to make thiings more clear in a moment 00245 const Real& my_min_x = this->first(0); 00246 const Real& my_max_x = this->second(0); 00247 const Real& other_min_x = other_box.first(0); 00248 const Real& other_max_x = other_box.second(0); 00249 00250 const bool x_int = is_between(my_min_x, other_min_x, my_max_x) || is_between(my_min_x, other_max_x, my_max_x) || 00251 is_between(other_min_x, my_min_x, other_max_x) || is_between(other_min_x, my_max_x, other_max_x); 00252 00253 bool intersection_true = x_int; 00254 00255 #if LIBMESH_DIM > 1 00256 const Real& my_min_y = this->first(1); 00257 const Real& my_max_y = this->second(1); 00258 const Real& other_min_y = other_box.first(1); 00259 const Real& other_max_y = other_box.second(1); 00260 00261 const bool y_int = is_between(my_min_y, other_min_y, my_max_y) || is_between(my_min_y, other_max_y, my_max_y) || 00262 is_between(other_min_y, my_min_y, other_max_y) || is_between(other_min_y, my_max_y, other_max_y); 00263 00264 intersection_true = intersection_true && y_int; 00265 #endif 00266 00267 #if LIBMESH_DIM > 2 00268 const Real& my_min_z = this->first(2); 00269 const Real& my_max_z = this->second(2); 00270 const Real& other_min_z = other_box.first(2); 00271 const Real& other_max_z = other_box.second(2); 00272 00273 const bool z_int = is_between(my_min_z, other_min_z, my_max_z) || is_between(my_min_z, other_max_z, my_max_z) || 00274 is_between(other_min_z, my_min_z, other_max_z) || is_between(other_min_z, my_max_z, other_max_z); 00275 00276 intersection_true = intersection_true && z_int; 00277 #endif 00278 00279 return intersection_true; 00280 } 00281 00282 bool MeshTools::BoundingBox::contains_point (const Point & p) const 00283 { 00284 // Make local variables first to make thiings more clear in a moment 00285 Real my_min_x = this->first(0); 00286 Real my_max_x = this->second(0); 00287 bool x_int = is_between(my_min_x, p(0), my_max_x); 00288 00289 bool intersection_true = x_int; 00290 00291 #if LIBMESH_DIM > 1 00292 Real my_min_y = this->first(1); 00293 Real my_max_y = this->second(1); 00294 bool y_int = is_between(my_min_y, p(1), my_max_y); 00295 00296 intersection_true = intersection_true && y_int; 00297 #endif 00298 00299 00300 #if LIBMESH_DIM > 2 00301 Real my_min_z = this->first(2); 00302 Real my_max_z = this->second(2); 00303 bool z_int = is_between(my_min_z, p(2), my_max_z); 00304 00305 intersection_true = intersection_true && z_int; 00306 #endif 00307 00308 return intersection_true; 00309 } 00310 00311 // ------------------------------------------------------------ 00312 // MeshTools functions 00313 dof_id_type MeshTools::total_weight(const MeshBase& mesh) 00314 { 00315 if (!mesh.is_serial()) 00316 { 00317 parallel_only(); 00318 dof_id_type weight = MeshTools::weight (mesh, libMesh::processor_id()); 00319 CommWorld.sum(weight); 00320 dof_id_type unpartitioned_weight = 00321 MeshTools::weight (mesh, DofObject::invalid_processor_id); 00322 return weight + unpartitioned_weight; 00323 } 00324 00325 SumElemWeight sew; 00326 00327 Threads::parallel_reduce (ConstElemRange (mesh.elements_begin(), 00328 mesh.elements_end()), 00329 sew); 00330 return sew.weight(); 00331 00332 } 00333 00334 00335 00336 dof_id_type MeshTools::weight(const MeshBase& mesh, const processor_id_type pid) 00337 { 00338 SumElemWeight sew; 00339 00340 Threads::parallel_reduce (ConstElemRange (mesh.pid_elements_begin(pid), 00341 mesh.pid_elements_end(pid)), 00342 sew); 00343 return sew.weight(); 00344 } 00345 00346 00347 00348 void MeshTools::build_nodes_to_elem_map (const MeshBase& mesh, 00349 std::vector<std::vector<dof_id_type> >& nodes_to_elem_map) 00350 { 00351 nodes_to_elem_map.resize (mesh.n_nodes()); 00352 00353 MeshBase::const_element_iterator el = mesh.elements_begin(); 00354 const MeshBase::const_element_iterator end = mesh.elements_end(); 00355 00356 for (; el != end; ++el) 00357 for (unsigned int n=0; n<(*el)->n_nodes(); n++) 00358 { 00359 libmesh_assert_less ((*el)->node(n), nodes_to_elem_map.size()); 00360 libmesh_assert_less ((*el)->id(), mesh.n_elem()); 00361 00362 nodes_to_elem_map[(*el)->node(n)].push_back((*el)->id()); 00363 } 00364 } 00365 00366 00367 00368 void MeshTools::build_nodes_to_elem_map (const MeshBase& mesh, 00369 std::vector<std::vector<const Elem*> >& nodes_to_elem_map) 00370 { 00371 nodes_to_elem_map.resize (mesh.n_nodes()); 00372 00373 MeshBase::const_element_iterator el = mesh.elements_begin(); 00374 const MeshBase::const_element_iterator end = mesh.elements_end(); 00375 00376 for (; el != end; ++el) 00377 for (unsigned int n=0; n<(*el)->n_nodes(); n++) 00378 { 00379 libmesh_assert_less ((*el)->node(n), nodes_to_elem_map.size()); 00380 00381 nodes_to_elem_map[(*el)->node(n)].push_back(*el); 00382 } 00383 } 00384 00385 00386 00387 void MeshTools::find_boundary_nodes (const MeshBase& mesh, 00388 std::vector<bool>& on_boundary) 00389 { 00390 // Resize the vector which holds boundary nodes and fill with false. 00391 on_boundary.resize(mesh.n_nodes()); 00392 std::fill(on_boundary.begin(), 00393 on_boundary.end(), 00394 false); 00395 00396 // Loop over elements, find those on boundary, and 00397 // mark them as true in on_boundary. 00398 MeshBase::const_element_iterator el = mesh.active_elements_begin(); 00399 const MeshBase::const_element_iterator end = mesh.active_elements_end(); 00400 00401 for (; el != end; ++el) 00402 for (unsigned int s=0; s<(*el)->n_neighbors(); s++) 00403 if ((*el)->neighbor(s) == NULL) // on the boundary 00404 { 00405 const AutoPtr<Elem> side((*el)->build_side(s)); 00406 00407 for (unsigned int n=0; n<side->n_nodes(); n++) 00408 on_boundary[side->node(n)] = true; 00409 } 00410 } 00411 00412 00413 00414 MeshTools::BoundingBox 00415 MeshTools::bounding_box(const MeshBase& mesh) 00416 { 00417 // This function must be run on all processors at once 00418 parallel_only(); 00419 00420 FindBBox find_bbox; 00421 00422 Threads::parallel_reduce (ConstNodeRange (mesh.local_nodes_begin(), 00423 mesh.local_nodes_end()), 00424 find_bbox); 00425 00426 // and the unpartitioned nodes 00427 Threads::parallel_reduce (ConstNodeRange (mesh.pid_nodes_begin(DofObject::invalid_processor_id), 00428 mesh.pid_nodes_end(DofObject::invalid_processor_id)), 00429 find_bbox); 00430 00431 // Compare the bounding boxes across processors 00432 CommWorld.min(find_bbox.min()); 00433 CommWorld.max(find_bbox.max()); 00434 00435 return find_bbox.bbox(); 00436 } 00437 00438 00439 00440 Sphere 00441 MeshTools::bounding_sphere(const MeshBase& mesh) 00442 { 00443 BoundingBox bbox = bounding_box(mesh); 00444 00445 const Real diag = (bbox.second - bbox.first).size(); 00446 const Point cent = (bbox.second + bbox.first)/2; 00447 00448 return Sphere (cent, .5*diag); 00449 } 00450 00451 00452 00453 MeshTools::BoundingBox 00454 MeshTools::processor_bounding_box (const MeshBase& mesh, 00455 const processor_id_type pid) 00456 { 00457 libmesh_assert_less (pid, libMesh::n_processors()); 00458 00459 FindBBox find_bbox; 00460 00461 Threads::parallel_reduce (ConstElemRange (mesh.pid_elements_begin(pid), 00462 mesh.pid_elements_end(pid)), 00463 find_bbox); 00464 00465 return find_bbox.bbox(); 00466 } 00467 00468 00469 00470 Sphere 00471 MeshTools::processor_bounding_sphere (const MeshBase& mesh, 00472 const processor_id_type pid) 00473 { 00474 BoundingBox bbox = processor_bounding_box(mesh,pid); 00475 00476 const Real diag = (bbox.second - bbox.first).size(); 00477 const Point cent = (bbox.second + bbox.first)/2; 00478 00479 return Sphere (cent, .5*diag); 00480 } 00481 00482 00483 00484 MeshTools::BoundingBox 00485 MeshTools::subdomain_bounding_box (const MeshBase& mesh, 00486 const subdomain_id_type sid) 00487 { 00488 libmesh_assert_not_equal_to (mesh.n_nodes(), 0); 00489 00490 Point min( 1.e30, 1.e30, 1.e30); 00491 Point max(-1.e30, -1.e30, -1.e30); 00492 00493 for (unsigned int e=0; e<mesh.n_elem(); e++) 00494 if (mesh.elem(e)->subdomain_id() == sid) 00495 for (unsigned int n=0; n<mesh.elem(e)->n_nodes(); n++) 00496 for (unsigned int i=0; i<mesh.spatial_dimension(); i++) 00497 { 00498 min(i) = std::min(min(i), mesh.point(mesh.elem(e)->node(n))(i)); 00499 max(i) = std::max(max(i), mesh.point(mesh.elem(e)->node(n))(i)); 00500 } 00501 00502 return BoundingBox (min, max); 00503 } 00504 00505 00506 00507 Sphere 00508 MeshTools::subdomain_bounding_sphere (const MeshBase& mesh, 00509 const subdomain_id_type sid) 00510 { 00511 BoundingBox bbox = subdomain_bounding_box(mesh,sid); 00512 00513 const Real diag = (bbox.second - bbox.first).size(); 00514 const Point cent = (bbox.second + bbox.first)/2; 00515 00516 return Sphere (cent, .5*diag); 00517 } 00518 00519 00520 00521 void MeshTools::elem_types (const MeshBase& mesh, 00522 std::vector<ElemType>& et) 00523 { 00524 MeshBase::const_element_iterator el = mesh.elements_begin(); 00525 const MeshBase::const_element_iterator end = mesh.elements_end(); 00526 00527 // Automatically get the first type 00528 et.push_back((*el)->type()); ++el; 00529 00530 // Loop over the rest of the elements. 00531 // If the current element type isn't in the 00532 // vector, insert it. 00533 for (; el != end; ++el) 00534 if (!std::count(et.begin(), et.end(), (*el)->type())) 00535 et.push_back((*el)->type()); 00536 } 00537 00538 00539 00540 dof_id_type MeshTools::n_elem_of_type (const MeshBase& mesh, 00541 const ElemType type) 00542 { 00543 return static_cast<dof_id_type>(std::distance(mesh.type_elements_begin(type), 00544 mesh.type_elements_end (type))); 00545 } 00546 00547 00548 00549 dof_id_type MeshTools::n_active_elem_of_type (const MeshBase& mesh, 00550 const ElemType type) 00551 { 00552 return static_cast<dof_id_type>(std::distance(mesh.active_type_elements_begin(type), 00553 mesh.active_type_elements_end (type))); 00554 } 00555 00556 dof_id_type MeshTools::n_non_subactive_elem_of_type_at_level(const MeshBase& mesh, 00557 const ElemType type, 00558 const unsigned int level) 00559 { 00560 dof_id_type cnt = 0; 00561 // iterate over the elements of the specified type 00562 MeshBase::const_element_iterator el = mesh.type_elements_begin(type); 00563 const MeshBase::const_element_iterator end = mesh.type_elements_end(type); 00564 00565 for(; el!=end; ++el) 00566 if( ((*el)->level() == level) && !(*el)->subactive()) 00567 cnt++; 00568 00569 return cnt; 00570 } 00571 00572 00573 unsigned int MeshTools::n_active_local_levels(const MeshBase& mesh) 00574 { 00575 unsigned int max_level = 0; 00576 00577 MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); 00578 const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); 00579 00580 for( ; el != end_el; ++el) 00581 max_level = std::max((*el)->level(), max_level); 00582 00583 return max_level + 1; 00584 } 00585 00586 00587 00588 unsigned int MeshTools::n_active_levels(const MeshBase& mesh) 00589 { 00590 parallel_only(); 00591 00592 unsigned int nl = MeshTools::n_active_local_levels(mesh); 00593 00594 MeshBase::const_element_iterator el = 00595 mesh.unpartitioned_elements_begin(); 00596 const MeshBase::const_element_iterator end_el = 00597 mesh.unpartitioned_elements_end(); 00598 00599 for( ; el != end_el; ++el) 00600 if ((*el)->active()) 00601 nl = std::max((*el)->level() + 1, nl); 00602 00603 CommWorld.max(nl); 00604 return nl; 00605 } 00606 00607 00608 00609 unsigned int MeshTools::n_local_levels(const MeshBase& mesh) 00610 { 00611 unsigned int max_level = 0; 00612 00613 MeshBase::const_element_iterator el = mesh.local_elements_begin(); 00614 const MeshBase::const_element_iterator end_el = mesh.local_elements_end(); 00615 00616 for( ; el != end_el; ++el) 00617 max_level = std::max((*el)->level(), max_level); 00618 00619 return max_level + 1; 00620 } 00621 00622 00623 00624 unsigned int MeshTools::n_levels(const MeshBase& mesh) 00625 { 00626 parallel_only(); 00627 00628 unsigned int nl = MeshTools::n_local_levels(mesh); 00629 00630 MeshBase::const_element_iterator el = 00631 mesh.unpartitioned_elements_begin(); 00632 const MeshBase::const_element_iterator end_el = 00633 mesh.unpartitioned_elements_end(); 00634 00635 for( ; el != end_el; ++el) 00636 nl = std::max((*el)->level() + 1, nl); 00637 00638 CommWorld.max(nl); 00639 return nl; 00640 } 00641 00642 00643 00644 void MeshTools::get_not_subactive_node_ids(const MeshBase& mesh, 00645 std::set<dof_id_type>& not_subactive_node_ids) 00646 { 00647 MeshBase::const_element_iterator el = mesh.elements_begin(); 00648 const MeshBase::const_element_iterator end_el = mesh.elements_end(); 00649 for( ; el != end_el; ++el) 00650 { 00651 const Elem* elem = (*el); 00652 if(!elem->subactive()) 00653 for (unsigned int n=0; n<elem->n_nodes(); ++n) 00654 not_subactive_node_ids.insert(elem->node(n)); 00655 } 00656 } 00657 00658 00659 00660 dof_id_type MeshTools::n_elem (const MeshBase::const_element_iterator &begin, 00661 const MeshBase::const_element_iterator &end) 00662 { 00663 return std::distance(begin, end); 00664 } 00665 00666 00667 00668 dof_id_type MeshTools::n_nodes (const MeshBase::const_node_iterator &begin, 00669 const MeshBase::const_node_iterator &end) 00670 { 00671 return std::distance(begin, end); 00672 } 00673 00674 00675 00676 unsigned int MeshTools::n_p_levels (const MeshBase& mesh) 00677 { 00678 parallel_only(); 00679 00680 unsigned int max_p_level = 0; 00681 00682 // first my local elements 00683 MeshBase::const_element_iterator 00684 el = mesh.local_elements_begin(), 00685 end_el = mesh.local_elements_end(); 00686 00687 for( ; el != end_el; ++el) 00688 max_p_level = std::max((*el)->p_level(), max_p_level); 00689 00690 // then any unpartitioned objects 00691 el = mesh.unpartitioned_elements_begin(); 00692 end_el = mesh.unpartitioned_elements_end(); 00693 00694 for( ; el != end_el; ++el) 00695 max_p_level = std::max((*el)->p_level(), max_p_level); 00696 00697 CommWorld.max(max_p_level); 00698 return max_p_level + 1; 00699 } 00700 00701 00702 00703 void MeshTools::find_nodal_neighbors(const MeshBase&, const Node& n, 00704 std::vector<std::vector<const Elem*> >& nodes_to_elem_map, 00705 std::vector<const Node*>& neighbors) 00706 { 00707 dof_id_type global_id = n.id(); 00708 00709 //Iterators to iterate through the elements that include this node 00710 std::vector<const Elem*>::const_iterator el = nodes_to_elem_map[global_id].begin(); 00711 std::vector<const Elem*>::const_iterator end_el = nodes_to_elem_map[global_id].end(); 00712 00713 unsigned int n_ed=0; // Number of edges on the element 00714 unsigned int ed=0; // Current edge 00715 unsigned int l_n=0; // Local node number 00716 unsigned int o_n=0; // Other node on this edge 00717 00718 //Assume we find a edge... then prove ourselves wrong... 00719 bool found_edge=true; 00720 00721 Node * node_to_save = NULL; 00722 00723 //Look through the elements that contain this node 00724 //find the local node id... then find the side that 00725 //node lives on in the element 00726 //next, look for the _other_ node on that side 00727 //That other node is a "nodal_neighbor"... save it 00728 for(;el != end_el;el++) 00729 { 00730 //We only care about active elements... 00731 if((*el)->active()) 00732 { 00733 n_ed=(*el)->n_edges(); 00734 00735 //Find the local node id 00736 while(global_id != (*el)->node(l_n++)) { } 00737 l_n--; //Hmmm... take the last one back off 00738 00739 while(ed<n_ed) 00740 { 00741 00742 //Find the edge the node is on 00743 while(found_edge && !(*el)->is_node_on_edge(l_n,ed++)) 00744 { 00745 //This only happens if all the edges have already been found 00746 if(ed>=n_ed) 00747 found_edge=false; 00748 } 00749 00750 //Did we find one? 00751 if(found_edge) 00752 { 00753 ed--; //Take the last one back off again 00754 00755 //Now find the other node on that edge 00756 while(!(*el)->is_node_on_edge(o_n++,ed) || global_id==(*el)->node(o_n-1)) { } 00757 o_n--; 00758 00759 //We've found one! Save it.. 00760 node_to_save=(*el)->get_node(o_n); 00761 00762 //Search to see if we've already found this one 00763 std::vector<const Node*>::const_iterator result = std::find(neighbors.begin(),neighbors.end(),node_to_save); 00764 00765 //If we didn't find it and add it to the vector 00766 if(result == neighbors.end()) 00767 neighbors.push_back(node_to_save); 00768 } 00769 00770 //Reset to look for another 00771 o_n=0; 00772 00773 //Keep looking for edges, node may be on more than one edge 00774 ed++; 00775 } 00776 00777 //Reset to get ready for the next element 00778 l_n=ed=0; 00779 found_edge=true; 00780 } 00781 } 00782 } 00783 00784 void MeshTools::find_hanging_nodes_and_parents(const MeshBase& mesh, std::map<dof_id_type, std::vector<dof_id_type> >& hanging_nodes) 00785 { 00786 MeshBase::const_element_iterator it = mesh.active_local_elements_begin(); 00787 const MeshBase::const_element_iterator end = mesh.active_local_elements_end(); 00788 00789 //Loop through all the elements 00790 for (; it != end; ++it) 00791 { 00792 //Save it off for easier access 00793 const Elem* elem = (*it); 00794 00795 //Right now this only works for quad4's 00796 //libmesh_assert_equal_to (elem->type(), libMeshEnums::QUAD4); 00797 if(elem->type() == libMeshEnums::QUAD4) 00798 { 00799 //Loop over the sides looking for sides that have hanging nodes 00800 //This code is inspired by compute_proj_constraints() 00801 for (unsigned int s=0; s<elem->n_sides(); s++) 00802 { 00803 //If not a boundary node 00804 if (elem->neighbor(s) != NULL) 00805 { 00806 // Get pointers to the element's neighbor. 00807 const Elem* neigh = elem->neighbor(s); 00808 00809 //Is there a coarser element next to this one? 00810 if (neigh->level() < elem->level()) 00811 { 00812 const Elem *ancestor = elem; 00813 while (neigh->level() < ancestor->level()) 00814 ancestor = ancestor->parent(); 00815 unsigned int s_neigh = neigh->which_neighbor_am_i(ancestor); 00816 libmesh_assert_less (s_neigh, neigh->n_neighbors()); 00817 00818 //Couple of helper uints... 00819 unsigned int local_node1=0; 00820 unsigned int local_node2=0; 00821 00822 bool found_in_neighbor = false; 00823 00824 //Find the two vertices that make up this side 00825 while(!elem->is_node_on_side(local_node1++,s)) { } 00826 local_node1--; 00827 00828 //Start looking for the second one with the next node 00829 local_node2=local_node1+1; 00830 00831 //Find the other one 00832 while(!elem->is_node_on_side(local_node2++,s)) { } 00833 local_node2--; 00834 00835 //Pull out their global ids: 00836 dof_id_type node1 = elem->node(local_node1); 00837 dof_id_type node2 = elem->node(local_node2); 00838 00839 //Now find which node is present in the neighbor 00840 //FIXME This assumes a level one rule! 00841 //The _other_ one is the hanging node 00842 00843 //First look for the first one 00844 //FIXME could be streamlined a bit 00845 for(unsigned int n=0;n<neigh->n_sides();n++) 00846 { 00847 if(neigh->node(n) == node1) 00848 found_in_neighbor=true; 00849 } 00850 00851 dof_id_type hanging_node=0; 00852 00853 if(!found_in_neighbor) 00854 hanging_node=node1; 00855 else //If it wasn't node1 then it must be node2! 00856 hanging_node=node2; 00857 00858 //Reset these for reuse 00859 local_node1=0; 00860 local_node2=0; 00861 00862 //Find the first node that makes up the side in the neighbor (these should be the parent nodes) 00863 while(!neigh->is_node_on_side(local_node1++,s_neigh)) { } 00864 local_node1--; 00865 00866 local_node2=local_node1+1; 00867 00868 //Find the second node... 00869 while(!neigh->is_node_on_side(local_node2++,s_neigh)) { } 00870 local_node2--; 00871 00872 //Save them if we haven't already found the parents for this one 00873 if(hanging_nodes[hanging_node].size()<2) 00874 { 00875 hanging_nodes[hanging_node].push_back(neigh->node(local_node1)); 00876 hanging_nodes[hanging_node].push_back(neigh->node(local_node2)); 00877 } 00878 } 00879 } 00880 } 00881 } 00882 } 00883 } 00884 00885 00886 00887 void MeshTools::correct_node_proc_ids 00888 (MeshBase &mesh, 00889 LocationMap<Node> &loc_map) 00890 { 00891 // This function must be run on all processors at once 00892 parallel_only(); 00893 00894 // We'll need the new_nodes_map to answer other processors' 00895 // requests. It should never be empty unless we don't have any 00896 // nodes. 00897 libmesh_assert(mesh.nodes_begin() == mesh.nodes_end() || 00898 !loc_map.empty()); 00899 00900 // Fix all nodes' processor ids. Coarsening may have left us with 00901 // nodes which are no longer touched by any elements of the same 00902 // processor id, and for DofMap to work we need to fix that. 00903 00904 // In the first pass, invalidate processor ids for nodes on active 00905 // elements. We avoid touching subactive-only nodes. 00906 MeshBase::element_iterator e_it = mesh.active_elements_begin(); 00907 const MeshBase::element_iterator e_end = mesh.active_elements_end(); 00908 for (; e_it != e_end; ++e_it) 00909 { 00910 Elem *elem = *e_it; 00911 for (unsigned int n=0; n != elem->n_nodes(); ++n) 00912 { 00913 Node *node = elem->get_node(n); 00914 node->invalidate_processor_id(); 00915 } 00916 } 00917 00918 // In the second pass, find the lowest processor ids on active 00919 // elements touching each node, and set the node processor id. 00920 for (e_it = mesh.active_elements_begin(); e_it != e_end; ++e_it) 00921 { 00922 Elem *elem = *e_it; 00923 processor_id_type proc_id = elem->processor_id(); 00924 for (unsigned int n=0; n != elem->n_nodes(); ++n) 00925 { 00926 Node *node = elem->get_node(n); 00927 if (node->processor_id() == DofObject::invalid_processor_id || 00928 node->processor_id() > proc_id) 00929 node->processor_id() = proc_id; 00930 } 00931 } 00932 00933 // Those two passes will correct every node that touches a local 00934 // element, but we can't be sure about nodes touching remote 00935 // elements. Fix those now. 00936 MeshCommunication().make_node_proc_ids_parallel_consistent 00937 (mesh, loc_map); 00938 } 00939 00940 00941 00942 #ifdef DEBUG 00943 void MeshTools::libmesh_assert_equal_n_systems (const MeshBase &mesh) 00944 { 00945 MeshBase::const_element_iterator el = 00946 mesh.elements_begin(); 00947 const MeshBase::const_element_iterator el_end = 00948 mesh.elements_end(); 00949 if (el == el_end) 00950 return; 00951 00952 const unsigned int n_sys = (*el)->n_systems(); 00953 00954 for (; el != el_end; ++el) 00955 { 00956 const Elem *elem = *el; 00957 libmesh_assert_equal_to (elem->n_systems(), n_sys); 00958 } 00959 00960 MeshBase::const_node_iterator node_it = 00961 mesh.nodes_begin(); 00962 const MeshBase::const_node_iterator node_end = 00963 mesh.nodes_end(); 00964 00965 if (node_it == node_end) 00966 return; 00967 00968 for (; node_it != node_end; ++node_it) 00969 { 00970 const Node *node = *node_it; 00971 libmesh_assert_equal_to (node->n_systems(), n_sys); 00972 } 00973 } 00974 00975 00976 00977 void MeshTools::libmesh_assert_old_dof_objects (const MeshBase &mesh) 00978 { 00979 #ifdef LIBMESH_ENABLE_AMR 00980 MeshBase::const_element_iterator el = 00981 mesh.elements_begin(); 00982 const MeshBase::const_element_iterator el_end = 00983 mesh.elements_end(); 00984 00985 for (; el != el_end; ++el) 00986 { 00987 const Elem *elem = *el; 00988 00989 if (elem->refinement_flag() == Elem::JUST_REFINED || 00990 elem->refinement_flag() == Elem::INACTIVE) 00991 continue; 00992 00993 if (elem->has_dofs()) 00994 libmesh_assert(elem->old_dof_object); 00995 00996 for (unsigned int n=0; n != elem->n_nodes(); ++n) 00997 { 00998 const Node *node = elem->get_node(n); 00999 if (node->has_dofs()) 01000 libmesh_assert(elem->get_node(n)->old_dof_object); 01001 } 01002 } 01003 #endif // LIBMESH_ENABLE_AMR 01004 } 01005 01006 01007 01008 void MeshTools::libmesh_assert_valid_node_pointers(const MeshBase &mesh) 01009 { 01010 const MeshBase::const_element_iterator el_end = 01011 mesh.elements_end(); 01012 for (MeshBase::const_element_iterator el = 01013 mesh.elements_begin(); el != el_end; ++el) 01014 { 01015 const Elem* elem = *el; 01016 libmesh_assert (elem); 01017 while (elem) 01018 { 01019 elem->libmesh_assert_valid_node_pointers(); 01020 for (unsigned int n=0; n != elem->n_neighbors(); ++n) 01021 if (elem->neighbor(n) && 01022 elem->neighbor(n) != remote_elem) 01023 elem->neighbor(n)->libmesh_assert_valid_node_pointers(); 01024 01025 libmesh_assert_not_equal_to (elem->parent(), remote_elem); 01026 elem = elem->parent(); 01027 } 01028 } 01029 } 01030 01031 01032 void MeshTools::libmesh_assert_valid_remote_elems(const MeshBase &mesh) 01033 { 01034 const MeshBase::const_element_iterator el_end = 01035 mesh.local_elements_end(); 01036 for (MeshBase::const_element_iterator el = 01037 mesh.local_elements_begin(); el != el_end; ++el) 01038 { 01039 const Elem* elem = *el; 01040 libmesh_assert (elem); 01041 for (unsigned int n=0; n != elem->n_neighbors(); ++n) 01042 libmesh_assert_not_equal_to (elem->neighbor(n), remote_elem); 01043 #ifdef LIBMESH_ENABLE_AMR 01044 const Elem* parent = elem->parent(); 01045 if (parent) 01046 { 01047 libmesh_assert_not_equal_to (parent, remote_elem); 01048 for (unsigned int c=0; c != elem->n_children(); ++c) 01049 libmesh_assert_not_equal_to (parent->child(c), remote_elem); 01050 } 01051 #endif 01052 } 01053 } 01054 01055 01056 void MeshTools::libmesh_assert_no_links_to_elem(const MeshBase &mesh, 01057 const Elem *bad_elem) 01058 { 01059 const MeshBase::const_element_iterator el_end = 01060 mesh.elements_end(); 01061 for (MeshBase::const_element_iterator el = 01062 mesh.elements_begin(); el != el_end; ++el) 01063 { 01064 const Elem* elem = *el; 01065 libmesh_assert (elem); 01066 libmesh_assert_not_equal_to (elem->parent(), bad_elem); 01067 for (unsigned int n=0; n != elem->n_neighbors(); ++n) 01068 libmesh_assert_not_equal_to (elem->neighbor(n), bad_elem); 01069 #ifdef LIBMESH_ENABLE_AMR 01070 if (elem->has_children()) 01071 for (unsigned int c=0; c != elem->n_children(); ++c) 01072 libmesh_assert_not_equal_to (elem->child(c), bad_elem); 01073 #endif 01074 } 01075 } 01076 01077 01078 01079 void MeshTools::libmesh_assert_valid_elem_ids(const MeshBase &mesh) 01080 { 01081 processor_id_type lastprocid = 0; 01082 dof_id_type lastelemid = 0; 01083 01084 const MeshBase::const_element_iterator el_end = 01085 mesh.active_elements_end(); 01086 for (MeshBase::const_element_iterator el = 01087 mesh.active_elements_begin(); el != el_end; ++el) 01088 { 01089 const Elem* elem = *el; 01090 libmesh_assert (elem); 01091 processor_id_type elemprocid = elem->processor_id(); 01092 dof_id_type elemid = elem->id(); 01093 01094 libmesh_assert_greater_equal (elemid, lastelemid); 01095 libmesh_assert_greater_equal (elemprocid, lastprocid); 01096 01097 lastelemid = elemid; 01098 lastprocid = elemprocid; 01099 } 01100 } 01101 01102 01103 01104 void MeshTools::libmesh_assert_valid_amr_elem_ids(const MeshBase &mesh) 01105 { 01106 const MeshBase::const_element_iterator el_end = 01107 mesh.elements_end(); 01108 for (MeshBase::const_element_iterator el = 01109 mesh.elements_begin(); el != el_end; ++el) 01110 { 01111 const Elem* elem = *el; 01112 libmesh_assert (elem); 01113 01114 const Elem* parent = elem->parent(); 01115 01116 if (parent) 01117 { 01118 libmesh_assert_greater_equal (elem->id(), parent->id()); 01119 libmesh_assert_greater_equal (elem->processor_id(), parent->processor_id()); 01120 } 01121 } 01122 } 01123 01124 01125 01126 void MeshTools::libmesh_assert_connected_nodes (const MeshBase &mesh) 01127 { 01128 std::set<const Node*> used_nodes; 01129 01130 const MeshBase::const_element_iterator el_end = 01131 mesh.elements_end(); 01132 for (MeshBase::const_element_iterator el = 01133 mesh.elements_begin(); el != el_end; ++el) 01134 { 01135 const Elem* elem = *el; 01136 libmesh_assert (elem); 01137 01138 for (unsigned int n=0; n<elem->n_nodes(); ++n) 01139 used_nodes.insert(elem->get_node(n)); 01140 } 01141 01142 const MeshBase::const_node_iterator node_end = mesh.nodes_end(); 01143 01144 for (MeshBase::const_node_iterator node_it = mesh.nodes_begin(); 01145 node_it != node_end; ++node_it) 01146 { 01147 Node *node = *node_it; 01148 libmesh_assert(node); 01149 libmesh_assert(used_nodes.count(node)); 01150 } 01151 } 01152 01153 01154 01155 namespace MeshTools { 01156 01157 void libmesh_assert_valid_dof_ids(const MeshBase &mesh) 01158 { 01159 if (libMesh::n_processors() == 1) 01160 return; 01161 01162 parallel_only(); 01163 01164 dof_id_type pmax_elem_id = mesh.max_elem_id(); 01165 CommWorld.max(pmax_elem_id); 01166 01167 for (dof_id_type i=0; i != pmax_elem_id; ++i) 01168 assert_semiverify_dofobj(mesh.query_elem(i)); 01169 01170 dof_id_type pmax_node_id = mesh.max_node_id(); 01171 CommWorld.max(pmax_node_id); 01172 01173 for (dof_id_type i=0; i != pmax_node_id; ++i) 01174 assert_semiverify_dofobj(mesh.query_node_ptr(i)); 01175 } 01176 01177 template <> 01178 void libmesh_assert_valid_procids<Elem>(const MeshBase& mesh) 01179 { 01180 if (libMesh::n_processors() == 1) 01181 return; 01182 01183 parallel_only(); 01184 01185 // We want this test to be valid even when called even after nodes 01186 // have been added asynchonously but before they're renumbered 01187 dof_id_type parallel_max_elem_id = mesh.max_elem_id(); 01188 CommWorld.max(parallel_max_elem_id); 01189 01190 // Check processor ids for consistency between processors 01191 01192 for (dof_id_type i=0; i != parallel_max_elem_id; ++i) 01193 { 01194 const Elem *elem = mesh.query_elem(i); 01195 01196 processor_id_type min_id = 01197 elem ? elem->processor_id() : 01198 std::numeric_limits<processor_id_type>::max(); 01199 CommWorld.min(min_id); 01200 01201 processor_id_type max_id = 01202 elem ? elem->processor_id() : 01203 std::numeric_limits<processor_id_type>::min(); 01204 CommWorld.max(max_id); 01205 01206 if (elem) 01207 { 01208 libmesh_assert_equal_to (min_id, elem->processor_id()); 01209 libmesh_assert_equal_to (max_id, elem->processor_id()); 01210 } 01211 01212 if (min_id == libMesh::processor_id()) 01213 libmesh_assert(elem); 01214 } 01215 01216 // If we're adaptively refining, check processor ids for consistency 01217 // between parents and children. 01218 #ifdef LIBMESH_ENABLE_AMR 01219 01220 // Ancestor elements we won't worry about, but subactive and active 01221 // elements ought to have parents with consistent processor ids 01222 01223 const MeshBase::const_element_iterator el_end = 01224 mesh.elements_end(); 01225 for (MeshBase::const_element_iterator el = 01226 mesh.elements_begin(); el != el_end; ++el) 01227 { 01228 const Elem *elem = *el; 01229 libmesh_assert(elem); 01230 01231 if (!elem->active() && !elem->subactive()) 01232 continue; 01233 01234 const Elem *parent = elem->parent(); 01235 01236 if (parent) 01237 { 01238 libmesh_assert(parent->has_children()); 01239 processor_id_type parent_procid = parent->processor_id(); 01240 bool matching_child_id = false; 01241 for (unsigned int c = 0; c != parent->n_children(); ++c) 01242 { 01243 const Elem* child = parent->child(c); 01244 libmesh_assert(child); 01245 01246 // If we've got a remote_elem then we don't know whether 01247 // it's responsible for the parent's processor id; all 01248 // we can do is assume it is and let its processor fail 01249 // an assert if there's something wrong. 01250 if (child == remote_elem || 01251 child->processor_id() == parent_procid) 01252 matching_child_id = true; 01253 } 01254 libmesh_assert(matching_child_id); 01255 } 01256 } 01257 #endif 01258 } 01259 01260 01261 01262 template <> 01263 void libmesh_assert_valid_procids<Node>(const MeshBase& mesh) 01264 { 01265 if (libMesh::n_processors() == 1) 01266 return; 01267 01268 parallel_only(); 01269 01270 // We want this test to be valid even when called even after nodes 01271 // have been added asynchonously but before they're renumbered 01272 dof_id_type parallel_max_node_id = mesh.max_node_id(); 01273 CommWorld.max(parallel_max_node_id); 01274 01275 // Check processor ids for consistency between processors 01276 01277 for (dof_id_type i=0; i != parallel_max_node_id; ++i) 01278 { 01279 const Node *node = mesh.query_node_ptr(i); 01280 01281 processor_id_type min_id = 01282 node ? node->processor_id() : 01283 std::numeric_limits<processor_id_type>::max(); 01284 CommWorld.min(min_id); 01285 01286 processor_id_type max_id = 01287 node ? node->processor_id() : 01288 std::numeric_limits<processor_id_type>::min(); 01289 CommWorld.max(max_id); 01290 01291 if (node) 01292 { 01293 libmesh_assert_equal_to (min_id, node->processor_id()); 01294 libmesh_assert_equal_to (max_id, node->processor_id()); 01295 } 01296 01297 if (min_id == libMesh::processor_id()) 01298 libmesh_assert(node); 01299 } 01300 01301 std::vector<bool> node_touched_by_me(parallel_max_node_id, false); 01302 01303 const MeshBase::const_element_iterator el_end = 01304 mesh.active_local_elements_end(); 01305 for (MeshBase::const_element_iterator el = 01306 mesh.active_local_elements_begin(); el != el_end; ++el) 01307 { 01308 const Elem* elem = *el; 01309 libmesh_assert (elem); 01310 01311 for (unsigned int i=0; i != elem->n_nodes(); ++i) 01312 { 01313 const Node *node = elem->get_node(i); 01314 dof_id_type nodeid = node->id(); 01315 node_touched_by_me[nodeid] = true; 01316 } 01317 } 01318 std::vector<bool> node_touched_by_anyone(node_touched_by_me); 01319 CommWorld.max(node_touched_by_anyone); 01320 01321 const MeshBase::const_node_iterator nd_end = mesh.local_nodes_end(); 01322 for (MeshBase::const_node_iterator nd = mesh.local_nodes_begin(); 01323 nd != nd_end; ++nd) 01324 { 01325 const Node *node = *nd; 01326 libmesh_assert(node); 01327 01328 dof_id_type nodeid = node->id(); 01329 libmesh_assert(!node_touched_by_anyone[nodeid] || 01330 node_touched_by_me[nodeid]); 01331 } 01332 } 01333 01334 } // namespace MeshTools 01335 01336 01337 01338 #ifdef LIBMESH_ENABLE_AMR 01339 void MeshTools::libmesh_assert_valid_refinement_flags(const MeshBase &mesh) 01340 { 01341 parallel_only(); 01342 if (libMesh::n_processors() == 1) 01343 return; 01344 01345 std::vector<unsigned char> my_elem_h_state(mesh.max_elem_id(), 255); 01346 std::vector<unsigned char> my_elem_p_state(mesh.max_elem_id(), 255); 01347 01348 const MeshBase::const_element_iterator el_end = 01349 mesh.elements_end(); 01350 for (MeshBase::const_element_iterator el = 01351 mesh.elements_begin(); el != el_end; ++el) 01352 { 01353 const Elem* elem = *el; 01354 libmesh_assert (elem); 01355 dof_id_type elemid = elem->id(); 01356 01357 my_elem_h_state[elemid] = 01358 static_cast<unsigned char>(elem->refinement_flag()); 01359 01360 my_elem_p_state[elemid] = 01361 static_cast<unsigned char>(elem->p_refinement_flag()); 01362 } 01363 std::vector<unsigned char> min_elem_h_state(my_elem_h_state); 01364 CommWorld.min(min_elem_h_state); 01365 01366 std::vector<unsigned char> min_elem_p_state(my_elem_p_state); 01367 CommWorld.min(min_elem_p_state); 01368 01369 for (dof_id_type i=0; i!= mesh.max_elem_id(); ++i) 01370 { 01371 libmesh_assert(my_elem_h_state[i] == 255 || 01372 my_elem_h_state[i] == min_elem_h_state[i]); 01373 libmesh_assert(my_elem_p_state[i] == 255 || 01374 my_elem_p_state[i] == min_elem_p_state[i]); 01375 } 01376 } 01377 #else 01378 void MeshTools::libmesh_assert_valid_refinement_flags(const MeshBase &) 01379 { 01380 } 01381 #endif // LIBMESH_ENABLE_AMR 01382 01383 01384 01385 #ifdef LIBMESH_ENABLE_AMR 01386 void MeshTools::libmesh_assert_valid_refinement_tree(const MeshBase &mesh) 01387 { 01388 const MeshBase::const_element_iterator el_end = 01389 mesh.elements_end(); 01390 for (MeshBase::const_element_iterator el = 01391 mesh.elements_begin(); el != el_end; ++el) 01392 { 01393 const Elem *elem = *el; 01394 libmesh_assert(elem); 01395 if (elem->has_children()) 01396 for (unsigned int n=0; n != elem->n_children(); ++n) 01397 { 01398 libmesh_assert(elem->child(n)); 01399 if (elem->child(n) != remote_elem) 01400 libmesh_assert_equal_to (elem->child(n)->parent(), elem); 01401 } 01402 if (elem->active()) 01403 { 01404 libmesh_assert(!elem->ancestor()); 01405 libmesh_assert(!elem->subactive()); 01406 } 01407 else if (elem->ancestor()) 01408 { 01409 libmesh_assert(!elem->subactive()); 01410 } 01411 else 01412 libmesh_assert(elem->subactive()); 01413 } 01414 } 01415 #else 01416 void MeshTools::libmesh_assert_valid_refinement_tree(const MeshBase &) 01417 { 01418 } 01419 #endif // LIBMESH_ENABLE_AMR 01420 01421 01422 01423 void MeshTools::libmesh_assert_valid_neighbors(const MeshBase &mesh) 01424 { 01425 const MeshBase::const_element_iterator el_end = mesh.elements_end(); 01426 for (MeshBase::const_element_iterator el = mesh.elements_begin(); 01427 el != el_end; ++el) 01428 { 01429 const Elem* elem = *el; 01430 libmesh_assert (elem); 01431 elem->libmesh_assert_valid_neighbors(); 01432 } 01433 } 01434 01435 01436 01437 #endif 01438 01439 01440 01441 void MeshTools::Private::globally_renumber_nodes_and_elements (MeshBase& mesh) 01442 { 01443 MeshCommunication().assign_global_indices(mesh); 01444 } 01445 01446 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:47 UTC
Hosted By: