LCOV - code coverage report
Current view: top level - src/partitioning - centroid_partitioner.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 32 52 61.5 %
Date: 2025-08-19 19:27:09 Functions: 5 8 62.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : // C++ includes
      19             : #include <algorithm> // for std::stable_sort
      20             : 
      21             : // Local includes
      22             : #include "libmesh/centroid_partitioner.h"
      23             : #include "libmesh/elem.h"
      24             : #include "libmesh/enum_partitioner_type.h"
      25             : #include "libmesh/int_range.h"
      26             : 
      27             : namespace libMesh
      28             : {
      29             : 
      30             : 
      31         142 : PartitionerType CentroidPartitioner::type() const
      32             : {
      33         142 :   return CENTROID_PARTITIONER;
      34             : }
      35             : 
      36             : 
      37         301 : void CentroidPartitioner::partition_range(MeshBase & mesh,
      38             :                                           MeshBase::element_iterator it,
      39             :                                           MeshBase::element_iterator end,
      40             :                                           unsigned int n)
      41             : {
      42             :   // Check for easy returns
      43         301 :   if (it == end)
      44           2 :     return;
      45             : 
      46         230 :   if (n == 1)
      47             :     {
      48           0 :       this->single_partition_range (it, end);
      49           0 :       return;
      50             :     }
      51             : 
      52             :   // Make sure the user has not handed us an
      53             :   // invalid number of partitions.
      54          34 :   libmesh_assert_greater (n, 0);
      55             : 
      56             :   // We don't yet support distributed meshes with this Partitioner
      57         230 :   if (!mesh.is_serial())
      58           0 :     libmesh_not_implemented();
      59             : 
      60             :   // Compute the element vertex averages.  Note: we used to skip this step
      61             :   // if the number of elements was unchanged from the last call, but
      62             :   // that doesn't account for elements that have moved a lot since the
      63             :   // last time the Partitioner was called...
      64         426 :   this->compute_vertex_avgs (it, end);
      65             : 
      66         230 :   switch (this->sort_method())
      67             :     {
      68         230 :     case X:
      69             :       {
      70         230 :         std::stable_sort(_elem_vertex_avgs.begin(),
      71             :                          _elem_vertex_avgs.end(),
      72             :                          CentroidPartitioner::sort_x);
      73             : 
      74         230 :         break;
      75             :       }
      76             : 
      77             : 
      78           0 :     case Y:
      79             :       {
      80           0 :         std::stable_sort(_elem_vertex_avgs.begin(),
      81             :                          _elem_vertex_avgs.end(),
      82             :                          CentroidPartitioner::sort_y);
      83             : 
      84           0 :         break;
      85             : 
      86             :       }
      87             : 
      88             : 
      89           0 :     case Z:
      90             :       {
      91           0 :         std::stable_sort(_elem_vertex_avgs.begin(),
      92             :                          _elem_vertex_avgs.end(),
      93             :                          CentroidPartitioner::sort_z);
      94             : 
      95           0 :         break;
      96             :       }
      97             : 
      98             : 
      99           0 :     case RADIAL:
     100             :       {
     101           0 :         std::stable_sort(_elem_vertex_avgs.begin(),
     102             :                          _elem_vertex_avgs.end(),
     103             :                          CentroidPartitioner::sort_radial);
     104             : 
     105           0 :         break;
     106             :       }
     107           0 :     default:
     108           0 :       libmesh_error_msg("Unknown sort method: " << this->sort_method());
     109             :     }
     110             : 
     111             :   // Compute target_size, the approximate number of elements on each processor.
     112             :   const dof_id_type target_size = cast_int<dof_id_type>
     113         264 :     (_elem_vertex_avgs.size() / n);
     114             : 
     115       10856 :   for (auto i : index_range(_elem_vertex_avgs))
     116             :     {
     117       10626 :       Elem * elem = _elem_vertex_avgs[i].second;
     118             : 
     119             :       // FIXME: All "extra" elements go on the last processor... this
     120             :       // could probably be improved.
     121       13016 :       elem->processor_id() =
     122       16472 :         std::min (cast_int<processor_id_type>(i / target_size),
     123       13449 :                   cast_int<processor_id_type>(n-1));
     124             :     }
     125             : }
     126             : 
     127             : 
     128             : 
     129         301 : void CentroidPartitioner::_do_partition (MeshBase & mesh,
     130             :                                          const unsigned int n)
     131             : {
     132         301 :   this->partition_range(mesh,
     133         602 :                         mesh.elements_begin(),
     134         337 :                         mesh.elements_end(),
     135          72 :                         n);
     136         301 : }
     137             : 
     138             : 
     139             : 
     140         230 : void CentroidPartitioner::compute_vertex_avgs (MeshBase::element_iterator it,
     141             :                                                MeshBase::element_iterator end)
     142             : {
     143         230 :   _elem_vertex_avgs.clear();
     144             : 
     145       11052 :   for (auto & elem : as_range(it, end))
     146       10788 :     _elem_vertex_avgs.emplace_back(elem->vertex_average(), elem);
     147         230 : }
     148             : 
     149             : 
     150             : 
     151             : 
     152       55508 : bool CentroidPartitioner::sort_x (const std::pair<Point, Elem *> & lhs,
     153             :                                   const std::pair<Point, Elem *> & rhs)
     154             : {
     155       55508 :   return (lhs.first(0) < rhs.first(0));
     156             : }
     157             : 
     158             : 
     159             : 
     160             : 
     161           0 : bool CentroidPartitioner::sort_y (const std::pair<Point, Elem *> & lhs,
     162             :                                   const std::pair<Point, Elem *> & rhs)
     163             : {
     164           0 :   return (lhs.first(1) < rhs.first(1));
     165             : }
     166             : 
     167             : 
     168             : 
     169             : 
     170             : 
     171           0 : bool CentroidPartitioner::sort_z (const std::pair<Point, Elem *> & lhs,
     172             :                                   const std::pair<Point, Elem *> & rhs)
     173             : {
     174           0 :   return (lhs.first(2) < rhs.first(2));
     175             : }
     176             : 
     177             : 
     178             : 
     179           0 : bool CentroidPartitioner::sort_radial (const std::pair<Point, Elem *> & lhs,
     180             :                                        const std::pair<Point, Elem *> & rhs)
     181             : {
     182           0 :   return (lhs.first.norm() < rhs.first.norm());
     183             : }
     184             : 
     185             : } // namespace libMesh

Generated by: LCOV version 1.14