Line data Source code
1 :
2 : //
3 : // Class ParticleSpatialLayout
4 : // Particle layout based on spatial decomposition.
5 : //
6 : // This is a specialized version of ParticleLayout, which places particles
7 : // on processors based on their spatial location relative to a fixed grid.
8 : // In particular, this can maintain particles on processors based on a
9 : // specified FieldLayout or RegionLayout, so that particles are always on
10 : // the same node as the node containing the Field region to which they are
11 : // local. This may also be used if there is no associated Field at all,
12 : // in which case a grid is selected based on an even distribution of
13 : // particles among processors.
14 : //
15 : // After each 'time step' in a calculation, which is defined as a period
16 : // in which the particle positions may change enough to affect the global
17 : // layout, the user must call the 'update' routine, which will move
18 : // particles between processors, etc. After the Nth call to update, a
19 : // load balancing routine will be called instead. The user may set the
20 : // frequency of load balancing (N), or may supply a function to
21 : // determine if load balancing should be done or not.
22 : //
23 : #ifndef IPPL_PARTICLE_SPATIAL_LAYOUT_H
24 : #define IPPL_PARTICLE_SPATIAL_LAYOUT_H
25 :
26 : #include "Types/IpplTypes.h"
27 :
28 : #include "FieldLayout/FieldLayout.h"
29 : #include "Particle/ParticleBase.h"
30 : #include "Particle/ParticleLayout.h"
31 : #include "Region/RegionLayout.h"
32 :
33 : #include "Communicate/Window.h"
34 : #include <vector>
35 :
36 : namespace ippl {
37 :
38 : /*!
39 : * ParticleSpatialLayout class definition.
40 : * @tparam T value type
41 : * @tparam Dim dimension
42 : * @tparam Mesh type
43 : */
44 : template <typename T, unsigned Dim, class Mesh = UniformCartesian<T, Dim>,
45 : typename... PositionProperties>
46 : class ParticleSpatialLayout : public detail::ParticleLayout<T, Dim, PositionProperties...> {
47 : public:
48 : using Base = detail::ParticleLayout<T, Dim, PositionProperties...>;
49 : using typename Base::position_memory_space, typename Base::position_execution_space;
50 :
51 : using hash_type = detail::hash_type<position_memory_space>;
52 : using locate_type = typename detail::ViewType<int, 1, position_memory_space>::view_type;
53 : using bool_type = typename detail::ViewType<bool, 1, position_memory_space>::view_type;
54 :
55 : using vector_type = typename Base::vector_type;
56 : using RegionLayout_t =
57 : typename detail::RegionLayout<T, Dim, Mesh, position_memory_space>::uniform_type;
58 : using FieldLayout_t = typename ippl::FieldLayout<Dim>;
59 :
60 : using size_type = detail::size_type;
61 :
62 : public:
63 : // constructor: this one also takes a Mesh
64 : ParticleSpatialLayout(FieldLayout<Dim>&, Mesh&);
65 :
66 : ParticleSpatialLayout()
67 : : detail::ParticleLayout<T, Dim, PositionProperties...>() {}
68 :
69 60 : ~ParticleSpatialLayout() = default;
70 :
71 : void updateLayout(FieldLayout<Dim>&, Mesh&);
72 :
73 : template <class ParticleContainer>
74 : void update(ParticleContainer& pc);
75 :
76 12 : const RegionLayout_t& getRegionLayout() const { return rlayout_m; }
77 :
78 : protected:
79 : //! The RegionLayout which determines where our particles go.
80 : RegionLayout_t rlayout_m;
81 :
82 : //! The FieldLayout containing information on nearest neighbors
83 : FieldLayout_t& flayout_m;
84 :
85 : // MPI RMA window for one-sided communication
86 : mpi::rma::Window<mpi::rma::Active> window_m;
87 :
88 : // Vector keeping track of the recieves from all ranks
89 : std::vector<size_type> nRecvs_m;
90 :
91 : //! Type of the Kokkos view containing the local regions.
92 : using region_view_type = typename RegionLayout_t::view_type;
93 : //! Type of a single Region object.
94 : using region_type = typename region_view_type::value_type;
95 : //! Array of N rank lists, where N = number of hypercubes for the dimension Dim.
96 : using neighbor_list = typename FieldLayout_t::neighbor_list;
97 :
98 : template <size_t... Idx>
99 : KOKKOS_INLINE_FUNCTION constexpr static bool positionInRegion(
100 : const std::index_sequence<Idx...>&, const vector_type& pos, const region_type& region);
101 :
102 : /*!
103 : * Evaluates the total number of MPI ranks sharing the spatial nearest neighbors.
104 : * @param neighbors structure containing, for every spatial direction, a list of
105 : * MPI ranks IDs corresponding to the nearest neighbors of the current local domain section.
106 : * @return The total number of the ranks.
107 : */
108 : size_type getNeighborSize(const neighbor_list& neighbors) const;
109 :
110 : public:
111 : /*!
112 : * For each particle in the bunch, determine the rank on which it should
113 : * be stored based on its location
114 : * @tparam ParticleContainer the particle container type
115 : * @param pc the particle container
116 : * @param ranks the integer view in which to store the destination ranks
117 : * @param invalid the boolean view in which to store whether each particle
118 : * is invalidated, i.e. needs to be sent to another rank
119 : * @return The total number of invalidated particles
120 : */
121 : template <typename ParticleContainer>
122 : std::pair<size_type,size_type> locateParticles(const ParticleContainer& pc, locate_type& ranks,
123 : bool_type& invalid, locate_type& nSends_dview, locate_type& sends_dview) const;
124 :
125 : /*!
126 : * @param rank we sent to
127 : * @param ranks a container specifying where a particle at the i-th index should go.
128 : * @param hash a mapping to fill the send buffer contiguously
129 : */
130 : void fillHash(int rank, const locate_type& ranks, hash_type& hash);
131 :
132 : /*!
133 : * @param rank we sent to
134 : * @param ranks a container specifying where a particle at the i-th index should go.
135 : */
136 : size_t numberOfSends(int rank, const locate_type& ranks);
137 : };
138 : } // namespace ippl
139 :
140 : #include "Particle/ParticleSpatialLayout.hpp"
141 :
142 : #endif
143 :
|