peclet.voro 1.0.0
Device-native moving-particle Voronoi dynamics
Loading...
Searching...
No Matches
voronoi_halo.hpp
Go to the documentation of this file.
1
22#ifndef PECLET_VORO_MPI_VORONOI_HALO_HPP
23#define PECLET_VORO_MPI_VORONOI_HALO_HPP
24
25#include <array>
26#include <cstddef>
27#include <vector>
28
29#include "peclet/core/common/mpi.hpp"
30#include "peclet/core/decomp/block_decomposer.hpp"
31#include "peclet/core/halo/particle_halo_topology.hpp"
32#include "peclet/core/halo/particle_migrator.hpp"
33
34namespace peclet::voro {
35namespace mpi {
36
37template <class Real>
39 public:
40 using Vec3 = std::array<Real, 3>;
41
43 struct Gathered {
44 std::vector<Vec3> pos;
45 std::vector<long> gid;
46 std::vector<Real> weight;
47 int nOwned = 0;
48 };
49
53 void init(std::array<Real, 3> origin, std::array<Real, 3> size, std::array<long, 3> gsize,
54 std::array<bool, 3> periodic, MPI_Comm comm = MPI_COMM_WORLD) {
55 comm_ = comm;
56 int sz = 1;
57 MPI_Comm_rank(comm_, &rank_);
58 MPI_Comm_size(comm_, &sz);
59 dec_.init(static_cast<std::size_t>(sz), peclet::core::IVec<3>{gsize[0], gsize[1], gsize[2]});
60 peclet::core::halo::DomainMap<3> map;
61 for (int i = 0; i < 3; ++i) {
62 map.origin[i] = origin[i];
63 map.cellSize[i] = size[i] / static_cast<double>(gsize[i]);
64 map.periodic[i] = periodic[i];
65 }
66 mig_.init(dec_, rank_, map, comm_);
67 halo_.init(mig_);
68 }
69
70 int rank() const { return rank_; }
71 int size() const {
72 int s = 1;
73 MPI_Comm_size(comm_, &s);
74 return s;
75 }
76
78 int ownerOf(const Vec3& x) const {
79 peclet::core::Vec<3> v{x[0], x[1], x[2]};
80 return mig_.ownerOf(v);
81 }
82
85 Gathered gather(const std::vector<Vec3>& ownedPos, const std::vector<long>& ownedGid,
86 const std::vector<Real>& ownedWeight, double rcut) {
87 const int nOwned = static_cast<int>(ownedPos.size());
88 std::vector<peclet::core::Vec<3>> pv(nOwned);
89 for (int i = 0; i < nOwned; ++i)
90 pv[i] = peclet::core::Vec<3>{ownedPos[i][0], ownedPos[i][1], ownedPos[i][2]};
91 // includePeriodicSelf=false: the tessellator is periodic-native (minimal image),
92 // so two same-rank seeds interact across a periodic face directly — only
93 // cross-rank neighbours (which the build still gathers, periodic images
94 // included) need to travel as ghosts. Self-ghosts would just duplicate owned
95 // seeds (wrapping back onto them) and inflate the set.
96 halo_.build(pv, rcut, /*includePeriodicSelf=*/false);
97 const int ng = static_cast<int>(halo_.numGhost());
98
99 // Forward owner global-id and weight onto the ghost copies.
100 std::vector<long> ghostGid(ng);
101 std::vector<Real> ghostW(ng);
102 halo_.forward(ownedGid.data(), ghostGid.data());
103 halo_.forward(ownedWeight.data(), ghostW.data());
104 const std::vector<peclet::core::Vec<3>>& gpos = halo_.ghostPositions();
105
106 Gathered g;
107 g.nOwned = nOwned;
108 g.pos.resize(nOwned + ng);
109 g.gid.resize(nOwned + ng);
110 g.weight.resize(nOwned + ng);
111 for (int i = 0; i < nOwned; ++i) {
112 g.pos[i] = ownedPos[i];
113 g.gid[i] = ownedGid[i];
114 g.weight[i] = ownedWeight[i];
115 }
116 for (int j = 0; j < ng; ++j) {
117 g.pos[nOwned + j] = Vec3{gpos[j][0], gpos[j][1], gpos[j][2]};
118 g.gid[nOwned + j] = ghostGid[j];
119 g.weight[nOwned + j] = ghostW[j];
120 }
121 nGhost_ = ng;
122 return g;
123 }
124
126 int numGhost() const { return nGhost_; }
127
137 void refreshPositions(const std::vector<Vec3>& ownedPos, std::vector<Vec3>& out) {
138 const int nOwned = static_cast<int>(ownedPos.size());
139 const int ng = nGhost_;
140 std::vector<Real> ox(nOwned), oy(nOwned), oz(nOwned), gx(ng), gy(ng), gz(ng);
141 for (int i = 0; i < nOwned; ++i) {
142 ox[i] = ownedPos[i][0];
143 oy[i] = ownedPos[i][1];
144 oz[i] = ownedPos[i][2];
145 }
146 halo_.forward(ox.data(), gx.data());
147 halo_.forward(oy.data(), gy.data());
148 halo_.forward(oz.data(), gz.data());
149 out.resize(nOwned + ng);
150 for (int i = 0; i < nOwned; ++i)
151 out[i] = ownedPos[i];
152 for (int j = 0; j < ng; ++j)
153 out[nOwned + j] = Vec3{gx[j], gy[j], gz[j]};
154 }
155
156 private:
157 int nGhost_ = 0;
158 MPI_Comm comm_ = MPI_COMM_WORLD;
159 int rank_ = 0;
160 peclet::core::decomp::BlockDecomposer<3> dec_;
161 peclet::core::halo::ParticleMigrator<3> mig_;
162 peclet::core::halo::ParticleHaloTopology<3> halo_;
163};
164
165} // namespace mpi
166} // namespace peclet::voro
167
168#endif // PECLET_VORO_MPI_VORONOI_HALO_HPP
Definition voronoi_halo.hpp:38
int rank() const
Definition voronoi_halo.hpp:70
int numGhost() const
Number of ghosts in the last gather() (the established topology).
Definition voronoi_halo.hpp:126
int size() const
Definition voronoi_halo.hpp:71
Gathered gather(const std::vector< Vec3 > &ownedPos, const std::vector< long > &ownedGid, const std::vector< Real > &ownedWeight, double rcut)
Definition voronoi_halo.hpp:85
std::array< Real, 3 > Vec3
Definition voronoi_halo.hpp:40
void init(std::array< Real, 3 > origin, std::array< Real, 3 > size, std::array< long, 3 > gsize, std::array< bool, 3 > periodic, MPI_Comm comm=MPI_COMM_WORLD)
Definition voronoi_halo.hpp:53
void refreshPositions(const std::vector< Vec3 > &ownedPos, std::vector< Vec3 > &out)
Definition voronoi_halo.hpp:137
int ownerOf(const Vec3 &x) const
Rank that owns position x.
Definition voronoi_halo.hpp:78
Definition convex_cell.hpp:40
Combined owned+ghost seeds (owned first), with global ids and weights.
Definition voronoi_halo.hpp:43
std::vector< long > gid
global seed id per entry
Definition voronoi_halo.hpp:45
std::vector< Vec3 > pos
[0,nOwned) owned, [nOwned,size) ghost
Definition voronoi_halo.hpp:44
int nOwned
Definition voronoi_halo.hpp:47
std::vector< Real > weight
per entry (0 if unweighted)
Definition voronoi_halo.hpp:46