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
20template <typename MF>
22{
23public:
24 using VEC = Vector<MF>;
25 using MG = MLMGT<MF>;
26 using RT = typename MG::RT; // double or float
28
29 explicit GMRESMLMGT (MG& mlmg);
30
39 void solve (MF& a_sol, MF const& a_rhs, RT a_tol_rel, RT a_tol_abs);
40
41 void solve (Vector<MF*> const& a_sol, Vector<MF const*> const& a_rhs, RT a_tol_rel, RT a_tol_abs);
42
44 void setVerbose (int v) {
45 m_verbose = v;
47 }
48
50 void setMaxIters (int niters) { m_gmres.setMaxIters(niters); }
51
53 [[nodiscard]] int getNumIters () const { return m_gmres.getNumIters(); }
54
56 [[nodiscard]] RT getResidualNorm () const { return m_gmres.getResidualNorm(); }
57
59 GM& getGMRES () { return m_gmres; }
60
62 VEC makeVecRHS () const;
63
65 VEC makeVecLHS () const;
66
67 RT norm2 (VEC const& mf) const;
68
69 static void scale (VEC& mf, RT scale_factor);
70
71 RT dotProduct (VEC const& mf1, VEC const& mf2) const;
72
74 static void setToZero (VEC& lhs);
75
77 static void assign (VEC& lhs, VEC const& rhs);
78
80 static void increment (VEC& lhs, VEC const& rhs, RT a);
81
83 static void linComb (VEC& lhs, RT a, VEC const& rhs_a, RT b, VEC const& rhs_b);
84
86 void apply (VEC& lhs, VEC const& rhs) const;
87
88 void precond (VEC& lhs, VEC const& rhs) const;
89
91 bool usePrecond (bool new_flag) { return std::exchange(m_use_precond, new_flag); }
92
94 void setPrecondNumIters (int precond_niters) { m_precond_niters = precond_niters; }
95
96private:
100 int m_verbose = 0;
101 int m_nlevels = 0;
102 bool m_use_precond = true;
104};
105
106template <typename MF>
108 : m_mlmg(&mlmg), m_linop(&mlmg.getLinOp()), m_nlevels(m_linop->NAMRLevels())
109{
111 m_gmres.define(*this);
112}
113
114template <typename MF>
116{
117 VEC vmf(m_nlevels);
118 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
119 vmf[ilev] = m_linop->make(ilev, 0, IntVect(0));
120 }
121 return vmf;
122}
123
124template <typename MF>
126{
127 VEC vmf(m_nlevels);
128 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
129 vmf[ilev] = m_linop->make(ilev, 0, IntVect(1));
130 setBndry(vmf[ilev], RT(0), 0, nComp(vmf[ilev]));
131 }
132 return vmf;
133}
134
135template <typename MF>
136auto GMRESMLMGT<MF>::norm2 (VEC const& mf) const -> RT
137{
138 return m_linop->norm2Precond(GetVecOfConstPtrs(mf));
139}
140
141template <typename MF>
142void GMRESMLMGT<MF>::scale (VEC& mf, RT scale_factor)
143{
144 for (auto& xmf : mf) {
145 Scale(xmf, scale_factor, 0, nComp(xmf), 0);
146 }
147}
148
149template <typename MF>
150auto GMRESMLMGT<MF>::dotProduct (VEC const& mf1, VEC const& mf2) const -> RT
151{
152 return m_linop->dotProductPrecond(GetVecOfConstPtrs(mf1), GetVecOfConstPtrs(mf2));
153}
154
155template <typename MF>
157{
158 for (auto& xmf : lhs) {
159 setVal(xmf, RT(0.0));
160 }
161}
162
163template <typename MF>
164void GMRESMLMGT<MF>::assign (VEC& lhs, VEC const& rhs)
165{
166 auto nlevels = int(lhs.size());
167 for (int ilev = 0; ilev < nlevels; ++ilev) {
168 LocalCopy(lhs[ilev], rhs[ilev], 0, 0, nComp(lhs[ilev]), IntVect(0));
169 }
170}
171
172template <typename MF>
173void GMRESMLMGT<MF>::increment (VEC& lhs, VEC const& rhs, RT a)
174{
175 auto nlevels = int(lhs.size());
176 for (int ilev = 0; ilev < nlevels; ++ilev) {
177 Saxpy(lhs[ilev], a, rhs[ilev], 0, 0, nComp(lhs[ilev]), IntVect(0));
178 }
179}
180
181template <typename MF>
182void GMRESMLMGT<MF>::linComb (VEC& lhs, RT a, VEC const& rhs_a, RT b, VEC const& rhs_b)
183{
184 auto nlevels = int(lhs.size());
185 for (int ilev = 0; ilev < nlevels; ++ilev) {
186 LinComb(lhs[ilev], a, rhs_a[ilev], 0, b, rhs_b[ilev], 0, 0, nComp(lhs[ilev]), IntVect(0));
187 }
188}
189
190template <typename MF>
191void GMRESMLMGT<MF>::apply (VEC& lhs, VEC const& rhs) const
192{
193 m_mlmg->applyPrecond(GetVecOfPtrs(lhs), GetVecOfPtrs(const_cast<VEC&>(rhs)));
194}
195
196template <typename MF>
197void GMRESMLMGT<MF>::precond (VEC& lhs, VEC const& rhs) const
198{
199 if (m_use_precond) {
200 m_mlmg->setPrecondIter(m_precond_niters);
201 setToZero(lhs);
202 m_mlmg->precond(GetVecOfPtrs(lhs), GetVecOfConstPtrs(rhs), 0, 0);
203 } else {
204 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
205 LocalCopy(lhs[ilev], rhs[ilev], 0, 0, nComp(lhs[ilev]), IntVect(0));
206 }
207 }
208}
209
210template <typename MF>
211void GMRESMLMGT<MF>::solve (MF& a_sol, MF const& a_rhs, RT a_tol_rel, RT a_tol_abs)
212{
213 AMREX_ALWAYS_ASSERT(m_nlevels == 1);
214 this->solve({&a_sol}, {&a_rhs}, a_tol_rel, a_tol_abs);
215}
216
217template <typename MF>
218void GMRESMLMGT<MF>::solve (Vector<MF*> const& a_sol, Vector<MF const*> const& a_rhs, RT a_tol_rel, RT a_tol_abs)
219{
220 m_mlmg->incPrintIdentation();
221 auto mlmg_verbose = m_mlmg->getVerbose();
222 auto mlmg_bottom_verbose = m_mlmg->getBottomVerbose();
223 m_mlmg->setVerbose(m_verbose);
224 auto mlmg_bottom_solver = m_mlmg->getBottomSolver();
225
226 if (mlmg_bottom_solver != BottomSolver::smoother &&
227 mlmg_bottom_solver != BottomSolver::hypre &&
228 mlmg_bottom_solver != BottomSolver::petsc)
229 {
230 m_mlmg->setBottomSolver(BottomSolver::smoother);
231 }
232
233 auto res = makeVecLHS();
234 auto cor = makeVecLHS();
235
236 m_mlmg->apply(GetVecOfPtrs(res), a_sol); // res = L(sol)
237 // res = L(sol) - rhs
238 bool need_to_scale_rhs = m_linop->scaleRHS(0,nullptr);
239 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
240 MF const* prhs;
241 if (need_to_scale_rhs) {
242 LocalCopy(cor[ilev], *a_rhs[ilev], 0, 0, nComp(cor[ilev]), IntVect(0));
243 auto r = m_linop->scaleRHS(ilev, &(cor[ilev]));
245 prhs = &(cor[ilev]);
246 } else {
247 prhs = a_rhs[ilev];
248 }
249 Saxpy(res[ilev], RT(-1), *prhs, 0, 0, nComp(res[ilev]), IntVect(0));
250 }
251 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
252 m_linop->setDirichletNodesToZero(ilev,0,res[ilev]);
253 }
254 m_gmres.solve(cor, res, a_tol_rel, a_tol_abs); // L(cor) = res
255 // sol = sol - cor
256 for (int ilev = 0; ilev < m_nlevels; ++ilev) {
257 Saxpy(*a_sol[ilev], RT(-1), cor[ilev], 0, 0, nComp(*a_sol[ilev]), IntVect(0));
258 }
259
260 m_mlmg->setBottomSolver(mlmg_bottom_solver);
261 m_mlmg->setVerbose(mlmg_verbose);
262 m_mlmg->setBottomVerbose(mlmg_bottom_verbose);
263 m_mlmg->decPrintIdentation();
264}
265
268
269}
270
271#endif
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
Solve using GMRES with multigrid as preconditioner.
Definition AMReX_GMRES_MLMG.H:22
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:211
static void assign(VEC &lhs, VEC const &rhs)
lhs = rhs
Definition AMReX_GMRES_MLMG.H:164
VEC makeVecRHS() const
Make MultiFab without ghost cells.
Definition AMReX_GMRES_MLMG.H:115
int m_precond_niters
Definition AMReX_GMRES_MLMG.H:103
GMRESMLMGT(MG &mlmg)
Definition AMReX_GMRES_MLMG.H:107
GM m_gmres
Definition AMReX_GMRES_MLMG.H:97
int getNumIters() const
Gets the number of iterations.
Definition AMReX_GMRES_MLMG.H:53
void setPrecondNumIters(int precond_niters)
Set the number of MLMG preconditioner iterations per GMRES iteration.
Definition AMReX_GMRES_MLMG.H:94
Vector< MF > VEC
Definition AMReX_GMRES_MLMG.H:24
static void setToZero(VEC &lhs)
lhs = 0
Definition AMReX_GMRES_MLMG.H:156
GM & getGMRES()
Get the GMRES object.
Definition AMReX_GMRES_MLMG.H:59
void setVerbose(int v)
Sets verbosity.
Definition AMReX_GMRES_MLMG.H:44
typename MG::RT RT
Definition AMReX_GMRES_MLMG.H:26
RT dotProduct(VEC const &mf1, VEC const &mf2) const
Definition AMReX_GMRES_MLMG.H:150
VEC makeVecLHS() const
Make MultiFab with ghost cells and set ghost cells to zero.
Definition AMReX_GMRES_MLMG.H:125
RT norm2(VEC const &mf) const
Definition AMReX_GMRES_MLMG.H:136
static void scale(VEC &mf, RT scale_factor)
Definition AMReX_GMRES_MLMG.H:142
static void linComb(VEC &lhs, RT a, VEC const &rhs_a, RT b, VEC const &rhs_b)
lhs = a*rhs_a + b*rhs_b
Definition AMReX_GMRES_MLMG.H:182
MLLinOpT< MF > * m_linop
Definition AMReX_GMRES_MLMG.H:99
static void increment(VEC &lhs, VEC const &rhs, RT a)
lhs += a*rhs
Definition AMReX_GMRES_MLMG.H:173
int m_verbose
Definition AMReX_GMRES_MLMG.H:100
bool m_use_precond
Definition AMReX_GMRES_MLMG.H:102
MG * m_mlmg
Definition AMReX_GMRES_MLMG.H:98
RT getResidualNorm() const
Gets the 2-norm of the residual.
Definition AMReX_GMRES_MLMG.H:56
int m_nlevels
Definition AMReX_GMRES_MLMG.H:101
bool usePrecond(bool new_flag)
Control whether or not to use MLMG as preconditioner.
Definition AMReX_GMRES_MLMG.H:91
void apply(VEC &lhs, VEC const &rhs) const
lhs = L(rhs)
Definition AMReX_GMRES_MLMG.H:191
void setMaxIters(int niters)
Sets the max number of iterations.
Definition AMReX_GMRES_MLMG.H:50
void precond(VEC &lhs, VEC const &rhs) const
Definition AMReX_GMRES_MLMG.H:197
int getNumIters() const
Gets the number of iterations.
Definition AMReX_GMRES.H:114
void define(M &linop)
Definition AMReX_GMRES.H:188
void setVerbose(int v)
Sets verbosity.
Definition AMReX_GMRES.H:105
void setMaxIters(int niters)
Sets the max number of iterations.
Definition AMReX_GMRES.H:111
RT getResidualNorm() const
Gets the 2-norm of the residual.
Definition AMReX_GMRES.H:120
Definition AMReX_MLLinOp.H:102
Definition AMReX_MLMG.H:17
void preparePrecond()
Definition AMReX_MLMG.H:1231
typename MLLinOpT< MF >::RT RT
Definition AMReX_MLMG.H:32
Long size() const noexcept
Definition AMReX_Vector.H:53
Definition AMReX_Amr.cpp:49
__host__ __device__ void ignore_unused(const Ts &...)
This shuts up the compiler about unused variables.
Definition AMReX.H:138
int nComp(FabArrayBase const &fa)
Definition AMReX_FabArrayBase.cpp:2854
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:1966
void LocalCopy(DMF &dst, SMF const &src, int scomp, int dcomp, int ncomp, IntVect const &nghost)
dst = src
Definition AMReX_FabArrayUtility.H:1950
Vector< const T * > GetVecOfConstPtrs(const Vector< T > &a)
Definition AMReX_Vector.H:93
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:2009
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:30
void setBndry(MF &dst, typename MF::value_type val, int scomp, int ncomp)
dst = val in ghost cells.
Definition AMReX_FabArrayUtility.H:1934
Vector< T * > GetVecOfPtrs(Vector< T > &a)
Definition AMReX_Vector.H:64
void Scale(MF &dst, typename MF::value_type val, int scomp, int ncomp, int nghost)
dst *= val
Definition AMReX_FabArrayUtility.H:1941
void setVal(MF &dst, typename MF::value_type val)
dst = val
Definition AMReX_FabArrayUtility.H:1927