core
Shared MPI block decomposition + asynchronous ghost-layer exchange (header-only C++20)
Loading...
Searching...
No Matches
face_csr.hpp
Go to the documentation of this file.
1// core — shared, backend-agnostic kernels for an assembled face-CSR operator.
2//
3// The "host" serial reference solver (peclet::core::amr::AmrCutCell / oracle::AmrFlow, pure C++20)
4// and the "device" Kokkos solver (peclet::core::amr::MomentumOp + momentum.hpp) used to carry two
5// independent encodings of the SAME per-cell arithmetic — a real drift risk. This header is the
6// single source of that arithmetic: the assembled operator
7//
8// (A u)_i = diag_i · u_i + Σ_{k ∈ [start_i, start_{i+1})} coef_k · u[nbr_k]
9// ( + optional implicit-FOU advection over a second CSR )
10//
11// expressed once as MORTON_HD row kernels over a *templated accessor*, so the SAME body serves
12// - the host: a plain serial loop, arrays = raw pointers (no Kokkos dependency — MORTON_HD is
13// empty
14// in a non-Kokkos, non-CUDA build, so these compile as ordinary inline functions); and
15// - the device: inside Kokkos::parallel_for, arrays = Kokkos::View.
16//
17// Mesh-agnostic: it names no octree types and assumes nothing beyond the CSR, so it is equally the
18// kernel layer for a future Voronoi-cell (unstructured polyhedral) operator.
19#ifndef PECLET_CORE_AMR_FACE_CSR_HPP
20#define PECLET_CORE_AMR_FACE_CSR_HPP
21
23
24// MORTON_HD: KOKKOS_FUNCTION under a Kokkos build, __host__ __device__ under nvcc, empty otherwise
25// — so the row kernels are device-callable when compiled for the device and ordinary host functions
26// in the pure-C++ build. morton.hpp defines it for all three cases; when the (optional) morton
27// checkout is absent the operator is host-only, so an empty fallback is exactly right.
28#if defined(PECLET_CORE_HAVE_MORTON)
29#include <morton/morton.hpp>
30#endif
31#ifndef MORTON_HD
32#define MORTON_HD
33#endif
34
35namespace peclet::core::amr {
36
39template <class T>
40struct HostArr {
41 const T* p = nullptr;
42 HostArr() = default;
43 explicit HostArr(const T* ptr) : p(ptr) {}
44 MORTON_HD T operator()(Index i) const { return p[i]; }
45};
46
50template <class D, class I>
59
61template <class Op, class U>
62MORTON_HD inline double faceCsrApplyRow(const Op& op, Index i, const U& u) {
63 double acc = op.diag(i) * u(i);
64 for (Index k = op.start(i); k < op.start(i + 1); ++k)
65 acc += op.coef(k) * u(op.nbr(k));
66 if (op.hasAdv) {
67 acc += op.advDiag(i) * u(i);
68 for (Index k = op.advStart(i); k < op.advStart(i + 1); ++k)
69 acc += op.advCoef(k) * u(op.advNbr(k));
70 }
71 return acc;
72}
73
77template <class Op, class U>
78MORTON_HD inline void faceCsrOffDiag(const Op& op, Index i, const U& u, double& off, double& d) {
79 off = 0.0;
80 d = op.diag(i);
81 for (Index k = op.start(i); k < op.start(i + 1); ++k)
82 off += op.coef(k) * u(op.nbr(k));
83 if (op.hasAdv) {
84 for (Index k = op.advStart(i); k < op.advStart(i + 1); ++k)
85 off += op.advCoef(k) * u(op.advNbr(k));
86 d += op.advDiag(i);
87 }
88}
89
93MORTON_HD inline double faceCsrPointUpdate(double b_i, double off, double d, double uOld,
94 double omega) {
95 const double nu = (d != 0.0) ? (b_i - off) / d : uOld;
96 return (1.0 - omega) * uOld + omega * nu;
97}
98
99// ---------------------------------------------------------------------------
100// The conservative FV (graded-Laplacian) operator — the *pressure* form. Unlike the general
101// momentum operator above it stores per-face conductances `w` and a per-cell `invVol`, with the
102// diagonal *derived* (the symmetric Laplacian Σ w·(u_nbr − u_i)); a Helmholtz generalisation
103// H u = c0·u + cD·( invVol·( Σ w·(u_nbr − u_i) − bcDiag·u ) )
104// (c0=0, cD=1 ⇒ the pure FV Laplacian L) keeps the L path bit-exact. Same body for host
105// (AmrPoisson) and device (poisson.hpp FvOp).
106// ---------------------------------------------------------------------------
107
109template <class D, class I>
110struct FvCsrOpT {
111 Index n = 0;
112 D invVol, coef; // coef = per-face conductance w = openness·A_f/d_f
114 D bcDiag; // homogeneous-Dirichlet boundary diagonal (0 when periodic)
115 double c0 = 0.0, cD = 1.0;
116};
117
119template <class Op, class U>
120MORTON_HD inline double fvApplyRow(const Op& op, Index i, const U& u) {
121 const double ui = u(i);
122 double acc = 0.0;
123 for (Index k = op.start(i); k < op.start(i + 1); ++k)
124 acc += op.coef(k) * (u(op.nbr(k)) - ui);
125 return op.c0 * ui + op.cD * (op.invVol(i) * (acc - op.bcDiag(i) * ui));
126}
127
130template <class Op, class U>
131MORTON_HD inline double fvPointSolve(const Op& op, Index i, const U& u, double rhs_i, double uOld) {
132 double sumOff = 0.0, sw = 0.0;
133 for (Index k = op.start(i); k < op.start(i + 1); ++k) {
134 sumOff += op.coef(k) * u(op.nbr(k));
135 sw += op.coef(k);
136 }
137 const double swbc = sw + op.bcDiag(i);
138 if (op.c0 == 0.0 && op.cD == 1.0)
139 return (swbc != 0.0) ? (sumOff - rhs_i / op.invVol(i)) / swbc : uOld;
140 const double Hii = op.c0 - op.cD * op.invVol(i) * swbc;
141 const double Hoff = op.cD * op.invVol(i) * sumOff;
142 return (Hii != 0.0) ? (rhs_i - Hoff) / Hii : uOld;
143}
144
145} // namespace peclet::core::amr
146
147#endif // PECLET_CORE_AMR_FACE_CSR_HPP
#define MORTON_HD
MORTON_HD void faceCsrOffDiag(const Op &op, Index i, const U &u, double &off, double &d)
Off-diagonal sum and the (advection-inclusive) diagonal for the point smoothers: out off = Σ coef·u[n...
Definition face_csr.hpp:78
MORTON_HD double faceCsrPointUpdate(double b_i, double off, double d, double uOld, double omega)
The damped point update used by both Jacobi and (multicolour) Gauss–Seidel: returns the new u_i given...
Definition face_csr.hpp:93
MORTON_HD double fvApplyRow(const Op &op, Index i, const U &u)
(H u)_i = c0·u_i + cD·( invVol_i·( Σ w·(u_nbr − u_i) − bcDiag_i·u_i ) ).
Definition face_csr.hpp:120
MORTON_HD double fvPointSolve(const Op &op, Index i, const U &u, double rhs_i, double uOld)
The point solve of H u = rhs for one row (raw value, before damping), matching the host point solve a...
Definition face_csr.hpp:131
MORTON_HD double faceCsrApplyRow(const Op &op, Index i, const U &u)
(A u)_i — one assembled-operator row.
Definition face_csr.hpp:62
Kokkos::View< T *, MemSpace > View
1D device array.
Definition view.hpp:26
std::int64_t Index
Signed index type for grids and particles (supersedes block_decomposer's long int IndxT).
Definition types.hpp:15
A backend-agnostic view of an assembled face-CSR operator.
Definition face_csr.hpp:51
A backend-agnostic view of an assembled FV (weight-CSR) operator.
Definition face_csr.hpp:110
A uniform accessor over a raw host array, giving it the operator()(i) that Kokkos::View has,...
Definition face_csr.hpp:40
MORTON_HD T operator()(Index i) const
Definition face_csr.hpp:44