|
peclet-dem 0.4.0
Performance-portable XPBD Discrete Element Method (Kokkos + ArborX)
|
dem — portable (Kokkos) manifold velocity solve (normal restitution impulse). More...
#include <climits>#include <Kokkos_Core.hpp>#include <tuple>#include <utility>#include <vector>#include "contact_preprocessing.hpp"#include "dem_portable.hpp"#include "solver_fused.hpp"Go to the source code of this file.
Classes | |
| struct | peclet::dem::PGSManifoldSweep |
| One full colored PGS sweep. More... | |
Namespaces | |
| namespace | peclet |
| namespace | peclet::dem |
| namespace | peclet::dem::detail |
Functions | |
| F3 | peclet::dem::detail::ld3 (Kokkos::View< const float *[3], CpMem > v, int i) |
| float | peclet::dem::detail::genInvMass (F3 tau, F3 invIlocal, F4 q) |
| void | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 > | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 | peclet::dem::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 | peclet::dem::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). | |
dem — portable (Kokkos) manifold velocity solve (normal restitution impulse).
Kokkos port of solve_velocity_jacobi_kernel (solver_velocity.cu): one thread per manifold computes the aggregate normal impulse (with growth-velocity term and restitution) and atomically scatters the linear/angular velocity deltas onto the two bodies' REAL indices. Faithful copy of the CUDA math; runs on the particle SoA expressed as Kokkos Views. Friction is a separate per-contact pass (solver_position) and is not done here, matching the original.
Definition in file solver_velocity.hpp.