Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_Grid_GlobalGrid_impl.hpp
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
12#ifndef CABANA_GRID_GLOBALGRID_IMPL_HPP
13#define CABANA_GRID_GLOBALGRID_IMPL_HPP
14
15#include <algorithm>
16#include <cmath>
17#include <limits>
18
19namespace Cabana
20{
21namespace Grid
22{
23//---------------------------------------------------------------------------//
24// Constructor.
25template <class MeshType>
27 MPI_Comm comm, const std::shared_ptr<GlobalMesh<MeshType>>& global_mesh,
28 const std::array<bool, num_space_dim>& periodic,
29 const BlockPartitioner<num_space_dim>& partitioner )
30 : _global_mesh( global_mesh )
31 , _periodic( periodic )
32{
33 // Partition the problem.
34 std::array<int, num_space_dim> global_num_cell;
35 for ( std::size_t d = 0; d < num_space_dim; ++d )
36 global_num_cell[d] = _global_mesh->globalNumCell( d );
37 _ranks_per_dim = partitioner.ranksPerDimension( comm, global_num_cell );
38
39 // Extract the periodicity of the boundary as integers.
40 std::array<int, num_space_dim> periodic_dims;
41 for ( std::size_t d = 0; d < num_space_dim; ++d )
42 periodic_dims[d] = _periodic[d];
43
44 // Generate a communicator with a Cartesian topology.
45 int reorder_cart_ranks = 1;
46
47 auto num_space_dim_copy = num_space_dim;
48 auto ranks_per_dim_copy = _ranks_per_dim.data();
49 auto periodic_dims_copy = periodic_dims.data();
50 _cart_comm_ptr.reset(
51 // Duplicate the communicator and store in a std::shared_ptr so that
52 // all copies point to the same object
53 [comm, num_space_dim_copy, ranks_per_dim_copy, periodic_dims_copy,
54 reorder_cart_ranks]()
55 {
56 auto p = std::make_unique<MPI_Comm>();
57 MPI_Cart_create( comm, num_space_dim_copy, ranks_per_dim_copy,
58 periodic_dims_copy, reorder_cart_ranks, p.get() );
59 return p.release();
60 }(),
61 // Custom deleter to mark the communicator for deallocation
62 []( MPI_Comm* p )
63 {
64 MPI_Comm_free( p );
65 delete p;
66 } );
68 // Get the Cartesian topology index of this rank.
69 int linear_rank;
70 MPI_Comm_rank( this->comm(), &linear_rank );
71 MPI_Cart_coords( this->comm(), linear_rank, num_space_dim,
72 _cart_rank.data() );
73
74 // Get the cells per dimension and the remainder.
75 partitioner.ownedCellInfo( this->comm(), global_num_cell, _owned_num_cell,
76 _global_cell_offset );
77
78 // Determine if a block is on the low or high boundaries.
79 for ( std::size_t d = 0; d < num_space_dim; ++d )
80 {
81 _boundary_lo[d] = ( 0 == _cart_rank[d] );
82 _boundary_hi[d] = ( _ranks_per_dim[d] - 1 == _cart_rank[d] );
83 }
84}
86//---------------------------------------------------------------------------//
87// Destructor.
88template <class MeshType>
89GlobalGrid<MeshType>::~GlobalGrid()
90{
91}
93//---------------------------------------------------------------------------//
94// Get the grid communicator.
95template <class MeshType>
97{
98 return *_cart_comm_ptr;
99}
100
101//---------------------------------------------------------------------------//
102// Get the global mesh data.
103template <class MeshType>
105{
106 return *_global_mesh;
107}
108
109//---------------------------------------------------------------------------//
110// Get whether a given dimension is periodic.
111template <class MeshType>
112bool GlobalGrid<MeshType>::isPeriodic( const int dim ) const
113{
114 return _periodic[dim];
115}
116
117//---------------------------------------------------------------------------//
118// Determine if this block is on a low boundary in the given dimension.
119template <class MeshType>
120bool GlobalGrid<MeshType>::onLowBoundary( const int dim ) const
121{
122 return _boundary_lo[dim];
123}
124
125//---------------------------------------------------------------------------//
126// Determine if this block is on a high boundary in the given dimension.
127template <class MeshType>
128bool GlobalGrid<MeshType>::onHighBoundary( const int dim ) const
130 return _boundary_hi[dim];
131}
133//---------------------------------------------------------------------------//
134// Get the number of blocks in each dimension in the global mesh.
135template <class MeshType>
136int GlobalGrid<MeshType>::dimNumBlock( const int dim ) const
137{
138 return _ranks_per_dim[dim];
139}
141//---------------------------------------------------------------------------//
142// Get the total number of blocks.
143template <class MeshType>
146 int comm_size;
147 MPI_Comm_size( this->comm(), &comm_size );
148 return comm_size;
149}
151//---------------------------------------------------------------------------//
152// Get the id of this block in a given dimension.
153template <class MeshType>
154int GlobalGrid<MeshType>::dimBlockId( const int dim ) const
156 return _cart_rank[dim];
157}
158
159//---------------------------------------------------------------------------//
160// Get the id of this block.
161template <class MeshType>
163{
164 int comm_rank;
165 MPI_Comm_rank( this->comm(), &comm_rank );
166 return comm_rank;
167}
168
169//---------------------------------------------------------------------------//
170// Get the MPI rank of a block with the given indices. If the rank is out
171// of bounds and the boundary is not periodic, return -1 to indicate an
172// invalid rank.
173template <class MeshType>
175 const std::array<int, num_space_dim>& ijk ) const
176{
177 // Check for invalid indices. An index is invalid if it is out of bounds
178 // and the dimension is not periodic. An out of bound index in a periodic
179 // dimension is valid because it will wrap around to a valid index.
180 for ( std::size_t d = 0; d < num_space_dim; ++d )
181 if ( !_periodic[d] && ( ijk[d] < 0 || _ranks_per_dim[d] <= ijk[d] ) )
182 return -1;
183
184 // If we have indices get their rank.
185 int lr;
186 MPI_Cart_rank( this->comm(), ijk.data(), &lr );
187 return lr;
188}
189
190//---------------------------------------------------------------------------//
191// Get the MPI rank of a block with the given indices. If the rank is out
192// of bounds and the boundary is not periodic, return -1 to indicate an
193// invalid rank.
194template <class MeshType>
195template <std::size_t NSD>
196std::enable_if_t<3 == NSD, int>
197GlobalGrid<MeshType>::blockRank( const int i, const int j, const int k ) const
198{
199 std::array<int, 3> cr = { i, j, k };
200 return blockRank( cr );
201}
202
203//---------------------------------------------------------------------------//
204// Get the MPI rank of a block with the given indices. If the rank is out
205// of bounds and the boundary is not periodic, return -1 to indicate an
206// invalid rank.
207template <class MeshType>
208template <std::size_t NSD>
209std::enable_if_t<2 == NSD, int>
210GlobalGrid<MeshType>::blockRank( const int i, const int j ) const
211{
212 std::array<int, 2> cr = { i, j };
213 return blockRank( cr );
214}
215
216//---------------------------------------------------------------------------//
217// Get the global number of cells in a given dimension.
218template <class MeshType>
220{
221 return _global_mesh->globalNumCell( dim );
222}
223
224//---------------------------------------------------------------------------//
225// Get the global number of nodes in a given dimension.
226template <class MeshType>
228{
229 // If this dimension is periodic that last node in the dimension is
230 // repeated across the periodic boundary.
231 if ( _periodic[dim] )
232 return globalNumEntity( Cell(), dim );
233 else
234 return globalNumEntity( Cell(), dim ) + 1;
235}
236
237//---------------------------------------------------------------------------//
238// Get the global number of I-faces in a given dimension.
239template <class MeshType>
241{
242 return ( Dim::I == dim ) ? globalNumEntity( Node(), dim )
243 : globalNumEntity( Cell(), dim );
244}
245
246//---------------------------------------------------------------------------//
247// Get the global number of J-faces in a given dimension.
248template <class MeshType>
250{
251 return ( Dim::J == dim ) ? globalNumEntity( Node(), dim )
252 : globalNumEntity( Cell(), dim );
253}
254
255//---------------------------------------------------------------------------//
256// Get the global number of K-faces in a given dimension.
257template <class MeshType>
258template <std::size_t NSD>
259std::enable_if_t<3 == NSD, int>
261{
262 return ( Dim::K == dim ) ? globalNumEntity( Node(), dim )
263 : globalNumEntity( Cell(), dim );
264}
265
266//---------------------------------------------------------------------------//
267// Get the global number of I-edges in a given dimension.
268template <class MeshType>
269template <std::size_t NSD>
270std::enable_if_t<3 == NSD, int>
272{
273 return ( Dim::I == dim ) ? globalNumEntity( Cell(), dim )
274 : globalNumEntity( Node(), dim );
275}
276
277//---------------------------------------------------------------------------//
278// Get the global number of J-edges in a given dimension.
279template <class MeshType>
280template <std::size_t NSD>
281std::enable_if_t<3 == NSD, int>
283{
284 return ( Dim::J == dim ) ? globalNumEntity( Cell(), dim )
285 : globalNumEntity( Node(), dim );
286}
287
288//---------------------------------------------------------------------------//
289// Get the global number of K-edges in a given dimension.
290template <class MeshType>
291template <std::size_t NSD>
292std::enable_if_t<3 == NSD, int>
294{
295 return ( Dim::K == dim ) ? globalNumEntity( Cell(), dim )
296 : globalNumEntity( Node(), dim );
297}
298
299//---------------------------------------------------------------------------//
300// Get the owned number of cells in a given dimension.
301template <class MeshType>
302int GlobalGrid<MeshType>::ownedNumCell( const int dim ) const
303{
304 return _owned_num_cell[dim];
305}
306
307//---------------------------------------------------------------------------//
308// Get the global offset in a given dimension for the entity of a given
309// type. This is where our block starts in the global indexing scheme.
310template <class MeshType>
311int GlobalGrid<MeshType>::globalOffset( const int dim ) const
312{
313 return _global_cell_offset[dim];
314}
315
316//---------------------------------------------------------------------------//
317// Set the number of owned cells and global offset. Make sure this is
318// consistent across all ranks.
319template <class MeshType>
321 const std::array<int, num_space_dim>& num_cell,
322 const std::array<int, num_space_dim>& offset )
323{
324 std::copy( std::begin( num_cell ), std::end( num_cell ),
325 std::begin( _owned_num_cell ) );
326 std::copy( std::begin( offset ), std::end( offset ),
327 std::begin( _global_cell_offset ) );
328}
329
330//---------------------------------------------------------------------------//
331} // namespace Grid
332} // namespace Cabana
333
334#endif // end CABANA_GRID_GLOBALGRID_IMPL_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.
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.
bool onLowBoundary(const int dim) const
Determine if this block is on a low boundary in this dimension.
Definition Cabana_Grid_GlobalGrid_impl.hpp:120
int globalOffset(const int dim) const
Get the global offset in a given dimension. This is where our block starts in the global indexing sch...
Definition Cabana_Grid_GlobalGrid_impl.hpp:311
const GlobalMesh< MeshType > & globalMesh() const
Get the global mesh data.
Definition Cabana_Grid_GlobalGrid_impl.hpp:104
MPI_Comm comm() const
Get the communicator. This communicator was generated with a Cartesian topology.
Definition Cabana_Grid_GlobalGrid_impl.hpp:96
int dimBlockId(const int dim) const
Get the id of this block in a given dimension.
Definition Cabana_Grid_GlobalGrid_impl.hpp:154
int totalNumBlock() const
Get the total number of blocks.
Definition Cabana_Grid_GlobalGrid_impl.hpp:144
bool isPeriodic(const int dim) const
Get whether a given dimension is periodic.
Definition Cabana_Grid_GlobalGrid_impl.hpp:112
int blockId() const
Get the id of this block.
Definition Cabana_Grid_GlobalGrid_impl.hpp:162
int ownedNumCell(const int dim) const
Get the owned number of cells in a given dimension of this block.
Definition Cabana_Grid_GlobalGrid_impl.hpp:302
int dimNumBlock(const int dim) const
Get the number of blocks in each dimension in the global mesh.
Definition Cabana_Grid_GlobalGrid_impl.hpp:136
GlobalGrid(MPI_Comm comm, const std::shared_ptr< GlobalMesh< MeshType > > &global_mesh, const std::array< bool, num_space_dim > &periodic, const BlockPartitioner< num_space_dim > &partitioner)
Constructor.
Definition Cabana_Grid_GlobalGrid_impl.hpp:26
int blockRank(const std::array< int, num_space_dim > &ijk) const
Get the MPI rank of a block with the given indices. If the rank is out of bounds and the boundary is ...
Definition Cabana_Grid_GlobalGrid_impl.hpp:174
bool onHighBoundary(const int dim) const
Determine if this block is on a high boundary in this dimension.
Definition Cabana_Grid_GlobalGrid_impl.hpp:128
static constexpr std::size_t num_space_dim
Spatial dimension.
Definition Cabana_Grid_GlobalGrid.hpp:45
int globalNumEntity(Cell, const int dim) const
Get the global number of entities in a given dimension.
Definition Cabana_Grid_GlobalGrid_impl.hpp:219
void setNumCellAndOffset(const std::array< int, num_space_dim > &num_cell, const std::array< int, num_space_dim > &offset)
Set number of cells and offset of local part of the grid. Make sure these are consistent across all r...
Definition Cabana_Grid_GlobalGrid_impl.hpp:320
Global mesh partial specialization for uniform mesh.
Definition Cabana_Grid_GlobalMesh.hpp:49
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
Mesh cell tag.
Definition Cabana_Grid_Types.hpp:49
Mesh edge tag.
Definition Cabana_Grid_Types.hpp:95
Mesh face tag.
Definition Cabana_Grid_Types.hpp:64
Mesh node tag.
Definition Cabana_Grid_Types.hpp:56