Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_Distributor.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_DISTRIBUTOR_HPP
17#define CABANA_DISTRIBUTOR_HPP
18
19#include <Cabana_AoSoA.hpp>
21#include <Cabana_Core_Config.hpp>
22#include <Cabana_Slice.hpp>
23
24#include <Kokkos_Core.hpp>
25#include <Kokkos_Profiling_ScopedRegion.hpp>
26
27#include <mpi.h>
28
29#include <exception>
30#include <vector>
31
32namespace Cabana
33{
34//---------------------------------------------------------------------------//
62template <class MemorySpace, class CommSpaceType = Mpi>
63class Distributor : public CommunicationPlan<MemorySpace, CommSpaceType>
64{
65 public:
67 using commspace_type = CommSpaceType;
68
103 template <class ViewType>
104 Distributor( MPI_Comm comm, const ViewType& element_export_ranks,
105 const std::vector<int>& neighbor_ranks )
106 : CommunicationPlan<MemorySpace, CommSpaceType>( comm )
107 {
108 auto neighbor_ids = this->createWithTopology(
109 Export(), element_export_ranks, neighbor_ranks );
110 this->createExportSteering( neighbor_ids, element_export_ranks );
111 }
112
140 template <class ViewType>
141 Distributor( MPI_Comm comm, const ViewType& element_export_ranks )
142 : CommunicationPlan<MemorySpace, CommSpaceType>( comm )
143 {
144 auto neighbor_ids =
145 this->createWithoutTopology( Export(), element_export_ranks );
146 this->createExportSteering( neighbor_ids, element_export_ranks );
147 }
148};
149
150//---------------------------------------------------------------------------//
152template <typename>
153struct is_distributor_impl : public std::false_type
154{
155};
156
157template <typename MemorySpace, typename CommSpaceType>
158struct is_distributor_impl<Distributor<MemorySpace, CommSpaceType>>
159 : public std::true_type
160{
161};
163
165template <class T>
167 : public is_distributor_impl<typename std::remove_cv<T>::type>::type
168{
169};
170
171} // end namespace Cabana
172
173// Include communication backends from what is enabled in CMake.
174#ifdef Cabana_ENABLE_MPI
176#endif // Enable MPI
177
178namespace Cabana
179{
180
181//---------------------------------------------------------------------------//
202template <class ExecutionSpace, class Distributor_t, class AoSoA_t>
203void migrate( ExecutionSpace exec_space, const Distributor_t& distributor,
204 const AoSoA_t& src, AoSoA_t& dst,
205 typename std::enable_if<( is_distributor<Distributor_t>::value &&
207 int>::type* = 0 )
208{
209 // Check that src and dst are the right size.
210 if ( src.size() != distributor.exportSize() )
211 throw std::runtime_error( "Cabana::migrate: Source is "
212 "the wrong size for migration! (Label: " +
213 src.label() + ")" );
214 if ( dst.size() != distributor.totalNumImport() )
215 throw std::runtime_error( "Cabana::migrate: Destination "
216 "is the wrong size for migration! (Label: " +
217 dst.label() + ")" );
218
219 // Move the data.
220 Impl::migrateData( typename Distributor_t::commspace_type(), exec_space,
221 distributor, src, dst );
222}
223
241template <class Distributor_t, class AoSoA_t>
242void migrate( const Distributor_t& distributor, const AoSoA_t& src,
243 AoSoA_t& dst,
244 typename std::enable_if<( is_distributor<Distributor_t>::value &&
246 int>::type* = 0 )
247{
248 migrate( typename Distributor_t::execution_space{}, distributor, src, dst );
249}
250
251//---------------------------------------------------------------------------//
275template <class ExecutionSpace, class Distributor_t, class AoSoA_t>
276void migrate( ExecutionSpace exec_space, const Distributor_t& distributor,
277 AoSoA_t& aosoa,
278 typename std::enable_if<( is_distributor<Distributor_t>::value &&
280 int>::type* = 0 )
281{
282 // Check that the AoSoA is the right size.
283 if ( aosoa.size() != distributor.exportSize() )
284 throw std::runtime_error(
285 "Cabana::migrate (in-place): "
286 "AoSoA is the wrong size for migration! (Label: " +
287 aosoa.label() + ")" );
288
289 // Determine if the source of destination decomposition has more data on
290 // this rank.
291 bool dst_is_bigger =
292 ( distributor.totalNumImport() > distributor.exportSize() );
293
294 // If the destination decomposition is bigger than the source
295 // decomposition resize now so we have enough space to do the operation.
296 if ( dst_is_bigger )
297 aosoa.resize( distributor.totalNumImport() );
298
299 // Move the data.
300 Impl::migrateData( typename Distributor_t::commspace_type(), exec_space,
301 distributor, aosoa, aosoa );
302
303 // If the destination decomposition is smaller than the source
304 // decomposition resize after we have moved the data.
305 if ( !dst_is_bigger )
306 aosoa.resize( distributor.totalNumImport() );
307}
308
330template <class Distributor_t, class AoSoA_t>
331void migrate( const Distributor_t& distributor, AoSoA_t& aosoa,
332 typename std::enable_if<( is_distributor<Distributor_t>::value &&
334 int>::type* = 0 )
335{
336 migrate( typename Distributor_t::execution_space{}, distributor, aosoa );
337}
338
360template <class ExecutionSpace, class Distributor_t, class Slice_t>
361void migrate( ExecutionSpace exec_space, const Distributor_t& distributor,
362 const Slice_t& src, Slice_t& dst,
363 typename std::enable_if<( is_distributor<Distributor_t>::value &&
365 int>::type* = 0 )
366{
367 // Check that src and dst are the right size.
368 if ( src.size() != distributor.exportSize() )
369 throw std::runtime_error( "Cabana::migrate: Source Slice is the wrong "
370 "size for migration! (Label: " +
371 src.label() + ")" );
372 if ( dst.size() != distributor.totalNumImport() )
373 throw std::runtime_error( "Cabana::migrate: Destination Slice is the "
374 "wrong size for migration! (Label: " +
375 dst.label() + ")" );
376
377 // Move the data.
378 Impl::migrateSlice( typename Distributor_t::commspace_type(), exec_space,
379 distributor, src, dst );
380}
381
401template <class Distributor_t, class Slice_t>
402void migrate( const Distributor_t& distributor, const Slice_t& src,
403 Slice_t& dst,
404 typename std::enable_if<( is_distributor<Distributor_t>::value &&
406 int>::type* = 0 )
407{
408 migrate( typename Distributor_t::execution_space{}, distributor, src, dst );
409}
410//---------------------------------------------------------------------------//
411
412} // end namespace Cabana
413
414#endif // end CABANA_DISTRIBUTOR_HPP
Array-of-Struct-of-Arrays particle data structure.
Multi-node communication patterns. Base class.
Vanilla MPI implementation of Cabana::migrate variations.
Slice a single particle property from an AoSoA.
void createExportSteering(const PackViewType &neighbor_ids, const RankViewType &element_export_ranks)
Create the export steering vector.
Definition Cabana_CommunicationPlanBase.hpp:569
MPI_Comm comm() const
Get the MPI communicator.
Definition Cabana_CommunicationPlanBase.hpp:465
Kokkos::View< size_type *, memory_space > createWithTopology(ExecutionSpace exec_space, Export, const RankViewType &element_export_ranks, const std::vector< int > &neighbor_ranks)
Neighbor and export rank creator. Use this when you already know which ranks neighbor each other (i....
Definition Cabana_CommunicationPlan_Mpi.hpp:107
Kokkos::View< size_type *, memory_space > createWithoutTopology(ExecutionSpace exec_space, Export, const RankViewType &element_export_ranks)
Export rank creator. Use this when you don't know who you will receiving from - only who you are send...
Definition Cabana_CommunicationPlan_Mpi.hpp:272
CommunicationPlan(MPI_Comm comm)
Constructor.
Definition Cabana_CommunicationPlan_Mpi.hpp:59
A communication plan for migrating data from one uniquely-owned decomposition to another uniquely own...
Definition Cabana_Distributor.hpp:64
Distributor(MPI_Comm comm, const ViewType &element_export_ranks)
Export rank constructor. Use this when you don't know who you will be receiving from - only who you a...
Definition Cabana_Distributor.hpp:141
Distributor(MPI_Comm comm, const ViewType &element_export_ranks, const std::vector< int > &neighbor_ranks)
Topology and export rank constructor. Use this when you already know which ranks neighbor each other ...
Definition Cabana_Distributor.hpp:104
CommSpaceType commspace_type
Communication space.
Definition Cabana_Distributor.hpp:67
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
void migrate(ExecutionSpace exec_space, const Distributor_t &distributor, const AoSoA_t &src, AoSoA_t &dst, typename std::enable_if<(is_distributor< Distributor_t >::value &&is_aosoa< AoSoA_t >::value), int >::type *=0)
Synchronously migrate data between two different decompositions using the distributor forward communi...
Definition Cabana_Distributor.hpp:203
Export-based tag - default.
Definition Cabana_Tags.hpp:38
AoSoA static type checker.
Definition Cabana_AoSoA.hpp:61
Distributor static type checker.
Definition Cabana_Distributor.hpp:168
Slice static type checker.
Definition Cabana_Slice.hpp:868