57template <
class T,
class Ops>
62 using RT =
typename T::value_type;
73 void Define (const T&, Ops*) override;
75 void Update (const T& a_U) override;
80 void Apply (T&, const T&) override;
132template <
class T,
class Ops>
135 using namespace amrex;
137 Print() << pc_name <<
" verbose: " << (
m_verbose?
"true":
"false") <<
"\n";
141 Print() << pc_name <<
" absolute tolerance: " <<
m_atol <<
"\n";
142 Print() << pc_name <<
" relative tolerance: " <<
m_rtol <<
"\n";
145template <
class T,
class Ops>
155 pp.query(
"absolute_tolerance",
m_atol);
156 pp.query(
"relative_tolerance",
m_rtol);
159template <
class T,
class Ops>
164 const auto& geom =
m_ops->GetGeometry(n);
165 for (
int dim = 0; dim < 3; dim++) {
169 m_x_ghost[n][dim].FillBoundary(geom.periodicity());
174template <
class T,
class Ops>
177 using namespace amrex;
178 auto& b_mfarrvec = a_b.getArrayVec();
179 auto& x_mfarrvec = a_x.getArrayVec();
183 for (
int dim = 0; dim < 3; dim++) {
184 const auto& b_mf = *(b_mfarrvec[n][dim]);
185 const auto& a_mf = *((*m_bcoefs)[n][dim]);
186 const int ncomp = a_mf.nComp();
191 for (
int d = 0; d < AMREX_SPACEDIM; d++) {
192 nc[d] =
m_ops->GetMassMatricesPCnComp(dim, d);
193 w[d] = (nc[d] - 1) / 2;
199 using ReduceTuple =
typename decltype(reduce_data)::Type;
203 ?
m_x_ghost[n][dim] : *(x_mfarrvec[n][dim]);
205 for (
MFIter mfi(b_mf); mfi.isValid(); ++mfi) {
206 const Box bx = mfi.validbox();
207 auto xg_arr = xg_mf.const_array(mfi);
208 auto b_arr = b_mf.const_array(mfi);
209 auto a_arr = a_mf.const_array(mfi);
212 auto x_arr = x_mfarrvec[n][dim]->const_array(mfi);
213 reduce_op.
eval(bx, reduce_data,
216 const RT Ax = x_arr(i,j,k) * (
RT(1.0) + a_arr(i,j,k,0));
217 const RT r = b_arr(i,j,k) - Ax;
221 reduce_op.
eval(bx, reduce_data,
226 for (
int c2 = 0; c2 < nc[2]; c2++) {
227 const int kk = k + c2 - w[2];
228 for (
int c1 = 0; c1 < nc[1]; c1++) {
229 const int jj = j + c1 - w[1];
230 for (
int c0 = 0; c0 < nc[0]; c0++) {
231 const int ii = i + c0 - w[0];
232 mx += a_arr(i,j,k,comp) * xg_arr(ii,jj,kk);
237 const RT Ax = xg_arr(i,j,k) + mx;
238 const RT r = b_arr(i,j,k) - Ax;
245 res_sq += dim_res_sq;
248 return std::sqrt(res_sq);
251template <
class T,
class Ops>
256 using namespace amrex;
260 "JacobiPC::Define() called on defined object" );
263 "JacobiPC::Define(): a_ops is nullptr" );
266 "JacobiPC::Define() must be called with Efield_fp type");
277template <
class T,
class Ops>
281 using namespace amrex;
285 "JacobiPC::Update() called on undefined object" );
288 auto& u_mfarrvec = a_U.getArrayVec();
295 for (
int dim = 0; dim < 3; dim++) {
298 for (
int d = 0; d < AMREX_SPACEDIM; d++) {
299 const int nc_d =
m_ops->GetMassMatricesPCnComp(dim, d);
300 const int w_d = (nc_d - 1) / 2;
309 for (
int dim = 0; dim < 3; dim++) {
327 <<
": theta*dt = " << this->
m_dt <<
"\n";
331template <
class T,
class Ops>
335 using namespace amrex;
339 "JacobiPC::Apply() called on undefined object" );
342 "JacobiPC::Apply() - a_x must be Efield_fp type");
345 "JacobiPC::Apply() - a_b must be Efield_fp type");
352 auto& b_mfarrvec = a_b.getArrayVec();
353 auto& x_mfarrvec = a_x.getArrayVec();
356 "Error in JacobiPC::Apply() - mismatch in number of levels." );
361 for (
int adapt = 0; adapt <= max_omega_reductions; adapt++) {
365 for (
int dim = 0; dim < 3; dim++) {
366 const auto& b_mf = *(b_mfarrvec[n][dim]);
367 const auto& a_mf = *((*m_bcoefs)[n][dim]);
368 auto& x_mf = *(x_mfarrvec[n][dim]);
369 const int diag_comp = (a_mf.nComp() - 1) / 2;
372 const Box bx = mfi.tilebox();
373 auto x_arr = x_mf.array(mfi);
374 auto b_arr = b_mf.const_array(mfi);
375 auto a_arr = a_mf.const_array(mfi);
380 x_arr(i,j,k) = b_arr(i,j,k)
381 / (
RT(1.0) + a_arr(i,j,k,diag_comp));
389 const RT bnorm = a_b.norm2();
391 amrex::Print() <<
" pc_jacobi (diag): residual = " << res
392 <<
", " << res / std::max(bnorm,
RT(1.e-30))
400 const RT bnorm = a_b.norm2();
405 amrex::Print() <<
" pc_jacobi: iter = 0, residual = " << res0
406 <<
", " << res0 / std::max(bnorm,
RT(1.e-30))
407 <<
" (rel.), omega = " << omega <<
"\n";
410 bool diverged =
false;
412 for (
int iter = 0; iter <
m_max_iter; iter++) {
417 for (
int dim = 0; dim < 3; dim++) {
418 const auto& b_mf = *(b_mfarrvec[n][dim]);
419 const auto& a_mf = *((*m_bcoefs)[n][dim]);
420 auto& x_mf = *(x_mfarrvec[n][dim]);
421 auto& w_mf =
m_work[n][dim];
424 const int ncomp = a_mf.nComp();
425 if (ncomp <= 1) {
continue; }
427 const int diag_comp = (ncomp - 1) / 2;
431 for (
int d = 0; d < AMREX_SPACEDIM; d++) {
432 nc[d] =
m_ops->GetMassMatricesPCnComp(dim, d);
433 w[d] = (nc[d] - 1) / 2;
440 const Box bx = mfi.tilebox();
441 auto w_arr = w_mf.array(mfi);
442 auto xg_arr = xg_mf.const_array(mfi);
443 auto a_arr = a_mf.const_array(mfi);
450 for (
int c2 = 0; c2 < nc[2]; c2++) {
451 const int kk = k + c2 - w[2];
452 for (
int c1 = 0; c1 < nc[1]; c1++) {
453 const int jj = j + c1 - w[1];
454 for (
int c0 = 0; c0 < nc[0]; c0++) {
455 const int ii = i + c0 - w[0];
456 mx += a_arr(i,j,k,comp)
462 w_arr(i,j,k) = xg_arr(i,j,k) + mx;
468 const Box bx = mfi.tilebox();
469 auto x_arr = x_mf.array(mfi);
470 auto b_arr = b_mf.const_array(mfi);
471 auto w_arr = w_mf.const_array(mfi);
472 auto a_arr = a_mf.const_array(mfi);
477 const RT r = b_arr(i,j,k) - w_arr(i,j,k);
478 x_arr(i,j,k) += om * r
479 / (
RT(1.0) + a_arr(i,j,k,diag_comp));
490 <<
", residual = " << res_norm
491 <<
", " << res_norm / std::max(bnorm,
RT(1.e-30))
499 <<
"reducing omega to " << omega <<
"\n";
516 if (!diverged) {
break; }
@ pc_jacobi
Definition PreconditionerLibrary.H:14
#define WARPX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition TextMsg.H:13
bool m_is_defined
Definition JacobiPC.H:99
JacobiPC(JacobiPC &&) noexcept=delete
void Apply(T &, const T &) override
Solve (I + M) x = b via damped Jacobi iteration.
Definition JacobiPC.H:332
void printParameters() const override
Print parameters.
Definition JacobiPC.H:133
int m_stencil_width
Definition JacobiPC.H:121
void copyToGhostAndFill(const amrex::Vector< amrex::Array< amrex::MultiFab *, 3 > > &a_x_mfarrvec)
Definition JacobiPC.H:160
~JacobiPC() override=default
RT m_rtol
Definition JacobiPC.H:107
amrex::Array< amrex::MultiFab, 3 > MFArr
Definition JacobiPC.H:97
RT m_omega
Definition JacobiPC.H:103
const amrex::Vector< amrex::Array< amrex::MultiFab *, 3 > > * m_bcoefs
Definition JacobiPC.H:113
bool m_has_offdiag
Definition JacobiPC.H:115
Ops * m_ops
Definition JacobiPC.H:109
JacobiPC(const JacobiPC &)=delete
typename T::value_type RT
Definition JacobiPC.H:62
bool m_adaptive_omega
Definition JacobiPC.H:104
bool m_work_defined
Definition JacobiPC.H:116
amrex::Vector< amrex::Array< amrex::MultiFab, 3 > > m_work
Definition JacobiPC.H:118
RT computeResidualNorm(const T &a_x, const T &a_b) const
Compute ||b - (I+M)*x|| for residual monitoring. Uses the ghost-padded m_x_ghost (which must already ...
Definition JacobiPC.H:175
void Update(const T &a_U) override
Update the preconditioner.
Definition JacobiPC.H:278
amrex::Vector< amrex::Array< amrex::MultiFab, 3 > > m_x_ghost
Definition JacobiPC.H:119
int m_num_amr_levels
Definition JacobiPC.H:111
void readParameters()
Definition JacobiPC.H:146
int m_max_iter
Definition JacobiPC.H:102
RT m_atol
Definition JacobiPC.H:106
JacobiPC & operator=(const JacobiPC &)=delete
void Define(const T &, Ops *) override
Define the preconditioner.
Definition JacobiPC.H:252
bool m_verbose
Definition JacobiPC.H:101
bool IsDefined() const override
Check if the nonlinear solver has been defined.
Definition JacobiPC.H:84
RT m_dt
Definition Preconditioner.H:117
Preconditioner()=default
Default constructor.
__host__ static __device__ constexpr IntVectND< dim > TheZeroVector() noexcept
static void Copy(MultiFab &dst, const MultiFab &src, int srccomp, int dstcomp, int numcomp, int nghost)
std::enable_if_t< IsFabArray< MF >::value > eval(MF const &mf, IntVect const &nghost, D &reduce_data, F &&f)
void Sum(T &v, MPI_Comm comm)
MPI_Comm CommunicatorSub() noexcept
int nComp(FabArrayBase const &fa)
std::enable_if_t< std::is_integral_v< T > > ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
DistributionMapping const & DistributionMap(FabArrayBase const &fa)
std::string getEnumNameString(T const &v)
bool TilingIfNotGPU() noexcept
BoxArray const & boxArray(FabArrayBase const &fa)
__host__ __device__ constexpr int get(IntVectND< dim > const &iv) noexcept
@ Efield_fp
Definition Fields.H:97