IPPL API Reference
Independent Parallel Particle Layer C++ API
Loading...
Searching...
No Matches
PCG.h
1//
2// Class PCG
3// Preconditioned Conjugate Gradient solver algorithm
4//
5
6#ifndef IPPL_PCG_H
7#define IPPL_PCG_H
8
9#include "FEM/FEMVector.h"
10#include "Preconditioner.h"
11#include "SolverAlgorithm.h"
12#include <array>
13#include <algorithm>
14
15namespace ippl {
16 namespace pcg_preconditioner_defaults {
17 inline constexpr int newton_level = 5;
18 inline constexpr int chebyshev_degree = 31;
19 inline constexpr int richardson_iterations = 4;
20 inline constexpr int gauss_seidel_inner = 2;
21 inline constexpr int gauss_seidel_outer = 2;
22 inline constexpr int communication = 0;
23 inline constexpr double ssor_omega = 1.57079632679;
24
25 inline constexpr std::array<const char*, 7> valid_types = {
26 "jacobi", "newton", "chebyshev", "richardson", "richardson_alt", "gauss-seidel", "ssor"
27 };
28
29 inline bool is_valid_type(const std::string& type) {
30 return std::find(valid_types.begin(), valid_types.end(), type) != valid_types.end();
31 }
32 } // namespace pcg_preconditioner_defaults
33
34 template <typename OperatorRet, typename LowerRet, typename UpperRet, typename UpperLowerRet,
35 typename InverseDiagRet, typename DiagRet, typename FieldLHS,
36 typename FieldRHS = FieldLHS>
37 class CG : public SolverAlgorithm<FieldLHS, FieldRHS> {
39 typedef typename Base::lhs_type::value_type T;
40
41 public:
42 using typename Base::lhs_type, typename Base::rhs_type;
43 using OperatorF = std::function<OperatorRet(lhs_type&)>;
44 using LowerF = std::function<LowerRet(lhs_type&)>;
45 using UpperF = std::function<UpperRet(lhs_type&)>;
46 using UpperLowerF = std::function<UpperLowerRet(lhs_type&)>;
47 using InverseDiagF = std::function<InverseDiagRet(lhs_type&)>;
48 using DiagF = std::function<DiagRet(lhs_type&)>;
49 using mesh_type = typename lhs_type::Mesh_t;
50 using layout_type = typename lhs_type::Layout_t;
51
52 virtual ~CG() = default;
53
54 /*
55 * Initializes the fields needed for CG operations
56 * and avoids allocating them at each solve step.
57 * @param mesh The mesh to initialize the field with
58 * @param layout The layout to initialize the field with
59 */
60 virtual void initializeFields(mesh_type& mesh, layout_type& layout) {
61 r.initialize(mesh, layout);
62 d.initialize(mesh, layout);
63 q.initialize(mesh, layout);
64 }
65
70 virtual void setOperator(OperatorF op) { op_m = std::move(op); }
71 virtual void setPreconditioner(
72 [[maybe_unused]] OperatorF&& op, // Operator passed to chebyshev and newton
73 [[maybe_unused]] LowerF&& lower, // Operator passed to 2-step gauss-seidel and ssor
74 [[maybe_unused]] UpperF&& upper, // Operator passed to 2-step gauss-seidel and ssor
75 [[maybe_unused]] UpperLowerF&&
76 upper_and_lower, // Operator passed to 2-step gauss-seidel
77 [[maybe_unused]] InverseDiagF&&
78 inverse_diagonal, // Operator passed to jacobi, 2-step gauss-seidel and ssor
79 [[maybe_unused]] DiagF&& diagonal, // Operator passed to SSOR
80 [[maybe_unused]] double alpha, // smallest eigenvalue of the operator
81 [[maybe_unused]] double beta, // largest eigenvalue of the operator
82 [[maybe_unused]] std::string preconditioner_type =
83 "", // Name of the preconditioner that should be used
84 [[maybe_unused]] int level =
85 pcg_preconditioner_defaults::newton_level, // This is a dummy default parameter, actual default parameter should be
86 // set in main
87 [[maybe_unused]] int degree =
88 pcg_preconditioner_defaults::chebyshev_degree, // This is a dummy default parameter, actual default parameter should
89 // be set in main
90 [[maybe_unused]] int richardson_iterations =
91 pcg_preconditioner_defaults::richardson_iterations, // This is a dummy default parameter, actual default
92 // parameter should be set in main
93 [[maybe_unused]] int inner =
94 pcg_preconditioner_defaults::gauss_seidel_inner, // This is a dummy default parameter, actual default parameter should be
95 // set in main
96 [[maybe_unused]] int outer =
97 pcg_preconditioner_defaults::gauss_seidel_outer, // This is a dummy default parameter, actual default parameter should be
98 [[maybe_unused]] double omega = pcg_preconditioner_defaults::ssor_omega // This is a dummy default parameter, actual default
99 // parameter should be set in main
100 ) {}
106 virtual int getIterationCount() { return iterations_m; }
107
108 virtual void operator()(lhs_type& lhs, rhs_type& rhs,
109 const ParameterList& params) override {
110 constexpr unsigned Dim = lhs_type::dim;
111
112 static IpplTimings::TimerRef cg_ops = IpplTimings::getTimer("CG");
113 static IpplTimings::TimerRef up_layout = IpplTimings::getTimer("updateLayout");
114 static IpplTimings::TimerRef apply = IpplTimings::getTimer("applyOp");
115 static IpplTimings::TimerRef inner = IpplTimings::getTimer("innerProduct");
116
117 IpplTimings::startTimer(cg_ops);
118
119 iterations_m = 0;
120 const int maxIterations = params.get<int>("max_iterations");
121
122 // Variable names mostly based on description in
123 // https://www.cs.cmu.edu/~quake-papers/painless-conjugate-gradient.pdf
124 IpplTimings::startTimer(up_layout);
125 r.updateLayout(lhs.getLayout());
126 d.updateLayout(lhs.getLayout());
127 q.updateLayout(lhs.getLayout());
128 IpplTimings::stopTimer(up_layout);
129
130 using bc_type = BConds<lhs_type, Dim>;
131 bc_type lhsBCs = lhs.getFieldBC();
132 bc_type bc;
133
134 bool allFacesPeriodic = true;
135 for (unsigned int i = 0; i < 2 * Dim; ++i) {
136 FieldBC bcType = lhsBCs[i]->getBCType();
137 if (bcType == PERIODIC_FACE) {
138 // If the LHS has periodic BCs, so does the residue
139 bc[i] = std::make_shared<PeriodicFace<lhs_type>>(i);
140 } else if (bcType & CONSTANT_FACE) {
141 // If the LHS has constant BCs, the residue is zero on the BCs
142 // Bitwise AND with CONSTANT_FACE will succeed for ZeroFace or ConstantFace
143 bc[i] = std::make_shared<ZeroFace<lhs_type>>(i);
144 allFacesPeriodic = false;
145 } else {
146 throw IpplException("PCG::operator()",
147 "Only periodic or constant BCs for LHS supported.");
148 return;
149 }
150 }
151
152 IpplTimings::startTimer(apply);
153 r = rhs - op_m(lhs);
154 IpplTimings::stopTimer(apply);
155
156 d = r.deepCopy();
157 d.setFieldBC(bc);
158
159 IpplTimings::startTimer(inner);
160 T delta1 = innerProduct(r, d);
161 IpplTimings::stopTimer(inner);
162 T delta0 = delta1;
163 residueNorm = Kokkos::sqrt(delta1);
164 const T tolerance = params.get<T>("tolerance") * norm(rhs);
165
166 while (iterations_m < maxIterations && residueNorm > tolerance) {
167 IpplTimings::startTimer(apply);
168 q = op_m(d);
169 IpplTimings::stopTimer(apply);
170
171 IpplTimings::startTimer(inner);
172 T alpha = delta1 / innerProduct(d, q);
173 IpplTimings::stopTimer(inner);
174 lhs = lhs + alpha * d;
175
176 // The exact residue is given by
177 // r = rhs - op_m(lhs);
178 // This correction is generally not used in practice because
179 // applying the Laplacian is computationally expensive and
180 // the correction does not have a significant effect on accuracy;
181 // in some implementations, the correction may be applied every few
182 // iterations to offset accumulated floating point errors
183 r = r - alpha * q;
184 delta0 = delta1;
185 IpplTimings::startTimer(inner);
186 delta1 = innerProduct(r, r);
187 IpplTimings::stopTimer(inner);
188 T beta = delta1 / delta0;
189
190 residueNorm = Kokkos::sqrt(delta1);
191 d = r + beta * d;
192 ++iterations_m;
193 }
194
195 if (allFacesPeriodic) {
196 T avg = lhs.getVolumeAverage();
197 lhs = lhs - avg;
198 }
199 IpplTimings::stopTimer(cg_ops);
200 }
201
202 virtual T getResidue() const { return residueNorm; }
203
204 protected:
205 OperatorF op_m;
206 T residueNorm = 0;
207 int iterations_m = 0;
208
209 // Workspaces, allocated once via initializeFields() and reused across
210 // solves. Protected so derived solvers (e.g. PCG) can extend the
211 // workspace set without redeclaring r, d, q as locals on every
212 // operator() call.
213 lhs_type r;
214 lhs_type d;
215 lhs_type q;
216 };
217
218 template <typename OperatorRet, typename LowerRet, typename UpperRet, typename UpperLowerRet,
219 typename InverseDiagRet, typename T>
220 class CG<OperatorRet, LowerRet, UpperRet, UpperLowerRet, InverseDiagRet, FEMVector<T>,
221 FEMVector<T>> : public SolverAlgorithm<FEMVector<T>, FEMVector<T>> {
223
224 public:
225 using typename Base::lhs_type, typename Base::rhs_type;
226 using OperatorF = std::function<OperatorRet(lhs_type&)>;
227 using LowerF = std::function<LowerRet(lhs_type&)>;
228 using UpperF = std::function<UpperRet(lhs_type&)>;
229 using UpperLowerF = std::function<UpperLowerRet(lhs_type&)>;
230 using InverseDiagF = std::function<InverseDiagRet(lhs_type&)>;
231
232 virtual ~CG() = default;
233
238 virtual void setOperator(OperatorF op) { op_m = std::move(op); }
239 virtual void setPreconditioner(
240 [[maybe_unused]] OperatorF&& op, // Operator passed to chebyshev and newton
241 [[maybe_unused]] LowerF&& lower, // Operator passed to 2-step gauss-seidel
242 [[maybe_unused]] UpperF&& upper, // Operator passed to 2-step gauss-seidel
243 [[maybe_unused]] UpperLowerF&&
244 upper_and_lower, // Operator passed to 2-step gauss-seidel
245 [[maybe_unused]] InverseDiagF&&
246 inverse_diagonal, // Operator passed to jacobi and 2-step gauss-seidel
247 [[maybe_unused]] double alpha, // smallest eigenvalue of the operator
248 [[maybe_unused]] double beta, // largest eigenvalue of the operator
249 [[maybe_unused]] std::string preconditioner_type =
250 "", // Name of the preconditioner that should be used
251 [[maybe_unused]] int level =
252 pcg_preconditioner_defaults::newton_level, // This is a dummy default parameter, actual default parameter should be
253 // set in main
254 [[maybe_unused]] int degree =
255 pcg_preconditioner_defaults::chebyshev_degree, // This is a dummy default parameter, actual default parameter should
256 // be set in main
257 [[maybe_unused]] int richardson_iterations =
258 pcg_preconditioner_defaults::richardson_iterations, // This is a dummy default parameter, actual default
259 // parameter should be set in main
260 [[maybe_unused]] int inner =
261 pcg_preconditioner_defaults::gauss_seidel_inner, // This is a dummy default parameter, actual default parameter should be
262 // set in main
263 [[maybe_unused]] int outer = pcg_preconditioner_defaults::gauss_seidel_outer // This is a dummy default parameter, actual default
264 // parameter should be set in main
265 ) {}
271 virtual int getIterationCount() { return iterations_m; }
272
273 virtual void operator()(lhs_type& lhs, rhs_type& rhs,
274 const ParameterList& params) override {
275 // constexpr unsigned Dim = lhs_type::dim;
276 // typename lhs_type::Mesh_t& mesh = lhs.get_mesh();
277 // typename lhs_type::Layout_t& layout = lhs.getLayout();
278
279 iterations_m = 0;
280 const int maxIterations = params.get<int>("max_iterations");
281
282 // Variable names mostly based on description in
283 // https://www.cs.cmu.edu/~quake-papers/painless-conjugate-gradient.pdf
284 lhs_type r = lhs.deepCopy();
285 r = 0;
286 lhs_type d = lhs.deepCopy();
287 d = 0;
288
289 r = rhs - op_m(lhs);
290 r.setHalo(0);
291 d = r; //.deepCopy();
292 // d.setFieldBC(bc);
293 T delta1 = innerProduct(r, d);
294 T delta0 = delta1;
295 residueNorm = Kokkos::sqrt(delta1);
296 const T tolerance = params.get<T>("tolerance") * norm(rhs);
297
298 lhs_type q = lhs.deepCopy();
299 q = 0;
300
301 while (iterations_m < maxIterations && residueNorm > tolerance) {
302 q = op_m(d);
303 d.setHalo(0);
304 T alpha = delta1 / innerProduct(d, q);
305 lhs = lhs + alpha * d;
306
307 // The exact residue is given by
308 // r = rhs - op_m(lhs);
309 // This correction is generally not used in practice because
310 // applying the Laplacian is computationally expensive and
311 // the correction does not have a significant effect on accuracy;
312 // in some implementations, the correction may be applied every few
313 // iterations to offset accumulated floating point errors
314 r = r - alpha * q;
315 delta0 = delta1;
316 r.setHalo(0);
317 delta1 = innerProduct(r, r);
318 T beta = delta1 / delta0;
319
320 residueNorm = Kokkos::sqrt(delta1);
321 d = r + beta * d;
322 ++iterations_m;
323 }
324 }
325
326 virtual T getResidue() const { return residueNorm; }
327
328 protected:
329 OperatorF op_m;
330 T residueNorm = 0;
331 int iterations_m = 0;
332 };
333
334 template <typename OperatorRet, typename LowerRet, typename UpperRet, typename UpperLowerRet,
335 typename InverseDiagRet, typename DiagRet, typename FieldLHS,
336 typename FieldRHS = FieldLHS>
337 class PCG : public CG<OperatorRet, LowerRet, UpperRet, UpperLowerRet, InverseDiagRet, DiagRet,
338 FieldLHS, FieldRHS> {
340 typedef typename Base::lhs_type::value_type T;
341
342 public:
343 using typename Base::lhs_type, typename Base::rhs_type;
344 using OperatorF = std::function<OperatorRet(lhs_type&)>;
345 using LowerF = std::function<LowerRet(lhs_type&)>;
346 using UpperF = std::function<UpperRet(lhs_type&)>;
347 using UpperLowerF = std::function<UpperLowerRet(lhs_type&)>;
348 using InverseDiagF = std::function<InverseDiagRet(lhs_type&)>;
349 using DiagF = std::function<DiagRet(lhs_type&)>;
350
351 using mesh_type = typename lhs_type::Mesh_t;
352 using layout_type = typename lhs_type::Layout_t;
353
354 PCG()
355 : CG<OperatorRet, LowerRet, UpperRet, UpperLowerRet, InverseDiagRet, DiagRet, FieldLHS,
356 FieldRHS>()
357 , preconditioner_m(nullptr) {};
358
359 void initializeFields(mesh_type& mesh, layout_type& layout) override {
360 CG<OperatorRet, LowerRet, UpperRet, UpperLowerRet, InverseDiagRet, DiagRet, FieldLHS,
361 FieldRHS>::initializeFields(mesh, layout);
362 s.initialize(mesh, layout);
363 pcond_out.initialize(mesh, layout);
364 }
365
371 OperatorF&& op, // Operator passed to chebyshev and newton
372 LowerF&& lower, // Operator passed to 2-step gauss-seidel
373 UpperF&& upper, // Operator passed to 2-step gauss-seidel
374 UpperLowerF&& upper_and_lower, // Operator passed to 2-step gauss-seidel
375 InverseDiagF&& inverse_diagonal, // Operator passed to jacobi and 2-step gauss-seidel
376 DiagF&& diagonal, // Operator passed to ssor
377 double alpha, // smallest eigenvalue of the operator
378 double beta, // largest eigenvalue of the operator
379 std::string preconditioner_type = "", // Name of the preconditioner that should be used
380 int level = pcg_preconditioner_defaults::newton_level, // This is a dummy default parameter, actual default parameter should be
381 // set in main
382 int degree = pcg_preconditioner_defaults::chebyshev_degree, // This is a dummy default parameter, actual default parameter should
383 // be set in main
384 int richardson_iterations = pcg_preconditioner_defaults::richardson_iterations, // This is a dummy default parameter, actual default
385 // parameter should be set in main
386 int inner = pcg_preconditioner_defaults::gauss_seidel_inner, // This is a dummy default parameter, actual default parameter should be
387 // set in main
388 int outer = pcg_preconditioner_defaults::gauss_seidel_outer, // This is a dummy default parameter, actual default parameter should be
389 // set in main
390 double omega = pcg_preconditioner_defaults::ssor_omega // This is a dummy default parameter, actual default
391 // parameter should be set in main
392 // default = pi/2 as this was found optimal during hyperparameter scan for test case
393 // (see
394 // https://amas.web.psi.ch/people/aadelmann/ETH-Accel-Lecture-1/projectscompleted/cse/BSc-mbolliger.pdf)
395 ) override {
396 if (preconditioner_type == "jacobi") {
397 // Turn on damping parameter
398 /*
399 double w = 2.0 / ((alpha + beta));
400 preconditioner_m = std::move(std::make_unique<jacobi_preconditioner<FieldLHS ,
401 InverseDiagF>>(std::move(inverse_diagonal), w));
402 */
403 preconditioner_m =
404 std::move(std::make_unique<jacobi_preconditioner<FieldLHS, InverseDiagF>>(
405 std::move(inverse_diagonal)));
406 } else if (preconditioner_type == "newton") {
407 preconditioner_m = std::move(
409 std::move(op), alpha, beta, level, 1e-3));
410 } else if (preconditioner_type == "chebyshev") {
411 preconditioner_m = std::move(
413 std::move(op), alpha, beta, degree, 1e-3));
414 } else if (preconditioner_type == "richardson") {
415 preconditioner_m =
416 std::move(std::make_unique<
418 std::move(upper_and_lower), std::move(inverse_diagonal),
419 richardson_iterations));
420 } else if (preconditioner_type == "richardson_alt") {
421 preconditioner_m =
422 std::move(std::make_unique<
424 std::move(op), std::move(inverse_diagonal), richardson_iterations));
425 } else if (preconditioner_type == "gauss-seidel") {
426 preconditioner_m = std::move(
428 std::move(lower), std::move(upper), std::move(inverse_diagonal), inner,
429 outer));
430 } else if (preconditioner_type == "ssor") {
431 preconditioner_m =
432 std::move(std::make_unique<
434 std::move(lower), std::move(upper), std::move(inverse_diagonal),
435 std::move(diagonal), inner, outer, omega));
436 } else {
437 preconditioner_m = std::move(std::make_unique<preconditioner<FieldLHS>>());
438 }
439 }
440
441 void operator()(lhs_type& lhs, rhs_type& rhs, const ParameterList& params) override {
442 constexpr unsigned Dim = lhs_type::dim;
443
444 if (preconditioner_m == nullptr) {
445 throw IpplException("PCG::operator()",
446 "Preconditioner has not been set for PCG solver");
447 }
448
449 this->iterations_m = 0;
450 const int maxIterations = params.get<int>("max_iterations");
451
452 // Variable names mostly based on description in
453 // https://www.cs.cmu.edu/~quake-papers/painless-conjugate-gradient.pdf
454 // Field layouts are updated such that we don't keep a stale domain decomposition
455 // if the lhs layout has been changed during the simulation, for example by the load
456 // balancer.
457 this->r.updateLayout(lhs.getLayout());
458 this->d.updateLayout(lhs.getLayout());
459 s.updateLayout(lhs.getLayout());
460 pcond_out.updateLayout(lhs.getLayout());
461 this->q.updateLayout(lhs.getLayout());
462
463 // Each preconditioner's init_fields() is responsible for being
464 // cheap on the steady-state path (refreshing layout in-place, not
465 // reallocating).
466 preconditioner_m->init_fields(lhs);
467
468 using bc_type = BConds<lhs_type, Dim>;
469 bc_type lhsBCs = lhs.getFieldBC();
470 bc_type bc;
471
472 bool allFacesPeriodic = true;
473 for (unsigned int i = 0; i < 2 * Dim; ++i) {
474 FieldBC bcType = lhsBCs[i]->getBCType();
475 if (bcType == PERIODIC_FACE) {
476 // If the LHS has periodic BCs, so does the residue
477 bc[i] = std::make_shared<PeriodicFace<lhs_type>>(i);
478 } else if (bcType & CONSTANT_FACE) {
479 // If the LHS has constant BCs, the residue is zero on the BCs
480 // Bitwise AND with CONSTANT_FACE will succeed for ZeroFace or ConstantFace
481 bc[i] = std::make_shared<ZeroFace<lhs_type>>(i);
482 allFacesPeriodic = false;
483 } else {
484 throw IpplException("PCG::operator()",
485 "Only periodic or constant BCs for LHS supported.");
486 return;
487 }
488 }
489
490 this->r = rhs - this->op_m(lhs);
491 (*preconditioner_m)(this->r, pcond_out);
492 this->d = T(1) * pcond_out;
493 this->d.setFieldBC(bc);
494
495 T delta1 = innerProduct(this->r, this->d);
496 T delta0 = delta1;
497 this->residueNorm = Kokkos::sqrt(Kokkos::abs(delta1));
498 const T tolerance = params.get<T>("tolerance") * this->residueNorm;
499
500 while (this->iterations_m<maxIterations&& this->residueNorm> tolerance) {
501 // op_m(d) writes its expression into q's existing storage; no
502 // allocation, no per-iteration deep copy.
503 this->q = this->op_m(this->d);
504 T alpha = delta1 / innerProduct(this->d, this->q);
505 lhs = lhs + alpha * this->d;
506
507 // The exact residue is given by
508 // r = rhs - BaseCG::op_m(lhs);
509 // This correction is generally not used in practice because
510 // applying the Laplacian is computationally expensive and
511 // the correction does not have a significant effect on accuracy;
512 // in some implementations, the correction may be applied every few
513 // iterations to offset accumulated floating point errors
514 this->r = this->r - alpha * this->q;
515 // s := M^{-1} r; preconditioner writes into s (NoBcFace).
516 (*preconditioner_m)(this->r, s);
517
518 delta0 = delta1;
519 delta1 = innerProduct(this->r, s);
520
521 T beta = delta1 / delta0;
522 this->residueNorm = Kokkos::sqrt(Kokkos::abs(delta1));
523
524 this->d = s + beta * this->d;
525 ++this->iterations_m;
526 }
527
528 if (allFacesPeriodic) {
529 T avg = lhs.getVolumeAverage();
530 lhs = lhs - avg;
531 }
532 }
533
534 protected:
535 std::unique_ptr<preconditioner<FieldLHS>> preconditioner_m;
536
537 /*
538 * Extends the CG workspace with the preconditioner result buffers s and
539 * pcond_out so operator() does not allocate per solve.
540 * Preconditioner result buffers, allocated once via initializeFields()
541 * pcond_out keeps its default NoBcFace BCs: the preconditioner's internal operator
542 * chain therefore never triggers PeriodicFace::apply MPI calls -- if it
543 * did, the global MPI sequence would diverge from the master code path
544 * (where the preconditioner returned a fresh NoBcFace field) and
545 * intermittent multi-rank halo deadlocks would follow.
546 */
547
548 lhs_type s;
549 lhs_type pcond_out;
550 };
551
552}; // namespace ippl
553
554#endif
Definition IpplException.h:6
Definition BConds.h:23
virtual void operator()(lhs_type &lhs, rhs_type &rhs, const ParameterList &params) override
Definition PCG.h:273
Definition PCG.h:37
virtual int getIterationCount()
Definition PCG.h:106
virtual void setOperator(OperatorF op)
Definition PCG.h:70
virtual void operator()(lhs_type &lhs, rhs_type &rhs, const ParameterList &params) override
Definition PCG.h:108
1D vector used in the context of FEM.
Definition FEMVector.h:34
FEMVector< T > deepCopy() const
Create a deep copy, where all the information of this vector is copied to a new one.
Definition FEMVector.hpp:234
void setHalo(T setValue)
Set the halo cells to setValue.
Definition FEMVector.hpp:152
Definition PCG.h:338
void setPreconditioner(OperatorF &&op, LowerF &&lower, UpperF &&upper, UpperLowerF &&upper_and_lower, InverseDiagF &&inverse_diagonal, DiagF &&diagonal, double alpha, double beta, std::string preconditioner_type="", int level=pcg_preconditioner_defaults::newton_level, int degree=pcg_preconditioner_defaults::chebyshev_degree, int richardson_iterations=pcg_preconditioner_defaults::richardson_iterations, int inner=pcg_preconditioner_defaults::gauss_seidel_inner, int outer=pcg_preconditioner_defaults::gauss_seidel_outer, double omega=pcg_preconditioner_defaults::ssor_omega) override
Definition PCG.h:370
void operator()(lhs_type &lhs, rhs_type &rhs, const ParameterList &params) override
Definition PCG.h:441
Definition ParameterList.h:29
T get(const std::string &key) const
Definition ParameterList.h:59
Definition SolverAlgorithm.h:16
Definition Archive.h:20
KOKKOS_INLINE_FUNCTION constexpr decltype(auto) apply(const View &view, const Coords &coords)
Definition IpplOperations.h:64
T innerProduct(const FEMVector< T > &a, const FEMVector< T > &b)
Calculate the inner product between two ippl::FEMVector(s).
Definition FEMVector.h:407
Definition Preconditioner.h:503
Definition Preconditioner.h:69
Definition Preconditioner.h:245
Definition Preconditioner.h:109
Definition Preconditioner.h:32
Definition Preconditioner.h:434
Definition Preconditioner.h:367
Definition Preconditioner.h:598