19#ifndef DEM_SLEEPING_HPP
20#define DEM_SLEEPING_HPP
22#include <Kokkos_Core.hpp>
32 Kokkos::View<
const float* [3],
CpMem> pos,
33 Kokkos::View<
const float* [4],
CpMem> quat,
34 Kokkos::View<
float* [3],
CpMem> posPred,
35 Kokkos::View<
float* [4],
CpMem> quatPred,
36 Kokkos::View<
float* [3],
CpMem> velPred,
37 Kokkos::View<
float* [3],
CpMem> angVelPred) {
40 "peclet::dem::freeze_asleep", Kokkos::RangePolicy<CpExec>(space, 0, numReal),
41 KOKKOS_LAMBDA(
int i) {
44 for (
int c = 0; c < 3; ++c) {
45 posPred(i, c) = pos(i, c);
47 angVelPred(i, c) = 0.0f;
49 for (
int c = 0; c < 4; ++c)
50 quatPred(i, c) = quat(i, c);
59 Kokkos::View<const int*, CpMem> realIdx,
60 Kokkos::View<const float*, CpMem> invMass,
61 Kokkos::View<float*, CpMem> invMassEff,
float sleeperFrac) {
64 "peclet::dem::inv_mass_eff", Kokkos::RangePolicy<CpExec>(space, 0, numBodies),
65 KOKKOS_LAMBDA(
int i) {
66 invMassEff(i) = asleep(realIdx(i)) ? sleeperFrac * invMass(i) : invMass(i);
75 int numManifolds, Kokkos::View<const int*, CpMem> realIdx,
76 Kokkos::View<const unsigned char*, CpMem> asleep,
77 Kokkos::View<unsigned char*, CpMem> manifoldSleep) {
80 "peclet::dem::manifold_sleep", Kokkos::RangePolicy<CpExec>(space, 0, numManifolds),
81 KOKKOS_LAMBDA(
int idx) {
85 const bool aA = asleep(realIdx(m.
bodyA)) != 0;
86 const bool aB = (m.
bodyB < 0) ?
true : (asleep(realIdx(m.
bodyB)) != 0);
87 s = (aA && aB) ? 1 : 0;
89 manifoldSleep(idx) = s;
96 int numContacts, Kokkos::View<const int*, CpMem> realIdx,
97 Kokkos::View<const unsigned char*, CpMem> asleep,
98 Kokkos::View<unsigned char*, CpMem> contactSleep) {
100 Kokkos::parallel_for(
101 "peclet::dem::contact_sleep", Kokkos::RangePolicy<CpExec>(space, 0, numContacts),
102 KOKKOS_LAMBDA(
int idx) {
104 const bool aA = asleep(realIdx(c.
bodyA)) != 0;
105 const bool aB = (c.
bodyB < 0) ?
true : (asleep(realIdx(c.
bodyB)) != 0);
106 contactSleep(idx) = (aA && aB) ? 1 : 0;
118 Kokkos::View<const int*, CpMem> realIdx,
119 Kokkos::View<
const float* [3],
CpMem> velPred,
float wakeSpeed,
120 Kokkos::View<unsigned char*, CpMem> asleep,
121 Kokkos::View<unsigned char*, CpMem> sleepCounter,
122 Kokkos::View<unsigned char*, CpMem> movingWall,
123 Kokkos::View<int*, CpMem> curCount,
int numReal) {
125 Kokkos::parallel_for(
126 "peclet::dem::wake_reset", Kokkos::RangePolicy<CpExec>(space, 0, numReal),
127 KOKKOS_LAMBDA(
int i) {
131 const float wakeSpeed2 = wakeSpeed * wakeSpeed;
132 Kokkos::parallel_for(
133 "peclet::dem::wake_disturbed", Kokkos::RangePolicy<CpExec>(space, 0, numManifolds),
134 KOKKOS_LAMBDA(
int idx) {
138 const int ra = realIdx(m.
bodyA);
139 Kokkos::atomic_add(&curCount(ra), 1);
142 rb = realIdx(m.
bodyB);
145 Kokkos::atomic_add(&curCount(rb), 1);
150 if (wv.
x != 0.0f || wv.
y != 0.0f || wv.
z != 0.0f) {
154 sleepCounter(ra) = 0;
159 const bool sA = asleep(ra) != 0, sB = asleep(rb) != 0;
163 const int awake = sA ? rb : ra, sleeper = sA ? ra : rb;
164 const float vx = velPred(awake, 0), vy = velPred(awake, 1), vz = velPred(awake, 2);
165 if (vx * vx + vy * vy + vz * vz > wakeSpeed2) {
167 sleepCounter(sleeper) = 0;
177 Kokkos::View<int*, CpMem> prevCount,
178 Kokkos::View<const unsigned char*, CpMem> movingWall,
179 Kokkos::View<unsigned char*, CpMem> asleep,
180 Kokkos::View<unsigned char*, CpMem> sleepCounter,
183 Kokkos::parallel_for(
184 "peclet::dem::wake_contact_change", Kokkos::RangePolicy<CpExec>(space, 0, numReal),
185 KOKKOS_LAMBDA(
int i) {
190 if (wakeOnChange && asleep(i) && curCount(i) < prevCount(i)) {
196 prevCount(i) = curCount(i);
206 Kokkos::View<
const float* [3],
CpMem> angVel,
207 Kokkos::View<const float*, CpMem> rad,
208 Kokkos::View<const unsigned char*, CpMem> grounded,
209 Kokkos::View<const unsigned char*, CpMem> movingWall,
210 Kokkos::View<unsigned char*, CpMem> asleep,
211 Kokkos::View<unsigned char*, CpMem> sleepCounter,
float sleepSpeed,
212 int K, Kokkos::View<
float* [3],
CpMem> velOut,
213 Kokkos::View<
float* [3],
CpMem> angVelOut) {
215 const float s2 = sleepSpeed * sleepSpeed;
216 Kokkos::parallel_for(
217 "peclet::dem::update_sleep", Kokkos::RangePolicy<CpExec>(space, 0, numReal),
218 KOKKOS_LAMBDA(
int i) {
221 const float vx = vel(i, 0), vy = vel(i, 1), vz = vel(i, 2);
222 const float wx = angVel(i, 0), wy = angVel(i, 1), wz = angVel(i, 2);
223 const float r = rad(i);
224 const bool lowLin = (vx * vx + vy * vy + vz * vz) < s2;
225 const bool lowAng = (wx * wx + wy * wy + wz * wz) * r * r < s2;
226 if (lowLin && lowAng && grounded(i) > 0 && !movingWall(i)) {
227 int c =
static_cast<int>(sleepCounter(i)) + 1;
230 for (
int k = 0; k < 3; ++k) {
232 angVelOut(i, k) = 0.0f;
236 sleepCounter(i) =
static_cast<unsigned char>(c > 255 ? 255 : c);
dem — portable POD types + math + analytic SDFs shared by the Kokkos kernel ports.
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 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 staye...
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 —...
CpExec::memory_space CpMem
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...
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 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 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 th...
Kokkos::DefaultExecutionSpace CpExec
Portable mirror of ManifoldConstraint.