$extrastylesheet
centroid_partitioner.C
Go to the documentation of this file.
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 // C++ includes
00019 #include <algorithm> // for std::sort
00020 
00021 // Local includes
00022 #include "libmesh/centroid_partitioner.h"
00023 #include "libmesh/mesh_base.h"
00024 #include "libmesh/elem.h"
00025 
00026 namespace libMesh
00027 {
00028 
00029 
00030 //---------------------------------------------------------
00031 // CentroidPartitioner methods
00032 void CentroidPartitioner::_do_partition (MeshBase& mesh,
00033                                          const unsigned int n)
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_msg("Unknown sort method: " << this->sort_method());
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 (cast_int<processor_id_type>(i / target_size),
00114                   cast_int<processor_id_type>(n-1));
00115     }
00116 }
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 void CentroidPartitioner::compute_centroids (MeshBase& mesh)
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 }
00143 
00144 
00145 
00146 
00147 bool CentroidPartitioner::sort_x (const std::pair<Point, Elem*>& lhs,
00148                                   const std::pair<Point, Elem*>& rhs)
00149 {
00150   return (lhs.first(0) < rhs.first(0));
00151 }
00152 
00153 
00154 
00155 
00156 bool CentroidPartitioner::sort_y (const std::pair<Point, Elem*>& lhs,
00157                                   const std::pair<Point, Elem*>& rhs)
00158 {
00159   return (lhs.first(1) < rhs.first(1));
00160 }
00161 
00162 
00163 
00164 
00165 
00166 bool CentroidPartitioner::sort_z (const std::pair<Point, Elem*>& lhs,
00167                                   const std::pair<Point, Elem*>& rhs)
00168 {
00169   return (lhs.first(2) < rhs.first(2));
00170 }
00171 
00172 
00173 
00174 bool CentroidPartitioner::sort_radial (const std::pair<Point, Elem*>& lhs,
00175                                        const std::pair<Point, Elem*>& rhs)
00176 {
00177   return (lhs.first.size() < rhs.first.size());
00178 }
00179 
00180 } // namespace libMesh