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