LCOV - code coverage report
Current view: top level - src/partitioner - LibmeshPartitioner.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 47 104 45.2 %
Date: 2025-07-17 01:28:37 Functions: 7 9 77.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "LibmeshPartitioner.h"
      11             : 
      12             : #include "MooseApp.h"
      13             : #include "MooseMeshUtils.h"
      14             : 
      15             : #include "libmesh/linear_partitioner.h"
      16             : #include "libmesh/centroid_partitioner.h"
      17             : #include "libmesh/parmetis_partitioner.h"
      18             : #include "libmesh/metis_partitioner.h"
      19             : #include "libmesh/hilbert_sfc_partitioner.h"
      20             : #include "libmesh/morton_sfc_partitioner.h"
      21             : #include "libmesh/subdomain_partitioner.h"
      22             : 
      23             : registerMooseObject("MooseApp", LibmeshPartitioner);
      24             : 
      25             : InputParameters
      26       14569 : LibmeshPartitioner::validParams()
      27             : {
      28       14569 :   InputParameters params = MoosePartitioner::validParams();
      29       14569 :   params.addClassDescription("Mesh partitioning using capabilities defined in libMesh.");
      30             :   MooseEnum partitioning(
      31       14569 :       "metis=-2 parmetis=-1 linear=0 centroid hilbert_sfc morton_sfc subdomain_partitioner");
      32       14569 :   params.addRequiredParam<MooseEnum>(
      33             :       "partitioner",
      34             :       partitioning,
      35             :       "Specifies a mesh partitioner to use when splitting the mesh for a parallel computation.");
      36       14569 :   MooseEnum direction("x y z radial");
      37       14569 :   params.addParam<MooseEnum>("centroid_partitioner_direction",
      38             :                              direction,
      39             :                              "Specifies the sort direction if using the centroid partitioner. "
      40             :                              "Available options: x, y, z, radial");
      41       14569 :   params.addParam<std::vector<std::vector<SubdomainName>>>(
      42             :       "blocks", {}, "Block is seperated by ;, and partition mesh block by block. ");
      43       29138 :   return params;
      44       14569 : }
      45             : 
      46         192 : LibmeshPartitioner::LibmeshPartitioner(const InputParameters & params)
      47             :   : MoosePartitioner(params),
      48         192 :     _partitioner_name(getParam<MooseEnum>("partitioner")),
      49         384 :     _subdomain_blocks(getParam<std::vector<std::vector<SubdomainName>>>("blocks"))
      50             : {
      51         192 :   switch (_partitioner_name)
      52             :   {
      53           0 :     case -2: // metis
      54           0 :       _partitioner = std::make_unique<libMesh::MetisPartitioner>();
      55           0 :       break;
      56           0 :     case -1: // parmetis
      57           0 :       _partitioner = std::make_unique<libMesh::ParmetisPartitioner>();
      58           0 :       break;
      59             : 
      60          72 :     case 0: // linear
      61          72 :       _partitioner = std::make_unique<libMesh::LinearPartitioner>();
      62          72 :       break;
      63           0 :     case 1: // centroid
      64             :     {
      65           0 :       if (!isParamValid("centroid_partitioner_direction"))
      66           0 :         mooseError(
      67             :             "If using the centroid partitioner you _must_ specify centroid_partitioner_direction!");
      68             : 
      69           0 :       MooseEnum direction = getParam<MooseEnum>("centroid_partitioner_direction");
      70             : 
      71           0 :       if (direction == "x")
      72             :         _partitioner =
      73           0 :             std::make_unique<libMesh::CentroidPartitioner>(libMesh::CentroidPartitioner::X);
      74           0 :       else if (direction == "y")
      75             :         _partitioner =
      76           0 :             std::make_unique<libMesh::CentroidPartitioner>(libMesh::CentroidPartitioner::Y);
      77           0 :       else if (direction == "z")
      78             :         _partitioner =
      79           0 :             std::make_unique<libMesh::CentroidPartitioner>(libMesh::CentroidPartitioner::Z);
      80           0 :       else if (direction == "radial")
      81             :         _partitioner =
      82           0 :             std::make_unique<libMesh::CentroidPartitioner>(libMesh::CentroidPartitioner::RADIAL);
      83           0 :       break;
      84           0 :     }
      85           0 :     case 2: // hilbert_sfc
      86           0 :       _partitioner = std::make_unique<libMesh::HilbertSFCPartitioner>();
      87           0 :       break;
      88           0 :     case 3: // morton_sfc
      89           0 :       _partitioner = std::make_unique<libMesh::MortonSFCPartitioner>();
      90           0 :       break;
      91         120 :     case 4: // subdomain_partitioner
      92         120 :       _partitioner = std::make_unique<libMesh::SubdomainPartitioner>();
      93         120 :       break;
      94             :   }
      95         192 : }
      96             : 
      97         368 : LibmeshPartitioner::~LibmeshPartitioner() {}
      98             : 
      99             : std::unique_ptr<Partitioner>
     100         152 : LibmeshPartitioner::clone() const
     101             : {
     102         152 :   switch (_partitioner_name)
     103             :   {
     104           0 :     case -2: // metis
     105           0 :       return std::make_unique<libMesh::MetisPartitioner>();
     106             : 
     107           0 :     case -1: // parmetis
     108           0 :       return std::make_unique<libMesh::ParmetisPartitioner>();
     109             : 
     110          72 :     case 0: // linear
     111          72 :       return std::make_unique<libMesh::LinearPartitioner>();
     112             : 
     113           0 :     case 1: // centroid
     114             :     {
     115           0 :       if (!isParamValid("centroid_partitioner_direction"))
     116           0 :         mooseError(
     117             :             "If using the centroid partitioner you _must_ specify centroid_partitioner_direction!");
     118             : 
     119           0 :       MooseEnum direction = getParam<MooseEnum>("centroid_partitioner_direction");
     120             : 
     121           0 :       if (direction == "x")
     122           0 :         return std::make_unique<libMesh::CentroidPartitioner>(libMesh::CentroidPartitioner::X);
     123           0 :       else if (direction == "y")
     124           0 :         return std::make_unique<libMesh::CentroidPartitioner>(libMesh::CentroidPartitioner::Y);
     125           0 :       else if (direction == "z")
     126           0 :         return std::make_unique<libMesh::CentroidPartitioner>(libMesh::CentroidPartitioner::Z);
     127           0 :       else if (direction == "radial")
     128           0 :         return std::make_unique<libMesh::CentroidPartitioner>(libMesh::CentroidPartitioner::RADIAL);
     129           0 :       break;
     130           0 :     }
     131           0 :     case 2: // hilbert_sfc
     132           0 :       return std::make_unique<libMesh::HilbertSFCPartitioner>();
     133             : 
     134           0 :     case 3: // morton_sfc
     135           0 :       return std::make_unique<libMesh::MortonSFCPartitioner>();
     136             : 
     137          80 :     case 4: // subdomain_partitioner
     138          80 :       return _app.getFactory().clone(*this);
     139             :   }
     140             :   // this cannot happen but I need to trick the compiler into
     141             :   // believing me
     142           0 :   mooseError("Error in LibmeshPartitioner: Supplied partitioner option causes error in clone()");
     143             :   return std::make_unique<libMesh::MetisPartitioner>();
     144             : }
     145             : 
     146             : void
     147          36 : LibmeshPartitioner::prepareBlocksForSubdomainPartitioner(
     148             :     const MeshBase & mesh, libMesh::SubdomainPartitioner & subdomain_partitioner)
     149             : {
     150             :   // For making sure all of the blocks exist
     151          36 :   std::set<subdomain_id_type> mesh_subdomain_ids;
     152          36 :   mesh.subdomain_ids(mesh_subdomain_ids);
     153             : 
     154             :   // Clear chunks before filling
     155          36 :   subdomain_partitioner.chunks.clear();
     156             : 
     157             :   // Insert each chunk
     158         100 :   for (const auto & group : _subdomain_blocks)
     159             :   {
     160          68 :     const auto subdomain_ids = MooseMeshUtils::getSubdomainIDs(mesh, group);
     161         324 :     for (const auto id : subdomain_ids)
     162         260 :       if (!mesh_subdomain_ids.count(id))
     163           4 :         paramError("blocks", "The block ", id, " was not found on the mesh");
     164             : 
     165          64 :     std::set<subdomain_id_type> subdomain_ids_set(subdomain_ids.begin(), subdomain_ids.end());
     166             : 
     167          64 :     subdomain_partitioner.chunks.push_back(subdomain_ids_set);
     168          64 :   }
     169          32 : }
     170             : 
     171             : void
     172          36 : LibmeshPartitioner::partition(MeshBase & mesh, const unsigned int n)
     173             : {
     174          36 :   if (_partitioner_name == "subdomain_partitioner")
     175             :   {
     176             :     mooseAssert(_partitioner.get(), "Partitioner is a NULL object");
     177          36 :     prepareBlocksForSubdomainPartitioner(
     178          36 :         mesh, static_cast<libMesh::SubdomainPartitioner &>(*_partitioner.get()));
     179             :   }
     180             : 
     181          32 :   _partitioner->partition(mesh, n);
     182          32 : }
     183             : 
     184             : void
     185           0 : LibmeshPartitioner::partition(MeshBase & mesh)
     186             : {
     187           0 :   if (_partitioner_name == "subdomain_partitioner")
     188             :   {
     189             :     mooseAssert(_partitioner.get(), "Partitioner is a NULL object");
     190           0 :     prepareBlocksForSubdomainPartitioner(
     191           0 :         mesh, static_cast<libMesh::SubdomainPartitioner &>(*_partitioner.get()));
     192             :   }
     193             : 
     194           0 :   _partitioner->partition(mesh);
     195           0 : }
     196             : 
     197             : void
     198           0 : LibmeshPartitioner::_do_partition(MeshBase & /*mesh*/, const unsigned int /*n*/)
     199             : {
     200           0 : }

Generated by: LCOV version 1.14