Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_GMRES_MLMG.H
Go to the documentation of this file.
1#ifndef AMREX_GMRES_MLMG_H_
2#define AMREX_GMRES_MLMG_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_GMRES.H>
6#include <AMReX_MLMG.H>
7#include <AMReX_TypeTraits.H>
8#include <utility>
9
10namespace amrex {
11
26template <typename MF>
28{
29public:
30 using VEC = Vector<MF>;
31 using MG = MLMGT<MF>;
32 using RT = typename MG::RT; // double or float
34
40 explicit GMRESMLMGT (MG& mlmg);
41
53 void solve (MF& a_sol, MF const& a_rhs, RT a_tol_rel, RT a_tol_abs);
54
63 void solve (Vector<MF*> const& a_sol, Vector<MF const*> const& a_rhs, RT a_tol_rel, RT a_tol_abs);
64
66 void setVerbose (int v) {
67 m_verbose = v;
68 m_gmres.setVerbose(v);
69 }
70
72 void setMaxIters (int niters) { m_gmres.setMaxIters(niters); }
73
75 [[nodiscard]] int getNumIters () const { return m_gmres.getNumIters(); }
76
78 [[nodiscard]] RT getResidualNorm () const { return m_gmres.getResidualNorm(); }
79
81 GM& getGMRES () { return m_gmres; }
82
84 VEC makeVecRHS () const;
85
88 VEC makeVecLHS () const;
89
91 RT norm2 (VEC const& mf) const;
92
94 static void scale (VEC& mf, RT scale_factor);
95
97 RT dotProduct (VEC const& mf1, VEC const& mf2) const;
98
104 static void setToZero (VEC& lhs);
105
112 static void assign (VEC& lhs, VEC const& rhs);
113
121 static void increment (VEC& lhs, VEC const& rhs, RT a);
122
132 static void linComb (VEC& lhs, RT a, VEC const& rhs_a, RT b, VEC const& rhs_b);
133
140 void apply (VEC& lhs, VEC const& rhs) const;
141
148 void precond (VEC& lhs, VEC const& rhs) const;
149
156 bool usePrecond (bool new_flag) { return std::exchange(m_use_precond, new_flag); }
157
163 void setPrecondNumIters (int precond_niters) { m_precond_niters = precond_niters; }
164
165private:
166 GM m_gmres;
167 MG* m_mlmg;
168 MLLinOpT<MF>* m_linop;
169 int m_verbose = 0;
170 int m_nlevels = 0;
171 bool m_use_precond = true;
172 int m_precond_niters = 1;
173};
174
175template <typename MF>
177 : m_mlmg(&mlmg), m_linop(&mlmg.getLinOp()), m_nlevels(m_linop->NAMRLevels())
178{
179 m_mlmg->preparePrecond();
180 m_gmres.define(*this);
181}
182
183template <typename MF>
185{
186 VEC vmf(m_nlevels);
187 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
188 vmf[ilev] = m_linop->make(ilev, 0, IntVect(0));
189 }
190 return vmf;
191}
192
193template <typename MF>
195{
196 VEC vmf(m_nlevels);
197 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
198 vmf[ilev] = m_linop->make(ilev, 0, IntVect(1));
199 setBndry(vmf[ilev], RT(0), 0, nComp(vmf[ilev]));
200 }
201 return vmf;
202}
203
204template <typename MF>
205auto GMRESMLMGT<MF>::norm2 (VEC const& mf) const -> RT
206{
207 return m_linop->norm2Precond(GetVecOfConstPtrs(mf));
208}
209
210template <typename MF>
211void GMRESMLMGT<MF>::scale (VEC& mf, RT scale_factor)
212{
213 for (auto& xmf : mf) {
214 Scale(xmf, scale_factor, 0, nComp(xmf), 0);
215 }
216}
217
218template <typename MF>
219auto GMRESMLMGT<MF>::dotProduct (VEC const& mf1, VEC const& mf2) const -> RT
220{
221 return m_linop->dotProductPrecond(GetVecOfConstPtrs(mf1), GetVecOfConstPtrs(mf2));
222}
223
224template <typename MF>
226{
227 for (auto& xmf : lhs) {
228 setVal(xmf, RT(0.0));
229 }
230}
231
232template <typename MF>
233void GMRESMLMGT<MF>::assign (VEC& lhs, VEC const& rhs)
234{
235 auto nlevels = int(lhs.size());
236 for (int ilev = 0; ilev < nlevels; ++ilev) {
237 LocalCopy(lhs[ilev], rhs[ilev], 0, 0, nComp(lhs[ilev]), IntVect(0));
238 }
239}
240
241template <typename MF>
242void GMRESMLMGT<MF>::increment (VEC& lhs, VEC const& rhs, RT a)
243{
244 auto nlevels = int(lhs.size());
245 for (int ilev = 0; ilev < nlevels; ++ilev) {
246 Saxpy(lhs[ilev], a, rhs[ilev], 0, 0, nComp(lhs[ilev]), IntVect(0));
247 }
248}
249
250template <typename MF>
251void GMRESMLMGT<MF>::linComb (VEC& lhs, RT a, VEC const& rhs_a, RT b, VEC const& rhs_b)
252{
253 auto nlevels = int(lhs.size());
254 for (int ilev = 0; ilev < nlevels; ++ilev) {
255 LinComb(lhs[ilev], a, rhs_a[ilev], 0, b, rhs_b[ilev], 0, 0, nComp(lhs[ilev]), IntVect(0));
256 }
257}
258
259template <typename MF>
260void GMRESMLMGT<MF>::apply (VEC& lhs, VEC const& rhs) const
261{
262 m_mlmg->applyPrecond(GetVecOfPtrs(lhs), GetVecOfPtrs(const_cast<VEC&>(rhs)));
263}
264
265template <typename MF>
266void GMRESMLMGT<MF>::precond (VEC& lhs, VEC const& rhs) const
267{
268 if (m_use_precond) {
269 m_mlmg->setPrecondIter(m_precond_niters);
270 setToZero(lhs);
271 m_mlmg->precond(GetVecOfPtrs(lhs), GetVecOfConstPtrs(rhs), 0, 0);
272 } else {
273 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
274 LocalCopy(lhs[ilev], rhs[ilev], 0, 0, nComp(lhs[ilev]), IntVect(0));
275 }
276 }
277}
278
279template <typename MF>
280void GMRESMLMGT<MF>::solve (MF& a_sol, MF const& a_rhs, RT a_tol_rel, RT a_tol_abs)
281{
282 AMREX_ALWAYS_ASSERT(m_nlevels == 1);
283 this->solve({&a_sol}, {&a_rhs}, a_tol_rel, a_tol_abs);
284}
285
286template <typename MF>
287void GMRESMLMGT<MF>::solve (Vector<MF*> const& a_sol, Vector<MF const*> const& a_rhs, RT a_tol_rel, RT a_tol_abs)
288{
289 m_mlmg->incPrintIdentation();
290 auto mlmg_verbose = m_mlmg->getVerbose();
291 auto mlmg_bottom_verbose = m_mlmg->getBottomVerbose();
292 m_mlmg->setVerbose(m_verbose);
293 auto mlmg_bottom_solver = m_mlmg->getBottomSolver();
294
295 if (mlmg_bottom_solver != BottomSolver::smoother &&
296 mlmg_bottom_solver != BottomSolver::hypre &&
297 mlmg_bottom_solver != BottomSolver::petsc &&
298 mlmg_bottom_solver != BottomSolver::algmg)
299 {
300 m_mlmg->setBottomSolver(BottomSolver::smoother);
301 }
302
303 auto res = makeVecLHS();
304 auto cor = makeVecLHS();
305
306 m_mlmg->apply(GetVecOfPtrs(res), a_sol); // res = L(sol)
307 // res = L(sol) - rhs
308 bool need_to_scale_rhs = m_linop->scaleRHS(0,nullptr);
309 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
310 MF const* prhs;
311 if (need_to_scale_rhs) {
312 LocalCopy(cor[ilev], *a_rhs[ilev], 0, 0, nComp(cor[ilev]), IntVect(0));
313 auto r = m_linop->scaleRHS(ilev, &(cor[ilev]));
315 prhs = &(cor[ilev]);
316 } else {
317 prhs = a_rhs[ilev];
318 }
319 Saxpy(res[ilev], RT(-1), *prhs, 0, 0, nComp(res[ilev]), IntVect(0));
320 }
321 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
322 m_linop->setDirichletNodesToZero(ilev,0,res[ilev]);
323 }
324 m_gmres.setInitialGuessNonzero(false); // cor starts at zero
325 m_gmres.solve(cor, res, a_tol_rel, a_tol_abs); // L(cor) = res
326 // sol = sol - cor
327 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
328 Saxpy(*a_sol[ilev], RT(-1), cor[ilev], 0, 0, nComp(*a_sol[ilev]), IntVect(0));
329 }
330
331 m_mlmg->setBottomSolver(mlmg_bottom_solver);
332 m_mlmg->setVerbose(mlmg_verbose);
333 m_mlmg->setBottomVerbose(mlmg_bottom_verbose);
334 m_mlmg->decPrintIdentation();
335}
336
339
340}
341
342#endif
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
Solve using GMRES with multigrid as preconditioner.
Definition AMReX_GMRES_MLMG.H:28
void solve(MF &a_sol, MF const &a_rhs, RT a_tol_rel, RT a_tol_abs)
Solve the linear system.
Definition AMReX_GMRES_MLMG.H:280
static void assign(VEC &lhs, VEC const &rhs)
Copy rhs into lhs level by level.
Definition AMReX_GMRES_MLMG.H:233
VEC makeVecRHS() const
Return a MultiFab vector without ghost cells for RHS storage.
Definition AMReX_GMRES_MLMG.H:184
GMRESMLMGT(MG &mlmg)
Wrap an existing MLMG hierarchy as a GMRES operator/preconditioner.
Definition AMReX_GMRES_MLMG.H:176
int getNumIters() const
Number of iterations executed by the last solve().
Definition AMReX_GMRES_MLMG.H:75
void setPrecondNumIters(int precond_niters)
Adjust how many MLMG smoothing iterations run inside each GMRES iteration.
Definition AMReX_GMRES_MLMG.H:163
Vector< MF > VEC
Definition AMReX_GMRES_MLMG.H:30
static void setToZero(VEC &lhs)
Reset lhs to zero on every AMR level.
Definition AMReX_GMRES_MLMG.H:225
GM & getGMRES()
Direct access to the underlying GMRES driver for fine-grained tuning.
Definition AMReX_GMRES_MLMG.H:81
void setVerbose(int v)
Set verbosity level v for both GMRES and MLMG components.
Definition AMReX_GMRES_MLMG.H:66
typename MG::RT RT
Definition AMReX_GMRES_MLMG.H:32
RT dotProduct(VEC const &mf1, VEC const &mf2) const
Return the preconditioner-aware dot product between mf1 and mf2.
Definition AMReX_GMRES_MLMG.H:219
GMRES< Vector< MF >, GMRESMLMGT< MF > > GM
Definition AMReX_GMRES_MLMG.H:33
VEC makeVecLHS() const
Definition AMReX_GMRES_MLMG.H:194
RT norm2(VEC const &mf) const
Return the 2-norm of mf using the multigrid operator's weighting.
Definition AMReX_GMRES_MLMG.H:205
static void scale(VEC &mf, RT scale_factor)
Scale each component of mf by scale_factor.
Definition AMReX_GMRES_MLMG.H:211
MLMGT< MF > MG
Definition AMReX_GMRES_MLMG.H:31
static void linComb(VEC &lhs, RT a, VEC const &rhs_a, RT b, VEC const &rhs_b)
Form a linear combination: lhs = a * rhs_a + b * rhs_b.
Definition AMReX_GMRES_MLMG.H:251
static void increment(VEC &lhs, VEC const &rhs, RT a)
Add a scaled vector: lhs += a * rhs.
Definition AMReX_GMRES_MLMG.H:242
RT getResidualNorm() const
Final residual 2-norm produced by the last solve().
Definition AMReX_GMRES_MLMG.H:78
bool usePrecond(bool new_flag)
Enable or disable MLMG as a preconditioner.
Definition AMReX_GMRES_MLMG.H:156
void apply(VEC &lhs, VEC const &rhs) const
Apply the operator supplied to the constructor.
Definition AMReX_GMRES_MLMG.H:260
void setMaxIters(int niters)
Cap the number of GMRES iterations executed per solve to niters.
Definition AMReX_GMRES_MLMG.H:72
void precond(VEC &lhs, VEC const &rhs) const
Apply the MLMG-based preconditioner: lhs = P^{-1}(rhs).
Definition AMReX_GMRES_MLMG.H:266
int getNumIters() const
Number of iterations executed by the last solve().
Definition AMReX_GMRES.H:142
void define(M &linop)
Bind the solver to a linear operator.
Definition AMReX_GMRES.H:221
void setVerbose(int v)
Set verbosity level v (0 = silent).
Definition AMReX_GMRES.H:125
void setMaxIters(int niters)
Cap the number of iterations performed by solve().
Definition AMReX_GMRES.H:139
RT getResidualNorm() const
Final residual 2-norm from the last solve().
Definition AMReX_GMRES.H:148
Abstract base class for multilevel linear operators used by MLMG and the bottom solvers.
Definition AMReX_MLLinOp.H:139
Definition AMReX_MLMG.H:39
void preparePrecond()
Prepare preconditioner-specific caches (e.g., boundary data).
Definition AMReX_MLMG.H:1857
typename MLLinOpT< MF >::RT RT
Definition AMReX_MLMG.H:54
Long size() const noexcept
Definition AMReX_Vector.H:54
Definition AMReX_Amr.cpp:50
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:273
void Scale(MF &dst, typename MF::value_type val, int scomp, int ncomp, int nghost)
dst *= val
Definition AMReX_FabArrayUtility.H:2175
Vector< const T * > GetVecOfConstPtrs(const Vector< T > &a)
Definition AMReX_Vector.H:94
int nComp(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.nComp().
Definition AMReX_FabArrayBase.cpp:2939
void LinComb(MF &dst, typename MF::value_type a, MF const &src_a, int acomp, typename MF::value_type b, MF const &src_b, int bcomp, int dcomp, int ncomp, IntVect const &nghost)
dst = a*src_a + b*src_b
Definition AMReX_FabArrayUtility.H:2241
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
Vector< T * > GetVecOfPtrs(Vector< T > &a)
Definition AMReX_Vector.H:65
void LocalCopy(DMF &dst, SMF const &src, int scomp, int dcomp, int ncomp, IntVect const &nghost)
dst = src
Definition AMReX_FabArrayUtility.H:2182
void setBndry(MF &dst, typename MF::value_type val, int scomp, int ncomp)
dst = val in ghost cells.
Definition AMReX_FabArrayUtility.H:2168
const int[]
Definition AMReX_BLProfiler.cpp:1665
void Saxpy(MF &dst, typename MF::value_type a, MF const &src, int scomp, int dcomp, int ncomp, IntVect const &nghost)
dst += a * src
Definition AMReX_FabArrayUtility.H:2198
void setVal(MF &dst, typename MF::value_type val)
dst = val
Definition AMReX_FabArrayUtility.H:2161