7#ifndef DEM_SOLVE_COPIES_HPP
8#define DEM_SOLVE_COPIES_HPP
12#include <Kokkos_Core.hpp>
13#include <Kokkos_Sort.hpp>
49 v = V(Kokkos::view_alloc(Kokkos::WithoutInitializing, std::string(label)), n + n / 2 + 64);
55 Kokkos::View<const int*, CpMem> realIdx,
56 Kokkos::View<const int*, CpMem> color,
57 Kokkos::View<int*, CpMem> eA, Kokkos::View<int*, CpMem> eB) {
59 "peclet::dem::copies_vel_ends", Kokkos::RangePolicy<CpExec>(0, nm), KOKKOS_LAMBDA(
int e) {
61 const bool act = color(e) != -2;
62 eA(e) = act ? realIdx(m.
bodyA) : -1;
63 eB(e) = (act && m.
bodyB >= 0) ? realIdx(m.
bodyB) : -1;
71 Kokkos::View<const int*, CpMem> color,
72 Kokkos::View<int*, CpMem> eA, Kokkos::View<int*, CpMem> eB) {
74 "peclet::dem::copies_pos_ends", Kokkos::RangePolicy<CpExec>(0, nu), KOKKOS_LAMBDA(
int u) {
76 const bool act = color(u) != -2;
77 eA(u) = act ? c.
bodyA : -1;
84 Kokkos::View<const int*, CpMem> eB,
int nE,
int nV,
85 Kokkos::View<int*, CpMem> deg) {
86 Kokkos::deep_copy(Kokkos::subview(deg, Kokkos::pair<int, int>(0, nV)), 0);
88 "peclet::dem::copies_degree", Kokkos::RangePolicy<CpExec>(0, nE), KOKKOS_LAMBDA(
int e) {
90 Kokkos::atomic_add(°(eA(e)), 1);
92 Kokkos::atomic_add(°(eB(e)), 1);
104 Kokkos::View<const int*, CpMem> eB,
int nE,
int nV,
int slotBase,
105 Kokkos::View<const int*, CpMem> deg,
PhaseCopies& H) {
107 using Kokkos::view_alloc;
108 using Kokkos::WithoutInitializing;
113 growCopyView(H.
slotA,
static_cast<std::size_t
>(nE),
"peclet::dem::copies_slotA");
114 growCopyView(H.
slotB,
static_cast<std::size_t
>(nE),
"peclet::dem::copies_slotB");
115 Kokkos::deep_copy(space, Kokkos::subview(H.
slotA, Kokkos::pair<int, int>(0, nE)), -1);
116 Kokkos::deep_copy(space, Kokkos::subview(H.
slotB, Kokkos::pair<int, int>(0, nE)), -1);
117 Kokkos::View<int*, CpMem> hubId(
118 view_alloc(space,
"peclet::dem::copies_hubid", WithoutInitializing), nV);
120 Kokkos::parallel_scan(
121 "peclet::dem::copies_hub_scan", Kokkos::RangePolicy<CpExec>(space, 0, nV),
122 KOKKOS_LAMBDA(
int v,
int& run,
const bool final) {
123#if defined(PECLET_DEM_TEST_MUTANT) && PECLET_DEM_TEST_MUTANT == 3
124 const bool hub =
false;
129 hubId(v) = hub ? run : -1;
139 growCopyView(H.
hubS,
static_cast<std::size_t
>(nHubs),
"peclet::dem::copies_hubs");
142 Kokkos::parallel_for(
143 "peclet::dem::copies_hub_list", Kokkos::RangePolicy<CpExec>(space, 0, nV),
144 KOKKOS_LAMBDA(
int v) {
145 const int h = hubId(v);
151 Kokkos::View<int*, CpMem> copyOff(
152 view_alloc(space,
"peclet::dem::copies_off", WithoutInitializing), nHubs);
153 Kokkos::View<int*, CpMem> degOff(
154 view_alloc(space,
"peclet::dem::copies_doff", WithoutInitializing), nHubs);
155 int nCopies = 0, nEntries = 0, maxDeg = 0;
156 Kokkos::parallel_scan(
157 "peclet::dem::copies_off_scan", Kokkos::RangePolicy<CpExec>(space, 0, nHubs),
158 KOKKOS_LAMBDA(
int h,
int& run,
const bool final) {
164 Kokkos::parallel_scan(
165 "peclet::dem::copies_doff_scan", Kokkos::RangePolicy<CpExec>(space, 0, nHubs),
166 KOKKOS_LAMBDA(
int h,
int& run,
const bool final) {
172 Kokkos::parallel_reduce(
173 "peclet::dem::copies_maxdeg", Kokkos::RangePolicy<CpExec>(space, 0, nHubs),
174 KOKKOS_LAMBDA(
int h,
int& m) {
178 Kokkos::Max<int>(maxDeg));
185 Kokkos::View<std::uint64_t*, CpMem> keys(
186 view_alloc(space,
"peclet::dem::copies_keys", WithoutInitializing), nEntries);
187 Kokkos::View<int, CpMem> cursor(
"peclet::dem::copies_cursor");
188 Kokkos::parallel_for(
189 "peclet::dem::copies_entries", Kokkos::RangePolicy<CpExec>(space, 0, nE),
190 KOKKOS_LAMBDA(
int e) {
191 const int ends[2] = {eA(e), eB(e)};
192 for (
int end = 0; end < 2; ++end) {
193 const int v = ends[end];
194 if (v < 0 || hubId(v) < 0)
196 const int p = Kokkos::atomic_fetch_add(&cursor(), 1);
197 keys(p) = (
static_cast<std::uint64_t
>(hubId(v)) << 33) |
198 (
static_cast<std::uint64_t
>(
static_cast<unsigned>(e)) << 1) |
199 static_cast<std::uint64_t
>(end);
202 Kokkos::sort(space, keys);
204 "peclet::dem::copies_base");
208 Kokkos::parallel_for(
209 "peclet::dem::copies_assign", Kokkos::RangePolicy<CpExec>(space, 0, nEntries),
210 KOKKOS_LAMBDA(
int p) {
211 const std::uint64_t k = keys(p);
212 const int h =
static_cast<int>(k >> 33);
213 const int e =
static_cast<int>((k >> 1) & 0xFFFFFFFFull);
214 const int end =
static_cast<int>(k & 1ull);
216 const int c = (p - degOff(h)) % s;
217 const int slot = (c == 0) ? hv(h) : slotBase + copyOff(h) + c - 1;
223 cb(copyOff(h) + c - 1) = hv(h);
244 Kokkos::View<const int*, CpMem> deg,
246 bool identityBodies =
false) {
248 using Kokkos::view_alloc;
249 using Kokkos::WithoutInitializing;
255 Kokkos::View<int*, CpMem> cnt(
"peclet::dem::copies_cnt", span);
256 Kokkos::parallel_for(
257 "peclet::dem::copies_grp_cnt", Kokkos::RangePolicy<CpExec>(space, 0, nQ),
258 KOKKOS_LAMBDA(
int qi) {
259 const int o = identityBodies ? ((qi < span) ? qi : cb(qi - span))
260 : ((qi < span) ? realIdx(qi) : realIdx(cb(qi - span)));
261 Kokkos::atomic_add(&cnt(o), 1);
263 Kokkos::View<std::uint64_t*, CpMem> keys(
264 view_alloc(space,
"peclet::dem::copies_gkeys", WithoutInitializing), nQ);
266 Kokkos::parallel_reduce(
267 "peclet::dem::copies_grp_keys", Kokkos::RangePolicy<CpExec>(space, 0, nQ),
268 KOKKOS_LAMBDA(
int qi,
int& acc) {
269 const int q = (qi < span) ? qi : base + (qi - span);
270 const int o = identityBodies ? ((qi < span) ? qi : cb(qi - span))
271 : ((qi < span) ? realIdx(qi) : realIdx(cb(qi - span)));
273 keys(qi) = (
static_cast<std::uint64_t
>(
static_cast<unsigned>(o)) << 32) |
274 static_cast<unsigned>(q);
277 keys(qi) = ~std::uint64_t(0);
284 Kokkos::sort(space, keys);
293 const bool haveShift = imageShift.extent(0) > 0;
295 Kokkos::parallel_scan(
296 "peclet::dem::copies_grp_scan", Kokkos::RangePolicy<CpExec>(space, 0, nMem),
297 KOKKOS_LAMBDA(
int p,
int& run,
const bool final) {
298 const bool isNew = (p == 0) || ((keys(p) >> 32) != (keys(p - 1) >> 32));
300 const int q =
static_cast<int>(keys(p) & 0xFFFFFFFFull);
302 const int b = (q < base) ? q : cb(q - base);
303 F3 sh{0.0f, 0.0f, 0.0f};
304 if (haveShift && b >= numReal && b < span)
305 sh =
F3{imageShift(b, 0), imageShift(b, 1), imageShift(b, 2)};
309 ga(p) = (q >= base || deg(q) > 0) ? 1 : 0;
317 Kokkos::deep_copy(space, Kokkos::subview(gs, nG), nMem);
319 growCopyView(H.
seedX,
static_cast<std::size_t
>(nG),
"peclet::dem::copies_seedx");
320 growCopyView(H.
seedW,
static_cast<std::size_t
>(nG),
"peclet::dem::copies_seedw");
322 Kokkos::parallel_for(
323 "peclet::dem::copies_grp_k", Kokkos::RangePolicy<CpExec>(space, 0, nG), KOKKOS_LAMBDA(
int g) {
325 for (
int p = gs(g); p < gs(g + 1); ++p)
327 gk(g) = k > 0 ? k : 1;
337 Kokkos::View<const float*, CpMem> invMass,
338 Kokkos::View<
const float* [3],
CpMem> invInertia) {
346 Kokkos::parallel_for(
347 "peclet::dem::copies_solve_views", Kokkos::RangePolicy<CpExec>(space, 0, nSlots),
348 KOKKOS_LAMBDA(
int q) {
349 const bool own = q < static_cast<int>(invMass.extent(0));
350 ims(q) = own ? invMass(q) : 0.0f;
351 for (
int c = 0; c < 3; ++c)
352 iis(q, c) = own ? invInertia(q, c) : 0.0f;
358 Kokkos::parallel_for(
359 "peclet::dem::copies_solve_split", Kokkos::RangePolicy<CpExec>(space, 0, H.
nGroups),
360 KOKKOS_LAMBDA(
int g) {
361 const int b = gq(gs(g));
363 const float kf =
static_cast<float>(k);
364 const float m = kf * invMass(b);
365 const float i0 = kf * invInertia(b, 0), i1 = kf * invInertia(b, 1),
366 i2 = kf * invInertia(b, 2);
367 for (
int p = gs(g); p < gs(g + 1); ++p) {
373 spl(q) = k > 1 ? 1 : 0;
390 Kokkos::parallel_for(
391 "peclet::dem::copies_seed_state", Kokkos::RangePolicy<CpExec>(0, H.
nCopies),
392 KOKKOS_LAMBDA(
int c) {
393 const int q = base + c, b = cb(c);
394 for (
int j = 0; j < 4; ++j) {
395 quat(q, j) = quat(b, j);
396 quatPred(q, j) = quatPred(b, j);
398 for (
int j = 0; j < 3; ++j)
399 invI(q, j) = invI(b, j);
400 grounded(q) = grounded(b);
411 Kokkos::View<
float* [3],
CpMem> w,
412 Kokkos::View<float*, CpMem> orphan,
413 Kokkos::View<float*, CpMem> orphanPeak,
414 bool shareFromBase =
false) {
423 const bool haveW = w.extent(0) > 0;
424 const bool haveO = orphan.extent(0) > 0;
425 Kokkos::parallel_for(
426 "peclet::dem::copies_mark", Kokkos::RangePolicy<CpExec>(0, H.
nGroups), KOKKOS_LAMBDA(
int g) {
427 const int b = gq(gs(g));
428 for (
int c = 0; c < 3; ++c) {
433 float share = 0.0f, pk = 0.0f;
435 share = shareFromBase ? orphan(b) : orphan(b) /
static_cast<float>(gk(g));
438 for (
int p = gs(g); p < gs(g + 1); ++p) {
441 for (
int c = 0; c < 3; ++c) {
442 x(q, c) = sx(g, c) + gsh(p, c);
464 Kokkos::View<
float* [3],
CpMem> w, Kokkos::View<float*, CpMem> orphan,
465 Kokkos::View<float*, CpMem> orphanPeak,
466 Kokkos::View<float, CpMem> consensus = {}) {
476 const bool haveW = w.extent(0) > 0;
477 const bool haveO = orphan.extent(0) > 0;
478 const bool haveC = consensus.data() !=
nullptr;
479 Kokkos::parallel_for(
480 "peclet::dem::copies_fold", Kokkos::RangePolicy<CpExec>(space, 0, H.
nGroups),
481 KOKKOS_LAMBDA(
int g) {
482 const float kf =
static_cast<float>(gk(g));
483 float tx[3] = {0.0f, 0.0f, 0.0f}, tw[3] = {0.0f, 0.0f, 0.0f};
484 float oSum = 0.0f, oPk = 0.0f;
485 for (
int p = gs(g); p < gs(g + 1); ++p) {
489 for (
int c = 0; c < 3; ++c) {
490 tx[c] += x(q, c) - (sx(g, c) + gsh(p, c));
492 tw[c] += w(q, c) - sw(g, c);
496 oPk = Kokkos::fmax(oPk, orphanPeak(q));
500 for (
int c = 0; c < 3; ++c) {
501#if defined(PECLET_DEM_TEST_MUTANT) && PECLET_DEM_TEST_MUTANT == 2
502 nx[c] = sx(g, c) + tx[c];
503 nw[c] = haveW ? sw(g, c) + tw[c] : 0.0f;
505 nx[c] = sx(g, c) + tx[c] / kf;
506 nw[c] = haveW ? sw(g, c) + tw[c] / kf : 0.0f;
509 const float share = oSum / kf;
512 for (
int p = gs(g); p < gs(g + 1); ++p) {
517 for (
int c = 0; c < 3; ++c) {
518 const float e = tx[c] / kf - (x(q, c) - (sx(g, c) + gsh(p, c)));
521 cmax = Kokkos::fmax(cmax, Kokkos::sqrt(s2));
524 Kokkos::atomic_max(&consensus(), cmax);
526 for (
int p = gs(g); p < gs(g + 1); ++p) {
528 for (
int c = 0; c < 3; ++c) {
529 x(q, c) = nx[c] + gsh(p, c);
544 Kokkos::View<
float* [3],
CpMem> x,
545 Kokkos::View<
float* [3],
CpMem> w) {
551 Kokkos::parallel_for(
552 "peclet::dem::copies_reseed", Kokkos::RangePolicy<CpExec>(space, 0, H.
nGroups),
553 KOKKOS_LAMBDA(
int g) {
554 const int b = gq(gs(g));
555 for (
int p = gs(g) + 1; p < gs(g + 1); ++p) {
557 for (
int c = 0; c < 3; ++c) {
558 x(q, c) = x(b, c) + gsh(p, c);
568 if (H.
nGroups <= 0 || orphan.extent(0) == 0)
573 Kokkos::parallel_for(
574 "peclet::dem::copies_unfold", Kokkos::RangePolicy<CpExec>(0, H.
nGroups),
575 KOKKOS_LAMBDA(
int g) {
577 for (
int p = gs(g); p < gs(g + 1); ++p)
580 orphan(gq(gs(g))) = s;
590 Kokkos::View<const int*, CpMem> realIdx,
592 Kokkos::View<unsigned char*, CpMem> hit,
int nSlots) {
594 Kokkos::deep_copy(space, Kokkos::subview(hit, Kokkos::pair<int, int>(0, nSlots)),
595 static_cast<unsigned char>(0));
596 Kokkos::parallel_for(
597 "peclet::dem::activity_vel", Kokkos::RangePolicy<CpExec>(space, 0, nm), KOKKOS_LAMBDA(
int e) {
601 Kokkos::atomic_store(&hit(ov.
slotA(e, realIdx(m.
bodyA))),
static_cast<unsigned char>(1));
603 Kokkos::atomic_store(&hit(ov.
slotB(e, realIdx(m.
bodyB))),
static_cast<unsigned char>(1));
612 Kokkos::View<unsigned char*, CpMem> hit,
int nSlots) {
614 Kokkos::deep_copy(space, Kokkos::subview(hit, Kokkos::pair<int, int>(0, nSlots)),
615 static_cast<unsigned char>(0));
616 Kokkos::parallel_for(
617 "peclet::dem::activity_pos", Kokkos::RangePolicy<CpExec>(space, 0, nu), KOKKOS_LAMBDA(
int u) {
621 Kokkos::atomic_store(&hit(ov.
slotA(u, c.
bodyA)),
static_cast<unsigned char>(1));
623 Kokkos::atomic_store(&hit(ov.
slotB(u, c.
bodyB)),
static_cast<unsigned char>(1));
635 Kokkos::parallel_for(
636 "peclet::dem::activity_a", Kokkos::RangePolicy<CpExec>(space, 0, nAll),
637 KOKKOS_LAMBDA(
int q) { a(q) = q < nSlots ? static_cast<int>(hit(q)) : 0; });
643 Kokkos::parallel_for(
644 "peclet::dem::activity_groups", Kokkos::RangePolicy<CpExec>(space, 0, H.
nGroups),
645 KOKKOS_LAMBDA(
int g) {
647 for (
int p = gs(g); p < gs(g + 1); ++p) {
648 const unsigned char h = hit(gq(p));
652 gk(g) = n > 0 ? n : 1;
664 Kokkos::View<const float*, CpMem> invMass,
665 Kokkos::View<
const float* [3],
CpMem> invInertia,
666 Kokkos::View<const int*, CpMem> kRank) {
676 const bool haveCopies = H.
nCopies > 0;
677 Kokkos::parallel_for(
678 "peclet::dem::rankk_solve_views", Kokkos::RangePolicy<CpExec>(space, 0, nSlots),
679 KOKKOS_LAMBDA(
int q) {
680 const int b = (haveCopies && q >= base) ? cb(q - base) : q;
681 const int k = kRank(b);
683 const float kf =
static_cast<float>(k);
684 ims(q) = kf * invMass(b);
685 for (
int c = 0; c < 3; ++c)
686 iis(q, c) = kf * invInertia(b, c);
690 for (
int c = 0; c < 3; ++c)
691 iis(q, c) = invInertia(b, c);
701 Kokkos::View<const int*, CpMem> k,
702 Kokkos::View<const int*, CpMem> a,
int n,
703 Kokkos::View<float*, CpMem> out) {
704 Kokkos::parallel_for(
705 "peclet::dem::inv_mass_coarse", Kokkos::RangePolicy<CpExec>(0, n), KOKKOS_LAMBDA(
int q) {
706 const int aq = a(q) > 1 ? a(q) : 1;
707 const float ratio =
static_cast<float>(k(q)) /
static_cast<float>(aq);
708 out(q) = invMass(q) * ratio;
718 Kokkos::View<const int*, CpMem> k,
719 Kokkos::View<const int*, CpMem> a,
int n,
720 Kokkos::View<
float* [3],
CpMem> out) {
721 Kokkos::parallel_for(
722 "peclet::dem::inv_inertia_coarse", Kokkos::RangePolicy<CpExec>(0, n), KOKKOS_LAMBDA(
int q) {
723 const int aq = a(q) > 1 ? a(q) : 1;
724 const float ratio =
static_cast<float>(k(q)) /
static_cast<float>(aq);
725 for (
int c = 0; c < 3; ++c)
726 out(q, c) = invInertia(q, c) * ratio;
734 int nGroups1, Kokkos::View<const int*, CpMem> a) {
735 if (nV <= 0 || nGroups1 <= 0)
737 Kokkos::View<int*, CpMem> cnt(
"peclet::dem::ml_inact_cnt", nGroups1);
738 Kokkos::parallel_for(
739 "peclet::dem::ml_inact_hist", Kokkos::RangePolicy<CpExec>(0, nV),
740 KOKKOS_LAMBDA(
int v) { Kokkos::atomic_add(&cnt(parent(off + v)), 1); });
742 Kokkos::parallel_reduce(
743 "peclet::dem::ml_inact_count", Kokkos::RangePolicy<CpExec>(0, nV),
744 KOKKOS_LAMBDA(
int v,
int& acc) {
745 if (a(v) == 0 && cnt(parent(off + v)) >= 2)
758 Kokkos::parallel_reduce(
759 "peclet::dem::copies_count_split", Kokkos::RangePolicy<CpExec>(0, H.
nGroups),
760 KOKKOS_LAMBDA(
int g,
int& acc) { acc += gk(g) > 1 ? 1 : 0; }, n);
770 Kokkos::View<const unsigned char*, CpMem> split) {
771 if (nV <= 0 || nGroups1 <= 0 || split.extent(0) <
static_cast<std::size_t
>(nV))
773 Kokkos::View<int*, CpMem> cnt(
"peclet::dem::ml_agg_cnt", nGroups1);
774 Kokkos::parallel_for(
775 "peclet::dem::ml_agg_hist", Kokkos::RangePolicy<CpExec>(0, nV),
776 KOKKOS_LAMBDA(
int v) { Kokkos::atomic_add(&cnt(parent(off + v)), 1); });
778 Kokkos::parallel_reduce(
779 "peclet::dem::ml_agg_count", Kokkos::RangePolicy<CpExec>(0, nV),
780 KOKKOS_LAMBDA(
int v,
int& acc) {
781 if (split(v) != 0 && cnt(parent(off + v)) >= 2)
791 Kokkos::View<const int*, CpMem> eB,
int nE,
int nV,
792 Kokkos::View<const float*, CpMem> invMass) {
795 const int nH = H.
nHubs;
797 Kokkos::View<int*, CpMem> hubOf(
"peclet::dem::lh_hubof", nV);
798 Kokkos::deep_copy(hubOf, -1);
799 Kokkos::parallel_for(
800 "peclet::dem::lh_map", Kokkos::RangePolicy<CpExec>(0, nH),
801 KOKKOS_LAMBDA(
int h) { hubOf(hv(h)) = h; });
802 Kokkos::View<double*, CpMem> msum(
"peclet::dem::lh_msum", nH);
803 Kokkos::View<int*, CpMem> mcnt(
"peclet::dem::lh_mcnt", nH);
804 Kokkos::parallel_for(
805 "peclet::dem::lh_accum", Kokkos::RangePolicy<CpExec>(0, nE), KOKKOS_LAMBDA(
int e) {
806 const int a = eA(e), b = eB(e);
809 const int ends[2][2] = {{a, b}, {b, a}};
810 for (
int j = 0; j < 2; ++j) {
811 const int h = hubOf(ends[j][0]);
812 const float im = invMass(ends[j][1]);
813 if (h >= 0 && im > 0.0f) {
814 Kokkos::atomic_add(&msum(h), 1.0 /
static_cast<double>(im));
815 Kokkos::atomic_add(&mcnt(h), 1);
820 Kokkos::parallel_reduce(
821 "peclet::dem::lh_count", Kokkos::RangePolicy<CpExec>(0, nH),
822 KOKKOS_LAMBDA(
int h,
int& acc) {
823 const float im = invMass(hv(h));
824 if (mcnt(h) == 0 || im <= 0.0f)
826 const double mHub = 1.0 /
static_cast<double>(im);
827 if (mHub < 10.0 * msum(h) /
static_cast<double>(mcnt(h)))
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 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...
int countSplitBodiesKokkos(const PhaseCopies &H)
Count the bodies whose group has k > 1 (split_stats).
constexpr int kHubEdgeBudget
Hub edge budget (§4.4): a colouring vertex with more active edges is split into ceil(d / kHubEdgeBudg...
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 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))),...
CpExec::memory_space CpMem
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...
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 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 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....
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...
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 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 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,...
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.
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 ...
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) !...
Kokkos::DefaultExecutionSpace CpExec
dem — portable (Kokkos) particle SoA container: the storage the dem flip pivots on.
Portable mirror of ManifoldConstraint.
Kokkos::View< float *[3], CpMem > invInertiaSolve
Kokkos::View< unsigned char *, CpMem > splitSlot
Kokkos::View< float *, CpMem > invMassSolve
Kokkos::View< unsigned char *, CpMem > groundedLevel
One solve phase's body copies (docs/contact_solve_framework.md §4.4, §4.5, §WO-4 item 2): the hub cop...
Kokkos::View< float *[3], CpMem > seedX
Kokkos::View< int *, CpMem > hubS
Kokkos::View< float *[3], CpMem > seedW
Kokkos::View< int *, CpMem > slotB
Kokkos::View< float *[3], CpMem > groupShift
Kokkos::View< int *, CpMem > hubVertex
Kokkos::View< int *, CpMem > copyBase
Kokkos::View< int *, CpMem > slotA
Kokkos::View< int *, CpMem > groupK
Kokkos::View< int *, CpMem > groupStart
Kokkos::View< unsigned char *, CpMem > groupActive
Kokkos::View< int *, CpMem > groupSlot
The position units of a contact list as a CSR (§4.3): unit u owns the contacts list(start(u)) .
Per-edge slot overrides of a phase's hub copies (docs/contact_solve_framework.md §4....
int slotA(int e, int def) const
int slotB(int e, int def) const