Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_Grid_Partitioner.hpp
Go to the documentation of this file.
1/****************************************************************************
2 * Copyright (c) 2018-2023 by the Cabana authors *
3 * All rights reserved. *
4 * *
5 * This file is part of the Cabana library. Cabana is distributed under a *
6 * BSD 3-clause license. For the licensing terms see the LICENSE file in *
7 * the top-level directory. *
8 * *
9 * SPDX-License-Identifier: BSD-3-Clause *
10 ****************************************************************************/
11
16#ifndef CABANA_GRID_PARTITIONER_HPP
17#define CABANA_GRID_PARTITIONER_HPP
18
19#include <array>
20#include <stdexcept>
21
22#include <mpi.h>
23
24namespace Cabana
25{
26namespace Grid
27{
28//---------------------------------------------------------------------------//
35template <std::size_t NumSpaceDim>
37{
38 public:
40 static constexpr std::size_t num_space_dim = NumSpaceDim;
41
42 ~BlockPartitioner() = default;
43
50 virtual std::array<int, num_space_dim> ranksPerDimension(
51 MPI_Comm comm,
52 const std::array<int, num_space_dim>& global_cells_per_dim ) const = 0;
53
64 virtual void ownedCellInfo(
65 MPI_Comm cart_comm,
66 const std::array<int, num_space_dim>& global_cells_per_dim,
67 std::array<int, num_space_dim>& owned_num_cell,
68 std::array<int, num_space_dim>& global_cell_offset ) const = 0;
69};
70
71//---------------------------------------------------------------------------//
77template <std::size_t NumSpaceDim>
78class ManualBlockPartitioner : public BlockPartitioner<NumSpaceDim>
79{
80 public:
82 static constexpr std::size_t num_space_dim = NumSpaceDim;
83
88 ManualBlockPartitioner( const std::array<int, NumSpaceDim>& ranks_per_dim )
89 : _ranks_per_dim( ranks_per_dim )
90 {
91 }
92
97 std::array<int, NumSpaceDim>
98 ranksPerDimension( MPI_Comm comm,
99 const std::array<int, NumSpaceDim>& ) const override
100 {
101 int comm_size;
102 MPI_Comm_size( comm, &comm_size );
103 int nrank = 1;
104 for ( std::size_t d = 0; d < num_space_dim; ++d )
105 nrank *= _ranks_per_dim[d];
106 if ( comm_size != nrank )
107 throw std::runtime_error(
108 "ManualPartitioner ranks do not match comm size" );
109 return _ranks_per_dim;
110 }
111
123 MPI_Comm cart_comm,
124 const std::array<int, num_space_dim>& global_cells_per_dim,
125 std::array<int, num_space_dim>& owned_num_cell,
126 std::array<int, num_space_dim>& global_cell_offset ) const override
127 {
128 // Get the cells per dimension and the remainder.
129 std::array<int, num_space_dim> cells_per_dim;
130 std::array<int, num_space_dim> dim_remainder;
131 std::array<int, num_space_dim> cart_rank;
132 averageCellInfo( cart_comm, global_cells_per_dim, cart_rank,
133 cells_per_dim, dim_remainder );
134
135 // Compute the global cell offset and the local low corner on this rank
136 // by computing the starting global cell index via exclusive scan.
137 global_cell_offset =
138 globalCellOffsetHelper( cart_rank, cells_per_dim, dim_remainder );
139
140 // Compute the number of local cells in this rank in each dimension.
141 owned_num_cell =
142 ownedCellsHelper( cart_rank, cells_per_dim, dim_remainder );
143 }
144
152 std::array<int, num_space_dim> ownedCellsPerDimension(
153 MPI_Comm cart_comm,
154 const std::array<int, num_space_dim>& global_cells_per_dim ) const
155 {
156 // Get the cells per dimension and the remainder.
157 std::array<int, num_space_dim> cells_per_dim;
158 std::array<int, num_space_dim> dim_remainder;
159 std::array<int, num_space_dim> cart_rank;
160 averageCellInfo( cart_comm, global_cells_per_dim, cart_rank,
161 cells_per_dim, dim_remainder );
162
163 // Compute the number of local cells in this rank in each dimension.
164 return ownedCellsHelper( cart_rank, cells_per_dim, dim_remainder );
165 }
166
167 private:
178 inline void
179 averageCellInfo( MPI_Comm cart_comm,
180 const std::array<int, num_space_dim>& global_cells_per_dim,
181 std::array<int, num_space_dim>& cart_rank,
182 std::array<int, num_space_dim>& cells_per_dim,
183 std::array<int, num_space_dim>& dim_remainder ) const
184 {
185 // Get the Cartesian size and topology index of this rank.
186 int linear_rank;
187 MPI_Comm_rank( cart_comm, &linear_rank );
188 MPI_Cart_coords( cart_comm, linear_rank, num_space_dim,
189 cart_rank.data() );
190 // Get the cells per dimension and the remainder.
191 for ( std::size_t d = 0; d < num_space_dim; ++d )
192 {
193 cells_per_dim[d] = global_cells_per_dim[d] / _ranks_per_dim[d];
194 dim_remainder[d] = global_cells_per_dim[d] % _ranks_per_dim[d];
195 }
196 }
197
207 inline std::array<int, num_space_dim> ownedCellsHelper(
208 const std::array<int, num_space_dim>& cart_rank,
209 const std::array<int, num_space_dim>& cells_per_dim,
210 const std::array<int, num_space_dim>& dim_remainder ) const
211 {
212 std::array<int, num_space_dim> owned_num_cell;
213 // Compute the number of local cells in this rank in each dimension.
214 for ( std::size_t d = 0; d < num_space_dim; ++d )
215 {
216 owned_num_cell[d] = cells_per_dim[d];
217 if ( dim_remainder[d] > cart_rank[d] )
218 ++owned_num_cell[d];
219 }
220 return owned_num_cell;
221 }
222
232 inline std::array<int, num_space_dim> globalCellOffsetHelper(
233 const std::array<int, num_space_dim>& cart_rank,
234 const std::array<int, num_space_dim>& cells_per_dim,
235 const std::array<int, num_space_dim>& dim_remainder ) const
236 {
237 std::array<int, num_space_dim> global_cell_offset;
238 // Compute the global cell offset and the local low corner on this rank
239 // by computing the starting global cell index via exclusive scan.
240 for ( std::size_t d = 0; d < num_space_dim; ++d )
241 {
242 global_cell_offset[d] = 0;
243 for ( int r = 0; r < cart_rank[d]; ++r )
244 {
245 global_cell_offset[d] += cells_per_dim[d];
246 if ( dim_remainder[d] > r )
247 ++global_cell_offset[d];
248 }
249 }
250 return global_cell_offset;
251 }
252
253 private:
254 std::array<int, NumSpaceDim> _ranks_per_dim;
255};
256
257//---------------------------------------------------------------------------//
269template <std::size_t NumSpaceDim>
270class DimBlockPartitioner : public BlockPartitioner<NumSpaceDim>
271{
272 public:
274 static constexpr std::size_t num_space_dim = NumSpaceDim;
275
278 {
279 // Initialize so that all ranks will be modified when requested.
280 initUnpartitionedDims();
281 };
282
287 DimBlockPartitioner( const int dim )
288 {
289 initUnpartitionedDims();
290
291 // Only partition in the other dimensions.
292 _unpartitioned_dim[dim] = 1;
293 };
294
300 DimBlockPartitioner( const int dim_1, const int dim_2 )
301 {
302 static_assert(
303 NumSpaceDim > 2,
304 "Cannot partition 2d system with 2 unpartitioned dimensions." );
305
306 initUnpartitionedDims();
307
308 // Only partition in the third dimension.
309 _unpartitioned_dim[dim_1] = 1;
310 _unpartitioned_dim[dim_2] = 1;
311 };
312
317 std::array<int, NumSpaceDim>
318 ranksPerDimension( MPI_Comm comm,
319 const std::array<int, NumSpaceDim>& ) const override
320 {
321 int comm_size;
322 MPI_Comm_size( comm, &comm_size );
323 auto ranks_per_dim = _unpartitioned_dim;
324 MPI_Dims_create( comm_size, NumSpaceDim, ranks_per_dim.data() );
325
326 return ranks_per_dim;
327 }
328
340 MPI_Comm cart_comm,
341 const std::array<int, num_space_dim>& global_cells_per_dim,
342 std::array<int, num_space_dim>& owned_num_cell,
343 std::array<int, num_space_dim>& global_cell_offset ) const override
344 {
345 // Get the cells per dimension and the remainder.
346 std::array<int, num_space_dim> cells_per_dim;
347 std::array<int, num_space_dim> dim_remainder;
348 std::array<int, num_space_dim> cart_rank;
349 averageCellInfo( cart_comm, global_cells_per_dim, cart_rank,
350 cells_per_dim, dim_remainder );
351
352 // Compute the global cell offset and the local low corner on this rank
353 // by computing the starting global cell index via exclusive scan.
354 global_cell_offset =
355 globalCellOffsetHelper( cart_rank, cells_per_dim, dim_remainder );
356
357 // Compute the number of local cells in this rank in each dimension.
358 owned_num_cell =
359 ownedCellsHelper( cart_rank, cells_per_dim, dim_remainder );
360 }
361
370 std::array<int, num_space_dim> ownedCellsPerDimension(
371 MPI_Comm cart_comm,
372 const std::array<int, num_space_dim>& global_cells_per_dim ) const
373 {
374 // Get the cells per dimension and the remainder.
375 std::array<int, num_space_dim> cells_per_dim;
376 std::array<int, num_space_dim> dim_remainder;
377 std::array<int, num_space_dim> cart_rank;
378 averageCellInfo( cart_comm, global_cells_per_dim, cart_rank,
379 cells_per_dim, dim_remainder );
380
381 // Compute the number of local cells in this rank in each dimension.
382 return ownedCellsHelper( cart_rank, cells_per_dim, dim_remainder );
383 }
384
385 private:
386 std::array<int, NumSpaceDim> _unpartitioned_dim;
387
389 void initUnpartitionedDims()
390 {
391 for ( std::size_t d = 0; d < NumSpaceDim; ++d )
392 _unpartitioned_dim[d] = 0;
393 }
394
405 inline void
406 averageCellInfo( MPI_Comm cart_comm,
407 const std::array<int, num_space_dim>& global_cells_per_dim,
408 std::array<int, num_space_dim>& cart_rank,
409 std::array<int, num_space_dim>& cells_per_dim,
410 std::array<int, num_space_dim>& dim_remainder ) const
411 {
412 // Get the Cartesian size and topology index of this rank.
413 std::array<int, num_space_dim> ranks_per_dim;
414 std::array<int, num_space_dim> cart_period;
415 MPI_Cart_get( cart_comm, num_space_dim, ranks_per_dim.data(),
416 cart_period.data(), cart_rank.data() );
417
418 // Get the cells per dimension and the remainder.
419 for ( std::size_t d = 0; d < num_space_dim; ++d )
420 {
421 cells_per_dim[d] = global_cells_per_dim[d] / ranks_per_dim[d];
422 dim_remainder[d] = global_cells_per_dim[d] % ranks_per_dim[d];
423 }
424 }
425
435 inline std::array<int, num_space_dim> ownedCellsHelper(
436 const std::array<int, num_space_dim>& cart_rank,
437 const std::array<int, num_space_dim>& cells_per_dim,
438 const std::array<int, num_space_dim>& dim_remainder ) const
439 {
440 std::array<int, num_space_dim> owned_num_cell;
441 // Compute the number of local cells in this rank in each dimension.
442 for ( std::size_t d = 0; d < num_space_dim; ++d )
443 {
444 owned_num_cell[d] = cells_per_dim[d];
445 if ( dim_remainder[d] > cart_rank[d] )
446 ++owned_num_cell[d];
447 }
448 return owned_num_cell;
449 }
450
460 inline std::array<int, num_space_dim> globalCellOffsetHelper(
461 const std::array<int, num_space_dim>& cart_rank,
462 const std::array<int, num_space_dim>& cells_per_dim,
463 const std::array<int, num_space_dim>& dim_remainder ) const
464 {
465 std::array<int, num_space_dim> global_cell_offset;
466 // Compute the global cell offset and the local low corner on this rank
467 // by computing the starting global cell index via exclusive scan.
468 for ( std::size_t d = 0; d < num_space_dim; ++d )
469 {
470 global_cell_offset[d] = 0;
471 for ( int r = 0; r < cart_rank[d]; ++r )
472 {
473 global_cell_offset[d] += cells_per_dim[d];
474 if ( dim_remainder[d] > r )
475 ++global_cell_offset[d];
476 }
477 }
478 return global_cell_offset;
479 }
480};
481
482//---------------------------------------------------------------------------//
483
484} // namespace Grid
485} // namespace Cabana
486
487#endif // end CABANA_GRID_PARTITIONER_HPP
Block partitioner base class.
Definition Cabana_Grid_Partitioner.hpp:37
virtual void ownedCellInfo(MPI_Comm cart_comm, const std::array< int, num_space_dim > &global_cells_per_dim, std::array< int, num_space_dim > &owned_num_cell, std::array< int, num_space_dim > &global_cell_offset) const =0
Get the owned number of cells and global cell offset of the current MPI rank.
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Partitioner.hpp:40
virtual std::array< int, num_space_dim > ranksPerDimension(MPI_Comm comm, const std::array< int, num_space_dim > &global_cells_per_dim) const =0
Get the number of MPI ranks in each dimension of the grid.
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Partitioner.hpp:274
void ownedCellInfo(MPI_Comm cart_comm, const std::array< int, num_space_dim > &global_cells_per_dim, std::array< int, num_space_dim > &owned_num_cell, std::array< int, num_space_dim > &global_cell_offset) const override
Get the owned number of cells and the global cell offset of the current MPI rank.
Definition Cabana_Grid_Partitioner.hpp:339
DimBlockPartitioner(const int dim)
Constructor for NumSpaceDim-1 (1d for 2d system).
Definition Cabana_Grid_Partitioner.hpp:287
DimBlockPartitioner()
Default constructor (automatically partitioned in all dimensions).
Definition Cabana_Grid_Partitioner.hpp:277
DimBlockPartitioner(const int dim_1, const int dim_2)
Constructor for 1d decomposition (3d systems only).
Definition Cabana_Grid_Partitioner.hpp:300
std::array< int, num_space_dim > ownedCellsPerDimension(MPI_Comm cart_comm, const std::array< int, num_space_dim > &global_cells_per_dim) const
Get the owned number of cells of the current MPI rank.
Definition Cabana_Grid_Partitioner.hpp:370
std::array< int, NumSpaceDim > ranksPerDimension(MPI_Comm comm, const std::array< int, NumSpaceDim > &) const override
Get the MPI ranks per dimension.
Definition Cabana_Grid_Partitioner.hpp:318
ManualBlockPartitioner(const std::array< int, NumSpaceDim > &ranks_per_dim)
Constructor.
Definition Cabana_Grid_Partitioner.hpp:88
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_Partitioner.hpp:82
std::array< int, num_space_dim > ownedCellsPerDimension(MPI_Comm cart_comm, const std::array< int, num_space_dim > &global_cells_per_dim) const
Get the owned number of cells of the current MPI rank.
Definition Cabana_Grid_Partitioner.hpp:152
void ownedCellInfo(MPI_Comm cart_comm, const std::array< int, num_space_dim > &global_cells_per_dim, std::array< int, num_space_dim > &owned_num_cell, std::array< int, num_space_dim > &global_cell_offset) const override
Get the owned number of cells of the current MPI rank.
Definition Cabana_Grid_Partitioner.hpp:122
std::array< int, NumSpaceDim > ranksPerDimension(MPI_Comm comm, const std::array< int, NumSpaceDim > &) const override
Get the MPI ranks per dimension.
Definition Cabana_Grid_Partitioner.hpp:98
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36