31#ifndef PECLET_VORO_REPAIR_HPP
32#define PECLET_VORO_REPAIR_HPP
35#include <Kokkos_Core.hpp>
38#include "peclet/core/common/view.hpp"
63template <
class Real,
int MAXP = 64,
int MAXT = 112,
bool Weighted = false>
65 using Mem = peclet::core::MemSpace;
66 using Exec = peclet::core::ExecSpace;
67 using PlanePolicy = std::conditional_t<Weighted, Power, Voronoi>;
82 Real
L[3] = {1, 1, 1};
135 Kokkos::View<Real*, Mem>
vol;
153 void alloc(
int n,
const Real Lbox[3], Real tol_, Real skin_,
int sw_ = 4,
int densityCount_ = -1,
156 nProc = (nProc_ < 0) ? n : nProc_;
161 for (
int k = 0; k < 3; ++k)
166 using Kokkos::view_alloc;
167 using Kokkos::WithoutInitializing;
168 vol = Kokkos::View<Real*, Mem>(
"mt.vol", n);
169 xRef = Kokkos::View<Real*, Mem>(view_alloc(std::string(
"mt.xRef"), WithoutInitializing),
171 mask = Kokkos::View<int*, Mem>(
"mt.mask", n);
172 mask2 = Kokkos::View<int*, Mem>(
"mt.mask2", n);
173 mover = Kokkos::View<int*, Mem>(
"mt.mover", n);
174 rebuilt = Kokkos::View<int*, Mem>(
"mt.rebuilt", n);
175 wl1 = Kokkos::View<int*, Mem>(view_alloc(std::string(
"mt.wl1"), WithoutInitializing), n);
176 wl2 = Kokkos::View<int*, Mem>(view_alloc(std::string(
"mt.wl2"), WithoutInitializing), n);
177 wlM = Kokkos::View<int*, Mem>(view_alloc(std::string(
"mt.wlM"), WithoutInitializing), n);
178 extraNbr = Kokkos::View<int*, Mem>(view_alloc(std::string(
"mt.extraNbr"), WithoutInitializing),
180 extraCnt = Kokkos::View<int*, Mem>(
"mt.extraCnt", n);
181 counter = Kokkos::View<int, Mem>(
"mt.counter");
186 constexpr bool host = Kokkos::SpaceAccessibility<Kokkos::HostSpace, Mem>::accessible;
198 void rebuild(
const Kokkos::View<Real*, Mem>& pos,
bool eagerAdj =
true) {
199 Kokkos::View<long*, Mem> gd;
205 Kokkos::deep_copy(
vol, res.view.cellVolume);
206 Kokkos::deep_copy(
xRef, pos);
213 int compact(
const Kokkos::View<int*, Mem>& m,
const Kokkos::View<int*, Mem>& wl) {
218 Kokkos::parallel_for(
219 "mt.compact", Kokkos::RangePolicy<Exec>(0,
nProc), KOKKOS_LAMBDA(
int i) {
221 W(Kokkos::atomic_fetch_add(&c(), 1)) = i;
236 template <
bool Local>
237 void certify(
const Kokkos::View<Real*, Mem>& pos,
const Kokkos::View<int*, Mem>& outMask,
238 const Kokkos::View<int*, Mem>& outMover,
bool useSkin) {
239 Kokkos::deep_copy(outMask, 0);
241 Kokkos::deep_copy(outMover, 0);
248 const bool doExtra =
surgical && useSkin;
261 const Real Lx =
L[0], Ly =
L[1], Lz =
L[2];
262 const Real Lxh = Real(0.5) * Lx, Lyh = Real(0.5) * Ly, Lzh = Real(0.5) * Lz;
263 const Real tolL =
tol, half2 = Real(0.25) *
skin *
skin;
264 const bool skinOn = useSkin;
265 const int nP_ =
nProc;
267 Kokkos::parallel_for(
268 "mt.certify", Kokkos::RangePolicy<Exec>(0,
nProc), KOKKOS_LAMBDA(
int i) {
270 st.
load(i, c, Lx, Ly, Lz);
271 const Real* wPtr = Wt.data();
272 Real wSelfI = Real(0);
273 if constexpr (Weighted) wSelfI = Wt(i);
274 c.template reevalGeometry<PlanePolicy>(P(3 * i), P(3 * i + 1), P(3 * i + 2), P.data(), Lx,
283 const unsigned char* pk4 = &Pk4((
size_t)i * MAXT * 4);
284 const Real tl = tolL;
293 Real dx = P(3 * i) - XR(3 * i), dy = P(3 * i + 1) - XR(3 * i + 1),
294 dz = P(3 * i + 2) - XR(3 * i + 2);
295 dx = dx > Lxh ? dx - Lx : (dx < -Lxh ? dx + Lx : dx);
296 dy = dy > Lyh ? dy - Ly : (dy < -Lyh ? dy + Ly : dy);
297 dz = dz > Lzh ? dz - Lz : (dz < -Lzh ? dz + Lz : dz);
298 mover = (dx * dx + dy * dy + dz * dz) > half2;
306 for (
int q = 0; q < nP; ++q)
307 if (partners[q] < nP_)
308 Kokkos::atomic_exchange(&M(partners[q]), 1);
311 for (
int q = 0; q < nP; ++q) {
312 const int cell = partners[q];
313 if (cell < 0 || cell >= nP_)
315 for (
int r = 0; r < nP; ++r) {
318 const int nb = partners[r];
321 const int slot = Kokkos::atomic_fetch_add(&EC(cell), 1);
323 EN((
size_t)cell * kCap + slot) = nb;
338 template <
bool Local>
339 void certifyList(
const Kokkos::View<Real*, Mem>& pos,
const Kokkos::View<int*, Mem>& list,
int n,
340 const Kokkos::View<int*, Mem>& outMask) {
341 Kokkos::deep_copy(outMask, 0);
349 const Real Lx =
L[0], Ly =
L[1], Lz =
L[2];
350 const Real tolL =
tol;
351 const int nP_ =
nProc;
353 Kokkos::parallel_for(
354 "mt.certifyList", Kokkos::RangePolicy<Exec>(0, n), KOKKOS_LAMBDA(
int s) {
355 const int i = list(s);
357 st.
load(i, c, Lx, Ly, Lz);
358 const Real* wPtr = Wt.data();
359 Real wSelfI = Real(0);
360 if constexpr (Weighted) wSelfI = Wt(i);
361 c.template reevalGeometry<PlanePolicy>(P(3 * i), P(3 * i + 1), P(3 * i + 2), P.data(), Lx,
367 const unsigned char* pk4 =
368 &Pk4((
size_t)i * MAXT * 4);
369 const Real tl = tolL;
378 for (
int q = 0; q < nP; ++q)
379 if (partners[q] < nP_)
380 Kokkos::atomic_exchange(&M(partners[q]), 1);
395 const Real Lx =
L[0], Ly =
L[1], Lz =
L[2];
397 Kokkos::parallel_for(
398 "mt.rebuildAdjAll", Kokkos::RangePolicy<Exec>(0,
nProc), KOKKOS_LAMBDA(
int i) {
400 st.
load(i, c, Lx, Ly,
402 const Real* wPtr = Wt.data();
403 Real wSelfI = Real(0);
404 if constexpr (Weighted) wSelfI = Wt(i);
405 c.template reevalGeometry<PlanePolicy>(P(3 * i), P(3 * i + 1), P(3 * i + 2), P.data(), Lx,
430 const Kokkos::View<Real*, Mem>& pos) {
436 subsetGather<Real, Weighted, true>(grid, wl, n,
store.
np,
store.
nt,
store.
pnbr,
store.
tri,
vol,
442 Kokkos::parallel_for(
443 "mt.markRebuilt", Kokkos::RangePolicy<Exec>(0, n), KOKKOS_LAMBDA(
int s) {
446 XR(3 * i) = P(3 * i);
447 XR(3 * i + 1) = P(3 * i + 1);
448 XR(3 * i + 2) = P(3 * i + 2);
455 const Kokkos::View<int*, Mem>& outMask) {
456 Kokkos::deep_copy(outMask, 0);
462 const int nP_ =
nProc;
463 Kokkos::parallel_for(
464 "mt.collectNbrs", Kokkos::RangePolicy<Exec>(0, n), KOKKOS_LAMBDA(
int s) {
466 const int np = st.
np(i), nt = st.
nt(i);
467 for (
int k = 6; k < np; ++k) {
468 const int j = st.
pnbr((
size_t)i * MAXP + k);
469 if (j < 0 || j >= nP_ || rb(j))
472 for (
int t = 0; t < nt; ++t) {
473 const unsigned w = st.
tri((
size_t)i * MAXT + t);
474 if (!((w >> 24) & 1u))
476 const int a = (int)(w & 0xffu), b = (int)((w >> 8) & 0xffu),
477 cc = (
int)((w >> 16) & 0xffu);
478 if (a == k || b == k || cc == k)
482 Kokkos::atomic_exchange(&M(j), 1);
496 const Kokkos::View<Real*, Mem>& pos) {
509 const Real Lx =
L[0], Ly =
L[1], Lz =
L[2];
510 const Real Lxh = Real(0.5) * Lx, Lyh = Real(0.5) * Ly, Lzh = Real(0.5) * Lz;
511 Kokkos::parallel_for(
512 "mt.surgical", Kokkos::RangePolicy<Exec>(0, n), KOKKOS_LAMBDA(
int s) {
516 const Real sx = P(3 * i), sy = P(3 * i + 1), sz = P(3 * i + 2);
517 const int npi = st.
np(i);
518 for (
int k = 6; k < npi && !c.
overflow; ++k) {
519 const int j = st.
pnbr((
size_t)i * MAXP + k);
522 Real rx = P(3 * j) - sx, ry = P(3 * j + 1) - sy, rz = P(3 * j + 2) - sz;
523 rx = rx > Lxh ? rx - Lx : (rx < -Lxh ? rx + Lx : rx);
524 ry = ry > Lyh ? ry - Ly : (ry < -Lyh ? ry + Ly : ry);
525 rz = rz > Lzh ? rz - Lz : (rz < -Lzh ? rz + Lz : rz);
526 const Real nrm[3] = {rx, ry, rz};
527 c.
clip(nrm, Real(0.5) * (rx * rx + ry * ry + rz * rz), j);
529 const int ne = EC(i) < kCap ? EC(i) : kCap;
530 for (
int e = 0; e < ne && !c.
overflow; ++e) {
531 const int j = EN((
size_t)i * kCap + e);
534 Real rx = P(3 * j) - sx, ry = P(3 * j + 1) - sy, rz = P(3 * j + 2) - sz;
535 rx = rx > Lxh ? rx - Lx : (rx < -Lxh ? rx + Lx : rx);
536 ry = ry > Lyh ? ry - Ly : (ry < -Lyh ? ry + Ly : ry);
537 rz = rz > Lzh ? rz - Lz : (rz < -Lzh ? rz + Lz : rz);
538 const Real nrm[3] = {rx, ry, rz};
539 c.
clip(nrm, Real(0.5) * (rx * rx + ry * ry + rz * rz), j);
545 &Pk4((
size_t)i * MAXT * 4));
561 const int dimx = grid.
dimx, dimy = grid.
dimy, dimz = grid.
dimz;
562 const int ncell = dimx * dimy * dimz;
563 if ((
int)
cellFlag.extent(0) < ncell)
565 Kokkos::view_alloc(std::string(
"mt.cellFlag"), Kokkos::WithoutInitializing), ncell);
567 const Real icx = grid.
icx, icy = grid.
icy, icz = grid.
icz;
571 Kokkos::parallel_for(
572 "mt.dilate.count", Kokkos::RangePolicy<Exec>(0,
nProc), KOKKOS_LAMBDA(
int i) {
575 const int gx = ((int)Kokkos::floor(P(3 * i) * icx) % dimx + dimx) % dimx;
576 const int gy = ((int)Kokkos::floor(P(3 * i + 1) * icy) % dimy + dimy) % dimy;
577 const int gz = ((int)Kokkos::floor(P(3 * i + 2) * icz) % dimz + dimz) % dimz;
578 Kokkos::atomic_inc(&CF(gx + gy * dimx + gz * dimx * dimy));
582 Kokkos::parallel_reduce(
583 "mt.dilate.mark", Kokkos::RangePolicy<Exec>(0,
nProc),
584 KOKKOS_LAMBDA(
int i,
long& a) {
587 const int gx = ((int)Kokkos::floor(P(3 * i) * icx) % dimx + dimx) % dimx;
588 const int gy = ((int)Kokkos::floor(P(3 * i + 1) * icy) % dimy + dimy) % dimy;
589 const int gz = ((int)Kokkos::floor(P(3 * i + 2) * icz) % dimz + dimz) % dimz;
591 for (
int dz = -1; dz <= 1; ++dz)
592 for (
int dy = -1; dy <= 1; ++dy)
593 for (
int dx = -1; dx <= 1; ++dx) {
594 const int nx = (gx + dx + dimx) % dimx, ny = (gy + dy + dimy) % dimy,
595 nz = (gz + dz + dimz) % dimz;
596 sum += CF(nx + ny * dimx + nz * dimx * dimy);
610 void certifyDispatch(
const Kokkos::View<Real*, Mem>& pos,
const Kokkos::View<int*, Mem>& outMask,
611 const Kokkos::View<int*, Mem>& outMover,
bool useSkin) {
613 certify<true>(pos, outMask, outMover, useSkin);
615 certify<false>(pos, outMask, outMover, useSkin);
618 int n,
const Kokkos::View<int*, Mem>& outMask) {
620 certifyList<true>(pos, list, n, outMask);
622 certifyList<false>(pos, list, n, outMask);
629 Kokkos::View<long*, Mem>());
680 Kokkos::parallel_for(
681 "mt.surgMask", Kokkos::RangePolicy<Exec>(0,
nProc),
682 KOKKOS_LAMBDA(
int i) { M2(i) = (Msk(i) && !Mv(i)) ? 1 : 0; });
706 for (
int vp = 0; vp <
verifyCap + 1; ++vp) {
Definition convex_cell.hpp:40
Definition convex_cell.hpp:139
KOKKOS_INLINE_FUNCTION Real volumePerVertex() const
Definition convex_cell.hpp:1036
KOKKOS_INLINE_FUNCTION bool isLocallyConvexPartners(const unsigned char *poke4, Real tol, int *outPartners, int maxPartners, int &nPartners) const
Definition convex_cell.hpp:453
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
KOKKOS_INLINE_FUNCTION void rebuildAdjacency()
Definition convex_cell.hpp:523
KOKKOS_INLINE_FUNCTION bool isSelfConsistentPartners(Real tol, int *outPartners, int maxPartners, int &nPartners) const
Definition convex_cell.hpp:342
KOKKOS_INLINE_FUNCTION bool clip(const Real pdir[3], Real d, int nbr)
Definition convex_cell.hpp:584
KOKKOS_INLINE_FUNCTION void computePoke4(unsigned char *out) const
Definition convex_cell.hpp:391
int clusterNbhd
Definition repair.hpp:102
bool dilate(const TessGrid< Real > &grid, const Kokkos::View< Real *, Mem > &pos)
Definition repair.hpp:560
void surgicalRepair(const Kokkos::View< int *, Mem > &wl, int n, const Kokkos::View< Real *, Mem > &pos)
Definition repair.hpp:495
bool useDilation
Definition repair.hpp:91
int densityCount
Definition repair.hpp:81
void certifyDispatch(const Kokkos::View< Real *, Mem > &pos, const Kokkos::View< int *, Mem > &outMask, const Kokkos::View< int *, Mem > &outMover, bool useSkin)
Definition repair.hpp:610
int nProc
Definition repair.hpp:78
Real skin
Verlet skin width (absolute); a particle moving > skin/2 is a Pass-1 mover.
Definition repair.hpp:85
Kokkos::View< int *, Mem > wl1
Definition repair.hpp:143
bool surgical
repair flip cells by re-clipping known candidates instead of gathering
Definition repair.hpp:115
Kokkos::View< int *, Mem > extraNbr
Definition repair.hpp:145
Kokkos::View< Real *, Mem > vol
Definition repair.hpp:135
Kokkos::View< int *, Mem > mask2
Definition repair.hpp:143
void rebuild(const Kokkos::View< Real *, Mem > &pos, bool eagerAdj=true)
Definition repair.hpp:198
bool useGate
high-churn → rebuild routing (the "never slower than rebuild" guard)
Definition repair.hpp:90
Real tol
certificate tolerance (absolute distance); ~1e-4·spacing FP64, ~2e-3·spacing FP32
Definition repair.hpp:83
int N
total cells in the resident arrays (single-domain: all; MPI: owned+ghost)
Definition repair.hpp:77
Kokkos::View< int, Mem > counter
Definition repair.hpp:146
bool useLocalNow
this step's certify uses the local cert (= localCert && adjFresh)
Definition repair.hpp:132
bool localCert
Definition repair.hpp:119
int verifyCap
max verify extra-passes before falling back to a full rebuild
Definition repair.hpp:86
std::conditional_t< Weighted, Power, Voronoi > PlanePolicy
Definition repair.hpp:67
int gridNcell
Definition repair.hpp:147
Kokkos::View< int *, Mem > wl2
Definition repair.hpp:143
void rebuildAdjAll(const Kokkos::View< Real *, Mem > &pos)
Definition repair.hpp:389
void gatherSet(const TessGrid< Real > &grid, const Kokkos::View< int *, Mem > &wl, int n, const Kokkos::View< Real *, Mem > &pos)
Definition repair.hpp:429
int compact(const Kokkos::View< int *, Mem > &m, const Kokkos::View< int *, Mem > &wl)
Compact the nonzero entries of m[0..nProc) into wl, returning the count.
Definition repair.hpp:213
peclet::core::ExecSpace Exec
Definition repair.hpp:66
void collectNewNbrs(const Kokkos::View< int *, Mem > &wl, int n, const Kokkos::View< int *, Mem > &outMask)
Definition repair.hpp:454
Kokkos::View< Real *, Mem > weight
Definition repair.hpp:137
static constexpr int kExtraCap
per-cell capacity for partner-discovered new neighbours
Definition repair.hpp:117
void certify(const Kokkos::View< Real *, Mem > &pos, const Kokkos::View< int *, Mem > &outMask, const Kokkos::View< int *, Mem > &outMover, bool useSkin)
Definition repair.hpp:237
int sw
Definition repair.hpp:81
void setWeights(const Kokkos::View< Real *, Mem > &w)
Set the per-seed power weights (Weighted only). Held by reference; the caller keeps it alive.
Definition repair.hpp:141
Kokkos::View< int *, Mem > cellFlag
Definition repair.hpp:144
Kokkos::View< int *, Mem > rebuilt
Definition repair.hpp:143
Kokkos::View< Real *, Mem > xRef
Definition repair.hpp:136
void certifyList(const Kokkos::View< Real *, Mem > &pos, const Kokkos::View< int *, Mem > &list, int n, const Kokkos::View< int *, Mem > &outMask)
Definition repair.hpp:339
Kokkos::View< int *, Mem > mask
Definition repair.hpp:143
Kokkos::View< int *, Mem > wlM
Definition repair.hpp:143
RepairStats step(const Kokkos::View< Real *, Mem > &pos)
One moving-point update step. Updates store + vol in place from pos.
Definition repair.hpp:626
double dilateMaxChurn
Definition repair.hpp:99
bool adjFresh
Definition repair.hpp:127
double churnThresh
Definition repair.hpp:96
Kokkos::View< int *, Mem > extraCnt
Definition repair.hpp:145
void certifyListDispatch(const Kokkos::View< Real *, Mem > &pos, const Kokkos::View< int *, Mem > &list, int n, const Kokkos::View< int *, Mem > &outMask)
Definition repair.hpp:617
Store store
Definition repair.hpp:134
Kokkos::View< int *, Mem > mover
Definition repair.hpp:143
Real L[3]
Definition repair.hpp:82
void alloc(int n, const Real Lbox[3], Real tol_, Real skin_, int sw_=4, int densityCount_=-1, int nProc_=-1)
Definition repair.hpp:153
void maybeBuildAdj(const Kokkos::View< Real *, Mem > &pos)
Definition repair.hpp:417
peclet::core::MemSpace Mem
Definition repair.hpp:65
Sentinel "no geometry" provider — the default; the clip stage is skipped.
Definition sdf.hpp:36
Per-step repair telemetry.
Definition repair.hpp:48
int extra
cells gathered across the verify extra-passes
Definition repair.hpp:54
int pass1
cells gathered in Pass 1 (flagged ∪ partners ∪ skin-movers, after dilation)
Definition repair.hpp:51
int surgical
Pass-1 cells repaired surgically (Phase 4, no grid gather)
Definition repair.hpp:55
int pass2
cells gathered in Pass 2 (new face-neighbours of the movers)
Definition repair.hpp:53
bool fellBack
true if the cold-build fallback was triggered (repair did not close)
Definition repair.hpp:58
Route route
Definition repair.hpp:57
int pass1Raw
flagged count BEFORE dilation (the gate signal: pass1Raw/nProc = churn)
Definition repair.hpp:52
Route
Which path the Phase-3 adaptive gate took this step.
Definition repair.hpp:50
@ kDilated
Definition repair.hpp:50
@ kTwoPass
Definition repair.hpp:50
@ kRebuildGate
Definition repair.hpp:50
int verifyPasses
number of verify iterations run
Definition repair.hpp:56
Definition tess_grid.hpp:55
int dimz
Definition tess_grid.hpp:70
int dimy
Definition tess_grid.hpp:70
int dimx
Definition tess_grid.hpp:70
Real icz
Definition tess_grid.hpp:69
Real icx
Definition tess_grid.hpp:69
Real icy
Definition tess_grid.hpp:69
Definition topology_store.hpp:39
void alloc(int n)
Definition topology_store.hpp:53
Kokkos::View< int *, MemSpace > np
Definition topology_store.hpp:42
Kokkos::View< unsigned char *, MemSpace > poke4
Definition topology_store.hpp:47
KOKKOS_INLINE_FUNCTION void load(int i, Cell &c, Real L0, Real L1, Real L2) const
Definition topology_store.hpp:93
Kokkos::View< unsigned *, MemSpace > tri
Definition topology_store.hpp:45
KOKKOS_INLINE_FUNCTION void save(int i, const Cell &c) const
Persist cell c at slot i (call after the cell is finalised — clipped + complete).
Definition topology_store.hpp:75
Kokkos::View< int *, MemSpace > nt
Definition topology_store.hpp:43
Kokkos::View< int *, MemSpace > pnbr
Definition topology_store.hpp:44
void allocPoke4()
Definition topology_store.hpp:67