2#ifndef AMREX_MLCGSOLVER_H_
3#define AMREX_MLCGSOLVER_H_
4#include <AMReX_Config.H>
65 int solve (MF& solnL,
const MF& rhsL,
RT eps_rel,
RT eps_abs);
74 [[nodiscard]]
int getVerbose ()
const {
return verbose; }
83 [[nodiscard]]
int getMaxIter ()
const {
return maxiter; }
120 [[nodiscard]]
RT dotxy (
const MF& r,
const MF&
z,
bool local =
false);
128 [[nodiscard]]
RT norm_inf (
const MF& res,
bool local =
false);
148 int solve_cg (MF& solnL,
const MF& rhsL,
RT eps_rel,
RT eps_abs);
157 const int amrlev = 0;
163 bool initial_vec_zeroed =
false;
164 std::string print_ident;
167template <
typename MF>
169 : Lp(_lp), solver_type(_typ), mglev(_lp.NMGLevels(0)-1)
174template <
typename MF>
178 if (solver_type == Type::BiCGStab) {
179 return solve_bicgstab(sol,rhs,eps_rel,eps_abs);
181 return solve_cg(sol,rhs,eps_rel,eps_abs);
185template <
typename MF>
191 const int ncomp =
nComp(sol);
194 MF p = Lp.make(amrlev, mglev,
nGrowVect(sol), async_info);
195 MF r = Lp.make(amrlev, mglev,
nGrowVect(sol), async_info);
199 MF rh = Lp.make(amrlev, mglev, nghost, async_info);
200 MF v = Lp.make(amrlev, mglev, nghost, async_info);
201 MF t = Lp.make(amrlev, mglev, nghost, async_info);
206 if ( initial_vec_zeroed ) {
209 sorig = Lp.make(amrlev, mglev, nghost, async_info);
218 Lp.normalize(amrlev, mglev, r);
221 RT rnorm = norm_inf(r);
222 const RT rnorm0 = rnorm;
226 amrex::Print() << print_ident <<
"MLCGSolver_BiCGStab: Initial error (error0) = " << rnorm0 <<
'\n';
230 RT rho_1 = 0, alpha = 0, omega = 0;
232 if ( rnorm0 == 0 || rnorm0 < eps_abs )
236 amrex::Print() << print_ident <<
"MLCGSolver_BiCGStab: niter = 0,"
237 <<
", rnorm = " << rnorm
238 <<
", eps_abs = " << eps_abs <<
'\n';
240 if ( !initial_vec_zeroed ) {
241 LocalAdd(sol, sorig, 0, 0, ncomp, nghost);
246 for (; iter <= maxiter; ++iter)
248 const RT rho = dotxy(rh,r);
259 const RT beta = (rho/rho_1)*(alpha/omega);
260 if constexpr (IsMultiFabLike_v<MF>) {
265 Saxpy(p, -omega, v, 0, 0, ncomp, nghost);
266 Xpay(p,
beta, r, 0, 0, ncomp, nghost);
270 Lp.normalize(amrlev, mglev, v);
272 RT rhTv = dotxy(rh,v);
273 if ( rhTv !=
RT(0.0) )
281 if constexpr (IsMultiFabLike_v<MF>) {
283 Saxpy_Saxpy(sol, alpha, p, r, -alpha, v, 0, 0, ncomp, nghost);
285 Saxpy(sol, alpha, p, 0, 0, ncomp, nghost);
286 Saxpy(r, -alpha, v, 0, 0, ncomp, nghost);
293 amrex::Print() << print_ident <<
"MLCGSolver_BiCGStab: Half Iter "
294 << std::setw(11) << iter
296 << rnorm/(rnorm0) <<
'\n';
299 if ( rnorm < eps_rel*rnorm0 || rnorm < eps_abs ) {
break; }
302 Lp.normalize(amrlev, mglev, t);
308 RT tvals[2] = { dotxy(t,t,
true), dotxy(t,r,
true) };
314 if ( tvals[0] !=
RT(0.0) )
316 omega = tvals[1]/tvals[0];
322 if constexpr (IsMultiFabLike_v<MF>) {
324 Saypy_Saxpy(sol, omega, r, -omega, t, 0, 0, ncomp, nghost);
326 Saxpy(sol, omega, r, 0, 0, ncomp, nghost);
327 Saxpy(r, -omega, t, 0, 0, ncomp, nghost);
334 amrex::Print() << print_ident <<
"MLCGSolver_BiCGStab: Iteration "
335 << std::setw(11) << iter
337 << rnorm/(rnorm0) <<
'\n';
340 if ( rnorm < eps_rel*rnorm0 || rnorm < eps_abs ) {
break; }
351 amrex::Print() << print_ident <<
"MLCGSolver_BiCGStab: Final: Iteration "
352 << std::setw(4) << iter
354 << rnorm/(rnorm0) <<
'\n';
357 if ( ret == 0 && rnorm > eps_rel*rnorm0 && rnorm > eps_abs)
365 if ( ( ret == 0 || ret == 8 ) && (rnorm < rnorm0) )
367 if ( !initial_vec_zeroed ) {
368 LocalAdd(sol, sorig, 0, 0, ncomp, nghost);
370 if (ret == 8) { ret = 9; }
375 if ( !initial_vec_zeroed ) {
376 LocalAdd(sol, sorig, 0, 0, ncomp, nghost);
383template <
typename MF>
389 const int ncomp =
nComp(sol);
392 MF p = Lp.make(amrlev, mglev,
nGrowVect(sol), async_info);
395 MF r = Lp.make(amrlev, mglev, nghost, async_info);
396 MF q = Lp.make(amrlev, mglev, nghost, async_info);
400 if ( initial_vec_zeroed ) {
403 sorig = Lp.make(amrlev, mglev, nghost, async_info);
411 RT rnorm = norm_inf(r);
412 const RT rnorm0 = rnorm;
416 amrex::Print() << print_ident <<
"MLCGSolver_CG: Initial error (error0) : " << rnorm0 <<
'\n';
423 if ( rnorm0 == 0 || rnorm0 < eps_abs )
426 amrex::Print() << print_ident <<
"MLCGSolver_CG: niter = 0,"
427 <<
", rnorm = " << rnorm
428 <<
", eps_abs = " << eps_abs <<
'\n';
430 if ( !initial_vec_zeroed ) {
431 LocalAdd(sol, sorig, 0, 0, ncomp, nghost);
436 for (; iter <= maxiter; ++iter)
451 Xpay(p,
beta, r, 0, 0, ncomp, nghost);
471 <<
" alpha " << alpha <<
'\n';
473 if constexpr (IsMultiFabLike_v<MF>) {
475 Saxpy_Saxpy(sol, alpha, p, r, -alpha, q, 0, 0, ncomp, nghost);
477 Saxpy(sol, alpha, p, 0, 0, ncomp, nghost);
478 Saxpy(r, -alpha, q, 0, 0, ncomp, nghost);
484 amrex::Print() << print_ident <<
"MLCGSolver_cg: Iteration"
485 << std::setw(4) << iter
487 << rnorm/(rnorm0) <<
'\n';
490 if ( rnorm < eps_rel*rnorm0 || rnorm < eps_abs ) {
break; }
497 amrex::Print() << print_ident <<
"MLCGSolver_cg: Final Iteration"
498 << std::setw(4) << iter
500 << rnorm/(rnorm0) <<
'\n';
503 if ( ret == 0 && rnorm > eps_rel*rnorm0 && rnorm > eps_abs )
511 if ( ( ret == 0 || ret == 8 ) && (rnorm < rnorm0) )
513 if ( !initial_vec_zeroed ) {
514 LocalAdd(sol, sorig, 0, 0, ncomp, nghost);
516 if (ret == 8) { ret = 9; }
521 if ( !initial_vec_zeroed ) {
522 LocalAdd(sol, sorig, 0, 0, ncomp, nghost);
529template <
typename MF>
535 RT result = Lp.xdoty(amrlev, mglev, r,
z, local);
540template <
typename MF>
544 int ncomp =
nComp(res);
#define BL_PROFILE_VAR_START(vname)
Definition AMReX_BLProfiler.H:573
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:562
#define BL_PROFILE_VAR_STOP(vname)
Definition AMReX_BLProfiler.H:574
#define BL_PROFILE_VAR(fname, vname)
Definition AMReX_BLProfiler.H:571
#define BL_PROFILE_VAR_NS(fname, vname)
Definition AMReX_BLProfiler.H:572
GpuArray< Real, 3 > beta
Definition AMReX_MLEBNodeFDLaplacian.cpp:1099
CG-family solvers (BiCGStab or CG) for use as the bottom solver in MLMG.
Definition AMReX_MLCGSolver.H:21
RT dotxy(const MF &r, const MF &z, bool local=false)
Dot product helper; set local to true to skip the MPI reduction.
Definition AMReX_MLCGSolver.H:531
void setSolver(Type _typ) noexcept
Switch between BiCGStab and CG after construction.
Definition AMReX_MLCGSolver.H:48
bool getInitSolnZeroed() const
Whether setInitSolnZeroed(true) was requested.
Definition AMReX_MLCGSolver.H:101
void setVerbose(int _verbose)
Control how much logging is emitted (0 = silent).
Definition AMReX_MLCGSolver.H:72
int getNGhost()
Current grow-cell count (same in every direction).
Definition AMReX_MLCGSolver.H:110
MLCGSolverT< MF > & operator=(const MLCGSolverT< MF > &rhs)=delete
int getNumIters() const noexcept
Iteration count from the last solve* call (or -1 if unused).
Definition AMReX_MLCGSolver.H:151
int solve_cg(MF &solnL, const MF &rhsL, RT eps_rel, RT eps_abs)
Raw CG implementation mirroring the high-level solve() signature.
Definition AMReX_MLCGSolver.H:385
RT norm_inf(const MF &res, bool local=false)
Infinity norm helper; set local to true to skip the MPI reduction.
Definition AMReX_MLCGSolver.H:542
void setInitSolnZeroed(bool _sol_zeroed)
Definition AMReX_MLCGSolver.H:99
int solve_bicgstab(MF &solnL, const MF &rhsL, RT eps_rel, RT eps_abs)
Raw BiCGStab implementation mirroring the high-level solve() signature.
Definition AMReX_MLCGSolver.H:187
MLCGSolverT(MLCGSolverT< MF > &&rhs)=delete
typename MLLinOpT< MF >::FAB FAB
Definition AMReX_MLCGSolver.H:24
int getMaxIter() const
Current iteration cap.
Definition AMReX_MLCGSolver.H:83
void setPrintIdentation(std::string s)
Prefix printed messages (e.g., to indent per level).
Definition AMReX_MLCGSolver.H:90
int solve(MF &solnL, const MF &rhsL, RT eps_rel, RT eps_abs)
Solve Lp(solnL)=rhsL to the requested tolerance.
Definition AMReX_MLCGSolver.H:176
Type
Definition AMReX_MLCGSolver.H:27
typename MLLinOpT< MF >::RT RT
Definition AMReX_MLCGSolver.H:25
void setNGhost(int _nghost)
Set the number of grow cells used when allocating temporaries.
Definition AMReX_MLCGSolver.H:108
MLCGSolverT(MLLinOpT< MF > &_lp, Type _typ=Type::BiCGStab)
Construct a solver bound to _lp.
Definition AMReX_MLCGSolver.H:168
int getVerbose() const
Current verbosity level.
Definition AMReX_MLCGSolver.H:74
void setMaxIter(int _maxiter)
Cap the number of Krylov iterations performed.
Definition AMReX_MLCGSolver.H:81
MLCGSolverT(const MLCGSolverT< MF > &rhs)=delete
Abstract base class for multilevel linear operators used by MLMG and the bottom solvers.
Definition AMReX_MLLinOp.H:137
typename FabDataType< MF >::fab_type FAB
Definition AMReX_MLLinOp.H:147
typename FabDataType< MF >::value_type RT
Definition AMReX_MLLinOp.H:148
This class provides the user with a few print options.
Definition AMReX_Print.H:35
Arena * The_Async_Arena()
Definition AMReX_Arena.cpp:825
void Sum(Gpu::DeviceVector< T > &v, MPI_Comm comm)
Definition AMReX_GpuParallelReduce.H:37
bool IOProcessor() noexcept
Is this CPU the I/O Processor? To get the rank number, call IOProcessorNumber()
Definition AMReX_ParallelDescriptor.H:289
void Max(KeyValuePair< K, V > &vi, MPI_Comm comm)
Definition AMReX_ParallelReduce.H:133
Definition AMReX_Amr.cpp:50
void Saxpy_Xpay(MF &dst, typename MF::value_type a_saxpy, MF const &src_saxpy, typename MF::value_type a_xpay, MF const &src_xpay, int scomp, int dcomp, int ncomp, IntVect const &nghost)
dst += a_saxpy * src_saxpy followed by dst = src_xpay + a_xpay * dst
Definition AMReX_FabArrayUtility.H:2214
int nComp(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.nComp().
Definition AMReX_FabArrayBase.cpp:2860
void Saxpy_Saxpy(MF &dst1, typename MF::value_type a1, MF const &src1, MF &dst2, typename MF::value_type a2, MF const &src2, int scomp, int dcomp, int ncomp, IntVect const &nghost)
dst1 += a1 * src1 followed by dst2 += a2 * src2
Definition AMReX_FabArrayUtility.H:2223
void Saypy_Saxpy(MF &dst1, typename MF::value_type a1, MF &dst2, typename MF::value_type a2, MF const &src, int scomp, int dcomp, int ncomp, IntVect const &nghost)
dst1 += a1 * dst2 followed by dst2 += a2 * src
Definition AMReX_FabArrayUtility.H:2232
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
IntVect nGrowVect(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.nGrowVect().
Definition AMReX_FabArrayBase.cpp:2865
void LocalCopy(DMF &dst, SMF const &src, int scomp, int dcomp, int ncomp, IntVect const &nghost)
dst = src
Definition AMReX_FabArrayUtility.H:2182
MF::value_type norminf(MF const &mf, int scomp, int ncomp, IntVect const &nghost, bool local=false)
Return the infinity norm, with an MPI maximum unless local is true.
Definition AMReX_FabArrayUtility.H:2262
void Xpay(MF &dst, typename MF::value_type a, MF const &src, int scomp, int dcomp, int ncomp, IntVect const &nghost)
dst = src + a * dst
Definition AMReX_FabArrayUtility.H:2206
void Warning(const std::string &msg)
Print a warning message to the diagnostic stream and keep running.
Definition AMReX.cpp:248
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 LocalAdd(MF &dst, MF const &src, int scomp, int dcomp, int ncomp, IntVect const &nghost)
dst += src
Definition AMReX_FabArrayUtility.H:2190
void setVal(MF &dst, typename MF::value_type val)
dst = val
Definition AMReX_FabArrayUtility.H:2161
FabArray memory allocation information.
Definition AMReX_FabArray.H:73
MFInfo & SetArena(Arena *ar) noexcept
Select the Arena used for FAB storage.
Definition AMReX_FabArray.H:87