15#ifndef PECLET_VORO_FV_OPERATORS_HPP
16#define PECLET_VORO_FV_OPERATORS_HPP
19#include <Kokkos_Core.hpp>
26using DV = Kokkos::View<Real*, peclet::core::MemSpace>;
31 using Exec = peclet::core::ExecSpace;
33 "fv.div", Kokkos::RangePolicy<Exec>(0, m.
nCells), KOKKOS_LAMBDA(
const int i) {
48 using Exec = peclet::core::ExecSpace;
50 const bool dir = pb.extent(0) > 0;
52 "fv.gradN", Kokkos::RangePolicy<Exec>(0, m.
nFaces), KOKKOS_LAMBDA(
const int f) {
57 out(f) = dir ? (pb(f - nI) - p(a)) / m.
faceHa(f) : Real(0);
66 if ((
int)scratchFace.extent(0) != m.
nFaces)
67 scratchFace = DV<Real>(
"fv.scratchFace", m.
nFaces);
75 using Exec = peclet::core::ExecSpace;
78 "fv.greenGauss", Kokkos::RangePolicy<Exec>(0, m.
nCells), KOKKOS_LAMBDA(
const int i) {
79 Real g[3] = {0, 0, 0};
87 pf = (hb * p(a) + ha * p(b)) / (ha + hb);
92 for (
int c = 0; c < 3; ++c)
93 g[c] += w * m.
normal(f, c);
96 for (
int c = 0; c < 3; ++c)
97 out(3 * i + c) = g[c] * iv;
104 using Exec = peclet::core::ExecSpace;
105 Kokkos::parallel_for(
106 "fv.perot", Kokkos::RangePolicy<Exec>(0, m.
nCells), KOKKOS_LAMBDA(
const int i) {
107 Real v[3] = {0, 0, 0};
111 const Real w = s * u(f) * m.
faceArea(f);
114 for (
int c = 0; c < 3; ++c) {
115 const Real cf = m.
centroid(f, c) - (s < 0 ? m.
conn(f, c) : Real(0));
120 for (
int c = 0; c < 3; ++c)
121 out(3 * i + c) = v[c] * iv;
132 Real A[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
137 for (
int r = 0; r < 3; ++r) {
139 for (
int k = 0; k < 3; ++k)
140 A[3 * r + k] -= w * t * m.
normal(f, k);
143 const Real det = A[0] * (A[4] * A[8] - A[5] * A[7]) - A[1] * (A[3] * A[8] - A[5] * A[6]) +
144 A[2] * (A[3] * A[7] - A[4] * A[6]);
145 const Real
id = Real(1) / det;
146 R[0] = (A[4] * A[8] - A[5] * A[7]) *
id;
147 R[1] = (A[2] * A[7] - A[1] * A[8]) *
id;
148 R[2] = (A[1] * A[5] - A[2] * A[4]) *
id;
149 R[3] = (A[5] * A[6] - A[3] * A[8]) *
id;
150 R[4] = (A[0] * A[8] - A[2] * A[6]) *
id;
151 R[5] = (A[2] * A[3] - A[0] * A[5]) *
id;
152 R[6] = (A[3] * A[7] - A[4] * A[6]) *
id;
153 R[7] = (A[1] * A[6] - A[0] * A[7]) *
id;
154 R[8] = (A[0] * A[4] - A[1] * A[3]) *
id;
163 using Exec = peclet::core::ExecSpace;
165 const bool hasW = Uwall.extent(0) > 0;
166 Kokkos::parallel_for(
167 "fv.vgg", Kokkos::RangePolicy<Exec>(0, m.
nCells), KOKKOS_LAMBDA(
const int i) {
168 Real g[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
176 for (
int c = 0; c < 3; ++c)
177 Uf[c] = (hb * U(3 * a + c) + ha * U(3 * b + c)) / (ha + hb);
179 for (
int c = 0; c < 3; ++c)
180 Uf[c] = hasW ? Uwall(3 * (f - nI) + c) : U(3 * i + c);
183 for (
int c = 0; c < 3; ++c)
184 for (
int k = 0; k < 3; ++k)
185 g[3 * c + k] += w * Uf[c] * m.
normal(f, k);
190 for (
int c = 0; c < 3; ++c)
191 for (
int k = 0; k < 3; ++k) {
193 for (
int kk = 0; kk < 3; ++kk)
194 v += R[3 * k + kk] * g[3 * c + kk];
195 out(9 * i + 3 * c + k) = v * iv;
208 using Exec = peclet::core::ExecSpace;
210 const bool skew = gradU.extent(0) > 0, hasB = ub.extent(0) > 0;
211 Kokkos::parallel_for(
212 "fv.project", Kokkos::RangePolicy<Exec>(0, m.
nFaces), KOKKOS_LAMBDA(
const int f) {
217 const Real ha = m.
faceHa(f), hb = m.
faceHb(f), wa = hb / (ha + hb), wb = ha / (ha + hb);
218 for (
int c = 0; c < 3; ++c)
219 un += (wa * ucell(3 * a + c) + wb * ucell(3 * b + c)) * m.
normal(f, c);
222 for (
int k = 0; k < 3; ++k)
224 for (
int c = 0; c < 3; ++c) {
226 for (
int k = 0; k < 3; ++k)
227 dc += (wa * gradU(9 * a + 3 * c + k) + wb * gradU(9 * b + 3 * c + k)) * t[k];
228 un += dc * m.
normal(f, c);
234 for (
int c = 0; c < 3; ++c)
235 un += ucell(3 * a + c) * m.
normal(f, c);
243 using Exec = peclet::core::ExecSpace;
245 Kokkos::parallel_reduce(
246 "fv.dotCells", Kokkos::RangePolicy<Exec>(0, m.
nCells),
247 KOKKOS_LAMBDA(
const int i, Real& acc) { acc += m.
cellVolume(i) * a(i) * b(i); }, s);
252 using Exec = peclet::core::ExecSpace;
254 Kokkos::parallel_reduce(
255 "fv.dotFaces", Kokkos::RangePolicy<Exec>(0, m.
nInterior),
256 KOKKOS_LAMBDA(
const int f, Real& acc) { acc += m.
faceArea(f) * m.
faceDist(f) * a(f) * b(f); },
274 bool wallPrescribed =
false,
275 const std::function<void(
const DV<Real>&,
int)>& exchange = {}) {
276 using Exec = peclet::core::ExecSpace;
278 Kokkos::parallel_for(
279 "fv.T0t", Kokkos::RangePolicy<Exec>(0, m.
nCells), KOKKOS_LAMBDA(
const int i) {
280 Real v[3] = {0, 0, 0}, M[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
286 const Real wi = (m.
cellFaceSign(q) > 0 ? hb : ha) / (ha + hb);
287 const Real w = m.
faceArea(f) * (ha + hb) * wi * g(f);
288 for (
int c = 0; c < 3; ++c)
289 v[c] += w * m.
normal(f, c);
292 for (
int k = 0; k < 3; ++k)
294 for (
int c = 0; c < 3; ++c)
295 for (
int k = 0; k < 3; ++k)
296 M[3 * c + k] += w * m.
normal(f, c) * t[k];
300 for (
int c = 0; c < 3; ++c)
301 out(3 * i + c) = v[c] * iv;
305 for (
int c = 0; c < 3; ++c)
306 for (
int k = 0; k < 3; ++k) {
308 for (
int kk = 0; kk < 3; ++kk)
309 v2 += M[3 * c + kk] * R[3 * kk + k];
310 scratch9(9 * i + 3 * c + k) = v2 * iv;
317 exchange(scratch9, 9);
319 Kokkos::parallel_for(
320 "fv.T1t", Kokkos::RangePolicy<Exec>(0, m.
nCells), KOKKOS_LAMBDA(
const int i) {
321 Real v[3] = {0, 0, 0};
328 for (
int c = 0; c < 3; ++c)
329 for (
int k = 0; k < 3; ++k)
330 v[c] += m.
faceArea(f) * m.
normal(f, k) * scratch9(9 * i + 3 * c + k);
335 const Real wi = (m.
cellFaceSign(q) > 0 ? hb : ha) / (ha + hb);
336 for (
int c = 0; c < 3; ++c) {
338 for (
int k = 0; k < 3; ++k)
340 (scratch9(9 * a + 3 * c + k) - scratch9(9 * b + 3 * c + k));
345 for (
int c = 0; c < 3; ++c)
346 out(3 * i + c) += v[c] * iv;
361 using Exec = peclet::core::ExecSpace;
363 const bool hasG = gradU.extent(0) > 0, hasW = Uwall.extent(0) > 0;
364 Kokkos::parallel_for(
365 "fv.wallLS", Kokkos::RangePolicy<Exec>(0, nB), KOKKOS_LAMBDA(
const int b) {
366 const int f = nI + b, i = m.
faceCellA(f);
367 const Real ha = m.
faceHa(f);
369 for (
int c = 0; c < 3; ++c) {
371 Uw[c] = hasW ? Uwall(3 * b + c) : Real(0);
374 Real S2 = 0, S3 = 0, S4 = 0, R1[3] = {0, 0, 0}, R2[3] = {0, 0, 0};
375 auto add = [&](Real s,
const Real du[3]) {
376 const Real s2 = s * s;
380 for (
int c = 0; c < 3; ++c) {
386 for (
int c = 0; c < 3; ++c)
387 du[c] = U(3 * i + c) - Uw[c];
396 for (
int c = 0; c < 3; ++c) {
397 d[c] = sg * m.
conn(g, c);
400 const Real s = ha - dn;
401 if (!(s > Real(0.05) * ha))
403 for (
int c = 0; c < 3; ++c) {
406 for (
int k = 0; k < 3; ++k)
407 tang += gradU(9 * i + 3 * c + k) * (d[k] - dn * n[k]);
408 du[c] = U(3 * j + c) - tang - Uw[c];
412 const Real det = S2 * S4 - S3 * S3;
413 for (
int c = 0; c < 3; ++c) {
415 if (det > Real(1e-30) * S2 * S4)
416 a = (S4 * R1[c] - S3 * R2[c]) / det;
418 a = (U(3 * i + c) - Uw[c]) / ha;
431 using Exec = peclet::core::ExecSpace;
433 DV<Real> r(
"cg.r", N), z(
"cg.z", N), q(
"cg.q", N), sf;
434 Real Vtot = 0, fMean = 0;
435 Kokkos::parallel_reduce(
436 "cg.vtot", Kokkos::RangePolicy<Exec>(0, N),
437 KOKKOS_LAMBDA(
const int i, Real& acc) { acc += m.
cellVolume(i); }, Vtot);
438 Kokkos::parallel_reduce(
439 "cg.fmean", Kokkos::RangePolicy<Exec>(0, N),
440 KOKKOS_LAMBDA(
const int i, Real& acc) { acc += m.
cellVolume(i) * f(i); }, fMean);
442 Kokkos::deep_copy(p, Real(0));
444 Kokkos::parallel_for(
445 "cg.r0", Kokkos::RangePolicy<Exec>(0, N),
446 KOKKOS_LAMBDA(
const int i) { r(i) = f(i) - fMean; });
447 Kokkos::deep_copy(z, r);
449 const Real r0 = Kokkos::sqrt(rr);
450 if (!(r0 > Real(0))) {
455 for (; it < maxIter; ++it) {
457 Kokkos::parallel_for(
458 "cg.negq", Kokkos::RangePolicy<Exec>(0, N), KOKKOS_LAMBDA(
const int i) { q(i) = -q(i); });
462 const Real alpha = rr / zq;
463 Kokkos::parallel_for(
464 "cg.upd", Kokkos::RangePolicy<Exec>(0, N), KOKKOS_LAMBDA(
const int i) {
465 p(i) += alpha * z(i);
466 r(i) -= alpha * q(i);
469 resOut = Kokkos::sqrt(rrn) / (r0 > Real(0) ? r0 : Real(1));
474 const Real beta = rrn / rr;
476 Kokkos::parallel_for(
477 "cg.z", Kokkos::RangePolicy<Exec>(0, N),
478 KOKKOS_LAMBDA(
const int i) { z(i) = r(i) + beta * z(i); });
482 Kokkos::parallel_reduce(
483 "cg.pmean", Kokkos::RangePolicy<Exec>(0, N),
484 KOKKOS_LAMBDA(
const int i, Real& acc) { acc += m.
cellVolume(i) * p(i); }, pMean);
486 Kokkos::parallel_for(
487 "cg.pin", Kokkos::RangePolicy<Exec>(0, N), KOKKOS_LAMBDA(
const int i) { p(i) -= pMean; });
Track C, rung C1 (Voronoi methods plan): the FACE mesh of a published tessellation — one record per g...
Definition collocated.hpp:38
void laplacian(const FaceMesh< Real > &m, const DV< Real > &p, const DV< Real > &out, DV< Real > &scratchFace, const DV< Real > &pb=DV< Real >{})
L p = div(grad p): the two-point Laplacian (Neumann on boundary faces unless pb is given).
Definition operators.hpp:64
Real dotCells(const FaceMesh< Real > &m, const DV< Real > &a, const DV< Real > &b)
Definition operators.hpp:242
void vectorGreenGauss(const FaceMesh< Real > &m, const DV< Real > &U, const DV< Real > &out, const DV< Real > &Uwall=DV< Real >{})
Definition operators.hpp:161
void faceInterpTranspose(const FaceMesh< Real > &m, const DV< Real > &g, const DV< Real > &out, bool skew=false, const DV< Real > &scratch9=DV< Real >{}, bool wallPrescribed=false, const std::function< void(const DV< Real > &, int)> &exchange={})
Definition operators.hpp:272
void projectToFaces(const FaceMesh< Real > &m, const DV< Real > &ucell, const DV< Real > &out, const DV< Real > &gradU=DV< Real >{}, const DV< Real > &ub=DV< Real >{})
Definition operators.hpp:206
Kokkos::View< Real *, peclet::core::MemSpace > DV
Definition operators.hpp:26
KOKKOS_INLINE_FUNCTION void cellSkewInverse(const FaceMesh< Real > &m, int i, Real R[9])
Definition operators.hpp:131
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 perotVelocity(const FaceMesh< Real > &m, const DV< Real > &u, const DV< Real > &out)
Perot reconstruction of the cell velocity (3N) from face-normal fluxes.
Definition operators.hpp:103
void wallGradientLS(const FaceMesh< Real > &m, const DV< Real > &U, const DV< Real > &gradU, const DV< Real > &Uwall, const DV< Real > &out)
Definition operators.hpp:359
void greenGaussGradient(const FaceMesh< Real > &m, const DV< Real > &p, const DV< Real > &out)
Green–Gauss cell gradient (3N): distance-weighted face values, boundary faces use p_A.
Definition operators.hpp:74
Real dotFaces(const FaceMesh< Real > &m, const DV< Real > &a, const DV< Real > &b)
Definition operators.hpp:251
int poissonCG(const FaceMesh< Real > &m, const DV< Real > &f, const DV< Real > &p, Real tol, int maxIter, Real &resOut)
Definition operators.hpp:429
Kokkos::View< int *, Mem > cellFace
Definition mesh.hpp:49
Kokkos::View< Real *, Mem > faceHb
Definition mesh.hpp:45
int nInterior
Definition mesh.hpp:35
Kokkos::View< int *, Mem > faceCellB
Definition mesh.hpp:40
KOKKOS_INLINE_FUNCTION Real conn(int f, int c) const
Definition mesh.hpp:57
Kokkos::View< Real *, Mem > faceDist
Definition mesh.hpp:44
KOKKOS_INLINE_FUNCTION Real normal(int f, int c) const
Definition mesh.hpp:55
Kokkos::View< int *, Mem > faceCellA
Definition mesh.hpp:40
int nCells
Definition mesh.hpp:35
KOKKOS_INLINE_FUNCTION Real centroid(int f, int c) const
Definition mesh.hpp:56
KOKKOS_INLINE_FUNCTION int cellFacesBegin(int i) const
Definition mesh.hpp:53
Kokkos::View< Real *, Mem > cellFaceSign
Definition mesh.hpp:50
KOKKOS_INLINE_FUNCTION int cellFacesEnd(int i) const
Definition mesh.hpp:54
Kokkos::View< Real *, Mem > cellVolume
Definition mesh.hpp:51
int nFaces
Definition mesh.hpp:35
Kokkos::View< Real *, Mem > faceArea
Definition mesh.hpp:42
Kokkos::View< Real *, Mem > faceHa
Definition mesh.hpp:45