📄 parallel_mesh.c
字号:
// $Id: parallel_mesh.C 2803 2008-04-23 21:14:29Z roystgnr $// The libMesh Finite Element Library.// Copyright (C) 2002-2007 Benjamin S. Kirk, John W. Peterson // This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Lesser General Public License for more details. // You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA// Local includes#include "boundary_info.h"#include "elem.h"#include "libmesh_logging.h"#include "mesh_communication.h"#include "parallel_mesh.h"#include "parallel.h"// ------------------------------------------------------------// ParallelMesh class member functionsParallelMesh::ParallelMesh (unsigned int d) : UnstructuredMesh (d), _is_serial(true), _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0), _next_free_local_node_id(libMesh::processor_id()), _next_free_local_elem_id(libMesh::processor_id()), _next_free_unpartitioned_node_id(libMesh::n_processors()), _next_free_unpartitioned_elem_id(libMesh::n_processors()){}ParallelMesh::~ParallelMesh (){ this->clear(); // Free nodes and elements}// This might be specialized later, but right now it's just here to// make sure the compiler doesn't give us a default (non-deep) copy// constructor instead.ParallelMesh::ParallelMesh (const ParallelMesh &other_mesh) : UnstructuredMesh (other_mesh){ this->copy_nodes_and_elements(other_mesh); _n_nodes = other_mesh.n_nodes(); _n_elem = other_mesh.n_elem(); _max_node_id = other_mesh.max_node_id(); _max_elem_id = other_mesh.max_elem_id();}ParallelMesh::ParallelMesh (const UnstructuredMesh &other_mesh) : UnstructuredMesh (other_mesh){ this->copy_nodes_and_elements(other_mesh); _n_nodes = other_mesh.n_nodes(); _n_elem = other_mesh.n_elem(); _max_node_id = other_mesh.max_node_id(); _max_elem_id = other_mesh.max_elem_id();}// We use cached values for these so they can be called// from one processor without bothering the rest, but// we may need to update those caches before doing a full// renumberingvoid ParallelMesh::update_parallel_id_counts(){ // This function must be run on all processors at once parallel_only(); _n_elem = this->n_local_elem(); Parallel::sum(_n_elem); _n_elem += this->n_unpartitioned_elem(); _max_elem_id = _elements.empty() ? 0 : _elements.rbegin()->first + 1; Parallel::max(_max_elem_id); _n_nodes = this->n_local_nodes(); Parallel::sum(_n_nodes); _n_nodes += this->n_unpartitioned_nodes(); _max_node_id = _nodes.empty() ? 0 : _nodes.rbegin()->first + 1; Parallel::max(_max_node_id);}// Or in debug mode we may want to test the uncached values without// changing the cacheunsigned int ParallelMesh::parallel_n_elem() const{ // This function must be run on all processors at once parallel_only(); unsigned int n_local = this->n_local_elem(); Parallel::sum(n_local); n_local += this->n_unpartitioned_elem(); return n_local;}unsigned int ParallelMesh::parallel_max_elem_id() const{ // This function must be run on all processors at once parallel_only(); unsigned int max_local = _elements.empty() ? 0 : _elements.rbegin()->first + 1; Parallel::max(max_local); return max_local;}unsigned int ParallelMesh::parallel_n_nodes() const{ // This function must be run on all processors at once parallel_only(); unsigned int n_local = this->n_local_nodes(); Parallel::sum(n_local); n_local += this->n_unpartitioned_nodes(); return n_local;}unsigned int ParallelMesh::parallel_max_node_id() const{ // This function must be run on all processors at once parallel_only(); unsigned int max_local = _nodes.empty() ? 0 : _nodes.rbegin()->first + 1; Parallel::max(max_local); return max_local;}const Point& ParallelMesh::point (const unsigned int i) const{ libmesh_assert (_nodes[i] != NULL); libmesh_assert (_nodes[i]->id() == i); return (*_nodes[i]);}const Node& ParallelMesh::node (const unsigned int i) const{ libmesh_assert (_nodes[i] != NULL); libmesh_assert (_nodes[i]->id() == i); return (*_nodes[i]);}Node& ParallelMesh::node (const unsigned int i){ libmesh_assert (_nodes[i] != NULL); libmesh_assert (_nodes[i]->id() == i); return (*_nodes[i]);}const Node* ParallelMesh::node_ptr (const unsigned int i) const{// libmesh_assert (_nodes[i] != NULL); libmesh_assert (_nodes[i] == NULL || _nodes[i]->id() == i); return _nodes[i];}Node* & ParallelMesh::node_ptr (const unsigned int i){// libmesh_assert (_nodes[i] != NULL); libmesh_assert (_nodes[i] == NULL || _nodes[i]->id() == i); return _nodes[i];}Elem* ParallelMesh::elem (const unsigned int i) const{// libmesh_assert (_elements[i] != NULL); libmesh_assert (_elements[i] == NULL || _elements[i]->id() == i); return _elements[i];}Elem* ParallelMesh::add_elem (Elem *e){ // Don't try to add NULLs! libmesh_assert(e); const unsigned int elem_procid = e->processor_id(); if (!e->valid_id()) { // Use the unpartitioned ids for unpartitioned elems, // in serial, and temporarily for ghost elems unsigned int *next_id = &_next_free_unpartitioned_elem_id; if (elem_procid == libMesh::processor_id() && !this->is_serial()) next_id = &_next_free_local_elem_id; e->set_id (*next_id); *next_id += libMesh::n_processors() + 1; } else { if (_next_free_unpartitioned_elem_id <= e->id()) _next_free_unpartitioned_elem_id += libMesh::n_processors() + 1; if (_next_free_local_elem_id <= e->id()) _next_free_local_elem_id += libMesh::n_processors() + 1; } // Don't try to overwrite existing elems libmesh_assert (!_elements[e->id()]); _elements[e->id()] = e; // Make the cached elem data more accurate _n_elem++; _max_elem_id = std::max(_max_elem_id, e->id()+1); // Unpartitioned elems should be added on every processor// And shouldn't be added in the same batch as ghost elems// But we might be just adding on processor 0 to// broadcast later#if 0#ifdef DEBUG if (elem_procid == DofObject::invalid_processor_id) { unsigned int elem_id = e->id(); Parallel::max(elem_id); libmesh_assert(elem_id == e->id()); }#endif#endif return e;}Elem* ParallelMesh::insert_elem (Elem* e){ if (_elements[e->id()]) this->delete_elem(_elements[e->id()]); _elements[e->id()] = e; return e;}void ParallelMesh::delete_elem(Elem* e){ libmesh_assert (e); // Delete the element from the BoundaryInfo object this->boundary_info->remove(e); // But not yet from the container; we might invalidate // an iterator that way! //_elements.erase(e->id()); // Instead, we set it to NULL for now _elements[e->id()] = NULL; // delete the element delete e;}void ParallelMesh::renumber_elem(const unsigned int old_id, const unsigned int new_id){ Elem *elem = _elements[old_id]; libmesh_assert (elem); libmesh_assert (elem->id() == old_id); elem->set_id(new_id); libmesh_assert (!_elements[new_id]); _elements[new_id] = elem; _elements.erase(old_id);}Node* ParallelMesh::add_point (const Point& p, const unsigned int id, const unsigned int proc_id){ if (_nodes.count(id)) { Node *n = _nodes[id]; libmesh_assert (n); libmesh_assert (n->id() == id); *n = p; n->processor_id() = proc_id; return n; } Node* n = Node::build(p, id).release(); n->processor_id() = proc_id; return ParallelMesh::add_node(n);}Node* ParallelMesh::add_node (Node *n){ // Don't try to add NULLs! libmesh_assert(n); const unsigned int node_procid = n->processor_id(); if (!n->valid_id()) { // Use the unpartitioned ids for unpartitioned nodes, // in serial, and temporarily for ghost nodes unsigned int *next_id = &_next_free_unpartitioned_node_id; if (node_procid == libMesh::processor_id() && !this->is_serial()) next_id = &_next_free_local_node_id; n->set_id (*next_id); *next_id += libMesh::n_processors() + 1; } else { if (_next_free_unpartitioned_node_id <= n->id()) _next_free_unpartitioned_node_id += libMesh::n_processors() + 1; if (_next_free_local_node_id <= n->id()) _next_free_local_node_id += libMesh::n_processors() + 1; } // Don't try to overwrite existing nodes libmesh_assert (!_nodes[n->id()]); _nodes[n->id()] = n; // Make the cached elem data more accurate _n_nodes++; _max_node_id = std::max(_max_node_id, n->id()+1); // Unpartitioned nodes should be added on every processor// And shouldn't be added in the same batch as ghost nodes// But we might be just adding on processor 0 to// broadcast later#if 0#ifdef DEBUG if (node_procid == DofObject::invalid_processor_id) { unsigned int node_id = n->id(); Parallel::max(node_id); libmesh_assert(node_id == n->id()); }#endif#endif return n;}Node* ParallelMesh::insert_node (Node* n){ // If we already have this node we cannot // simply delete it, because we may have elements // which are attached to its address. // // Instead, call the Node = Point assignment operator // to overwrite the spatial coordinates (but keep its // address), delete the provided node, and return the // address of the one we already had. if (_nodes.count(n->id())) { Node *my_n = _nodes[n->id()]; *my_n = static_cast<Point>(*n); delete n; n = my_n; } else _nodes[n->id()] = n; return n;}void ParallelMesh::delete_node(Node* n){ libmesh_assert (n != NULL); libmesh_assert (_nodes[n->id()] != NULL); // Delete the node from the BoundaryInfo object this->boundary_info->remove(n); // And from the container _nodes.erase(n->id()); // delete the node delete n;}void ParallelMesh::renumber_node(const unsigned int old_id, const unsigned int new_id){ Node *node = _nodes[old_id]; libmesh_assert (node); libmesh_assert (node->id() == old_id); node->set_id(new_id); libmesh_assert (!_nodes[new_id]); _nodes[new_id] = node; _nodes.erase(old_id);}void ParallelMesh::clear (){ // Call parent clear function MeshBase::clear();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -