|
peclet-dem 0.4.0
Performance-portable XPBD Discrete Element Method (Kokkos + ArborX)
|
Namespaces | |
| namespace | detail |
| namespace | mldetail |
Classes | |
| struct | ContactC |
| Portable mirror of ParticleSystem.cuh ContactConstraint (the fields this reduction touches). More... | |
| struct | ContactHierarchy |
| Host-side description of one built hierarchy (offsets into the packed group pools). More... | |
| struct | CudaIterGraph |
| struct | Domain |
| struct | F3 |
| struct | F4 |
| struct | FusedLoopSpec |
| Device-side iteration loop: run up to maxIters sweeps of the colour classes inside ONE kernel, evaluating the adaptive stop on-device (the same residual the host loop read back between launches — the readback round trip and the CUDA-graph capture disappear entirely). More... | |
| struct | FusedSweepCtx |
| Device-side context for a fused colour sweep: the colour offsets (numColors+1, uploaded from buildColorBucketsKokkos's host vector), the barrier counter, and the largest colour bucket (grid sizing). More... | |
| struct | HertzMindlinLaw |
| Hertz–Mindlin force-law policy (the first force law; see file comment). More... | |
| struct | KE2 |
| Berendsen thermostat: reduce translational + rotational KE over real particles, compute the two scaling factors, and rescale linear/angular velocities. More... | |
| struct | ManifoldC |
| Portable mirror of ManifoldConstraint. More... | |
| struct | MlCoarseSweep |
| The per-manifold coarse-PGS body (translation-only, e = 0, shared fine accumulator) lives in MlCoarseSweep so the per-colour launch loop and the fused whole-cycle kernel share it verbatim. More... | |
| struct | MlFusedCtx |
| Fused-coarse-cycle context: flat per-level colour offsets on device + barrier + meta. More... | |
| struct | MlFusedMeta |
| Host-POD description of a built hierarchy for the fused coarse-cycle kernel (fixed-size arrays: kernel argument by value). More... | |
| struct | MlScratch |
| Device scratch for the multilevel pass, sized once (see Particles::allocate). More... | |
| struct | Particles |
| struct | PGSManifoldSweep |
| One full colored PGS sweep. More... | |
| struct | PlaneP |
| struct | PositionContactSweep |
| The per-contact overlap-projection body lives in PositionContactSweep so the colored launch loop and the fused colour sweep (solver_fused.hpp) share it verbatim: solveOne(idx) must only run concurrently on contacts that are body-disjoint within one launch (a colour class). More... | |
| struct | ShapeDesc |
| Portable mirror of ShapeDescriptor (analytic fields + a flat-array point shell). More... | |
| class | Simulation |
| Host-facing facade with std::vector setters/getters (binding-agnostic). More... | |
| struct | SoloForceHooks |
| Single-GPU hooks: no ghosts, reductions are already global. Everything inlines away. More... | |
| struct | SoloSolveHooks |
| Single-GPU hooks: no ghost refresh, residuals are already global. Everything inlines away. More... | |
| struct | WallSdf |
| Static, world-space SDF container/geometry the particles collide against (a drum barrel, a hopper, a vibrating tray, ...). More... | |
Typedefs | |
| using | BpExec = Kokkos::DefaultExecutionSpace |
| using | BpMem = BpExec::memory_space |
| using | CpExec = Kokkos::DefaultExecutionSpace |
| using | CpMem = CpExec::memory_space |
| using | V3 = Kokkos::View< float *[3], CpMem > |
| using | V4 = Kokkos::View< float *[4], CpMem > |
| using | Vf = Kokkos::View< float *, CpMem > |
| using | Vi = Kokkos::View< int *, CpMem > |
| using | PairTableView = Kokkos::View< const float *, CpMem > |
| using | MatIdView = Kokkos::View< const unsigned char *, CpMem > |
| using | PosView = Kokkos::View< const float *[3], CpMem > |
| using | QuatView = Kokkos::View< const float *[4], CpMem > |
| using | ScalarF = Kokkos::View< const float *, CpMem > |
| using | ScalarI = Kokkos::View< const int *, CpMem > |
| using | ShellView = Kokkos::View< const float *[3], CpMem > |
| using | GridView = Kokkos::View< const float *, CpMem > |
| using | FrManifoldCounts = Kokkos::View< float *[2], CpMem > |
Enumerations | |
| enum | ShapeKind { SHAPE_GRID_SDF = 0 , SPHERE = 1 , HOLLOW_CYLINDER = 2 , BOX = 3 } |
Functions | |
| template<class PosV , class RadV , class PairsV , class CountV > | |
| int | findCollisionsArborX (PosV pos, RadV rad, int numParticles, int numReal, float margin, PairsV outPairs, CountV outCount, float boxCap=0.0f) |
| Emit candidate collision pairs (i<j) for real particles into outPairs/outCount. | |
| unsigned long long | pairKeyOf (const ManifoldC &m, Kokkos::View< const int *, CpMem > realIdx) |
| Persistent-contact detection for the gravity-gated restitution rule. | |
| void | markPersistentManifoldsKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const int *, CpMem > keyIdx, Kokkos::View< const unsigned long long *, CpMem > prevKeys, int prevCount, Kokkos::View< unsigned long long *, CpMem > outKeys, Kokkos::View< unsigned char *, CpMem > outFlags) |
keyIdx maps a body slot to the identity the pair key is built from: the REAL index map on the single-GPU path (stable within a run), or the GLOBAL particle id under MPI (stable across ranks, halo rebuilds and ownership migration — local slots are neither). | |
| void | gatherWarmLambdaKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const int *, CpMem > keyIdx, Kokkos::View< const unsigned long long *, CpMem > prevKeys, Kokkos::View< const float *, CpMem > prevLambda, Kokkos::View< const float *[3], CpMem > prevLambdaT, Kokkos::View< const float *, CpMem > prevPosImpulse, Kokkos::View< const float *, CpMem > prevRestBank, Kokkos::View< const float *, CpMem > prevRestVPeak, int prevCount, Kokkos::View< unsigned long long *, CpMem > outKeys, Kokkos::View< float *, CpMem > outWarm, Kokkos::View< float *[3], CpMem > outWarmT, Kokkos::View< float *, CpMem > outPosImpulse, Kokkos::View< float *, CpMem > outRestBank, Kokkos::View< float *, CpMem > outRestVPeak, Kokkos::View< unsigned char *, CpMem > outMatched={}) |
| Warm-start gather for the PGS velocity solve: per manifold, write its pair key and look up the previous substep's converged push impulse (0 for a new contact). | |
| void | commitPairKeysLambdaKokkos (Kokkos::View< const unsigned long long *, CpMem > keys, Kokkos::View< const float *, CpMem > lambda, Kokkos::View< const float *[3], CpMem > lambdaT, Kokkos::View< const float *, CpMem > restBank, Kokkos::View< const float *, CpMem > restVPeak, Kokkos::View< unsigned long long *, CpMem > prevKeys, Kokkos::View< float *, CpMem > prevLambda, Kokkos::View< float *[3], CpMem > prevLambdaT, Kokkos::View< float *, CpMem > prevRestBank, Kokkos::View< float *, CpMem > prevRestVPeak, Kokkos::View< int *, CpMem > perm, int numManifolds, Kokkos::View< const int *, CpMem > color={}, Kokkos::View< int *, CpMem > prevColor={}) |
| Save this substep's keys + converged impulses (normal AND tangential) and key-sort them for next substep's gather. | |
| void | commitPairKeysKokkos (Kokkos::View< const unsigned long long *, CpMem > keys, Kokkos::View< unsigned long long *, CpMem > prevKeys, int numManifolds) |
| Copy this substep's keys into prevKeys and sort them for next substep's binary search. | |
| void | updateGroundedLevelsKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const float *[3], CpMem > posPred, F3 gHat, Kokkos::View< unsigned char *, CpMem > grounded, int numReal, int sweeps, int decay) |
Guendelman support levels, warm-started: decay every body's level by decay, re-seed 255 at wall/plane contacts, then sweeps monotone propagation passes lower -> upper (255 -> 254 -> ...) through the manifold graph. | |
| void | computeHeightLevelsKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const float *[3], CpMem > posPred, F3 gHat, Kokkos::View< int *, CpMem > heights, int numReal) |
| void | buildColorBucketsKokkos (Kokkos::View< const int *, CpMem > colorOf, int n, int numColors, Kokkos::View< int *, CpMem > perm, Kokkos::View< int *, CpMem > cursor, std::vector< int > &offs) |
| Dense colour buckets (numColors <= 64): perm[offs[c] . | |
| long long | colorKey (int idx) |
| splitmix32 finalizer: a well-mixed pseudo-random priority per edge index. | |
| std::uint64_t | pairKey (const ContactC &c) |
| Canonical pair key: (min<<32)|max, or (idA<<32)|0xFFFFFFFF for a boundary (idB<0) contact. | |
| void | decodeKey (std::uint64_t key, int &bodyA, int &bodyB) |
| Decode the canonical (bodyA, bodyB) from a pair key (bodyB = -1 for boundary). | |
| ManifoldC | transformContact (const ContactC &c) |
| Per-contact transform to a single-point manifold, aligned to the canonical pair. | |
| int | reduceContactsToManifoldsKokkos (Kokkos::View< const ContactC *, CpMem > contacts, int n, Kokkos::View< ManifoldC *, CpMem > outManifolds, Kokkos::View< int, CpMem > outCount, Kokkos::View< int *, CpMem > contactSlot={}) |
Reduce n contacts to manifolds (one per unique canonical pair). | |
| void | frictionBoundFromLambdaKokkos (Kokkos::View< ContactC *, CpMem > contacts, int numContacts, Kokkos::View< const int *, CpMem > contactSlot, Kokkos::View< const ManifoldC *, CpMem > manifolds, Kokkos::View< const float *, CpMem > lambdaAcc) |
| PGS friction bound: overwrite each contact's friction_lambda_n with its manifold's converged PGS push impulse (lambdaAcc, shared equally over the manifold's contact points). | |
| void | commitPosImpulseKokkos (Kokkos::View< const float *, CpMem > posLambdaContact, int numContacts, Kokkos::View< const int *, CpMem > contactSlot, Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const unsigned long long *, CpMem > keys, Kokkos::View< const unsigned long long *, CpMem > prevKeysSorted, int prevCount, float dt, Kokkos::View< float *, CpMem > scratchManifold, Kokkos::View< float *, CpMem > prevPosImpulse) |
| After the position solve: convert the per-contact positional lambdas into an impulse- equivalent per manifold (lambda_pos / dt has force units; x dt back to impulse => just lambda_pos * m_eff... the positional lambda already carries 1/w mass weighting, so the impulse equivalent over the substep is lambda_pos / dt * dt = lambda_pos / (w*...) – we store lambda_pos/dt * dt = lambda_pos scaled by 1/dt to velocity-impulse units) and write it into the sorted prev-store so next substep's warm gather can top up the Coulomb bound. | |
| F3 | add3 (F3 a, F3 b) |
| F3 | sub3 (F3 a, F3 b) |
| F3 | scale3 (F3 a, float s) |
| float | dot3 (F3 a, F3 b) |
| float | len3 (F3 v) |
| F3 | cross3v (F3 a, F3 b) |
| F4 | cross3 (F4 a, F4 b) |
| template<class V > | |
| F3 | ldF3 (const V &v, int i) |
| template<class V > | |
| F4 | ldF4 (const V &v, int i) |
| F3 | rotateVector (F4 q, F3 v) |
| F3 | invRotateVector (F4 q, F3 v) |
| F4 | quatInverse (F4 q) |
| F4 | quatMult (F4 a, F4 b) |
| float | sdfSphere (F3 p, F4 params) |
| float | sdfHollowCylinder (F3 p, F4 params) |
| float | sdfBox (F3 p, F4 params) |
| float | sdfEval (F3 p, int type, F4 params) |
| void | predictVelocityKokkos (int n, V3 pos, Vf invMass, V3 vel, V4 quat, V3 angVel, V3 invInertia, V3 posPred, V4 quatPred, V3 velPred, V3 angVelPred, V3 deltaPos, V4 deltaQuat, V3 deltaVel, V3 deltaAngVel, Vi constraintCounts, F3 gravity, float dt, V3 extForce) |
| Predict velocity (gravity + gyroscopic precession), speculative position, and clear all deltas. | |
| void | applyVelocityDeltasKokkos (int n, V3 velPred, V3 angVelPred, V3 deltaVel, V3 deltaAngVel) |
| Add accumulated velocity/angular deltas onto the predicted velocity, then clear the delta buffers. | |
| void | applyVelocityAndPredictPositionKokkos (int n, V3 pos, Vf invMass, V3 vel, V4 quat, V3 velPred, V3 angVelPred, V3 posPred, V4 quatPred, V3 angVel, float dt) |
| Re-integration: persist solved velocity, trapezoidal position predict, quaternion integrate. | |
| void | computeContactCountsKokkos (Kokkos::View< const ContactC *, CpMem > contacts, int numContacts, Vi constraintCounts) |
| Per-contact constraint-count pre-pass (active contacts, dist <= 0). | |
| void | applyUpdatesKokkos (int n, V3 posPred, V3 velPred, V3 deltaPos, V3 deltaVel, Vi constraintCounts) |
| Jacobi count-averaged apply of position/velocity deltas, then clear deltas + counts. | |
| void | finalCommitKokkos (int n, V3 pos, Vf invMass, V3 posPred, V4 quat, V4 quatPred, Domain dom) |
| Final commit: periodic wrap of the predicted position into the domain, commit position + quat. | |
| void | applyThermostatKokkos (int numReal, V3 vel, Vf invMass, V3 angVel, V3 invInertia, V4 quat, double kB, double tau, double Ttarget, float dt) |
| void | updateGrowthScalesKokkos (int n, Vf scale, Vf targetScale, float factor) |
| Growth mode: scale = target * factor (when active). | |
| void | writeLammpsDump (const std::string &filename, int step, const std::vector< float > &pos, const std::vector< float > &vel, const std::vector< float > &quat, const std::vector< float > &radii, const float *boxMin, const float *boxMax, bool pbcEnabled) |
| void | writeSdfVti (const std::string &filename, const std::vector< float > &grid, int rx, int ry, int rz, const float *minB, const float *maxB) |
| F3 | loadF3 (PosView v, int i) |
| F4 | loadF4 (QuatView v, int i) |
| float | sampleGridSdf (F3 p, const ShapeDesc &d, GridView grid) |
Trilinearly sample an imported grid SDF at canonical point p. | |
| float | sampleWallSdf (F3 p, const WallSdf &w, GridView grid) |
Trilinearly sample a static world-space wall SDF at world point p. | |
| float | sdfEvalShape (F3 p, const ShapeDesc &d, GridView grid) |
| Canonical-space SDF of a shape: analytic dispatch, or a trilinear grid sample for an imported grid SDF. | |
| void | detectContactsKokkos (Kokkos::View< const int *[2], CpMem > pairs, int numPairs, PosView pos, QuatView quat, ScalarF scale, ScalarI shapeId, Kokkos::View< const ShapeDesc *, CpMem > shapes, ShellView shell, float globalScale, float margin, Kokkos::View< ContactC *, CpMem > outContacts, Kokkos::View< int, CpMem > outCount, Kokkos::View< float, CpMem > maxOverlap, GridView sdfGrid=GridView{}, MatIdView matId=MatIdView{}, PairTableView pairTable=PairTableView{}) |
| Pair point-shell vs SDF contacts. | |
| void | detectWallSdfKokkos (int numReal, int numWalls, PosView pos, QuatView quat, ScalarF scale, ScalarI shapeId, Kokkos::View< const ShapeDesc *, CpMem > shapes, ShellView shell, Kokkos::View< const WallSdf *, CpMem > walls, GridView wallGrid, float globalScale, float margin, Kokkos::View< ContactC *, CpMem > outContacts, Kokkos::View< int, CpMem > outCount, Kokkos::View< float, CpMem > maxOverlap, MatIdView matId=MatIdView{}, PairTableView pairTable=PairTableView{}) |
| Per-real-particle contacts against a static world-space wall SDF set (a drum barrel, hopper, vibrating tray, ...). | |
| void | detectBoundaryKokkos (int numReal, int numPlanes, PosView pos, QuatView quat, ScalarF scale, ScalarI shapeId, Kokkos::View< const ShapeDesc *, CpMem > shapes, ShellView shell, Kokkos::View< const PlaneP *, CpMem > planes, float globalScale, float margin, Kokkos::View< ContactC *, CpMem > outContacts, Kokkos::View< int, CpMem > outCount, Kokkos::View< float, CpMem > maxOverlap) |
| Per-real-particle contacts against explicit planes (point-shell shapes test each surface point; analytic spheres use centre-minus-radius). | |
| std::vector< float > | generateSdfKokkos (int rx, int ry, int rz, F3 dmin, F3 dmax, int numReal, PosView pos, QuatView quat, ScalarF scale, ScalarI shapeId, Kokkos::View< const ShapeDesc *, CpMem > shapes, bool px, bool py, bool pz, GridView sdfGrid=GridView{}) |
| int | calculateGhostCapacity (int nReal, Domain dom, float skin) |
| Padded particle-array capacity that leaves room for the periodic ghosts generateGhostsKokkos will emit: the real count plus an estimate of the boundary-shell ghost population, gated on which axes are actually periodic. | |
| void | generateGhostsKokkos (int numReal, int capacity, Domain dom, float skin, V3 pos, Vf invMass, V3 posPred, V3 vel, V3 velPred, V4 quat, V4 quatPred, V3 angVel, V3 angVelPred, Vf scale, Vi shapeId, Vi realIndices, Kokkos::View< int, CpMem > topGhost, Vi gid=Vi{}, Kokkos::View< unsigned char *, CpMem > materialId={}) |
| Generate periodic ghosts for particles [0,numReal). | |
| std::vector< F3 > | genCylinderShell (float radius, float height, float thickness, float spacing) |
| std::vector< F3 > | genBoxShell (float hx, float hy, float hz, float spacing) |
| void | demStep (Particles &P) |
| One full XPBD DEM substep over the particle SoA (mirrors simulation.cpp Simulation::step()). | |
| float | computeOverlapsKokkos (Particles &P) |
| Max pair interpenetration on the committed state (faithful to CUDA Simulation::compute_overlaps): copy committed pos/quat into the predicted buffers, regenerate the periodic ghosts from that state, then run the same broad/narrow phase as demStep and return the recorded max overlap. | |
| void | freezeAsleepKokkos (int numReal, Kokkos::View< const unsigned char *, CpMem > asleep, Kokkos::View< const float *[3], CpMem > pos, Kokkos::View< const float *[4], CpMem > quat, Kokkos::View< float *[3], CpMem > posPred, Kokkos::View< float *[4], CpMem > quatPred, Kokkos::View< float *[3], CpMem > velPred, Kokkos::View< float *[3], CpMem > angVelPred) |
| After predictVelocity: re-freeze the currently-asleep bodies so gravity/prediction do not move them — velPred = angVelPred = 0, posPred = pos, quatPred = quat. | |
| void | buildInvMassEffKokkos (int numBodies, Kokkos::View< const unsigned char *, CpMem > asleep, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< float *, CpMem > invMassEff, float sleeperFrac) |
| Effective inverse mass for the solve: a sleeping body (real, or a periodic ghost whose real is asleep) is immovable — invMassEff = 0. | |
| void | computeManifoldSleepKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const unsigned char *, CpMem > asleep, Kokkos::View< unsigned char *, CpMem > manifoldSleep) |
| Per-manifold "both endpoints asleep" flag (a static wall, bodyB < 0, counts as asleep). | |
| void | computeContactSleepKokkos (Kokkos::View< const ContactC *, CpMem > contacts, int numContacts, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const unsigned char *, CpMem > asleep, Kokkos::View< unsigned char *, CpMem > contactSleep) |
| Per-contact twin of computeManifoldSleepKokkos for the position colouring. | |
| void | wakeDisturbedKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const float *[3], CpMem > velPred, float wakeSpeed, Kokkos::View< unsigned char *, CpMem > asleep, Kokkos::View< unsigned char *, CpMem > sleepCounter, Kokkos::View< unsigned char *, CpMem > movingWall, Kokkos::View< int *, CpMem > curCount, int numReal) |
| Wake pass (before the solve): a sleeper is woken when actually disturbed. | |
| void | wakeContactChangeKokkos (int numReal, Kokkos::View< const int *, CpMem > curCount, Kokkos::View< int *, CpMem > prevCount, Kokkos::View< const unsigned char *, CpMem > movingWall, Kokkos::View< unsigned char *, CpMem > asleep, Kokkos::View< unsigned char *, CpMem > sleepCounter, bool wakeOnChange) |
| Contact-set-change wake rule (b): wake any still-asleep body whose live contact count differs from the stored one (a support gained or lost), then refresh the store. | |
| void | updateSleepKokkos (int numReal, Kokkos::View< const float *[3], CpMem > vel, Kokkos::View< const float *[3], CpMem > angVel, Kokkos::View< const float *, CpMem > rad, Kokkos::View< const unsigned char *, CpMem > grounded, Kokkos::View< const unsigned char *, CpMem > movingWall, Kokkos::View< unsigned char *, CpMem > asleep, Kokkos::View< unsigned char *, CpMem > sleepCounter, float sleepSpeed, int K, Kokkos::View< float *[3], CpMem > velOut, Kokkos::View< float *[3], CpMem > angVelOut) |
| Sleep detection (after the commit): an AWAKE, grounded body whose linear AND angular motion has stayed below sleepSpeed for K consecutive substeps is put to sleep (velocity + spin zeroed). | |
| int | readInt (Kokkos::View< int, CpMem > v) |
| float | readFloat (Kokkos::View< float, CpMem > v) |
| void | fillGidBaseKokkos (Vi gid, int n, int base) |
| gid(i) = base + i over [0, n) — the per-rank global-id re-base of the distributed step (namespace scope: nvcc forbids KOKKOS_LAMBDA in member functions). | |
| float | maxOwnedRadius (const Particles &P) |
| Largest effective particle radius over the owned set (= max scale × globalScale, growth included). | |
| int | findCollisionsGrow (Particles &P, float margin) |
| Broad phase with an automatically-grown pair buffer. | |
| int | findCollisionsVerlet (Particles &P, float margin, float maxRad) |
| Verlet-cached impulse broadphase (single-GPU, non-periodic). | |
| template<class Hooks > | |
| void | demSolveContacts (Particles &P, int nc, int nm, int nBodies, Kokkos::View< const int *, CpMem > keyIdx, const Hooks &hooks) |
| One full velocity + position contact solve over the already-built contacts/manifolds (see file comment). | |
| void | hertzRebuildPairs (Particles &P, float skin) |
Rebuild the Hertz cached pair list with margin skin, carrying the Mindlin shear history across by pair key (permutation sort of the OLD list, binary search from the NEW). | |
| void | hertzCommitHistory (Particles &P) |
| Save the current list (sorted by key) so the NEXT rebuild can carry the history. | |
| void | zeroForceScratchKokkos (V3 dv, V3 dw, int lo, int hi) |
| Zero the force/torque accumulator rows [lo, hi) — under MPI the pair kernels atomically accumulate onto ghost slots too (Newton's third law), but only owned rows are consumed and cleared by the integrator; without this the ghost rows grow without bound. | |
| void | fillWorldRadiiKokkos (Vf scale, Vf rad, float gs, float bR, int n) |
| World radii rad(i) = scale(i) * globalScale * baseRadius over [0, n) (n = owned + ghosts after a halo gather; the driver's own preamble fills the owned span). | |
| template<class Law , class Hooks > | |
| void | demStepForce (Particles &P, float dt, int nsteps, float skinFrac, const Law &law, const Hooks &hooks) |
nsteps explicit force-based DEM steps of size dt with force law Law (see file comment). | |
| void | demStepHertz (Particles &P, float dt, int nsteps, float skinFrac) |
nsteps of the soft-sphere Hertz-Mindlin engine — the single-GPU instantiation of the force-based driver (kept as the historical entry point; see demStepForce). | |
| void | accumulateNormalImpulseKokkos (Kokkos::View< ContactC *, CpMem > contacts, int numContacts, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const float *[3], CpMem > velPred, Kokkos::View< const float *[3], CpMem > angVelPred, Kokkos::View< const int *, CpMem > realIdx, float growthRate) |
| Force-chain normal load, accumulated over the velocity iterations: contacts(idx).friction_lambda_n += approach / w_n. | |
| void | computePlaneLoadKokkos (Kokkos::View< ContactC *, CpMem > contacts, int numContacts, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const float *[3], CpMem > velPred, Kokkos::View< const float *[3], CpMem > angVelPred, FrManifoldCounts planeFriction) |
| Plane (idB<0) one-shot loads. | |
| void | countFrictionContactsKokkos (Kokkos::View< const ContactC *, CpMem > contacts, int numContacts, Kokkos::View< const int *, CpMem > realIdx, FrManifoldCounts planeFriction) |
| Per-body active-contact count into planeFriction(:,1). | |
| void | solveContactFrictionKokkos (Kokkos::View< const ContactC *, CpMem > contacts, int numContacts, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const float *[3], CpMem > velPred, Kokkos::View< const float *[3], CpMem > angVelPred, Kokkos::View< const int *, CpMem > realIdx, FrManifoldCounts planeFriction, float frictionDynamic, Kokkos::View< float *[3], CpMem > deltaVel, Kokkos::View< float *[3], CpMem > deltaAngVel) |
| One count-averaged Coulomb friction sweep. | |
| bool | demFusedWanted (bool graphReplayAvailable) |
| Fused-sweep policy (read once). | |
| FusedSweepCtx | demMakeFusedCtx (CpExec &space, const std::vector< int > &offs, Kokkos::View< int *, CpMem > offsDev, Kokkos::View< unsigned *, CpMem > bar) |
| Fill a FusedSweepCtx from buildColorBucketsKokkos's host offsets: async-upload them into the pooled device view and record the largest bucket. | |
| void | hertzPairEMu (int matA, int matB, PairTableView pairTable, float eGlobal, float muGlobal, float &e, float &mu) |
| Pairwise (e, mu) lookup shared with the narrowphase convention: pair table if present, global fallback otherwise. | |
| float | hertzBetaD (float e) |
| Restitution -> damping ratio beta_d = ln e / sqrt(ln^2 e + pi^2) (e in (0, 1]; e <= 0 -> -1, the critically-damped limit used by LIGGGHTS for e -> 0). | |
| F3 | hertzForce (float delta, F3 nhat, F3 vrel, float rStar, float mStar, float eStar, float gStar, float e, float mu, float dt, F3 &xi) |
| One Hertz–Mindlin force evaluation for a sphere-sphere or sphere-wall contact. | |
| void | hertzPairForcesKokkos (Kokkos::View< const int *[2], CpMem > pairs, int numPairs, Kokkos::View< const float *[3], CpMem > pos, Kokkos::View< const float *[3], CpMem > vel, Kokkos::View< const float *[3], CpMem > angVel, Kokkos::View< const float *, CpMem > rad, Kokkos::View< const float *, CpMem > invMass, MatIdView matId, PairTableView pairTable, float eGlobal, float muGlobal, Kokkos::View< const float *, CpMem > hertzE, Kokkos::View< const float *, CpMem > hertzNu, float dt, Kokkos::View< float *[3], CpMem > xi, Kokkos::View< float *[3], CpMem > force, Kokkos::View< float *[3], CpMem > torque) |
| Cached-pair forces: overlap from current positions; history resets when a cached pair is currently separated. | |
| void | hertzWallForcesKokkos (Kokkos::View< const int *, CpMem > candSlots, int numCand, Kokkos::View< const WallSdf *, CpMem > walls, GridView wallGrid, Kokkos::View< const float *[3], CpMem > pos, Kokkos::View< const float *[3], CpMem > vel, Kokkos::View< const float *[3], CpMem > angVel, Kokkos::View< const float *, CpMem > rad, Kokkos::View< const float *, CpMem > invMass, MatIdView matId, PairTableView pairTable, float eGlobal, float muGlobal, Kokkos::View< const float *, CpMem > hertzE, Kokkos::View< const float *, CpMem > hertzNu, float dt, Kokkos::View< float *[3], CpMem > xiWall, int maxWalls, Kokkos::View< float *[3], CpMem > force, Kokkos::View< float *[3], CpMem > torque, Kokkos::View< const float *[4], CpMem > quat={}, Kokkos::View< const float *, CpMem > scale={}, ScalarI shapeId={}, Kokkos::View< const ShapeDesc *, CpMem > shapes={}, ShellView shell={}, float globalScale=1.0f, float contactRadiusFrac=0.5f, bool hasShapes=false, Kokkos::View< float *, CpMem > snWall={}) |
| SDF-wall forces (per particle x wall). | |
| int | hertzBuildWallCandidatesKokkos (int numReal, int numWalls, Kokkos::View< const WallSdf *, CpMem > walls, GridView wallGrid, Kokkos::View< const float *[3], CpMem > pos, Kokkos::View< const float *, CpMem > rad, float skin, Kokkos::View< int *, CpMem > outSlots, Kokkos::View< int, CpMem > outCount) |
| Build the wall candidate list: particles within (radius + skin) of any wall's zero level. | |
| void | hertzIntegrateKokkos (int numReal, Kokkos::View< float *[3], CpMem > force, Kokkos::View< float *[3], CpMem > torque, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, F3 gravity, float dt, Kokkos::View< float *[3], CpMem > vel, Kokkos::View< float *[3], CpMem > angVel, Kokkos::View< float *[3], CpMem > pos, Kokkos::View< float *[4], CpMem > quat={}, bool integrateOrientation=false) |
| Symplectic-Euler kick-drift (MUSEN-style) + displacement tracking for the Verlet rebuild. | |
| float | hertzMaxDisp2Kokkos (int numReal, Kokkos::View< const float *[3], CpMem > pos, Kokkos::View< const float *[3], CpMem > refPos) |
| Max squared displacement since the last pair build (called only at rebuild checks – keeping this out of the integrate kernel avoids a per-step single-address atomic). | |
| void | hertzShapePairForcesKokkos (Kokkos::View< const int *[2], CpMem > pairs, int numPairs, Kokkos::View< const float *[3], CpMem > pos, Kokkos::View< const float *[4], CpMem > quat, Kokkos::View< const float *[3], CpMem > vel, Kokkos::View< const float *[3], CpMem > angVel, Kokkos::View< const float *, CpMem > scale, ScalarI shapeId, Kokkos::View< const ShapeDesc *, CpMem > shapes, ShellView shell, GridView sdfGrid, float globalScale, float contactRadiusFrac, Kokkos::View< const float *, CpMem > invMass, MatIdView matId, PairTableView pairTable, float eGlobal, float muGlobal, Kokkos::View< const float *, CpMem > hertzE, Kokkos::View< const float *, CpMem > hertzNu, float dt, Kokkos::View< float *[3], CpMem > xi, Kokkos::View< float *, CpMem > snPrev, Kokkos::View< float *[3], CpMem > force, Kokkos::View< float *[3], CpMem > torque) |
| Non-spherical pairs: per-point Hertz springs over A's point shell against B's SDF (the same one-sided sampling convention as the narrowphase), ONE Mindlin patch history per pair. | |
| ContactHierarchy | buildContactHierarchyKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const int *, CpMem > mColor, Kokkos::View< const float *, CpMem > vn0, Kokkos::View< const float *[3], CpMem > vt0, Kokkos::View< const unsigned char *, CpMem > persistent, Kokkos::View< const float *[3], CpMem > posPred, F3 gHat, Kokkos::View< const float *, CpMem > invMass, float qsThr, int gateMask, int numReal, MlScratch &S, Kokkos::View< long long *, CpMem > winner, Kokkos::View< std::uint64_t *, CpMem > colorMask, bool excludeImmovable=false, Kokkos::View< const unsigned char *, CpMem > asleep={}) |
| Build the aggregation hierarchy + per-level crossing-manifold colorings. | |
| void | buildCoarseBucketsKokkos (const ContactHierarchy &H, MlScratch &S, int numManifolds, Kokkos::View< int *, CpMem > colorScratch, Kokkos::View< int *, CpMem > perm, Kokkos::View< int *, CpMem > cursor, std::vector< std::vector< int > > &offs) |
| One multilevel stabilization cycle over an already-built hierarchy: fine colored smoothing is the caller's business; this runs the coarse leg (fine -> coarse), updating velPred in place. | |
| MlFusedCtx | demMakeMlFusedCtx (CpExec &space, const ContactHierarchy &H, const std::vector< std::vector< int > > &bkOffs, int numManifolds, int numReal, int coarseSweeps, Kokkos::View< int *, CpMem > offsDev, Kokkos::View< unsigned *, CpMem > bar) |
| Build the fused-coarse-cycle context from an already-built hierarchy + its dense buckets: flatten the per-level colour offsets into the pooled device view (async upload) and record the grid-sizing work bound. | |
| void | multilevelCoarseCycleKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< float *[3], CpMem > velPred, Kokkos::View< float *, CpMem > lambdaAcc, Kokkos::View< float, CpMem > maxApproach, int numReal, const ContactHierarchy &H, MlScratch &S, int coarseSweeps, Kokkos::View< const float *, CpMem > restRel={}, const std::vector< std::vector< int > > *bkOffs=nullptr, Kokkos::View< const int *, CpMem > bkPerm={}, const MlFusedCtx *fused=nullptr) |
| void | solvePositionKokkos (Kokkos::View< const ContactC *, CpMem > contacts, int numContacts, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > posPred, Kokkos::View< const float *[4], CpMem > quatPred, Kokkos::View< const float *[4], CpMem > quatStatic, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< float *[3], CpMem > deltaPos, Kokkos::View< float *[4], CpMem > deltaQuat, Kokkos::View< int *, CpMem > constraintCounts, Kokkos::View< float, CpMem > maxOverlap, Kokkos::View< const int *, CpMem > onlyColor={}, int colorFilter=0) |
Accumulate XPBD position corrections for numContacts contacts. | |
| int | colorContactsKokkos (Kokkos::View< const ContactC *, CpMem > contacts, int numContacts, int numBodies, Kokkos::View< int *, CpMem > cColor, Kokkos::View< long long *, CpMem > bodyWinner, Kokkos::View< std::uint64_t *, CpMem > bodyMask, int &leftover, Kokkos::View< const unsigned char *, CpMem > sleepMask={}) |
| Greedy graph-colour the contacts (raw bodyA/bodyB): no two contacts sharing a body get the same colour. | |
| int | colorContactsIncrementalKokkos (Kokkos::View< const ContactC *, CpMem > contacts, int numContacts, int numBodies, Kokkos::View< const unsigned long long *, CpMem > prevKeys, Kokkos::View< const int *, CpMem > prevColor, int prevCount, Kokkos::View< int *, CpMem > cColor, Kokkos::View< unsigned long long *, CpMem > keysOut, Kokkos::View< long long *, CpMem > bodyWinner, Kokkos::View< std::uint64_t *, CpMem > bodyMask, int &leftover, bool forceFull, Kokkos::View< const unsigned char *, CpMem > sleepMask={}) |
| Incremental (warm-started) contact colouring for the single-GPU PGS position solve. | |
| void | commitContactColorKokkos (Kokkos::View< const unsigned long long *, CpMem > keys, Kokkos::View< const int *, CpMem > color, Kokkos::View< unsigned long long *, CpMem > prevKeys, Kokkos::View< int *, CpMem > prevColor, Kokkos::View< int *, CpMem > perm, int numContacts) |
| Commit this substep's per-contact (key, colour) sorted by key, for next substep's warm gather. | |
| bool | solvePositionColoredGSKokkos (Kokkos::View< const ContactC *, CpMem > contacts, int numContacts, Kokkos::View< const int *, CpMem > cColor, int numColors, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< float *[3], CpMem > posPred, Kokkos::View< const float *[4], CpMem > quatPred, Kokkos::View< const float *[4], CpMem > quatStatic, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< float, CpMem > maxOverlap, Kokkos::View< float *, CpMem > posLambdaAcc={}, Kokkos::View< const int *, CpMem > colorPerm={}, const std::vector< int > *colorOffs=nullptr, const FusedSweepCtx *fused=nullptr, const FusedLoopSpec *loop=nullptr) |
Colored Gauss–Seidel XPBD overlap solve: sweep the numColors colour classes in order, applying each contact's non-penetration correction directly to posPred (in place, translation only). | |
| void | solveVelocityKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const float *[4], CpMem > quat, Kokkos::View< const float *[3], CpMem > velPred, Kokkos::View< const float *[3], CpMem > angVelPred, Kokkos::View< const int *, CpMem > realIdx, float growthRate, float restitutionNormal, float restVelThreshold, Kokkos::View< float *[3], CpMem > deltaVel, Kokkos::View< float *[3], CpMem > deltaAngVel, Kokkos::View< int *, CpMem > velCounts, Kokkos::View< const int *, CpMem > onlyColor={}, int colorFilter=0, Kokkos::View< const unsigned char *, CpMem > persistent={}, Kokkos::View< const float *[3], CpMem > posPred={}, F3 gHat={}, Kokkos::View< const unsigned char *, CpMem > grounded={}) |
Accumulate normal-restitution velocity deltas for numManifolds manifolds. | |
| template<class V3 , class Vi > | |
| void | applyVelocityDeltasAveragedKokkos (int n, V3 velPred, V3 angVelPred, V3 deltaVel, V3 deltaAngVel, Vi velCounts) |
| Apply the accumulated velocity deltas AVERAGED by the per-body manifold count — the velocity- solve twin of the position solve's constraint-count averaging (applyUpdatesKokkos). | |
| int | colorManifoldsKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, int numReal, Kokkos::View< int *, CpMem > mColor, Kokkos::View< long long *, CpMem > bodyWinner, Kokkos::View< std::uint64_t *, CpMem > bodyMask, int &leftover, Kokkos::View< const unsigned char *, CpMem > sleepMask={}) |
| Greedy graph-colour the manifolds: no two manifolds sharing a real body get the same colour. | |
| int | colorManifoldsIncrementalKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, int numReal, Kokkos::View< const unsigned long long *, CpMem > prevKeys, Kokkos::View< const int *, CpMem > prevColor, int prevCount, Kokkos::View< int *, CpMem > mColor, Kokkos::View< long long *, CpMem > bodyWinner, Kokkos::View< std::uint64_t *, CpMem > bodyMask, int &leftover, bool forceFull, Kokkos::View< const unsigned char *, CpMem > sleepMask={}) |
| Incremental (warm-started) manifold colouring for the single-GPU PGS path. | |
| void | computeVn0Kokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const float *[3], CpMem > velPred, Kokkos::View< const float *[3], CpMem > angVelPred, Kokkos::View< const int *, CpMem > realIdx, float growthRate, Kokkos::View< float *, CpMem > vn0, Kokkos::View< float *[3], CpMem > vt0) |
| -— Warm-started projected Gauss-Seidel (PGS) velocity solve -— Nonsmooth contact dynamics (Moreau-Jean; Stewart-Trinkle LCP): per manifold an ACCUMULATED push impulse p >= 0 along the manifold normal, updated by colored GS sweeps and projected to p >= 0 (a contact may push, never pull; over-push is retracted in later sweeps). | |
| void | updateRestitutionBankKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const float *[4], CpMem > quat, Kokkos::View< const float *[3], CpMem > velPred, Kokkos::View< const float *[3], CpMem > angVelPred, Kokkos::View< const int *, CpMem > realIdx, float growthRate, float restitutionNormal, float restVelThreshold, Kokkos::View< const float *, CpMem > vn0, Kokkos::View< const float *, CpMem > lambdaAcc, Kokkos::View< const float *, CpMem > restRel, Kokkos::View< float *, CpMem > restBank, Kokkos::View< float *, CpMem > restVPeak) |
| Event-level (Poisson) restitution bookkeeping, once per substep AFTER all velocity phases (restitutionModel == 1 only). | |
| void | decayBodyOrphanKokkos (Kokkos::View< float *, CpMem > orphan, Kokkos::View< float *, CpMem > orphanVPeak, int numOwned, float restVelThreshold) |
| Orphan-account aging, once per substep over the OWNED bodies: both the balance and the carried event peak decay 1/64 per substep (e-fold ~3 ms at dt = 5e-5 — long enough for the rebound payout, which completes within ~2 ms of turnaround, short enough that a BURIED impactor's slowly re-fed credit cannot keep fluidizing its crater: with the pair-state 1/256 decay the 100k Dosta plateau crept 0.007 deeper), and once the peak ages below the resting threshold the whole account evaporates — stranded credit on a settling body never pops the pile later. | |
| void | scatterOrphanBanksKokkos (Kokkos::View< const unsigned long long *, CpMem > prevKeys, Kokkos::View< const float *, CpMem > prevRestBank, Kokkos::View< const float *, CpMem > prevRestVPeak, Kokkos::View< const unsigned char *, CpMem > matched, int prevCount, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< float *, CpMem > orphan, Kokkos::View< float *, CpMem > orphanVPeak, Kokkos::View< const int *, CpMem > gidSorted={}, Kokkos::View< const int *, CpMem > slotSorted={}) |
| Orphan transfer: previous-ledger entries NOT matched by any current manifold (their pair died this substep) credit their remaining owed budget to the endpoint BODIES, mass-weighted — the heavier endpoint keeps the larger share (energy of a later release scales J^2/2m, so the light grain is the dangerous store and the heavy impactor is both the safe one and the event's physical carrier); boundary pairs (wall endpoint) credit everything to the particle. | |
| std::tuple< double, float, int > | restBankStatsKokkos (Kokkos::View< const float *, CpMem > bank, int n) |
| Poisson-restitution diagnostics: (sum, max, count>0) over the committed owed-impulse store (namespace scope: nvcc forbids KOKKOS_LAMBDA in member functions). | |
| void | computeSideFlagsKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const unsigned char *, CpMem > persistent, Kokkos::View< const unsigned char *, CpMem > grounded, Kokkos::View< const float *[3], CpMem > posPred, Kokkos::View< const float *[3], CpMem > velPred, F3 gHat, float riseThr, Kokkos::View< unsigned char *, CpMem > sideFlag, Kokkos::View< const float *, CpMem > vn0, float approachThr) |
| Decide each persistent contact's treatment ONCE per substep (before any impulse is applied): 0 = symmetric momentum-conserving PGS, 1 = one-sided with B as the held ground side, 2 = A held. | |
| void | warmStartApplyKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const float *[4], CpMem > quat, Kokkos::View< float *[3], CpMem > velPred, Kokkos::View< float *[3], CpMem > angVelPred, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const float *, CpMem > warmP, Kokkos::View< float *[3], CpMem > warmT) |
| Apply the warm-start impulses up front (order-independent: fixed impulses, atomic adds). | |
| PGSManifoldSweep | makePGSManifoldSweep (Kokkos::View< const ManifoldC *, CpMem > manifolds, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const float *[4], CpMem > quat, Kokkos::View< float *[3], CpMem > velPred, Kokkos::View< float *[3], CpMem > angVelPred, Kokkos::View< const int *, CpMem > realIdx, float growthRate, float restitutionNormal, float restVelThreshold, Kokkos::View< float, CpMem > maxApproach, Kokkos::View< float, CpMem > maxApproachQS, Kokkos::View< float *, CpMem > lambdaAcc, Kokkos::View< const float *, CpMem > vn0, Kokkos::View< const unsigned char *, CpMem > sideFlag, Kokkos::View< float *[3], CpMem > lambdaT, float frictionDynamic, Kokkos::View< const float *[3], CpMem > vt0, float restitutionTangent, Kokkos::View< const float *, CpMem > posImpulse, Kokkos::View< float *, CpMem > restBank, Kokkos::View< float *, CpMem > restRel, Kokkos::View< const unsigned char *, CpMem > restPersistent, Kokkos::View< const float *, CpMem > restVPeak, F3 restGHat, Kokkos::View< const unsigned char *, CpMem > restGrounded, bool restNewtonOff, bool restOneSided, Kokkos::View< float *, CpMem > restOrphan, Kokkos::View< const float *, CpMem > restOrphanVPeak) |
| Build the shared per-manifold sweep functor (the colored launch loop, the fused kernels and the fused multilevel iteration loop all run this one body). | |
| bool | solveVelocityPGSKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > mColor, int numColors, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const float *[4], CpMem > quat, Kokkos::View< float *[3], CpMem > velPred, Kokkos::View< float *[3], CpMem > angVelPred, Kokkos::View< const int *, CpMem > realIdx, float growthRate, float restitutionNormal, float restVelThreshold, Kokkos::View< float, CpMem > maxApproach, Kokkos::View< float *, CpMem > lambdaAcc, Kokkos::View< const float *, CpMem > vn0, Kokkos::View< const unsigned char *, CpMem > sideFlag, Kokkos::View< float *[3], CpMem > lambdaT, float frictionDynamic, Kokkos::View< const float *[3], CpMem > vt0={}, float restitutionTangent=0.0f, Kokkos::View< const float *, CpMem > posImpulse={}, Kokkos::View< float, CpMem > maxApproachQS={}, Kokkos::View< float *, CpMem > restBank={}, Kokkos::View< float *, CpMem > restRel={}, Kokkos::View< const unsigned char *, CpMem > restPersistent={}, Kokkos::View< const float *, CpMem > restVPeak={}, F3 restGHat={}, Kokkos::View< const unsigned char *, CpMem > restGrounded={}, bool restNewtonOff=false, bool restOneSided=false, Kokkos::View< float *, CpMem > restOrphan={}, Kokkos::View< const float *, CpMem > restOrphanVPeak={}, Kokkos::View< const int *, CpMem > colorPerm={}, const std::vector< int > *colorOffs=nullptr, const FusedSweepCtx *fused=nullptr, const FusedLoopSpec *loop=nullptr) |
Returns true when the sweep (or, with loop, the whole iteration loop) was submitted; false ONLY in loop mode when the fused path is unavailable — the caller then runs its own host-side iteration loop (which calls back in per-iteration mode). | |
| void | buildLevelColorBucketsKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const int *, CpMem > mColor, Kokkos::View< const int *, CpMem > heights, Kokkos::View< int *, CpMem > keys, Kokkos::View< int *, CpMem > perm, std::vector< std::pair< int, int > > &buckets) |
| Bucket the active coloured manifolds by (support level, colour) for the level-ordered ("multilevel") stabilization sweeps. | |
| void | solveVelocityPGSBucketsKokkos (const PGSManifoldSweep &f, Kokkos::View< const int *, CpMem > perm, const std::vector< std::pair< int, int > > &buckets, bool topDown) |
| Level-ordered symmetric sweep: launch one PGS kernel per (level, colour) bucket, ascending (bottom-up: a chain's load drains towards the floor in ~one pass) or descending (top-down: the return pass carries rebound waves back up). | |
| void | solveVelocityColoredGSKokkos (Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > mColor, int numColors, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const float *[4], CpMem > quat, Kokkos::View< float *[3], CpMem > velPred, Kokkos::View< float *[3], CpMem > angVelPred, Kokkos::View< const int *, CpMem > realIdx, float growthRate, float restitutionNormal, float restVelThreshold, Kokkos::View< float, CpMem > maxApproach, Kokkos::View< const unsigned char *, CpMem > persistent={}, Kokkos::View< const float *[3], CpMem > posPred={}, F3 gHat={}, Kokkos::View< const unsigned char *, CpMem > grounded={}) |
Colored Gauss–Seidel normal-restitution solve: sweep the numColors colour classes in order, applying each manifold's impulse directly to velPred/angVelPred (in place). | |
Variables | |
| constexpr int | kLevelInf = 1 << 28 |
| Height-from-floor BFS levels for the level-ordered ("multilevel") stabilization pass: 0 at a wall/plane contact, else 1 + min over supporting contacts, kLevelInf with no contact path to the floor. | |
| constexpr int | kMaxMaterials = 8 |
| Pair-material lookup: flat [K*K*2] table, entry ((a*K + b)*2) = restitution, +1 = friction. | |
| constexpr int | kMlMaxLevels = 10 |
| 6-bit colour slots per level in the packed word; slot value 63 = not crossing / not eligible at that level (skipped by the coarse sweeps). | |
| constexpr int | kMlSlotSkip = 63 |
| using peclet::dem::BpExec = typedef Kokkos::DefaultExecutionSpace |
Definition at line 21 of file broadphase_arborx.hpp.
| using peclet::dem::BpMem = typedef BpExec::memory_space |
Definition at line 22 of file broadphase_arborx.hpp.
| using peclet::dem::CpExec = typedef Kokkos::DefaultExecutionSpace |
Definition at line 27 of file contact_preprocessing.hpp.
| using peclet::dem::CpMem = typedef CpExec::memory_space |
Definition at line 28 of file contact_preprocessing.hpp.
| using peclet::dem::V3 = typedef Kokkos::View<float* [3], CpMem> |
Definition at line 24 of file integration.hpp.
| using peclet::dem::V4 = typedef Kokkos::View<float* [4], CpMem> |
Definition at line 25 of file integration.hpp.
| using peclet::dem::Vf = typedef Kokkos::View<float*, CpMem> |
Definition at line 26 of file integration.hpp.
| using peclet::dem::Vi = typedef Kokkos::View<int*, CpMem> |
Definition at line 27 of file integration.hpp.
| using peclet::dem::PairTableView = typedef Kokkos::View<const float*, CpMem> |
Definition at line 80 of file narrowphase.hpp.
| using peclet::dem::MatIdView = typedef Kokkos::View<const unsigned char*, CpMem> |
Definition at line 81 of file narrowphase.hpp.
| using peclet::dem::PosView = typedef Kokkos::View<const float* [3], CpMem> |
Definition at line 84 of file narrowphase.hpp.
| using peclet::dem::QuatView = typedef Kokkos::View<const float* [4], CpMem> |
Definition at line 85 of file narrowphase.hpp.
| using peclet::dem::ScalarF = typedef Kokkos::View<const float*, CpMem> |
Definition at line 86 of file narrowphase.hpp.
| using peclet::dem::ScalarI = typedef Kokkos::View<const int*, CpMem> |
Definition at line 87 of file narrowphase.hpp.
| using peclet::dem::ShellView = typedef Kokkos::View<const float* [3], CpMem> |
Definition at line 88 of file narrowphase.hpp.
| using peclet::dem::GridView = typedef Kokkos::View<const float*, CpMem> |
Definition at line 89 of file narrowphase.hpp.
| using peclet::dem::FrManifoldCounts = typedef Kokkos::View<float* [2], CpMem> |
Definition at line 25 of file solver_friction.hpp.
| Enumerator | |
|---|---|
| SHAPE_GRID_SDF | |
| SPHERE | |
| HOLLOW_CYLINDER | |
| BOX | |
Definition at line 77 of file dem_portable.hpp.
|
inline |
Emit candidate collision pairs (i<j) for real particles into outPairs/outCount.
pos[numParticles][3] positions of all particles (real first, then ghosts) rad[numParticles] effective radius per particle (scale * global_scale) numReal only particles [0,numReal) issue queries (own real particles) margin safety margin added to every box half-width (cuBQL uses 0.1*global_scale) outPairs[maxPairs][2] preallocated output; outCount is the (clamped) number found Returns the number of pairs found (may exceed maxPairs if the buffer is too small).
Definition at line 36 of file broadphase_arborx.hpp.
References PECLET_DEM_SANE_BOX.
Referenced by findCollisionsGrow().
| unsigned long long peclet::dem::pairKeyOf | ( | const ManifoldC & | m, |
| Kokkos::View< const int *, CpMem > | realIdx | ||
| ) |
Persistent-contact detection for the gravity-gated restitution rule.
Key = (min real body, max real body) packed in 64 bits; boundary manifolds (bodyB = -1: planes + SDF walls, merged per particle) use lo = 0xFFFFFFFF. Flags each manifold whose pair already existed in the PREVIOUS substep (prevKeys sorted, device binary search). Real indices are stable within a single-GPU run, so the key identifies the physical pair across substeps.
Definition at line 71 of file contact_preprocessing.hpp.
References peclet::dem::ManifoldC::bodyA, and peclet::dem::ManifoldC::bodyB.
Referenced by markPersistentManifoldsKokkos().
|
inline |
keyIdx maps a body slot to the identity the pair key is built from: the REAL index map on the single-GPU path (stable within a run), or the GLOBAL particle id under MPI (stable across ranks, halo rebuilds and ownership migration — local slots are neither).
Definition at line 82 of file contact_preprocessing.hpp.
References peclet::dem::ManifoldC::num_points, and pairKeyOf().
Referenced by demSolveContacts().
|
inline |
Warm-start gather for the PGS velocity solve: per manifold, write its pair key and look up the previous substep's converged push impulse (0 for a new contact).
Periodic-ghost duplicate manifolds (realA > realB twin) get key ~0 and warm 0 – the canonical twin carries the impulse. keyIdx: see markPersistentManifoldsKokkos (realIdx keeps the periodic-dedup role; keyIdx builds the cross-substep pair identity).
Definition at line 119 of file contact_preprocessing.hpp.
Referenced by demSolveContacts().
|
inline |
Save this substep's keys + converged impulses (normal AND tangential) and key-sort them for next substep's gather.
A permutation sort carries both value arrays through one key sort.
Definition at line 172 of file contact_preprocessing.hpp.
Referenced by demSolveContacts().
|
inline |
Copy this substep's keys into prevKeys and sort them for next substep's binary search.
Definition at line 220 of file contact_preprocessing.hpp.
|
inline |
Guendelman support levels, warm-started: decay every body's level by decay, re-seed 255 at wall/plane contacts, then sweeps monotone propagation passes lower -> upper (255 -> 254 -> ...) through the manifold graph.
Warm start makes a few sweeps per substep track slowly-moving support fronts; the decay retires groundedness ~32 substeps after lift-off. Geometry-only (no persistence / velocity condition): grounded means "has a contact path down to the floor".
Definition at line 238 of file contact_preprocessing.hpp.
References peclet::dem::ManifoldC::bodyA, peclet::dem::ManifoldC::bodyB, dot3(), ldF3(), peclet::dem::ManifoldC::num_points, sub3(), peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by demSolveContacts().
|
inline |
Definition at line 287 of file contact_preprocessing.hpp.
References peclet::dem::ManifoldC::bodyA, peclet::dem::ManifoldC::bodyB, dot3(), kLevelInf, ldF3(), peclet::dem::ManifoldC::num_points, sub3(), peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by demSolveContacts().
|
inline |
Dense colour buckets (numColors <= 64): perm[offs[c] .
. offs[c+1]) lists the item indices of colour c. Histogram + host prefix + scatter — two small kernels and one 64-int readback, amortized over every sweep that would otherwise scan ALL n items per colour per iteration (measured 25k multilevel: the per-colour full scans were 40% of GPU time and the step is host-submission-bound). Within a colour the scatter order is arbitrary — colour classes are body-disjoint, so the sweep result is bit-identical. Items with colour < 0 (inactive, dups, mask-saturation leftovers) are excluded, exactly like the scan-mode colour filter.
Definition at line 338 of file contact_preprocessing.hpp.
Referenced by buildCoarseBucketsKokkos(), and demSolveContacts().
| long long peclet::dem::colorKey | ( | int | idx | ) |
splitmix32 finalizer: a well-mixed pseudo-random priority per edge index.
Random priorities make the Jones-Plassmann arbitration finish in O(log n) rounds w.h.p.; RAW indices are adversarial for lattice-ordered dense packs (monotone index chains -> one win per round -> O(chain) rounds).
Definition at line 374 of file contact_preprocessing.hpp.
| std::uint64_t peclet::dem::pairKey | ( | const ContactC & | c | ) |
Canonical pair key: (min<<32)|max, or (idA<<32)|0xFFFFFFFF for a boundary (idB<0) contact.
Definition at line 384 of file contact_preprocessing.hpp.
References peclet::dem::ContactC::bodyA, and peclet::dem::ContactC::bodyB.
| void peclet::dem::decodeKey | ( | std::uint64_t | key, |
| int & | bodyA, | ||
| int & | bodyB | ||
| ) |
Decode the canonical (bodyA, bodyB) from a pair key (bodyB = -1 for boundary).
Definition at line 394 of file contact_preprocessing.hpp.
Per-contact transform to a single-point manifold, aligned to the canonical pair.
Inactive contacts (dist > 0) contribute a zero manifold with num_points = 0. Mirrors ContactToManifold + TransformAndFilter from contact_preprocessing.cu.
Definition at line 403 of file contact_preprocessing.hpp.
References peclet::dem::ContactC::bodyA, peclet::dem::ContactC::bodyB, peclet::dem::ContactC::boundaryFriction, peclet::dem::ContactC::boundaryRestitution, peclet::dem::ContactC::boundaryVel, cross3(), peclet::dem::ContactC::dist, peclet::dem::ContactC::normal, peclet::dem::ContactC::rA, peclet::dem::ContactC::rB, peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
|
inline |
Reduce n contacts to manifolds (one per unique canonical pair).
outManifolds must hold at least the number of unique pairs; returns that count (also written to outCount).
Definition at line 442 of file contact_preprocessing.hpp.
Referenced by demStep().
|
inline |
PGS friction bound: overwrite each contact's friction_lambda_n with its manifold's converged PGS push impulse (lambdaAcc, shared equally over the manifold's contact points).
The legacy accumulateNormalImpulse bound derives from approach velocities, which the PGS warm start has already cancelled – without this the Coulomb bound is ~0 and friction is inert.
Definition at line 541 of file contact_preprocessing.hpp.
References peclet::dem::ManifoldC::num_points.
|
inline |
After the position solve: convert the per-contact positional lambdas into an impulse- equivalent per manifold (lambda_pos / dt has force units; x dt back to impulse => just lambda_pos * m_eff... the positional lambda already carries 1/w mass weighting, so the impulse equivalent over the substep is lambda_pos / dt * dt = lambda_pos / (w*...) – we store lambda_pos/dt * dt = lambda_pos scaled by 1/dt to velocity-impulse units) and write it into the sorted prev-store so next substep's warm gather can top up the Coulomb bound.
Definition at line 563 of file contact_preprocessing.hpp.
Referenced by demSolveContacts().
Definition at line 25 of file dem_portable.hpp.
References peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by accumulateNormalImpulseKokkos(), applyUpdatesKokkos(), applyVelocityAndPredictPositionKokkos(), applyVelocityDeltasKokkos(), computePlaneLoadKokkos(), computeVn0Kokkos(), detectBoundaryKokkos(), hertzForce(), hertzPairForcesKokkos(), hertzShapePairForcesKokkos(), predictVelocityKokkos(), rotateVector(), solveContactFrictionKokkos(), peclet::dem::PositionContactSweep::solveOne(), and peclet::dem::PGSManifoldSweep::solveOne().
Definition at line 28 of file dem_portable.hpp.
References peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by accumulateNormalImpulseKokkos(), computeHeightLevelsKokkos(), computePlaneLoadKokkos(), computeSideFlagsKokkos(), computeVn0Kokkos(), detectBoundaryKokkos(), peclet::dem::mldetail::eligible(), hertzForce(), hertzMaxDisp2Kokkos(), hertzPairForcesKokkos(), hertzShapePairForcesKokkos(), solveContactFrictionKokkos(), peclet::dem::PositionContactSweep::solveOne(), peclet::dem::PGSManifoldSweep::solveOne(), peclet::dem::MlCoarseSweep::solveOne(), updateGroundedLevelsKokkos(), updateRestitutionBankKokkos(), and warmStartApplyKokkos().
Definition at line 31 of file dem_portable.hpp.
References peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by accumulateNormalImpulseKokkos(), applyThermostatKokkos(), applyUpdatesKokkos(), applyVelocityAndPredictPositionKokkos(), computeVn0Kokkos(), detectBoundaryKokkos(), hertzForce(), hertzPairForcesKokkos(), hertzShapePairForcesKokkos(), predictVelocityKokkos(), rotateVector(), solveContactFrictionKokkos(), peclet::dem::PGSManifoldSweep::solveOne(), peclet::dem::MlCoarseSweep::solveOne(), updateRestitutionBankKokkos(), and warmStartApplyKokkos().
Definition at line 34 of file dem_portable.hpp.
References peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by accumulateNormalImpulseKokkos(), computeHeightLevelsKokkos(), computePlaneLoadKokkos(), computeSideFlagsKokkos(), computeVn0Kokkos(), detectBoundaryKokkos(), peclet::dem::mldetail::eligible(), peclet::dem::detail::genInvMass(), hertzForce(), hertzMaxDisp2Kokkos(), hertzPairForcesKokkos(), hertzShapePairForcesKokkos(), len3(), solveContactFrictionKokkos(), peclet::dem::PositionContactSweep::solveOne(), peclet::dem::PGSManifoldSweep::solveOne(), peclet::dem::MlCoarseSweep::solveOne(), updateGroundedLevelsKokkos(), updateRestitutionBankKokkos(), and warmStartApplyKokkos().
| float peclet::dem::len3 | ( | F3 | v | ) |
Definition at line 37 of file dem_portable.hpp.
References dot3().
Referenced by hertzShapePairForcesKokkos(), and sdfSphere().
Definition at line 40 of file dem_portable.hpp.
References peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by accumulateNormalImpulseKokkos(), computePlaneLoadKokkos(), computeVn0Kokkos(), peclet::dem::detail::computeW(), hertzPairForcesKokkos(), hertzShapePairForcesKokkos(), predictVelocityKokkos(), rotateVector(), solveContactFrictionKokkos(), peclet::dem::PGSManifoldSweep::solveOne(), and warmStartApplyKokkos().
Definition at line 43 of file dem_portable.hpp.
References peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
Referenced by transformContact().
| F3 peclet::dem::ldF3 | ( | const V & | v, |
| int | i | ||
| ) |
Definition at line 49 of file dem_portable.hpp.
Referenced by accumulateNormalImpulseKokkos(), applyThermostatKokkos(), applyUpdatesKokkos(), applyVelocityAndPredictPositionKokkos(), applyVelocityDeltasKokkos(), computeHeightLevelsKokkos(), computePlaneLoadKokkos(), computeSideFlagsKokkos(), peclet::dem::mldetail::eligible(), finalCommitKokkos(), predictVelocityKokkos(), solveContactFrictionKokkos(), peclet::dem::PositionContactSweep::solveOne(), and updateGroundedLevelsKokkos().
| F4 peclet::dem::ldF4 | ( | const V & | v, |
| int | i | ||
| ) |
Definition at line 53 of file dem_portable.hpp.
Referenced by applyThermostatKokkos(), applyVelocityAndPredictPositionKokkos(), finalCommitKokkos(), predictVelocityKokkos(), and peclet::dem::PositionContactSweep::solveOne().
Definition at line 59 of file dem_portable.hpp.
References add3(), cross3v(), scale3(), peclet::dem::F4::w, peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
Referenced by detectBoundaryKokkos(), hertzShapePairForcesKokkos(), invRotateVector(), predictVelocityKokkos(), peclet::dem::PositionContactSweep::solveOne(), peclet::dem::PGSManifoldSweep::solveOne(), and warmStartApplyKokkos().
Definition at line 64 of file dem_portable.hpp.
References rotateVector(), peclet::dem::F4::w, peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
Referenced by applyThermostatKokkos(), peclet::dem::detail::genInvMass(), hertzShapePairForcesKokkos(), predictVelocityKokkos(), peclet::dem::PGSManifoldSweep::solveOne(), and warmStartApplyKokkos().
Definition at line 67 of file dem_portable.hpp.
References peclet::dem::F4::w, peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
Referenced by peclet::dem::PositionContactSweep::solveOne().
Definition at line 70 of file dem_portable.hpp.
References peclet::dem::F4::w, peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
Referenced by peclet::dem::PositionContactSweep::solveOne().
Definition at line 79 of file dem_portable.hpp.
References len3(), and peclet::dem::F4::x.
Referenced by sdfEval().
Definition at line 83 of file dem_portable.hpp.
References peclet::dem::F3::x, peclet::dem::F4::x, peclet::dem::F3::y, peclet::dem::F4::y, peclet::dem::F3::z, and peclet::dem::F4::z.
Referenced by sdfEval().
Definition at line 95 of file dem_portable.hpp.
References peclet::dem::F3::x, peclet::dem::F4::x, peclet::dem::F3::y, peclet::dem::F4::y, peclet::dem::F3::z, and peclet::dem::F4::z.
Referenced by sdfEval().
Definition at line 105 of file dem_portable.hpp.
References BOX, HOLLOW_CYLINDER, sdfBox(), sdfHollowCylinder(), sdfSphere(), and SPHERE.
Referenced by sdfEvalShape().
|
inline |
Predict velocity (gravity + gyroscopic precession), speculative position, and clear all deltas.
Definition at line 44 of file integration.hpp.
References add3(), cross3v(), invRotateVector(), ldF3(), ldF4(), rotateVector(), scale3(), peclet::dem::detail::st3(), peclet::dem::detail::st4(), peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by demStep().
|
inline |
Add accumulated velocity/angular deltas onto the predicted velocity, then clear the delta buffers.
Definition at line 97 of file integration.hpp.
References add3(), ldF3(), and peclet::dem::detail::st3().
Referenced by demSolveContacts().
|
inline |
Re-integration: persist solved velocity, trapezoidal position predict, quaternion integrate.
Definition at line 112 of file integration.hpp.
References add3(), ldF3(), ldF4(), scale3(), peclet::dem::detail::st3(), peclet::dem::detail::st4(), peclet::dem::F4::w, peclet::dem::F3::x, peclet::dem::F4::x, peclet::dem::F3::y, peclet::dem::F4::y, peclet::dem::F3::z, and peclet::dem::F4::z.
Referenced by demSolveContacts().
|
inline |
Per-contact constraint-count pre-pass (active contacts, dist <= 0).
Definition at line 151 of file integration.hpp.
References peclet::dem::ContactC::bodyA, peclet::dem::ContactC::bodyB, and peclet::dem::ContactC::dist.
|
inline |
Jacobi count-averaged apply of position/velocity deltas, then clear deltas + counts.
Definition at line 168 of file integration.hpp.
References add3(), ldF3(), scale3(), and peclet::dem::detail::st3().
Referenced by demSolveContacts().
|
inline |
Final commit: periodic wrap of the predicted position into the domain, commit position + quat.
Definition at line 187 of file integration.hpp.
References ldF3(), ldF4(), peclet::dem::Domain::max, peclet::dem::Domain::min, peclet::dem::Domain::periodic_x, peclet::dem::Domain::periodic_y, peclet::dem::Domain::periodic_z, peclet::dem::Domain::size, peclet::dem::detail::st3(), peclet::dem::detail::st4(), peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by demStep().
|
inline |
Definition at line 229 of file integration.hpp.
References invRotateVector(), ldF3(), ldF4(), peclet::dem::KE2::r, scale3(), peclet::dem::detail::st3(), peclet::dem::KE2::t, peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by demStep().
Growth mode: scale = target * factor (when active).
Definition at line 275 of file integration.hpp.
Referenced by demStep(), and peclet::dem::Simulation::setGrowthParams().
|
inline |
Definition at line 23 of file io.hpp.
Referenced by peclet::dem::Simulation::exportLammps(), and NB_MODULE().
|
inline |
Definition at line 86 of file io.hpp.
Referenced by peclet::dem::Simulation::exportSdf().
Definition at line 91 of file narrowphase.hpp.
Referenced by detectBoundaryKokkos(), hertzMaxDisp2Kokkos(), hertzPairForcesKokkos(), and hertzShapePairForcesKokkos().
Definition at line 94 of file narrowphase.hpp.
Referenced by detectBoundaryKokkos(), and hertzShapePairForcesKokkos().
Trilinearly sample an imported grid SDF at canonical point p.
The query is clamped into the sample lattice and the Euclidean distance from p to that clamped point is added back, so a probe outside the stored box gets a monotonically growing (positive) distance instead of a flat clamped value — the standard "clamp + residual" extension that keeps the far field well-signed and the central-difference normal sane near the grid boundary. Interior samples are exact trilinear. Requires nx,ny,nz >= 2 (the shape builder guarantees this).
Definition at line 104 of file narrowphase.hpp.
References peclet::dem::ShapeDesc::gridInvSpacing, peclet::dem::ShapeDesc::gridOffset, peclet::dem::ShapeDesc::gridOrigin, peclet::dem::ShapeDesc::nx, peclet::dem::ShapeDesc::ny, peclet::dem::ShapeDesc::nz, peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by sdfEvalShape().
Trilinearly sample a static world-space wall SDF at world point p.
Positive in the void, negative in the wall. The off-grid extension SUBTRACTS the clamp residual — the OPPOSITE of sampleGridSdf's object convention — because a wall SDF is a CONTAINER: the void is bounded and everything beyond the stored box is wall-side, so a probe outside the box must read an ever more negative (deeper-in-the-wall) distance. Adding the residual here (the old behaviour) made a grain pushed past the box boundary — e.g. squeezed through the floor plane, whose zero level sits exactly on the grid's lower face — read "clear" and free-fall out of the simulation forever: a 180k glass-bead pile lost 71k grains through the distributor during settling.
Definition at line 141 of file narrowphase.hpp.
References peclet::dem::WallSdf::gridOffset, peclet::dem::WallSdf::invSpacing, peclet::dem::WallSdf::nx, peclet::dem::WallSdf::ny, peclet::dem::WallSdf::nz, peclet::dem::WallSdf::origin, peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by hertzBuildWallCandidatesKokkos().
Canonical-space SDF of a shape: analytic dispatch, or a trilinear grid sample for an imported grid SDF.
grid may be an empty View when no grid shape is present.
Definition at line 171 of file narrowphase.hpp.
References peclet::dem::ShapeDesc::params, sampleGridSdf(), sdfEval(), SHAPE_GRID_SDF, and peclet::dem::ShapeDesc::type.
Referenced by hertzShapePairForcesKokkos().
|
inline |
Pair point-shell vs SDF contacts.
pairs[numPairs][2] are (idA,idB) from the broad-phase; emits ContactC into outContacts guarded by atomic outCount (clamped to outContacts.extent(0)).
Definition at line 179 of file narrowphase.hpp.
Referenced by computeOverlapsKokkos(), and demStep().
|
inline |
Per-real-particle contacts against a static world-space wall SDF set (a drum barrel, hopper, vibrating tray, ...).
Mirrors detectBoundaryKokkos but the boundary is the wall's zero level set: each surface point (or the sphere centre) is tested against sampleWallSdf, the outward gradient is the contact normal, and every emitted contact carries the wall's rigid-body surface velocity at the contact point plus the wall's binary (particle–wall) restitution/friction — so the moving-wall terms flow through the manifold velocity solve and the per-contact friction sweep. bodyB = -1 (a boundary, like a plane); the wall surface point is stored in rB for the position solve's plane-linearised non-penetration constraint.
Definition at line 278 of file narrowphase.hpp.
Referenced by computeOverlapsKokkos(), and demStep().
|
inline |
Per-real-particle contacts against explicit planes (point-shell shapes test each surface point; analytic spheres use centre-minus-radius).
bodyB = -1; plane anchor stored in rB.
Definition at line 371 of file narrowphase.hpp.
References add3(), peclet::dem::ContactC::bodyA, dot3(), loadF3(), loadF4(), peclet::dem::PlaneP::normal, peclet::dem::ShapeDesc::numPoints, peclet::dem::ShapeDesc::params, peclet::dem::PlaneP::point, rotateVector(), scale3(), peclet::dem::ShapeDesc::shellOffset, sub3(), peclet::dem::F3::x, peclet::dem::F4::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by computeOverlapsKokkos(), and demStep().
|
inline |
Definition at line 25 of file output_sdf.hpp.
Referenced by peclet::dem::Simulation::getSdfGrid().
|
inline |
Padded particle-array capacity that leaves room for the periodic ghosts generateGhostsKokkos will emit: the real count plus an estimate of the boundary-shell ghost population, gated on which axes are actually periodic.
Faithful port of the CUDA Simulation::calculate_capacity (small/dense box -> full 26-neighbour headroom; large box -> a few times the boundary-shell volume fraction), with the periodicity gating added so a closed or partly-periodic box is not over-allocated. skin is the ghost band width at each periodic face (1.0*globalScale in the solver).
Definition at line 25 of file periodicity.hpp.
References peclet::dem::Domain::periodic_x, peclet::dem::Domain::periodic_y, peclet::dem::Domain::periodic_z, peclet::dem::Domain::size, peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by computeOverlapsKokkos(), and demStep().
|
inline |
Generate periodic ghosts for particles [0,numReal).
topGhost must be pre-seeded to numReal (the first free slot); on return it holds the total particle count. Slots beyond capacity are dropped. skin is the ghost band width at each periodic face.
Definition at line 43 of file periodicity.hpp.
Referenced by computeOverlapsKokkos(), and demStep().
|
inline |
Definition at line 21 of file shapes_portable.hpp.
Referenced by peclet::dem::Simulation::initializeShape().
|
inline |
Definition at line 80 of file shapes_portable.hpp.
Referenced by peclet::dem::Simulation::initializeShape().
|
inline |
One full XPBD DEM substep over the particle SoA (mirrors simulation.cpp Simulation::step()).
Definition at line 49 of file sim.hpp.
References peclet::dem::Particles::angVel, peclet::dem::Particles::angVelPred, applyThermostatKokkos(), peclet::dem::Particles::asleep, peclet::dem::Particles::baseRadius, buildInvMassEffKokkos(), calculateGhostCapacity(), peclet::dem::Particles::capacity, computeContactSleepKokkos(), computeManifoldSleepKokkos(), peclet::dem::Particles::constraintCounts, peclet::dem::Particles::contactCount, peclet::dem::Particles::contacts, peclet::dem::Particles::contactSleep, peclet::dem::Particles::contactSlot, peclet::dem::Particles::deltaAngVel, peclet::dem::Particles::deltaPos, peclet::dem::Particles::deltaQuat, peclet::dem::Particles::deltaVel, demSolveContacts(), detectBoundaryKokkos(), detectContactsKokkos(), detectWallSdfKokkos(), peclet::dem::Particles::domain, peclet::dem::Particles::dt, peclet::dem::Particles::ensureCapacity(), peclet::dem::Particles::extForce, peclet::dem::Particles::extForceActive, finalCommitKokkos(), findCollisionsGrow(), findCollisionsVerlet(), freezeAsleepKokkos(), generateGhostsKokkos(), peclet::dem::Particles::gid, peclet::dem::Particles::globalScale, peclet::dem::Particles::gravity, peclet::dem::Particles::groundedLevel, peclet::dem::Particles::growthFactor, peclet::dem::Particles::growthRate, peclet::dem::Particles::invInertia, peclet::dem::Particles::invMass, peclet::dem::Particles::invMassEff, peclet::dem::Particles::manifoldCount, peclet::dem::Particles::manifolds, peclet::dem::Particles::manifoldSleep, peclet::dem::Particles::materialId, peclet::dem::Particles::maxOverlap, maxOwnedRadius(), peclet::dem::Particles::numParticles, peclet::dem::Particles::numPlanes, peclet::dem::Particles::numReal, peclet::dem::Particles::numWalls, peclet::dem::Particles::pairMaterials, peclet::dem::Particles::pairs, peclet::dem::Domain::periodic_x, peclet::dem::Domain::periodic_y, peclet::dem::Domain::periodic_z, peclet::dem::Particles::planes, peclet::dem::Particles::pos, peclet::dem::Particles::posPred, predictVelocityKokkos(), peclet::dem::Particles::quat, peclet::dem::Particles::quatPred, peclet::dem::Particles::rad, readInt(), peclet::dem::Particles::realIndices, reduceContactsToManifoldsKokkos(), peclet::dem::Particles::scale, peclet::dem::Particles::sdfGrid, peclet::dem::Particles::shapeId, peclet::dem::Particles::shapes, peclet::dem::Particles::shell, peclet::dem::Particles::sleepCounter, peclet::dem::Particles::sleepCurCount, peclet::dem::Particles::sleepImmovableFrac, peclet::dem::Particles::sleepingEnabled, peclet::dem::Particles::sleepK, peclet::dem::Particles::sleepMovingWall, peclet::dem::Particles::sleepPrevCount, peclet::dem::Particles::sleepScale, peclet::dem::Particles::sleepWakeLostContact, peclet::dem::Particles::targetScale, peclet::dem::Particles::thermostatKB, peclet::dem::Particles::thermostatTau, peclet::dem::Particles::thermostatTemp, peclet::dem::Particles::topGhost, updateGrowthScalesKokkos(), updateSleepKokkos(), peclet::dem::Particles::vel, peclet::dem::Particles::velPred, peclet::dem::Particles::verletSkinFrac, wakeContactChangeKokkos(), wakeDisturbedKokkos(), peclet::dem::Particles::wakeScale, peclet::dem::Particles::wallGrid, peclet::dem::Particles::walls, peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by peclet::dem::Simulation::step().
|
inline |
Max pair interpenetration on the committed state (faithful to CUDA Simulation::compute_overlaps): copy committed pos/quat into the predicted buffers, regenerate the periodic ghosts from that state, then run the same broad/narrow phase as demStep and return the recorded max overlap.
No solve.
Definition at line 185 of file sim.hpp.
References peclet::dem::Particles::angVel, peclet::dem::Particles::angVelPred, peclet::dem::Particles::baseRadius, calculateGhostCapacity(), peclet::dem::Particles::capacity, peclet::dem::Particles::contactCount, peclet::dem::Particles::contacts, detectBoundaryKokkos(), detectContactsKokkos(), detectWallSdfKokkos(), peclet::dem::Particles::domain, peclet::dem::Particles::ensureCapacity(), findCollisionsGrow(), generateGhostsKokkos(), peclet::dem::Particles::gid, peclet::dem::Particles::globalScale, peclet::dem::Particles::invMass, peclet::dem::Particles::materialId, peclet::dem::Particles::maxOverlap, maxOwnedRadius(), peclet::dem::Particles::numParticles, peclet::dem::Particles::numPlanes, peclet::dem::Particles::numReal, peclet::dem::Particles::numWalls, peclet::dem::Particles::pairMaterials, peclet::dem::Particles::pairs, peclet::dem::Particles::planes, peclet::dem::Particles::pos, peclet::dem::Particles::posPred, peclet::dem::Particles::quat, peclet::dem::Particles::quatPred, peclet::dem::Particles::rad, readInt(), peclet::dem::Particles::realIndices, peclet::dem::Particles::scale, peclet::dem::Particles::sdfGrid, peclet::dem::Particles::shapeId, peclet::dem::Particles::shapes, peclet::dem::Particles::shell, peclet::dem::Particles::topGhost, peclet::dem::Particles::vel, peclet::dem::Particles::velPred, peclet::dem::Particles::wallGrid, and peclet::dem::Particles::walls.
Referenced by peclet::dem::Simulation::computeOverlaps().
|
inline |
After predictVelocity: re-freeze the currently-asleep bodies so gravity/prediction do not move them — velPred = angVelPred = 0, posPred = pos, quatPred = quat.
Definition at line 31 of file sleeping.hpp.
Referenced by demStep().
|
inline |
Effective inverse mass for the solve: a sleeping body (real, or a periodic ghost whose real is asleep) is immovable — invMassEff = 0.
Everything else keeps its real invMass. Built over the full body-slot span (owned + ghosts); the driver's swap points every solve kernel at it.
Definition at line 58 of file sleeping.hpp.
Referenced by demStep().
|
inline |
Per-manifold "both endpoints asleep" flag (a static wall, bodyB < 0, counts as asleep).
Such manifolds are excluded from colouring / sweeps / the multilevel hierarchy but STILL carry their frozen force network through the warm-start ledger (the caller never skips the ledger kernels).
Definition at line 74 of file sleeping.hpp.
References peclet::dem::ManifoldC::bodyA, peclet::dem::ManifoldC::bodyB, and peclet::dem::ManifoldC::num_points.
Referenced by demStep().
|
inline |
Per-contact twin of computeManifoldSleepKokkos for the position colouring.
Definition at line 95 of file sleeping.hpp.
References peclet::dem::ContactC::bodyA, and peclet::dem::ContactC::bodyB.
Referenced by demStep().
|
inline |
Wake pass (before the solve): a sleeper is woken when actually disturbed.
Over this substep's manifolds — (a) a manifold pairing it with an AWAKE body whose speed exceeds wakeSpeed wakes it; (c) a contact with a MOVING wall (wallVel != 0) wakes it (and flags it never-sleep this substep). Also tallies each real body's live contact count into curCount for the caller's contact-set-change wake rule (b). velPred is the post-predict / post-freeze velocity (awake bodies carry their real speed, sleepers carry 0).
Definition at line 117 of file sleeping.hpp.
References peclet::dem::ManifoldC::bodyA, peclet::dem::ManifoldC::bodyB, peclet::dem::ManifoldC::num_points, peclet::dem::ManifoldC::wallVel_sum, peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
Referenced by demStep().
|
inline |
Contact-set-change wake rule (b): wake any still-asleep body whose live contact count differs from the stored one (a support gained or lost), then refresh the store.
Also clears the counter of a moving-wall body so it can never accumulate toward sleep.
Definition at line 176 of file sleeping.hpp.
Referenced by demStep().
|
inline |
Sleep detection (after the commit): an AWAKE, grounded body whose linear AND angular motion has stayed below sleepSpeed for K consecutive substeps is put to sleep (velocity + spin zeroed).
Any body at/above the threshold, ungrounded, or on a moving wall resets its counter. vel / angVel are the committed velocities of this substep.
Definition at line 205 of file sleeping.hpp.
Referenced by demStep().
|
inline |
Definition at line 42 of file solve_driver.hpp.
Referenced by computeOverlapsKokkos(), peclet::dem::Simulation::debugColoringConflicts(), demStep(), peclet::dem::Simulation::numContacts(), and peclet::dem::Simulation::numManifolds().
|
inline |
Definition at line 47 of file solve_driver.hpp.
Referenced by demSolveContacts().
|
inline |
gid(i) = base + i over [0, n) — the per-rank global-id re-base of the distributed step (namespace scope: nvcc forbids KOKKOS_LAMBDA in member functions).
Definition at line 55 of file solve_driver.hpp.
|
inline |
Largest effective particle radius over the owned set (= max scale × globalScale, growth included).
The ghost band + broadphase margin are sized off THIS, not globalScale directly, so they scale with the actual grain size — set particles in SI (radius = 1e-3, globalScale left at 1) and the halo layer follows automatically. For the usual convention (globalScale ≈ grain size, scale ≈ 1) it is numerically identical to the old 1.0*globalScale.
Definition at line 67 of file solve_driver.hpp.
References peclet::dem::Particles::baseRadius, peclet::dem::Particles::globalScale, peclet::dem::Particles::numReal, and peclet::dem::Particles::scale.
Referenced by computeOverlapsKokkos(), and demStep().
|
inline |
Broad phase with an automatically-grown pair buffer.
findCollisionsArborX guards its pair WRITES at maxPairs but returns the RAW candidate count, which can exceed P.pairs' capacity once a bed compacts (more neighbour pairs than the buffer holds — e.g. a fluidized bed driven denser by the CFD-DEM drag). Feeding that raw count straight into detectContactsKokkos as its loop bound makes the narrowphase read P.pairs out of bounds → cudaErrorIllegalAddress. Here we detect the overflow, reallocate P.pairs (with headroom so an oscillating count doesn't realloc every step) and re-run once so no candidate pair is silently dropped, then clamp defensively so the returned count is ALWAYS ≤ the buffer extent — the narrowphase can never walk off the end regardless.
Definition at line 88 of file solve_driver.hpp.
References peclet::dem::Particles::crad(), peclet::dem::Particles::domain, findCollisionsArborX(), peclet::dem::Particles::maxPairs, peclet::dem::Particles::numParticles, peclet::dem::Particles::numReal, peclet::dem::Particles::pairCount, peclet::dem::Particles::pairs, peclet::dem::Particles::posPred, peclet::dem::Domain::size, peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by computeOverlapsKokkos(), demStep(), findCollisionsVerlet(), and hertzRebuildPairs().
|
inline |
Verlet-cached impulse broadphase (single-GPU, non-periodic).
Reuse the last ArborX candidate list while no particle's predicted position has moved more than skin/2 since the build; the list is built at margin + skin, so every within-margin pair is still present between rebuilds — a SUPERSET, so the narrowphase yields identical contacts (order differs -> run-scatter, like the colouring/fused paths). Rebuilds on an invalid cache, growth beyond the skin, or the displacement bound. Composes with sleeping: a frozen bed has zero displacement, so it never rebuilds. The caller guarantees non-periodic (no per-step ghost-slot churn) and verletSkinFrac > 0.
Definition at line 110 of file solve_driver.hpp.
References findCollisionsGrow(), peclet::dem::Particles::impNumPairs, peclet::dem::Particles::impRefMaxRad, peclet::dem::Particles::impRefPos, peclet::dem::Particles::numReal, peclet::dem::Particles::posPred, and peclet::dem::Particles::verletSkinFrac.
Referenced by demStep().
|
inline |
One full velocity + position contact solve over the already-built contacts/manifolds (see file comment).
Runs between the narrow phase and finalCommit; the caller owns ghost construction, broad/narrow phase and the commit.
Definition at line 224 of file solve_driver.hpp.
References accumulateNormalImpulseKokkos(), peclet::dem::Particles::angVel, peclet::dem::Particles::angVelPred, applyUpdatesKokkos(), applyVelocityAndPredictPositionKokkos(), applyVelocityDeltasAveragedKokkos(), applyVelocityDeltasKokkos(), peclet::dem::Particles::asleep, peclet::dem::Particles::baseRadius, peclet::dem::Particles::bodyColorMask, peclet::dem::Particles::bodyOrphan, peclet::dem::Particles::bodyOrphanVPeak, peclet::dem::Particles::bodyWinner, peclet::dem::Particles::bucketCursor, buildCoarseBucketsKokkos(), buildColorBucketsKokkos(), buildContactHierarchyKokkos(), buildLevelColorBucketsKokkos(), colorContactsIncrementalKokkos(), colorContactsKokkos(), colorManifoldsIncrementalKokkos(), colorManifoldsKokkos(), commitContactColorKokkos(), commitPairKeysLambdaKokkos(), peclet::dem::Particles::commitPerm, commitPosImpulseKokkos(), computeHeightLevelsKokkos(), computePlaneLoadKokkos(), computeSideFlagsKokkos(), computeVn0Kokkos(), peclet::dem::Particles::constraintCounts, peclet::dem::Particles::contactColor, peclet::dem::Particles::contactKeys, peclet::dem::Particles::contacts, peclet::dem::Particles::contactSleep, peclet::dem::Particles::contactSlot, countFrictionContactsKokkos(), decayBodyOrphanKokkos(), peclet::dem::Particles::deltaAngVel, peclet::dem::Particles::deltaPos, peclet::dem::Particles::deltaQuat, peclet::dem::Particles::deltaVel, demFusedWanted(), demMakeFusedCtx(), demMakeMlFusedCtx(), peclet::dem::Particles::dt, peclet::dem::Particles::extForceActive, peclet::dem::Particles::frictionDynamic, peclet::dem::Particles::fusedBar, gatherWarmLambdaKokkos(), peclet::dem::Particles::gid, peclet::dem::Particles::globalScale, peclet::dem::Particles::graphCache, peclet::dem::Particles::gravity, peclet::dem::Particles::groundedLevel, peclet::dem::Particles::growthRate, peclet::dem::Particles::heightLevel, peclet::dem::Particles::invInertia, peclet::dem::Particles::invMass, peclet::dem::mldetail::kGateSlip, peclet::dem::Particles::lambdaAcc, peclet::dem::Particles::lambdaT, peclet::dem::Particles::levelKey, peclet::dem::Particles::levelPerm, makePGSManifoldSweep(), peclet::dem::Particles::manifoldColor, peclet::dem::Particles::manifoldPersistent, peclet::dem::Particles::manifolds, peclet::dem::Particles::manifoldSleep, markPersistentManifoldsKokkos(), peclet::dem::Particles::maxApproach, peclet::dem::Particles::maxApproachQS, peclet::dem::FusedSweepCtx::maxBucket, peclet::dem::Particles::maxOverlap, peclet::dem::MlFusedCtx::maxWork, peclet::dem::Particles::mlBucketPerm, peclet::dem::Particles::mlColorPacked, peclet::dem::Particles::mlGrp, peclet::dem::Particles::mlInvMassG, peclet::dem::Particles::mlMassG, peclet::dem::Particles::mlMate, peclet::dem::Particles::mlOffsDev, peclet::dem::Particles::mlParent, peclet::dem::Particles::mlVelG, peclet::dem::Particles::mlVelG0, multilevelCoarseCycleKokkos(), peclet::dem::ContactHierarchy::numLevels, peclet::dem::Particles::numParticles, peclet::dem::Particles::numReal, peclet::dem::Particles::pairKeys, PECLET_DEM_GRAPH_LOOP, peclet::dem::Particles::planeFriction, peclet::dem::Particles::pos, peclet::dem::Particles::posCommitPerm, peclet::dem::Particles::posImpulse, peclet::dem::Particles::positionIterations, peclet::dem::Particles::posLambdaContact, peclet::dem::Particles::posLastFullColors, peclet::dem::Particles::posOffsDev, peclet::dem::Particles::posPerm, peclet::dem::Particles::posPred, peclet::dem::Particles::posPrevContactCount, peclet::dem::Particles::prevContactColor, peclet::dem::Particles::prevContactKeys, peclet::dem::Particles::prevLambda, peclet::dem::Particles::prevLambdaT, peclet::dem::Particles::prevManifoldColor, peclet::dem::Particles::prevMatched, peclet::dem::Particles::prevPairCount, peclet::dem::Particles::prevPairKeys, peclet::dem::Particles::prevPosImpulse, peclet::dem::Particles::prevRestBank, peclet::dem::Particles::prevRestVPeak, peclet::dem::Particles::quat, peclet::dem::Particles::quatPred, readFloat(), peclet::dem::Particles::realIndices, peclet::dem::Particles::restBank, peclet::dem::Particles::restitutionModel, peclet::dem::Particles::restitutionNormal, peclet::dem::Particles::restitutionTangent, peclet::dem::Particles::restRel, peclet::dem::Particles::restVPeak, scatterOrphanBanksKokkos(), peclet::dem::Particles::sideFlags, peclet::dem::Particles::sleepingEnabled, solveContactFrictionKokkos(), solvePositionColoredGSKokkos(), solvePositionKokkos(), solveVelocityColoredGSKokkos(), solveVelocityKokkos(), solveVelocityPGSBucketsKokkos(), solveVelocityPGSKokkos(), peclet::dem::Particles::stabilizationMode, updateGroundedLevelsKokkos(), updateRestitutionBankKokkos(), peclet::dem::Particles::vel, peclet::dem::Particles::velLastFullColors, peclet::dem::Particles::velocityIterations, peclet::dem::Particles::velocityUseGS, peclet::dem::Particles::velOffsDev, peclet::dem::Particles::velPerm, peclet::dem::Particles::velPred, peclet::dem::Particles::vn0, peclet::dem::Particles::vt0, peclet::dem::Particles::wallFrictionMax, warmStartApplyKokkos(), peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by demStep().
|
inline |
Rebuild the Hertz cached pair list with margin skin, carrying the Mindlin shear history across by pair key (permutation sort of the OLD list, binary search from the NEW).
Keys are built from GLOBAL ids (identity == local index single-rank, so single-GPU behaviour is unchanged; under MPI ghost slots are not stable identities, gids are).
Definition at line 50 of file solve_driver_force.hpp.
References findCollisionsGrow(), peclet::dem::Particles::gid, peclet::dem::Particles::hertzDispMax, peclet::dem::Particles::hertzKeys, peclet::dem::Particles::hertzNumPairs, peclet::dem::Particles::hertzPrevCount, peclet::dem::Particles::hertzPrevKeys, peclet::dem::Particles::hertzPrevXi, peclet::dem::Particles::hertzRefPos, peclet::dem::Particles::hertzSnPair, peclet::dem::Particles::hertzXi, peclet::dem::Particles::pairs, peclet::dem::Particles::pos, and peclet::dem::Particles::posPred.
Referenced by peclet::dem::HertzMindlinLaw::rebuild().
|
inline |
Save the current list (sorted by key) so the NEXT rebuild can carry the history.
Definition at line 103 of file solve_driver_force.hpp.
References peclet::dem::Particles::hertzKeys, peclet::dem::Particles::hertzNumPairs, peclet::dem::Particles::hertzPrevCount, peclet::dem::Particles::hertzPrevKeys, peclet::dem::Particles::hertzPrevXi, and peclet::dem::Particles::hertzXi.
Referenced by peclet::dem::HertzMindlinLaw::commitHistory().
Zero the force/torque accumulator rows [lo, hi) — under MPI the pair kernels atomically accumulate onto ghost slots too (Newton's third law), but only owned rows are consumed and cleared by the integrator; without this the ghost rows grow without bound.
Definition at line 190 of file solve_driver_force.hpp.
World radii rad(i) = scale(i) * globalScale * baseRadius over [0, n) (n = owned + ghosts after a halo gather; the driver's own preamble fills the owned span).
Definition at line 207 of file solve_driver_force.hpp.
|
inline |
nsteps explicit force-based DEM steps of size dt with force law Law (see file comment).
The force/torque accumulators reuse the impulse engine's deltaVel/deltaAngVel scratch.
Definition at line 228 of file solve_driver_force.hpp.
References peclet::dem::Particles::angVel, peclet::dem::Particles::baseRadius, peclet::dem::Particles::deltaAngVel, peclet::dem::Particles::deltaVel, peclet::dem::Particles::globalScale, peclet::dem::Particles::gravity, hertzIntegrateKokkos(), hertzMaxDisp2Kokkos(), peclet::dem::Particles::hertzNumPairs, peclet::dem::Particles::hertzNumWallCand, peclet::dem::Particles::hertzRefPos, peclet::dem::Particles::invInertia, peclet::dem::Particles::invMass, peclet::dem::Particles::numReal, peclet::dem::Particles::pos, peclet::dem::Particles::posPred, peclet::dem::Particles::quat, peclet::dem::Particles::rad, peclet::dem::Particles::scale, peclet::dem::Particles::shapes, peclet::dem::Particles::vel, and peclet::dem::Particles::velPred.
Referenced by demStepHertz().
|
inline |
nsteps of the soft-sphere Hertz-Mindlin engine — the single-GPU instantiation of the force-based driver (kept as the historical entry point; see demStepForce).
Definition at line 338 of file solve_driver_force.hpp.
References demStepForce().
Referenced by peclet::dem::Simulation::stepHertz().
|
inline |
Force-chain normal load, accumulated over the velocity iterations: contacts(idx).friction_lambda_n += approach / w_n.
Body-body AND wall (boundary) contacts — a grain buried under the bed thus gets the WEIGHT TRANSMITTED FROM ABOVE pressing it into the wall, not just its own one-shot gravity approach (computePlaneLoad). Without this a deep bed slips against a moving wall instead of being dragged up (a rotating drum stays flat).
Definition at line 32 of file solver_friction.hpp.
References add3(), peclet::dem::ContactC::bodyA, peclet::dem::ContactC::bodyB, peclet::dem::ContactC::boundaryVel, peclet::dem::detail::computeW(), cross3v(), dot3(), ldF3(), peclet::dem::ContactC::normal, peclet::dem::ContactC::rA, peclet::dem::ContactC::rB, scale3(), sub3(), peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
Referenced by demSolveContacts().
|
inline |
Plane (idB<0) one-shot loads.
Zeros planeFriction first (both columns), then sets the per-contact friction_lambda_n and the per-body max plane load (.x).
Definition at line 87 of file solver_friction.hpp.
References add3(), peclet::dem::ContactC::bodyA, peclet::dem::ContactC::bodyB, peclet::dem::ContactC::boundaryVel, peclet::dem::detail::computeW(), cross3v(), dot3(), ldF3(), peclet::dem::ContactC::normal, peclet::dem::ContactC::rA, sub3(), peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
Referenced by demSolveContacts().
|
inline |
Per-body active-contact count into planeFriction(:,1).
Definition at line 123 of file solver_friction.hpp.
References peclet::dem::ContactC::bodyA, peclet::dem::ContactC::bodyB, and peclet::dem::ContactC::friction_lambda_n.
Referenced by demSolveContacts().
|
inline |
One count-averaged Coulomb friction sweep.
Zeros the delta arrays first, then accumulates the tangential impulse (clamped by mu*normal-load, divided by the larger contact count) into them.
Definition at line 142 of file solver_friction.hpp.
References add3(), peclet::dem::ContactC::bodyA, peclet::dem::ContactC::bodyB, peclet::dem::ContactC::boundaryFriction, peclet::dem::ContactC::boundaryVel, cross3v(), dot3(), peclet::dem::ContactC::friction_lambda_n, ldF3(), peclet::dem::ContactC::normal, peclet::dem::ContactC::rA, peclet::dem::ContactC::rB, scale3(), sub3(), peclet::dem::F3::x, peclet::dem::F4::x, peclet::dem::F3::y, peclet::dem::F4::y, peclet::dem::F3::z, and peclet::dem::F4::z.
Referenced by demSolveContacts().
|
inline |
Fused-sweep policy (read once).
PECLET_DEM_NO_FUSED=1 forces the launch path everywhere; PECLET_DEM_FUSED=1 forces the fused path everywhere it applies. Default: fused only where CUDA-graph replay is unavailable — the distributed step (ghost syncs inside the loops forbid capture) and PECLET_DEM_NO_GRAPH runs. Measured on the 25k/100k Dosta beds (RTX 5080): graph replay beats the fused kernels by 2-4% on the solo GPU (pipelined graph-node transitions are cheaper than software grid barriers once the step is GPU-bound), while capture-less paths pay the full per-launch submission storm that fusion removes (25k multilevel: 17.4 -> 16.2 ms/step with graphs off).
Definition at line 59 of file solver_fused.hpp.
Referenced by demSolveContacts().
|
inline |
Fill a FusedSweepCtx from buildColorBucketsKokkos's host offsets: async-upload them into the pooled device view and record the largest bucket.
The caller owns the policy decision (demFusedWanted); no-CUDA / empty / oversize => inactive ctx.
Definition at line 246 of file solver_fused.hpp.
References peclet::dem::FusedSweepCtx::bar, peclet::dem::FusedSweepCtx::maxBucket, and peclet::dem::FusedSweepCtx::offsDev.
Referenced by demSolveContacts().
| void peclet::dem::hertzPairEMu | ( | int | matA, |
| int | matB, | ||
| PairTableView | pairTable, | ||
| float | eGlobal, | ||
| float | muGlobal, | ||
| float & | e, | ||
| float & | mu | ||
| ) |
Pairwise (e, mu) lookup shared with the narrowphase convention: pair table if present, global fallback otherwise.
Definition at line 27 of file solver_hertz.hpp.
References kMaxMaterials.
Referenced by hertzPairForcesKokkos(), and hertzShapePairForcesKokkos().
| float peclet::dem::hertzBetaD | ( | float | e | ) |
Restitution -> damping ratio beta_d = ln e / sqrt(ln^2 e + pi^2) (e in (0, 1]; e <= 0 -> -1, the critically-damped limit used by LIGGGHTS for e -> 0).
Definition at line 41 of file solver_hertz.hpp.
Referenced by hertzForce(), and hertzShapePairForcesKokkos().
| F3 peclet::dem::hertzForce | ( | float | delta, |
| F3 | nhat, | ||
| F3 | vrel, | ||
| float | rStar, | ||
| float | mStar, | ||
| float | eStar, | ||
| float | gStar, | ||
| float | e, | ||
| float | mu, | ||
| float | dt, | ||
| F3 & | xi | ||
| ) |
One Hertz–Mindlin force evaluation for a sphere-sphere or sphere-wall contact.
Returns the force ON body A applied at the contact point (linear) and updates xi in place. nhat points from B to A (push direction on A). vrel = contact velocity of A relative to B.
Definition at line 53 of file solver_hertz.hpp.
References add3(), dot3(), hertzBetaD(), scale3(), and sub3().
Referenced by hertzPairForcesKokkos().
|
inline |
Cached-pair forces: overlap from current positions; history resets when a cached pair is currently separated.
Forces/torques accumulate atomically (a body appears in many pairs).
Definition at line 88 of file solver_hertz.hpp.
References add3(), cross3v(), dot3(), force(), hertzForce(), hertzPairEMu(), loadF3(), scale3(), sub3(), and peclet::dem::F3::x.
Referenced by peclet::dem::HertzMindlinLaw::pairForces().
|
inline |
SDF-wall forces (per particle x wall).
Gradient by central differences at half a grid cell. The wall's rigid surface velocity enters vrel; per-(particle, wall) history in xiWall.
Definition at line 148 of file solver_hertz.hpp.
Referenced by peclet::dem::HertzMindlinLaw::wallForces().
|
inline |
Build the wall candidate list: particles within (radius + skin) of any wall's zero level.
Between pair rebuilds nothing else can reach a wall (same Verlet-skin argument as the pair list), so the per-step wall pass only visits these slots. Encodes i * maxWalls + wallIdx.
Definition at line 343 of file solver_hertz.hpp.
References sampleWallSdf().
Referenced by peclet::dem::HertzMindlinLaw::rebuild().
|
inline |
Symplectic-Euler kick-drift (MUSEN-style) + displacement tracking for the Verlet rebuild.
Spheres: isotropic inertia, angular update needs no orientation.
Definition at line 374 of file solver_hertz.hpp.
Referenced by demStepForce().
|
inline |
Max squared displacement since the last pair build (called only at rebuild checks – keeping this out of the integrate kernel avoids a per-step single-address atomic).
Definition at line 429 of file solver_hertz.hpp.
References dot3(), loadF3(), and sub3().
Referenced by demStepForce().
|
inline |
Non-spherical pairs: per-point Hertz springs over A's point shell against B's SDF (the same one-sided sampling convention as the narrowphase), ONE Mindlin patch history per pair.
Per shell point k: penetration delta_k from B's SDF, its own Hertz normal spring + dashpot applied AT THE POINT (correct face/edge force distribution and torques); the tangential spring acts at the load-weighted patch centroid, bounded by mu * (sum of point spring forces). R* combines per-shape CONTACT radii (Hertz curvature is undefined at faces/edges – this is the standard point-spring approximation; spheres use their true radii via params.x).
Definition at line 454 of file solver_hertz.hpp.
References add3(), cross3v(), dot3(), force(), hertzBetaD(), hertzPairEMu(), invRotateVector(), len3(), loadF3(), loadF4(), peclet::dem::ShapeDesc::numPoints, peclet::dem::ShapeDesc::params, rotateVector(), scale3(), sdfEvalShape(), peclet::dem::ShapeDesc::shellOffset, SPHERE, sub3(), peclet::dem::ShapeDesc::type, peclet::dem::F3::x, peclet::dem::F4::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by peclet::dem::HertzMindlinLaw::pairForces().
|
inline |
Build the aggregation hierarchy + per-level crossing-manifold colorings.
Eligibility for both matching and coarse solving: mldetail::eligible (active, non-dup, persistent, quasi-static, support-oriented). Walls (bodyB < 0) never merge but their manifolds ARE coarse contacts (the momentum sink). Returns the host hierarchy description.
Definition at line 128 of file solver_multilevel.hpp.
Referenced by demSolveContacts().
|
inline |
One multilevel stabilization cycle over an already-built hierarchy: fine colored smoothing is the caller's business; this runs the coarse leg (fine -> coarse), updating velPred in place.
Eligibility is baked into the packed per-level colours (slot 63 = skip), and the composed body -> group map is rebuilt from identity each cycle (numReal-sized passes; cheap next to the sweeps). Dense per-(level, colour) buckets for the coarse cycle, built ONCE per hierarchy (the structure is static for the whole substep, so every sweep of every stabilization iteration reuses them instead of scanning ALL manifolds per colour — measured 40% of GPU time and the bulk of the launch-submission bound at 25k). perm segment for level l lives at [(l-1)*numManifolds, l*numManifolds). Colour slots >= numColors (kMlSlotSkip = uncoloured / non-crossing) are excluded — exactly the set the scan-mode colour filter never matched.
Definition at line 379 of file solver_multilevel.hpp.
References buildColorBucketsKokkos(), peclet::dem::MlScratch::colorPacked, peclet::dem::ContactHierarchy::numColors, and peclet::dem::ContactHierarchy::numLevels.
Referenced by demSolveContacts().
|
inline |
Build the fused-coarse-cycle context from an already-built hierarchy + its dense buckets: flatten the per-level colour offsets into the pooled device view (async upload) and record the grid-sizing work bound.
Inactive (maxWork = 0) when fused sweeps are off / no CUDA / the pooled view is too small.
Definition at line 651 of file solver_multilevel.hpp.
References peclet::dem::MlFusedCtx::bar, peclet::dem::MlFusedMeta::coarseSweeps, flat(), peclet::dem::ContactHierarchy::groupOff, peclet::dem::MlFusedMeta::groupOff, kMlMaxLevels, peclet::dem::MlFusedCtx::maxWork, peclet::dem::MlFusedCtx::meta, peclet::dem::ContactHierarchy::numColors, peclet::dem::MlFusedMeta::numColors, peclet::dem::ContactHierarchy::numGroups, peclet::dem::MlFusedMeta::numGroups, peclet::dem::ContactHierarchy::numLevels, peclet::dem::MlFusedMeta::numLevels, peclet::dem::MlFusedMeta::numReal, peclet::dem::MlFusedMeta::offsBase, peclet::dem::MlFusedCtx::offsDev, peclet::dem::ContactHierarchy::parentOff, peclet::dem::MlFusedMeta::parentOff, and peclet::dem::MlFusedMeta::permBase.
Referenced by demSolveContacts().
|
inline |
Definition at line 701 of file solver_multilevel.hpp.
Referenced by demSolveContacts().
|
inline |
Accumulate XPBD position corrections for numContacts contacts.
Definition at line 36 of file solver_position.hpp.
Referenced by demSolveContacts().
|
inline |
Greedy graph-colour the contacts (raw bodyA/bodyB): no two contacts sharing a body get the same colour.
Round-based max-index arbitration, identical machinery to colorManifoldsKokkos but over the per-contact graph with direct (non-realIdx) body slots; every contact is active. numBodies is the body-slot count (numParticles, incl. periodic ghosts, which the position solve corrects independently). Returns the number of colours used.
Definition at line 154 of file solver_position.hpp.
Referenced by demSolveContacts().
|
inline |
Incremental (warm-started) contact colouring for the single-GPU PGS position solve.
Twin of colorManifoldsIncrementalKokkos, but over the per-contact graph: key every contact by its canonical pair, carry the previous substep's colour by that key (sorted ledger), seed the per-body masks, and re-arbitrate only the NEW (-1) contacts. A pair can own MORE than one contact (non-spherical multi-point patches) and periodic ghost slots churn, so the carried colours are CONFLICT-CHECKED while the mask is built (a repeated colour on a shared body forces a full recolour that substep) — the sphere / non-periodic bed hits the fast path, everything else stays correct by falling back. forceFull bypasses the carry. keysOut holds this substep's contact keys for the subsequent commit. Returns the number of colours used.
Definition at line 253 of file solver_position.hpp.
Referenced by demSolveContacts().
|
inline |
Commit this substep's per-contact (key, colour) sorted by key, for next substep's warm gather.
Definition at line 395 of file solver_position.hpp.
Referenced by demSolveContacts().
|
inline |
Colored Gauss–Seidel XPBD overlap solve: sweep the numColors colour classes in order, applying each contact's non-penetration correction directly to posPred (in place, translation only).
Same per-contact math as solvePositionKokkos — only the write-back differs (in-place RMW instead of atomic-accumulate + count-average). Race-free because a colour is an independent set of contacts. One outer call = one full sweep over all colours; the caller loops it positionIterations times. Dense-bucket mode (colorPerm/colorOffs from buildColorBucketsKokkos) covers only each colour's own contacts; the fused mode collapses the whole sweep into one kernel — both bit-identical.
Definition at line 509 of file solver_position.hpp.
Referenced by demSolveContacts().
|
inline |
Accumulate normal-restitution velocity deltas for numManifolds manifolds.
Definition at line 39 of file solver_velocity.hpp.
Referenced by demSolveContacts().
|
inline |
Apply the accumulated velocity deltas AVERAGED by the per-body manifold count — the velocity- solve twin of the position solve's constraint-count averaging (applyUpdatesKokkos).
A body in a dense pile receives one full-strength impulse per touching manifold; the raw Jacobi SUM overshoots by ~the contact count and diverges hard for e ≳ 0.5 (a settled 180k glass-bead bed switched to e=0.8 grew |v| by ~5x per substep). A lone binary collision (count 1) is unchanged.
Definition at line 233 of file solver_velocity.hpp.
Referenced by demSolveContacts().
|
inline |
Greedy graph-colour the manifolds: no two manifolds sharing a real body get the same colour.
Round-based max-index (Jones–Plassmann) arbitration, no adjacency lists: each round every still- uncoloured manifold contends for its endpoint bodies via atomicMax(bodyWinner, idx); a manifold that wins BOTH endpoints has no uncoloured conflict this round, so it commits the lowest colour free at either endpoint (a per-body bitmask) — and, as the unique winner of those bodies, updates the masks race-free. Inactive manifolds (empty, or the periodic-dedup duplicate realA>realB) are tagged -2 and skipped by the solve. Runs once per step; the colouring is reused across the velocity sweeps. Returns the number of colours used (0 if no active manifolds).
Definition at line 277 of file solver_velocity.hpp.
Referenced by demSolveContacts().
|
inline |
Incremental (warm-started) manifold colouring for the single-GPU PGS path.
Carry each surviving pair's colour from the previous substep — matched by pair key against the sorted (prevPairKeys, prevColor) ledger committed alongside the warm impulses — seed the per-body colour masks from those carried colours, then run the SAME Jones-Plassmann arbitration ONLY over the NEW (colour == -1) manifolds. Result is bit-identical in FORM to colorManifoldsKokkos (a valid body-disjoint colouring + numColors); only the assignment differs.
VALIDITY (why the carried colours need no re-arbitration): within a single-GPU run realIndices are stable, so a surviving pair key maps to the same two real bodies. Last substep's colouring was valid, so any two survivors sharing a real body carried DIFFERENT colours — the survivor subset is still a valid colouring. A conflict edge can only appear via a NEW manifold, which is arbitrated against the frozen (carried) masks. Hence seeding the masks non-atomically-safe with atomic_or and running the rounds over the -1 set reproduces a valid colouring. forceFull bypasses the carry entirely (fresh substep / colour-count-creep recompaction) — identical output to colorManifoldsKokkos. Single-GPU only: under MPI migration a carried colour can cross into a neighbourhood it never arbitrated against, so the distributed path keeps the full recolour.
Definition at line 395 of file solver_velocity.hpp.
Referenced by demSolveContacts().
|
inline |
-— Warm-started projected Gauss-Seidel (PGS) velocity solve -— Nonsmooth contact dynamics (Moreau-Jean; Stewart-Trinkle LCP): per manifold an ACCUMULATED push impulse p >= 0 along the manifold normal, updated by colored GS sweeps and projected to p >= 0 (a contact may push, never pull; over-push is retracted in later sweeps).
At convergence the p's are the contact force network (x dt): a resting pile's chains carry exactly the weight above them, all velocities -> 0 – statics with no notion of "lower body" or gravity direction, momentum-conserving at every contact (the wall provides the reaction). Deep-pile convergence is bought by WARM STARTING: p is seeded from the previous substep's converged value (matched by pair key) and applied up front, so a static network is re-established in ~1 sweep per substep. Restitution enters as the target relative velocity -e*vn0 on the PRE-SOLVE approach vn0 (with the resting threshold), so fresh binary impacts reproduce the one-shot impulse exactly. Pre-solve approach velocity per manifold (the restitution bias), measured BEFORE the warm-start application. Same kinematics as the sweep kernel.
Definition at line 543 of file solver_velocity.hpp.
References add3(), peclet::dem::ManifoldC::bodyA, peclet::dem::ManifoldC::bodyB, cross3v(), dot3(), peclet::dem::detail::ld3(), peclet::dem::ManifoldC::normal_sum, peclet::dem::ManifoldC::num_points, peclet::dem::ManifoldC::rA_sum, peclet::dem::ManifoldC::rB_sum, scale3(), sub3(), peclet::dem::ManifoldC::torque_armA_sum, peclet::dem::ManifoldC::torque_armB_sum, peclet::dem::ManifoldC::wallVel_sum, peclet::dem::F3::x, peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
Referenced by demSolveContacts().
|
inline |
Event-level (Poisson) restitution bookkeeping, once per substep AFTER all velocity phases (restitutionModel == 1 only).
Per pair, two carried floats define the current impact EVENT:
Definition at line 612 of file solver_velocity.hpp.
References peclet::dem::ManifoldC::bodyA, peclet::dem::ManifoldC::bodyB, dot3(), peclet::dem::detail::genInvMass(), peclet::dem::detail::ld3(), peclet::dem::ManifoldC::normal_sum, peclet::dem::ManifoldC::num_points, peclet::dem::ManifoldC::rA_sum, peclet::dem::ManifoldC::rB_sum, peclet::dem::ManifoldC::restitution_sum, scale3(), sub3(), peclet::dem::ManifoldC::torque_armA_sum, peclet::dem::ManifoldC::torque_armB_sum, peclet::dem::ManifoldC::wallVel_sum, peclet::dem::F3::x, peclet::dem::F4::x, peclet::dem::F4::y, and peclet::dem::F4::z.
Referenced by demSolveContacts().
|
inline |
Orphan-account aging, once per substep over the OWNED bodies: both the balance and the carried event peak decay 1/64 per substep (e-fold ~3 ms at dt = 5e-5 — long enough for the rebound payout, which completes within ~2 ms of turnaround, short enough that a BURIED impactor's slowly re-fed credit cannot keep fluidizing its crater: with the pair-state 1/256 decay the 100k Dosta plateau crept 0.007 deeper), and once the peak ages below the resting threshold the whole account evaporates — stranded credit on a settling body never pops the pile later.
Definition at line 711 of file solver_velocity.hpp.
Referenced by demSolveContacts().
|
inline |
Orphan transfer: previous-ledger entries NOT matched by any current manifold (their pair died this substep) credit their remaining owed budget to the endpoint BODIES, mass-weighted — the heavier endpoint keeps the larger share (energy of a later release scales J^2/2m, so the light grain is the dangerous store and the heavy impactor is both the safe one and the event's physical carrier); boundary pairs (wall endpoint) credit everything to the particle.
The carried event peak joins by max. Key components are keyIdx identities: REAL slots on the single-GPU path (direct index); global ids under MPI — resolved through the sorted (gidSorted, slotSorted) map (an endpoint owned by another rank simply isn't found here; that rank's redundant ledger copy credits it).
Definition at line 738 of file solver_velocity.hpp.
Referenced by demSolveContacts().
|
inline |
Poisson-restitution diagnostics: (sum, max, count>0) over the committed owed-impulse store (namespace scope: nvcc forbids KOKKOS_LAMBDA in member functions).
Definition at line 802 of file solver_velocity.hpp.
Referenced by peclet::dem::Simulation::restBankStats(), and peclet::dem::Simulation::restOrphanStats().
|
inline |
Decide each persistent contact's treatment ONCE per substep (before any impulse is applied): 0 = symmetric momentum-conserving PGS, 1 = one-sided with B as the held ground side, 2 = A held.
One-sided requires the ground side grounded (contact path to the floor) and not rising. Flagged contacts get their warm impulse ZEROED: their ground side is held externally (recursively down to the floor), so the correct per-substep impulse is only the ~m g dt refill, accumulated from zero – warm-applying last substep's chain impulse one-sidedly would inject the whole column weight as upward velocity (measured: instant crush + churn from the inconsistent ledger).
Definition at line 830 of file solver_velocity.hpp.
References peclet::dem::ManifoldC::bodyA, peclet::dem::ManifoldC::bodyB, dot3(), peclet::dem::detail::ld3(), ldF3(), peclet::dem::ManifoldC::num_points, sub3(), peclet::dem::F3::x, peclet::dem::F3::y, and peclet::dem::F3::z.
Referenced by demSolveContacts().
|
inline |
Apply the warm-start impulses up front (order-independent: fixed impulses, atomic adds).
Definition at line 871 of file solver_velocity.hpp.
References peclet::dem::ManifoldC::bodyA, peclet::dem::ManifoldC::bodyB, cross3v(), dot3(), invRotateVector(), peclet::dem::detail::ld3(), peclet::dem::ManifoldC::normal_sum, peclet::dem::ManifoldC::num_points, peclet::dem::ManifoldC::rA_sum, peclet::dem::ManifoldC::rB_sum, rotateVector(), scale3(), sub3(), peclet::dem::ManifoldC::torque_armA_sum, peclet::dem::ManifoldC::torque_armB_sum, peclet::dem::F3::x, peclet::dem::F4::x, peclet::dem::F3::y, peclet::dem::F4::y, peclet::dem::F3::z, and peclet::dem::F4::z.
Referenced by demSolveContacts().
|
inline |
Build the shared per-manifold sweep functor (the colored launch loop, the fused kernels and the fused multilevel iteration loop all run this one body).
maxApproachQS empty => aliased to maxApproach (the duplicate atomic_max is idempotent).
Definition at line 1412 of file solver_velocity.hpp.
Referenced by demSolveContacts().
|
inline |
Returns true when the sweep (or, with loop, the whole iteration loop) was submitted; false ONLY in loop mode when the fused path is unavailable — the caller then runs its own host-side iteration loop (which calls back in per-iteration mode).
Definition at line 1462 of file solver_velocity.hpp.
Referenced by demSolveContacts().
|
inline |
Bucket the active coloured manifolds by (support level, colour) for the level-ordered ("multilevel") stabilization sweeps.
A manifold's level is the smaller of its bodies' height-from-floor BFS levels (wall/plane manifolds sit at their body's level, i.e. 0), clamped to 1023; ungrounded manifolds land in the last buckets. key = level*64 + colour; key-sorting a permutation groups each (level, colour) bucket contiguously, and the host bucket list (begin, end into the permutation) drives the ordered sweeps. Inactive and uncoloured manifolds (colour < 0: periodic dups, empty, mask-saturation leftovers – the main loop's Jacobi fallback owns those) are keyed out entirely.
Definition at line 1541 of file solver_velocity.hpp.
References peclet::dem::ManifoldC::bodyA, peclet::dem::ManifoldC::bodyB, and peclet::dem::ManifoldC::num_points.
Referenced by demSolveContacts().
|
inline |
Level-ordered symmetric sweep: launch one PGS kernel per (level, colour) bucket, ascending (bottom-up: a chain's load drains towards the floor in ~one pass) or descending (top-down: the return pass carries rebound waves back up).
Same impulse math and lambda >= 0 projection as the colored sweep (shared PGSManifoldSweep) – fully symmetric, exact momentum conservation; the ordering only accelerates transport. Launches are stream-ordered, so the Gauss-Seidel dependency between buckets needs no per-bucket fence.
Definition at line 1593 of file solver_velocity.hpp.
References peclet::dem::PGSManifoldSweep::solveOne().
Referenced by demSolveContacts().
|
inline |
Colored Gauss–Seidel normal-restitution solve: sweep the numColors colour classes in order, applying each manifold's impulse directly to velPred/angVelPred (in place).
Same per-manifold impulse math as solveVelocityKokkos (growth-velocity term, approach gate, resting-contact e=0 threshold, and the R·(invI_local·(Rᵀ J))·… world-space angular update) — only the write-back differs (in-place RMW instead of atomic-accumulate + count-average). Race-free because a colour is an independent set of manifolds. One outer call = one full sweep over all colours; the caller loops it velocityIterations times.
Definition at line 1615 of file solver_velocity.hpp.
Referenced by demSolveContacts().
|
inlineconstexpr |
Height-from-floor BFS levels for the level-ordered ("multilevel") stabilization pass: 0 at a wall/plane contact, else 1 + min over supporting contacts, kLevelInf with no contact path to the floor.
Recomputed FRESH each time the pass triggers – no warm start and no decay: a stale-low height would mis-order the sweeps, and the pass runs rarely enough that the exact BFS (early exit once a sweep changes nothing) is affordable. The support-orientation test (up vs 0.3|dx|) matches updateGroundedLevelsKokkos; ghost-slot positions keep the pair geometry periodic-aware.
Definition at line 286 of file contact_preprocessing.hpp.
Referenced by computeHeightLevelsKokkos().
|
constexpr |
Pair-material lookup: flat [K*K*2] table, entry ((a*K + b)*2) = restitution, +1 = friction.
Definition at line 79 of file narrowphase.hpp.
Referenced by hertzPairEMu(), and peclet::dem::Simulation::setPairMaterial().
|
inlineconstexpr |
6-bit colour slots per level in the packed word; slot value 63 = not crossing / not eligible at that level (skipped by the coarse sweeps).
Definition at line 43 of file solver_multilevel.hpp.
Referenced by demMakeMlFusedCtx().
|
inlineconstexpr |
Definition at line 44 of file solver_multilevel.hpp.