libMesh::CentroidPartitioner Class Reference

#include <centroid_partitioner.h>

Inheritance diagram for libMesh::CentroidPartitioner:

List of all members.

Public Types

enum  CentroidSortMethod {
  X = 0, Y, Z, RADIAL,
  INVALID_METHOD
}

Public Member Functions

 CentroidPartitioner (const CentroidSortMethod sm=X)
virtual AutoPtr< Partitionerclone () const
CentroidSortMethod sort_method () const
void set_sort_method (const CentroidSortMethod sm)
void partition (MeshBase &mesh, const unsigned int n=libMesh::n_processors())
void repartition (MeshBase &mesh, const unsigned int n=libMesh::n_processors())
virtual void attach_weights (ErrorVector *)

Static Public Member Functions

static void partition_unpartitioned_elements (MeshBase &mesh, const unsigned int n=libMesh::n_processors())
static void set_parent_processor_ids (MeshBase &mesh)
static void set_node_processor_ids (MeshBase &mesh)

Protected Member Functions

virtual void _do_partition (MeshBase &mesh, const unsigned int n)
void single_partition (MeshBase &mesh)
virtual void _do_repartition (MeshBase &mesh, const unsigned int n)

Protected Attributes

ErrorVector_weights

Static Protected Attributes

static const dof_id_type communication_blocksize = 1000000

Private Member Functions

void compute_centroids (MeshBase &mesh)

Static Private Member Functions

static bool sort_x (const std::pair< Point, Elem * > &lhs, const std::pair< Point, Elem * > &rhs)
static bool sort_y (const std::pair< Point, Elem * > &lhs, const std::pair< Point, Elem * > &rhs)
static bool sort_z (const std::pair< Point, Elem * > &lhs, const std::pair< Point, Elem * > &rhs)
static bool sort_radial (const std::pair< Point, Elem * > &lhs, const std::pair< Point, Elem * > &rhs)

Private Attributes

CentroidSortMethod _sort_method
std::vector< std::pair< Point,
Elem * > > 
_elem_centroids

Detailed Description

The centroid partitioner partitions simply based on the locations of element centroids. You must define what you mean by "less than" for the list of element centroids, e.g. if you only care about distance in the z-direction, you would define "less than" differently than if you cared about radial distance.

Author:
John W. Peterson and Benjamin S. Kirk, 2003

Definition at line 52 of file centroid_partitioner.h.


Member Enumeration Documentation

A typedef which is reserved only for use within this class. If X is chosen, then centroid locations will be sorted according to their X-location, etc...

Enumerator:
X 
Y 
Z 
RADIAL 
INVALID_METHOD 

Definition at line 62 of file centroid_partitioner.h.

00062                           {X=0,
00063                            Y,
00064                            Z,
00065                            RADIAL,
00066                            INVALID_METHOD};


Constructor & Destructor Documentation

libMesh::CentroidPartitioner::CentroidPartitioner ( const CentroidSortMethod  sm = X  )  [inline, explicit]

Constructor. Takes the CentroidSortMethod to use, which defaults to X ordering.

Definition at line 73 of file centroid_partitioner.h.

Referenced by clone().

00073 : _sort_method(sm) {}


Member Function Documentation

void libMesh::CentroidPartitioner::_do_partition ( MeshBase mesh,
const unsigned int  n 
) [protected, virtual]

Partitions the mesh into n subdomains. This is a required interface for the class.

Implements libMesh::Partitioner.

Definition at line 32 of file centroid_partitioner.C.

References _elem_centroids, compute_centroids(), std::min(), libMesh::MeshTools::n_elem(), libMesh::MeshBase::n_elem(), libMesh::DofObject::processor_id(), RADIAL, libMesh::Partitioner::single_partition(), sort_method(), sort_radial(), sort_x(), sort_y(), sort_z(), X, Y, and Z.

00034 {
00035   // Check for an easy return
00036   if (n == 1)
00037     {
00038       this->single_partition (mesh);
00039       return;
00040     }
00041 
00042 
00043   // Possibly reconstruct centroids
00044   if (mesh.n_elem() != _elem_centroids.size())
00045     this->compute_centroids (mesh);
00046 
00047 
00048 
00049   switch (this->sort_method())
00050     {
00051     case X:
00052       {
00053         std::sort(_elem_centroids.begin(),
00054                   _elem_centroids.end(),
00055                   CentroidPartitioner::sort_x);
00056 
00057         break;
00058       }
00059 
00060 
00061     case Y:
00062       {
00063         std::sort(_elem_centroids.begin(),
00064                   _elem_centroids.end(),
00065                   CentroidPartitioner::sort_y);
00066 
00067         break;
00068 
00069       }
00070 
00071 
00072     case Z:
00073       {
00074         std::sort(_elem_centroids.begin(),
00075                   _elem_centroids.end(),
00076                   CentroidPartitioner::sort_z);
00077 
00078         break;
00079       }
00080 
00081 
00082      case RADIAL:
00083       {
00084         std::sort(_elem_centroids.begin(),
00085                   _elem_centroids.end(),
00086                   CentroidPartitioner::sort_radial);
00087 
00088         break;
00089       }
00090     default:
00091       libmesh_error();
00092     }
00093 
00094 
00095   // Make sure the user has not handed us an
00096   // invalid number of partitions.
00097   libmesh_assert_greater (n, 0);
00098 
00099   // the number of elements, e.g. 1000
00100   const dof_id_type n_elem      = mesh.n_elem();
00101   // the number of elements per processor, e.g 400
00102   const dof_id_type target_size = n_elem / n;
00103 
00104   // Make sure the mesh hasn't changed since the
00105   // last time we computed the centroids.
00106   libmesh_assert_equal_to (mesh.n_elem(), _elem_centroids.size());
00107 
00108   for (dof_id_type i=0; i<n_elem; i++)
00109     {
00110       Elem* elem = _elem_centroids[i].second;
00111 
00112       elem->processor_id() =
00113         std::min (libmesh_cast_int<processor_id_type>(i / target_size),
00114                   libmesh_cast_int<processor_id_type>(n-1));
00115     }
00116 }

virtual void libMesh::Partitioner::_do_repartition ( MeshBase mesh,
const unsigned int  n 
) [inline, protected, virtual, inherited]

This is the actual re-partitioning method which can be overloaded in derived classes. Note that the default behavior is to simply call the partition function.

Reimplemented in libMesh::ParmetisPartitioner.

Definition at line 143 of file partitioner.h.

References libMesh::Partitioner::_do_partition().

Referenced by libMesh::Partitioner::repartition().

00144                                                       { this->_do_partition (mesh, n); }

virtual void libMesh::Partitioner::attach_weights ( ErrorVector  )  [inline, virtual, inherited]

Attach weights that can be used for partitioning. This ErrorVector should be _exactly_ the same on every processor and should have mesh->max_elem_id() entries.

Reimplemented in libMesh::MetisPartitioner.

Definition at line 118 of file partitioner.h.

00118 { libmesh_not_implemented(); }

virtual AutoPtr<Partitioner> libMesh::CentroidPartitioner::clone (  )  const [inline, virtual]

Creates a new partitioner of this type and returns it in an AutoPtr.

Implements libMesh::Partitioner.

Definition at line 79 of file centroid_partitioner.h.

References CentroidPartitioner(), and sort_method().

00079                                               {
00080     AutoPtr<Partitioner> cloned_partitioner
00081       (new CentroidPartitioner(sort_method()));
00082     return cloned_partitioner;
00083   }

void libMesh::CentroidPartitioner::compute_centroids ( MeshBase mesh  )  [private]

Computes a list of element centroids for the mesh. This list will be kept around in case a repartition is desired.

Definition at line 125 of file centroid_partitioner.C.

References _elem_centroids, libMesh::Elem::centroid(), libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), and libMesh::MeshBase::n_elem().

Referenced by _do_partition().

00126 {
00127   _elem_centroids.clear();
00128   _elem_centroids.reserve(mesh.n_elem());
00129 
00130 //   elem_iterator it(mesh.elements_begin());
00131 //   const elem_iterator it_end(mesh.elements_end());
00132 
00133   MeshBase::element_iterator       it     = mesh.elements_begin();
00134   const MeshBase::element_iterator it_end = mesh.elements_end();
00135 
00136   for (; it != it_end; ++it)
00137     {
00138       Elem* elem = *it;
00139 
00140       _elem_centroids.push_back(std::make_pair(elem->centroid(), elem));
00141     }
00142 }

void libMesh::Partitioner::partition ( MeshBase mesh,
const unsigned int  n = libMesh::n_processors() 
) [inherited]

Partition the MeshBase into n parts. If the user does not specify a number of pieces into which the mesh should be partitioned, then the default behavior of the partitioner is to partition according to the number of processors defined in libMesh::n_processors(). The partitioner currently does not modify the subdomain_id of each element. This number is reserved for things like material properties, etc.

Definition at line 48 of file partitioner.C.

References libMesh::Partitioner::_do_partition(), libMesh::MeshTools::libmesh_assert_valid_procids< Elem >(), libMesh::MeshTools::libmesh_assert_valid_remote_elems(), std::min(), libMesh::MeshBase::n_active_elem(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::MeshBase::redistribute(), libMesh::MeshBase::set_n_partitions(), libMesh::Partitioner::set_node_processor_ids(), libMesh::Partitioner::set_parent_processor_ids(), libMesh::Partitioner::single_partition(), and libMesh::MeshBase::update_post_partitioning().

Referenced by libMesh::SFCPartitioner::_do_partition(), libMesh::MetisPartitioner::_do_partition(), and libMesh::ParmetisPartitioner::_do_repartition().

00050 {
00051   parallel_only();
00052 
00053   // BSK - temporary fix while redistribution is integrated 6/26/2008
00054   // Uncomment this to not repartition in parallel
00055 //   if (!mesh.is_serial())
00056 //     return;
00057 
00058   // we cannot partition into more pieces than we have
00059   // active elements!
00060   const unsigned int n_parts =
00061     static_cast<unsigned int>
00062       (std::min(mesh.n_active_elem(), static_cast<dof_id_type>(n)));
00063 
00064   // Set the number of partitions in the mesh
00065   mesh.set_n_partitions()=n_parts;
00066 
00067   if (n_parts == 1)
00068     {
00069       this->single_partition (mesh);
00070       return;
00071     }
00072 
00073   // First assign a temporary partitioning to any unpartitioned elements
00074   Partitioner::partition_unpartitioned_elements(mesh, n_parts);
00075 
00076   // Call the partitioning function
00077   this->_do_partition(mesh,n_parts);
00078 
00079   // Set the parent's processor ids
00080   Partitioner::set_parent_processor_ids(mesh);
00081 
00082   // Redistribute elements if necessary, before setting node processor
00083   // ids, to make sure those will be set consistently
00084   mesh.redistribute();
00085 
00086 #ifdef DEBUG
00087   MeshTools::libmesh_assert_valid_remote_elems(mesh);
00088 
00089   // Messed up elem processor_id()s can leave us without the child
00090   // elements we need to restrict vectors on a distributed mesh
00091   MeshTools::libmesh_assert_valid_procids<Elem>(mesh);
00092 #endif
00093 
00094   // Set the node's processor ids
00095   Partitioner::set_node_processor_ids(mesh);
00096 
00097 #ifdef DEBUG
00098   MeshTools::libmesh_assert_valid_procids<Elem>(mesh);
00099 #endif
00100 
00101   // Give derived Mesh classes a chance to update any cached data to
00102   // reflect the new partitioning
00103   mesh.update_post_partitioning();
00104 }

void libMesh::Partitioner::partition_unpartitioned_elements ( MeshBase mesh,
const unsigned int  n = libMesh::n_processors() 
) [static, inherited]

This function

Definition at line 168 of file partitioner.C.

References libMesh::MeshTools::bounding_box(), end, libMesh::MeshTools::n_elem(), libMesh::n_processors(), libMesh::DofObject::processor_id(), libMesh::MeshBase::unpartitioned_elements_begin(), and libMesh::MeshBase::unpartitioned_elements_end().

Referenced by libMesh::Partitioner::partition(), and libMesh::Partitioner::repartition().

00170 {
00171   MeshBase::element_iterator       it  = mesh.unpartitioned_elements_begin();
00172   const MeshBase::element_iterator end = mesh.unpartitioned_elements_end();
00173 
00174   const dof_id_type n_unpartitioned_elements = MeshTools::n_elem (it, end);
00175 
00176   // the unpartitioned elements must exist on all processors. If the range is empty on one
00177   // it is empty on all, and we can quit right here.
00178   if (!n_unpartitioned_elements) return;
00179 
00180   // find the target subdomain sizes
00181   std::vector<dof_id_type> subdomain_bounds(libMesh::n_processors());
00182 
00183   for (processor_id_type pid=0; pid<libMesh::n_processors(); pid++)
00184     {
00185       dof_id_type tgt_subdomain_size = 0;
00186 
00187       // watch out for the case that n_subdomains < n_processors
00188       if (pid < n_subdomains)
00189         {
00190           tgt_subdomain_size = n_unpartitioned_elements/n_subdomains;
00191 
00192           if (pid < n_unpartitioned_elements%n_subdomains)
00193             tgt_subdomain_size++;
00194 
00195         }
00196 
00197       //libMesh::out << "pid, #= " << pid << ", " << tgt_subdomain_size << std::endl;
00198       if (pid == 0)
00199         subdomain_bounds[0] = tgt_subdomain_size;
00200       else
00201         subdomain_bounds[pid] = subdomain_bounds[pid-1] + tgt_subdomain_size;
00202     }
00203 
00204   libmesh_assert_equal_to (subdomain_bounds.back(), n_unpartitioned_elements);
00205 
00206   // create the unique mapping for all unpartitioned elements independent of partitioning
00207   // determine the global indexing for all the unpartitoned elements
00208   std::vector<dof_id_type> global_indices;
00209 
00210   // Calling this on all processors a unique range in [0,n_unpartitioned_elements) is constructed.
00211   // Only the indices for the elements we pass in are returned in the array.
00212   MeshCommunication().find_global_indices (MeshTools::bounding_box(mesh), it, end,
00213                                            global_indices);
00214 
00215   for (dof_id_type cnt=0; it != end; ++it)
00216     {
00217       Elem *elem = *it;
00218 
00219       libmesh_assert_less (cnt, global_indices.size());
00220       const dof_id_type global_index =
00221         global_indices[cnt++];
00222 
00223       libmesh_assert_less (global_index, subdomain_bounds.back());
00224       libmesh_assert_less (global_index, n_unpartitioned_elements);
00225 
00226       const processor_id_type subdomain_id =
00227         libmesh_cast_int<processor_id_type>
00228         (std::distance(subdomain_bounds.begin(),
00229                        std::upper_bound(subdomain_bounds.begin(),
00230                                         subdomain_bounds.end(),
00231                                         global_index)));
00232       libmesh_assert_less (subdomain_id, n_subdomains);
00233 
00234       elem->processor_id() = subdomain_id;
00235       //libMesh::out << "assigning " << global_index << " to " << subdomain_id << std::endl;
00236     }
00237 }

void libMesh::Partitioner::repartition ( MeshBase mesh,
const unsigned int  n = libMesh::n_processors() 
) [inherited]

Repartitions the MeshBase into n parts. This is required since some partitoning algorithms can repartition more efficiently than computing a new partitioning from scratch. The default behavior is to simply call this->partition(n)

Definition at line 110 of file partitioner.C.

References libMesh::Partitioner::_do_repartition(), std::min(), libMesh::MeshBase::n_active_elem(), libMesh::Partitioner::partition_unpartitioned_elements(), libMesh::MeshBase::set_n_partitions(), libMesh::Partitioner::set_node_processor_ids(), libMesh::Partitioner::set_parent_processor_ids(), and libMesh::Partitioner::single_partition().

00112 {
00113   // we cannot partition into more pieces than we have
00114   // active elements!
00115   const unsigned int n_parts =
00116     static_cast<unsigned int>
00117       (std::min(mesh.n_active_elem(), static_cast<dof_id_type>(n)));
00118 
00119   // Set the number of partitions in the mesh
00120   mesh.set_n_partitions()=n_parts;
00121 
00122   if (n_parts == 1)
00123     {
00124       this->single_partition (mesh);
00125       return;
00126     }
00127 
00128   // First assign a temporary partitioning to any unpartitioned elements
00129   Partitioner::partition_unpartitioned_elements(mesh, n_parts);
00130 
00131   // Call the partitioning function
00132   this->_do_repartition(mesh,n_parts);
00133 
00134   // Set the parent's processor ids
00135   Partitioner::set_parent_processor_ids(mesh);
00136 
00137   // Set the node's processor ids
00138   Partitioner::set_node_processor_ids(mesh);
00139 }

void libMesh::Partitioner::set_node_processor_ids ( MeshBase mesh  )  [static, inherited]

This function is called after partitioning to set the processor IDs for the nodes. By definition, a Node's processor ID is the minimum processor ID for all of the elements which share the node.

Definition at line 419 of file partitioner.C.

References libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::CommWorld, libMesh::Elem::get_node(), libMesh::DofObject::id(), libMesh::DofObject::invalid_processor_id, libMesh::DofObject::invalidate_processor_id(), libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), std::min(), libMesh::MeshTools::n_elem(), libMesh::Elem::n_nodes(), libMesh::MeshBase::n_partitions(), libMesh::n_processors(), libMesh::MeshBase::node_ptr(), libMesh::MeshBase::nodes_begin(), libMesh::MeshBase::nodes_end(), libMesh::MeshBase::not_active_elements_begin(), libMesh::MeshBase::not_active_elements_end(), libMesh::processor_id(), libMesh::DofObject::processor_id(), libMesh::Parallel::Communicator::send_receive(), libMesh::MeshBase::subactive_elements_begin(), libMesh::MeshBase::subactive_elements_end(), libMesh::MeshBase::unpartitioned_elements_begin(), and libMesh::MeshBase::unpartitioned_elements_end().

Referenced by libMesh::UnstructuredMesh::all_first_order(), libMesh::Partitioner::partition(), libMesh::XdrIO::read(), libMesh::Partitioner::repartition(), and libMesh::BoundaryInfo::sync().

00420 {
00421   START_LOG("set_node_processor_ids()","Partitioner");
00422 
00423   // This function must be run on all processors at once
00424   parallel_only();
00425 
00426   // If we have any unpartitioned elements at this
00427   // stage there is a problem
00428   libmesh_assert (MeshTools::n_elem(mesh.unpartitioned_elements_begin(),
00429                             mesh.unpartitioned_elements_end()) == 0);
00430 
00431 
00432 //   const dof_id_type orig_n_local_nodes = mesh.n_local_nodes();
00433 
00434 //   libMesh::err << "[" << libMesh::processor_id() << "]: orig_n_local_nodes="
00435 //          << orig_n_local_nodes << std::endl;
00436 
00437   // Build up request sets.  Each node is currently owned by a processor because
00438   // it is connected to an element owned by that processor.  However, during the
00439   // repartitioning phase that element may have been assigned a new processor id, but
00440   // it is still resident on the original processor.  We need to know where to look
00441   // for new ids before assigning new ids, otherwise we may be asking the wrong processors
00442   // for the wrong information.
00443   //
00444   // The only remaining issue is what to do with unpartitioned nodes.  Since they are required
00445   // to live on all processors we can simply rely on ourselves to number them properly.
00446   std::vector<std::vector<dof_id_type> >
00447     requested_node_ids(libMesh::n_processors());
00448 
00449   // Loop over all the nodes, count the ones on each processor.  We can skip ourself
00450   std::vector<dof_id_type> ghost_nodes_from_proc(libMesh::n_processors(), 0);
00451 
00452   MeshBase::node_iterator       node_it  = mesh.nodes_begin();
00453   const MeshBase::node_iterator node_end = mesh.nodes_end();
00454 
00455   for (; node_it != node_end; ++node_it)
00456     {
00457       Node *node = *node_it;
00458       libmesh_assert(node);
00459       const processor_id_type current_pid = node->processor_id();
00460       if (current_pid != libMesh::processor_id() &&
00461           current_pid != DofObject::invalid_processor_id)
00462         {
00463           libmesh_assert_less (current_pid, ghost_nodes_from_proc.size());
00464           ghost_nodes_from_proc[current_pid]++;
00465         }
00466     }
00467 
00468   // We know how many objects live on each processor, so reserve()
00469   // space for each.
00470   for (processor_id_type pid=0; pid != libMesh::n_processors(); ++pid)
00471     requested_node_ids[pid].reserve(ghost_nodes_from_proc[pid]);
00472 
00473   // We need to get the new pid for each node from the processor
00474   // which *currently* owns the node.  We can safely skip ourself
00475   for (node_it = mesh.nodes_begin(); node_it != node_end; ++node_it)
00476     {
00477       Node *node = *node_it;
00478       libmesh_assert(node);
00479       const processor_id_type current_pid = node->processor_id();
00480       if (current_pid != libMesh::processor_id() &&
00481           current_pid != DofObject::invalid_processor_id)
00482         {
00483           libmesh_assert_less (current_pid, requested_node_ids.size());
00484           libmesh_assert_less (requested_node_ids[current_pid].size(),
00485                               ghost_nodes_from_proc[current_pid]);
00486           requested_node_ids[current_pid].push_back(node->id());
00487         }
00488 
00489       // Unset any previously-set node processor ids
00490       node->invalidate_processor_id();
00491     }
00492 
00493   // Loop over all the active elements
00494   MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
00495   const MeshBase::element_iterator elem_end = mesh.active_elements_end();
00496 
00497   for ( ; elem_it != elem_end; ++elem_it)
00498     {
00499       Elem* elem = *elem_it;
00500       libmesh_assert(elem);
00501 
00502       libmesh_assert_not_equal_to (elem->processor_id(), DofObject::invalid_processor_id);
00503 
00504       // For each node, set the processor ID to the min of
00505       // its current value and this Element's processor id.
00506       //
00507       // TODO: we would probably get better parallel partitioning if
00508       // we did something like "min for even numbered nodes, max for
00509       // odd numbered".  We'd need to be careful about how that would
00510       // affect solution ordering for I/O, though.
00511       for (unsigned int n=0; n<elem->n_nodes(); ++n)
00512         elem->get_node(n)->processor_id() = std::min(elem->get_node(n)->processor_id(),
00513                                                      elem->processor_id());
00514     }
00515 
00516   // And loop over the subactive elements, but don't reassign
00517   // nodes that are already active on another processor.
00518   MeshBase::element_iterator       sub_it  = mesh.subactive_elements_begin();
00519   const MeshBase::element_iterator sub_end = mesh.subactive_elements_end();
00520 
00521   for ( ; sub_it != sub_end; ++sub_it)
00522     {
00523       Elem* elem = *sub_it;
00524       libmesh_assert(elem);
00525 
00526       libmesh_assert_not_equal_to (elem->processor_id(), DofObject::invalid_processor_id);
00527 
00528       for (unsigned int n=0; n<elem->n_nodes(); ++n)
00529         if (elem->get_node(n)->processor_id() == DofObject::invalid_processor_id)
00530           elem->get_node(n)->processor_id() = elem->processor_id();
00531     }
00532 
00533   // Same for the inactive elements -- we will have already gotten most of these
00534   // nodes, *except* for the case of a parent with a subset of children which are
00535   // ghost elements.  In that case some of the parent nodes will not have been
00536   // properly handled yet
00537   MeshBase::element_iterator       not_it  = mesh.not_active_elements_begin();
00538   const MeshBase::element_iterator not_end = mesh.not_active_elements_end();
00539 
00540   for ( ; not_it != not_end; ++not_it)
00541     {
00542       Elem* elem = *not_it;
00543       libmesh_assert(elem);
00544 
00545       libmesh_assert_not_equal_to (elem->processor_id(), DofObject::invalid_processor_id);
00546 
00547       for (unsigned int n=0; n<elem->n_nodes(); ++n)
00548         if (elem->get_node(n)->processor_id() == DofObject::invalid_processor_id)
00549           elem->get_node(n)->processor_id() = elem->processor_id();
00550     }
00551 
00552   // We can't assert that all nodes are connected to elements, because
00553   // a ParallelMesh with NodeConstraints might have pulled in some
00554   // remote nodes solely for evaluating those constraints.
00555   // MeshTools::libmesh_assert_connected_nodes(mesh);
00556 
00557   // For such nodes, we'll do a sanity check later when making sure
00558   // that we successfully reset their processor ids to something
00559   // valid.
00560 
00561   // Next set node ids from other processors, excluding self
00562   for (processor_id_type p=1; p != libMesh::n_processors(); ++p)
00563     {
00564       // Trade my requests with processor procup and procdown
00565       processor_id_type procup = (libMesh::processor_id() + p) %
00566                                   libMesh::n_processors();
00567       processor_id_type procdown = (libMesh::n_processors() +
00568                                     libMesh::processor_id() - p) %
00569                                     libMesh::n_processors();
00570       std::vector<dof_id_type> request_to_fill;
00571       CommWorld.send_receive(procup, requested_node_ids[procup],
00572                              procdown, request_to_fill);
00573 
00574       // Fill those requests in-place
00575       for (std::size_t i=0; i != request_to_fill.size(); ++i)
00576         {
00577           Node *node = mesh.node_ptr(request_to_fill[i]);
00578           libmesh_assert(node);
00579           const processor_id_type new_pid = node->processor_id();
00580           libmesh_assert_not_equal_to (new_pid, DofObject::invalid_processor_id);
00581           libmesh_assert_less (new_pid, mesh.n_partitions()); // this is the correct test --
00582           request_to_fill[i] = new_pid;           //  the number of partitions may
00583         }                                         //  not equal the number of processors
00584 
00585       // Trade back the results
00586       std::vector<dof_id_type> filled_request;
00587       CommWorld.send_receive(procdown, request_to_fill,
00588                              procup,   filled_request);
00589       libmesh_assert_equal_to (filled_request.size(), requested_node_ids[procup].size());
00590 
00591       // And copy the id changes we've now been informed of
00592       for (std::size_t i=0; i != filled_request.size(); ++i)
00593         {
00594           Node *node = mesh.node_ptr(requested_node_ids[procup][i]);
00595           libmesh_assert(node);
00596           libmesh_assert_less (filled_request[i], mesh.n_partitions()); // this is the correct test --
00597           node->processor_id(filled_request[i]);           //  the number of partitions may
00598         }                                                  //  not equal the number of processors
00599     }
00600 
00601 #ifdef DEBUG
00602   MeshTools::libmesh_assert_valid_procids<Node>(mesh);
00603 #endif
00604 
00605   STOP_LOG("set_node_processor_ids()","Partitioner");
00606 }

static void libMesh::Partitioner::set_parent_processor_ids ( MeshBase mesh  )  [static, inherited]

This function is called after partitioning to set the processor IDs for the inactive parent elements. A Parent's processor ID is the same as its first child.

Referenced by libMesh::Partitioner::partition(), and libMesh::Partitioner::repartition().

void libMesh::CentroidPartitioner::set_sort_method ( const CentroidSortMethod  sm  )  [inline]

Change how the elements will be sorted.

Definition at line 93 of file centroid_partitioner.h.

References _sort_method.

00093 {_sort_method = sm; }

void libMesh::Partitioner::single_partition ( MeshBase mesh  )  [protected, inherited]

Trivially "partitions" the mesh for one processor. Simply loops through the elements and assigns all of them to processor 0. Is is provided as a separate function so that derived classes may use it without reimplementing it.

Definition at line 145 of file partitioner.C.

References libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::MeshBase::nodes_begin(), and libMesh::MeshBase::nodes_end().

Referenced by libMesh::SFCPartitioner::_do_partition(), libMesh::MetisPartitioner::_do_partition(), libMesh::LinearPartitioner::_do_partition(), _do_partition(), libMesh::ParmetisPartitioner::_do_repartition(), libMesh::Partitioner::partition(), and libMesh::Partitioner::repartition().

00146 {
00147   START_LOG("single_partition()","Partitioner");
00148 
00149   // Loop over all the elements and assign them to processor 0.
00150   MeshBase::element_iterator       elem_it  = mesh.elements_begin();
00151   const MeshBase::element_iterator elem_end = mesh.elements_end();
00152 
00153   for ( ; elem_it != elem_end; ++elem_it)
00154     (*elem_it)->processor_id() = 0;
00155 
00156   // For a single partition, all the nodes are on processor 0
00157   MeshBase::node_iterator       node_it  = mesh.nodes_begin();
00158   const MeshBase::node_iterator node_end = mesh.nodes_end();
00159 
00160   for ( ; node_it != node_end; ++node_it)
00161     (*node_it)->processor_id() = 0;
00162 
00163   STOP_LOG("single_partition()","Partitioner");
00164 }

CentroidSortMethod libMesh::CentroidPartitioner::sort_method (  )  const [inline]

Specifies how the elements will be sorted.

Definition at line 88 of file centroid_partitioner.h.

References _sort_method.

Referenced by _do_partition(), and clone().

00088 { return _sort_method; }

bool libMesh::CentroidPartitioner::sort_radial ( const std::pair< Point, Elem * > &  lhs,
const std::pair< Point, Elem * > &  rhs 
) [static, private]

Partition the list of centroids based on the radial position of the centroid. This provides a function which may be passed to the std::sort routine for sorting the elements by centroid.

Definition at line 174 of file centroid_partitioner.C.

Referenced by _do_partition().

00176 {
00177   return (lhs.first.size() < rhs.first.size());
00178 }

bool libMesh::CentroidPartitioner::sort_x ( const std::pair< Point, Elem * > &  lhs,
const std::pair< Point, Elem * > &  rhs 
) [static, private]

Partition the list of centroids based on the x-coordinate of the centroid. This provides a function which may be passed to the std::sort routine for sorting the elements by centroid.

Definition at line 147 of file centroid_partitioner.C.

Referenced by _do_partition().

00149 {
00150   return (lhs.first(0) < rhs.first(0));
00151 }

bool libMesh::CentroidPartitioner::sort_y ( const std::pair< Point, Elem * > &  lhs,
const std::pair< Point, Elem * > &  rhs 
) [static, private]

Partition the list of centroids based on the y-coordinate of the centroid. This provides a function which may be passed to the std::sort routine for sorting the elements by centroid.

Definition at line 156 of file centroid_partitioner.C.

Referenced by _do_partition().

00158 {
00159   return (lhs.first(1) < rhs.first(1));
00160 }

bool libMesh::CentroidPartitioner::sort_z ( const std::pair< Point, Elem * > &  lhs,
const std::pair< Point, Elem * > &  rhs 
) [static, private]

Partition the list of centroids based on the z-coordinate of the centroid. This provides a function which may be passed to the std::sort routine for sorting the elements by centroid.

Definition at line 166 of file centroid_partitioner.C.

Referenced by _do_partition().

00168 {
00169   return (lhs.first(2) < rhs.first(2));
00170 }


Member Data Documentation

std::vector<std::pair<Point, Elem*> > libMesh::CentroidPartitioner::_elem_centroids [private]

Vector which holds pairs of centroids and their respective element pointers.

Definition at line 160 of file centroid_partitioner.h.

Referenced by _do_partition(), and compute_centroids().

Store a flag which tells which type of sort method we are using.

Definition at line 154 of file centroid_partitioner.h.

Referenced by set_sort_method(), and sort_method().

The weights that might be used for partitioning.

Definition at line 155 of file partitioner.h.

Referenced by libMesh::MetisPartitioner::_do_partition(), and libMesh::MetisPartitioner::attach_weights().

const dof_id_type libMesh::Partitioner::communication_blocksize = 1000000 [static, protected, inherited]

The blocksize to use when doing blocked parallel communication. This limits the maximum vector size which can be used in a single communication step.

Definition at line 150 of file partitioner.h.


The documentation for this class was generated from the following files:

Site Created By: libMesh Developers
Last modified: February 05 2013 19:55:12 UTC

Hosted By:
SourceForge.net Logo