27#ifndef PECLET_CORE_AMR_PCG_HPP
28#define PECLET_CORE_AMR_PCG_HPP
30#ifdef PECLET_CORE_HAVE_MORTON
46 Kokkos::parallel_reduce(
64 for (
Index k = start(
i); k < start(
i + 1); ++k)
66 mask(
i) = (d > 1
e-30) ? 1.0 : 0.0;
81 double su = 0.0,
sv = 0.0;
82 Kokkos::parallel_reduce(
83 "amr::pcg_meannum", n,
85 Kokkos::parallel_reduce(
88 const double m = (
sv > 0.0) ?
su /
sv : 0.0;
100 Kokkos::parallel_for(
114template <
int Dim,
unsigned Bits = (Dim == 2 ? 32u : (Dim == 3 ? 21u : 16u))>
142 double tol = 1
e-10) {
143 const Index n =
mg.numLeaves(0);
144 const FvOp& op =
mg.op(0);
162 Kokkos::deep_copy(x, 0.0);
163 Kokkos::deep_copy(r_,
rhs);
170 applyPrec(
mg, r_, z_, n);
172 Kokkos::deep_copy(p_, z_);
185 double alpha =
rz /
pAp;
194 applyPrec(
mg, r_, z_, n);
211 Kokkos::deep_copy(
mg.b(0),
r);
213 Kokkos::deep_copy(
mg.x(0), 0.0);
214 for (
int k = 0; k < cyclesPerPrec_; ++k)
215 mg.vcycle(pre_, post_, bottom_, omega_);
216 Kokkos::deep_copy(
z,
mg.x(0));
219 void ensure(
Index n) {
220 if (r_.extent(0) ==
static_cast<std::size_t
>(n))
222 r_ =
View<double>(
"pcg_r",
static_cast<std::size_t
>(n));
223 z_ =
View<double>(
"pcg_z",
static_cast<std::size_t
>(n));
224 p_ =
View<double>(
"pcg_p",
static_cast<std::size_t
>(n));
225 Ap_ =
View<double>(
"pcg_Ap",
static_cast<std::size_t
>(n));
226 mask_ =
View<double>(
"pcg_fluidmask",
static_cast<std::size_t
>(n));
230 int pre_ = 2, post_ = 2, bottom_ = 40;
232 int cyclesPerPrec_ = 1;
233 bool singular_ =
true;
Result solve(MG &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).
Multigrid< Dim, Bits > MG
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 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)
Project u onto the FLUID range: zero solid cells, then subtract the volume-weighted mean over the flu...
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).
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,...
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