peclet.voro 1.0.4
Device-native moving-particle Voronoi dynamics
Loading...
Searching...
No Matches
reeval_tessellation.hpp
Go to the documentation of this file.
1
23#ifndef PECLET_VORO_REEVAL_TESSELLATION_HPP
24#define PECLET_VORO_REEVAL_TESSELLATION_HPP
25
26#include <Kokkos_Core.hpp>
27#include <string>
28
29#include "peclet/core/common/view.hpp"
31#include "peclet/voro/sdf.hpp" // WallStore
33#include "peclet/voro/tessellator.hpp" // areaGradEnumerate / areaGradFill (rung A3)
35
36namespace peclet::voro {
37
48template <class Real, int MAXP, int MAXT>
50 const Kokkos::View<Real*, peclet::core::MemSpace>& pos,
51 const Kokkos::View<Real*, peclet::core::MemSpace>& vol, int N,
52 const Real L[3], WallStore<Real> wall = {},
53 Kokkos::View<Real*, peclet::core::MemSpace> xRef = {},
54 bool withAreaGrad = false, bool withMoments = false) {
55 using Mem = peclet::core::MemSpace;
56 using Exec = peclet::core::ExecSpace;
57 using Cell = ConvexCell<Real, MAXP, MAXT, false>;
58 using Kokkos::view_alloc;
59 using Kokkos::WithoutInitializing;
60 const Real Lx = L[0], Ly = L[1], Lz = L[2];
61 TopologyStore<MAXP, MAXT> st = store;
62 Kokkos::View<Real*, Mem> P = pos;
63
64 // ---- 1. per-cell live-face count (topology only: the >=3-incident-live-triangle criterion) ----
65 Kokkos::View<int*, Mem> facetCount("rp.facetCount", static_cast<std::size_t>(N));
66 Kokkos::View<int*, Mem> edgeCount("rp.edgeCount", withAreaGrad ? static_cast<std::size_t>(N) : 0);
67 constexpr int kMaxF = MAXP; // == CellBuilder::MAXF_TMP: what the cold build can publish
68 const bool wag = withAreaGrad;
69 Kokkos::parallel_for(
70 "reevalPublish.count", Kokkos::RangePolicy<Exec>(0, N), KOKKOS_LAMBDA(const int i) {
71 Cell c;
72 st.load(i, c, Lx, Ly, Lz);
73 int nf = 0;
74 int faces[kMaxF];
75 for (int k = 0; k < c.np; ++k) {
76 int cnt = 0;
77 for (int t = 0; t < c.nt; ++t)
78 if (c.alive[t] && (c.t0[t] == k || c.t1[t] == k || c.t2[t] == k))
79 ++cnt;
80 if (cnt >= 3) {
81 if (nf < kMaxF)
82 faces[nf] = k;
83 ++nf;
84 }
85 }
86 facetCount(i) = nf;
87 if (wag) {
88 unsigned char part[kMaxF * Cell::MAXFV], pcnt[kMaxF];
89 bool full = false;
90 edgeCount(i) = (nf > 0 && nf <= kMaxF)
91 ? areaGradEnumerate<Cell, kMaxF>(c, faces, nf, part, pcnt, full)
92 : 0;
93 }
94 });
95
96 // ---- 2. exclusive prefix sum -> per-cell facet base + total facet count ----
97 Kokkos::View<int*, Mem> base(view_alloc(std::string("rp.base"), WithoutInitializing),
98 static_cast<std::size_t>(N));
99 int nFacets = 0;
100 {
101 Kokkos::View<int*, Mem> fc = facetCount, bs = base;
102 Kokkos::parallel_scan(
103 "reevalPublish.scan", N,
104 KOKKOS_LAMBDA(const int i, int& upd, const bool final_pass) {
105 if (final_pass)
106 bs(i) = upd;
107 upd += fc(i);
108 },
109 nFacets);
110 }
111 Kokkos::View<int*, Mem> ebase(view_alloc(std::string("rp.ebase"), WithoutInitializing),
112 withAreaGrad ? static_cast<std::size_t>(N) : 0);
113 int nEdges = 0;
114 if (withAreaGrad) {
115 Kokkos::View<int*, Mem> ec = edgeCount, eb = ebase;
116 Kokkos::parallel_scan(
117 "reevalPublish.scanEdges", N,
118 KOKKOS_LAMBDA(const int i, int& upd, const bool final_pass) {
119 if (final_pass)
120 eb(i) = upd;
121 upd += ec(i);
122 },
123 nEdges);
124 }
125
126 // ---- 3. fill the facet CSR: reeval geometry, then facetGeometry per live face ----
127 const std::size_t nF = static_cast<std::size_t>(nFacets);
128 Kokkos::View<gid_t*, Mem> fNbr(view_alloc(std::string("rp.fNbr"), WithoutInitializing), nF);
129 Kokkos::View<Real*, Mem> fArea(view_alloc(std::string("rp.fArea"), WithoutInitializing), nF * 3);
130 Kokkos::View<Real*, Mem> fDV(view_alloc(std::string("rp.fDV"), WithoutInitializing), nF * 3);
131 Kokkos::View<Real*, Mem> fConn(view_alloc(std::string("rp.fConn"), WithoutInitializing), nF * 3);
132 const std::size_t nE = static_cast<std::size_t>(nEdges);
133 Kokkos::View<int*, Mem> eOff(view_alloc(std::string("rp.eOff"), WithoutInitializing),
134 withAreaGrad ? nF : 0);
135 Kokkos::View<int*, Mem> eCnt(view_alloc(std::string("rp.eCnt"), WithoutInitializing),
136 withAreaGrad ? nF : 0);
137 Kokkos::View<int*, Mem> eFacet(view_alloc(std::string("rp.eFacet"), WithoutInitializing),
138 withAreaGrad ? nE : 0);
139 Kokkos::View<Real*, Mem> eGrad(view_alloc(std::string("rp.eGrad"), WithoutInitializing),
140 withAreaGrad ? nE * 3 : 0);
141 Kokkos::View<Real*, Mem> eLen(view_alloc(std::string("rp.eLen"), WithoutInitializing),
142 withAreaGrad ? nE * 4 : 0);
143 Kokkos::View<Real*, Mem> fM2(view_alloc(std::string("rp.fM2"), WithoutInitializing),
144 withMoments ? nF : 0);
145 const bool wm = withMoments;
146 {
147 Kokkos::View<int*, Mem> bs = base, eb = ebase;
148 WallStore<Real> Wl = wall;
149 Kokkos::View<Real*, Mem> XR = xRef;
150 const Real Lxh = Real(0.5) * Lx, Lyh = Real(0.5) * Ly, Lzh = Real(0.5) * Lz;
151 Kokkos::parallel_for(
152 "reevalPublish.fill", Kokkos::RangePolicy<Exec>(0, N), KOKKOS_LAMBDA(const int i) {
153 Cell c;
154 st.load(i, c, Lx, Ly, Lz);
155 if (Wl.active()) { // restore the wall planes for the seed's displacement since save
156 Real dx = P(3 * i) - XR(3 * i), dy = P(3 * i + 1) - XR(3 * i + 1),
157 dz = P(3 * i + 2) - XR(3 * i + 2);
158 dx = dx > Lxh ? dx - Lx : (dx < -Lxh ? dx + Lx : dx);
159 dy = dy > Lyh ? dy - Ly : (dy < -Lyh ? dy + Ly : dy);
160 dz = dz > Lzh ? dz - Lz : (dz < -Lzh ? dz + Lz : dz);
161 Wl.load(i, c, dx, dy, dz);
162 }
163 c.reevalGeometry(P(3 * i), P(3 * i + 1), P(3 * i + 2), P.data(), Lx);
164 int idx = 0;
165 const int b = bs(i);
166 int faces[kMaxF];
167 for (int k = 0; k < c.np; ++k) {
168 int cnt = 0;
169 for (int t = 0; t < c.nt; ++t)
170 if (c.alive[t] && (c.t0[t] == k || c.t1[t] == k || c.t2[t] == k))
171 ++cnt;
172 if (cnt < 3)
173 continue; // not a polygon face — same criterion as the count pass
174 if (idx < kMaxF)
175 faces[idx] = k;
176 Real area[3] = {0, 0, 0}, dv[3] = {0, 0, 0}, conn[3];
177 conn[0] = Real(2) * c.n[k][0];
178 conn[1] = Real(2) * c.n[k][1];
179 conn[2] = Real(2) * c.n[k][2];
180 c.facetGeometry(k, area, dv, conn); // zeros for a degenerate face (matches buildCell)
181 const std::size_t g = static_cast<std::size_t>(b + idx);
182 fNbr(g) = static_cast<gid_t>(c.pnbr[k]);
183 for (int cc = 0; cc < 3; ++cc) {
184 fArea(3 * g + cc) = area[cc];
185 fDV(3 * g + cc) = dv[cc];
186 fConn(3 * g + cc) = conn[cc];
187 }
188 if (wm)
189 fM2(g) = c.faceMoment2(k);
190 ++idx;
191 }
192 if (wag && idx > 0 && idx <= kMaxF) {
193 unsigned char part[kMaxF * Cell::MAXFV], pcnt[kMaxF];
194 bool full = false;
195 areaGradEnumerate<Cell, kMaxF>(c, faces, idx, part, pcnt, full);
196 areaGradFill<Cell, kMaxF>(c, faces, idx, part, pcnt, b, eb(i), eOff, eCnt, eFacet,
197 eGrad, eLen);
198 }
199 });
200 }
201
202 // ---- 4. assemble the published view (cellVolume reuses the repair's volumes) ----
203 TessellationView<Real> view;
204 view.cellFacetOffset = base;
205 view.cellFacetCount = facetCount;
206 view.cellVolume = vol;
207 view.cellSeedId = Kokkos::View<gid_t*, Mem>(
208 view_alloc(std::string("rp.seedId"), WithoutInitializing), static_cast<std::size_t>(N));
209 {
210 Kokkos::View<gid_t*, Mem> vSeed = view.cellSeedId;
211 Kokkos::parallel_for(
212 "reevalPublish.seedId", Kokkos::RangePolicy<Exec>(0, N),
213 KOKKOS_LAMBDA(const int i) { vSeed(i) = static_cast<gid_t>(i); });
214 }
215 view.facetNeighbor = fNbr;
216 view.facetArea = fArea;
217 view.facetConnect = fDV;
218 view.facetConnVec = fConn;
219 if (withMoments)
220 view.facetMoment2 = fM2;
221 if (withAreaGrad) {
222 view.facetEdgeOffset = eOff;
223 view.facetEdgeCount = eCnt;
224 view.edgeFacet = eFacet;
225 view.edgeAreaGrad = eGrad;
226 view.edgeLength =
227 Kokkos::View<Real*, Mem>(view_alloc(std::string("rp.edgeLength"), WithoutInitializing), nE);
228 {
229 auto el = view.edgeLength;
230 Kokkos::parallel_for(
231 "reevalPublish.edgeLength", Kokkos::RangePolicy<Exec>(0, nE),
232 KOKKOS_LAMBDA(const int e) { el(e) = eLen((size_t)e * 4); });
233 }
234 }
235 return view;
236}
237
238} // namespace peclet::voro
239
240#endif // PECLET_VORO_REEVAL_TESSELLATION_HPP
Device-native Voronoi tessellation, geometry and finite-volume physics.
Definition convex_cell.hpp:41
std::int32_t gid_t
Definition tessellation_view.hpp:41
TessellationView< Real > reevalPublish(const TopologyStore< MAXP, MAXT > &store, const Kokkos::View< Real *, peclet::core::MemSpace > &pos, const Kokkos::View< Real *, peclet::core::MemSpace > &vol, int N, const Real L[3], WallStore< Real > wall={}, Kokkos::View< Real *, peclet::core::MemSpace > xRef={}, bool withAreaGrad=false, bool withMoments=false)
Definition reeval_tessellation.hpp:49
Definition tessellation_view.hpp:111
Definition topology_store.hpp:39
Definition sdf.hpp:352
Published, read-only device data layer for the tessellation (migration §2.1, §3).