13#ifndef CD_AMRMULTIGRIDKRYLOVOPIMPLEM_H
14#define CD_AMRMULTIGRIDKRYLOVOPIMPLEM_H
22#include <CD_NamespaceHeader.H>
29 this->clear(m_precondTmp);
30 this->clear(m_precondDcor);
36 const Vector<RefCountedPtr<LevelData<BaseFab<bool>>>>& a_validCells,
37 const Vector<Real>& a_dx,
40 const int a_numVCycles)
42 CH_TIME(
"AMRMultigridKrylovOp::define");
45 m_amrOps = a_mg->getAMROperators();
48 m_numVCycles = std::max(1, a_numVCycles);
55 this->clear(m_precondTmp);
56 this->clear(m_precondDcor);
58 m_precondInit =
false;
59 m_volumeCached =
false;
62 m_dxScale.resize(a_lmax + 1, 1.0);
63 for (
int lvl = 0; lvl <= a_lmax; lvl++) {
64 m_dxScale[lvl] = D_TERM(a_dx[lvl], *a_dx[lvl], *a_dx[lvl]);
69 m_validMask = a_validCells;
76 m_mg->computeAMROperator(a_lhs,
const_cast<Vector<LevelData<T>*
>&>(a_phi), m_lmax, m_lbase, a_homogeneous);
82 const Vector<LevelData<T>*>& a_phi,
83 const Vector<LevelData<T>*>& a_rhs,
86 m_mg->computeAMRResidual(a_lhs,
87 const_cast<Vector<LevelData<T>*
>&>(a_phi),
99 CH_TIME(
"AMRMultigridKrylovOp::preCond");
101 if (!m_precondInit) {
102 this->create(m_precondTmp, a_residual);
103 this->create(m_precondDcor, a_residual);
104 m_precondInit =
true;
107 this->setToZero(a_cor);
109 for (
int iter = 0; iter < m_numVCycles; iter++) {
115 this->assign(m_precondTmp, a_residual);
118 this->residual(m_precondTmp, a_cor, a_residual,
true);
119 this->scale(m_precondTmp, -1.0);
122 this->setToZero(m_precondDcor);
123 m_mg->AMRVCycle(m_precondDcor, m_precondTmp, m_lmax, m_lmax, m_lbase);
125 this->incr(a_cor, m_precondDcor, 1.0);
133 a_lhs.resize(a_rhs.size(),
nullptr);
134 for (
int lvl = m_lbase; lvl < a_rhs.size(); lvl++) {
135 a_lhs[lvl] =
new LevelData<T>();
136 m_amrOps[lvl]->create(*a_lhs[lvl], *a_rhs[lvl]);
144 for (
int lvl = 0; lvl < a_lhs.size(); lvl++) {
145 if (a_lhs[lvl] !=
nullptr) {
147 a_lhs[lvl] =
nullptr;
156 for (
int lvl = m_lbase; lvl < a_rhs.size(); lvl++) {
157 m_amrOps[lvl]->assign(*a_lhs[lvl], *a_rhs[lvl]);
165 CH_TIME(
"AMRMultigridKrylovOp::dotProduct");
169 const int nLevels = m_lmax - m_lbase + 1;
170 const bool needVol = !m_volumeCached;
174 Vector<Real> partials(needVol ? 2 * nLevels : nLevels, 0.0);
176 for (
int lvl = m_lbase; lvl <= m_lmax; lvl++) {
177 auto* op =
static_cast<OpType*
>(m_amrOps[lvl]);
180 op->dotProductMaskedLocal(xy, vol, *a_1[lvl], *a_2[lvl], *m_validMask[lvl], needVol);
182 partials[lvl - m_lbase] = xy;
184 partials[nLevels + (lvl - m_lbase)] = vol;
191 m_volume.resize(m_lmax + 1, 0.0);
192 for (
int lvl = m_lbase; lvl <= m_lmax; lvl++) {
193 m_volume[lvl] = partials[nLevels + (lvl - m_lbase)];
195 m_volumeCached =
true;
203 for (
int lvl = m_lbase; lvl <= m_lmax; lvl++) {
204 if (m_volume[lvl] > 0.0) {
205 prod += (partials[lvl - m_lbase] / m_volume[lvl]) * m_dxScale[lvl];
216 const Vector<LevelData<T>*> a_2[],
219 CH_TIME(
"AMRMultigridKrylovOp::mDotProduct");
223 const int nLevels = m_lmax - m_lbase + 1;
224 const int nNum = a_sz * nLevels;
225 const bool needVol = !m_volumeCached;
228 Vector<Real> partials(needVol ? nNum + nLevels : nNum, 0.0);
230 for (
int lvl = m_lbase; lvl <= m_lmax; lvl++) {
231 auto* op =
static_cast<OpType*
>(m_amrOps[lvl]);
234 for (
int k = 0; k < a_sz; k++) {
237 const bool needVolHere = needVol && (k == 0);
239 op->dotProductMaskedLocal(xy, v, *a_1[lvl], *(a_2[k][lvl]), *m_validMask[lvl], needVolHere);
241 partials[k * nLevels + (lvl - m_lbase)] = xy;
248 partials[nNum + (lvl - m_lbase)] = vol;
255 m_volume.resize(m_lmax + 1, 0.0);
256 for (
int lvl = m_lbase; lvl <= m_lmax; lvl++) {
257 m_volume[lvl] = partials[nNum + (lvl - m_lbase)];
259 m_volumeCached =
true;
262 for (
int k = 0; k < a_sz; k++) {
264 for (
int lvl = m_lbase; lvl <= m_lmax; lvl++) {
265 if (m_volume[lvl] > 0.0) {
266 prod += (partials[k * nLevels + (lvl - m_lbase)] / m_volume[lvl]) * m_dxScale[lvl];
277 for (
int lvl = m_lbase; lvl < a_lhs.size(); lvl++) {
278 m_amrOps[lvl]->incr(*a_lhs[lvl], *a_x[lvl], a_scale);
285 const Vector<LevelData<T>*>& a_x,
286 const Vector<LevelData<T>*>& a_y,
290 for (
int lvl = m_lbase; lvl < a_lhs.size(); lvl++) {
291 m_amrOps[lvl]->axby(*a_lhs[lvl], *a_x[lvl], *a_y[lvl], a_a, a_b);
299 for (
int lvl = m_lbase; lvl < a_lhs.size(); lvl++) {
300 m_amrOps[lvl]->scale(*a_lhs[lvl], a_scale);
309 return std::sqrt(this->dotProduct(a_rhs, a_rhs));
313 for (
int lvl = m_lbase; lvl <= m_lmax; lvl++) {
314 maxNorm = std::max(maxNorm, m_amrOps[lvl]->norm(*a_rhs[lvl], a_ord));
324 for (
int lvl = m_lbase; lvl < a_lhs.size(); lvl++) {
325 m_amrOps[lvl]->setToZero(*a_lhs[lvl]);
329#include <CD_NamespaceFooter.H>
Linear-operator adapter that exposes an AMR-multigrid cycle as a Krylov preconditioner.
Agglomeration of basic MPI reductions.
void residual(Vector< LevelData< T > * > &a_lhs, const Vector< LevelData< T > * > &a_phi, const Vector< LevelData< T > * > &a_rhs, bool a_homogeneous=false) override
AMR residual a_lhs = L(a_phi) - a_rhs.
Definition CD_AMRMultigridKrylovOpImplem.H:81
void incr(Vector< LevelData< T > * > &a_lhs, const Vector< LevelData< T > * > &a_x, Real a_scale) override
Increment a_lhs += a_scale*a_x.
Definition CD_AMRMultigridKrylovOpImplem.H:275
void assign(Vector< LevelData< T > * > &a_lhs, const Vector< LevelData< T > * > &a_rhs) override
Copy a_rhs into a_lhs.
Definition CD_AMRMultigridKrylovOpImplem.H:154
void define(AMRMultiGrid< LevelData< T > > *a_mg, const Vector< RefCountedPtr< LevelData< BaseFab< bool > > > > &a_validCells, const Vector< Real > &a_dx, const int a_lbase, const int a_lmax, const int a_numVCycles)
Define the adapter. Call once per regrid (after the AMRMultiGrid has been defined and init'd).
Definition CD_AMRMultigridKrylovOpImplem.H:35
void preCond(Vector< LevelData< T > * > &a_cor, const Vector< LevelData< T > * > &a_residual) override
Apply the preconditioner: a_cor approx L^{-1} a_residual via m_numVCycles multigrid cycles (cycle typ...
Definition CD_AMRMultigridKrylovOpImplem.H:97
void mDotProduct(const Vector< LevelData< T > * > &a_1, const int a_sz, const Vector< LevelData< T > * > a_2[], Real a_mdots[]) override
Batched inner products a_mdots[k] = dotProduct(a_1, a_2[k]) for k=0..a_sz-1.
Definition CD_AMRMultigridKrylovOpImplem.H:214
void axby(Vector< LevelData< T > * > &a_lhs, const Vector< LevelData< T > * > &a_x, const Vector< LevelData< T > * > &a_y, Real a_a, Real a_b) override
Set a_lhs = a_a*a_x + a_b*a_y.
Definition CD_AMRMultigridKrylovOpImplem.H:284
void create(Vector< LevelData< T > * > &a_lhs, const Vector< LevelData< T > * > &a_rhs) override
Allocate a_lhs to mirror a_rhs.
Definition CD_AMRMultigridKrylovOpImplem.H:131
void applyOp(Vector< LevelData< T > * > &a_lhs, const Vector< LevelData< T > * > &a_phi, bool a_homogeneous=false) override
Matrix-vector product L(phi) over the AMR hierarchy (always homogeneous for the Krylov path).
Definition CD_AMRMultigridKrylovOpImplem.H:74
Real norm(const Vector< LevelData< T > * > &a_rhs, int a_ord) override
Norm of a_rhs. For a_ord==2 this is the inner-product-induced norm sqrt(dotProduct(x,...
Definition CD_AMRMultigridKrylovOpImplem.H:306
Real dotProduct(const Vector< LevelData< T > * > &a_1, const Vector< LevelData< T > * > &a_2) override
AMR-composite inner product (allocation-free, fine-covered cells masked out).
Definition CD_AMRMultigridKrylovOpImplem.H:163
virtual ~AMRMultigridKrylovOp()
Destructor. Frees the preconditioner scratch storage.
Definition CD_AMRMultigridKrylovOpImplem.H:25
void clear(Vector< LevelData< T > * > &a_lhs) override
Free a holder created by create().
Definition CD_AMRMultigridKrylovOpImplem.H:142
void setToZero(Vector< LevelData< T > * > &a_lhs) override
Set a_lhs = 0.
Definition CD_AMRMultigridKrylovOpImplem.H:322
void scale(Vector< LevelData< T > * > &a_lhs, const Real &a_scale) override
Scale a_lhs *= a_scale.
Definition CD_AMRMultigridKrylovOpImplem.H:297
Real sum(const Real &a_value) noexcept
Compute the sum across all MPI ranks.
Definition CD_ParallelOpsImplem.H:354
Trait mapping a FAB type to the concrete chombo-discharge Helmholtz operator that owns it.
Definition CD_AMRMultigridKrylovOp.H:40