peclet.voro 1.0.4
Device-native moving-particle Voronoi dynamics
Loading...
Searching...
No Matches
peclet::voro Namespace Reference

Device-native Voronoi tessellation, geometry and finite-volume physics. More...

Namespaces

namespace  detail
 
namespace  energy
 
namespace  fv
 
namespace  mpi
 
namespace  physics
 
namespace  pybind
 

Classes

struct  AuxMaps
 
struct  BuildReport
 A2a validity diagnostics of a cold (re)build (counts over the maintained cells). More...
 
struct  CellBuilder
 
struct  ConvexCell
 
struct  HostTessellation
 Host-side CSR buffers — the conversion target and the round-trip oracle. More...
 
struct  InterfaceResult
 
struct  Invariants
 Per-step invariant residuals (all should be ~0 / ~machine-precision for a correct tessellation). More...
 
struct  MovingTessellation
 
struct  NoSdf
 Sentinel "no geometry" provider — the default; the clip stage is skipped. More...
 
struct  OracleDiff
 Result of comparing the current updated state against a fresh cold-build oracle. More...
 
struct  OtResult
 
struct  PoreCellsResult
 The clipped polyhedra, packed as flat arrays in seed order (VTK_POLYHEDRON layout). More...
 
struct  PoreSectionResult
 
struct  Power
 
struct  RepairStats
 Per-step repair telemetry. More...
 
struct  SdfBox
 
struct  SdfGrid
 
struct  SdfHollowCylinder
 
struct  SdfScene
 
struct  SdfSphere
 
struct  SdfSpheres
 
struct  SubsetGatherResult
 
struct  TangentOnly
 
struct  TessellationView
 
struct  TessellatorResult
 
struct  TessGrid
 
struct  TopologyStore
 
struct  VerletSkin
 
struct  Voronoi
 
struct  WallStore
 
struct  WorklistCache
 

Typedefs

using gid_t = std::int32_t
 

Enumerations

enum class  Precond { Jacobi , ColoredGS , GraphAMG , SteepestDescent }
 
enum  StatusBit {
  kOk = 0 , kOverflow = 1 , kEmpty = 2 , kIncomplete = 4 ,
  kNegOffset = 8 , kBuried = 16 , kReachExceeded = 32
}
 Per-cell status bits written by the build pass. More...
 
enum  SkinTrigger : int { kSkinNone = 0 , kSkinMover = 1 }
 

Functions

template<class Real , int MAXP, int MAXT, bool TrackAdj, class Policy = Voronoi>
KOKKOS_INLINE_FUNCTION void buildConvexCell (ConvexCell< Real, MAXP, MAXT, TrackAdj > &c, const Real L[3], const Real *relx, const Real *rely, const Real *relz, const int *ids, int nNbr, Real wSelf=Real(0), const Real *weights=nullptr)
 
template<class Real >
Invariants checkInvariants (const TessellationView< Real > &view, const AuxMaps< Real > &aux, double boxVolume)
 
template<class Real >
void compareVolumes (const Kokkos::View< Real *, peclet::core::MemSpace > &volCurrent, const TessellationView< Real > &oracle, OracleDiff &out)
 Compare a current per-cell volume array against the oracle view's volumes (cell i == seed i).
 
template<class Real >
void compareNeighbours (const Kokkos::View< int *, peclet::core::MemSpace > &storeNp, const Kokkos::View< int *, peclet::core::MemSpace > &storeNt, const Kokkos::View< int *, peclet::core::MemSpace > &storePnbr, const Kokkos::View< unsigned *, peclet::core::MemSpace > &storeTri, int MAXP, int MAXT, const TessellationView< Real > &oracle, OracleDiff &out)
 
template<class Real , bool Weighted = false, class Sdf = NoSdf>
OtResult meshVolumeOptimize (std::vector< Real > &pos, std::vector< Real > &weight, const std::vector< Real > &vsetIn, const Real L[3], int N, int sw, const Sdf &sdf, int maxNewton, Real tol, int cgIters=kOptimizerCgIters, Precond prec=Precond::Jacobi, bool verbose=false, Real muBarrier=0, Real muDecay=(Real) kBarrierDecay, bool freeEnergy=false)
 
template<class Real , class Sdf = NoSdf>
InterfaceResult interfaceMinimize (std::vector< Real > &pos, const std::vector< int > &type, double sigma, const Real L[3], int N, int sw, const Sdf &sdf, int maxIter, Real tol, bool verbose=false)
 
template<class Real , class Sdf = NoSdf>
OtResult meshVolumeOptimizeDevice (std::vector< Real > &posHost, const std::vector< Real > &vsetIn, const Real L[3], int N, int sw, const Sdf &sdf, int maxNewton, Real tol, int cgIters=kOptimizerCgIters, bool verbose=false)
 
template<class Real , class Sdf = NoSdf>
OtResult otVolumeControl (std::vector< Real > &pos, std::vector< Real > &weight, const std::vector< Real > &vsetIn, const Real L[3], int N, int sw, const Sdf &sdf, int maxNewton, Real tol, Real reg=Real(1e-6), Real damp=Real(1), bool verbose=false)
 
template<class Policy , class Cell , class Real >
KOKKOS_INLINE_FUNCTION void chainToDofs (const Cell &c, const Real seed[3], const Real *pos, Real wSelf, const Real *weight, Real L, const Real *gx, const Real *gy, const Real *gz, Real fSelf[3], Real &fwSelf, Real *fnx, Real *fny, Real *fnz, Real *fwn)
 
template<class Real , class Sdf , int MAXP = kMaxPlanes, int MAXT = kMaxTriangles>
PoreCellsResult< Real > buildPoreCells (const Kokkos::View< Real *, peclet::core::MemSpace > &posFlat, int N, const Real L[3], const Sdf &sdf, int sw=kSearchWindow)
 
template<class Real , class Sdf , int MAXP = kMaxPlanes, int MAXT = kMaxTriangles>
PoreSectionResult< Real > buildPoreSection (const Kokkos::View< Real *, peclet::core::MemSpace > &posFlat, int N, const Real L[3], const Sdf &sdf, const Real point[3], const Real normal[3], int sw=kSearchWindow)
 
template<class Real , int MAXP, int MAXT>
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)
 
template<class Real , class Sdf >
KOKKOS_INLINE_FUNCTION void sdfGradient (const Sdf &s, Real x, Real y, Real z, Real g[3])
 Central-difference gradient of any provider with eval() (matches peclet::core::geom::gradient).
 
template<class Real , class Sdf >
KOKKOS_INLINE_FUNCTION void sdfHessian (const Sdf &s, Real x, Real y, Real z, Real H[3][3])
 
template<class Real , class Sdf >
KOKKOS_INLINE_FUNCTION void sdfWallChain (const Sdf &sdf, Real x, Real y, Real z, const double gw[3], double fSelf[3])
 
template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION void addSdfWallForce (const ConvexCell< Real, MAXP, MAXT, TrackAdj > &c, const Real seed[3], const Sdf &sdf, const Real *gx, const Real *gy, const Real *gz, Real fSelf[3])
 
template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION int sdfSagittaShifts (const ConvexCell< Real, MAXP, MAXT, TrackAdj > &c, const Real seed[3], const Sdf &sdf, const int *planes, const Real *tangency, int nPlanes, Real *delta)
 
template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION bool sdfCutPlane (const ConvexCell< Real, MAXP, MAXT, TrackAdj > &c, const Real seed[3], const Sdf &sdf, const Real probe[3], Real radius, Real pv[3], Real &off, Real surf[3])
 
template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION bool sdfWouldClip (const ConvexCell< Real, MAXP, MAXT, TrackAdj > &c, const Real seed[3], const Sdf &sdf)
 
template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION bool clipCellAgainstSdf (ConvexCell< Real, MAXP, MAXT, TrackAdj > &c, const Real seed[3], const Sdf &sdf)
 
template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION void sdfWallFD (const ConvexCell< Real, MAXP, MAXT, TrackAdj > &unclipped, const Real seed[3], const Sdf &sdf, Real h, Real dV[3], Real dA[3])
 
template<class Real , bool Weighted = false, bool TrackAdj = false, class Sdf = NoSdf>
SubsetGatherResult< Real > subsetGather (const TessGrid< Real > &grid, const Kokkos::View< int *, peclet::core::MemSpace > &indices, int nSubset, const Kokkos::View< int *, peclet::core::MemSpace > &outNp, const Kokkos::View< int *, peclet::core::MemSpace > &outNt, const Kokkos::View< int *, peclet::core::MemSpace > &outPnbr, const Kokkos::View< unsigned *, peclet::core::MemSpace > &outTri, const Kokkos::View< Real *, peclet::core::MemSpace > &cellVol, const Kokkos::View< unsigned char *, peclet::core::MemSpace > &outPoke4={}, Sdf sdf={}, bool withForceGeom=false, WallStore< Real > outWall={}, Kokkos::View< int *, peclet::core::MemSpace > outNear={}, Kokkos::View< int *, peclet::core::MemSpace > outNearCnt={}, int nearCap=0, Real nearMargin=Real(0))
 
KOKKOS_INLINE_FUNCTION int morton3 (int x, int y, int z)
 
template<class Real , bool Weighted>
TessGrid< Real > buildTessGrid (const Kokkos::View< Real *, peclet::core::MemSpace > &posFlat, const Kokkos::View< Real *, peclet::core::MemSpace > &weight, int N, const Real L[3], int sw=kSearchWindow, int densityCount=-1, Kokkos::View< long *, peclet::core::MemSpace > gid={}, WorklistCache< Real > *wlc=nullptr)
 
gid_t toGid (std::uint32_t id)
 
template<class Real >
std::vector< int > buildReciprocalMap (const HostTessellation< Real > &t)
 
template<class Real >
TessellationView< Real > upload (const HostTessellation< Real > &h)
 Upload a HostTessellation to device Views.
 
template<class Cell , int MAXF>
KOKKOS_INLINE_FUNCTION int areaGradEnumerate (const Cell &c, const int *faces, int nf, unsigned char *part, unsigned char *pcnt, bool &full)
 
template<class Cell , int MAXF, class IView , class RView >
KOKKOS_INLINE_FUNCTION void areaGradFill (const Cell &c, const int *faces, int nf, const unsigned char *part, const unsigned char *pcnt, int base, int ebase, const IView &oEdgeOff, const IView &oEdgeCnt, const IView &oEdgeFacet, const RView &oEdgeGrad, const RView &oEdgeLen)
 
template<class Real , bool Weighted, class Sdf = NoSdf, int MAXP = kMaxPlanes, int MAXT = kMaxTriangles>
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=kSearchWindow, 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, WallStore< Real > outWall={}, bool withAreaGrad=false, Kokkos::View< int *, peclet::core::MemSpace > outNear={}, Kokkos::View< int *, peclet::core::MemSpace > outNearCnt={}, int nearCap=0, Real nearMargin=Real(0), bool withWallFD=false, bool withMoments=false, bool profile=false)
 
template<class Real >
AuxMaps< Real > buildAuxMaps (const TessellationView< Real > &view)
 Build {recip, cellOfFacet} on device from a published view (dense single-domain).
 
template<class Real >
int flagSkinMovers (const Kokkos::View< Real *, peclet::core::MemSpace > &pos, const Kokkos::View< Real *, peclet::core::MemSpace > &xRef, Real skin, const Real L[3], const Kokkos::View< int *, peclet::core::MemSpace > &outFlags)
 
template<class Real >
Real maxDisplacement (const Kokkos::View< Real *, peclet::core::MemSpace > &pos, const Kokkos::View< Real *, peclet::core::MemSpace > &xRef, const Real L[3])
 

Variables

constexpr int kMaxPlanes = 64
 
constexpr int kMaxTriangles = 112
 
constexpr int kPoreMaxPlanes = 128
 
constexpr int kPoreMaxTriangles = 256
 
constexpr int kSearchWindow = 4
 
constexpr double kCertificateTolerance = 1e-4
 
constexpr double kSkin = 0.25
 
constexpr int kOptimizerCgIters = 300
 
constexpr double kBarrierDecay = 0.7
 
constexpr int kBoundaryFacet = -2
 
constexpr int kMaxWallPlanes = 24
 
constexpr int kWlOffBias = 128
 

Detailed Description

Device-native Voronoi tessellation, geometry and finite-volume physics.

Typedef Documentation

◆ gid_t

using peclet::voro::gid_t = typedef std::int32_t

Seed/neighbour identifier in the published view. Signed so the unsigned sentinels map cleanly to negatives: 0xFFFFFFFF -> -1 (no neighbour), 0xFFFFFFFE -> -2 (boundary). Consumers treat facetNbr(f) < 0 as a boundary facet.

Enumeration Type Documentation

◆ Precond

enum class peclet::voro::Precond
strong
Enumerator
Jacobi 
ColoredGS 
GraphAMG 
SteepestDescent 

◆ SkinTrigger

Per-particle rebuild-trigger bits. Extensible: Phase 1 only ever sets kSkinMover; the deferred boundary trigger (Risk 1d) will add kSkinBoundary so a status-change near an SDF wall feeds the same Pass-1 set. Stored as int so the flag array doubles as a stream-compaction mask.

Enumerator
kSkinNone 
kSkinMover 

◆ StatusBit

Per-cell status bits written by the build pass.

Enumerator
kOk 
kOverflow 
kEmpty 
kIncomplete 
kNegOffset 
kBuried 
kReachExceeded 

Function Documentation

◆ addSdfWallForce()

template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION void peclet::voro::addSdfWallForce ( const ConvexCell< Real, MAXP, MAXT, TrackAdj > &  c,
const Real  seed[3],
const Sdf &  sdf,
const Real *  gx,
const Real *  gy,
const Real *  gz,
Real  fSelf[3] 
)

Differentiable SDF wall force (Effort 2, Option A — the seed-foot model). A wall facet (pnbr == kBoundaryFacet) is modelled as the tangent plane at the seed's foot point on sdf=0, so its seed-relative foot-point normal is n_wall(s) = −φ(s) û(s), û = ∇φ/|∇φ|. Its Jacobian is J_wall = ∂n_wall/∂s = −|∇φ| û ûᵀ − (φ/|∇φ|)(I − û ûᵀ) H, H = ∇²φ, so the wall's contribution to dGeom/dseed is J_wallᵀ g summed over the cell's wall facets (g = dGeom/dn_k from geomVolumeGrad). EXACT for a flat wall (φ linear ⇒ H=0, one facet); first-order for a curved wall (the clip approximates the curve by several vertex-anchored tangent facets, modelled here as one effective seed-foot plane). Call AFTER chainToDofs<Policy> (which zeroes pnbr<0 planes); this adds the wall self-force into fSelf. No-op for NoSdf.

◆ areaGradEnumerate()

template<class Cell , int MAXF>
KOKKOS_INLINE_FUNCTION int peclet::voro::areaGradEnumerate ( const Cell &  c,
const int *  faces,
int  nf,
unsigned char *  part,
unsigned char *  pcnt,
bool &  full 
)

Per-cell build on the compact ConvexCell (dual-triangle) representation — one thread per cell (RangePolicy; the cell lives in the per-thread register/local frame). Holds the grid-sorted inputs, the published outputs, and the grid scalars; buildCell clips the worklist neighbours on the fly and emits the per-facet CSR (neighbour id + area vector + dV + connector) via ConvexCell::facetGeometry — the same quantities the retired half-edge ScratchCell published, now from the leaner cell whose geometry is a cheap separate pass (so re-eval over a fixed topology is possible: ConvexCell::reevalGeometry). Rung A3 — the facet-edge AREA-JACOBIAN CSR of one finalised cell (shared by the cold build's CellBuilder::publishAreaGrad and reevalPublish). Per triangle, ConvexCell::geomVolumeAreaGrad gives the 3x3 blocks ∂contrib_i/∂n_{pl[j]}; summed over the cell's triangles they are exactly ∂A_{pl[i]}/∂n_{pl[j]}, and (i, j) with i != j is always an edge pair (the two planes meet at that vertex), so the CSR is the union of {self} ∪ {edge partners} per face — enumerated from the triangle list (dedup by a short scan; part/pcnt are the caller's MAXF*kMaxFV / MAXF scratch), then filled by one scatter pass. Planes that publish no face (< 3 live triangles) are skipped as partners: no area, and their sliver dependence is below the published-face contract. faces[0..nf) = the cell's face planes in CSR order.

◆ areaGradFill()

template<class Cell , int MAXF, class IView , class RView >
KOKKOS_INLINE_FUNCTION void peclet::voro::areaGradFill ( const Cell &  c,
const int *  faces,
int  nf,
const unsigned char *  part,
const unsigned char *  pcnt,
int  base,
int  ebase,
const IView &  oEdgeOff,
const IView &  oEdgeCnt,
const IView &  oEdgeFacet,
const RView &  oEdgeGrad,
const RView &  oEdgeLen 
)

Fill the CSR entries reserved at ebase (see areaGradEnumerate): offsets/counts per facet (facet g = base + idx), partner facet indices (slot 0 = self), and the accumulated blocks.

◆ buildAuxMaps()

template<class Real >
AuxMaps< Real > peclet::voro::buildAuxMaps ( const TessellationView< Real > &  view)

Build {recip, cellOfFacet} on device from a published view (dense single-domain).

◆ buildConvexCell()

template<class Real , int MAXP, int MAXT, bool TrackAdj, class Policy = Voronoi>
KOKKOS_INLINE_FUNCTION void peclet::voro::buildConvexCell ( ConvexCell< Real, MAXP, MAXT, TrackAdj > &  c,
const Real  L[3],
const Real *  relx,
const Real *  rely,
const Real *  relz,
const int *  ids,
int  nNbr,
Real  wSelf = Real(0),
const Real *  weights = nullptr 
)

Build a cell from neighbour relative positions sorted by ascending distance (rSqHalf). Policy = Voronoi (default) clips closest-first with the security-radius early-out: once the next candidate's plane offset exceeds 2·max-vertex-rsq, no farther seed can cut. Policy = Power uses the radical-plane offset ½(|r|²+w_self−w_nbr) and — in this reference builder — applies EVERY candidate (no early-out; the bisector security certificate is invalid once the offset can go negative, so P1 keeps the trivially-correct apply-all path). weights is indexed like ids (neighbour weights); it may be null for Voronoi. Mirrors the half-edge buildVoronoiCell.

◆ buildPoreCells()

template<class Real , class Sdf , int MAXP = kMaxPlanes, int MAXT = kMaxTriangles>
PoreCellsResult< Real > peclet::voro::buildPoreCells ( const Kokkos::View< Real *, peclet::core::MemSpace > &  posFlat,
int  N,
const Real  L[3],
const Sdf &  sdf,
int  sw = kSearchWindow 
)

The SDF-clipped interstitial polyhedra of every seed, on the device.

Parameters
posFlatdevice seed positions, x-fastest (3·i + k), in [0, L).
Nseed count.
Lperiodic box extent.
sdfthe wall solid (any provider with eval()/gradH(); NoSdf gives the bare cells).
swthe gather window (grid blocks per axis; kPoreSearchWindow in the bindings). Seeds inside the solid (empty cell) and cells that overflow the capacity are skipped; the result counts the latter, and the cells whose gather coverage did not close (kIncomplete).

◆ buildPoreSection()

template<class Real , class Sdf , int MAXP = kMaxPlanes, int MAXT = kMaxTriangles>
PoreSectionResult< Real > peclet::voro::buildPoreSection ( const Kokkos::View< Real *, peclet::core::MemSpace > &  posFlat,
int  N,
const Real  L[3],
const Sdf &  sdf,
const Real  point[3],
const Real  normal[3],
int  sw = kSearchWindow 
)

The cross-section of the SDF-clipped interstitial mesh by the plane through point with normal: every cell cut directly (ConvexCell::sectionPolygon, from the dual edges, so the polygons tile the section exactly). Same gather and skip rules as buildPoreCells; a cell the plane misses (or grazes at fewer than three crossings) yields no polygon.

◆ buildReciprocalMap()

template<class Real >
std::vector< int > peclet::voro::buildReciprocalMap ( const HostTessellation< Real > &  t)

Reciprocal-facet transpose (NbrsToFacets, plan §2.5). For each packed facet g (cell i -> seed j) returns the packed index of the facet in cell j that points back to seed i, or -1 for a boundary facet or if no reciprocal exists. This is the map the atomic-free gather force reads through: a cell fetches its neighbour's reciprocal-facet quantities without scattering (no atomics).

Periodic multi-image facets (several g in i -> same j) are disambiguated by area-vector negation (the reciprocal has the most opposite area vector).

◆ buildTessellation()

template<class Real , bool Weighted, class Sdf = NoSdf, int MAXP = kMaxPlanes, int MAXT = kMaxTriangles>
TessellatorResult< Real > peclet::voro::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 = kSearchWindow,
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,
WallStore< Real >  outWall = {},
bool  withAreaGrad = false,
Kokkos::View< int *, peclet::core::MemSpace >  outNear = {},
Kokkos::View< int *, peclet::core::MemSpace >  outNearCnt = {},
int  nearCap = 0,
Real  nearMargin = Real(0),
bool  withWallFD = false,
bool  withMoments = false,
bool  profile = false 
)

Build the full tessellation on device.

Parameters
posFlatdevice positions, x-fastest per seed (3*i + k), in [0,L).
weightdevice per-seed weights (size N) for the Power policy; ignored (may be empty) when Weighted == false.
Nnumber of seeds.
Lperiodic box extent.
swgrid-block half-width (default 4; coverage = sw·cellSize).
densityCountseed count to derive the grid spacing from (cellSize ~ mean spacing). Defaults to N. In the distributed case the seeds are a clustered owned+ghost subset, so pass the GLOBAL count to keep the grid at the true local density.
nBuildbuild a cell only for seeds whose ORIGINAL index is < nBuild; the rest are still used as cut candidates (neighbours) but their own cell is skipped. Defaults to N (build all). In the distributed case the ghosts are appended after the nOwned owned seeds, so passing nOwned tessellates only the kept (owned) cells — the ghost cells are needed only as cutting seeds, so building them is wasted work (~the ghost fraction of the cold build).
profileprint the timing (grid / build / CSR), the worklist size, over-buffer rebuilds and max facets per cell on stderr (the API's profile switch; the result's overBufferRebuilds reports the rebuilds without it).

◆ buildTessGrid()

template<class Real , bool Weighted>
TessGrid< Real > peclet::voro::buildTessGrid ( const Kokkos::View< Real *, peclet::core::MemSpace > &  posFlat,
const Kokkos::View< Real *, peclet::core::MemSpace > &  weight,
int  N,
const Real  L[3],
int  sw = kSearchWindow,
int  densityCount = -1,
Kokkos::View< long *, peclet::core::MemSpace >  gid = {},
WorklistCache< Real > *  wlc = nullptr 
)

Build the counting-sort grid + worklist for the Voronoi gather (the first half of the old buildTessellation, unchanged). Weighted only affects the grid density (Power keeps 1 seed/cell; unweighted host uses 2/cell for cache locality). See buildTessellation for the argument semantics. wlc (optional) reuses/fills the step-invariant worklist table across calls (E3); nullptr rebuilds it every call (the original behaviour, byte-for-byte).

◆ chainToDofs()

template<class Policy , class Cell , class Real >
KOKKOS_INLINE_FUNCTION void peclet::voro::chainToDofs ( const Cell &  c,
const Real  seed[3],
const Real *  pos,
Real  wSelf,
const Real *  weight,
Real  L,
const Real *  gx,
const Real *  gy,
const Real *  gz,
Real  fSelf[3],
Real &  fwSelf,
Real *  fnx,
Real *  fny,
Real *  fnz,
Real *  fwn 
)

Chain a cell's per-plane geometry gradient (SoA gx/gy/gz, e.g. from geomVolumeGrad) to the physics DOFs under Policy. Accumulates the derivative w.r.t. the cell's OWN seed into fSelf (position) and fwSelf (weight), and writes the derivative w.r.t. each neighbour seed into (fnx,fny,fnz)[k] (position) and fwn[k] (weight) — the caller scatters those into the global per-seed arrays at index pnbr[k]. Box/SDF planes (pnbr < 0) contribute nothing here (zeroed); SDF-wall self-DOF forces are added by the SDF chain in sdf.hpp.

seed/pos/wSelf/weight/L recompute each plane's (r, ρ, c) for weighted policies; they are untouched for Voronoi (kHasWeightDof == false), so a caller with no weights may pass nullptr for pos/weight and 0 for wSelf on the Voronoi path.

◆ checkInvariants()

template<class Real >
Invariants peclet::voro::checkInvariants ( const TessellationView< Real > &  view,
const AuxMaps< Real > &  aux,
double  boxVolume 
)

Compute the per-step invariants of a published TessellationView. aux is its reciprocal map (buildAuxMaps(view)); pass the box volume Lx*Ly*Lz.

◆ clipCellAgainstSdf()

template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION bool peclet::voro::clipCellAgainstSdf ( ConvexCell< Real, MAXP, MAXT, TrackAdj > &  c,
const Real  seed[3],
const Sdf &  sdf 
)

Clip a built scratch cell against the SDF solid. Port of clipCellAgainstBoundary (m_boundaryMaxCuts=24, m_boundaryTol=1e-8): empties the cell if its seed is in the solid; otherwise iteratively projects the most violating vertex onto sdf=0 and clips by the tangent plane there, so a curved surface is approximated by a few planar wall facets. Rung A0 added the chord-plane fallback for a tangent plane that would exclude the seed (see the body) — the legacy port committed such planes and produced the dead cells seen in pore meshing.

Parameters
seedseed world position (the cell's vpos are relative to it).
Returns
true if the cell was emptied (seed inside solid).

◆ compareNeighbours()

template<class Real >
void peclet::voro::compareNeighbours ( const Kokkos::View< int *, peclet::core::MemSpace > &  storeNp,
const Kokkos::View< int *, peclet::core::MemSpace > &  storeNt,
const Kokkos::View< int *, peclet::core::MemSpace > &  storePnbr,
const Kokkos::View< unsigned *, peclet::core::MemSpace > &  storeTri,
int  MAXP,
int  MAXT,
const TessellationView< Real > &  oracle,
OracleDiff &  out 
)

Compare the stored topology against the oracle's neighbour sets, on FACE neighbours (a stored plane k counts only if ≥3 live triangles are incident — the raw pnbr also keeps non-face cutting planes, which are not neighbours). changedNbrFrac = cells whose face-neighbour SET differs (either direction); missedNbr = cells missing a TRUE neighbour (genuine staleness — what the repair must drive to zero). Needs the packed triangles (tri at stride MAXT) + nt to identify the faces.

◆ compareVolumes()

template<class Real >
void peclet::voro::compareVolumes ( const Kokkos::View< Real *, peclet::core::MemSpace > &  volCurrent,
const TessellationView< Real > &  oracle,
OracleDiff &  out 
)

Compare a current per-cell volume array against the oracle view's volumes (cell i == seed i).

◆ flagSkinMovers()

template<class Real >
int peclet::voro::flagSkinMovers ( const Kokkos::View< Real *, peclet::core::MemSpace > &  pos,
const Kokkos::View< Real *, peclet::core::MemSpace > &  xRef,
Real  skin,
const Real  L[3],
const Kokkos::View< int *, peclet::core::MemSpace > &  outFlags 
)

Flag every particle that has moved more than skin/2 from xRef (minimal image in box L), writing kSkinMover/kSkinNone into outFlags, and return the number flagged. outFlags must be sized N. The flag value is OR-combinable with future trigger bits; here it is overwritten each call (the only Phase-1 trigger). One reduce + write pass; no host round-trip beyond the final count.

◆ interfaceMinimize()

template<class Real , class Sdf = NoSdf>
InterfaceResult peclet::voro::interfaceMinimize ( std::vector< Real > &  pos,
const std::vector< int > &  type,
double  sigma,
const Real  L[3],
int  N,
int  sw,
const Sdf &  sdf,
int  maxIter,
Real  tol,
bool  verbose = false 
)

◆ maxDisplacement()

template<class Real >
Real peclet::voro::maxDisplacement ( const Kokkos::View< Real *, peclet::core::MemSpace > &  pos,
const Kokkos::View< Real *, peclet::core::MemSpace > &  xRef,
const Real  L[3] 
)

Largest per-seed displacement from xRef (minimal image), in absolute units. Diagnostics / the Verlet rebuild decision (max-disp > skin/2 -> a global rebuild is the simplest safe response).

◆ meshVolumeOptimize()

template<class Real , bool Weighted = false, class Sdf = NoSdf>
OtResult peclet::voro::meshVolumeOptimize ( std::vector< Real > &  pos,
std::vector< Real > &  weight,
const std::vector< Real > &  vsetIn,
const Real  L[3],
int  N,
int  sw,
const Sdf &  sdf,
int  maxNewton,
Real  tol,
int  cgIters = kOptimizerCgIters,
Precond  prec = Precond::Jacobi,
bool  verbose = false,
Real  muBarrier = 0,
Real  muDecay = (Real)kBarrierDecay,
bool  freeEnergy = false 
)

Minimise the DIMENSIONLESS relative volume energy E = Σ (V_i/V_ref,i − 1)² by damped Gauss-Newton over positions (and weights when Weighted). vsetIn is the per-cell reference volume V_ref (may be non-uniform — spatially-graded refinement); it is renormalised to the actual total cell volume so the residual has zero mean and E → 0 is achievable. pos (3N) and weight (N; used only when Weighted) are updated in place.

NOTE: with an SDF the per-cell volume gradient still uses only the published seed-seed facetConnect (it omits the SDF wall-facet term), so pore-space meshing does not yet fully equalise — the wall gradient needs to be produced inside the tessellator (see the study in tests/kokkos/bench_mesh_optimizer).

Parameters
precJacobi / ColoredGS / GraphAMG CG preconditioner.
cgItersinner CG iterations per Newton step;
tolon the gradient ∞-norm.

◆ meshVolumeOptimizeDevice()

template<class Real , class Sdf = NoSdf>
OtResult peclet::voro::meshVolumeOptimizeDevice ( std::vector< Real > &  posHost,
const std::vector< Real > &  vsetIn,
const Real  L[3],
int  N,
int  sw,
const Sdf &  sdf,
int  maxNewton,
Real  tol,
int  cgIters = kOptimizerCgIters,
bool  verbose = false 
)

◆ morton3()

KOKKOS_INLINE_FUNCTION int peclet::voro::morton3 ( int  x,
int  y,
int  z 
)

3D Morton (Z-order) code of a grid cell, via the suite's morton library (Morton<3,21>, software bit path on device — no BMI2; bit-identical to the former hand-rolled magic-bits spread). Used to order the cell grid so a cell's spatial neighbourhood is near it in memory — the gather then reads near-contiguous cellStart/posSorted instead of chasing z-neighbours dimx*dimy entries apart. Good to 21 bits/axis (grid indices are far below that).

◆ otVolumeControl()

template<class Real , class Sdf = NoSdf>
OtResult peclet::voro::otVolumeControl ( std::vector< Real > &  pos,
std::vector< Real > &  weight,
const std::vector< Real > &  vsetIn,
const Real  L[3],
int  N,
int  sw,
const Sdf &  sdf,
int  maxNewton,
Real  tol,
Real  reg = Real(1e-6),
Real  damp = Real(1),
bool  verbose = false 
)

Drive the power weights weight (size N, updated in place) so the power-cell volumes match vsetIn (size N). pos (size 3N) are the fixed seeds. Returns convergence diagnostics.

Parameters
swgrid coverage half-width for the tessellation (default 4).
maxNewtonmax Newton iterations.
tolconvergence on max_i |V_i − V_set_i| (absolute volume).
regtiny Laplacian regularisation ε (lifts the constant nullspace so L+εI is SPD).
dampNewton step scale α (1 = full Newton; <1 damps).
verboseprint per-iteration residual.

vsetIn is normalised internally so Σ V_set = Σ V (the total tessellated volume) — the constant nullspace of L requires a compatible right-hand side (Σ residual = 0).

◆ reevalPublish()

template<class Real , int MAXP, int MAXT>
TessellationView< Real > peclet::voro::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 
)

Re-evaluate the geometry of every cell in store on positions pos and publish a force-geometry TessellationView (facet neighbour / area / dV / connector CSR), reusing vol for the per-cell volume. MAXP/MAXT are the store's ConvexCell capacities; N cells; L the (cubic) box. wall + xRef (optional, rung A0): the resident SDF wall planes and the per-cell positions at which they were saved, so a wall-clipped cell's planes are restored for the seed's current position before the re-eval (see WallStore). Leave both empty for a wall-free tessellation. withAreaGrad (rung A3): also publish the facet-edge area-Jacobian CSR (the same layout the cold build emits, with a deterministic prefix-sum reservation), so the energy layer runs on the incremental path too.

◆ sdfCutPlane()

template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION bool peclet::voro::sdfCutPlane ( const ConvexCell< Real, MAXP, MAXT, TrackAdj > &  c,
const Real  seed[3],
const Sdf &  sdf,
const Real  probe[3],
Real  radius,
Real  pv[3],
Real &  off,
Real  surf[3] 
)

The wall cut plane for a probe point (the seed for the first cut, a violating vertex after): closest point on φ = 0 + outward normal (oriented into the fluid), the half-space {x : pv·x ≤ off} in seed-relative coordinates with pv = −normal, plus the tangency point surf (world) for the sagitta post-pass. Shared by clipCellAgainstSdf and the moving-point boundary watch (sdfWouldClip), so both make the same decision. Returns false if the gradient is degenerate (no plane).

◆ sdfGradient()

template<class Real , class Sdf >
KOKKOS_INLINE_FUNCTION void peclet::voro::sdfGradient ( const Sdf &  s,
Real  x,
Real  y,
Real  z,
Real  g[3] 
)

Central-difference gradient of any provider with eval() (matches peclet::core::geom::gradient).

◆ sdfHessian()

template<class Real , class Sdf >
KOKKOS_INLINE_FUNCTION void peclet::voro::sdfHessian ( const Sdf &  s,
Real  x,
Real  y,
Real  z,
Real  H[3][3] 
)

Central-difference Hessian H_ab = ∂²φ/∂x_a∂x_b (symmetrised), via differences of the gradient (same stencil as sdfGradient, so host/device agree). Used by the differentiable SDF wall force.

◆ sdfSagittaShifts()

template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION int peclet::voro::sdfSagittaShifts ( const ConvexCell< Real, MAXP, MAXT, TrackAdj > &  c,
const Real  seed[3],
const Sdf &  sdf,
const int *  planes,
const Real *  tangency,
int  nPlanes,
Real *  delta 
)

Rung A1 — second-order wall placement. A tangent plane at a tangency point surf (unit normal into the fluid) is exact for a flat wall but INSCRIBED for a curved one: over its face the true surface deviates from the plane by h(p) = φ(surf + p)/|∇φ| ≈ ½ pᵀ H p / |∇φ| (p in-plane, H = ∇²φ), so the tangent cut removes the fluid sliver between plane and wall on a convex solid and leaves solid inside the cell on a concave one. Once the multi-plane tangent clip has settled the cell, each committed wall plane k gets the mean sliver depth over its FINAL face polygon, δ_k = V_sag / A_k, V_sag = ½ Σ_ab H_ab M_ab / |∇φ|, M = ∫_face p pᵀ dA about surf, and clipCellAgainstSdf RE-CLIPS the un-cut cell with every plane translated INTO the solid by its δ_k (a re-clip, not a plane move, so the result is a valid convex clip and the resident certificate stays clean). The planar cell then has the curved cell's volume to second order. Shifts below round-off of the Hessian stencil (|δ| < 1e-8·h_k, i.e. flat walls) are zeroed so a flat wall is bit-identical to the tangent clip. Writes δ_k into delta (0 for planes with no face); returns the number of nonzero shifts.

◆ sdfWallChain()

template<class Real , class Sdf >
KOKKOS_INLINE_FUNCTION void peclet::voro::sdfWallChain ( const Sdf &  sdf,
Real  x,
Real  y,
Real  z,
const double  gw[3],
double  fSelf[3] 
)

The seed-foot SDF wall chain (rung A3 — the single source; see energy/wall.hpp): f_self += J_wallᵀ g_w with J_wall = dn/dx of the foot vector n = −φ∇φ/|∇φ|². Coordinates in Real, accumulation in double — the exact arithmetic of the optimiser's device kernel it replaces. No-op for NoSdf.

◆ sdfWallFD()

template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION void peclet::voro::sdfWallFD ( const ConvexCell< Real, MAXP, MAXT, TrackAdj > &  unclipped,
const Real  seed[3],
const Sdf &  sdf,
Real  h,
Real  dV[3],
Real  dA[3] 
)

Rung A1 (force half) — the wall part of a cell's geometry gradient, exact for WHATEVER the clip does (tangent planes, chord planes, the sagitta re-clip): central differences of the clipped cell's volume and wall area with respect to the seed position, with the neighbour planes held fixed in the seed frame (the chain-rule split the energy layer uses: neighbour planes go through the plane policy, wall planes through this). unclipped is the cell BEFORE the SDF clip; six SDF clips of a copy at seed ± h e_d. Writes dV/dx and dA_wall/dx (3 each).

◆ sdfWouldClip()

template<class Real , int MAXP, int MAXT, bool TrackAdj, class Sdf >
KOKKOS_INLINE_FUNCTION bool peclet::voro::sdfWouldClip ( const ConvexCell< Real, MAXP, MAXT, TrackAdj > &  c,
const Real  seed[3],
const Sdf &  sdf 
)

Would clipCellAgainstSdf commit at least one wall plane on this (un-clipped) cell? The exact decision the cold build makes, so the moving-point boundary watch flags precisely the cells whose cold rebuild would differ from a wall-free re-evaluation: the seed is in the solid (the cell would be emptied), OR the cell is within its circumradius of the surface AND (some vertex lies beyond the seed-foot tangent plane — the first cut — OR some vertex is inside the solid by more than the clip tolerance — a later cut). Reads the same tolerance and probe rule as the clip.

◆ subsetGather()

template<class Real , bool Weighted = false, bool TrackAdj = false, class Sdf = NoSdf>
SubsetGatherResult< Real > peclet::voro::subsetGather ( const TessGrid< Real > &  grid,
const Kokkos::View< int *, peclet::core::MemSpace > &  indices,
int  nSubset,
const Kokkos::View< int *, peclet::core::MemSpace > &  outNp,
const Kokkos::View< int *, peclet::core::MemSpace > &  outNt,
const Kokkos::View< int *, peclet::core::MemSpace > &  outPnbr,
const Kokkos::View< unsigned *, peclet::core::MemSpace > &  outTri,
const Kokkos::View< Real *, peclet::core::MemSpace > &  cellVol,
const Kokkos::View< unsigned char *, peclet::core::MemSpace > &  outPoke4 = {},
Sdf  sdf = {},
bool  withForceGeom = false,
WallStore< Real >  outWall = {},
Kokkos::View< int *, peclet::core::MemSpace >  outNear = {},
Kokkos::View< int *, peclet::core::MemSpace >  outNearCnt = {},
int  nearCap = 0,
Real  nearMargin = Real(0) 
)

Gather + clip the nSubset cells named by indices (original seed indices) off grid, writing their topology into the caller's store views and their volume into the result.

Parameters
grida TessGrid built for the CURRENT positions (buildTessGrid). Reused, not rebuilt.
indicesdevice view of nSubset ORIGINAL seed indices to (re)build (values in [0,N)).
nSubsetnumber of indices to process.
outNp,outNt,outPnbr,outTritopology store views, each sized as in TopologyStore::alloc(N) (N, N, N*MAXP, N*MAXT) with MAXP=CellBuilder::kMaxP, MAXT=CellBuilder::kMaxT.
cellVolN-sized view; the volume of each rebuilt cell is written at its original index.
withForceGeomif true also compute the per-facet area/dV/connector (kept for parity with the cold build); the facet CSR itself is not published here (the store is). Default false: the store + volume are what Phase-1 needs (geometry is re-derived on reload).

◆ toGid()

gid_t peclet::voro::toGid ( std::uint32_t  id)
inline

◆ upload()

template<class Real >
TessellationView< Real > peclet::voro::upload ( const HostTessellation< Real > &  h)

Upload a HostTessellation to device Views.

Variable Documentation

◆ kBarrierDecay

constexpr double peclet::voro::kBarrierDecay = 0.7
constexpr

◆ kBoundaryFacet

constexpr int peclet::voro::kBoundaryFacet = -2
constexpr

Neighbour id stamped on a facet produced by an SDF cut (a wall). Distinct from the initial-cuboid boundary (-1); published as facetNbr < 0 either way.

◆ kCertificateTolerance

constexpr double peclet::voro::kCertificateTolerance = 1e-4
constexpr

Moving-point repair: the certificate tolerance and the Verlet skin, both as fractions of the mean spacing cbrt(V/N) (MovingTessellation::alloc takes the absolute values).

◆ kMaxPlanes

constexpr int peclet::voro::kMaxPlanes = 64
constexpr

ConvexCell capacity of the resident (moving-point) tessellation: planes and dual triangles (= primal vertices) per cell — the production layout and the topology store's strides (README "Early wall clip"). The plane cap must fit a byte (ConvexCell's static_assert).

◆ kMaxTriangles

constexpr int peclet::voro::kMaxTriangles = 112
constexpr

◆ kMaxWallPlanes

constexpr int peclet::voro::kMaxWallPlanes = 24
constexpr

Upper bound on the wall planes one SDF clip can commit: clipCellAgainstSdf runs at most maxCuts (24) iterations and each commits at most one plane.

◆ kOptimizerCgIters

constexpr int peclet::voro::kOptimizerCgIters = 300
constexpr

Mesh optimisers: the CG iteration cap of the Gauss–Newton solve, and the per-iteration decay of the pore-space optimiser's log-barrier weight.

◆ kPoreMaxPlanes

constexpr int peclet::voro::kPoreMaxPlanes = 128
constexpr

Capacity of the pore-space (SDF-walled interstitial) cell reconstruction: wall-cut cells carry more planes than a Poisson–Voronoi cell.

◆ kPoreMaxTriangles

constexpr int peclet::voro::kPoreMaxTriangles = 256
constexpr

◆ kSearchWindow

constexpr int peclet::voro::kSearchWindow = 4
constexpr

Gather window of the tessellator's counting-sort grid: blocks per axis around a seed (coverage = window · block size); the moving-point path and the cold build share it.

◆ kSkin

constexpr double peclet::voro::kSkin = 0.25
constexpr

◆ kWlOffBias

constexpr int peclet::voro::kWlOffBias = 128
constexpr

Bias added to each signed block offset (dx,dy,dz) so it packs into one int (8 bits per axis) in the worklist table — a single load + bit-unpack in the hot gather loop instead of three scattered loads. Block offsets stay within [-sw,sw], sw << 128.