core 1.5.0
Shared MPI block decomposition, asynchronous ghost-layer exchange, SDF geometry, load balancing (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// Lifted verbatim from the AMR tree (peclet/core/amr/face_csr.hpp, 2026-09-10; QUALITY_PLAN G.2) —
4// the AMR package and voro's mesh optimiser both consume it. The "host" serial reference solver
5// (peclet::amr::AmrCutCell / oracle::AmrFlow, pure C++20) and the "device" Kokkos solver
6// (MomentumOp + csr_operator.hpp) used to carry two independent encodings of the SAME per-cell
7// arithmetic — a real drift risk. This header is the single source of that arithmetic: the
8// assembled operator
9//
10// (A u)_i = diag_i · u_i + Σ_{k ∈ [start_i, start_{i+1})} coef_k · u[nbr_k]
11// ( + optional implicit-FOU advection over a second CSR )
12//
13// expressed once as PECLET_HD row kernels over a *templated accessor*, so the SAME body serves
14// - the host: a plain serial loop, arrays = raw pointers (no Kokkos dependency — PECLET_HD is
15// plain `inline` in a non-Kokkos, non-CUDA build, so these compile as ordinary functions); and
16// - the device: inside Kokkos::parallel_for, arrays = Kokkos::View.
17//
18// Mesh-agnostic: it names no octree types and assumes nothing beyond the CSR, so it is equally the
19// kernel layer for a Voronoi-cell (unstructured polyhedral) operator.
20#ifndef PECLET_CORE_SOLVER_FACE_CSR_HPP
21#define PECLET_CORE_SOLVER_FACE_CSR_HPP
22
24
25// PECLET_HD (common/portable.hpp): KOKKOS_INLINE_FUNCTION under a Kokkos build, __host__ __device__
26// inline under nvcc/hipcc, plain inline otherwise — so the row kernels are device-callable when
27// compiled for the device and ordinary host functions in the pure-C++ build.
29
30namespace peclet::core::solver {
31
34template <class T>
35struct HostArr {
36 const T* p = nullptr;
37 HostArr() = default;
38 explicit HostArr(const T* ptr) : p(ptr) {}
39 PECLET_HD T operator()(Index i) const { return p[i]; }
40};
41
45template <class D, class I>
54
56template <class Op, class U>
57PECLET_HD double faceCsrApplyRow(const Op& op, Index i, const U& u) {
58 double acc = op.diag(i) * u(i);
59 for (Index k = op.start(i); k < op.start(i + 1); ++k)
60 acc += op.coef(k) * u(op.nbr(k));
61 if (op.hasAdv) {
62 acc += op.advDiag(i) * u(i);
63 for (Index k = op.advStart(i); k < op.advStart(i + 1); ++k)
64 acc += op.advCoef(k) * u(op.advNbr(k));
65 }
66 return acc;
67}
68
72template <class Op, class U>
73PECLET_HD void faceCsrOffDiag(const Op& op, Index i, const U& u, double& off, double& d) {
74 off = 0.0;
75 d = op.diag(i);
76 for (Index k = op.start(i); k < op.start(i + 1); ++k)
77 off += op.coef(k) * u(op.nbr(k));
78 if (op.hasAdv) {
79 for (Index k = op.advStart(i); k < op.advStart(i + 1); ++k)
80 off += op.advCoef(k) * u(op.advNbr(k));
81 d += op.advDiag(i);
82 }
83}
84
88PECLET_HD double faceCsrPointUpdate(double b_i, double off, double d, double uOld, double omega) {
89 const double nu = (d != 0.0) ? (b_i - off) / d : uOld;
90 return (1.0 - omega) * uOld + omega * nu;
91}
92
93// ---------------------------------------------------------------------------
94// The conservative FV (graded-Laplacian) operator — the *pressure* form. Unlike the general
95// momentum operator above it stores per-face conductances `w` and a per-cell `invVol`, with the
96// diagonal *derived* (the symmetric Laplacian Σ w·(u_nbr − u_i)); a Helmholtz generalisation
97// H u = c0·u + cD·( invVol·( Σ w·(u_nbr − u_i) − bcDiag·u ) )
98// (c0=0, cD=1 ⇒ the pure FV Laplacian L) keeps the L path bit-exact. Same body for host
99// (AmrPoisson) and device (poisson.hpp FvOp).
100// ---------------------------------------------------------------------------
101
103template <class D, class I>
104struct FvCsrOpT {
105 Index n = 0;
106 D invVol, coef; // coef = per-face conductance w = openness·A_f/d_f
108 D bcDiag; // homogeneous-Dirichlet boundary diagonal (0 when periodic)
109 double c0 = 0.0, cD = 1.0;
110};
111
113template <class Op, class U>
114PECLET_HD double fvApplyRow(const Op& op, Index i, const U& u) {
115 const double ui = u(i);
116 double acc = 0.0;
117 for (Index k = op.start(i); k < op.start(i + 1); ++k)
118 acc += op.coef(k) * (u(op.nbr(k)) - ui);
119 return op.c0 * ui + op.cD * (op.invVol(i) * (acc - op.bcDiag(i) * ui));
120}
121
124template <class Op, class U>
125PECLET_HD double fvPointSolve(const Op& op, Index i, const U& u, double rhs_i, double uOld) {
126 double sumOff = 0.0, sw = 0.0;
127 for (Index k = op.start(i); k < op.start(i + 1); ++k) {
128 sumOff += op.coef(k) * u(op.nbr(k));
129 sw += op.coef(k);
130 }
131 const double swbc = sw + op.bcDiag(i);
132 if (op.c0 == 0.0 && op.cD == 1.0)
133 return (swbc != 0.0) ? (sumOff - rhs_i / op.invVol(i)) / swbc : uOld;
134 const double Hii = op.c0 - op.cD * op.invVol(i) * swbc;
135 const double Hoff = op.cD * op.invVol(i) * sumOff;
136 return (Hii != 0.0) ? (rhs_i - Hoff) / Hii : uOld;
137}
138
139} // namespace peclet::core::solver
140
141#endif // PECLET_CORE_SOLVER_FACE_CSR_HPP
PECLET_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:73
PECLET_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:88
PECLET_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:114
PECLET_HD double faceCsrApplyRow(const Op &op, Index i, const U &u)
(A u)_i — one assembled-operator row.
Definition face_csr.hpp:57
PECLET_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:125
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
#define PECLET_HD
Definition portable.hpp:35
A backend-agnostic view of an assembled face-CSR operator.
Definition face_csr.hpp:46
A backend-agnostic view of an assembled FV (weight-CSR) operator.
Definition face_csr.hpp:104
A uniform accessor over a raw host array, giving it the operator()(i) that Kokkos::View has,...
Definition face_csr.hpp:35
PECLET_HD T operator()(Index i) const
Definition face_csr.hpp:39