31#ifndef DEM_SOLVE_DRIVER_HPP
32#define DEM_SOLVE_DRIVER_HPP
36#include <Kokkos_Core.hpp>
53inline int readInt(Kokkos::View<int, CpMem> v) {
55 Kokkos::deep_copy(h, v);
58inline float readFloat(Kokkos::View<float, CpMem> v) {
60 Kokkos::deep_copy(h, v);
68 "peclet::dem::gid_base", Kokkos::RangePolicy<CpExec>(0, n),
69 KOKKOS_LAMBDA(
int i) { gid(i) = base + i; });
83 Kokkos::parallel_reduce(
84 "peclet::dem::max_scale", Kokkos::RangePolicy<CpExec>(0, P.
numReal),
85 KOKKOS_LAMBDA(
int i,
float& m) { m = sc(i) > m ? sc(i) : m; }, Kokkos::Max<float>(mx));
97 "peclet::dem::world_radii", Kokkos::RangePolicy<CpExec>(space, 0, n),
98 KOKKOS_LAMBDA(
int i) { rad(i) = scale(i) * gs * bR; });
116 if (np >
static_cast<int>(P.
pairs.extent(0))) {
117 const int grown = np + np / 2 + 64;
118 Kokkos::realloc(Kokkos::WithoutInitializing, P.
pairs, grown);
123 return std::min(np,
static_cast<int>(P.
pairs.extent(0)));
141 Kokkos::parallel_reduce(
142 "peclet::dem::verlet_disp", Kokkos::RangePolicy<CpExec>(0, P.
numReal),
143 KOKKOS_LAMBDA(
int i,
float& acc) {
144 const float dx = pp(i, 0) - rp(i, 0), dy = pp(i, 1) - rp(i, 1), dz = pp(i, 2) - rp(i, 2);
145 const float d = dx * dx + dy * dy + dz * dz;
149 Kokkos::Max<float>(md2));
153 const float grow = std::max(0.0f, maxRad - P.
impRefMaxRad);
154 if (std::sqrt(md2) + 2.0f * grow > 0.5f * skin)
159 const auto rng = Kokkos::pair<int, int>(0, P.
numReal);
160 Kokkos::deep_copy(Kokkos::subview(P.
impRefPos, rng, Kokkos::ALL),
161 Kokkos::subview(P.
posPred, rng, Kokkos::ALL));
169#ifdef KOKKOS_ENABLE_CUDA
177struct CudaIterGraph {
178 cudaGraphExec_t exec =
nullptr;
181 cudaStream_t str = space.cuda_stream();
182 if (cudaStreamBeginCapture(str, cudaStreamCaptureModeThreadLocal) != cudaSuccess) {
183 (void)cudaGetLastError();
187 cudaGraph_t g =
nullptr;
188 if (cudaStreamEndCapture(str, &g) != cudaSuccess || g ==
nullptr) {
189 (void)cudaGetLastError();
195 if (cacheSlot !=
nullptr) {
196 exec =
static_cast<cudaGraphExec_t
>(cacheSlot);
197 cudaGraphExecUpdateResultInfo ri;
198 if (cudaGraphExecUpdate(exec, g, &ri) != cudaSuccess) {
199 (void)cudaGetLastError();
200 cudaGraphExecDestroy(exec);
205 if (exec ==
nullptr) {
206 if (cudaGraphInstantiate(&exec, g,
nullptr,
nullptr, 0) != cudaSuccess) {
207 (void)cudaGetLastError();
213 return exec !=
nullptr;
215 void launch(
CpExec& space) { cudaGraphLaunch(exec, space.cuda_stream()); }
220#define PECLET_DEM_GRAPH_LOOP(useVar, graphVar, emitVar, slotVar) \
221 if constexpr (!Hooks::distributed) { \
223 useVar = graphVar.capture(space, emitVar, slotVar); \
233#define PECLET_DEM_GRAPH_LOOP(useVar, graphVar, emitVar, slotVar) (void)graphVar;
253 float allMax(
float v)
const {
return v; }
276 P.
iterCountDev = Kokkos::View<int*, CpMem>(
"peclet::dem::iter_count", 2);
285 Kokkos::deep_copy(v, Kokkos::subview(P.
iterCountDev, slot));
292template <
class Hooks>
294 Kokkos::View<const int*, CpMem> keyIdx,
const Hooks& hooks) {
301 Kokkos::Profiling::pushRegion(
"dem::solve::prep");
302 const int nmVisible = hooks.visibleManifolds(nm);
315 const bool sleepOn = P.
sleepingEnabled && !Hooks::distributed && usePersistPre &&
317 const Kokkos::View<const unsigned char*, CpMem> mSleep =
318 sleepOn ? Kokkos::View<const unsigned char*, CpMem>(P.
manifoldSleep)
319 : Kokkos::View<const unsigned char*, CpMem>();
320 const Kokkos::View<const unsigned char*, CpMem> cSleep =
321 sleepOn ? Kokkos::View<const unsigned char*, CpMem>(P.
contactSleep)
322 : Kokkos::View<const unsigned char*, CpMem>();
323 const bool legacyFriction = friction && !(usePersistPre && P.
velocityUseGS);
353 Kokkos::View<int*, CpMem> edgeA, edgeB;
354 auto growSlots = [&](
int nCopies) {
355 if (slotBase + nCopies > P.
capacity)
358 std::string invariantMsg;
359 auto noteInvariant = [&](
const char* phase, Kokkos::View<const int*, CpMem> color,
int n) {
361 auto hc = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), color);
362 auto ha = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), edgeA);
363 auto hb = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), edgeB);
364 auto hd = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), P.
vertexDegree);
365 int bad = 0, first = -1;
366 for (
int e = 0; e < n; ++e)
372 std::string m = std::string(
"colouring invariant violated: ") + std::to_string(bad) +
" " +
373 phase +
" uncolourable edges after hub splitting";
375 m +=
" (first: vertex " + std::to_string(ha(first)) +
", degree " +
376 std::to_string(ha(first) >= 0 ? hd(ha(first)) : 0);
378 m +=
"; vertex " + std::to_string(hb(first)) +
", degree " + std::to_string(hd(hb(first)));
381 invariantMsg += (invariantMsg.empty() ?
"" :
"; ") + m;
389 const bool incrColor = usePersistPre && P.
velocityUseGS && !Hooks::distributed && !incrColorOff;
395 Kokkos::View<const unsigned long long*, CpMem>(P.
prevPairKeys),
401 Kokkos::View<const unsigned long long*, CpMem>(P.
prevPairKeys),
411 !Hooks::distributed);
413 if (velLeftover > 0 && nm > 0) {
415 edgeA = Kokkos::View<int*, CpMem>(
"peclet::dem::copies_eA", nm);
416 edgeB = Kokkos::View<int*, CpMem>(
"peclet::dem::copies_eB", nm);
418 Kokkos::View<const int*, CpMem>(P.
manifoldColor), edgeA, edgeB);
426 !Hooks::distributed, slotBase + VC.
nCopies);
432 Kokkos::View<const float*, CpMem>(P.
invMass));
434 noteInvariant(
"velocity", Kokkos::View<const int*, CpMem>(P.
manifoldColor), nm);
439 std::vector<int> velOffs;
440 const bool velBuckets = P.
velocityUseGS && nm > 0 && numColors > 0;
444 const Kokkos::View<const int*, CpMem> velPermC(P.
velPerm);
445 const std::vector<int>* velOffsP = velBuckets ? &velOffs :
nullptr;
463 int numPosColors = 0;
468 const bool incrPosColor =
469 usePersistPre && P.
velocityUseGS && !Hooks::distributed && !incrColorOff;
470 bool posDidFull =
false;
476 if (numPosUnits != nc)
477 posUnits =
PosUnits{Kokkos::subview(Kokkos::View<const int*, CpMem>(P.
unitStart),
478 Kokkos::pair<int, int>(0, numPosUnits + 1)),
479 Kokkos::subview(Kokkos::View<const int*, CpMem>(P.
unitContacts),
480 Kokkos::pair<int, int>(0, nc))};
488 posDidFull, cSleep, posUnits);
496 true, cSleep, posUnits);
509 if ((posLeftover > 0 || images) && numPosUnits > 0) {
510 edgeA = Kokkos::View<int*, CpMem>(
"peclet::dem::copies_eA", numPosUnits);
511 edgeB = Kokkos::View<int*, CpMem>(
"peclet::dem::copies_eB", numPosUnits);
513 Kokkos::View<const int*, CpMem>(P.
unitColor), edgeA, edgeB);
515 "peclet::dem::vertexDegree");
517 if (posLeftover > 0) {
526 posUnits, ovColor, slotBase + PC.
nCopies);
532 noteInvariant(
"position", Kokkos::View<const int*, CpMem>(P.
unitColor), numPosUnits);
536 : Kokkos::View<const float* [3], CpMem>(),
537 PC, Hooks::distributed);
557 const bool rankM = Hooks::distributed && hooks.rankK().exchanges;
565 if (!usePersistPre) {
567 growCopyView(P.
xGate,
static_cast<std::size_t
>(nm > 0 ? nm : 1),
"peclet::dem::xGate");
591 bool invariantPending = !invariantMsg.empty();
592 if constexpr (!Hooks::distributed) {
593 if (invariantPending)
594 throw std::runtime_error(invariantMsg);
596 auto voteInvariant = [&](
float res) {
597 bool bad = invariantPending;
598 invariantPending =
false;
599 const float r = hooks.allMaxAny(res, bad);
601 throw std::runtime_error(invariantMsg.empty()
602 ? std::string(
"colouring invariant violated on another rank")
609 std::vector<int> posOffs;
610 const bool posBuckets = P.
velocityUseGS && numPosUnits > 0 && numPosColors > 0;
614 const Kokkos::View<const int*, CpMem> posPermC(P.
posPerm);
615 const std::vector<int>* posOffsP = posBuckets ? &posOffs :
nullptr;
634 const RankK rk = hooks.rankK();
635#if defined(PECLET_DEM_TEST_MUTANT) && PECLET_DEM_TEST_MUTANT == 4
636 const bool xOn =
false;
648 const Kokkos::View<float*, CpMem> bankV = poisson ? P.
restBank : Kokkos::View<float*, CpMem>();
649 const Kokkos::View<float*, CpMem> relV = poisson ? P.
restRel : Kokkos::View<float*, CpMem>();
650 const Kokkos::View<const float*, CpMem> vpkC =
651 poisson ? Kokkos::View<const float*, CpMem>(P.
restVPeak)
652 : Kokkos::View<const float*, CpMem>();
653 const Kokkos::View<float*, CpMem> orphV = poisson ? P.
bodyOrphan : Kokkos::View<float*, CpMem>();
654 const Kokkos::View<const float*, CpMem> orphPk =
656 : Kokkos::View<const float*, CpMem>();
660 Kokkos::deep_copy(mt,
static_cast<unsigned char>(0));
666 poisson ? P.
prevMatched : Kokkos::View<unsigned char*, CpMem>(),
667 !Hooks::distributed);
670 auto rr = Kokkos::subview(P.
restRel, Kokkos::pair<int, int>(0, nm));
671 Kokkos::deep_copy(rr, 0.0f);
680 Kokkos::View<const int*, CpMem> gidSorted, slotSorted;
681 if constexpr (Hooks::distributed) {
682 Kokkos::View<int*, CpMem> gs(
683 Kokkos::view_alloc(space,
"peclet::dem::orphan_gids", Kokkos::WithoutInitializing),
685 Kokkos::View<int*, CpMem> ss(
686 Kokkos::view_alloc(space,
"peclet::dem::orphan_slots", Kokkos::WithoutInitializing),
689 Kokkos::parallel_for(
690 "peclet::dem::orphan_gid_map", Kokkos::RangePolicy<CpExec>(space, 0, nBodies),
691 KOKKOS_LAMBDA(
int i) {
695 Kokkos::Experimental::sort_by_key(space, gs, ss);
702 Kokkos::View<const unsigned char*, CpMem>(P.
prevMatched),
705 Hooks::distributed ? P.
numReal : -1);
718 auto flags = Kokkos::subview(P.
sideFlags, Kokkos::pair<int, int>(0, nm));
719 Kokkos::deep_copy(flags,
static_cast<unsigned char>(0));
722 P.
vt0, !Hooks::distributed);
729 if constexpr (Hooks::distributed)
730 hooks.openVelocityPhase(P, poisson);
736 if constexpr (Hooks::distributed)
737 hooks.openPositionCounts(P, rankM);
743 const bool velCopiesOn = VC.
nGroups > 0;
747 const bool velM = rankM && usePGS;
748 Kokkos::View<const float*, CpMem> invMassVel = P.
invMass;
749 Kokkos::View<const float* [3], CpMem> invInertiaVel = P.
invInertia;
751 const Kokkos::View<float*, CpMem> orphPkW =
764 }
else if (velCopiesOn) {
781 const bool velCons = velCopiesOn || velM;
782 auto withConsensus = [&](
float res,
bool cons) {
787 return std::max(res, c);
791 const float fusedOff = -1.0f;
797 if constexpr (Hooks::distributed) {
799 hooks.syncVelocities(P);
806 hooks.syncVelocities(P);
813 const float vRest = 2.0f * P.
dt * gMagP;
819 auto emitVelIter = [&] {
826 Kokkos::View<const float*, CpMem>(P.
posImpulse), {}, bankV, relV, vpkC,
827 orphV, orphPk, velPermC, velOffsP, velFusedP,
nullptr, velOv);
833 bool velLoopDone =
false;
834 if constexpr (!Hooks::distributed) {
835 if (usePGS && P.
velocityUseGS && !velCopiesOn && velFusedP) {
844 Kokkos::View<const float*, CpMem>(P.
posImpulse), {}, bankV, relV, vpkC, orphV, orphPk,
845 velPermC, velOffsP, velFusedP, &spec, {});
848 bool graphVel =
false;
856 Kokkos::Profiling::popRegion();
857 Kokkos::Profiling::pushRegion(
"dem::solve::vel");
863 !Hooks::distributed);
881 Kokkos::View<const unsigned long long*, CpMem>(P.
velMask), P.
xGate,
889 {}, {}, {}, velOv, xGate);
902 if (stopsOn && velRes <= (usePGS ? 0.02f * vRest : vRest))
910 !Hooks::distributed);
911 hooks.syncContactCounts(P);
915 true, !Hooks::distributed);
919 if constexpr (Hooks::distributed) {
920 if (hooks.syncPoint(it))
924 if constexpr (Hooks::distributed)
926 Kokkos::Profiling::popRegion();
927 Kokkos::Profiling::pushRegion(
"dem::solve::stab_fric");
934 const float vRestS = 2.0f * P.
dt * gMagP;
942 8.0f * P.
dt * gMagP, !Hooks::distributed);
945 auto emitOsIter = [&] {
953 bankV, relV, vpkC, orphV, orphPk, velPermC, velOffsP, velFusedP,
nullptr, velOv);
956 bool osLoopDone =
false;
957 if constexpr (!Hooks::distributed) {
958 if (!velCopiesOn && velFusedP) {
966 Kokkos::View<const float*, CpMem>(P.
posImpulse), {}, bankV, relV, vpkC, orphV,
967 orphPk, velPermC, velOffsP, velFusedP, &spec, {});
970 bool graphOs =
false;
983 if (stopsOn && osRes <= vRestS)
985 if constexpr (Hooks::distributed) {
986 if (hooks.syncPoint(it))
990 }
else if (smode == 2) {
1003 const float qsThr = 8.0f * P.
dt * gMagP;
1015#if defined(PECLET_DEM_TEST_MUTANT) && PECLET_DEM_TEST_MUTANT == 6
1016 Kokkos::View<const float*, CpMem> invMassCoarse = P.
invMassSolve;
1018 Kokkos::View<const float*, CpMem> invMassCoarse = P.
invMass;
1022 "peclet::dem::invMassCoarse");
1024 Kokkos::View<const int*, CpMem>(P.
aVel), nBodies,
1031 Kokkos::View<const float* [3], CpMem> invInertiaCoarse = P.
invInertia;
1034 "peclet::dem::invInertiaCoarse");
1036 Kokkos::View<const int*, CpMem>(P.
aVel), nBodies,
1042 const std::size_t ng = P.
mlInvMassG.extent(0);
1043 const auto wi = Kokkos::WithoutInitializing;
1044 P.
mlOriginG = Kokkos::View<float* [3], CpMem>(Kokkos::view_alloc(wi,
"mlOriginG"), ng);
1045 P.
mlComOffG = Kokkos::View<float* [3], CpMem>(Kokkos::view_alloc(wi,
"mlComOffG"), ng);
1046 P.
mlAngG = Kokkos::View<float* [3], CpMem>(Kokkos::view_alloc(wi,
"mlAngG"), ng);
1047 P.
mlAngG0 = Kokkos::View<float* [3], CpMem>(Kokkos::view_alloc(wi,
"mlAngG0"), ng);
1048 P.
mlInvIG = Kokkos::View<float* [6], CpMem>(Kokkos::view_alloc(wi,
"mlInvIG"), ng);
1055 Kokkos::View<const float* [4], CpMem>(P.
quat), invInertiaCoarse};
1058 Kokkos::View<const float*, CpMem>(P.
vn0), Kokkos::View<
const float* [3],
CpMem>(P.
vt0),
1062 sleepOn ? Kokkos::View<const unsigned char*, CpMem>(P.
asleep)
1063 : Kokkos::View<const unsigned char*, CpMem>(),
1071 Kokkos::View<const int*, CpMem>(P.
aVel)) > 0)
1072 throw std::logic_error(
"rank-level M: a coarse group holds a vertex with a = 0");
1074 if (H.
numLevels > 0 && (velCopiesOn || velM))
1078 Kokkos::View<const int*, CpMem>(S.parent), H.
parentOff[0], nBodies,
1085 std::vector<std::vector<int>> mlOffs;
1109 auto emitMlIter = [&] {
1117 P.
maxApproachQS, bankV, relV, vpkC, orphV, orphPk, velPermC, velOffsP, velFusedP,
1124 Kokkos::View<const float*, CpMem>(relV), &mlOffs,
1125 Kokkos::View<const int*, CpMem>(P.
mlBucketPerm), mlFusedP);
1132 bool mlLoopDone =
false;
1133#ifdef KOKKOS_ENABLE_CUDA
1134 if constexpr (!Hooks::distributed) {
1135 if (!velCopiesOn && velFusedP) {
1143 Kokkos::View<const float*, CpMem>(P.
posImpulse), bankV, relV, vpkC, orphV, orphPk,
1145 mlLoopDone = demLaunchFusedMlLoop(
1148 P.
maxApproachQS, Kokkos::View<const float*, CpMem>(relV), S,
1149 Kokkos::View<const int*, CpMem>(P.
mlBucketPerm), *mlFusedP,
1162 vpkC, orphV, orphPk, velPermC, velOffsP, velFusedP, &spec, {});
1167 bool graphMl =
false;
1180 if (stopsOn && mlRes <= vRestS)
1182 if constexpr (Hooks::distributed) {
1183 if (hooks.syncPoint(it))
1187 }
else if (smode == 4) {
1195 std::vector<std::pair<int, int>> buckets;
1213 Kokkos::View<const unsigned char*, CpMem>(P.
sideFlags),
1218 Kokkos::View<const float*, CpMem>(P.
posImpulse),
1235 if (stopsOn && orRes <= vRestS)
1237 if constexpr (Hooks::distributed) {
1238 if (hooks.syncPoint(it))
1242 }
else if (smode == 3) {
1248 for (
int it = 0; it < 256; ++it) {
1256 bankV, relV, vpkC, orphV, orphPk, velPermC, velOffsP, velFusedP,
nullptr, velOv);
1259 if (stopsOn && esRes <= vRestS)
1261 if constexpr (Hooks::distributed) {
1262 if (hooks.syncPoint(it))
1267 if constexpr (Hooks::distributed)
1277 hooks.restoreOrphanBalance(P);
1278 }
else if (velCopiesOn) {
1288 !Hooks::distributed);
1296 Hooks::distributed ? Kokkos::View<const int*, CpMem>()
1301 if (legacyFriction) {
1303 hooks.syncFrictionCounts(P);
1309 if constexpr (Hooks::distributed)
1310 hooks.syncVelocities(P);
1315 if constexpr (Hooks::distributed)
1316 hooks.publishPositions(P);
1321 const bool posCopiesOn = PC.
nGroups > 0;
1322 Kokkos::View<const float*, CpMem> invMassPos = P.
invMass;
1323 Kokkos::View<const float* [3], CpMem> invInertiaPos = P.
invInertia;
1339#if defined(PECLET_DEM_TEST_MUTANT) && PECLET_DEM_TEST_MUTANT == 7
1343 }
else if (posCopiesOn) {
1352#if defined(PECLET_DEM_TEST_MUTANT) && PECLET_DEM_TEST_MUTANT == 7
1356 Kokkos::Profiling::popRegion();
1357 Kokkos::Profiling::pushRegion(
"dem::solve::pos");
1358 auto syncPos = [&] {
1359 if constexpr (Hooks::distributed) {
1360 hooks.syncPositions(P);
1369 auto pc = Kokkos::subview(P.
posLambdaContact, Kokkos::pair<int, int>(0, nc));
1370 Kokkos::deep_copy(pc, 0.0f);
1377 auto emitPosIter = [&] {
1378 Kokkos::deep_copy(space, P.
maxOverlap, 0.0f);
1389 const bool posCons = posCopiesOn || posM;
1393 bool posLoopDone =
false;
1394 if constexpr (!Hooks::distributed) {
1399 Kokkos::deep_copy(space, P.
maxOverlap, 0.0f);
1406 bool graphPos =
false;
1427 if (stopsOn && posRes < posTol)
1432 hooks.syncContactCounts(P);
1439 if constexpr (Hooks::distributed) {
1440 if (hooks.syncPoint(it))
1444 if constexpr (Hooks::distributed)
1450 if (usePGS && nm > 0)
1453 Kokkos::Profiling::popRegion();
dem — portable (ArborX) broad-phase, the Kokkos-native replacement for the CUDA-only cuBQL broad-phas...
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 ...
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.
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={}, SlotOverride ov={}, bool dedupTwins=true, int vertexSpan=0)
Greedy graph-colour the manifolds: no two manifolds sharing a real body get the same colour.
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, bool massSplit=false)
Accumulate XPBD position corrections for numContacts contacts.
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 activityHitVelocityKokkos(Kokkos::View< const ManifoldC *, CpMem > manifolds, int nm, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const int *, CpMem > color, SlotOverride ov, Kokkos::View< unsigned char *, CpMem > hit, int nSlots)
Rank-level activity pass (docs/contact_solve_framework.md §13.3 C4; the distributed step only),...
void computeXGateKokkos(Kokkos::View< const ManifoldC *, CpMem > manifolds, int nm, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const unsigned long long *, CpMem > velMask, Kokkos::View< unsigned char *, CpMem > gate, int color, int numColors, long long t)
The per-manifold fire gate of sync interval t: 1 iff this rank (colour color) holds every endpoint wh...
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 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 sco...
float maxOwnedRadius(const Particles &P)
Largest effective particle radius over the owned set (= max scale × globalScale, growth included).
void buildHubCopiesKokkos(Kokkos::View< const int *, CpMem > eA, Kokkos::View< const int *, CpMem > eB, int nE, int nV, int slotBase, Kokkos::View< const int *, CpMem > deg, PhaseCopies &H)
Build one phase's hub copies (§4.4 steps 2, 3 and 5): every vertex with d > kHubEdgeBudget active edg...
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 float *, CpMem > restVPeak={}, 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, SlotOverride ov={})
Returns true when the sweep (or, with loop, the whole iteration loop) was submitted; false ONLY in lo...
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={}, PosUnits units={}, SlotOverride ov={}, int vertexSpan=0)
Greedy graph-colour the contacts (raw bodyA/bodyB): no two contacts sharing a body get the same colou...
int countSplitBodiesKokkos(const PhaseCopies &H)
Count the bodies whose group has k > 1 (split_stats).
void countVelocityJacobiKokkos(Kokkos::View< const ManifoldC *, CpMem > manifolds, int numManifolds, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< int *, CpMem > counts, bool dedupTwins=true)
Mass-split Jacobi count pass (docs/contact_solve_framework.md §3.1, D3): per body (REAL index),...
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, const MlBodyViews &body, 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 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 commen...
Kokkos::View< float *, CpMem > Vf
Kokkos::View< int *, CpMem > Vi
int * demIterCountSlot(Particles &P, int slot)
Diagnostics (docs/contact_solve_framework.md §12 S12): the device scalar a fused main loop writes its...
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] .
void reseedCopiesKokkos(CpExec space, const PhaseCopies &H, Kokkos::View< float *[3], CpMem > x, Kokkos::View< float *[3], CpMem > w)
Re-seed every member from its base, sigma unchanged (the multilevel pass, after the coarse cycle has ...
int countInactiveAggregatedKokkos(Kokkos::View< const int *, CpMem > parent, int off, int nV, int nGroups1, Kokkos::View< const int *, CpMem > a)
Debug-build check (§13.2, §13.5 WO-5 item 4): the vertices with a = 0 that sit in a level-1 multileve...
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 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-...
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, bool dedupTwins=true)
Decide each persistent contact's treatment ONCE per substep (before any impulse is applied): 0 = symm...
bool demFusedWanted(bool graphReplayAvailable, int mode)
Fused-sweep policy.
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={}, bool dedupTwins=true)
Incremental (warm-started) manifold colouring for the single-GPU PGS path.
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 ...
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={}, bool dedupTwins=true)
Warm-start gather for the PGS velocity solve: per manifold, write its pair key and look up the previo...
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...
int readInt(Kokkos::View< int, CpMem > v)
float readFloat(Kokkos::View< float, CpMem > v)
void buildInvMassCoarseKokkos(Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const int *, CpMem > k, Kokkos::View< const int *, CpMem > a, int n, Kokkos::View< float *, CpMem > out)
The multilevel coarse vertex's inverse mass (§13.2): invMass(q) (k(q) / max(1, a(q))),...
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={}, int ownedLimit=-1)
Orphan transfer: previous-ledger entries NOT matched by any current manifold (their pair died this su...
int buildPositionUnitsKokkos(Kokkos::View< const ContactC *, CpMem > contacts, int n, Kokkos::View< int *, CpMem > unitStart, Kokkos::View< int *, CpMem > unitContacts, int numManifolds=-1)
Build the position units of contacts [0, n) (docs/contact_solve_framework.md §4.3,...
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.
CpExec::memory_space CpMem
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={}, bool massSplit=false, bool dedupTwins=true)
Accumulate normal-restitution velocity deltas for numManifolds manifolds.
int demReadIterCount(const Particles &P, int slot)
The count a fused main loop wrote (one small readback, only with P.iterCounters on); -1 with the coun...
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") ...
void positionEdgeEndsKokkos(Kokkos::View< const ContactC *, CpMem > contacts, const PosUnits &units, int nu, Kokkos::View< const int *, CpMem > color, Kokkos::View< int *, CpMem > eA, Kokkos::View< int *, CpMem > eB)
Position-phase colouring edges: one per unit, the leader contact's raw (bodyA, bodyB); active = the u...
void finishActivityKokkos(Kokkos::View< const unsigned char *, CpMem > hit, int nSlots, PhaseCopies &H, Kokkos::View< int *, CpMem > a)
a(q) from the pass (§13.3): hit(q) for a slot outside any group; at a hub base the number of its grou...
int findCollisionsGrow(Particles &P, float margin)
Broad phase with an automatically-grown pair buffer.
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 subs...
long long countUnfiredKokkos(Kokkos::View< const unsigned char *, CpMem > gate, int nm)
Diagnostics (iterCounters): the number of gated-off manifolds of one sweep.
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 cal...
constexpr float kSplitOmegaVelocity
Split relaxation (§4.5, §13.1): the PGS normal step on an edge touching a mass-split slot is scaled b...
void countPositionJacobiKokkos(Kokkos::View< const ContactC *, CpMem > contacts, int numContacts, Kokkos::View< int *, CpMem > counts)
Mass-split Jacobi count pass (docs/contact_solve_framework.md §3.1, D3): per body slot,...
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...
void seedCopySlotStateKokkos(Particles &P, const PhaseCopies &H)
Seed the copy slots' read-only state from their hub vertex (§4.4 step 6): orientation,...
void unfoldOrphanKokkos(const PhaseCopies &H, Kokkos::View< float *, CpMem > orphan)
Orphan accounts back from share form (before a rank sync and at the end of the velocity phase): the b...
void buildSolveViewsKokkos(Particles &P, const PhaseCopies &H, int nSlots, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia)
Solve views of a phase (§4.5): invMassSolve / invInertiaSolve = the phase's masses on every slot in [...
void fillWorldRadiiKokkos(Vf scale, Vf rad, float gs, float bR, int n)
World radii rad(i) = scale(i) * globalScale * baseRadius over [0, n): the owned span before a step,...
void applyVelocityDeltasAveragedKokkos(int n, V3 velPred, V3 angVelPred, V3 deltaVel, V3 deltaAngVel, Vi velCounts, bool averaged=true)
Apply the accumulated velocity deltas AVERAGED by the per-body manifold count — the velocity- solve t...
void buildInvInertiaCoarseKokkos(Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const int *, CpMem > k, Kokkos::View< const int *, CpMem > a, int n, Kokkos::View< float *[3], CpMem > out)
The multilevel coarse vertex's inverse inertia (docs/contact_physics_followups.md §2....
constexpr int kColorUncolourable
void buildCopyGroupsKokkos(Kokkos::View< const int *, CpMem > realIdx, int span, int numReal, Kokkos::View< const int *, CpMem > deg, Kokkos::View< const float *[3], CpMem > imageShift, PhaseCopies &H, bool identityBodies=false)
Build the fold groups of a phase (§4.4 "local fold", §WO-4 item 2): every body with more than one slo...
int countLightHubsKokkos(const PhaseCopies &H, Kokkos::View< const int *, CpMem > eA, Kokkos::View< const int *, CpMem > eB, int nE, int nV, Kokkos::View< const float *, CpMem > invMass)
Light hubs (split_stats, R-P3): velocity hubs whose mass is below 10x the mean mass of their partners...
int findCollisionsVerlet(Particles &P, float margin, float maxRad)
Verlet-cached impulse broadphase (single-GPU, non-periodic).
void markCopySeedsKokkos(const PhaseCopies &H, Kokkos::View< float *[3], CpMem > x, Kokkos::View< float *[3], CpMem > w, Kokkos::View< float *, CpMem > orphan, Kokkos::View< float *, CpMem > orphanPeak, bool shareFromBase=false)
Mark the phase seed sigma of every group and re-seed its members from the base (§4....
void buildSolveViewsRankKKokkos(Particles &P, const PhaseCopies &H, int nSlots, Kokkos::View< const float *, CpMem > invMass, Kokkos::View< const float *[3], CpMem > invInertia, Kokkos::View< const int *, CpMem > kRank)
Solve views under rank-level M (§13.3, §4.5): invMassSolve / invInertiaSolve = k x the body's masses ...
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, bool dedupTwins=true)
Apply the warm-start impulses up front (order-independent: fixed impulses, atomic adds).
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 *[4], CpMem > quat, 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.
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, bool dedupTwins=true)
-— Warm-started projected Gauss-Seidel (PGS) velocity solve -— Nonsmooth contact dynamics (Moreau-Jea...
void applyUpdatesKokkos(int n, V3 posPred, V3 velPred, V3 deltaPos, V3 deltaVel, Vi constraintCounts, bool averaged=true)
Jacobi count-averaged apply of position/velocity deltas, then clear deltas + counts.
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={}, SlotOverride ov={}, XGateSpec xg={})
Colored Gauss–Seidel normal-restitution solve: sweep the numColors colour classes in order,...
void vertexDegreeKokkos(Kokkos::View< const int *, CpMem > eA, Kokkos::View< const int *, CpMem > eB, int nE, int nV, Kokkos::View< int *, CpMem > deg)
Per-vertex active degree over [0, nV) (§4.4 step 1). Wall edges have one endpoint.
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, bool dedupTwins=true)
Force-chain normal load, accumulated over the velocity iterations: contacts(idx).friction_lambda_n +=...
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={}, const MlBodyViews &body={})
Build the aggregation hierarchy + per-level crossing-manifold colorings.
void activityHitPositionKokkos(Kokkos::View< const ContactC *, CpMem > contacts, const PosUnits &units, int nu, Kokkos::View< const int *, CpMem > color, SlotOverride ov, Kokkos::View< unsigned char *, CpMem > hit, int nSlots)
The same over the position phase's units (raw slots of the leader contact, through the overrides).
void velocityEdgeEndsKokkos(Kokkos::View< const ManifoldC *, CpMem > manifolds, int nm, Kokkos::View< const int *, CpMem > realIdx, Kokkos::View< const int *, CpMem > color, Kokkos::View< int *, CpMem > eA, Kokkos::View< int *, CpMem > eB)
Velocity-phase colouring edges: the vertices realIdx(bodyA / bodyB) of each manifold (-1: a wall end,...
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...
void growCopyView(V &v, std::size_t n, const char *label)
Grow-only (re)allocation of a copy-machinery view to at least n entries.
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 float *, CpMem > restVPeak, Kokkos::View< float *, CpMem > restOrphan, Kokkos::View< const float *, CpMem > restOrphanVPeak, SlotOverride ov={})
Build the shared per-manifold sweep functor (the colored launch loop, the fused kernels and the fused...
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.
void expandUnitColorsKokkos(const PosUnits &units, int numUnits, Kokkos::View< const int *, CpMem > unitColor, Kokkos::View< int *, CpMem > contactColor)
Copy each position unit's colour onto its contacts (contactColor(i) = unitColor(unit of i)).
void foldCopiesKokkos(CpExec space, const PhaseCopies &H, Kokkos::View< float *[3], CpMem > x, Kokkos::View< float *[3], CpMem > w, Kokkos::View< float *, CpMem > orphan, Kokkos::View< float *, CpMem > orphanPeak, Kokkos::View< float, CpMem > consensus={})
The local fold (§4.4), once per iteration after the sweep: per group T = sum over the ACTIVE members ...
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 d...
int countSplitAggregatedKokkos(Kokkos::View< const int *, CpMem > parent, int off, int nV, int nGroups1, Kokkos::View< const unsigned char *, CpMem > split)
split_stats.mlHubAggregated (§13.2's positive control): the vertices v in [0, nV) with split(v) !...
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).
bool solvePositionColoredGSKokkos(Kokkos::View< const ContactC *, CpMem > contacts, const PosUnits &units, 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, SlotOverride ov={}, Kokkos::View< float, CpMem > posResidual={}, float omega=1.0f)
Colored Gauss–Seidel XPBD overlap solve: sweep the numColors colour classes in order,...
Kokkos::DefaultExecutionSpace CpExec
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={}, PosUnits units={})
Incremental (warm-started) contact colouring for the single-GPU PGS position solve.
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, bool dedupTwins=true)
Event-level (Poisson) restitution bookkeeping, once per substep AFTER all velocity phases (restitutio...
dem — portable (Kokkos) particle SoA container: the storage the dem flip pivots on.
dem — body copies of the contact solve (docs/contact_solve_framework.md §4.4, §4.5,...
#define PECLET_DEM_GRAPH_LOOP(useVar, graphVar, emitVar, slotVar)
dem — portable (Kokkos) Coulomb friction cluster (the single dissipative friction path).
dem — multilevel (GraphMG-style) momentum-conserving contact stabilization.
dem — portable (Kokkos) XPBD position solve (pure overlap removal).
dem — portable (Kokkos) manifold velocity solve (normal restitution impulse).
bool capture(CpExec &, F &&, void *&)
Device-side iteration loop: run up to maxIters sweeps of the colour classes inside ONE kernel,...
Device-side context for a fused colour sweep: the colour offsets (numColors+1, uploaded from buildCol...
The per-body inputs of the rigid coarse space (§2.3-§2.5): the predicted positions (the member offset...
Fused-coarse-cycle context: flat per-level colour offsets on device + barrier + meta.
Device scratch for the multilevel pass, sized once (see Particles::allocate).
One full colored PGS sweep.
std::vector< int > parentOff
std::vector< int > numGroups
Kokkos::View< float, CpMem > posResidual
Kokkos::View< int *, CpMem > commitPerm
Kokkos::View< unsigned *, CpMem > fusedBar
Kokkos::View< unsigned char *, CpMem > asleep
Kokkos::View< int *, CpMem > bucketCursor
Kokkos::View< unsigned char *, CpMem > sideFlags
Kokkos::View< unsigned long long *, CpMem > prevContactKeys
Kokkos::View< int *, CpMem > mlGrp
Kokkos::View< unsigned char *, CpMem > xGate
Kokkos::View< unsigned char *, CpMem > manifoldPersistent
Kokkos::View< int *, CpMem > aPos
Kokkos::View< float *[3], CpMem > impRefPos
Kokkos::View< int *, CpMem > posOffsDev
Kokkos::View< float *, CpMem > bodyOrphanVPeak
Kokkos::View< int *, CpMem > velPerm
Kokkos::View< unsigned char *, CpMem > contactSleep
Kokkos::View< float *, CpMem > prevLambda
void ensureCapacity(int newCap)
Kokkos::View< int *, CpMem > unitStart
Kokkos::View< ManifoldC *, CpMem > manifolds
Kokkos::View< float *[3], CpMem > mlOriginG
Kokkos::View< float *, CpMem > vn0
Kokkos::View< float *, CpMem > mlMassG
Kokkos::View< int *, CpMem > levelKey
Kokkos::View< int *[2], CpMem > pairs
Kokkos::View< float *[3], CpMem > invInertiaSolve
Kokkos::View< float *[3], CpMem > imageShift
Kokkos::View< float *[3], CpMem > mlAngG0
Kokkos::View< float *[3], CpMem > vt0
Kokkos::View< int *, CpMem > vertexDegree
Kokkos::View< float *, CpMem > restRel
Kokkos::View< int *, CpMem > levelPerm
Kokkos::View< int *, CpMem > prevManifoldColor
Kokkos::View< float *[3], CpMem > mlAngG
bool velCopiesLastSubstep
Kokkos::View< unsigned char *, CpMem > splitSlot
Kokkos::View< int *, CpMem > kVel
Kokkos::View< float *[3], CpMem > mlComOffG
Kokkos::View< unsigned long long *, CpMem > contactKeys
Kokkos::View< int *, CpMem > prevContactColor
Kokkos::View< unsigned char *, CpMem > prevMatched
Kokkos::View< unsigned char *, CpMem > activityHit
Kokkos::View< float, CpMem > maxApproach
Kokkos::View< float *, CpMem > prevRestBank
Kokkos::View< float *, CpMem > restVPeak
Kokkos::View< float *, CpMem > restBank
Kokkos::View< std::uint64_t *, CpMem > bodyColorMask
Kokkos::View< int *, CpMem > posCommitPerm
Kokkos::View< int *, CpMem > velOffsDev
Kokkos::View< int *, CpMem > mlOffsDev
Kokkos::View< unsigned long long *, CpMem > pairKeys
struct peclet::dem::Particles::MlLast mlLast
Kokkos::View< int *, CpMem > aVel
Kokkos::View< float, CpMem > maxConsensus
Kokkos::View< float *, CpMem > bodyOrphan
Kokkos::View< unsigned long long *, CpMem > prevPairKeys
Kokkos::View< int *, CpMem > posPerm
Kokkos::View< float *, CpMem > prevPosImpulse
Kokkos::View< int *, CpMem > contactColor
Kokkos::View< float *[3], CpMem > mlVelG
Kokkos::View< float *, CpMem > invMassSolve
Kokkos::View< float *[3], CpMem > mlVelG0
Kokkos::View< int *, CpMem > mlBucketPerm
Kokkos::View< float *[3], CpMem > invInertiaCoarse
Kokkos::View< int *, CpMem > mlParent
Kokkos::View< float *[3], CpMem > lambdaT
Kokkos::View< float *[3], CpMem > prevLambdaT
Kokkos::View< int *, CpMem > unitColor
Kokkos::View< int *, CpMem > kPos
Kokkos::View< float, CpMem > maxOverlap
Kokkos::View< float *, CpMem > posLambdaContact
Kokkos::View< unsigned long long *, CpMem > velMask
Kokkos::View< float *, CpMem > posImpulse
Kokkos::View< int *, CpMem > contactSlot
Kokkos::View< float *, CpMem > mlInvMassG
Kokkos::View< int *, CpMem > heightLevel
Kokkos::View< long long *, CpMem > bodyWinner
Kokkos::View< float *, CpMem > lambdaAcc
Kokkos::View< double *[7], CpMem > mlAccD
Kokkos::View< long long *, CpMem > mlColorPacked
Kokkos::View< float *, CpMem > invMassCoarse
Kokkos::View< int *, CpMem > iterCountDev
Kokkos::View< float, CpMem > maxApproachQS
Kokkos::View< unsigned char *, CpMem > manifoldSleep
Kokkos::View< const float *, CpMem > crad() const
Kokkos::View< float *[2], CpMem > planeFriction
Kokkos::View< float *, CpMem > prevRestVPeak
Kokkos::View< int *, CpMem > mlMate
Kokkos::View< ContactC *, CpMem > contacts
Kokkos::View< int, CpMem > pairCount
Kokkos::View< unsigned char *, CpMem > groundedLevel
Kokkos::View< int *, CpMem > unitContacts
Kokkos::View< int *, CpMem > manifoldColor
Kokkos::View< float *[6], CpMem > mlInvIG
One solve phase's body copies (docs/contact_solve_framework.md §4.4, §4.5, §WO-4 item 2): the hub cop...
Kokkos::View< int *, CpMem > slotB
Kokkos::View< int *, CpMem > slotA
The position units of a contact list as a CSR (§4.3): unit u owns the contacts list(start(u)) .
Rank-level M (docs/contact_solve_framework.md §13.3) as the hooks expose it to the driver: whether th...
Per-edge slot overrides of a phase's hub copies (docs/contact_solve_framework.md §4....
Single-GPU hooks: no ghost refresh, residuals are already global. Everything inlines away.
float allMaxAny(float v, bool &) const
static constexpr bool distributed
void beginSolve(Particles &) const
void restoreOrphanBalance(Particles &) const
void publishPositions(Particles &) const
void syncContactCounts(Particles &) const
int visibleManifolds(int nm) const
float allMax(float v) const
void openPositionCounts(Particles &, bool) const
void syncVelocities(Particles &) const
bool syncPoint(int) const
void syncFrictionCounts(Particles &) const
void syncPositions(Particles &) const
void openVelocityPhase(Particles &, bool) const
diagnostics.split_stats() (docs/contact_solve_framework.md §WO-4 item 4, §13.5 WO-4b): the last subst...
long long driftMigrations
long long unfiredSplitContacts
Rank-level X evaluated inline in the one-shot sweep (only for the manifolds of the colour being swept...