|
peclet.voro 1.0.0
Device-native moving-particle Voronoi dynamics
|
#include <convex_cell.hpp>
Public Member Functions | |
| KOKKOS_INLINE_FUNCTION void | initBox (Real L0, Real L1, Real L2) |
| KOKKOS_INLINE_FUNCTION void | computeVertex (int t) |
| KOKKOS_INLINE_FUNCTION void | initBoxPlanes (Real L0, Real L1, Real L2) |
| template<class Policy = Voronoi> | |
| KOKKOS_INLINE_FUNCTION void | reevalGeometry (Real sx, Real sy, Real sz, const Real *pos, Real L, Real wSelf=Real(0), const Real *weight=nullptr) |
| KOKKOS_INLINE_FUNCTION bool | isSelfConsistent (Real tol) const |
| KOKKOS_INLINE_FUNCTION bool | isSelfConsistentPartners (Real tol, int *outPartners, int maxPartners, int &nPartners) const |
| KOKKOS_INLINE_FUNCTION int | oppositePlane (int s, int x, int y) const |
| KOKKOS_INLINE_FUNCTION void | computePoke4 (unsigned char *out) const |
| KOKKOS_INLINE_FUNCTION bool | isLocallyConvex (const unsigned char *poke4, Real tol) const |
| KOKKOS_INLINE_FUNCTION bool | isLocallyConvexPartners (const unsigned char *poke4, Real tol, int *outPartners, int maxPartners, int &nPartners) const |
| KOKKOS_INLINE_FUNCTION Real | maxVertexRsq () const |
| Largest squared dual-vertex radius over live triangles (drives the security radius). | |
| KOKKOS_INLINE_FUNCTION int | findSharing (int self, int x, int y) const |
| KOKKOS_INLINE_FUNCTION void | rebuildAdjacency () |
| KOKKOS_INLINE_FUNCTION bool | checkAdjacencyInvariant () const |
| KOKKOS_INLINE_FUNCTION int | allocTri () |
| KOKKOS_INLINE_FUNCTION bool | clip (const Real pdir[3], Real d, int nbr) |
| KOKKOS_INLINE_FUNCTION bool | empty () const |
| KOKKOS_INLINE_FUNCTION int | countFaces () const |
| KOKKOS_INLINE_FUNCTION int | faceOrdered (int k, Real fx[MAXFV], Real fy[MAXFV], Real fz[MAXFV]) const |
| KOKKOS_INLINE_FUNCTION int | sectionPolygon (const Real p0[3], const Real u[3], Real px[MAXSV], Real py[MAXSV], Real pz[MAXSV]) const |
| KOKKOS_INLINE_FUNCTION Real | volume () const |
| KOKKOS_INLINE_FUNCTION void | planeN (int k, Real out[3]) const |
| KOKKOS_INLINE_FUNCTION Real | volumePerVertex () const |
| KOKKOS_INLINE_FUNCTION void | facetAreasPerVertex (Real *area) const |
| KOKKOS_INLINE_FUNCTION void | facetMomentsPerVertex (Real *area, Real *mx, Real *my, Real *mz) const |
| KOKKOS_INLINE_FUNCTION void | geomVolumeGrad (Real &vol, Real *dgx, Real *dgy, Real *dgz) const |
| KOKKOS_INLINE_FUNCTION void | geomVolumeArea (Real &vol, Real *avx, Real *avy, Real *avz, Real *dgx, Real *dgy, Real *dgz) const |
| KOKKOS_INLINE_FUNCTION void | geomVolumeAreaGrad (int t, int pl[3], Real contrib[3], Real grad[3][3][3]) const |
| KOKKOS_INLINE_FUNCTION void | geomVolumeAreaGradAD (int t, int pl[3], Real contrib[3], Real grad[3][3][3]) const |
| KOKKOS_INLINE_FUNCTION void | geometryPerVertex (Real &vol, Real *area, Real *mx, Real *my, Real *mz) const |
| KOKKOS_INLINE_FUNCTION bool | facetGeometry (int k, Real areaVec[3], Real dv[3], Real conn[3]) const |
Static Public Member Functions | |
| static KOKKOS_INLINE_FUNCTION void | polyAreaVec (const Real fx[], const Real fy[], const Real fz[], int m, Real A[3]) |
| Polygon area vector (0.5 Σ vi × v(i+1)) of an ordered face. | |
| static KOKKOS_INLINE_FUNCTION void | xprod (const Real a[3], const Real b[3], Real o[3]) |
| static KOKKOS_INLINE_FUNCTION Real | dot3 (const Real a[3], const Real b[3]) |
| static KOKKOS_INLINE_FUNCTION Real | det3 (const Real a[3], const Real b[3], const Real c[3]) |
| static KOKKOS_INLINE_FUNCTION void | edgeFoot (const Real v[3], const Real ck[3], Real f[3]) |
| foot of the perpendicular from v onto the edge line of direction ck: v − (v·ck/ck·ck) ck. | |
| static KOKKOS_INLINE_FUNCTION void | scatterFacetMoment (int ki, const Real ni[3], const Real ff[3], const Real fl[3], const Real v[3], Real *area, Real *mx, Real *my, Real *mz) |
| static KOKKOS_INLINE_FUNCTION void | scatterGradRaw (int ki, const Real ni[3], const Real ff[3], const Real fl[3], const Real v[3], Real *dgx, Real *dgy, Real *dgz) |
| static KOKKOS_INLINE_FUNCTION void | scatterAreaMomentRaw (int ki, const Real ni[3], const Real ff[3], const Real fl[3], const Real v[3], Real *sa_acc, Real *smx, Real *smy, Real *smz) |
| static KOKKOS_INLINE_FUNCTION void | edgeCrossAdj (int j, int p, int q, const Real Nn[3][3], const Real w[3], Real out[3]) |
Public Attributes | |
| Real | n [MAXP][3] |
| Real | nn [MAXP] |
| cached n·n, i.e. the half-space offset (so the cull test is n·x <= nn) | |
| int | pnbr [MAXP] |
| neighbour seed id per plane (<0 => bounding box) | |
| int | np |
| number of planes | |
| unsigned char | t0 [MAXT] |
| unsigned char | t1 [MAXT] |
| unsigned char | t2 [MAXT] |
| triangle = triple of plane indices | |
| Real | vx [MAXT] |
| Real | vy [MAXT] |
| Real | vz [MAXT] |
| cached dual-vertex position per triangle | |
| bool | alive [MAXT] |
| triangle live flag | |
| int | nt |
| triangle high-water mark | |
| bool | overflow |
| set if MAXP/MAXT exceeded -> cell invalid, caller falls back | |
| Kokkos::Array< int,(TrackAdj ? MAXT :0) *3 > | adj |
Static Public Attributes | |
| static constexpr bool | kTrackAdj |
| lets templated consumers (store save/load) branch at compile time | |
| static constexpr int | MAXFV = 28 |
| static constexpr int | MAXSV = 2 * MAXFV |
| max vertices on a cross-section polygon | |
Compact convex Voronoi cell. MAXP planes (<=255 so a plane index fits in a byte), MAXT dual triangles (= primal vertices). Trivially default-constructible (POD) so it lives in registers / a per-thread stack.
|
inline |
|
inline |
DEBUG oracle: true iff adj is internally consistent for all live triangles (every entry points to a live triangle that actually shares the edge, and the back-link is symmetric). Every incremental stitch in clip must leave this true; assert it after each clip in debug builds. Trivially true when !TrackAdj.
|
inline |
Add a plane for neighbour nbr and clip the cell by it. The plane is passed in (direction, offset) form {x : pdir·x <= d}; it is stored internally as its foot-point normal nf = (d/|pdir|²)·pdir (so {x : nf·x <= nf·nf} is the same half-space). Returns true if the cell was modified. The plane is only committed if it actually cuts (so redundant candidates don't grow np).
|
inline |
Compute the packed per-triangle "poke4" plane set the local certificate reads: for each live triangle, out[t*4 + 0..2] = the three edge-opposite planes (from adj, no findSharing) and out[t*4 + 3] = the dual Delaunay tet's FOURTH face (the one not incident to the seed) — the non-defining, non-edge-opposite plane the vertex is nearest to from inside (smallest positive slack). 0xff = none. Including the fourth face makes the local cert match the brute flag set (complete, not a subset). Dead triangles get all-0xff. Requires adj populated + the cached vertices; call once after the cell is finalised (gather / rebuild) and persist out — the cert then reads it directly each re-eval step, with NO per-vertex adj derivation.
|
inline |
Compute and cache the dual vertex of triangle t (where its three planes meet, Cramer's rule). Called once when a triangle is created; all later reads use the cache (vx/vy/vz), so the per-cell vertex solves are O(#triangles), not O(#clips · #triangles) — the difference between compute-bound and not.
|
inline |
|
inlinestatic |
|
inlinestatic |
|
inlinestatic |
Adjoint of a cross-product edge direction: (∂(N[p]×N[q])/∂n_j)^T w. Used by the analytic geomVolumeAreaGrad.
|
inlinestatic |
foot of the perpendicular from v onto the edge line of direction ck: v − (v·ck/ck·ck) ck.
|
inline |
|
inline |
Gather face k's vertices (the alive dual triangles containing plane k) and order them CCW around the face normal (insertion sort by in-plane angle). Returns the count, or <3 if k is not a (≥triangle) face. Shared by volume() and facetGeometry() — the G0/G1/G2 geometry tiers all start here.
|
inline |
Per-facet areas by the same vertex-local scatter (area[k] zeroed by caller, size np). Each vertex scatters into its 3 incident facets; |n_i| is the only sqrt (per facet). Order/adjacency-free.
|
inline |
Per-facet physics geometry (G2 tier) for plane k: the outward face area VECTOR, the volume gradient dV = ∂V/∂r_k, and the connecting vector r_k (= the plane normal). Matches the half-edge facetArea / facetConnect / facetConnVec. Returns false if k is not a face.
Derivation of dV: the cell is { r_k·x ≤ ½|r_k|² }. Perturbing r_k → r_k+δ moves a point x on face k off the plane by δ·(x−r_k); the outward normal displacement is −δ·(x−r_k)/|r_k|, so δV = ∫_face (−δ·(x−r_k)/|r_k|) dA = (area/|r_k|) δ·(r_k − c_k), with c_k the face centroid. Holding all other planes fixed, this is first-order exact ⇒ dV = ∂V/∂r_k = (area/|r_k|)·(r_k − c_k).
|
inline |
Per-facet area + first moment ∫x dA by the same vertex-local scatter (caller zeroes the np-sized arrays). The area-weighted facet centroid is c_k = (mx,my,mz)[k]/area[k]; the volume gradient (force) is then dV_k = ∂V/∂r_k = (area_k/|r_k|)(r_k − c_k) with connector r_k = 2·n[k] — sort/adjacency-free.
|
inline |
Find a live triangle != self that contains both plane indices x and y. In a valid triangulation an interior edge is shared by exactly two triangles. Dead triangles (alive==false) keep stale plane indices, so they MUST be skipped or they create phantom horizon edges (the cascade bug). During a clip the about-to-be-removed triangles are still alive==true (removed only after horizon collection), so they are correctly considered here and rejected by the caller's kill[] test.
|
inline |
MERGED vertex-local geometry: cell volume + per-facet area + per-facet first moment ∫x dA, all in ONE pass (shares n,c,D,v,feet per vertex). The production G1+G2 kernel — sort-free, adjacency-free. Caller zeroes the np-sized arrays. With connector r_k = 2·n[k] (so |r_k| = 2·sqrt(nn[k])), derive per facet k: areaVec_k = area[k] · r_k/|r_k| = area[k] · n[k]/|n[k]| (outward, toward the neighbour) centroid_k = (mx,my,mz)[k]/area[k] force dV_k = (area[k]/|r_k|)·(r_k − centroid_k)
|
inline |
geomVolumeArea tier (Phase 2): cell volume + the outward area-VECTOR A_k·n_k/|n_k| AND the volume gradient dV/dn_k per plane — the full G2 physics set (areas for fluxes/momentum, gradient for force). Like geomVolumeGrad it is fully SQRT-FREE: both outputs are |n|²-normalized — areaVec_k = S_a·n_k/(2·nn[k]) and dV/dn_k = (2·S_a·n_k − S_m)/(2·nn[k]) — with the raw S_a (=2|n_k|·A_k) and S_m (=2|n_k|·m_k) scattered per vertex. No extra scratch: during the scatter avx holds S_a and (dgx,dgy,dgz) hold S_m; the per-facet fold overwrites them in place (so the compact-cell stack stays at the 6 caller arrays). Caller zeroes all six. The facet centroid, if wanted, is c_k = S_m/S_a (also sqrt-free) — derivable but not exposed here. Matches facetGeometry's areaVec/dv to round-off.
|
inline |
geomFull primitive: the per-dual-triangle ("subtetrahedron") area-Jacobian block — the building block of the FULL coupled dA_k/dn_l (the OT/power-diagram Hessian), with NO ordering and NO adjacency. ANALYTIC, no-recompute version: it reuses the CACHED vertex v and computes the per-triangle intermediates (edge directions, feet) once in Real, then forms the derivatives in closed form. The vertex derivative is the rank-1 ∂v/∂n_j = (c_j/D)(2n_j − v)^T (c_j the cofactor, D the determinant); the area numerator N_i=det3(n_i,g_i,v) is differentiated trilinearly (∂/∂n_i = g_i×v, ∂/∂g via the foot adjoints, ∂/∂v via the rank-1 above), and the 1/(2|n_i|) factor adds the −δ_ij A_i n_i/nn_i term. Outputs: pl[3] = the (canonically ordered) plane indices; contrib[3] = the area contributions (Σ over triangles reproduces facetAreasPerVertex's area[k]); grad[i][j][c] = ∂contrib_i/∂n_{pl[j]}[c]. Consumer gathers A_{pl[i]} += contrib[i], dA_{pl[i]}/dn_{pl[j]} += grad[i][j], in any order.
|
inline |
Reference (forward-AD) implementation of the per-triangle area-Jacobian, kept only as the machine-precision ORACLE for the analytic geomVolumeAreaGrad (it recomputes everything in dual arithmetic, including the vertex — the redundancy the analytic version removes). Same outputs as geomVolumeAreaGrad.
|
inline |
geomVolumeGrad tier (Phase 2): cell volume + the volume gradient dV/dn_k per plane, with NO area/ centroid arrays exposed, NO sqrt anywhere, and only the 3 output arrays touched (so it keeps the compact cell's GPU occupancy). dV/dn_k = (2·A_k·n_k − m_k)/|n_k|; scattering the raw numerator 2·S_a·n_k − S_m per vertex (S_a = 2|n_k|·A_k, S_m = 2|n_k|·m_k), the per-facet fold is dV/dn_k = (numerator)/(2·nn[k]) — the |n_k| cancels into the stored nn=|n|². Caller zeroes the np-sized dgx/dgy/dgz (accumulate the numerator, then overwritten in place by the fold). Matches geometryPerVertex's closed form to round-off. Voronoi position force dV/dr_k = ½·(dgx,dgy,dgz)[k]; the policy layer (Phase 3) owns that chain.
|
inline |
Seed the cell with the big cuboid of extent (L0,L1,L2) centred on the seed. Planes 0:+x 1:-x 2:+y 3:-y 4:+z 5:-z; the 8 corners are the dual triangles.
|
inline |
Set ONLY the six bounding-box planes (0:+x 1:-x 2:+y 3:-y 4:+z 5:-z), np=6, no triangles. Used to rebuild a cell from a compact stored topology: the caller then overwrites np/nt and the triangle structure and calls reevalGeometry() (which fills the neighbour planes + all vertices).
|
inline |
Local convexity certificate (Lawson), O(nt). Per dual vertex, test it against its four precomputed poke4 planes (the three edge-opposite + the fourth-face plane): the cell is locally Voronoi iff no vertex pokes past any of them. With the fourth face included this matches the brute certificate's flag set (Delaunay's lemma over the full dual tet), so it is complete, not a subset. Reads the planes from poke4 (no adj), so it runs on ANY cell — the cert path keeps a lean cell + this persisted table.
|
inline |
Partner-emitting form of isLocallyConvex — same poke4 test, additionally emitting the violated-plane partner seed(s) (the pnbr id of each plane a vertex pokes past), deduplicated into outPartners. These are the gaining cells of a flip (the §1 repair signal) so the gather repair seeds Pass 1 from them.
|
inline |
Part II detection (D2 — the "convexity"/self-consistency certificate). After a re-eval on the FIXED stored topology, the cell is the intersection of its half-spaces ONLY if every dual vertex still lies inside every OTHER plane of the cell: n_k·v ≤ nn_k. If some vertex pokes out past a plane k (by more than tol, an absolute distance), that plane should have cut it ⇒ the stored topology is stale (a face was lost / an internal flip happened) ⇒ this cell needs a topology rebuild. This is purely cell-local (no neighbour data): it catches LOST faces directly. A GAINED face (an external seed that has moved close enough to cut this cell) is NOT visible here — the conjecture (to be tested empirically) is that such an event makes the PARTNER cell self-inconsistent, so a global sweep of this test still flags it. Exception: an SDF/boundary plane has no partner cell, so boundary cells need a separate boundary watch.
|
inline |
Part-II repair signal (Phase 1): the convexity/in-sphere certificate above, additionally emitting the violated-plane partner seed(s) — the pnbr id of each stored plane k a re-evaluated vertex pokes past. By the §1 analysis (dynamic_update_decision_and_plan.md) these partners are exactly the gaining cells of a 2→3 flip (cells i,m that never flag themselves), so they are the cheap, local, connectivity-free signal that reaches them — necessary for a complete one-pass repair. Partners are deduplicated into outPartners[0..nPartners) (capped at maxPartners; the rare overflow just truncates — the periodic oracle is the backstop). A violated plane with pnbr<0 (box/SDF wall) has no partner cell: it still marks the cell inconsistent (so the cell itself is rebuilt) but emits no partner — the SDF boundary-contact trigger (Risk 1d) is the deferred complement that catches gained wall faces. Returns true iff the cell is self-consistent (no violation past tol).
WEIGHTED/POWER (deferred, see [[vorflow-power-cells-deferred]]): for a Laguerre cell the in-sphere test n_k·v ≤ nn_k must become the empty-**orthosphere** (power-distance) predicate so completeness carries to the regular triangulation. The ConvexCell device path is Voronoi-only today (no radical-plane geometry), so only the unweighted form is implemented; the orthosphere form plugs in here when the Power policy lands.
|
inline |
Largest squared dual-vertex radius over live triangles (drives the security radius).
|
inline |
Edge-opposite plane of the triangle s across shared edge {x,y}: the one vertex (plane index) of s that is neither x nor y. Helper for the Lawson local certificate.
|
inline |
Foot-point normal of plane k — now stored directly, so just a copy (the reconstruction divide is gone).
|
inlinestatic |
Polygon area vector (0.5 Σ vi × v(i+1)) of an ordered face.
|
inline |
Brute O(nt²) rebuild of the edge-adjacency table from triangle topology (via findSharing). Bootstrap (initBox) + fallback only, never in the hot path. No-op when !TrackAdj.
|
inline |
Part II (moving points): re-evaluate this cell's geometry IN PLACE after the seeds moved, REUSING the resident topology (the surviving plane set pnbr + the dual-triangle structure t0/t1/t2/alive). No gather, no clip: each neighbour plane is rebuilt from the neighbour's new position (box planes pnbr<0 are fixed), then every live vertex is recomputed. Correct exactly when the topology is unchanged (the common case for small per-step displacement); a topology flip must be detected + repaired separately (Phase 1.5). pos is the global seed array (x- fastest, 3*N); L the periodic box length for min-imaging.
Policy = Voronoi (default) rebuilds the bisector foot point n = ½r (byte-identical to the historical path). Policy = Power rebuilds the radical foot point n = α r with offset d = ½(|r|²+w_self−w_nbr); pass the cell's own weight wSelf and the global weight array (indexed by pnbr[k]). weight may be null for Voronoi.
|
inlinestatic |
Scatter one facet's RAW area S_a (=Σdet3) and RAW first moment S_m (=Σdet3·centroid_tri) AT a vertex — scatterFacetMoment without the 1/(2|n|) factor (so NO sqrt). geomVolumeArea defers the shared 1/(2|n|) to its per-facet fold, where it cancels against |n| for the area-vector and the gradient.
|
inlinestatic |
Scatter one facet's area + first moment (∫x dA) at a vertex into the per-facet accumulators. Facet i's local boundary at v is the path f_first → v → f_last with apex n_i: two signed triangles (n_i,f_first,v) and (n_i,v,f_last). |n_i| is the one sqrt (per facet).
|
inlinestatic |
Scatter one facet's contribution to the volume-gradient NUMERATOR 2·S_a·n_k − S_m AT a vertex, with NO sqrt and into just the 3 output arrays. The trick: n_k is the SAME normal (= ni) at every vertex of facet k, so the per-vertex term 2·da·ni − mom already carries the facet normal; summed over the facet's vertices it is exactly 2·(Σda)·n_k − Σmom = 2·S_a·n_k − S_m. da, mom are RAW (no 1/(2|n|) factor); geomVolumeGrad's fold supplies the shared 1/(2·nn[k]) once per facet (also sqrt-free).
|
inline |
Cross-section of the cell by the plane {x : (x - p0)·u = 0}: the convex polygon the plane cuts out. Enumerates the cell's primal EDGES straight from the dual triangles — an edge is a pair of alive triangles sharing exactly two planes (each edge is then their two endpoints, found exactly once) — and collects the point where each edge crosses the plane, then orders the crossings CCW in the plane (same in-plane basis + diamond pseudo-angle as faceOrdered). This never relies on face watertightness, so it tiles a cross-section exactly where a face-by-face slice drops facets. Coordinates are in the cell's own frame (dual-vertex frame, i.e. seed-relative). Returns the vertex count m (0 or <3 if the plane misses/grazes the cell; -1 on MAXSV overflow — caller skips).
|
inline |
Cell volume (G1): V = (1/3) Σ_faces support_k · area_k. Seed (origin) is interior so every support distance is positive.
|
inline |
Cell volume (G1) by the vertex-local flag/divergence sum — NO ordering, NO adjacency, NO atan2, NO findSharing. One pass over vertices; each contributes 3 signed determinants.
|
inlinestatic |
| Kokkos::Array<int, (TrackAdj ? MAXT : 0) * 3> peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::adj |
Per-triangle edge adjacency, maintained incrementally in clip when TrackAdj — the input to the O(nt) Lawson local-convexity certificate (isLocallyConvex). Zero-footprint when !TrackAdj (Kokkos::Array<int,0> is the intended empty case, so sizeof(ConvexCell<...,false>) is unchanged). adj[t*3 + e] = index of the live triangle sharing edge-slot e of triangle t. Edge-slot convention (must match findSharing / fan enumeration): slot 0 = edge {vtx0, vtx1}, slot 1 = edge {vtx1, vtx2}, slot 2 = edge {vtx2, vtx0}, where (vtx0,vtx1,vtx2) = (t0[t], t1[t], t2[t]). The cell surface is a closed triangulation (topological sphere), so every edge is shared by exactly two live triangles; adj entries for live triangles are never -1 in a valid state. Killed triangles keep stale adj (they are alive==false, so the oracle ignores them and clip never follows into them).
| bool peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::alive[MAXT] |
triangle live flag
|
staticconstexpr |
lets templated consumers (store save/load) branch at compile time
|
staticconstexpr |
|
staticconstexpr |
max vertices on a cross-section polygon
| Real peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::n[MAXP][3] |
foot-point normal of each plane: half-space {x : n·x <= n·n}, so x=n is the foot of the perpendicular from the seed (origin) and |n| the seed->plane dist (= ½·(neighbour rel-pos) for Voronoi; the connector r = 2n).
| Real peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::nn[MAXP] |
cached n·n, i.e. the half-space offset (so the cull test is n·x <= nn)
| int peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::np |
number of planes
| int peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::nt |
triangle high-water mark
| bool peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::overflow |
set if MAXP/MAXT exceeded -> cell invalid, caller falls back
| int peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::pnbr[MAXP] |
neighbour seed id per plane (<0 => bounding box)
| unsigned char peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::t0[MAXT] |
| unsigned char peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::t1[MAXT] |
| unsigned char peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::t2[MAXT] |
triangle = triple of plane indices
| Real peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::vx[MAXT] |
| Real peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::vy[MAXT] |
| Real peclet::voro::ConvexCell< Real, MAXP, MAXT, TrackAdj >::vz[MAXT] |
cached dual-vertex position per triangle