31#ifndef PECLET_PNM_PORE_KERNELS_HPP
32#define PECLET_PNM_PORE_KERNELS_HPP
38#include <Kokkos_Core.hpp>
51using Exec = Kokkos::DefaultExecutionSpace;
52using Mem = Exec::memory_space;
59inline void uploadVec(
const std::vector<T>& h,
const Kokkos::View<T*, Mem>& d) {
63 d, Kokkos::View<
const T*, Kokkos::HostSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>(
70inline std::vector<typename V::value_type>
downloadN(
const V& d, std::size_t count) {
71 std::vector<typename V::value_type> out(count);
73 Kokkos::deep_copy(Kokkos::View<
typename V::value_type*, Kokkos::HostSpace,
74 Kokkos::MemoryTraits<Kokkos::Unmanaged>>(out.data(), count),
75 Kokkos::subview(d, Kokkos::make_pair(std::size_t(0), count)));
82 auto h = Kokkos::create_mirror_view(d);
83 Kokkos::deep_copy(h, d);
87KOKKOS_INLINE_FUNCTION
int get_idx(
int x,
int y,
int z,
I3 res) {
88 x = (x % res.x + res.x) % res.x;
89 y = (y % res.y + res.y) % res.y;
90 z = (z % res.z + res.z) % res.z;
91 return z * res.y * res.x + y * res.x + x;
94KOKKOS_INLINE_FUNCTION
int wrapc(
int a,
int n) {
96 return r < 0 ? r + n : r;
106 KOKKOS_INLINE_FUNCTION
Index cell(
int lx,
int ly,
int lz)
const {
109 KOKKOS_INLINE_FUNCTION
Index gid(
int lx,
int ly,
int lz)
const {
return cell(lx, ly, lz); }
110 KOKKOS_INLINE_FUNCTION
void gcoord(
int lx,
int ly,
int lz,
int& gx,
int& gy,
int& gz)
const {
115 KOKKOS_INLINE_FUNCTION
bool inOwned(
int,
int,
int)
const {
return true; }
116 KOKKOS_INLINE_FUNCTION
Index owned(
int ix,
int iy,
int iz)
const {
return cell(ix, iy, iz); }
119 iy = int((o /
nx) %
ny);
124 return cell(gx, gy, gz);
139 KOKKOS_INLINE_FUNCTION
Index lidx(
int lx,
int ly,
int lz)
const {
142 KOKKOS_INLINE_FUNCTION
Index cell(
int lx,
int ly,
int lz)
const {
return lidx(lx, ly, lz); }
144 KOKKOS_INLINE_FUNCTION
Index gidAt(
int lx,
int ly,
int lz)
const {
148 KOKKOS_INLINE_FUNCTION
Index gid(
int lx,
int ly,
int lz)
const {
return gidAt(lx, ly, lz); }
149 KOKKOS_INLINE_FUNCTION
void gcoord(
int lx,
int ly,
int lz,
int& gx,
int& gy,
int& gz)
const {
154 KOKKOS_INLINE_FUNCTION
bool inOwned(
int ix,
int iy,
int iz)
const {
155 return ix >= 0 && ix < nx && iy >= 0 && iy < ny && iz >= 0 && iz <
nz;
157 KOKKOS_INLINE_FUNCTION
Index owned(
int ix,
int iy,
int iz)
const {
162 iy = int((o /
nx) %
ny);
169 const int gx = int(
gid %
gnx);
171 const int gy = int(t %
gny), gz = int(t /
gny);
181 return lidx(lx, ly, lz);
187 KOKKOS_INLINE_FUNCTION
bool onSurface(
int ix,
int iy,
int iz)
const {
188 return !(ix > 0 && ix <
nx - 1 && iy > 0 && iy <
ny - 1 && iz > 0 && iz <
nz - 1);
196using MD3 = Kokkos::MDRangePolicy<Exec, Kokkos::Rank<3>>;
197using R1 = Kokkos::RangePolicy<Exec>;
213template <
class Geo,
class SdfView>
216 for (
int dz = -1;
dz <= 1; ++
dz)
217 for (
int dy = -1;
dy <= 1; ++
dy)
218 for (
int dx = -1; dx <= 1; ++dx) {
219 if (dx == 0 &&
dy == 0 &&
dz == 0)
221 const float nv = sdf(g.cell(
lx + dx,
ly +
dy,
lz +
dz));
231template <
class Geo,
class SdfView>
233 float ox,
float oy,
float oz,
float sx,
float sy,
float sz) {
234 float sw = 0.0f,
px = 0.0f,
py = 0.0f,
pz = 0.0f;
235 for (
int dz = -1;
dz <= 1; ++
dz)
236 for (
int dy = -1;
dy <= 1; ++
dy)
237 for (
int dx = -1; dx <= 1; ++dx) {
238 const float v = sdf(g.cell(
lx + dx,
ly +
dy,
lz +
dz));
239 float w = v > 0.0f ? v : 0.0f;
246 float fx = 0,
fy = 0,
fz = 0;
261template <
class Geo,
class SdfView>
266 for (
int dz = -1;
dz <= 1; ++
dz)
267 for (
int dy = -1;
dy <= 1; ++
dy)
268 for (
int dx = -1; dx <= 1; ++dx) {
269 if (dx == 0 &&
dy == 0 &&
dz == 0)
272 const float nv = sdf(g.cell(
lx + dx,
ly +
dy,
lz +
dz));
291template <
class Geo,
class FieldView>
295 for (
int a = 0;
a < 3; ++
a) {
296 const double fl = Kokkos::floor(
gp[
a]);
297 b[
a] =
static_cast<int>(
fl);
301 for (
int dz = 0;
dz < 2; ++
dz)
302 for (
int dy = 0;
dy < 2; ++
dy)
303 for (
int dx = 0; dx < 2; ++dx) {
305 (dx ?
f[0] : 1.0 -
f[0]) * (
dy ?
f[1] : 1.0 -
f[1]) * (
dz ?
f[2] : 1.0 -
f[2]);
306 acc +=
wt * p(g.cellAtGlobal(
b[0] + dx,
b[1] +
dy,
b[2] +
dz));
316 const int Dx = 2 * dx + (
d2 == 0) - (d == 0);
317 const int Dy = 2 *
dy + (
d2 == 1) - (d == 1);
318 const int Dz = 2 *
dz + (
d2 == 2) - (d == 2);
323template <
class KeyView>
325 typename KeyView::non_const_value_type
key) {
329 const auto k = keys(
mid);
352 return d == 0 ?
v0(
e) : (d == 1 ?
v1(
e) :
v2(
e));
362template <
class Geo,
class SdfView,
class PoreView,
class CountView>
364 std::array<float, 3> origin, std::array<float, 3> spacing,
367 const float ox = origin[0], oy = origin[1], oz = origin[2];
368 const float sx = spacing[0],
sy = spacing[1],
sz = spacing[2];
369 Kokkos::parallel_for(
372 const float cv = sdf(g.cell(
lx,
ly,
lz));
377 const int slot = Kokkos::atomic_fetch_add(&
counter(), 1);
379 pores(
slot) =
poreAt(g, sdf,
lx,
ly,
lz, ox, oy, oz,
sx,
sy,
sz);
389template <
class Geo,
class SdfView,
class ParentView>
392 using L =
typename ParentView::non_const_value_type;
394 Kokkos::parallel_for(
403template <
class ParentView>
405 using L =
typename ParentView::non_const_value_type;
406 Kokkos::parallel_for(
421template <
class Geo,
class ParentView,
class FlagView>
424 using L =
typename ParentView::non_const_value_type;
426 Kokkos::parallel_for(
432 const int dz_l[13] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0};
433 const int dy_l[13] = {-1, -1, -1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0};
434 const int dx_l[13] = {-1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, 1};
435 for (
int k = 0;
k < 13; ++
k) {
437 if (!g.inOwned(
jx,
jy,
jz))
440 if (
nl != -1 &&
my !=
nl) {
460template <
class ParentView,
class FlagView,
class MergeFn>
475template <
class Geo,
class SdfView,
class LabelView,
class FlagView>
478 using L =
typename LabelView::non_const_value_type;
480 Kokkos::parallel_for(
489 for (
int dz = -1;
dz <= 1; ++
dz)
490 for (
int dy = -1;
dy <= 1; ++
dy)
491 for (
int dx = -1; dx <= 1; ++dx) {
492 if (dx == 0 &&
dy == 0 &&
dz == 0)
512template <
class Geo,
class SdfView,
class LabelView,
class FlagView,
class SyncFn>
534template <
class SdfView,
class EmitFn>
538 Kokkos::parallel_for(
561template <
class Geo,
class SdfView,
class TargetView,
class ChaseFn,
class FinalFn,
class PeakFn>
566 Kokkos::parallel_for(
585template <
class Geo,
class TargetView>
589 Kokkos::parallel_reduce(
590 "pnm::resolve_roots",
R1(
space, 0, g.numOwned()),
598 for (
int s = 0; s < 64; ++s) {
629template <
class Geo,
class SegView,
class PairView,
class CountView>
633 Kokkos::parallel_for(
636 const int my = seg(g.cell(
lx,
ly,
lz));
637 const int dx_l[3] = {1, 0, 0},
dy_l[3] = {0, 1, 0},
dz_l[3] = {0, 0, 1};
638 for (
int k = 0;
k < 3; ++
k) {
641 const int slot = Kokkos::atomic_fetch_add(&
cnt(), 1);
653template <
class PairView>
657 for (std::size_t
i = 0;
i <
count; ++
i)
665template <
class Geo,
class SegView>
669 Kokkos::parallel_reduce(
670 "pnm::max_label",
R1(
space, 0, g.numOwned()),
674 const int sv = seg(g.cell(
ix + g.g,
iy + g.g,
iz + g.g));
678 Kokkos::Max<int>(
np));
692template <
class Geo,
class LabView,
class SdfView,
class OpenView,
class CoreView,
class ParentView,
697 using L =
typename ParentView::non_const_value_type;
700 Kokkos::parallel_for(
706 for (
int d = 0; d < 3; ++d) {
707 const Index f = 3 * o + d;
708 const Index nb = g.cell(
lx + (d == 0),
ly + (d == 1),
lz + (d == 2));
710 const double opn =
ho ? (d == 0 ? ox(
nb) : (d == 1 ? oy(
nb) : oz(
nb))) : 1.0;
711 const bool itf = (
a !=
b &&
a > 0 &&
b > 0 &&
opn > 0.0);
712 core(
f) = (
itf && sdf(
ce) > 0.0f && sdf(
nb) > 0.0f) ? 1 : 0;
722template <
class Geo,
class ParentView,
class PairView,
class FlagView>
725 using L =
typename ParentView::non_const_value_type;
727 Kokkos::parallel_for(
730 for (
int d = 0; d < 3; ++d) {
731 const Index f = 3 * o + d;
735 for (
int dz = -1;
dz <= 1; ++
dz)
736 for (
int dy = -1;
dy <= 1; ++
dy)
737 for (
int dx = -1; dx <= 1; ++dx) {
739 if (!g.inOwned(
jx,
jy,
jz))
742 for (
int d2 = 0;
d2 < 3; ++
d2) {
768template <
class Geo,
class ParentView,
class MinView>
772 Kokkos::parallel_for(
775 const Index gid = g.gid(
ix + g.g,
iy + g.g,
iz + g.g);
776 for (
int d = 0; d < 3; ++d)
777 if (
parent(3 * o + d) >= 0)
778 Kokkos::atomic_min(&
mg(
parent(3 * o + d)), 3 * gid + d);
786template <
class ParentView,
class PairView,
class LabView,
class RootFn>
789 Kokkos::parallel_for(
797template <
class ParentView,
class LabView,
class RootFn>
800 Kokkos::parallel_for(
809template <
class ParentView,
class LabView>
812 using L =
typename ParentView::non_const_value_type;
813 Kokkos::parallel_for(
823template <
class Geo,
class LabView,
class PairView,
class CoreView,
class NbLab,
class NbPair,
829 Kokkos::parallel_for(
832 for (
int d = 0; d < 3; ++d) {
833 const Index f = 3 * o + d;
838 for (
int dz = -1;
dz <= 1; ++
dz)
839 for (
int dy = -1;
dy <= 1; ++
dy)
840 for (
int dx = -1; dx <= 1; ++dx) {
842 for (
int d2 = 0;
d2 < 3; ++
d2) {
871 [](
const std::pair<Index, Index>& x,
const std::pair<Index, Index>& y) {
872 return x.second != y.second ? x.second < y.second : x.first < y.first;
875 std::vector<Index>
rootF;
877 ts.throats.push_back({
int(
rp.second >> 32),
int(
rp.second & 0x7fffffff)});
881 std::sort(
ts.keySorted.begin(),
ts.keySorted.end());
882 ts.slotOf.resize(
rootF.size());
883 for (std::size_t
t = 0;
t <
rootF.size(); ++
t) {
884 const auto it = std::lower_bound(
ts.keySorted.begin(),
ts.keySorted.end(),
rootF[
t]);
885 ts.slotOf[std::size_t(
it -
ts.keySorted.begin())] =
int(
t);
895template <
class Geo,
class LabView,
class FieldView,
class OpenView,
class FaceLabView,
896 class KeyView,
class SlotView,
class AncView,
class AccView>
903 std::array<float, 3> spacing, std::array<int, 3>
gdims,
const AccView& Q,
907 const double Ax =
double(spacing[1]) * spacing[2],
Ay =
double(spacing[0]) * spacing[2],
908 Az =
double(spacing[0]) * spacing[1];
909 const std::int64_t
ntl =
static_cast<std::int64_t
>(
nt);
911 const float oxo = origin[0],
oyo = origin[1],
ozo = origin[2];
912 const float sx = spacing[0],
sy = spacing[1],
sz = spacing[2];
914 Kokkos::parallel_for(
919 for (
int d = 0; d < 3; ++d) {
920 const Index nb = g.cell(
lx + (d == 0),
ly + (d == 1),
lz + (d == 2));
925 const double vel = d == 0 ? u(
nb) : (d == 1 ? v(
nb) : w(
nb));
926 const double opn =
ho ? (d == 0 ? ox(
nb) : (d == 1 ? oy(
nb) : oz(
nb))) : 1.0;
927 const double area = d == 0 ?
Ax : (d == 1 ?
Ay :
Az);
930 Kokkos::atomic_add(&
resid(
a - 1),
q);
932 Kokkos::atomic_add(&
resid(
b - 1), -
q);
937 const int lo =
a <
b ?
a :
b;
940 Kokkos::atomic_add(&Q(
slot),
a <
b ?
q : -
q);
941 Kokkos::atomic_add(&A(
slot),
w0);
950 for (
int a2 = 0;
a2 < 3; ++
a2) {
971 const std::vector<std::pair<int, int>>& throats,
const std::vector<Pore>& pores,
973 const std::vector<double>&
Cx,
const std::vector<double>&
Cy,
const std::vector<double>&
Cz,
974 const std::vector<double>&
ancX,
const std::vector<double>&
ancY,
975 const std::vector<double>&
ancZ, std::array<float, 3> spacing, std::array<int, 3>
gdims,
976 std::array<double, 3>
grad_p) {
977 const std::size_t
nt = throats.size();
978 std::vector<double> dp(
nt);
981 for (std::size_t
t = 0;
t <
nt; ++
t) {
982 const int li = throats[
t].first,
lj = throats[
t].second;
991 for (
int a = 0;
a < 3; ++
a) {
992 const double ct = (
Cx[
t] * (
a == 0) +
Cy[
t] * (
a == 1) +
Cz[
t] * (
a == 2)) /
aw;
void forestInit(const Exec &space, const Geo &geo, const SdfView &sdf, const TargetView &target, const ChaseFn &chase, const FinalFn &finalOf, const PeakFn &peakOf)
Steepest-neighbour forest for the hold-at-ghost root resolution.
Kokkos::RangePolicy< Exec > R1
void floodSweep(const Exec &space, const Geo &geo, const SdfView &sdf, const LabelView &labels, const LabelView &labelsN, const FlagView &changed)
One Jacobi flood sweep: every unlabelled solid voxel takes the smallest labelled 26-neighbour (reads ...
Index steepest(const Geo &g, const SdfView &sdf, int lx, int ly, int lz, Index cgid, bool ascent)
Steepest 26-neighbour under the (sdf, gid) lexicographic order: ascent (pores) or descent (solids); r...
void boundaryPairs(const Exec &space, const Geo &geo, const SegView &seg, const PairView &pairs, const CountView &cnt, Index maxPairs)
Boundary pairs: for every owned cell, the (min,max) label pairs across its +x/+y/+z faces where the l...
void leftoverInit(const Exec &space, std::size_t nf, const LabView &faceLab, const ParentView &parent)
Leftover tier init: parent = f for the films no core patch reached, -1 otherwise.
void faceLabelLeftover(const Exec &space, std::size_t nf, const ParentView &parent, const LabView &faceLab, const RootFn &rootOf)
Leftover-tier labels: the still-kSent films (their own CCL tier) get rootOf(parent).
MD3 ownedRange(const Exec &space, const Geo &geo)
The owned box of a geometry as an MDRange policy.
bool isPeak(const Geo &g, const SdfView &sdf, int lx, int ly, int lz, float cv, Index cgid)
Local SDF maximum under the global (sdf, gid) lexicographic order (26-neighbourhood).
void faceMerge(const Exec &space, const Geo &geo, const ParentView &parent, const PairView &fpair, const FlagView &changed)
One union sweep of the face CCL over the faces with parent >= 0 (same pair key + adjacency; owned-own...
void faceLabelCore(const Exec &space, std::size_t nf, const ParentView &parent, const PairView &fpair, const LabView &faceLab, const RootFn &rootOf)
Core-tier labels: faceLab = rootOf(parent) for the CCL'd faces, kSent for the remaining interface (fi...
Index bsearchKey(const KeyView &keys, Index nkeys, typename KeyView::non_const_value_type key)
Device binary search over a sorted key view; returns the position or -1.
void cclFixpoint(const Exec &space, const ParentView &parent, std::size_t n, const FlagView &changed, const MergeFn &merge)
Union-find to fixpoint: merge() launches one union sweep (setting changed), then a flatten; repeat un...
ThroatSlots throatSlots(std::vector< std::pair< Index, Index > > rootPair)
int maxLabel(const Exec &space, const Geo &geo, const SegView &seg)
The largest label over the owned box (= the number of pore labels).
void faceMinGid(const Exec &space, const Geo &geo, const ParentView &parent, const MinView &mg)
Per-component minimum GLOBAL face id (3*gid+d) of the local face CCL, keyed by the component root: th...
Kokkos::MDRangePolicy< Exec, Kokkos::Rank< 3 > > MD3
void filmAttachSweep(const Exec &space, const Geo &geo, const LabView &faceLab, const PairView &fpair, const CoreView &core, const NbLab &nbLab, const NbPair &nbPair, const FlagView &changed)
One Jacobi min-propagation sweep of the film attachment: every film face (interface,...
void faceInit(const Exec &space, const Geo &geo, const LabView &flowLab, const SdfView &sdf, const OpenView &ox, const OpenView &oy, const OpenView &oz, bool hasOpen, const CoreView &core, const ParentView &parent, const PairView &fpair)
Interface predicate + CORE tier per owned face: an interface face separates two different positive fl...
constexpr Index kSent
Film-face sentinel of the per-patch throat labelling: "interface face awaiting attachment".
void detectPores(const Exec &space, const Geo &geo, const SdfView &sdf, std::array< float, 3 > origin, std::array< float, 3 > spacing, const PoreView &pores, const CountView &counter, int maxPores)
Emit the owned peaks (local SDF maxima, sdf > 0) as Pore records into pores (atomic slot counter coun...
double trilinear(const Geo &g, const FieldView &p, const double gp[3])
Trilinear interpolation of a cell-centered periodic field at grid position gp (in cells).
void floodFixpoint(const Exec &space, const Geo &geo, const SdfView &sdf, LabelView &labels, LabelView &labelsN, const FlagView &changed, const SyncFn &sync)
Jacobi flood to fixpoint.
Pore poreAt(const Geo &g, const SdfView &sdf, int lx, int ly, int lz, float ox, float oy, float oz, float sx, float sy, float sz)
The pore record at a peak: sub-voxel position by the SDF^2-weighted centroid of the 3^3 neighbourhood...
void throatFlux(const Exec &space, const Geo &geo, const LabView &flowLab, const FieldView &u, const FieldView &v, const FieldView &w, const OpenView &ox, const OpenView &oy, const OpenView &oz, bool hasOpen, const FaceLabView &faceLab, const KeyView &keyD, const SlotView &slotD, std::size_t nt, const AncView &ancX, const AncView &ancY, const AncView &ancZ, std::array< float, 3 > origin, std::array< float, 3 > spacing, std::array< int, 3 > gdims, const AccView &Q, const AccView &A, const AccView &Cx, const AccView &Cy, const AccView &Cz, const AccView &resid)
Accumulate over every owned +face where the flow-basin label changes: the openness-weighted MAC flux ...
void gradientWalk(const Exec &space, const GridGeo &geo, const SdfView &sdf, bool ascentAll, const EmitFn &emit)
Single-rank gradient walk: from every owned cell follow the steepest neighbour (ascent for pores,...
std::vector< std::pair< int, int > > uniquePairs(const PairView &pairs, std::size_t count)
Interleaved device pairs -> host (l1,l2) list, sorted and unique.
bool facesAdjacent(int dx, int dy, int dz, int d, int d2)
Face adjacency of the per-patch throat CCL: two faces (cell offset (dx,dy,dz), directions d and d2) c...
void cclFlatten(const Exec &space, const ParentView &parent, std::size_t n)
Path compression: every labelled entry points at its root.
void initMarkers(const Exec &space, const Geo &geo, const SdfView &sdf, float thr, const ParentView &parent)
Deep-solid markers: parent(o) = o where sdf < thr, else -1 (owned-dense).
void cclMergeMarkers(const Exec &space, const Geo &geo, const ParentView &parent, const FlagView &changed)
One union sweep of the marker CCL (26-connectivity, 13 forward neighbours, union-by-min via atomic_mi...
int resolveHoldAtGhost(const Exec &space, const Geo &geo, const TargetView &target)
One round of pointer jumping with the hold-at-ghost invariant: chase within the field,...
std::vector< double > throatPressureDrops(const std::vector< std::pair< int, int > > &throats, const std::vector< Pore > &pores, const std::vector< double > &porePressure, const std::vector< double > &throatArea, const std::vector< double > &Cx, const std::vector< double > &Cy, const std::vector< double > &Cz, const std::vector< double > &ancX, const std::vector< double > &ancY, const std::vector< double > &ancZ, std::array< float, 3 > spacing, std::array< int, 3 > gdims, std::array< double, 3 > grad_p)
Total-pressure drop per throat: periodic parts + the macroscopic gradient along the throat- anchored ...
std::int64_t Index
Global voxel / face id (== peclet::core::Index; asserted where core is included).
int get_idx(int x, int y, int z, I3 res)
V::value_type readScalar(const V &d)
Read a device scalar (the changed / counter flags) back to the host.
void uploadVec(const std::vector< T > &h, const Kokkos::View< T *, Mem > &d)
Bulk host->device upload of a whole std::vector via one deep_copy over an unmanaged host view.
std::vector< typename V::value_type > downloadN(const V &d, std::size_t count)
Download the first count elements of a device view into a fresh std::vector via one deep_copy — only ...
Kokkos::DefaultExecutionSpace Exec
Extended-block geometry policy (the MPI pipeline): ghost-inclusive local box <-> global periodic grid...
Index cellAtGlobal(int gx, int gy, int gz) const
bool inOwned(int ix, int iy, int iz) const
std::size_t numExt() const
Index localOf(Index gid) const
gid -> extended-local linear index if the cell has an image in this extended box, else -1.
Index cell(int lx, int ly, int lz) const
bool onSurface(int ix, int iy, int iz) const
Is the owned cell within one cell of a block face (the only cells that can see a ghost)?
Index gid(int lx, int ly, int lz) const
void ownedCoords(Index o, int &ix, int &iy, int &iz) const
Index owned(int ix, int iy, int iz) const
static int wrapc(int a, int n)
void gcoord(int lx, int ly, int lz, int &gx, int &gy, int &gz) const
Index lidx(int lx, int ly, int lz) const
std::size_t numOwned() const
Index gidAt(int lx, int ly, int lz) const
gid of the (periodically wrapped) global cell under extended-local coords.
Single-rank geometry policy: the field IS the whole periodic grid, owned == field coords,...
Index cellAtGlobal(int gx, int gy, int gz) const
void ownedCoords(Index o, int &ix, int &iy, int &iz) const
bool inOwned(int, int, int) const
Index gid(int lx, int ly, int lz) const
Index owned(int ix, int iy, int iz) const
Index localOf(Index gid) const
Index cell(int lx, int ly, int lz) const
void gcoord(int lx, int ly, int lz, int &gx, int &gy, int &gz) const
std::size_t numOwned() const
static GridGeo of(I3 res)
Per-face field accessors for the film-attachment sweep: label / pair key of face (cell e,...
Index operator()(Index e, int d) const
Index operator()(Index e, int d) const
Global unique (patch root, pair key) list -> the throat list ordered by (pair, root fid),...
std::vector< Index > keySorted
std::vector< int > slotOf
std::vector< std::pair< int, int > > throats