79 std::vector<char> onWall(nP, 0);
80 for (
int f = 0; f < m.
nFaces; ++f)
85 for (
int p = 0; p < nP; ++p)
91 for (
int k = 0; k < 3; ++k)
92 Mq[k] = std::max<long long>(1, (
long long)std::floor(L[k] / tol));
93 auto cellOf = [&](Real x,
int k) {
94 long long c = (
long long)std::floor(x / L[k] * (Real)Mq[k]);
96 return c < 0 ? c + Mq[k] : c;
100 cellOf(m.
points[3 * p + 2], 2)}]
102 std::vector<int> parent(nP);
103 for (
int p = 0; p < nP; ++p)
105 std::function<int(
int)> find = [&](
int a) {
106 while (parent[a] != a)
107 a = parent[a] = parent[parent[a]];
110 const Real tol2 = tol * tol;
112 const long long c0[3] = {cellOf(m.
points[3 * p], 0), cellOf(m.
points[3 * p + 1], 1),
113 cellOf(m.
points[3 * p + 2], 2)};
114 for (
int dz = -1; dz <= 1; ++dz)
115 for (
int dy = -1; dy <= 1; ++dy)
116 for (
int dx = -1; dx <= 1; ++dx) {
117 auto w = [&](
long long c,
long long M) {
return ((c % M) + M) % M; };
119 detail::VertexKey{w(c0[0] + dx, Mq[0]), w(c0[1] + dy, Mq[1]), w(c0[2] + dz, Mq[2])});
120 if (it == grid.end())
122 for (
int q : it->second) {
126 for (
int k = 0; k < 3; ++k) {
128 d -= L[k] * std::round(d / L[k]);
132 const int ra = find(p), rb = find(q);
140 std::vector<Real> acc(3 * (
size_t)nP, Real(0));
141 std::vector<int> cnt(nP, 0);
144 const int r = find(p);
145 for (
int k = 0; k < 3; ++k) {
147 d -= L[k] * std::round(d / L[k]);
155 if (find(p) == p && cnt[p] > 1)
156 for (
int k = 0; k < 3; ++k)
157 m.
points[3 * p + k] += acc[3 * p + k] / (Real)cnt[p];
159 std::vector<int> newVerts, newOff(1, 0), newOwner, newNbr, newPatch;
160 std::vector<int> faceMap(m.
nFaces, -1);
161 for (
int f = 0; f < m.
nFaces; ++f) {
162 std::vector<int> poly;
165 if (poly.empty() || poly.back() != v)
168 while (poly.size() > 1 && poly.front() == poly.back())
172 faceMap[f] = (int)newOff.size() - 1;
173 newVerts.insert(newVerts.end(), poly.begin(), poly.end());
174 newOff.push_back((
int)newVerts.size());
175 newOwner.push_back(m.
owner[f]);
177 newPatch.push_back(m.
patch[f]);
179 std::vector<int> cf, cfo(1, 0);
180 for (
int i = 0; i < m.
nCells; ++i) {
183 cf.push_back(faceMap[m.
cellFace[q]]);
184 cfo.push_back((
int)cf.size());
187 for (
int f = 0; f < (int)newPatch.size(); ++f)
188 nInt += newPatch[f] == 0;
196 m.
nFaces = (int)newPatch.size();
204 const Kokkos::View<Real*, peclet::core::MemSpace>& pos,
int N,
206 Kokkos::View<Real*, peclet::core::MemSpace> xRef = {},
207 Real quantum = Real(1e-9)) {
208 using Cell = ConvexCell<Real, MAXP, MAXT, false>;
209 auto np = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, store.
np);
210 auto nt = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, store.
nt);
211 auto pnbr = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, store.
pnbr);
212 auto tri = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, store.
tri);
213 auto ph = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, pos);
215 auto loadHost = [&](
int i, Cell& c) {
216 c.initBoxPlanes(L[0], L[1], L[2]);
217 const int npi = np(i), nti = nt(i);
221 for (
int k = 6; k < npi; ++k)
222 c.pnbr[k] = pnbr((
size_t)i * MAXP + k);
223 for (
int t = 0; t < nti; ++t) {
224 const unsigned w = tri((
size_t)i * MAXT + t);
225 c.t0[t] = (
unsigned char)(w & 0xffu);
226 c.t1[t] = (
unsigned char)((w >> 8) & 0xffu);
227 c.t2[t] = (
unsigned char)((w >> 16) & 0xffu);
228 c.alive[t] = ((w >> 24) & 1u) != 0u;
231 const bool hasWall = wall.cnt.extent(0) > 0;
232 typename Kokkos::View<Real*, peclet::core::MemSpace>::host_mirror_type wrecM, xrM;
233 typename Kokkos::View<int*, peclet::core::MemSpace>::host_mirror_type wcntM;
235 wrecM = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, wall.rec);
236 wcntM = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, wall.cnt);
237 xrM = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, xRef);
241 m.cellVolume.assign(N, Real(0));
242 std::unordered_map<detail::VertexKey, int, detail::VertexKeyHash> vmap;
243 vmap.reserve((
size_t)N * 8);
245 const long long M[3] = {(
long long)std::llround(Real(1) / quantum),
246 (
long long)std::llround(Real(1) / quantum),
247 (
long long)std::llround(Real(1) / quantum)};
248 auto wrapq = [](
long long v,
long long m) {
250 return v < 0 ? v + m : v;
252 auto vertexId = [&](Real x, Real y, Real z) {
253 detail::VertexKey k{wrapq((
long long)std::llround(x / (quantum * L[0])), M[0]),
254 wrapq((
long long)std::llround(y / (quantum * L[1])), M[1]),
255 wrapq((
long long)std::llround(z / (quantum * L[2])), M[2])};
256 auto it = vmap.find(k);
257 if (it != vmap.end())
259 const int id = m.nPoints();
260 m.points.push_back(x);
261 m.points.push_back(y);
262 m.points.push_back(z);
267 std::vector<std::vector<int>> cellFaces(N);
268 std::vector<int> faceOwner, faceNbr, facePatch, faceOff{0}, faceV;
269 const Real Lh[3] = {L[0] / 2, L[1] / 2, L[2] / 2};
270 for (
int i = 0; i < N; ++i) {
273 const Real sx = ph(3 * i), sy = ph(3 * i + 1), sz = ph(3 * i + 2);
275 Real dx = sx - xrM(3 * i), dy = sy - xrM(3 * i + 1), dz = sz - xrM(3 * i + 2);
276 dx = dx > Lh[0] ? dx - L[0] : (dx < -Lh[0] ? dx + L[0] : dx);
277 dy = dy > Lh[1] ? dy - L[1] : (dy < -Lh[1] ? dy + L[1] : dy);
278 dz = dz > Lh[2] ? dz - L[2] : (dz < -Lh[2] ? dz + L[2] : dz);
281 const int nrec = wcntM(i);
282 for (
int k = 6; k < c.np; ++k) {
283 if (c.pnbr[k] >= 0 || r >= nrec)
286 const Real ux = wrecM(o), uy = wrecM(o + 1), uz = wrecM(o + 2);
287 const Real h = wrecM(o + 3) - (ux * dx + uy * dy + uz * dz);
295 c.reevalGeometry(sx, sy, sz, ph.data(), L[0]);
297 for (
int k = 0; k < c.np; ++k) {
298 Real fx[Cell::MAXFV], fy[Cell::MAXFV], fz[Cell::MAXFV];
299 const int nv = c.faceOrdered(k, fx, fy, fz);
302 const int j = c.pnbr[k];
304 for (
int q = 1; q + 1 < nv; ++q) {
305 const Real ax = fx[0], ay = fy[0], az = fz[0], bx = fx[q], by = fy[q], bz = fz[q],
306 cx = fx[q + 1], cy = fy[q + 1], cz = fz[q + 1];
307 V += std::fabs(ax * (by * cz - bz * cy) - ay * (bx * cz - bz * cx) +
308 az * (bx * cy - by * cx)) /
313 const int fid = (int)faceOwner.size();
314 faceOwner.push_back(i);
315 faceNbr.push_back(j >= 0 ? j : -1);
317 for (
int q = 0; q < nv; ++q)
318 faceV.push_back(vertexId(sx + fx[q], sy + fy[q], sz + fz[q]));
319 faceOff.push_back((
int)faceV.size());
320 cellFaces[i].push_back(fid);
322 cellFaces[j].push_back(fid);
327 const int nF = (int)faceOwner.size();
328 std::vector<int> perm(nF), inv(nF);
330 for (
int f = 0; f < nF; ++f)
331 if (facePatch[f] == 0)
334 for (
int f = 0; f < nF; ++f)
335 if (facePatch[f] != 0)
337 for (
int f = 0; f < nF; ++f)
340 m.faceOffset.assign(1, 0);
341 for (
int f = 0; f < nF; ++f) {
342 const int o = perm[f];
343 m.owner.push_back(faceOwner[o]);
344 m.neighbour.push_back(faceNbr[o]);
345 m.patch.push_back(facePatch[o]);
346 for (
int v = faceOff[o]; v < faceOff[o + 1]; ++v)
347 m.faceVerts.push_back(faceV[v]);
348 m.faceOffset.push_back((
int)m.faceVerts.size());
350 m.cellFaceOffset.assign(1, 0);
351 for (
int i = 0; i < N; ++i) {
352 for (
int f : cellFaces[i])
353 m.cellFace.push_back(inv[f]);
354 m.cellFaceOffset.push_back((
int)m.cellFace.size());
PolyMesh< Real > buildPolyMesh(const TopologyStore< MAXP, MAXT > &store, const Kokkos::View< Real *, peclet::core::MemSpace > &pos, int N, const Real L[3], WallStore< Real > wall={}, Kokkos::View< Real *, peclet::core::MemSpace > xRef={}, Real quantum=Real(1e-9))
Assemble the polyhedral mesh of a store at positions posHost (3N, world, in [0,L)).
Definition polymesh.hpp:203