peclet.voro 1.0.4
Device-native moving-particle Voronoi dynamics
Loading...
Searching...
No Matches
dec.hpp
Go to the documentation of this file.
1
24#ifndef PECLET_VORO_FV_DEC_HPP
25#define PECLET_VORO_FV_DEC_HPP
26
27#include <Kokkos_Core.hpp>
28
32
33namespace peclet::voro::fv {
34
38template <class Real>
39struct DecEdges {
40 using Mem = peclet::core::MemSpace;
41 Kokkos::View<int*, Mem> offset; // nInterior + 1
42 Kokkos::View<Real*, Mem> weight; // nEdges: ℓ_ε / |t|
43 Kokkos::View<int*, Mem> face2, face3; // nEdges: faces (B,k) and (k,A)
44 Kokkos::View<Real*, Mem> sign2, sign3; // nEdges: orientation of the legs B→k and k→A
45 int nEdges = 0, nSkipped = 0; // skipped: legs not found (wall / ghost / degenerate)
46};
47
49template <class Real>
51 using Exec = peclet::core::ExecSpace;
52 using Mem = peclet::core::MemSpace;
54 const int nI = m.nInterior, nF = view.numFacets();
55 // facet -> face (+ sign): every interior face is the owner facet (+1) and its reciprocal (−1)
56 Kokkos::View<int*, Mem> facetFace("dec.facetFace", nF);
57 Kokkos::View<Real*, Mem> facetSign("dec.facetSign", nF);
58 Kokkos::deep_copy(facetFace, -1);
59 {
60 auto FF = m.faceFacet;
61 auto A = m.faceCellA;
62 auto B = m.faceCellB;
63 Kokkos::parallel_for(
64 "dec.inv", Kokkos::RangePolicy<Exec>(0, nI), KOKKOS_LAMBDA(const int f) {
65 const int g = FF(f);
66 facetFace(g) = f;
67 facetSign(g) = Real(1);
68 // the reciprocal facet: cell B's facet whose neighbour is A
69 const int b = B(f), a = A(f);
70 if (b < 0 || b >= view.numCells())
71 return;
72 const int beg = view.cellFacetOffset(b), end = beg + view.cellFacetCount(b);
73 for (int h = beg; h < end; ++h)
74 if (view.facetNbr(h) == a) {
75 facetFace(h) = f;
76 facetSign(h) = Real(-1);
77 break;
78 }
79 });
80 }
81 // count edges per interior face (partner slots of the owner facet)
82 Kokkos::View<int*, Mem> cnt("dec.cnt", nI + 1);
83 {
84 auto FF = m.faceFacet;
85 Kokkos::parallel_for(
86 "dec.cnt", Kokkos::RangePolicy<Exec>(0, nI), KOKKOS_LAMBDA(const int f) {
87 const int g = FF(f);
88 cnt(f) = view.facetEdgeCount(g) > 0 ? view.facetEdgeCount(g) - 1 : 0;
89 });
90 }
91 d.offset = Kokkos::View<int*, Mem>("dec.offset", nI + 1);
92 {
93 auto off = d.offset;
94 Kokkos::parallel_scan(
95 "dec.scan", Kokkos::RangePolicy<Exec>(0, nI + 1),
96 KOKKOS_LAMBDA(const int f, int& upd, const bool fin) {
97 if (fin)
98 off(f) = upd;
99 upd += f < nI ? cnt(f) : 0;
100 });
101 }
102 int nE = 0;
103 Kokkos::deep_copy(nE, Kokkos::subview(d.offset, nI));
104 d.nEdges = nE;
105 d.weight = Kokkos::View<Real*, Mem>("dec.weight", nE);
106 d.face2 = Kokkos::View<int*, Mem>("dec.face2", nE);
107 d.face3 = Kokkos::View<int*, Mem>("dec.face3", nE);
108 d.sign2 = Kokkos::View<Real*, Mem>("dec.sign2", nE);
109 d.sign3 = Kokkos::View<Real*, Mem>("dec.sign3", nE);
110 int skipped = 0;
111 {
112 auto FF = m.faceFacet;
113 auto B = m.faceCellB;
114 auto off = d.offset;
115 auto W = d.weight;
116 auto F2 = d.face2;
117 auto F3 = d.face3;
118 auto S2 = d.sign2;
119 auto S3 = d.sign3;
120 const int nCells = m.nCells;
121 Kokkos::parallel_reduce(
122 "dec.fill", Kokkos::RangePolicy<Exec>(0, nI),
123 KOKKOS_LAMBDA(const int f, int& sk) {
124 const int g = FF(f), b = B(f);
125 const int eb = view.facetEdgeOffset(g), ec = view.facetEdgeCount(g);
126 int out = off(f);
127 // r_AB = connector of facet g
128 const Real rAB[3] = {view.connVec(g, 0), view.connVec(g, 1), view.connVec(g, 2)};
129 for (int e = eb + 1; e < eb + ec; ++e, ++out) {
130 const int g3 = view.edgePartner(e); // facet of cell A toward k
131 const int k = view.facetNbr(g3);
132 W(out) = Real(0);
133 F2(out) = F3(out) = -1;
134 S2(out) = S3(out) = Real(0);
135 if (k < 0 || k >= nCells || b < 0 || b >= nCells) {
136 ++sk;
137 continue;
138 }
139 const Real rAk[3] = {view.connVec(g3, 0), view.connVec(g3, 1), view.connVec(g3, 2)};
140 // |t| = ½ |r_AB × r_Ak|
141 const Real cx = rAB[1] * rAk[2] - rAB[2] * rAk[1],
142 cy = rAB[2] * rAk[0] - rAB[0] * rAk[2],
143 cz = rAB[0] * rAk[1] - rAB[1] * rAk[0];
144 const Real tArea = Real(0.5) * Kokkos::sqrt(cx * cx + cy * cy + cz * cz);
145 const Real len = view.edgeLen(e);
146 // leg k→A: facet g3 of A toward k; the face's stored orientation is A→k if A is its
147 // cell A, so k→A = −(A→k)
148 const int f3 = facetFace(g3);
149 if (f3 < 0 || tArea <= Real(0)) {
150 ++sk;
151 continue;
152 }
153 const Real s3 = -facetSign(g3);
154 // leg B→k: cell B's facet toward k
155 int f2 = -1;
156 Real s2 = 0;
157 const int bb = view.cellFacetOffset(b), be = bb + view.cellFacetCount(b);
158 for (int h = bb; h < be; ++h)
159 if (view.facetNbr(h) == k) {
160 f2 = facetFace(h);
161 s2 = facetSign(h); // +1 if that face is stored B→k
162 break;
163 }
164 if (f2 < 0) {
165 ++sk;
166 continue;
167 }
168 W(out) = len / tArea;
169 F2(out) = f2;
170 S2(out) = s2;
171 F3(out) = f3;
172 S3(out) = s3;
173 }
174 },
175 skipped);
176 }
177 d.nSkipped = skipped;
178 return d;
179}
180
184template <class Real>
185void decLaplacian(const FaceMesh<Real>& m, const DecEdges<Real>& d, const DV<Real>& u,
186 const DV<Real>& divScratch, const DV<Real>& out) {
187 using Exec = peclet::core::ExecSpace;
188 divergence(m, u, divScratch);
189 faceGradient(m, divScratch, out); // grad div (boundary faces: 0)
190 const int nI = m.nInterior;
191 Kokkos::parallel_for(
192 "dec.curlcurl", Kokkos::RangePolicy<Exec>(0, nI), KOKKOS_LAMBDA(const int f) {
193 Real cc = 0;
194 const Real g1 = u(f) * m.faceDist(f); // leg A→B
195 for (int e = d.offset(f); e < d.offset(f + 1); ++e) {
196 if (d.weight(e) <= Real(0))
197 continue;
198 const int f2 = d.face2(e), f3 = d.face3(e);
199 const Real gamma =
200 g1 + d.sign2(e) * u(f2) * m.faceDist(f2) + d.sign3(e) * u(f3) * m.faceDist(f3);
201 cc += d.weight(e) * gamma;
202 }
203 // degenerate (zero-area) faces carry no flux: no curl-curl contribution
204 if (m.faceArea(f) > Real(1e-14))
205 out(f) -= cc / m.faceArea(f);
206 else
207 out(f) = Real(0);
208 });
209}
210
211} // namespace peclet::voro::fv
212
213#endif // PECLET_VORO_FV_DEC_HPP
Track C, rung C1 (Voronoi methods plan): the FACE mesh of a published tessellation — one record per g...
Definition collocated.hpp:38
Kokkos::View< Real *, peclet::core::MemSpace > DV
Definition operators.hpp:26
DecEdges< Real > buildDecEdges(const TessellationView< Real > &view, const FaceMesh< Real > &m)
Build the DEC edge structure. facetOfFace-style inverse maps are built here from the mesh.
Definition dec.hpp:50
void divergence(const FaceMesh< Real > &m, const DV< Real > &u, const DV< Real > &out)
(div u)_i from face-normal fluxes u (nFaces; boundary faces included, along the outward normal).
Definition operators.hpp:30
void faceGradient(const FaceMesh< Real > &m, const DV< Real > &p, const DV< Real > &out, const DV< Real > &pb=DV< Real >{})
Definition operators.hpp:46
void decLaplacian(const FaceMesh< Real > &m, const DecEdges< Real > &d, const DV< Real > &u, const DV< Real > &divScratch, const DV< Real > &out)
Definition dec.hpp:185
Track C, rung C1: the discrete operators of the staggered COVOLUME scheme on a face mesh (plan verdic...
Definition tessellation_view.hpp:111
Kokkos::View< int *, peclet::core::MemSpace > facetEdgeOffset
Definition tessellation_view.hpp:138
KOKKOS_INLINE_FUNCTION gid_t facetNbr(int f) const
Definition tessellation_view.hpp:185
Kokkos::View< int *, peclet::core::MemSpace > facetEdgeCount
Definition tessellation_view.hpp:139
KOKKOS_INLINE_FUNCTION int edgePartner(int e) const
Definition tessellation_view.hpp:168
KOKKOS_INLINE_FUNCTION Real connVec(int f, int c) const
Definition tessellation_view.hpp:188
KOKKOS_INLINE_FUNCTION int numFacets() const
Definition tessellation_view.hpp:178
KOKKOS_INLINE_FUNCTION Real edgeLen(int e) const
Definition tessellation_view.hpp:170
Kokkos::View< int *, peclet::core::MemSpace > cellFacetOffset
Definition tessellation_view.hpp:117
KOKKOS_INLINE_FUNCTION int numCells() const
Definition tessellation_view.hpp:173
Kokkos::View< int *, peclet::core::MemSpace > cellFacetCount
Definition tessellation_view.hpp:118
Definition dec.hpp:39
Kokkos::View< Real *, Mem > weight
Definition dec.hpp:42
Kokkos::View< Real *, Mem > sign2
Definition dec.hpp:44
int nSkipped
Definition dec.hpp:45
peclet::core::MemSpace Mem
Definition dec.hpp:40
Kokkos::View< int *, Mem > face2
Definition dec.hpp:43
Kokkos::View< Real *, Mem > sign3
Definition dec.hpp:44
Kokkos::View< int *, Mem > face3
Definition dec.hpp:43
int nEdges
Definition dec.hpp:45
Kokkos::View< int *, Mem > offset
Definition dec.hpp:41
Definition mesh.hpp:33
int nInterior
Definition mesh.hpp:35
Kokkos::View< int *, Mem > faceFacet
Definition mesh.hpp:41
Kokkos::View< int *, Mem > faceCellB
Definition mesh.hpp:40
Kokkos::View< Real *, Mem > faceDist
Definition mesh.hpp:44
Kokkos::View< int *, Mem > faceCellA
Definition mesh.hpp:40
int nCells
Definition mesh.hpp:35
Kokkos::View< Real *, Mem > faceArea
Definition mesh.hpp:42
Published, read-only device data layer for the tessellation (migration §2.1, §3).