38#ifndef PECLET_CORE_AMR_CF_SCHEME_HPP
39#define PECLET_CORE_AMR_CF_SCHEME_HPP
41#ifdef PECLET_CORE_HAVE_MORTON
82template <
unsigned Bits,
class Ent,
class Flu
idFn>
92 const double sc =
static_cast<double>(
Index(1) <<
t.level(
coarse));
93 const double sf =
static_cast<double>(
Index(1) <<
t.level(
fine));
100 for (
int tt = 0;
tt < 3; ++
tt) {
103 const double dt = ((
static_cast<double>(
bf[0][
tt]) + 0.5 *
sf) -
104 (
static_cast<double>(
bc[0][
tt]) + 0.5 *
sc)) *
141 for (
int d = 0; d < 3; ++d)
142 ext[d] =
static_cast<long>(
t.brick()[d]) * (1L <<
t.lmax());
143 std::array<typename BlockOctree<3, Bits>::Coord, 3>
lo =
bc2[0];
144 const long shifted =
static_cast<long>(
lo[
tt]) + (dir > 0 ?
static_cast<long>(
sc2) : -
static_cast<long>(
sc2));
148 std::array<typename BlockOctree<3, Bits>::Coord, 3>
q =
lo;
149 for (
int d = 0; d < 3; ++d)
152 (
static_cast<long>(
q[d]) +
static_cast<long>(
sh)) %
ext[d]);
157 sm.w[
sm.n] = 1.0 /
static_cast<double>(1 << 3);
165 if (!
sp.ok || !
smi.ok)
169 const double cUp =
dt / (2.0 *
H) + 0.5 *
dt *
dt / (
H *
H);
170 const double cUm = -
dt / (2.0 *
H) + 0.5 *
dt *
dt / (
H *
H);
190template <
class Ent,
class Csr>
192 out.start.assign(
static_cast<std::size_t
>(n) + 1, 0);
194 out.start[
static_cast<std::size_t
>(
i) + 1] =
195 out.start[
static_cast<std::size_t
>(
i)] +
196 static_cast<Index>(
per[
static_cast<std::size_t
>(
i)].size());
197 const Index nz =
out.start[
static_cast<std::size_t
>(n)];
198 out.slot.resize(
static_cast<std::size_t
>(nz));
199 out.coef.resize(
static_cast<std::size_t
>(nz));
202 for (
const auto&
e :
per[
static_cast<std::size_t
>(
i)]) {
203 out.slot[
static_cast<std::size_t
>(k)] =
e.
cell;
204 out.coef[
static_cast<std::size_t
>(k)] =
e.w;
216template <
unsigned Bits,
class RowFn,
class Flu
idFn>
219 const Index n =
t.numLeaves();
220 std::vector<std::vector<detail::ScalarEnt>>
per(
static_cast<std::size_t
>(n));
224 const unsigned Li =
t.level(
i);
227 const unsigned Lj =
t.level(
j);
232 const double scale = factor *
invV * (
a *
c) * ((
Lj >
Li) ? 1.0 : -1.0);
252template <
unsigned Bits,
class RowFn,
class Flu
idFn>
255 const Index n =
t.numLeaves();
256 std::vector<std::vector<detail::CompEnt>>
per(
static_cast<std::size_t
>(n));
261 const unsigned Li =
t.level(
i);
264 const unsigned Lj =
t.level(
j);
270 const double d = 0.5 * (
H +
h);
271 const double wF = (0.5 *
H) / d,
wC = (0.5 *
h) / d;
272 const double scale =
invV * alpha *
area *
static_cast<double>(dir);
275 auto&
row =
per[
static_cast<std::size_t
>(
i)];
290 csr.comp.resize(
csr.slot.size());
293 for (
const auto&
e :
per[
static_cast<std::size_t
>(
i)])
294 csr.comp[
static_cast<std::size_t
>(k++)] =
e.comp;
308template <
unsigned Bits,
class RowFn,
class Flu
idFn>
312 const Index n =
t.numLeaves();
313 std::array<std::vector<std::vector<detail::ScalarEnt>>, 3>
per;
314 for (
int a = 0;
a < 3; ++
a)
315 per[
static_cast<std::size_t
>(
a)].resize(
static_cast<std::size_t
>(n));
320 const unsigned Li =
t.level(
i);
324 double sdist[3][2] = {};
329 const int s = (dir > 0) ? 0 : 1;
332 if (
t.level(
j) !=
Li)
335 for (
int a = 0;
a < 3; ++
a) {
336 if (!
cf[
a][0] && !
cf[
a][1])
338 if (
cnt[
a][0] == 0 ||
cnt[
a][1] == 0)
342 auto&
row =
per[
static_cast<std::size_t
>(
a)][
static_cast<std::size_t
>(
i)];
344 if (axis !=
a || alpha <= 1
e-12)
346 const int s = (dir > 0) ? 0 : 1;
347 const double w = (
s == 0) ?
wp :
wm;
348 const double inv = 1.0 /
static_cast<double>(
cnt[
a][
s]);
349 const double gsgn = (dir > 0) ? 1.0 : -1.0;
351 const double rw = (w - 0.5) *
inv *
gsgn / dist;
357 const unsigned Lj =
t.level(
j);
369 std::array<CfCsr, 3>
out;
370 for (
int a = 0;
a < 3; ++
a)
391template <
unsigned Bits,
class Flu
idFn>
394 const Index n =
t.numLeaves();
405 const unsigned Li =
t.level(
i);
407 d.
vel.
start[
static_cast<std::size_t
>(slot) + 1] = d.
vel.
start[
static_cast<std::size_t
>(slot)];
408 d.
phi.
start[
static_cast<std::size_t
>(slot) + 1] = d.
phi.
start[
static_cast<std::size_t
>(slot)];
409 const unsigned Lj =
t.level(
j);
414 const double wF = (0.5 *
H) / dist,
wC = (0.5 *
h) / dist;
415 std::vector<detail::CompEnt>
ve;
426 for (
const auto&
e :
ve) {
430 ++d.
vel.
start[
static_cast<std::size_t
>(slot) + 1];
434 std::vector<detail::ScalarEnt>
pe;
436 for (
const auto&
e :
pe) {
439 ++d.
phi.
start[
static_cast<std::size_t
>(slot) + 1];
452 const Index n =
static_cast<Index>(
c.start.size()) - 1;
455 for (
Index k =
c.start[
static_cast<std::size_t
>(
i)]; k <
c.start[
static_cast<std::size_t
>(
i) + 1];
457 acc +=
c.coef[
static_cast<std::size_t
>(k)] *
f[
static_cast<std::size_t
>(
c.slot[
static_cast<std::size_t
>(k)])];
458 out[
static_cast<std::size_t
>(
i)] +=
acc;
464 std::vector<double>&
out) {
465 const Index n =
static_cast<Index>(
c.start.size()) - 1;
468 for (
Index k =
c.start[
static_cast<std::size_t
>(
i)]; k <
c.start[
static_cast<std::size_t
>(
i) + 1];
470 acc +=
c.coef[
static_cast<std::size_t
>(k)] *
471 u[
static_cast<std::size_t
>(
c.comp[
static_cast<std::size_t
>(k)])]
472 [
static_cast<std::size_t
>(
c.slot[
static_cast<std::size_t
>(k)])];
473 out[
static_cast<std::size_t
>(
i)] +=
acc;
478#ifdef KOKKOS_INLINE_FUNCTION
495 d.
n =
static_cast<Index>(
h.start.size()) - 1;
496 d.
nz =
static_cast<Index>(
h.slot.size());
508 d.
n =
static_cast<Index>(
h.start.size()) - 1;
509 d.
nz =
static_cast<Index>(
h.slot.size());
528 Kokkos::parallel_for(
546 Kokkos::parallel_for(
551 const double v = (
a == 0) ?
u0(
sl(k)) : (
a == 1) ?
u1(
sl(k)) :
u2(
sl(k));
Cell-centered FV Poisson operator on one (periodic) block octree.
void forEachFaceNeighbor(Index i, Fn &&fn) const
Visit each face neighbour of leaf i: fn(neighbourSlot, coeff, axis, alpha) where coeff = A_f / d_f (p...
Real cellWidth(Index i) const
double faceOpenness(Index i, int axis, int dir) const
Openness of leaf i's face on (axis,dir); 1 if no openness has been set.
Index periodicNeighbor(Index i, int axis, int dir) const
Periodic face neighbour leaf (covering the cell just across the face).
void forEachFaceFull(Index i, Fn &&fn) const
Like forEachFaceNeighbor but exposes geometry for a consistent FV divergence/gradient: fn(neighbour,...
Real cellVolume(Index i) const
Per-block adaptive octree over block-local Morton codes.
typename M::coord_type Coord
void compactCsr(const std::vector< std::vector< Ent > > &per, Csr &out, Index n)
void cfAppendStencil(const AmrPoisson< 3, Bits > &ap, const BlockOctree< 3, Bits > &t, std::vector< Ent > &out, Index coarse, Index fine, int axis, double scale, FluidFn &&fluidOk, CfScheme scheme, const Ent &proto=Ent{})
Append the scheme's (coarse* − coarse_raw) substitution stencil for ONE directed C/F sub-face to out,...
void cfApplyCompHost(const CfCompCsr &c, const std::array< std::vector< double >, 3 > &u, std::vector< double > &out)
out(i) += Σ coef·u[comp](slot) (the divergence overlay).
CfUfDelta buildCfUfDelta(const AmrPoisson< 3, Bits > &ap, const BlockOctree< 3, Bits > &t, FluidFn &&fluidOk, CfScheme scheme)
void cfApply(const CfCsrDev &c, View< const double > f, View< double > out)
out(i) += Σ coef·f(slot).
CfScheme
Coarse/fine interface scheme for the collocated flow operators.
@ standard
raw coarse value (two-point flux; 1st-order at 2:1 faces)
@ quadratic
Martin–Cartwright tangential quadratic (2nd-order at 2:1 faces)
CfCompCsrDev uploadCfCompCsr(const CfCompCsr &h, const char *name)
std::vector< std::array< double, Dim > > transferFieldGradients(const BlockOctree< Dim, Bits > &oldT, const std::vector< double > &oldF)
Per-old-leaf minmod prolongation gradients (per fine-coordinate unit) — transferField's stencil,...
std::array< CfCsr, 3 > buildCfGradDelta(const AmrPoisson< 3, Bits > &ap, const BlockOctree< 3, Bits > &t, RowFn &&rowOk, FluidFn &&fluidOk, CfScheme scheme)
(G_scheme − G_std) for the ABC cell gradient gradOf/grad3.
void cfApplyHost(const CfCsr &c, const std::vector< double > &f, std::vector< double > &out)
out(i) += Σ coef·f(slot) (the scalar overlay: momentum ∇² delta, gradient delta per axis).
CfCsr buildCfLapDelta(const AmrPoisson< 3, Bits > &ap, const BlockOctree< 3, Bits > &t, double factor, RowFn &&rowOk, FluidFn &&fluidOk, CfScheme scheme)
(∇²_scheme − ∇²_std) as a scalar CSR, ×factor (pass μ for the momentum deferred-correction RHS,...
CfCompCsr buildCfDivDelta(const AmrPoisson< 3, Bits > &ap, const BlockOctree< 3, Bits > &t, RowFn &&rowOk, FluidFn &&fluidOk, CfScheme scheme)
(D_scheme − D_std) for the face-average divergence div_i = invV·Σ α·A·dir·(face value).
void cfApplyComp(const CfCompCsrDev &c, View< const double > u0, View< const double > u1, View< const double > u2, View< double > out)
out(i) += Σ coef·u[comp](slot).
CfCsrDev uploadCfCsr(const CfCsr &h, const char *name)
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).
Kokkos::View< T *, MemSpace > View
1D device array.
double Real
Default host floating type. Device kernels may use float; conversions happen at the boundary.
std::int64_t Index
Signed index type for grids and particles (supersedes block_decomposer's long int IndxT).
Component-tagged CSR overlay (the divergence delta): out(i) += Σ_k coef·u[comp](slot).
std::vector< double > coef
std::vector< Index > slot
std::vector< Index > start
std::vector< int8_t > comp
Device mirror of a CfCsr (empty when the scheme is standard / no C/F rows).
Scalar-input CSR overlay: out(i) += Σ_k coef·f(slot) over rows with C/F faces.
std::vector< Index > start
size n+1
std::vector< double > coef
std::vector< Index > slot
(uf_scheme − uf_std) for the div-free FACE field uf_k = ½(u_i+u_j) − (φ₊−φ₋)/d, one delta row per for...
CfCsr phi
reads the projection potential φ, rows = face slots
CfCompCsr vel
reads the velocity components, rows = face slots
An assembled face-CSR: row offsets (size n+1), neighbour index + coefficient per face (size nFaces).