27#ifndef PECLET_CORE_AMR_PCG_HPP
28#define PECLET_CORE_AMR_PCG_HPP
30#ifdef PECLET_CORE_HAVE_MORTON
47 Kokkos::parallel_reduce(
65 for (
Index k = start(
i); k < start(
i + 1); ++k)
67 mask(
i) = (d > 1
e-30) ? 1.0 : 0.0;
83 const std::function<
double(
double)>&
reduce) {
85 double su = 0.0,
sv = 0.0;
86 Kokkos::parallel_reduce(
87 "amr::pcg_meannum", n,
89 Kokkos::parallel_reduce(
96 const double m = (
sv > 0.0) ?
su /
sv : 0.0;
113 Kokkos::parallel_for(
127template <
int Dim,
unsigned Bits = (Dim == 2 ? 32u : (Dim == 3 ? 21u : 16u))>
171 template <
class MGT = MG>
173 double tol = 1
e-10) {
174 const Index n =
mg.numLeaves(0);
175 const FvOp& op =
mg.op(0);
192 const double s =
dotVol(
a, b, invVol, n);
193 return dotReduce_ ? dotReduce_(
s) :
s;
198 Kokkos::deep_copy(x, 0.0);
201 Kokkos::parallel_for(
209 applyPrec(
mg, r_, z_, n);
211 Kokkos::deep_copy(p_, z_);
225 double alpha =
rz /
pAp;
234 applyPrec(
mg, r_, z_, n);
254 Kokkos::deep_copy(
mg.b(0),
r);
256 Kokkos::deep_copy(
mg.x(0), 0.0);
257 for (
int k = 0; k < cyclesPerPrec_; ++k)
258 mg.vcycle(pre_, post_, bottom_, omega_);
259 Kokkos::deep_copy(
z,
mg.x(0));
268 void ensure(
Index n) {
271 if (r_.extent(0) ==
static_cast<std::size_t
>(n))
273 r_ =
View<double>(
"pcg_r",
static_cast<std::size_t
>(n));
274 z_ =
View<double>(
"pcg_z",
static_cast<std::size_t
>(n));
275 p_ =
View<double>(
"pcg_p",
static_cast<std::size_t
>(n));
276 Ap_ =
View<double>(
"pcg_Ap",
static_cast<std::size_t
>(n));
277 mask_ =
View<double>(
"pcg_fluidmask",
static_cast<std::size_t
>(n));
281 int pre_ = 2, post_ = 2, bottom_ = 40;
283 int cyclesPerPrec_ = 1;
284 bool singular_ =
true;
286 std::function<
double(
double)> dotReduce_;
Result solve(MGT &mg, View< double > x, View< const double > rhs, int maxIters=200, double tol=1e-10)
Solve L x = rhs on mg's finest level into x (size n; nExt distributed).
void setVcycle(int pre, int post, int bottom, double omega)
V-cycle parameters used for the preconditioner application.
void setCyclesPerPrec(int k)
Number of V-cycles per preconditioner application (default 1).
void setSingular(bool s)
Whether to project out the constant nullspace (default true; set false for the non-singular homogeneo...
void setDistributed(std::function< void(View< double >)> refresh, std::function< double(double)> dotReduce, Index nExt)
Distributed solve (docs/amr_distributed_flow.md, rung 3): refresh re-fills the ghost tail [n,...
void axpy(View< double > y, double a, View< const double > x, Index n)
y += a·x
void removeMeanVol(View< double > u, View< const double > invVol, View< const double > mask, Index n)
void applyFv(const FvOp &op, View< const double > u, View< double > Lu)
Hu = (c0·I + cD·L) u (consistent conservative FV Laplacian, c0=0/cD=1 ⇒ pure L).
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,...
void zpby(View< double > p, View< const double > z, double b, Index n)
p = z + b·p (CG direction update)
void negate(View< double > x, Index n)
y = −x (negate in place)
void maskSolid(View< double > u, View< const double > mask, Index n)
Zero the solid cells (project out the solid null modes).
void buildFluidMask(const FvOp &op, View< double > mask, Index n)
Build the fluid mask: mask(i)=1 where the operator diagonal Σ_f w_f (+ bcDiag) is non-trivial,...
void removeMeanVolReduced(View< double > u, View< const double > invVol, View< const double > mask, Index n, const std::function< double(double)> &reduce)
Project u onto the FLUID range: zero solid cells, then subtract the volume-weighted mean over the flu...
double dotVol(View< const double > u, View< const double > v, View< const double > invVol, Index n)
Volume-weighted dot <u,v>_D = Σ_i V_i u_i v_i, V_i = 1/invVol_i.
Kokkos::View< T *, MemSpace > View
1D device array.
std::int64_t Index
Signed index type for grids and particles (supersedes block_decomposer's long int IndxT).
View< double > invVol
1/V_i, size n
View< double > faceW
w_f = openness·A_f/d_f per face, size nFaces
View< Index > faceStart
CSR row offsets, size n+1.
View< double > bcDiag
Dirichlet boundary diagonal per cell (0 if periodic), size n.
double res0
initial volume-weighted residual norm
double res
final volume-weighted residual norm