core 1.5.0
Shared MPI block decomposition, asynchronous ghost-layer exchange, SDF geometry, load balancing (header-only C++20)
Loading...
Searching...
No Matches
coloring.hpp
Go to the documentation of this file.
1// core — greedy graph colouring of a face CSR for race-free multicolour Gauss–Seidel sweeps.
2//
3// Lifted verbatim from the AMR tree (peclet/core/amr/momentum.hpp, 2026-09-10; QUALITY_PLAN G.2):
4// on a 2:1-graded octree or a Voronoi-cell mesh the face-adjacency graph needs a general greedy
5// colouring (~6–8 colours); a colour is a set of cells with no shared face, so all of one colour
6// update in parallel reading the already-updated other colours — a true GS sweep, deterministic
7// (fixed cell order ⇒ fixed colouring). Mesh-agnostic: operates on a face CSR, no octree types.
8// Consumers: the AMR momentum multigrid (peclet-amr) and voro's mesh optimiser.
9#ifndef PECLET_CORE_SOLVER_COLORING_HPP
10#define PECLET_CORE_SOLVER_COLORING_HPP
11
12#include <cstddef>
13#include <vector>
14
17
18namespace peclet::core::solver {
19
22struct Coloring {
23 std::vector<Index> hStart;
25 int nColors = 1;
26};
27
39inline Coloring greedyColoring(const std::vector<Index>& start, const std::vector<Index>& nbr,
40 Index n) {
41 // Build the symmetric (undirected) adjacency in CSR form.
42 std::vector<Index> deg(static_cast<std::size_t>(n) + 1, 0);
43 for (Index i = 0; i < n; ++i)
44 for (Index k = start[static_cast<std::size_t>(i)]; k < start[static_cast<std::size_t>(i) + 1];
45 ++k) {
46 ++deg[static_cast<std::size_t>(i) + 1];
47 ++deg[static_cast<std::size_t>(nbr[static_cast<std::size_t>(k)]) + 1];
48 }
49 for (Index i = 0; i < n; ++i)
50 deg[static_cast<std::size_t>(i) + 1] += deg[static_cast<std::size_t>(i)];
51 std::vector<Index> aStart(deg); // copy of the offsets
52 std::vector<Index> aNbr(static_cast<std::size_t>(deg[static_cast<std::size_t>(n)]));
53 std::vector<Index> acur(deg.begin(), deg.end() - 1);
54 for (Index i = 0; i < n; ++i)
55 for (Index k = start[static_cast<std::size_t>(i)]; k < start[static_cast<std::size_t>(i) + 1];
56 ++k) {
57 const Index j = nbr[static_cast<std::size_t>(k)];
58 aNbr[static_cast<std::size_t>(acur[static_cast<std::size_t>(i)]++)] = j;
59 aNbr[static_cast<std::size_t>(acur[static_cast<std::size_t>(j)]++)] = i;
60 }
61 std::vector<int> color(static_cast<std::size_t>(n), -1);
62 std::vector<int> stamp; // stamp[c]==i ⇒ colour c forbidden for cell i (avoids per-cell clears)
63 int nColors = 1;
64 for (Index i = 0; i < n; ++i) {
65 for (Index k = aStart[static_cast<std::size_t>(i)]; k < aStart[static_cast<std::size_t>(i) + 1];
66 ++k) {
67 const int nc = color[static_cast<std::size_t>(aNbr[static_cast<std::size_t>(k)])];
68 if (nc >= 0) {
69 if (static_cast<std::size_t>(nc) >= stamp.size())
70 stamp.resize(static_cast<std::size_t>(nc) + 1, -1);
71 stamp[static_cast<std::size_t>(nc)] = static_cast<int>(i);
72 }
73 }
74 int c = 0;
75 while (c < static_cast<int>(stamp.size()) &&
76 stamp[static_cast<std::size_t>(c)] == static_cast<int>(i))
77 ++c;
78 color[static_cast<std::size_t>(i)] = c;
79 if (c + 1 > nColors)
80 nColors = c + 1;
81 }
83 col.nColors = nColors;
84 col.hStart.assign(static_cast<std::size_t>(nColors) + 1, 0);
85 for (Index i = 0; i < n; ++i)
86 ++col.hStart[static_cast<std::size_t>(color[static_cast<std::size_t>(i)]) + 1];
87 for (int c = 0; c < nColors; ++c)
88 col.hStart[static_cast<std::size_t>(c) + 1] += col.hStart[static_cast<std::size_t>(c)];
89 std::vector<Index> idx(static_cast<std::size_t>(n));
90 std::vector<Index> cur(col.hStart.begin(), col.hStart.end() - 1);
91 for (Index i = 0; i < n; ++i) {
92 const int c = color[static_cast<std::size_t>(i)];
93 idx[static_cast<std::size_t>(cur[static_cast<std::size_t>(c)]++)] = i;
94 }
95 col.idx = toDevice(idx, "gs_coloring");
96 return col;
97}
98
99} // namespace peclet::core::solver
100
101#endif // PECLET_CORE_SOLVER_COLORING_HPP
Coloring greedyColoring(const std::vector< Index > &start, const std::vector< Index > &nbr, Index n)
Greedy colouring of the face CSR (start/nbr, host): each cell gets the smallest colour not used by an...
Definition coloring.hpp:39
View< T > toDevice(const std::vector< T > &h, const std::string &label)
Upload a host std::vector into a freshly-sized device View (empty vector => empty view).
Definition view.hpp:44
Kokkos::View< T *, MemSpace > View
1D device array.
Definition view.hpp:26
std::int64_t Index
Signed index type for grids and particles (supersedes block_decomposer's long int IndxT).
Definition types.hpp:15
A graph colouring of a face CSR: cells grouped by colour.
Definition coloring.hpp:22
std::vector< Index > hStart
Definition coloring.hpp:23