26#ifndef PECLET_VORO_TESSELLATOR_HPP
27#define PECLET_VORO_TESSELLATOR_HPP
34#include <Kokkos_Core.hpp>
39#include "morton/morton.hpp"
40#include "peclet/core/common/view.hpp"
65 Kokkos::View<int*, peclet::core::MemSpace>
status;
77template <
class Real,
bool Weighted,
class Sdf,
bool TrackAdj = false>
80 static constexpr int kMaxP = 64;
81 static constexpr int kMaxT = 112;
84 using PlanePolicy = std::conditional_t<Weighted, Power, Voronoi>;
97 Kokkos::View<int*, MemSpace>
wlOff;
98 Kokkos::View<Real*, MemSpace>
wlRmin;
104 Kokkos::View<int*, MemSpace>
oNbr;
122 Kokkos::View<unsigned*, MemSpace>
oTri;
123 Kokkos::View<unsigned char*, MemSpace>
131 KOKKOS_INLINE_FUNCTION
void relVec(
int q, Real pix, Real piy, Real piz, Real pv[3])
const {
134 const Real Lxh = Real(0.5) *
Lx, Lyh = Real(0.5) *
Ly, Lzh = Real(0.5) *
Lz;
135 pv[0] = rx > Lxh ? rx -
Lx : (rx < -Lxh ? rx +
Lx : rx);
136 pv[1] = ry > Lyh ? ry -
Ly : (ry < -Lyh ? ry +
Ly : ry);
137 pv[2] = rz > Lzh ? rz -
Lz : (rz < -Lzh ? rz +
Lz : rz);
141 KOKKOS_INLINE_FUNCTION
int gridCell(
int rgx,
int rgy,
int rgz)
const {
142 int gx = rgx < 0 ? rgx +
dimx : (rgx >=
dimx ? rgx -
dimx : rgx);
143 int gy = rgy < 0 ? rgy +
dimy : (rgy >=
dimy ? rgy -
dimy : rgy);
144 int gz = rgz < 0 ? rgz +
dimz : (rgz >=
dimz ? rgz -
dimz : rgz);
149 KOKKOS_INLINE_FUNCTION
void homeCell(Real pix, Real piy, Real piz,
int& cx,
int& cy,
157 KOKKOS_INLINE_FUNCTION
int subBase(Real pix, Real piy, Real piz)
const {
158 const Real fxi = pix *
icx, fyi = piy *
icy, fzi = piz *
icz;
159 int sx = (int)((fxi - Kokkos::floor(fxi)) * Real(
wlS));
160 int sy = (int)((fyi - Kokkos::floor(fyi)) * Real(
wlS));
161 int sz = (int)((fzi - Kokkos::floor(fzi)) * Real(
wlS));
162 sx = sx < 0 ? 0 : (sx >=
wlS ?
wlS - 1 : sx);
163 sy = sy < 0 ? 0 : (sy >=
wlS ?
wlS - 1 : sy);
164 sz = sz < 0 ? 0 : (sz >=
wlS ?
wlS - 1 : sz);
169 KOKKOS_INLINE_FUNCTION
int worklistCell(
int base,
int g,
int cx,
int cy,
int cz)
const {
170 const int packed =
wlOff(base + g);
171 const int rgx = cx + ((packed & 0xFF) -
kWlOffBias);
172 const int rgy = cy + (((packed >> 8) & 0xFF) -
kWlOffBias);
173 const int rgz = cz + (((packed >> 16) & 0xFF) -
kWlOffBias);
180 KOKKOS_INLINE_FUNCTION
void finishCell(
Cell& c,
int i, Real pix, Real piy, Real piz, Real covSq,
181 Real wSelf = Real(0))
const {
192 const bool incomplete =
195 if constexpr (!std::is_same_v<Sdf, NoSdf>) {
196 const Real seedW[3] = {pix, piy, piz};
197 clipCellAgainstSdf<Real, kMaxP, kMaxT>(c, seedW,
sdf);
202 const bool empty = c.
empty();
214 for (
int k = 0; k < c.
np; ++k)
216 for (
int t = 0; t < c.
nt; ++t)
217 oTri[(
size_t)i *
kMaxT + t] = (unsigned)c.
t0[t] | ((
unsigned)c.
t1[t] << 8) |
218 ((
unsigned)c.
t2[t] << 16) | ((c.
alive[t] ? 1u : 0u) << 24);
219 if constexpr (TrackAdj)
229 for (
int k = 0; k < c.
np; ++k) {
231 for (
int t = 0; t < c.
nt; ++t)
232 if (c.
alive[t] && (c.
t0[t] == k || c.
t1[t] == k || c.
t2[t] == k))
244 const int base = Kokkos::atomic_fetch_add(&
facetCursor(0), nf);
245 if ((
size_t)base + (
size_t)nf >
facetCap) {
253 for (
int idx = 0; idx < nf; ++idx) {
254 const int k = faces[idx];
255 Real area[3] = {0, 0, 0}, dv[3] = {0, 0, 0}, conn[3];
256 conn[0] = Real(2) * c.
n[k][0];
257 conn[1] = Real(2) * c.
n[k][1];
258 conn[2] = Real(2) * c.
n[k][2];
261 oNbr((
size_t)base + idx) = c.
pnbr[k];
262 const size_t o = ((size_t)base + idx) * 3;
263 for (
int cc = 0; cc < 3; ++cc) {
264 oArea(o + cc) = area[cc];
265 oDV(o + cc) = dv[cc];
266 oConn(o + cc) = conn[cc];
283 homeCell(pix, piy, piz, cx, cy, cz);
284 const int base =
subBase(pix, piy, piz);
287 Real wSelf = Real(0);
288 if constexpr (Weighted) wSelf =
wSorted(pi);
298 for (
int g = 0; g <
nOff && !c.
overflow && !buried; ++g) {
299 if constexpr (Weighted) {
300 if (
wlRmin(base + g) > reachSq)
break;
302 if (
wlRmin(base + g) > Real(2) * secR2)
break;
315 relVec(q, pix, piy, piz, pv);
317 if constexpr (Weighted) wNbr =
wSorted(q);
318 const Real off = PlanePolicy::template offsetFromRel<Real>(pv, wSelf, wNbr);
319 if constexpr (Weighted) {
323 if (off <= Real(0)) {
328 const Real rho = pv[0] * pv[0] + pv[1] * pv[1] + pv[2] * pv[2];
341 if constexpr (Weighted) {
355 finishCell(c, i, pix, piy, piz, covSq, wSelf);
380template <
class Real,
bool Weighted,
class Sdf = NoSdf>
382 const Kokkos::View<Real*, peclet::core::MemSpace>& posFlat,
383 const Kokkos::View<Real*, peclet::core::MemSpace>& weight,
int N,
const Real L[3],
int sw = 4,
384 int densityCount = -1, Kokkos::View<long*, peclet::core::MemSpace> gid = {}, Sdf sdf = {},
385 bool withForceGeom =
true,
int nBuild = -1,
386 Kokkos::View<int*, peclet::core::MemSpace> outNp = {},
387 Kokkos::View<int*, peclet::core::MemSpace> outNt = {},
388 Kokkos::View<int*, peclet::core::MemSpace> outPnbr = {},
389 Kokkos::View<unsigned*, peclet::core::MemSpace> outTri = {},
390 Kokkos::View<int*, peclet::core::MemSpace> outCand = {},
391 Kokkos::View<int*, peclet::core::MemSpace> outCandCnt = {},
int candCap = 0,
392 WorklistCache<Real>* wlc =
nullptr) {
393 using peclet::core::MemSpace;
394 using Exec = peclet::core::ExecSpace;
398 const bool emitTopo = outNp.extent(0) ==
static_cast<size_t>(N);
399 const bool emitCand = outCand.extent(0) > 0 && candCap > 0;
404 const bool haveGid = gid.extent(0) ==
static_cast<size_t>(N);
406 const int nBuildEff = (nBuild >= 0 && nBuild < N) ? nBuild : N;
408 const bool prof = std::getenv(
"PECLET_VORO_PROFILE") !=
nullptr;
409 Kokkos::Timer ptimer;
410 double tGrid = 0, tBuild = 0, tCsr = 0;
415 auto grid = buildTessGrid<Real, Weighted>(posFlat, weight, N, L, sw, densityCount, gid, wlc);
416 const Real Lx = grid.Lx, Ly = grid.Ly, Lz = grid.Lz;
417 const Real icx = grid.icx, icy = grid.icy, icz = grid.icz, minCsz = grid.minCsz;
418 const int dimx = grid.dimx, dimy = grid.dimy, dimz = grid.dimz;
419 const int nOff = grid.nOff, wlS = grid.wlS;
420 const bool useMorton = grid.useMorton;
424 tGrid = ptimer.seconds();
430 Kokkos::View<Real*, MemSpace> cellVol(
"cellVol", N);
431 Kokkos::View<int*, MemSpace> facetCount(
"facetCount", N);
432 Kokkos::View<int*, MemSpace> status(
"status", N);
433 Kokkos::View<int*, MemSpace> cellFacetBase(
"cellFacetBase", N);
441 constexpr int MAXF_TMP = 50;
449 constexpr size_t kMeanFacets = 18;
450 const size_t facetCap = (size_t)N * kMeanFacets;
451 using Kokkos::view_alloc;
452 using Kokkos::WithoutInitializing;
453 Kokkos::View<int*, MemSpace> oNbr(view_alloc(std::string(
"oNbr"), WithoutInitializing), facetCap);
454 Kokkos::View<Real*, MemSpace> oArea(view_alloc(std::string(
"oArea"), WithoutInitializing),
456 Kokkos::View<Real*, MemSpace> oDV(view_alloc(std::string(
"oDV"), WithoutInitializing),
458 Kokkos::View<Real*, MemSpace> oConn(view_alloc(std::string(
"oConn"), WithoutInitializing),
460 Kokkos::View<int*, MemSpace> facetCursor(
"facetCursor", 1);
462 std::fprintf(stderr,
"[worklist] sw=%d nOff=%d\n", sw, nOff);
467 Kokkos::View<unsigned char*, MemSpace>
471 Real wMaxAll = Real(0);
472 if constexpr (Weighted) {
473 if (weight.extent(0) ==
static_cast<size_t>(N)) {
474 Kokkos::parallel_reduce(
475 "wmax", Kokkos::RangePolicy<Exec>(0, N),
476 KOKKOS_LAMBDA(
int idx, Real& m) { m = weight(idx) > m ? weight(idx) : m; },
477 Kokkos::Max<Real>(wMaxAll));
481 CellBuilder<Real, Weighted, Sdf> op{grid.binned,
526 const int nBuildL = nBuildEff;
527 auto binnedV0 = grid.binned;
528 Kokkos::parallel_for(
529 "tess.build", Kokkos::RangePolicy<Exec>(0, N), KOKKOS_LAMBDA(
const int pi) {
530 if (binnedV0(pi) >= nBuildL)
537 tBuild = ptimer.seconds();
547 Kokkos::deep_copy(nFacetsRaw, Kokkos::subview(facetCursor, 0));
550 const int nFacets = (size_t)nFacetsRaw > facetCap ? (
int)facetCap : nFacetsRaw;
552 TessellationView<Real> view;
553 view.cellFacetOffset = cellFacetBase;
554 view.cellFacetCount = facetCount;
555 view.cellVolume = cellVol;
557 Kokkos::View<gid_t*, MemSpace>(view_alloc(std::string(
"cellSeedId"), WithoutInitializing), N);
559 auto vSeed = view.cellSeedId;
560 Kokkos::parallel_for(
561 "tess.seedId", Kokkos::RangePolicy<Exec>(0, N),
562 KOKKOS_LAMBDA(
const int i) { vSeed(i) = (
gid_t)i; });
571 view.facetNeighbor = Kokkos::View<gid_t*, MemSpace>(
572 view_alloc(std::string(
"facetNeighbor"), WithoutInitializing), nFacets);
574 auto v = view.facetNeighbor;
576 Kokkos::parallel_for(
577 "tess.packNbr", Kokkos::RangePolicy<Exec>(0, nFacets),
578 KOKKOS_LAMBDA(
const int g) { v(g) = (
gid_t)src(g); });
581 oNbr = Kokkos::View<int*, MemSpace>();
583 view.facetArea = Kokkos::View<Real*, MemSpace>(
584 view_alloc(std::string(
"facetArea"), WithoutInitializing), (
size_t)nFacets * 3);
586 auto v = view.facetArea;
588 Kokkos::parallel_for(
589 "tess.packArea", Kokkos::RangePolicy<Exec>(0, nFacets), KOKKOS_LAMBDA(
const int g) {
590 for (
int cc = 0; cc < 3; ++cc)
591 v(3 * g + cc) = src(3 * (
size_t)g + cc);
595 oArea = Kokkos::View<Real*, MemSpace>();
597 view.facetConnect = Kokkos::View<Real*, MemSpace>(
598 view_alloc(std::string(
"facetConnect"), WithoutInitializing), (
size_t)nFacets * 3);
600 auto v = view.facetConnect;
602 Kokkos::parallel_for(
603 "tess.packDV", Kokkos::RangePolicy<Exec>(0, nFacets), KOKKOS_LAMBDA(
const int g) {
604 for (
int cc = 0; cc < 3; ++cc)
605 v(3 * g + cc) = src(3 * (
size_t)g + cc);
609 oDV = Kokkos::View<Real*, MemSpace>();
611 view.facetConnVec = Kokkos::View<Real*, MemSpace>(
612 view_alloc(std::string(
"facetConnVec"), WithoutInitializing), (
size_t)nFacets * 3);
614 auto v = view.facetConnVec;
616 Kokkos::parallel_for(
617 "tess.packConn", Kokkos::RangePolicy<Exec>(0, nFacets), KOKKOS_LAMBDA(
const int g) {
618 for (
int cc = 0; cc < 3; ++cc)
619 v(3 * g + cc) = src(3 * (
size_t)g + cc);
623 oConn = Kokkos::View<Real*, MemSpace>();
626 tCsr = ptimer.seconds();
627 std::fprintf(stderr,
"[tess N=%d] grid=%.4fs build=%.4fs csr=%.4fs (build %.0f%%)\n", N, tGrid,
628 tBuild, tCsr, 100.0 * tBuild / (tGrid + tBuild + tCsr));
632 auto fc = facetCount;
633 Kokkos::parallel_reduce(
634 "tess.maxFacets", Kokkos::RangePolicy<Exec>(0, N),
635 KOKKOS_LAMBDA(
const int c,
int& m) { m = fc(c) > m ? fc(c) : m; }, Kokkos::Max<int>(maxF));
636 std::fprintf(stderr,
"[tess N=%d] maxFacets/cell=%d (=> maxVerts ~ %d; CAP=%d)\n", N, maxF,
640 TessellatorResult<Real> res;
Definition convex_cell.hpp:40
std::int32_t gid_t
Definition tessellation_view.hpp:41
StatusBit
Per-cell status bits written by the build pass.
Definition tessellator.hpp:49
@ kOverflow
Definition tessellator.hpp:51
@ kNegOffset
Definition tessellator.hpp:59
@ kOk
Definition tessellator.hpp:50
@ kIncomplete
Definition tessellator.hpp:53
@ kEmpty
Definition tessellator.hpp:52
constexpr int kWlOffBias
Definition tess_grid.hpp:37
TessellatorResult< Real > buildTessellation(const Kokkos::View< Real *, peclet::core::MemSpace > &posFlat, const Kokkos::View< Real *, peclet::core::MemSpace > &weight, int N, const Real L[3], int sw=4, int densityCount=-1, Kokkos::View< long *, peclet::core::MemSpace > gid={}, Sdf sdf={}, bool withForceGeom=true, int nBuild=-1, Kokkos::View< int *, peclet::core::MemSpace > outNp={}, Kokkos::View< int *, peclet::core::MemSpace > outNt={}, Kokkos::View< int *, peclet::core::MemSpace > outPnbr={}, Kokkos::View< unsigned *, peclet::core::MemSpace > outTri={}, Kokkos::View< int *, peclet::core::MemSpace > outCand={}, Kokkos::View< int *, peclet::core::MemSpace > outCandCnt={}, int candCap=0, WorklistCache< Real > *wlc=nullptr)
Definition tessellator.hpp:381
KOKKOS_INLINE_FUNCTION int morton3(int x, int y, int z)
Definition tess_grid.hpp:45
Definition tessellator.hpp:78
Kokkos::View< int *, MemSpace > facetCursor
Definition tessellator.hpp:106
bool useMorton
Definition tessellator.hpp:111
Kokkos::View< int *, MemSpace > status
Definition tessellator.hpp:100
Kokkos::View< Real *, MemSpace > cellVol
Definition tessellator.hpp:101
Kokkos::View< Real *, MemSpace > wSorted
Definition tessellator.hpp:89
bool emitTopo
Definition tessellator.hpp:127
static constexpr int MAXF_TMP
Definition tessellator.hpp:82
Kokkos::View< unsigned char *, MemSpace > oPoke4
Definition tessellator.hpp:124
KOKKOS_INLINE_FUNCTION int subBase(Real pix, Real piy, Real piz) const
Flat base offset into the worklist tables for the wlS^3 sub-region the seed lands in.
Definition tessellator.hpp:157
int candCap
Definition tessellator.hpp:128
static constexpr int kMaxT
Definition tessellator.hpp:81
Kokkos::View< int *, MemSpace > oCandCnt
Definition tessellator.hpp:126
KOKKOS_INLINE_FUNCTION void buildCell(int pi) const
Definition tessellator.hpp:273
static constexpr int kMaxP
Definition tessellator.hpp:80
Real icx
Definition tessellator.hpp:108
int sw
Definition tessellator.hpp:110
int dimy
Definition tessellator.hpp:110
Kokkos::View< int *, MemSpace > oNbr
Definition tessellator.hpp:104
bool emitCand
Definition tessellator.hpp:127
bool haveGid
Definition tessellator.hpp:111
KOKKOS_INLINE_FUNCTION int gridCell(int rgx, int rgy, int rgz) const
Linear/Morton index of the grid cell at raw (periodic-unwrapped) offset.
Definition tessellator.hpp:141
Kokkos::View< gid_t *, MemSpace > gidSorted
Definition tessellator.hpp:90
int dimx
Definition tessellator.hpp:110
Real Ly
Definition tessellator.hpp:108
Real Lx
Definition tessellator.hpp:108
Real wMaxAll
Definition tessellator.hpp:109
int wlS
Definition tessellator.hpp:110
Kokkos::View< unsigned *, MemSpace > oTri
Definition tessellator.hpp:122
Real Lz
Definition tessellator.hpp:108
std::conditional_t< Weighted, Power, Voronoi > PlanePolicy
Definition tessellator.hpp:84
int nOff
Definition tessellator.hpp:110
Kokkos::View< int *, MemSpace > oNt
Definition tessellator.hpp:121
Sdf sdf
Definition tessellator.hpp:113
Kokkos::View< int *, MemSpace > wlOff
Definition tessellator.hpp:97
Kokkos::View< int *, MemSpace > binned
Definition tessellator.hpp:87
peclet::core::MemSpace MemSpace
Definition tessellator.hpp:79
Kokkos::View< Real *, MemSpace > oArea
Definition tessellator.hpp:105
bool withForceGeom
Definition tessellator.hpp:111
int dimz
Definition tessellator.hpp:110
KOKKOS_INLINE_FUNCTION void relVec(int q, Real pix, Real piy, Real piz, Real pv[3]) const
Minimal-image relative vector from the seed at (pix,piy,piz) to sorted seed q.
Definition tessellator.hpp:131
Kokkos::View< int *, MemSpace > cellStart
Definition tessellator.hpp:91
Kokkos::View< int *, MemSpace > cellFacetBase
Definition tessellator.hpp:103
Kokkos::View< int *, MemSpace > facetCount
Definition tessellator.hpp:102
size_t facetCap
Definition tessellator.hpp:112
Kokkos::View< int *, MemSpace > oTopoPnbr
Definition tessellator.hpp:121
Real icy
Definition tessellator.hpp:108
Kokkos::View< Real *, MemSpace > oConn
Definition tessellator.hpp:105
KOKKOS_INLINE_FUNCTION void finishCell(Cell &c, int i, Real pix, Real piy, Real piz, Real covSq, Real wSelf=Real(0)) const
Definition tessellator.hpp:180
Kokkos::View< Real *, MemSpace > oDV
Definition tessellator.hpp:105
Kokkos::View< int *, MemSpace > oNp
Definition tessellator.hpp:121
Kokkos::View< Real *, MemSpace > wlRmin
Definition tessellator.hpp:98
Real minCsz
Definition tessellator.hpp:108
Real icz
Definition tessellator.hpp:108
Kokkos::View< int *, MemSpace > oCand
Definition tessellator.hpp:126
Kokkos::View< Real *, MemSpace > posSorted
Definition tessellator.hpp:88
KOKKOS_INLINE_FUNCTION int worklistCell(int base, int g, int cx, int cy, int cz) const
Decode worklist entry g (relative to base) into a grid-cell index.
Definition tessellator.hpp:169
KOKKOS_INLINE_FUNCTION void homeCell(Real pix, Real piy, Real piz, int &cx, int &cy, int &cz) const
Home grid cell index (cx,cy,cz) of seed (pix,piy,piz).
Definition tessellator.hpp:149
Definition convex_cell.hpp:139
KOKKOS_INLINE_FUNCTION Real volumePerVertex() const
Definition convex_cell.hpp:1036
unsigned char t1[MAXT]
Definition convex_cell.hpp:150
KOKKOS_INLINE_FUNCTION void initBox(Real L0, Real L1, Real L2)
Definition convex_cell.hpp:173
bool overflow
set if MAXP/MAXT exceeded -> cell invalid, caller falls back
Definition convex_cell.hpp:154
int nt
triangle high-water mark
Definition convex_cell.hpp:153
Real n[MAXP][3]
Definition convex_cell.hpp:144
KOKKOS_INLINE_FUNCTION bool empty() const
Definition convex_cell.hpp:775
int pnbr[MAXP]
neighbour seed id per plane (<0 => bounding box)
Definition convex_cell.hpp:148
KOKKOS_INLINE_FUNCTION Real maxVertexRsq() const
Largest squared dual-vertex radius over live triangles (drives the security radius).
Definition convex_cell.hpp:490
KOKKOS_INLINE_FUNCTION bool clip(const Real pdir[3], Real d, int nbr)
Definition convex_cell.hpp:584
unsigned char t2[MAXT]
triangle = triple of plane indices
Definition convex_cell.hpp:150
int np
number of planes
Definition convex_cell.hpp:149
unsigned char t0[MAXT]
Definition convex_cell.hpp:150
KOKKOS_INLINE_FUNCTION void computePoke4(unsigned char *out) const
Definition convex_cell.hpp:391
bool alive[MAXT]
triangle live flag
Definition convex_cell.hpp:152
KOKKOS_INLINE_FUNCTION bool facetGeometry(int k, Real areaVec[3], Real dv[3], Real conn[3]) const
Definition convex_cell.hpp:1633
Definition tessellation_view.hpp:111
Definition tessellator.hpp:63
Kokkos::View< int *, peclet::core::MemSpace > status
Definition tessellator.hpp:65
TessellationView< Real > view
Definition tessellator.hpp:64
Published, read-only device data layer for the tessellation (migration §2.1, §3).