26#ifndef PECLET_AMR_PCG_HPP
27#define PECLET_AMR_PCG_HPP
35#include "peclet/core/common/view.hpp"
36#include "peclet/core/solver/vector_ops.hpp"
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 Index n,
const std::function<
double(
double)>&
reduce) {
83 double su = 0.0,
sv = 0.0;
84 Kokkos::parallel_reduce(
85 "amr::pcg_meannum", n,
87 Kokkos::parallel_reduce(
94 const double m = (
sv > 0.0) ?
su /
sv : 0.0;
115template <
int Dim,
unsigned Bits = (Dim == 2 ? 32u : (Dim == 3 ? 21u : 16u))>
159 template <
class MGT = MG>
161 double tol = 1
e-10) {
162 const Index n =
mg.numLeaves(0);
163 const FvOp& op =
mg.op(0);
180 const double s =
dotVol(
a, b, invVol, n);
181 return dotReduce_ ? dotReduce_(
s) :
s;
186 Kokkos::deep_copy(x, 0.0);
196 applyPrec(
mg, r_, z_, n);
198 Kokkos::deep_copy(p_, z_);
212 double alpha =
rz /
pAp;
221 applyPrec(
mg, r_, z_, n);
241 Kokkos::deep_copy(
mg.b(0),
r);
243 Kokkos::deep_copy(
mg.x(0), 0.0);
244 for (
int k = 0; k < cyclesPerPrec_; ++k)
245 mg.vcycle(pre_, post_, bottom_, omega_);
246 Kokkos::deep_copy(
z,
mg.x(0));
255 void ensure(
Index n) {
258 if (r_.extent(0) ==
static_cast<std::size_t
>(n))
260 r_ =
View<double>(
"pcg_r",
static_cast<std::size_t
>(n));
261 z_ =
View<double>(
"pcg_z",
static_cast<std::size_t
>(n));
262 p_ =
View<double>(
"pcg_p",
static_cast<std::size_t
>(n));
263 Ap_ =
View<double>(
"pcg_Ap",
static_cast<std::size_t
>(n));
264 mask_ =
View<double>(
"pcg_fluidmask",
static_cast<std::size_t
>(n));
268 int pre_ = 2, post_ = 2, bottom_ = 40;
270 int cyclesPerPrec_ = 1;
271 bool singular_ =
true;
273 std::function<
double(
double)> dotReduce_;
void setSingular(bool s)
Whether to project out the constant nullspace (default true; set false for the non-singular homogeneo...
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 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 setCyclesPerPrec(int k)
Number of V-cycles per preconditioner application (default 1).
void removeMeanVol(View< double > u, View< const double > invVol, View< const double > mask, Index n)
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...
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.
void maskSolid(View< double > u, View< const double > mask, Index n)
Zero the solid cells (project out the solid null modes).
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,...
View< Index > faceStart
CSR row offsets, size n+1.
View< double > bcDiag
Dirichlet boundary diagonal per cell (0 if periodic), size n.
View< double > invVol
1/V_i, size n
View< double > faceW
w_f = openness·A_f/d_f per face, size nFaces
double res0
initial volume-weighted residual norm
double res
final volume-weighted residual norm