peclet.voro 1.0.0
Device-native moving-particle Voronoi dynamics
Loading...
Searching...
No Matches
distributed_moving.hpp
Go to the documentation of this file.
1
20#ifndef PECLET_VORO_MPI_DISTRIBUTED_MOVING_HPP
21#define PECLET_VORO_MPI_DISTRIBUTED_MOVING_HPP
22
23#include <mpi.h>
24
25#include <array>
26#include <cmath>
27#include <vector>
28
29#include "../repair.hpp"
30#include "voronoi_halo.hpp"
31
33
34template <class Real, int MAXP = 64, int MAXT = 112>
36 using Vec3 = std::array<Real, 3>;
37 using Mem = typename Kokkos::DefaultExecutionSpace::memory_space;
38
39 struct StepStats {
40 bool regathered = false;
42 };
43
45 void init(std::array<Real, 3> origin, std::array<Real, 3> size, std::array<long, 3> gsize,
46 std::array<bool, 3> periodic, Real rcut, Real skin, Real tol, MPI_Comm comm,
47 int searchWindow = 4, int densityCount = -1) {
48 halo_.init(origin, size, gsize, periodic, comm);
49 comm_ = comm;
50 for (int d = 0; d < 3; ++d)
51 L_[d] = size[d];
52 rcut_ = rcut;
53 skin_ = skin;
54 tol_ = tol;
55 sw_ = searchWindow;
56 density_ = densityCount;
57 }
58
59 int ownerOf(const Vec3& x) const { return halo_.ownerOf(x); }
60
63 void establish(const std::vector<Vec3>& ownedPos, const std::vector<long>& ownedGid,
64 const std::vector<Real>& ownedW) {
65 gid_ = ownedGid;
66 w_ = ownedW;
67 regather(ownedPos);
68 }
69
71 StepStats step(const std::vector<Vec3>& ownedPos) {
72 StepStats st;
73 int localTrip = (maxDispFrom(ownedPos, refPos_) > Real(0.5) * skin_) ? 1 : 0;
74 int anyTrip = 0;
75 MPI_Allreduce(&localTrip, &anyTrip, 1, MPI_INT, MPI_MAX, comm_);
76 if (anyTrip) {
77 regather(ownedPos);
78 st.regathered = true;
79 } else {
80 std::vector<Vec3> comb;
81 halo_.refreshPositions(ownedPos, comb);
82 upload(comb);
83 st.repair = mt_.step(dPos_);
84 }
85 return st;
86 }
87
89 int nCombined() const { return nComb_; }
90 int nOwned() const { return nOwned_; }
93 const Kokkos::View<Real*, Mem>& positions() const { return dPos_; }
95 const std::vector<long>& combinedGid() const { return combGid_; }
96 long numRegathers() const { return nRegather_; }
97
98 private:
99 void regather(const std::vector<Vec3>& ownedPos) {
100 auto g = halo_.gather(ownedPos, gid_, w_, rcut_);
101 nComb_ = (int)g.pos.size();
102 nOwned_ = g.nOwned;
103 combGid_ = g.gid;
104 upload(g.pos);
105 mt_.alloc(nComb_, L_, tol_, skin_, sw_, density_, nOwned_);
106 mt_.rebuild(dPos_);
107 refPos_ = ownedPos;
108 ++nRegather_;
109 }
110
111 void upload(const std::vector<Vec3>& p) {
112 const int n = (int)p.size();
113 // exact size: MovingTessellation deep_copies the whole extent (xRef), so a slack buffer trips
114 // the extent check
115 if ((int)dPos_.extent(0) != 3 * n)
116 dPos_ = Kokkos::View<Real*, Mem>(
117 Kokkos::view_alloc(std::string("dmt_pos"), Kokkos::WithoutInitializing), (size_t)n * 3);
118 auto h = Kokkos::create_mirror_view(dPos_);
119 for (int i = 0; i < n; ++i)
120 for (int k = 0; k < 3; ++k)
121 h(3 * i + k) = wrap1(p[i][k], L_[k]);
122 Kokkos::deep_copy(dPos_, h);
123 }
124
125 Real maxDispFrom(const std::vector<Vec3>& a, const std::vector<Vec3>& b) const {
126 if (a.size() != b.size())
127 return Real(1e30); // ownership changed under us: force a re-gather
128 Real m2 = 0;
129 for (std::size_t i = 0; i < a.size(); ++i) {
130 Real d2 = 0;
131 for (int d = 0; d < 3; ++d) {
132 Real q = a[i][d] - b[i][d];
133 q -= std::round(q / L_[d]) * L_[d];
134 d2 += q * q;
135 }
136 m2 = std::max(m2, d2);
137 }
138 return std::sqrt(m2);
139 }
140
141 static Real wrap1(Real x, Real L) {
142 Real y = std::fmod(x, L);
143 return y < 0 ? y + L : y;
144 }
145
146 VoronoiHalo<Real> halo_;
147 MovingTessellation<Real, MAXP, MAXT> mt_;
148 Kokkos::View<Real*, Mem> dPos_;
149 std::vector<Vec3> refPos_; // owned positions at the last (re)gather (Verlet reference)
150 std::vector<long> gid_, combGid_;
151 std::vector<Real> w_;
152 Real L_[3] = {1, 1, 1};
153 Real rcut_ = 0, skin_ = 0, tol_ = 0;
154 int sw_ = 4, density_ = -1, nComb_ = 0, nOwned_ = 0;
155 long nRegather_ = 0;
156 MPI_Comm comm_ = MPI_COMM_WORLD;
157};
158
159} // namespace peclet::voro::mpi
160
161#endif // PECLET_VORO_MPI_DISTRIBUTED_MOVING_HPP
Definition distributed_moving.hpp:32
Definition repair.hpp:64
Per-step repair telemetry.
Definition repair.hpp:48
RepairStats repair
fast-path repair stats (valid when !regathered)
Definition distributed_moving.hpp:41
bool regathered
this step took the re-gather + cold-rebuild path (collective)
Definition distributed_moving.hpp:40
Definition distributed_moving.hpp:35
void establish(const std::vector< Vec3 > &ownedPos, const std::vector< long > &ownedGid, const std::vector< Real > &ownedW)
Definition distributed_moving.hpp:63
MovingTessellation< Real, MAXP, MAXT > & tess()
The device tessellation (cells [0, nOwned) are this rank's owned cells).
Definition distributed_moving.hpp:92
void init(std::array< Real, 3 > origin, std::array< Real, 3 > size, std::array< long, 3 > gsize, std::array< bool, 3 > periodic, Real rcut, Real skin, Real tol, MPI_Comm comm, int searchWindow=4, int densityCount=-1)
One-time setup. gsize is the ORB decomposition granularity (cells per axis).
Definition distributed_moving.hpp:45
typename Kokkos::DefaultExecutionSpace::memory_space Mem
Definition distributed_moving.hpp:37
std::array< Real, 3 > Vec3
Definition distributed_moving.hpp:36
int nOwned() const
Definition distributed_moving.hpp:90
const Kokkos::View< Real *, Mem > & positions() const
Definition distributed_moving.hpp:93
int ownerOf(const Vec3 &x) const
Definition distributed_moving.hpp:59
int nCombined() const
Combined owned+ghost count and owned count of the current tessellation.
Definition distributed_moving.hpp:89
StepStats step(const std::vector< Vec3 > &ownedPos)
Advance to new owned positions (same ownership as establish; collective every step).
Definition distributed_moving.hpp:71
const std::vector< long > & combinedGid() const
Global ids of the combined (owned+ghost) seeds after the last (re)gather.
Definition distributed_moving.hpp:95
long numRegathers() const
Definition distributed_moving.hpp:96
Distributed Voronoi halo over core (migration Phase 6).