$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 // Local includes 00021 #include "libmesh/boundary_info.h" 00022 #include "libmesh/elem.h" 00023 #include "libmesh/libmesh_logging.h" 00024 #include "libmesh/mesh_communication.h" 00025 #include "libmesh/parallel_mesh.h" 00026 #include "libmesh/parallel.h" 00027 #include "libmesh/parmetis_partitioner.h" 00028 00029 namespace libMesh 00030 { 00031 00032 // ------------------------------------------------------------ 00033 // ParallelMesh class member functions 00034 ParallelMesh::ParallelMesh (const Parallel::Communicator &comm_in, 00035 unsigned char d) : 00036 UnstructuredMesh (comm_in,d), _is_serial(true), 00037 _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0), 00038 _next_free_local_node_id(this->processor_id()), 00039 _next_free_local_elem_id(this->processor_id()), 00040 _next_free_unpartitioned_node_id(this->n_processors()), 00041 _next_free_unpartitioned_elem_id(this->n_processors()) 00042 { 00043 #ifdef LIBMESH_ENABLE_UNIQUE_ID 00044 _next_unique_id = this->processor_id(); 00045 #endif 00046 00047 // FIXME: give parmetis the communicator! 00048 _partitioner = UniquePtr<Partitioner>(new ParmetisPartitioner()); 00049 } 00050 00051 00052 #ifndef LIBMESH_DISABLE_COMMWORLD 00053 // ------------------------------------------------------------ 00054 // ParallelMesh class member functions 00055 ParallelMesh::ParallelMesh (unsigned char d) : 00056 UnstructuredMesh (d), _is_serial(true), 00057 _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0), 00058 _next_free_local_node_id(this->processor_id()), 00059 _next_free_local_elem_id(this->processor_id()), 00060 _next_free_unpartitioned_node_id(this->n_processors()), 00061 _next_free_unpartitioned_elem_id(this->n_processors()) 00062 { 00063 #ifdef LIBMESH_ENABLE_UNIQUE_ID 00064 _next_unique_id = this->processor_id(); 00065 #endif 00066 00067 // FIXME: give parmetis the communicator! 00068 _partitioner = UniquePtr<Partitioner>(new ParmetisPartitioner()); 00069 } 00070 #endif 00071 00072 00073 ParallelMesh::~ParallelMesh () 00074 { 00075 this->clear(); // Free nodes and elements 00076 } 00077 00078 00079 // This might be specialized later, but right now it's just here to 00080 // make sure the compiler doesn't give us a default (non-deep) copy 00081 // constructor instead. 00082 ParallelMesh::ParallelMesh (const ParallelMesh &other_mesh) : 00083 UnstructuredMesh (other_mesh), _is_serial(other_mesh._is_serial), 00084 _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0), 00085 _next_free_local_node_id(this->processor_id()), 00086 _next_free_local_elem_id(this->processor_id()), 00087 _next_free_unpartitioned_node_id(this->n_processors()), 00088 _next_free_unpartitioned_elem_id(this->n_processors()) 00089 { 00090 this->copy_nodes_and_elements(other_mesh); 00091 _n_nodes = other_mesh.n_nodes(); 00092 _n_elem = other_mesh.n_elem(); 00093 _max_node_id = other_mesh.max_node_id(); 00094 _max_elem_id = other_mesh.max_elem_id(); 00095 _next_free_local_node_id = 00096 other_mesh._next_free_local_node_id; 00097 _next_free_local_elem_id = 00098 other_mesh._next_free_local_elem_id; 00099 _next_free_unpartitioned_node_id = 00100 other_mesh._next_free_unpartitioned_node_id; 00101 _next_free_unpartitioned_elem_id = 00102 other_mesh._next_free_unpartitioned_elem_id; 00103 this->get_boundary_info() = other_mesh.get_boundary_info(); 00104 00105 // Need to copy extra_ghost_elems 00106 for(std::set<Elem *>::iterator it = other_mesh._extra_ghost_elems.begin(); 00107 it != other_mesh._extra_ghost_elems.end(); 00108 ++it) 00109 _extra_ghost_elems.insert(elem((*it)->id())); 00110 } 00111 00112 00113 00114 ParallelMesh::ParallelMesh (const UnstructuredMesh &other_mesh) : 00115 UnstructuredMesh (other_mesh), _is_serial(other_mesh.is_serial()), 00116 _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0), 00117 _next_free_local_node_id(this->processor_id()), 00118 _next_free_local_elem_id(this->processor_id()), 00119 _next_free_unpartitioned_node_id(this->n_processors()), 00120 _next_free_unpartitioned_elem_id(this->n_processors()) 00121 { 00122 this->copy_nodes_and_elements(other_mesh); 00123 this->get_boundary_info() = other_mesh.get_boundary_info(); 00124 00125 this->update_parallel_id_counts(); 00126 } 00127 00128 00129 // We use cached values for these so they can be called 00130 // from one processor without bothering the rest, but 00131 // we may need to update those caches before doing a full 00132 // renumbering 00133 void ParallelMesh::update_parallel_id_counts() 00134 { 00135 // This function must be run on all processors at once 00136 parallel_object_only(); 00137 00138 _n_elem = this->parallel_n_elem(); 00139 _n_nodes = this->parallel_n_nodes(); 00140 _max_node_id = this->parallel_max_node_id(); 00141 _max_elem_id = this->parallel_max_elem_id(); 00142 00143 if (_next_free_unpartitioned_elem_id < _max_elem_id) 00144 _next_free_unpartitioned_elem_id = 00145 ((_max_elem_id-1) / (this->n_processors() + 1) + 1) * 00146 (this->n_processors() + 1) + this->n_processors(); 00147 if (_next_free_local_elem_id < _max_elem_id) 00148 _next_free_local_elem_id = 00149 ((_max_elem_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) * 00150 (this->n_processors() + 1) + this->processor_id(); 00151 00152 if (_next_free_unpartitioned_node_id < _max_node_id) 00153 _next_free_unpartitioned_node_id = 00154 ((_max_node_id-1) / (this->n_processors() + 1) + 1) * 00155 (this->n_processors() + 1) + this->n_processors(); 00156 if (_next_free_local_node_id < _max_node_id) 00157 _next_free_local_node_id = 00158 ((_max_node_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) * 00159 (this->n_processors() + 1) + this->processor_id(); 00160 } 00161 00162 00163 // Or in debug mode we may want to test the uncached values without 00164 // changing the cache 00165 dof_id_type ParallelMesh::parallel_n_elem() const 00166 { 00167 // This function must be run on all processors at once 00168 parallel_object_only(); 00169 00170 dof_id_type n_local = this->n_local_elem(); 00171 this->comm().sum(n_local); 00172 n_local += this->n_unpartitioned_elem(); 00173 return n_local; 00174 } 00175 00176 00177 00178 dof_id_type ParallelMesh::parallel_max_elem_id() const 00179 { 00180 // This function must be run on all processors at once 00181 parallel_object_only(); 00182 00183 dof_id_type max_local = _elements.empty() ? 00184 0 : _elements.rbegin()->first + 1; 00185 this->comm().max(max_local); 00186 return max_local; 00187 } 00188 00189 00190 00191 dof_id_type ParallelMesh::parallel_n_nodes() const 00192 { 00193 // This function must be run on all processors at once 00194 parallel_object_only(); 00195 00196 dof_id_type n_local = this->n_local_nodes(); 00197 this->comm().sum(n_local); 00198 n_local += this->n_unpartitioned_nodes(); 00199 return n_local; 00200 } 00201 00202 00203 00204 dof_id_type ParallelMesh::parallel_max_node_id() const 00205 { 00206 // This function must be run on all processors at once 00207 parallel_object_only(); 00208 00209 dof_id_type max_local = _nodes.empty() ? 00210 0 : _nodes.rbegin()->first + 1; 00211 this->comm().max(max_local); 00212 return max_local; 00213 } 00214 00215 00216 00217 const Point& ParallelMesh::point (const dof_id_type i) const 00218 { 00219 libmesh_assert(_nodes[i]); 00220 libmesh_assert_equal_to (_nodes[i]->id(), i); 00221 00222 return (*_nodes[i]); 00223 } 00224 00225 00226 00227 00228 00229 const Node& ParallelMesh::node (const dof_id_type i) const 00230 { 00231 libmesh_assert(_nodes[i]); 00232 libmesh_assert_equal_to (_nodes[i]->id(), i); 00233 00234 return (*_nodes[i]); 00235 } 00236 00237 00238 00239 00240 00241 Node& ParallelMesh::node (const dof_id_type i) 00242 { 00243 libmesh_assert(_nodes[i]); 00244 libmesh_assert_equal_to (_nodes[i]->id(), i); 00245 00246 return (*_nodes[i]); 00247 } 00248 00249 00250 00251 const Node* ParallelMesh::node_ptr (const dof_id_type i) const 00252 { 00253 libmesh_assert(_nodes[i]); 00254 libmesh_assert_equal_to (_nodes[i]->id(), i); 00255 00256 return _nodes[i]; 00257 } 00258 00259 00260 00261 00262 Node* ParallelMesh::node_ptr (const dof_id_type i) 00263 { 00264 libmesh_assert(_nodes[i]); 00265 libmesh_assert_equal_to (_nodes[i]->id(), i); 00266 00267 return _nodes[i]; 00268 } 00269 00270 00271 00272 00273 const Node* ParallelMesh::query_node_ptr (const dof_id_type i) const 00274 { 00275 std::map<dof_id_type, Node*>::const_iterator it = _nodes.find(i); 00276 if (it != _nodes.end().it) 00277 { 00278 const Node* n = it->second; 00279 libmesh_assert (!n || n->id() == i); 00280 return n; 00281 } 00282 00283 return NULL; 00284 } 00285 00286 00287 00288 00289 Node* ParallelMesh::query_node_ptr (const dof_id_type i) 00290 { 00291 std::map<dof_id_type, Node*>::const_iterator it = _nodes.find(i); 00292 if (it != _nodes.end().it) 00293 { 00294 Node* n = it->second; 00295 libmesh_assert (!n || n->id() == i); 00296 return n; 00297 } 00298 00299 return NULL; 00300 } 00301 00302 00303 00304 00305 const Elem* ParallelMesh::elem (const dof_id_type i) const 00306 { 00307 libmesh_assert(_elements[i]); 00308 libmesh_assert_equal_to (_elements[i]->id(), i); 00309 00310 return _elements[i]; 00311 } 00312 00313 00314 00315 00316 Elem* ParallelMesh::elem (const dof_id_type i) 00317 { 00318 libmesh_assert(_elements[i]); 00319 libmesh_assert_equal_to (_elements[i]->id(), i); 00320 00321 return _elements[i]; 00322 } 00323 00324 00325 00326 00327 const Elem* ParallelMesh::query_elem (const dof_id_type i) const 00328 { 00329 std::map<dof_id_type, Elem*>::const_iterator it = _elements.find(i); 00330 if (it != _elements.end().it) 00331 { 00332 const Elem* e = it->second; 00333 libmesh_assert (!e || e->id() == i); 00334 return e; 00335 } 00336 00337 return NULL; 00338 } 00339 00340 00341 00342 00343 Elem* ParallelMesh::query_elem (const dof_id_type i) 00344 { 00345 std::map<dof_id_type, Elem*>::const_iterator it = _elements.find(i); 00346 if (it != _elements.end().it) 00347 { 00348 Elem* e = _elements[i]; 00349 libmesh_assert (!e || e->id() == i); 00350 return e; 00351 } 00352 00353 return NULL; 00354 } 00355 00356 00357 00358 00359 Elem* ParallelMesh::add_elem (Elem *e) 00360 { 00361 // Don't try to add NULLs! 00362 libmesh_assert(e); 00363 00364 // Trying to add an existing element is a no-op 00365 if (e->valid_id() && _elements[e->id()] == e) 00366 return e; 00367 00368 const processor_id_type elem_procid = e->processor_id(); 00369 00370 if (!e->valid_id()) 00371 { 00372 // We should only be creating new ids past the end of the range 00373 // of existing ids 00374 libmesh_assert_greater_equal(_next_free_unpartitioned_elem_id, 00375 _max_elem_id); 00376 libmesh_assert_greater_equal(_next_free_local_elem_id, _max_elem_id); 00377 00378 // Use the unpartitioned ids for unpartitioned elems, 00379 // in serial, and temporarily for ghost elems 00380 dof_id_type *next_id = &_next_free_unpartitioned_elem_id; 00381 if (elem_procid == this->processor_id() && 00382 !this->is_serial()) 00383 next_id = &_next_free_local_elem_id; 00384 e->set_id (*next_id); 00385 } 00386 00387 { 00388 // Advance next_ids up high enough that each is pointing to an 00389 // unused id and any subsequent increments will still point us 00390 // to unused ids 00391 _max_elem_id = std::max(_max_elem_id, 00392 static_cast<dof_id_type>(e->id()+1)); 00393 00394 if (_next_free_unpartitioned_elem_id < _max_elem_id) 00395 _next_free_unpartitioned_elem_id = 00396 ((_max_elem_id-1) / (this->n_processors() + 1) + 1) * 00397 (this->n_processors() + 1) + this->n_processors(); 00398 if (_next_free_local_elem_id < _max_elem_id) 00399 _next_free_local_elem_id = 00400 ((_max_elem_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) * 00401 (this->n_processors() + 1) + this->processor_id(); 00402 00403 #ifndef NDEBUG 00404 // We need a const mapvector so we don't inadvertently create 00405 // NULL entries when testing for non-NULL ones 00406 const mapvector<Elem*,dof_id_type>& const_elements = _elements; 00407 #endif 00408 libmesh_assert(!const_elements[_next_free_unpartitioned_elem_id]); 00409 libmesh_assert(!const_elements[_next_free_local_elem_id]); 00410 } 00411 00412 // Don't try to overwrite existing elems 00413 libmesh_assert (!_elements[e->id()]); 00414 00415 _elements[e->id()] = e; 00416 00417 // Try to make the cached elem data more accurate 00418 if (elem_procid == this->processor_id() || 00419 elem_procid == DofObject::invalid_processor_id) 00420 _n_elem++; 00421 00422 #ifdef LIBMESH_ENABLE_UNIQUE_ID 00423 if (!e->valid_unique_id() && processor_id() == e->processor_id()) 00424 { 00425 e->set_unique_id() = _next_unique_id; 00426 _next_unique_id += this->n_processors(); 00427 } 00428 #endif 00429 00430 // Unpartitioned elems should be added on every processor 00431 // And shouldn't be added in the same batch as ghost elems 00432 // But we might be just adding on processor 0 to 00433 // broadcast later 00434 // #ifdef DEBUG 00435 // if (elem_procid == DofObject::invalid_processor_id) 00436 // { 00437 // dof_id_type elem_id = e->id(); 00438 // this->comm().max(elem_id); 00439 // libmesh_assert_equal_to (elem_id, e->id()); 00440 // } 00441 // #endif 00442 00443 return e; 00444 } 00445 00446 00447 00448 Elem* ParallelMesh::insert_elem (Elem* e) 00449 { 00450 if (_elements[e->id()]) 00451 this->delete_elem(_elements[e->id()]); 00452 00453 // Try to make the cached elem data more accurate 00454 processor_id_type elem_procid = e->processor_id(); 00455 if (elem_procid == this->processor_id() || 00456 elem_procid == DofObject::invalid_processor_id) 00457 _n_elem++; 00458 00459 _elements[e->id()] = e; 00460 00461 return e; 00462 } 00463 00464 00465 00466 void ParallelMesh::delete_elem(Elem* e) 00467 { 00468 libmesh_assert (e); 00469 00470 // Try to make the cached elem data more accurate 00471 processor_id_type elem_procid = e->processor_id(); 00472 if (elem_procid == this->processor_id() || 00473 elem_procid == DofObject::invalid_processor_id) 00474 _n_elem--; 00475 00476 // Delete the element from the BoundaryInfo object 00477 this->get_boundary_info().remove(e); 00478 00479 // But not yet from the container; we might invalidate 00480 // an iterator that way! 00481 00482 //_elements.erase(e->id()); 00483 00484 // Instead, we set it to NULL for now 00485 00486 _elements[e->id()] = NULL; 00487 00488 // delete the element 00489 delete e; 00490 } 00491 00492 00493 00494 void ParallelMesh::renumber_elem(const dof_id_type old_id, 00495 const dof_id_type new_id) 00496 { 00497 Elem *el = _elements[old_id]; 00498 libmesh_assert (el); 00499 libmesh_assert_equal_to (el->id(), old_id); 00500 00501 el->set_id(new_id); 00502 libmesh_assert (!_elements[new_id]); 00503 _elements[new_id] = el; 00504 _elements.erase(old_id); 00505 } 00506 00507 00508 00509 Node* ParallelMesh::add_point (const Point& p, 00510 const dof_id_type id, 00511 const processor_id_type proc_id) 00512 { 00513 if (_nodes.count(id)) 00514 { 00515 Node *n = _nodes[id]; 00516 libmesh_assert (n); 00517 libmesh_assert_equal_to (n->id(), id); 00518 00519 *n = p; 00520 n->processor_id() = proc_id; 00521 00522 return n; 00523 } 00524 00525 Node* n = Node::build(p, id).release(); 00526 n->processor_id() = proc_id; 00527 00528 return ParallelMesh::add_node(n); 00529 } 00530 00531 00532 00533 Node* ParallelMesh::add_node (Node *n) 00534 { 00535 // Don't try to add NULLs! 00536 libmesh_assert(n); 00537 00538 // Trying to add an existing node is a no-op 00539 if (n->valid_id() && _nodes[n->id()] == n) 00540 return n; 00541 00542 const processor_id_type node_procid = n->processor_id(); 00543 00544 if (!n->valid_id()) 00545 { 00546 // We should only be creating new ids past the end of the range 00547 // of existing ids 00548 libmesh_assert_greater_equal(_next_free_unpartitioned_node_id, 00549 _max_node_id); 00550 libmesh_assert_greater_equal(_next_free_local_node_id, _max_node_id); 00551 00552 // Use the unpartitioned ids for unpartitioned nodes, 00553 // in serial, and temporarily for ghost nodes 00554 dof_id_type *next_id = &_next_free_unpartitioned_node_id; 00555 if (node_procid == this->processor_id() && 00556 !this->is_serial()) 00557 next_id = &_next_free_local_node_id; 00558 n->set_id (*next_id); 00559 } 00560 00561 { 00562 // Advance next_ids up high enough that each is pointing to an 00563 // unused id and any subsequent increments will still point us 00564 // to unused ids 00565 _max_node_id = std::max(_max_node_id, 00566 static_cast<dof_id_type>(n->id()+1)); 00567 00568 if (_next_free_unpartitioned_node_id < _max_node_id) 00569 _next_free_unpartitioned_node_id = 00570 ((_max_node_id-1) / (this->n_processors() + 1) + 1) * 00571 (this->n_processors() + 1) + this->n_processors(); 00572 if (_next_free_local_node_id < _max_node_id) 00573 _next_free_local_node_id = 00574 ((_max_node_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) * 00575 (this->n_processors() + 1) + this->processor_id(); 00576 00577 #ifndef NDEBUG 00578 // We need a const mapvector so we don't inadvertently create 00579 // NULL entries when testing for non-NULL ones 00580 const mapvector<Node*,dof_id_type>& const_nodes = _nodes; 00581 #endif 00582 libmesh_assert(!const_nodes[_next_free_unpartitioned_node_id]); 00583 libmesh_assert(!const_nodes[_next_free_local_node_id]); 00584 } 00585 00586 // Don't try to overwrite existing nodes 00587 libmesh_assert (!_nodes[n->id()]); 00588 00589 _nodes[n->id()] = n; 00590 00591 // Try to make the cached node data more accurate 00592 if (node_procid == this->processor_id() || 00593 node_procid == DofObject::invalid_processor_id) 00594 _n_nodes++; 00595 00596 #ifdef LIBMESH_ENABLE_UNIQUE_ID 00597 if (!n->valid_unique_id() && processor_id() == n->processor_id()) 00598 { 00599 n->set_unique_id() = _next_unique_id; 00600 _next_unique_id += this->n_processors(); 00601 } 00602 #endif 00603 00604 00605 // Unpartitioned nodes should be added on every processor 00606 // And shouldn't be added in the same batch as ghost nodes 00607 // But we might be just adding on processor 0 to 00608 // broadcast later 00609 // #ifdef DEBUG 00610 // if (node_procid == DofObject::invalid_processor_id) 00611 // { 00612 // dof_id_type node_id = n->id(); 00613 // this->comm().max(node_id); 00614 // libmesh_assert_equal_to (node_id, n->id()); 00615 // } 00616 // #endif 00617 00618 return n; 00619 } 00620 00621 00622 00623 Node* ParallelMesh::insert_node(Node* n) 00624 { 00625 return ParallelMesh::add_node(n); 00626 } 00627 00628 00629 00630 void ParallelMesh::delete_node(Node* n) 00631 { 00632 libmesh_assert(n); 00633 libmesh_assert(_nodes[n->id()]); 00634 00635 // Try to make the cached elem data more accurate 00636 processor_id_type node_procid = n->processor_id(); 00637 if (node_procid == this->processor_id() || 00638 node_procid == DofObject::invalid_processor_id) 00639 _n_nodes--; 00640 00641 // Delete the node from the BoundaryInfo object 00642 this->get_boundary_info().remove(n); 00643 00644 // But not yet from the container; we might invalidate 00645 // an iterator that way! 00646 00647 //_nodes.erase(n->id()); 00648 00649 // Instead, we set it to NULL for now 00650 00651 _nodes[n->id()] = NULL; 00652 00653 // delete the node 00654 delete n; 00655 } 00656 00657 00658 00659 void ParallelMesh::renumber_node(const dof_id_type old_id, 00660 const dof_id_type new_id) 00661 { 00662 Node *nd = _nodes[old_id]; 00663 libmesh_assert (nd); 00664 libmesh_assert_equal_to (nd->id(), old_id); 00665 00666 nd->set_id(new_id); 00667 libmesh_assert (!_nodes[new_id]); 00668 _nodes[new_id] = nd; 00669 _nodes.erase(old_id); 00670 } 00671 00672 00673 00674 void ParallelMesh::clear () 00675 { 00676 // Call parent clear function 00677 MeshBase::clear(); 00678 00679 00680 // Clear our elements and nodes 00681 { 00682 elem_iterator_imp it = _elements.begin(); 00683 const elem_iterator_imp end = _elements.end(); 00684 00685 // There is no need to remove the elements from 00686 // the BoundaryInfo data structure since we 00687 // already cleared it. 00688 for (; it != end; ++it) 00689 delete *it; 00690 00691 _elements.clear(); 00692 } 00693 00694 // clear the nodes data structure 00695 { 00696 node_iterator_imp it = _nodes.begin(); 00697 node_iterator_imp end = _nodes.end(); 00698 00699 // There is no need to remove the nodes from 00700 // the BoundaryInfo data structure since we 00701 // already cleared it. 00702 for (; it != end; ++it) 00703 delete *it; 00704 00705 _nodes.clear(); 00706 } 00707 00708 // We're no longer distributed if we were before 00709 _is_serial = true; 00710 00711 // Correct our caches 00712 _n_nodes = 0; 00713 _n_elem = 0; 00714 _max_node_id = 0; 00715 _max_elem_id = 0; 00716 _next_free_local_node_id = this->processor_id(); 00717 _next_free_local_elem_id = this->processor_id(); 00718 _next_free_unpartitioned_node_id = this->n_processors(); 00719 _next_free_unpartitioned_elem_id = this->n_processors(); 00720 } 00721 00722 00723 00724 void ParallelMesh::redistribute () 00725 { 00726 // If this is a truly parallel mesh, go through the redistribution/gather/delete remote steps 00727 if (!this->is_serial()) 00728 { 00729 // Construct a MeshCommunication object to actually redistribute the nodes 00730 // and elements according to the partitioner, and then to re-gather the neighbors. 00731 MeshCommunication mc; 00732 mc.redistribute(*this); 00733 00734 this->update_parallel_id_counts(); 00735 00736 // Is this necessary? If we are called from prepare_for_use(), this will be called 00737 // anyway... but users can always call partition directly, in which case we do need 00738 // to call delete_remote_elements()... 00739 // 00740 // Regardless of whether it's necessary, it isn't safe. We 00741 // haven't communicated new node processor_ids yet, and we can't 00742 // delete nodes until we do. 00743 // this->delete_remote_elements(); 00744 } 00745 } 00746 00747 00748 00749 void ParallelMesh::update_post_partitioning () 00750 { 00751 // this->recalculate_n_partitions(); 00752 00753 // Partitioning changes our numbers of unpartitioned objects 00754 this->update_parallel_id_counts(); 00755 } 00756 00757 00758 00759 template <typename T> 00760 void ParallelMesh::libmesh_assert_valid_parallel_object_ids 00761 (const mapvector<T*,dof_id_type> &objects) const 00762 { 00763 // This function must be run on all processors at once 00764 parallel_object_only(); 00765 00766 const dof_id_type pmax_node_id = this->parallel_max_node_id(); 00767 const dof_id_type pmax_elem_id = this->parallel_max_elem_id(); 00768 const dof_id_type pmax_id = std::max(pmax_node_id, pmax_elem_id); 00769 00770 for (dof_id_type i=0; i != pmax_id; ++i) 00771 { 00772 T* obj = objects[i]; // Returns NULL if there's no map entry 00773 00774 dof_id_type dofid = obj && obj->valid_id() ? 00775 obj->id() : DofObject::invalid_id; 00776 // Local lookups by id should return the requested object 00777 libmesh_assert(!obj || obj->id() == i); 00778 00779 dof_id_type min_dofid = dofid; 00780 this->comm().min(min_dofid); 00781 // All processors with an object should agree on id 00782 libmesh_assert (!obj || dofid == min_dofid); 00783 00784 dof_id_type procid = obj && obj->valid_processor_id() ? 00785 obj->processor_id() : DofObject::invalid_processor_id; 00786 00787 dof_id_type min_procid = procid; 00788 this->comm().min(min_procid); 00789 00790 // All processors with an object should agree on processor id 00791 libmesh_assert (!obj || procid == min_procid); 00792 00793 // Either: 00794 // 1.) I own this elem (min_procid == this->processor_id()) *and* I have a valid pointer to it (obj != NULL) 00795 // or 00796 // 2.) I don't own this elem (min_procid != this->processor_id()). (In this case I may or may not have a valid pointer to it.) 00797 00798 // Original assert logic 00799 // libmesh_assert (min_procid != this->processor_id() || obj); 00800 00801 // More human-understandable logic... 00802 libmesh_assert ( 00803 ((min_procid == this->processor_id()) && obj) 00804 || 00805 (min_procid != this->processor_id()) 00806 ); 00807 } 00808 } 00809 00810 00811 00812 void ParallelMesh::libmesh_assert_valid_parallel_ids () const 00813 { 00814 this->libmesh_assert_valid_parallel_object_ids (this->_elements); 00815 this->libmesh_assert_valid_parallel_object_ids (this->_nodes); 00816 } 00817 00818 00819 00820 void ParallelMesh::libmesh_assert_valid_parallel_flags () const 00821 { 00822 #ifdef LIBMESH_ENABLE_AMR 00823 // This function must be run on all processors at once 00824 parallel_object_only(); 00825 00826 dof_id_type pmax_elem_id = this->parallel_max_elem_id(); 00827 00828 for (dof_id_type i=0; i != pmax_elem_id; ++i) 00829 { 00830 Elem* el = _elements[i]; // Returns NULL if there's no map entry 00831 00832 unsigned int refinement_flag = el ? 00833 static_cast<unsigned int> (el->refinement_flag()) : libMesh::invalid_uint; 00834 #ifndef NDEBUG 00835 unsigned int p_refinement_flag = el ? 00836 static_cast<unsigned int> (el->p_refinement_flag()) : libMesh::invalid_uint; 00837 #endif 00838 00839 unsigned int min_rflag = refinement_flag; 00840 this->comm().min(min_rflag); 00841 // All processors with this element should agree on flag 00842 libmesh_assert (!el || min_rflag == refinement_flag); 00843 00844 #ifndef NDEBUG 00845 unsigned int min_pflag = p_refinement_flag; 00846 #endif 00847 // All processors with this element should agree on flag 00848 libmesh_assert (!el || min_pflag == p_refinement_flag); 00849 } 00850 #endif // LIBMESH_ENABLE_AMR 00851 } 00852 00853 00854 00855 template <typename T> 00856 dof_id_type ParallelMesh::renumber_dof_objects 00857 (mapvector<T*,dof_id_type> &objects) 00858 { 00859 // This function must be run on all processors at once 00860 parallel_object_only(); 00861 00862 typedef typename mapvector<T*,dof_id_type>::veclike_iterator object_iterator; 00863 00864 // In parallel we may not know what objects other processors have. 00865 // Start by figuring out how many 00866 dof_id_type unpartitioned_objects = 0; 00867 00868 std::vector<dof_id_type> 00869 ghost_objects_from_proc(this->n_processors(), 0); 00870 00871 object_iterator it = objects.begin(); 00872 object_iterator end = objects.end(); 00873 00874 for (; it != end;) 00875 { 00876 T *obj = *it; 00877 00878 // Remove any NULL container entries while we're here, 00879 // being careful not to invalidate our iterator 00880 if (!*it) 00881 objects.erase(it++); 00882 else 00883 { 00884 processor_id_type obj_procid = obj->processor_id(); 00885 if (obj_procid == DofObject::invalid_processor_id) 00886 unpartitioned_objects++; 00887 else 00888 ghost_objects_from_proc[obj_procid]++; 00889 ++it; 00890 } 00891 } 00892 00893 std::vector<dof_id_type> objects_on_proc(this->n_processors(), 0); 00894 this->comm().allgather(ghost_objects_from_proc[this->processor_id()], 00895 objects_on_proc); 00896 00897 #ifndef NDEBUG 00898 libmesh_assert(this->comm().verify(unpartitioned_objects)); 00899 for (processor_id_type p=0; p != this->n_processors(); ++p) 00900 libmesh_assert_less_equal (ghost_objects_from_proc[p], objects_on_proc[p]); 00901 #endif 00902 00903 // We'll renumber objects in blocks by processor id 00904 std::vector<dof_id_type> first_object_on_proc(this->n_processors()); 00905 for (processor_id_type i=1; i != this->n_processors(); ++i) 00906 first_object_on_proc[i] = first_object_on_proc[i-1] + 00907 objects_on_proc[i-1]; 00908 dof_id_type next_id = first_object_on_proc[this->processor_id()]; 00909 dof_id_type first_free_id = 00910 first_object_on_proc[this->n_processors()-1] + 00911 objects_on_proc[this->n_processors()-1] + 00912 unpartitioned_objects; 00913 00914 // First set new local object ids and build request sets 00915 // for non-local object ids 00916 00917 // Request sets to send to each processor 00918 std::vector<std::vector<dof_id_type> > 00919 requested_ids(this->n_processors()); 00920 00921 #ifdef LIBMESH_ENABLE_UNIQUE_ID 00922 std::vector<std::vector<unique_id_type> > 00923 requested_unique_ids(this->n_processors()); 00924 #endif 00925 00926 // We know how many objects live on each processor, so reseve() space for 00927 // each. 00928 for (processor_id_type p=0; p != this->n_processors(); ++p) 00929 if (p != this->processor_id()) 00930 { 00931 requested_ids[p].reserve(ghost_objects_from_proc[p]); 00932 #ifdef LIBMESH_ENABLE_UNIQUE_ID 00933 requested_unique_ids[p].reserve(ghost_objects_from_proc[p]); 00934 #endif 00935 } 00936 00937 end = objects.end(); 00938 for (it = objects.begin(); it != end; ++it) 00939 { 00940 T *obj = *it; 00941 if (obj->processor_id() == this->processor_id()) 00942 obj->set_id(next_id++); 00943 else if (obj->processor_id() != DofObject::invalid_processor_id) 00944 { 00945 requested_ids[obj->processor_id()].push_back(obj->id()); 00946 #ifdef LIBMESH_ENABLE_UNIQUE_ID 00947 // It's possible to have an invalid id for dofs not owned by this process. 00948 // We'll assert that they match on the receiving end. 00949 requested_unique_ids[obj->processor_id()].push_back(obj->valid_unique_id() ? obj-> unique_id() : DofObject::invalid_unique_id); 00950 #endif 00951 } 00952 } 00953 00954 // Next set ghost object ids from other processors 00955 if (this->n_processors() > 1) 00956 { 00957 for (processor_id_type p=1; p != this->n_processors(); ++p) 00958 { 00959 // Trade my requests with processor procup and procdown 00960 processor_id_type procup = cast_int<processor_id_type> 00961 ((this->processor_id() + p) % this->n_processors()); 00962 processor_id_type procdown = cast_int<processor_id_type> 00963 ((this->n_processors() + this->processor_id() - p) % 00964 this->n_processors()); 00965 std::vector<dof_id_type> request_to_fill; 00966 this->comm().send_receive(procup, requested_ids[procup], 00967 procdown, request_to_fill); 00968 00969 #ifdef LIBMESH_ENABLE_UNIQUE_ID 00970 std::vector<unique_id_type> unique_request_to_fill; 00971 this->comm().send_receive(procup, requested_unique_ids[procup], 00972 procdown, unique_request_to_fill); 00973 std::vector<unique_id_type> new_unique_ids(unique_request_to_fill.size()); 00974 #endif 00975 00976 // Fill those requests 00977 std::vector<dof_id_type> new_ids(request_to_fill.size()); 00978 for (std::size_t i=0; i != request_to_fill.size(); ++i) 00979 { 00980 T *obj = objects[request_to_fill[i]]; 00981 libmesh_assert(obj); 00982 libmesh_assert_equal_to (obj->processor_id(), this->processor_id()); 00983 new_ids[i] = obj->id(); 00984 #ifdef LIBMESH_ENABLE_UNIQUE_ID 00985 new_unique_ids[i] = obj->valid_unique_id() ? obj->unique_id() : DofObject::invalid_unique_id; 00986 #endif 00987 00988 libmesh_assert_greater_equal (new_ids[i], 00989 first_object_on_proc[this->processor_id()]); 00990 libmesh_assert_less (new_ids[i], 00991 first_object_on_proc[this->processor_id()] + 00992 objects_on_proc[this->processor_id()]); 00993 } 00994 00995 // Trade back the results 00996 std::vector<dof_id_type> filled_request; 00997 this->comm().send_receive(procdown, new_ids, 00998 procup, filled_request); 00999 01000 #ifdef LIBMESH_ENABLE_UNIQUE_ID 01001 std::vector<unique_id_type> unique_filled_request; 01002 this->comm().send_receive(procdown, new_unique_ids, 01003 procup, unique_filled_request); 01004 #endif 01005 01006 // And copy the id changes we've now been informed of 01007 for (std::size_t i=0; i != filled_request.size(); ++i) 01008 { 01009 T *obj = objects[requested_ids[procup][i]]; 01010 libmesh_assert (obj); 01011 libmesh_assert_equal_to (obj->processor_id(), procup); 01012 libmesh_assert_greater_equal (filled_request[i], 01013 first_object_on_proc[procup]); 01014 libmesh_assert_less (filled_request[i], 01015 first_object_on_proc[procup] + 01016 objects_on_proc[procup]); 01017 obj->set_id(filled_request[i]); 01018 01019 #ifdef LIBMESH_ENABLE_UNIQUE_ID 01020 if (!obj->valid_unique_id() && unique_filled_request[i] != DofObject::invalid_unique_id) 01021 obj->set_unique_id() = unique_filled_request[i]; 01022 #endif 01023 } 01024 } 01025 } 01026 01027 // Next set unpartitioned object ids 01028 next_id = 0; 01029 for (processor_id_type i=0; i != this->n_processors(); ++i) 01030 next_id += objects_on_proc[i]; 01031 for (it = objects.begin(); it != end; ++it) 01032 { 01033 T *obj = *it; 01034 if (obj->processor_id() == DofObject::invalid_processor_id) 01035 obj->set_id(next_id++); 01036 } 01037 01038 // Finally shuffle around objects so that container indices 01039 // match ids 01040 end = objects.end(); 01041 for (it = objects.begin(); it != end;) 01042 { 01043 T *obj = *it; 01044 if (obj) // don't try shuffling already-NULL entries 01045 { 01046 T *next = objects[obj->id()]; 01047 // If we have to move this object 01048 if (next != obj) 01049 { 01050 // NULL out its original position for now 01051 // (our shuffling may put another object there shortly) 01052 *it = NULL; 01053 01054 // There may already be another object with this id that 01055 // needs to be moved itself 01056 while (next) 01057 { 01058 // We shouldn't be trying to give two objects the 01059 // same id 01060 libmesh_assert_not_equal_to (next->id(), obj->id()); 01061 objects[obj->id()] = obj; 01062 obj = next; 01063 next = objects[obj->id()]; 01064 } 01065 objects[obj->id()] = obj; 01066 } 01067 } 01068 // Remove any container entries that were left as NULL, 01069 // being careful not to invalidate our iterator 01070 if (!*it) 01071 objects.erase(it++); 01072 else 01073 ++it; 01074 } 01075 01076 return first_free_id; 01077 } 01078 01079 01080 void ParallelMesh::renumber_nodes_and_elements () 01081 { 01082 parallel_object_only(); 01083 01084 if (_skip_renumber_nodes_and_elements) 01085 { 01086 this->update_parallel_id_counts(); 01087 return; 01088 } 01089 01090 START_LOG("renumber_nodes_and_elements()", "ParallelMesh"); 01091 01092 #ifdef DEBUG 01093 // Make sure our ids and flags are consistent 01094 this->libmesh_assert_valid_parallel_ids(); 01095 this->libmesh_assert_valid_parallel_flags(); 01096 #endif 01097 01098 std::set<dof_id_type> used_nodes; 01099 01100 // flag the nodes we need 01101 { 01102 element_iterator it = elements_begin(); 01103 element_iterator end = elements_end(); 01104 01105 for (; it != end; ++it) 01106 { 01107 Elem *el = *it; 01108 01109 for (unsigned int n=0; n != el->n_nodes(); ++n) 01110 used_nodes.insert(el->node(n)); 01111 } 01112 } 01113 01114 // Nodes not connected to any local elements, and NULL node entries 01115 // in our container, are deleted 01116 { 01117 node_iterator_imp it = _nodes.begin(); 01118 node_iterator_imp end = _nodes.end(); 01119 01120 for (; it != end;) 01121 { 01122 Node *nd = *it; 01123 if (!nd) 01124 _nodes.erase(it++); 01125 else if (!used_nodes.count(nd->id())) 01126 { 01127 // remove any boundary information associated with 01128 // this node 01129 this->get_boundary_info().remove (nd); 01130 01131 // delete the node 01132 delete nd; 01133 01134 _nodes.erase(it++); 01135 } 01136 else 01137 ++it; 01138 } 01139 } 01140 01141 // Finally renumber all the elements 01142 _n_elem = this->renumber_dof_objects (this->_elements); 01143 01144 // and all the remaining nodes 01145 _n_nodes = this->renumber_dof_objects (this->_nodes); 01146 01147 // And figure out what IDs we should use when adding new nodes and 01148 // new elements 01149 this->update_parallel_id_counts(); 01150 01151 // Make sure our caches are up to date and our 01152 // DofObjects are well packed 01153 #ifdef DEBUG 01154 libmesh_assert_equal_to (this->n_nodes(), this->parallel_n_nodes()); 01155 libmesh_assert_equal_to (this->n_elem(), this->parallel_n_elem()); 01156 const dof_id_type pmax_node_id = this->parallel_max_node_id(); 01157 const dof_id_type pmax_elem_id = this->parallel_max_elem_id(); 01158 libmesh_assert_equal_to (this->max_node_id(), pmax_node_id); 01159 libmesh_assert_equal_to (this->max_elem_id(), pmax_elem_id); 01160 libmesh_assert_equal_to (this->n_nodes(), this->max_node_id()); 01161 libmesh_assert_equal_to (this->n_elem(), this->max_elem_id()); 01162 01163 // Make sure our ids and flags are consistent 01164 this->libmesh_assert_valid_parallel_ids(); 01165 this->libmesh_assert_valid_parallel_flags(); 01166 01167 // And make sure we've made our numbering monotonic 01168 MeshTools::libmesh_assert_valid_elem_ids(*this); 01169 #endif 01170 01171 STOP_LOG("renumber_nodes_and_elements()", "ParallelMesh"); 01172 } 01173 01174 01175 01176 void ParallelMesh::fix_broken_node_and_element_numbering () 01177 { 01178 // We need access to iterators for the underlying containers, 01179 // not the mapvector<> reimplementations. 01180 mapvector<Node*,dof_id_type>::maptype &nodes = this->_nodes; 01181 mapvector<Elem*,dof_id_type>::maptype &elems = this->_elements; 01182 01183 // Nodes first 01184 { 01185 mapvector<Node*,dof_id_type>::maptype::iterator 01186 it = nodes.begin(), 01187 end = nodes.end(); 01188 01189 for (; it != end; ++it) 01190 if (it->second != NULL) 01191 it->second->set_id() = it->first; 01192 } 01193 01194 // Elements next 01195 { 01196 mapvector<Elem*,dof_id_type>::maptype::iterator 01197 it = elems.begin(), 01198 end = elems.end(); 01199 01200 for (; it != end; ++it) 01201 if (it->second != NULL) 01202 it->second->set_id() = it->first; 01203 } 01204 } 01205 01206 01207 01208 dof_id_type ParallelMesh::n_active_elem () const 01209 { 01210 parallel_object_only(); 01211 01212 // Get local active elements first 01213 dof_id_type active_elements = 01214 static_cast<dof_id_type>(std::distance (this->active_local_elements_begin(), 01215 this->active_local_elements_end())); 01216 this->comm().sum(active_elements); 01217 01218 // Then add unpartitioned active elements, which should exist on 01219 // every processor 01220 active_elements += 01221 static_cast<dof_id_type>(std::distance 01222 (this->active_pid_elements_begin(DofObject::invalid_processor_id), 01223 this->active_pid_elements_end(DofObject::invalid_processor_id))); 01224 return active_elements; 01225 } 01226 01227 01228 01229 void ParallelMesh::delete_remote_elements() 01230 { 01231 #ifdef DEBUG 01232 // Make sure our neighbor links are all fine 01233 MeshTools::libmesh_assert_valid_neighbors(*this); 01234 01235 // And our child/parent links, and our flags 01236 MeshTools::libmesh_assert_valid_refinement_tree(*this); 01237 01238 // Make sure our ids and flags are consistent 01239 this->libmesh_assert_valid_parallel_ids(); 01240 this->libmesh_assert_valid_parallel_flags(); 01241 01242 libmesh_assert_equal_to (this->n_nodes(), this->parallel_n_nodes()); 01243 libmesh_assert_equal_to (this->n_elem(), this->parallel_n_elem()); 01244 const dof_id_type pmax_node_id = this->parallel_max_node_id(); 01245 const dof_id_type pmax_elem_id = this->parallel_max_elem_id(); 01246 libmesh_assert_equal_to (this->max_node_id(), pmax_node_id); 01247 libmesh_assert_equal_to (this->max_elem_id(), pmax_elem_id); 01248 #endif 01249 01250 _is_serial = false; 01251 MeshCommunication().delete_remote_elements(*this, _extra_ghost_elems); 01252 01253 libmesh_assert_equal_to (this->max_elem_id(), this->parallel_max_elem_id()); 01254 01255 // Now make sure the containers actually shrink - strip 01256 // any newly-created NULL voids out of the element array 01257 mapvector<Elem*,dof_id_type>::veclike_iterator e_it = _elements.begin(); 01258 const mapvector<Elem*,dof_id_type>::veclike_iterator e_end = _elements.end(); 01259 for (; e_it != e_end;) 01260 if (!*e_it) 01261 _elements.erase(e_it++); 01262 else 01263 ++e_it; 01264 01265 mapvector<Node*,dof_id_type>::veclike_iterator n_it = _nodes.begin(); 01266 const mapvector<Node*,dof_id_type>::veclike_iterator n_end = _nodes.end(); 01267 for (; n_it != n_end;) 01268 if (!*n_it) 01269 _nodes.erase(n_it++); 01270 else 01271 ++n_it; 01272 01273 // We may have deleted no-longer-connected nodes or coarsened-away 01274 // elements; let's update our caches. 01275 this->update_parallel_id_counts(); 01276 01277 #ifdef DEBUG 01278 // We might not have well-packed objects if the user didn't allow us 01279 // to renumber 01280 // libmesh_assert_equal_to (this->n_nodes(), this->max_node_id()); 01281 // libmesh_assert_equal_to (this->n_elem(), this->max_elem_id()); 01282 01283 // Make sure our neighbor links are all fine 01284 MeshTools::libmesh_assert_valid_neighbors(*this); 01285 01286 // And our child/parent links, and our flags 01287 MeshTools::libmesh_assert_valid_refinement_tree(*this); 01288 01289 // Make sure our ids and flags are consistent 01290 this->libmesh_assert_valid_parallel_ids(); 01291 this->libmesh_assert_valid_parallel_flags(); 01292 #endif 01293 } 01294 01295 01296 void ParallelMesh::add_extra_ghost_elem(Elem* e) 01297 { 01298 // First add the elem like normal 01299 add_elem(e); 01300 01301 // Now add it to the set that won't be deleted when we call 01302 // delete_remote_elements() 01303 _extra_ghost_elems.insert(e); 01304 } 01305 01306 01307 void ParallelMesh::allgather() 01308 { 01309 if (_is_serial) 01310 return; 01311 _is_serial = true; 01312 MeshCommunication().allgather(*this); 01313 01314 // Make sure our caches are up to date and our 01315 // DofObjects are well packed 01316 #ifdef DEBUG 01317 libmesh_assert_equal_to (this->n_nodes(), this->parallel_n_nodes()); 01318 libmesh_assert_equal_to (this->n_elem(), this->parallel_n_elem()); 01319 const dof_id_type pmax_node_id = this->parallel_max_node_id(); 01320 const dof_id_type pmax_elem_id = this->parallel_max_elem_id(); 01321 libmesh_assert_equal_to (this->max_node_id(), pmax_node_id); 01322 libmesh_assert_equal_to (this->max_elem_id(), pmax_elem_id); 01323 01324 // If we've disabled renumbering we can't be sure we're contiguous 01325 // libmesh_assert_equal_to (this->n_nodes(), this->max_node_id()); 01326 // libmesh_assert_equal_to (this->n_elem(), this->max_elem_id()); 01327 01328 // Make sure our neighbor links are all fine 01329 MeshTools::libmesh_assert_valid_neighbors(*this); 01330 01331 // Make sure our ids and flags are consistent 01332 this->libmesh_assert_valid_parallel_ids(); 01333 this->libmesh_assert_valid_parallel_flags(); 01334 #endif 01335 } 01336 01337 #ifdef LIBMESH_ENABLE_UNIQUE_ID 01338 void ParallelMesh::assign_unique_ids() 01339 { 01340 { 01341 elem_iterator_imp it = _elements.begin(); 01342 const elem_iterator_imp end = _elements.end(); 01343 01344 for (; it != end; ++it) 01345 if ((*it) && ! (*it)->valid_unique_id() && processor_id() == (*it)->processor_id()) 01346 { 01347 (*it)->set_unique_id() = _next_unique_id; 01348 _next_unique_id += this->n_processors(); 01349 } 01350 } 01351 01352 { 01353 node_iterator_imp it = _nodes.begin(); 01354 node_iterator_imp end = _nodes.end(); 01355 01356 for (; it != end; ++it) 01357 if ((*it) && ! (*it)->valid_unique_id() && processor_id() == (*it)->processor_id()) 01358 { 01359 (*it)->set_unique_id() = _next_unique_id; 01360 _next_unique_id += this->n_processors(); 01361 } 01362 } 01363 } 01364 #endif 01365 01366 01367 } // namespace libMesh