MFEM  v4.6.0
Finite element discretization library
ginkgo.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #ifndef MFEM_GINKGO
13 #define MFEM_GINKGO
14 
15 #include "../config/config.hpp"
16 
17 #ifdef MFEM_USE_GINKGO
18 
19 #include "operator.hpp"
20 #include "sparsemat.hpp"
21 #include "solvers.hpp"
22 
23 #include <ginkgo/ginkgo.hpp>
24 
25 #include <iomanip>
26 #include <ios>
27 #include <string>
28 #include <vector>
29 #include <fstream>
30 #include <iostream>
31 
32 #define MFEM_GINKGO_VERSION \
33  ((GKO_VERSION_MAJOR*100 + GKO_VERSION_MINOR)*100 + GKO_VERSION_PATCH)
34 
35 namespace mfem
36 {
37 namespace Ginkgo
38 {
39 
40 /// The alias 'gko_array' refers to 'gko::Array' (Ginkgo < 1.5.0) or
41 /// 'gko::array' (Ginkgo >= 1.5.0).
42 #if MFEM_GINKGO_VERSION < 10500
43 template <typename T> using gko_array = gko::Array<T>;
44 #else
45 template <typename T> using gko_array = gko::array<T>;
46 #endif
47 
48 /**
49 * Helper class for a case where a wrapped MFEM Vector
50 * should be owned by Ginkgo, and deleted when the wrapper
51 * object goes out of scope.
52 */
53 template <typename T>
55 {
56 public:
57  using pointer = T *;
58 
59  // Destroys an MFEM object. Requires object to have a Destroy() method.
60  void operator()(pointer ptr) const noexcept { ptr->Destroy(); }
61 };
62 
63 /**
64 * This class wraps an MFEM vector object for Ginkgo's use. It
65 * allows Ginkgo and MFEM to operate directly on the same
66 * data, and is necessary to use MFEM Operators with Ginkgo
67 * solvers.
68 *
69 * @ingroup Ginkgo
70 */
71 
72 class VectorWrapper : public gko::matrix::Dense<double>
73 {
74 public:
75  VectorWrapper(std::shared_ptr<const gko::Executor> exec,
76  gko::size_type size, Vector *mfem_vec,
77  bool ownership = false)
78  : gko::matrix::Dense<double>(
79  exec,
80  gko::dim<2> {size, 1},
82  size,
83  mfem_vec->ReadWrite(
84  exec != exec->get_master() ? true : false)),
85  1)
86  {
87  // This controls whether or not we want Ginkgo to own its MFEM Vector.
88  // Normally, when we are wrapping an MFEM Vector created outside
89  // Ginkgo, we do not want ownership to be true. However, Ginkgo
90  // creates its own temporary vectors as part of its solvers, and
91  // these will be owned (and deleted) by Ginkgo.
92  if (ownership)
93  {
94  using deleter = gko_mfem_destroy<Vector>;
95  wrapped_vec = std::unique_ptr<Vector,
96  std::function<void(Vector *)>>(
97  mfem_vec, deleter{});
98  }
99  else
100  {
101  using deleter = gko::null_deleter<Vector>;
102  wrapped_vec = std::unique_ptr<Vector,
103  std::function<void(Vector *)>>(
104  mfem_vec, deleter{});
105  }
106  }
107 
108  static std::unique_ptr<VectorWrapper> create(
109  std::shared_ptr<const gko::Executor> exec,
110  gko::size_type size,
111  Vector *mfem_vec,
112  bool ownership = false)
113  {
114  return std::unique_ptr<VectorWrapper>(
115  new VectorWrapper(exec, size, mfem_vec, ownership));
116  }
117 
118  // Return reference to MFEM Vector object
119  Vector &get_mfem_vec_ref() { return *(this->wrapped_vec.get()); }
120 
121  // Return const reference to MFEM Vector object
122  const Vector &get_mfem_vec_const_ref() const { return *(this->wrapped_vec.get()); }
123 
124  // Override base Dense class implementation for creating new vectors
125  // with same executor and size as self
126  virtual std::unique_ptr<gko::matrix::Dense<double>>
127  create_with_same_config() const override
128  {
129  Vector *mfem_vec = new Vector(
130  this->get_size()[0],
131  this->wrapped_vec.get()->GetMemory().GetMemoryType());
132 
133  mfem_vec->UseDevice(this->wrapped_vec.get()->UseDevice());
134 
135  // If this function is called, Ginkgo is creating this
136  // object and should control the memory, so ownership is
137  // set to true
138  return VectorWrapper::create(this->get_executor(),
139  this->get_size()[0],
140  mfem_vec,
141  true);
142  }
143 
144  // Override base Dense class implementation for creating new vectors
145  // with same executor and type as self, but with a different size.
146  // This function will create "one large VectorWrapper" of size
147  // size[0] * size[1], since MFEM Vectors only have one dimension.
148  virtual std::unique_ptr<gko::matrix::Dense<double>> create_with_type_of_impl(
149  std::shared_ptr<const gko::Executor> exec,
150  const gko::dim<2> &size,
151  gko::size_type stride) const override
152  {
153  // Only stride of 1 is allowed for VectorWrapper type
154  if (stride > 1)
155  {
156  throw gko::Error(
157  __FILE__, __LINE__,
158  "VectorWrapper cannot be created with stride > 1");
159  }
160  // Compute total size of new Vector
161  gko::size_type total_size = size[0]*size[1];
162  Vector *mfem_vec = new Vector(
163  total_size,
164  this->wrapped_vec.get()->GetMemory().GetMemoryType());
165 
166  mfem_vec->UseDevice(this->wrapped_vec.get()->UseDevice());
167 
168  // If this function is called, Ginkgo is creating this
169  // object and should control the memory, so ownership is
170  // set to true
171  return VectorWrapper::create(
172  this->get_executor(), total_size, mfem_vec,
173  true);
174  }
175 
176  // Override base Dense class implementation for creating new sub-vectors
177  // from a larger vector.
178  virtual std::unique_ptr<gko::matrix::Dense<double>> create_submatrix_impl(
179  const gko::span &rows,
180  const gko::span &columns,
181  const gko::size_type stride) override
182  {
183 
184  gko::size_type num_rows = rows.end - rows.begin;
185  gko::size_type num_cols = columns.end - columns.begin;
186  // Data in the Dense matrix will be stored in row-major format.
187  // Check that we only have one column, and that the stride = 1
188  // (only allowed value for VectorWrappers).
189  if (num_cols > 1 || stride > 1)
190  {
191  throw gko::BadDimension(
192  __FILE__, __LINE__, __func__, "new_submatrix", num_rows,
193  num_cols,
194  "VectorWrapper submatrix must have one column and stride = 1");
195  }
196  int data_size = static_cast<int>(num_rows * num_cols);
197  int start = static_cast<int>(rows.begin);
198  // Create a new MFEM Vector pointing to this starting point in the data
199  Vector *mfem_vec = new Vector();
200  mfem_vec->MakeRef(*(this->wrapped_vec.get()), start, data_size);
201  mfem_vec->UseDevice(this->wrapped_vec.get()->UseDevice());
202 
203  // If this function is called, Ginkgo is creating this
204  // object and should control the memory, so ownership is
205  // set to true (but MFEM doesn't own and won't delete
206  // the data, at it's only a reference to the parent Vector)
207  return VectorWrapper::create(
208  this->get_executor(), data_size, mfem_vec,
209  true);
210  }
211 
212 private:
213  std::unique_ptr<Vector, std::function<void(Vector *)>> wrapped_vec;
214 };
215 
216 /**
217 * This class wraps an MFEM Operator for Ginkgo, to make its Mult()
218 * function available to Ginkgo, provided the input and output vectors
219 * are of the VectorWrapper type.
220 * Note that this class does NOT take ownership of the MFEM Operator.
221 *
222 * @ingroup Ginkgo
223 */
225  : public gko::EnableLinOp<OperatorWrapper>,
226  public gko::EnableCreateMethod<OperatorWrapper>
227 {
228 public:
229  OperatorWrapper(std::shared_ptr<const gko::Executor> exec,
230  gko::size_type size = 0,
231  const Operator *oper = NULL)
232  : gko::EnableLinOp<OperatorWrapper>(exec, gko::dim<2> {size, size}),
233  gko::EnableCreateMethod<OperatorWrapper>()
234  {
235  this->wrapped_oper = oper;
236  }
237 
238 protected:
239  void apply_impl(const gko::LinOp *b, gko::LinOp *x) const override;
240  void apply_impl(const gko::LinOp *alpha, const gko::LinOp *b,
241  const gko::LinOp *beta, gko::LinOp *x) const override;
242 
243 private:
244  const Operator *wrapped_oper;
245 };
246 
247 // Utility function which gets the scalar value of a Ginkgo gko::matrix::Dense
248 // matrix representing the norm of a vector.
249 template <typename ValueType=double>
250 double get_norm(const gko::matrix::Dense<ValueType> *norm)
251 {
252  // Put the value on CPU thanks to the master executor
253  auto cpu_norm = clone(norm->get_executor()->get_master(), norm);
254  // Return the scalar value contained at position (0, 0)
255  return cpu_norm->at(0, 0);
256 }
257 
258 // Utility function which computes the norm of a Ginkgo gko::matrix::Dense
259 // vector.
260 template <typename ValueType=double>
261 double compute_norm(const gko::matrix::Dense<ValueType> *b)
262 {
263  // Get the executor of the vector
264  auto exec = b->get_executor();
265  // Initialize a result scalar containing the value 0.0.
266  auto b_norm = gko::initialize<gko::matrix::Dense<ValueType>>({0.0}, exec);
267  // Use the dense `compute_norm2` function to compute the norm.
268  b->compute_norm2(lend(b_norm));
269  // Use the other utility function to return the norm contained in `b_norm``
270  return std::pow(get_norm(lend(b_norm)),2);
271 }
272 
273 /**
274  * Custom logger class which intercepts the residual norm scalar and solution
275  * vector in order to print a table of real vs recurrent (internal to the
276  * solvers) residual norms.
277  *
278  * This has been taken from the custom-logger example of Ginkgo. See the
279  * custom-logger example to understand how to write and modify your own loggers
280  * with Ginkgo.
281  *
282  * @ingroup Ginkgo
283  */
284 template <typename ValueType=double>
285 struct ResidualLogger : gko::log::Logger
286 {
287  // Output the logger's data in a table format
288  void write() const
289  {
290  // Print a header for the table
291  if (compute_real_residual)
292  {
293  mfem::out << "Iteration log with real residual norms:" << std::endl;
294  }
295  else
296  {
297  mfem::out << "Iteration log with residual norms:" << std::endl;
298  }
299  mfem::out << '|' << std::setw(10) << "Iteration" << '|' << std::setw(25)
300  << "Residual Norm" << '|' << std::endl;
301  // Print a separation line. Note that for creating `10` characters
302  // `std::setw()` should be set to `11`.
303  mfem::out << '|' << std::setfill('-') << std::setw(11) << '|' <<
304  std::setw(26) << '|' << std::setfill(' ') << std::endl;
305  // Print the data one by one in the form
306  mfem::out << std::scientific;
307  for (std::size_t i = 0; i < iterations.size(); i++)
308  {
309  mfem::out << '|' << std::setw(10) << iterations[i] << '|'
310  << std::setw(25) << residual_norms[i] << '|' << std::endl;
311  }
312  // std::defaultfloat could be used here but some compilers do not support
313  // it properly, e.g. the Intel compiler
314  mfem::out.unsetf(std::ios_base::floatfield);
315  // Print a separation line
316  mfem::out << '|' << std::setfill('-') << std::setw(11) << '|' <<
317  std::setw(26) << '|' << std::setfill(' ') << std::endl;
318  }
319 
320  using gko_dense = gko::matrix::Dense<ValueType>;
321 
322  // Customize the logging hook which is called every time an iteration is
323  // completed
324  void on_iteration_complete(const gko::LinOp *,
325  const gko::size_type &iteration,
326  const gko::LinOp *residual,
327  const gko::LinOp *solution,
328  const gko::LinOp *residual_norm,
329  const gko::LinOp *implicit_sq_residual_norm) const override
330  {
331  // If the solver shares the current solution vector and we want to
332  // compute the residual from that
333  if (solution && compute_real_residual)
334  {
335  // Store the matrix's executor
336  auto exec = matrix->get_executor();
337  // Compute the real residual vector by calling apply on the system
338  // First, compute res = A * x
339  matrix->apply(gko::lend(solution), gko::lend(res));
340  // Now do res = res - b, depending on which vector/oper type
341  // Check if b is a Ginkgo vector or wrapped MFEM Vector
342  if (dynamic_cast<const VectorWrapper*>(b))
343  {
344  const VectorWrapper *b_cast = gko::as<const VectorWrapper>(b);
345  // Copy the MFEM Vector stored in b
346  VectorWrapper *res_cast = gko::as<VectorWrapper>(res);
347  res_cast->get_mfem_vec_ref() -= b_cast->get_mfem_vec_const_ref();
348  }
349  else
350  {
351  // Create a scalar containing the value -1.0
352  auto neg_one = gko::initialize<gko_dense>({-1.0}, exec);
353  res->add_scaled(gko::lend(neg_one), gko::lend(b));
354  }
355 
356  // Compute the norm of the residual vector and add it to the
357  // `residual_norms` vector
358  residual_norms.push_back(compute_norm(gko::lend(res)));
359  }
360  else
361  {
362  // If the solver shares an implicit or recurrent residual norm, log its value
363  if (implicit_sq_residual_norm)
364  {
365  auto dense_norm = gko::as<gko_dense>(implicit_sq_residual_norm);
366  // Add the norm to the `residual_norms` vector
367  residual_norms.push_back(get_norm(dense_norm));
368  // Otherwise, use the recurrent residual vector
369  }
370  else if (residual_norm)
371  {
372  auto dense_norm = gko::as<gko_dense>(residual_norm);
373  // Add the norm to the `residual_norms` vector
374  residual_norms.push_back(get_norm(dense_norm));
375  // Otherwise, use the recurrent residual vector
376  }
377  else
378  {
379  auto dense_residual = gko::as<gko_dense>(residual);
380  // Compute the residual vector's norm
381  auto norm = compute_norm(gko::lend(dense_residual));
382  // Add the computed norm to the `residual_norms` vector
383  residual_norms.push_back(norm);
384  }
385  }
386  // Add the current iteration number to the `iterations` vector
387  iterations.push_back(iteration);
388  }
389 
390  // Version for solver that doesn't log implicit res norm
391  void on_iteration_complete(const gko::LinOp *op,
392  const gko::size_type &iteration,
393  const gko::LinOp *residual,
394  const gko::LinOp *solution,
395  const gko::LinOp *residual_norm) const override
396  {
397  on_iteration_complete(op, iteration, residual, solution, residual_norm,
398  nullptr);
399  }
400 
401  // Construct the logger and store the system matrix and b vectors
402  ResidualLogger(std::shared_ptr<const gko::Executor> exec,
403  const gko::LinOp *matrix, const gko_dense *b,
404  bool compute_real_residual=false)
405  :
406 #if MFEM_GINKGO_VERSION < 10500
407  gko::log::Logger(exec,
408  gko::log::Logger::iteration_complete_mask),
409 #else
410  gko::log::Logger(gko::log::Logger::iteration_complete_mask),
411 #endif
412  matrix {matrix},
413  b{b},
414  compute_real_residual{compute_real_residual}
415  {
416  if (compute_real_residual == true)
417  {
418  if (dynamic_cast<const VectorWrapper*>(b))
419  {
420  const VectorWrapper *b_cast = gko::as<const VectorWrapper>(b);
421  res = std::move(gko_dense::create_with_config_of(b_cast).release());
422  }
423  else
424  {
425  res = std::move(gko::clone(b).release());
426  }
427  }
428  }
429 
430 private:
431  // Pointer to the system matrix
432  const gko::LinOp *matrix;
433  // Pointer to the right hand sides
434  const gko_dense *b;
435  // Pointer to the residual workspace vector
436  gko_dense *res;
437  // Vector which stores all the residual norms
438  mutable std::vector<ValueType> residual_norms{};
439  // Vector which stores all the iteration numbers
440  mutable std::vector<std::size_t> iterations{};
441  // Whether or not to compute the residual at every iteration,
442  // rather than using the recurrent norm
443  const bool compute_real_residual;
444 };
445 
446 /**
447 * This class wraps a Ginkgo Executor for use in MFEM.
448 * Note that objects in the Ginkgo namespace intended to work
449 * together, e.g. a Ginkgo solver and preconditioner, should use the same
450 * GinkgoExecutor object. In general, most users will want to create
451 * one GinkgoExecutor object for use with all Ginkgo-related objects.
452 * The wrapper can be created to match MFEM's device configuration.
453 */
455 {
456 public:
457  // Types of Ginkgo Executors.
458  enum ExecType
459  {
460  /// Reference CPU Executor.
462  /// OpenMP CPU Executor.
463  OMP = 1,
464  /// CUDA GPU Executor.
465  CUDA = 2,
466  /// HIP GPU Executor.
467  HIP = 3
468  };
469  /**
470  * Constructor.
471  * Takes an @p GinkgoExecType argument and creates an Executor.
472  */
473  GinkgoExecutor(ExecType exec_type);
474 
475  /**
476  * Constructor.
477  * Takes an MFEM @p Device object and creates an Executor
478  * that "matches" (e.g., if MFEM is using the CPU, Ginkgo
479  * will choose the OmpExecutor; if MFEM is using CUDA,
480  * Ginkgo will choose the CudaExecutor).
481  */
482  GinkgoExecutor(Device &mfem_device);
483 
484  /**
485  * Destructor.
486  */
487  virtual ~GinkgoExecutor() = default;
488 
489  std::shared_ptr<gko::Executor> GetExecutor() const
490  {
491  return this->executor;
492  };
493 
494 private:
495  std::shared_ptr<gko::Executor> executor;
496 
497 };
498 
499 /**
500 * This class forms the base class for all of Ginkgo's preconditioners. The
501 * various derived classes only take the additional data that is specific to them.
502 * The entire collection of preconditioners that Ginkgo implements is available
503 * at the Ginkgo documentation and manual pages,
504 * https://ginkgo-project.github.io/ginkgo/doc/develop.
505 *
506 * @ingroup Ginkgo
507 */
509 {
510 public:
511  /**
512  * Constructor.
513  *
514  * The @p exec defines the paradigm where the solution is computed.
515  * Ginkgo currently supports four different executor types:
516  *
517  * + OmpExecutor specifies that the data should be stored and the
518  * associated operations executed on an OpenMP-supporting device (e.g.
519  * host CPU);
520  * + CudaExecutor specifies that the data should be stored and the
521  * operations executed on the NVIDIA GPU accelerator;
522  * + HipExecutor specifies that the data should be stored and the
523  * operations executed on the GPU accelerator using HIP;
524  * + ReferenceExecutor executes a non-optimized reference implementation,
525  * which can be used to debug the library.
526  */
528 
529  /**
530  * Destructor.
531  */
532  virtual ~GinkgoPreconditioner() = default;
533 
534  /**
535  * Generate the preconditioner for the given matrix @p op,
536  * which must be of MFEM SparseMatrix type.
537  * Calling this function is only required when creating a
538  * preconditioner for use with another MFEM solver; to use with
539  * a Ginkgo solver, get the LinOpFactory pointer through @p GetFactory()
540  * and pass to the Ginkgo solver constructor.
541  */
542  virtual void SetOperator(const Operator &op);
543 
544  /**
545  * Apply the preconditioner to input vector @p x, with out @p y.
546  */
547  virtual void Mult(const Vector &x, Vector &y) const;
548 
549  /**
550  * Return a pointer to the LinOpFactory that will generate the preconditioner
551  * with the parameters set through the specific constructor.
552  */
553  const std::shared_ptr<gko::LinOpFactory> GetFactory() const
554  {
555  return this->precond_gen;
556  };
557 
558  /**
559  * Return a pointer to the generated preconditioner for a specific matrix
560  * (that has previously been set with @p SetOperator).
561  */
562  const std::shared_ptr<gko::LinOp> GetGeneratedPreconditioner() const
563  {
564  return this->generated_precond;
565  };
566 
567  /**
568  * Return whether this GinkgoPreconditioner object has an explicitly-
569  * generated preconditioner, built for a specific matrix.
570  */
572  {
573  return this->has_generated_precond;
574  };
575 
576 protected:
577  /**
578  * The Ginkgo generated solver factory object.
579  */
580  std::shared_ptr<gko::LinOpFactory> precond_gen;
581 
582  /**
583  * Generated Ginkgo preconditioner for a specific matrix, created through
584  * @p SetOperator(), or a wrapped MFEM preconditioner.
585  * Must exist to use @p Mult().
586  */
587  std::shared_ptr<gko::LinOp> generated_precond;
588 
589  /**
590  * The execution paradigm in Ginkgo. The choices are between
591  * `gko::OmpExecutor`, `gko::CudaExecutor` and `gko::ReferenceExecutor`
592  * and more details can be found in Ginkgo's documentation.
593  */
594  std::shared_ptr<gko::Executor> executor;
595 
596  /**
597  * Whether or not we have generated a specific preconditioner for
598  * a matrix.
599  */
601 
602 };
603 
604 /**
605 * This class forms the base class for all of Ginkgo's iterative solvers.
606 * It is not intended to be used directly by MFEM applications. The various
607 * derived classes only take the additional data that is specific to them
608 * and solve the given linear system. The entire collection of solvers that
609 * Ginkgo implements is available at the Ginkgo documentation and manual pages,
610 * https://ginkgo-project.github.io/ginkgo/doc/develop.
611 *
612 * @ingroup Ginkgo
613 */
615 {
616 public:
617  /**
618  * Return a pointer to the LinOpFactory that will generate the solver
619  * with the parameters set through the specific constructor.
620  */
621  const std::shared_ptr<gko::LinOpFactory> GetFactory() const
622  {
623  return this->solver_gen;
624  };
625 
626  void SetPrintLevel(int print_lvl) { print_level = print_lvl; }
627 
628  int GetNumIterations() const { return final_iter; }
629  int GetConverged() const { return converged; }
630  double GetFinalNorm() const { return final_norm; }
631 
632  /**
633  * If the Operator is a SparseMatrix, set up a Ginkgo Csr matrix
634  * to use its data directly. If the Operator is not a matrix,
635  * create an OperatorWrapper for it and store.
636  */
637  virtual void SetOperator(const Operator &op);
638 
639  /**
640  * Solve the linear system <tt>Ax=y</tt>. Dependent on the information
641  * provided by derived classes one of Ginkgo's linear solvers is chosen.
642  */
643  virtual void Mult(const Vector &x, Vector &y) const;
644 
645  /**
646  * Return whether this GinkgoIterativeSolver object will use
647  * VectorWrapper types for input and output vectors.
648  * Note that Mult() will automatically create these wrappers if needed.
649  */
650  bool UsesVectorWrappers() const
651  {
652  return this->needs_wrapped_vecs;
653  };
654 
655  /**
656  * Destructor.
657  */
658  virtual ~GinkgoIterativeSolver() = default;
659 
660 protected:
661  /**
662  * Constructor.
663  *
664  * The @p exec defines the paradigm where the solution is computed.
665  * @p use_implicit_res_norm is for internal use by the derived classes
666  * for specific Ginkgo solvers; it indicates whether the solver makes
667  * an implicit residual norm estimate available for convergence checking.
668  * Each derived class automatically sets the correct value when calling this
669  * base class constructor.
670  *
671  */
673  bool use_implicit_res_norm);
674 
677  int max_iter;
678  double rel_tol;
679  double abs_tol;
680  mutable double final_norm;
681  mutable int final_iter;
682  mutable int converged;
683 
684  /**
685  * The Ginkgo solver factory object, to generate specific solvers.
686  */
687  std::shared_ptr<gko::LinOpFactory> solver_gen;
688 
689  /**
690  * The Ginkgo solver object, generated for a specific operator.
691  */
692  std::shared_ptr<gko::LinOp> solver;
693 
694  /**
695  * The residual criterion object that controls the reduction of the residual
696  * relative to the initial residual.
697  */
698  std::shared_ptr<gko::stop::ResidualNorm<>::Factory>
700 
701  /**
702  * The residual criterion object that controls the reduction of the residual
703  * based on an absolute tolerance.
704  */
705  std::shared_ptr<gko::stop::ResidualNorm<>::Factory>
707 
708  /**
709  * The implicit residual criterion object that controls the reduction of the residual
710  * relative to the initial residual, based on an implicit residual norm value.
711  */
712  std::shared_ptr<gko::stop::ImplicitResidualNorm<>::Factory>
714 
715  /**
716  * The implicit residual criterion object that controls the reduction of the residual
717  * based on an absolute tolerance, based on an implicit residual norm value.
718  */
719  std::shared_ptr<gko::stop::ImplicitResidualNorm<>::Factory>
721 
722  /**
723  * The Ginkgo convergence logger used to check for convergence and other
724  * solver data if needed.
725  */
726  mutable std::shared_ptr<gko::log::Convergence<>> convergence_logger;
727 
728  /**
729  * The residual logger object used to check for convergence and other solver
730  * data if needed.
731  */
732  mutable std::shared_ptr<ResidualLogger<>> residual_logger;
733 
734  /**
735  * The Ginkgo combined factory object is used to create a combined stopping
736  * criterion to be passed to the solver.
737  */
738  std::shared_ptr<gko::stop::Combined::Factory> combined_factory;
739 
740  /**
741  * The execution paradigm in Ginkgo. The choices are between
742  * `gko::OmpExecutor`, `gko::CudaExecutor` and `gko::ReferenceExecutor`
743  * and more details can be found in Ginkgo's documentation.
744  */
745  std::shared_ptr<gko::Executor> executor;
746 
747  /**
748  * Whether or not we need to use VectorWrapper types with this solver.
749  */
751 
752  /**
753  * Whether or not we need to use VectorWrapper types with the preconditioner
754  * or an inner solver. This value is set upon creation of the
755  * GinkgoIterativeSolver object and should never change.
756  */
758 
759  /** Rebuild the Ginkgo stopping criterion factory with the latest values
760  * of rel_tol, abs_tol, and max_iter.
761  */
762  void update_stop_factory();
763 
764 private:
765  /**
766  * Initialize the Ginkgo logger object with event masks. Refer to the logging
767  * event masks in Ginkgo's .../include/ginkgo/core/log/logger.hpp.
768  */
769  void
770  initialize_ginkgo_log(gko::matrix::Dense<double>* b) const;
771 
772  /**
773  * Pointer to either a Ginkgo CSR matrix or an OperatorWrapper wrapping
774  * an MFEM Operator (for matrix-free evaluation).
775  */
776  std::shared_ptr<gko::LinOp> system_oper;
777 
778 };
779 
780 /**
781  * This class adds helper functions for updating Ginkgo factories
782  * and solvers, when the full class type is needed. The derived classes
783  * should inherit from this class, rather than from GinkgoIterativeSolver
784  * directly.
785  */
786 template<typename SolverType>
788 {
789 public:
792 
793  void SetRelTol(double rtol)
794  {
795  rel_tol = rtol;
796  this->update_stop_factory();
797  gko::as<typename SolverType::Factory>(solver_gen)->get_parameters().criteria =
798  { combined_factory };
799  if (solver)
800  {
801  gko::as<SolverType>(solver)->set_stop_criterion_factory(combined_factory);
802  }
803  }
804 
805  void SetAbsTol(double atol)
806  {
807  abs_tol = atol;
808  this->update_stop_factory();
809  gko::as<typename SolverType::Factory>(solver_gen)->get_parameters().criteria =
810  { combined_factory };
811  if (solver)
812  {
813  gko::as<SolverType>(solver)->set_stop_criterion_factory(combined_factory);
814  }
815  }
816 
817  void SetMaxIter(int max_it)
818  {
819  max_iter = max_it;
820  this->update_stop_factory();
821  gko::as<typename SolverType::Factory>(solver_gen)->get_parameters().criteria =
822  { combined_factory };
823  if (solver)
824  {
825  gko::as<SolverType>(solver)->set_stop_criterion_factory(combined_factory);
826  }
827  }
828 };
829 
830 
831 /**
832  * An implementation of the solver interface using the Ginkgo CG solver.
833  *
834  * @ingroup Ginkgo
835  */
836 class CGSolver : public EnableGinkgoSolver<gko::solver::Cg<double>>
837 {
838 public:
839  /**
840  * Constructor.
841  *
842  * @param[in] exec The execution paradigm for the solver.
843  */
844  CGSolver(GinkgoExecutor &exec);
845 
846  /**
847  * Constructor.
848  *
849  * @param[in] exec The execution paradigm for the solver.
850  * @param[in] preconditioner The preconditioner for the solver.
851  */
852  CGSolver(GinkgoExecutor &exec,
853  const GinkgoPreconditioner &preconditioner);
854 };
855 
856 
857 /**
858  * An implementation of the solver interface using the Ginkgo BiCGStab solver.
859  *
860  * @ingroup Ginkgo
861  */
862 class BICGSTABSolver : public EnableGinkgoSolver<gko::solver::Bicgstab<double>>
863 {
864 public:
865  /**
866  * Constructor.
867  *
868  * @param[in] exec The execution paradigm for the solver.
869  */
871 
872  /**
873  * Constructor.
874  *
875  * @param[in] exec The execution paradigm for the solver.
876  * @param[in] preconditioner The preconditioner for the solver.
877  */
879  const GinkgoPreconditioner &preconditioner);
880 
881 };
882 
883 /**
884  * An implementation of the solver interface using the Ginkgo CGS solver.
885  *
886  * CGS or the conjugate gradient square method is an iterative type Krylov
887  * subspace method which is suitable for general systems.
888  *
889  * @ingroup Ginkgo
890  */
891 class CGSSolver : public EnableGinkgoSolver<gko::solver::Cgs<double>>
892 {
893 public:
894  /**
895  * Constructor.
896  *
897  * @param[in] exec The execution paradigm for the solver.
898  */
899  CGSSolver(GinkgoExecutor &exec);
900 
901  /**
902  * Constructor.
903  *
904  * @param[in] exec The execution paradigm for the solver.
905  * @param[in] preconditioner The preconditioner for the solver.
906  */
908  const GinkgoPreconditioner &preconditioner);
909 };
910 
911 /**
912  * An implementation of the solver interface using the Ginkgo FCG solver.
913  *
914  * FCG or the flexible conjugate gradient method is an iterative type Krylov
915  * subspace method which is suitable for symmetric positive definite methods.
916  *
917  * Though this method performs very well for symmetric positive definite
918  * matrices, it is in general not suitable for general matrices.
919  *
920  * In contrast to the standard CG based on the Polack-Ribiere formula, the
921  * flexible CG uses the Fletcher-Reeves formula for creating the orthonormal
922  * vectors spanning the Krylov subspace. This increases the computational cost
923  * of every Krylov solver iteration but allows for non-constant preconditioners.
924  *
925  * @ingroup Ginkgo
926  */
927 class FCGSolver : public EnableGinkgoSolver<gko::solver::Fcg<double>>
928 {
929 public:
930  /**
931  * Constructor.
932  *
933  * @param[in] exec The execution paradigm for the solver.
934  */
935  FCGSolver(GinkgoExecutor &exec);
936 
937  /**
938  * Constructor.
939  *
940  * @param[in] exec The execution paradigm for the solver.
941  * @param[in] preconditioner The preconditioner for the solver.
942  */
944  const GinkgoPreconditioner &preconditioner);
945 };
946 
947 /**
948  * An implementation of the solver interface using the Ginkgo GMRES solver.
949  *
950  * @ingroup Ginkgo
951  */
952 class GMRESSolver : public EnableGinkgoSolver<gko::solver::Gmres<double>>
953 {
954 public:
955  /**
956  * Constructor.
957  *
958  * @param[in] exec The execution paradigm for the solver.
959  * @param[in] dim The Krylov dimension of the solver. Value of 0 will
960  * let Ginkgo use its own internal default value.
961  */
962  GMRESSolver(GinkgoExecutor &exec, int dim = 0);
963 
964  /**
965  * Constructor.
966  *
967  * @param[in] exec The execution paradigm for the solver.
968  * @param[in] preconditioner The preconditioner for the solver.
969  * @param[in] dim The Krylov dimension of the solver. Value of 0 will
970  * let Ginkgo use its own internal default value.
971  */
973  const GinkgoPreconditioner &preconditioner,
974  int dim = 0);
975 
976  /**
977  * Change the Krylov dimension of the solver.
978  */
979  void SetKDim(int dim);
980 
981 protected:
982  int m; // Dimension of Krylov subspace
983 };
984 
985 using gko::solver::cb_gmres::storage_precision;
986 /**
987  * An implementation of the solver interface using the Ginkgo
988  * Compressed Basis GMRES solver. With CB-GMRES, the Krylov basis
989  * is "compressed" by storing in a lower precision. Currently, computations
990  * are always performed in double precision when using this MFEM integration.
991  * The Ginkgo storage precision options are accessed
992  * through Ginkgo::storage_precision::*. The default choice
993  * is Ginkgo::storage_precision::reduce1, i.e., store in float
994  * instead of double.
995  *
996  * @ingroup Ginkgo
997  */
998 class CBGMRESSolver : public EnableGinkgoSolver<gko::solver::CbGmres<double>>
999 {
1000 public:
1001  /**
1002  * Constructor.
1003  *
1004  * @param[in] exec The execution paradigm for the solver.
1005  * @param[in] dim The Krylov dimension of the solver. Value of 0 will
1006  * let Ginkgo use its own internal default value.
1007  * @param[in] prec The storage precision used in the CB-GMRES. Options
1008  * are: keep (keep double precision), reduce1 (double -> float),
1009  * reduce2 (double -> half), integer (double -> int64),
1010  * ireduce1 (double -> int32), ireduce2 (double -> int16).
1011  * See Ginkgo documentation for more about the CB-GMRES and
1012  * these options.
1013  */
1014  CBGMRESSolver(GinkgoExecutor &exec, int dim = 0,
1015  storage_precision prec = storage_precision::reduce1);
1016 
1017  /**
1018  * Constructor.
1019  *
1020  * @param[in] exec The execution paradigm for the solver.
1021  * @param[in] preconditioner The preconditioner for the solver.
1022  * @param[in] dim The Krylov dimension of the solver. Value of 0 will
1023  * let Ginkgo use its own internal default value.
1024  * @param[in] prec The storage precision used in the CB-GMRES. Options
1025  * are: keep (keep double precision), reduce1 (double -> float),
1026  * reduce2 (double -> half), integer (double -> int64),
1027  * ireduce1 (double -> int32), ireduce2 (double -> int16).
1028  * See Ginkgo documentation for more about the CB-GMRES and
1029  * these options.
1030  */
1032  const GinkgoPreconditioner &preconditioner,
1033  int dim = 0,
1034  storage_precision prec = storage_precision::reduce1);
1035 
1036  /**
1037  * Change the Krylov dimension of the solver.
1038  */
1039  void SetKDim(int dim);
1040 
1041 protected:
1042  int m; // Dimension of Krylov subspace
1043 };
1044 
1045 /**
1046  * An implementation of the solver interface using the Ginkgo IR solver.
1047  *
1048  * Iterative refinement (IR) is an iterative method that uses another coarse
1049  * method to approximate the error of the current solution via the current
1050  * residual.
1051  *
1052  * @ingroup Ginkgo
1053  */
1054 class IRSolver : public EnableGinkgoSolver<gko::solver::Ir<double>>
1055 {
1056 public:
1057  /**
1058  * Constructor.
1059  *
1060  * @param[in] exec The execution paradigm for the solver.
1061  */
1062  IRSolver(GinkgoExecutor &exec);
1063 
1064  /**
1065  * Constructor.
1066  *
1067  * @param[in] exec The execution paradigm for the solver.
1068  * @param[in] inner_solver The inner solver for the main solver.
1069  */
1070  IRSolver(GinkgoExecutor &exec,
1071  const GinkgoIterativeSolver &inner_solver);
1072 
1073 };
1074 
1075 /**
1076  * An implementation of the preconditioner interface using the Ginkgo Jacobi
1077  * preconditioner.
1078  *
1079  * @ingroup Ginkgo
1080  */
1082 {
1083 public:
1084  /**
1085  * Constructor.
1086  *
1087  * @param[in] exec The execution paradigm for the preconditioner.
1088  * @param[in] storage_opt The storage optimization parameter.
1089  * @param[in] accuracy The relative accuracy for the adaptive version.
1090  * @param[in] max_block_size Maximum block size.
1091  * See the Ginkgo documentation for more information on these parameters.
1092  */
1094  GinkgoExecutor &exec,
1095  const std::string &storage_opt = "none",
1096  const double accuracy = 1.e-1,
1097  const int max_block_size = 32
1098  );
1099 };
1100 
1101 /**
1102  * An implementation of the preconditioner interface using the Ginkgo
1103  * Incomplete LU preconditioner (ILU(0)).
1104  *
1105  * @ingroup Ginkgo
1106  */
1108 {
1109 public:
1110  /**
1111  * Constructor.
1112  *
1113  * @param[in] exec The execution paradigm for the preconditioner.
1114  * @param[in] factorization_type The factorization type: "exact" or
1115  * "parilu".
1116  * @param[in] sweeps The number of sweeps to do in the ParIlu
1117  * factorization algorithm. A value of 0 tells Ginkgo to use its
1118  * internal default value. This parameter is ignored in the case
1119  * of an exact factorization.
1120  * @param[in] skip_sort Only set this to true if the input matrix
1121  * that will be used to generate this preconditioner is guaranteed
1122  * to be sorted by column.
1123  *
1124  * Note: The use of this preconditioner will sort any input matrix
1125  * given to it, potentially changing the order of the stored values.
1126  */
1128  GinkgoExecutor &exec,
1129  const std::string &factorization_type = "exact",
1130  const int sweeps = 0,
1131  const bool skip_sort = false
1132  );
1133 };
1134 
1135 /**
1136  * An implementation of the preconditioner interface using the Ginkgo
1137  * Incomplete LU-Incomplete Sparse Approximate Inverse preconditioner.
1138  * The Ilu-ISAI preconditioner differs from the Ilu preconditioner in
1139  * that Incomplete Sparse Approximate Inverses (ISAIs) are formed
1140  * to approximate solving the triangular systems defined by L and U.
1141  * When the preconditioner is applied, these ISAI matrices are applied
1142  * through matrix-vector multiplication.
1143  *
1144  * @ingroup Ginkgo
1145  */
1147 {
1148 public:
1149  /**
1150  * Constructor.
1151  *
1152  * @param[in] exec The execution paradigm for the preconditioner.
1153  * @param[in] factorization_type The factorization type: "exact" or
1154  * "parilu".
1155  * @param[in] sweeps The number of sweeps to do in the ParIlu
1156  * factorization algorithm. A value of 0 tells Ginkgo to use its
1157  * internal default value. This parameter is ignored in the case
1158  * of an exact factorization.
1159  * @param[in] sparsity_power Parameter determining the sparsity pattern of
1160  * the ISAI approximations.
1161  * @param[in] skip_sort Only set this to true if the input matrix
1162  * that will be used to generate this preconditioner is guaranteed
1163  * to be sorted by column.
1164  * See the Ginkgo documentation for more information on these parameters.
1165  *
1166  * Note: The use of this preconditioner will sort any input matrix
1167  * given to it, potentially changing the order of the stored values.
1168  */
1170  GinkgoExecutor &exec,
1171  const std::string &factorization_type = "exact",
1172  const int sweeps = 0,
1173  const int sparsity_power = 1,
1174  const bool skip_sort = false
1175  );
1176 };
1177 
1178 /**
1179  * An implementation of the preconditioner interface using the Ginkgo
1180  * Incomplete Cholesky preconditioner (IC(0)).
1181  *
1182  * @ingroup Ginkgo
1183  */
1185 {
1186 public:
1187  /**
1188  * Constructor.
1189  *
1190  * @param[in] exec The execution paradigm for the preconditioner.
1191  * @param[in] factorization_type The factorization type: "exact" or
1192  * "paric".
1193  * @param[in] sweeps The number of sweeps to do in the ParIc
1194  * factorization algorithm. A value of 0 tells Ginkgo to use its
1195  * internal default value. This parameter is ignored in the case
1196  * of an exact factorization.
1197  * @param[in] skip_sort Only set this to true if the input matrix
1198  * that will be used to generate this preconditioner is guaranteed
1199  * to be sorted by column.
1200  *
1201  * Note: The use of this preconditioner will sort any input matrix
1202  * given to it, potentially changing the order of the stored values.
1203  */
1205  GinkgoExecutor &exec,
1206  const std::string &factorization_type = "exact",
1207  const int sweeps = 0,
1208  const bool skip_sort = false
1209  );
1210 };
1211 
1212 /**
1213  * An implementation of the preconditioner interface using the Ginkgo
1214  * Incomplete Cholesky-Incomplete Sparse Approximate Inverse preconditioner.
1215  * The Ic-ISAI preconditioner differs from the Ic preconditioner in
1216  * that Incomplete Sparse Approximate Inverses (ISAIs) are formed
1217  * to approximate solving the triangular systems defined by L and L^T.
1218  * When the preconditioner is applied, these ISAI matrices are applied
1219  * through matrix-vector multiplication.
1220  *
1221  * @ingroup Ginkgo
1222  */
1224 {
1225 public:
1226  /**
1227  * Constructor.
1228  *
1229  * @param[in] exec The execution paradigm for the preconditioner.
1230  * @param[in] factorization_type The factorization type: "exact" or
1231  * "paric".
1232  * @param[in] sweeps The number of sweeps to do in the ParIc
1233  * factorization algorithm. A value of 0 tells Ginkgo to use its
1234  * internal default value. This parameter is ignored in the case
1235  * of an exact factorization.
1236  * @param[in] sparsity_power Parameter determining the sparsity pattern of
1237  * the ISAI approximations.
1238  * @param[in] skip_sort Only set this to true if the input matrix
1239  * that will be used to generate this preconditioner is guaranteed
1240  * to be sorted by column.
1241  * See the Ginkgo documentation for more information on these parameters.
1242  *
1243  * Note: The use of this preconditioner will sort any input matrix
1244  * given to it, potentially changing the order of the stored values.
1245  */
1247  GinkgoExecutor &exec,
1248  const std::string &factorization_type = "exact",
1249  const int sweeps = 0,
1250  const int sparsity_power = 1,
1251  const bool skip_sort = false
1252  );
1253 };
1254 
1255 /**
1256  * A wrapper that allows Ginkgo to use MFEM preconditioners.
1257  *
1258  * @ingroup Ginkgo
1259  */
1261 {
1262 public:
1263  /**
1264  * Constructor.
1265  *
1266  * @param[in] exec The execution paradigm for the preconditioner.
1267  * @param[in] mfem_precond The MFEM Preconditioner to wrap.
1268  */
1270  GinkgoExecutor &exec,
1271  const Solver &mfem_precond
1272  );
1273 
1274  /**
1275  * SetOperator is not allowed for this type of preconditioner;
1276  * this function overrides the base class in order to give an
1277  * error if SetOperator() is called for this class.
1278  */
1279  virtual void SetOperator(const Operator &op)
1280  {
1281  MFEM_ABORT("Ginkgo::MFEMPreconditioner must be constructed "
1282  "with the MFEM Operator that it will wrap as an argument;\n"
1283  "calling SetOperator() is not allowed.");
1284  };
1285 };
1286 } // namespace Ginkgo
1287 
1288 } // namespace mfem
1289 
1290 #endif // MFEM_USE_GINKGO
1291 
1292 #endif // MFEM_GINKGO
std::shared_ptr< gko::log::Convergence<> > convergence_logger
Definition: ginkgo.hpp:726
void SetRelTol(double rtol)
Definition: ginkgo.hpp:793
std::shared_ptr< ResidualLogger<> > residual_logger
Definition: ginkgo.hpp:732
virtual ~GinkgoExecutor()=default
virtual void SetOperator(const Operator &op)
Definition: ginkgo.cpp:415
std::shared_ptr< gko::stop::ResidualNorm<>::Factory > abs_criterion
Definition: ginkgo.hpp:706
GinkgoIterativeSolver(GinkgoExecutor &exec, bool use_implicit_res_norm)
Definition: ginkgo.cpp:121
CBGMRESSolver(GinkgoExecutor &exec, int dim=0, storage_precision prec=storage_precision::reduce1)
Definition: ginkgo.cpp:720
const std::shared_ptr< gko::LinOp > GetGeneratedPreconditioner() const
Definition: ginkgo.hpp:562
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition: vector.hpp:115
std::shared_ptr< gko::LinOpFactory > precond_gen
Definition: ginkgo.hpp:574
CGSSolver(GinkgoExecutor &exec)
Definition: ginkgo.cpp:553
virtual std::unique_ptr< gko::matrix::Dense< double > > create_with_same_config() const override
Definition: ginkgo.hpp:127
MFEMPreconditioner(GinkgoExecutor &exec, const Solver &mfem_precond)
Definition: ginkgo.cpp:1127
static std::unique_ptr< VectorWrapper > create(std::shared_ptr< const gko::Executor > exec, gko::size_type size, Vector *mfem_vec, bool ownership=false)
Definition: ginkgo.hpp:108
JacobiPreconditioner(GinkgoExecutor &exec, const std::string &storage_opt="none", const double accuracy=1.e-1, const int max_block_size=32)
Definition: ginkgo.cpp:924
std::shared_ptr< gko::Executor > executor
Definition: ginkgo.hpp:594
GinkgoExecutor(ExecType exec_type)
Definition: ginkgo.cpp:31
virtual void SetOperator(const Operator &op)
Definition: ginkgo.hpp:1279
Vector beta
void SetKDim(int dim)
Definition: ginkgo.cpp:708
void SetMaxIter(int max_it)
Definition: ginkgo.hpp:817
gko::matrix::Dense< ValueType > gko_dense
Definition: ginkgo.hpp:320
virtual void Mult(const Vector &x, Vector &y) const
Definition: ginkgo.cpp:287
BICGSTABSolver(GinkgoExecutor &exec)
Definition: ginkgo.cpp:514
bool HasGeneratedPreconditioner() const
Definition: ginkgo.hpp:571
std::shared_ptr< gko::stop::ImplicitResidualNorm<>::Factory > imp_rel_criterion
Definition: ginkgo.hpp:713
IluPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const bool skip_sort=false)
Definition: ginkgo.cpp:955
virtual std::unique_ptr< gko::matrix::Dense< double > > create_submatrix_impl(const gko::span &rows, const gko::span &columns, const gko::size_type stride) override
Definition: ginkgo.hpp:178
double b
Definition: lissajous.cpp:42
const std::shared_ptr< gko::LinOpFactory > GetFactory() const
Definition: ginkgo.hpp:621
std::shared_ptr< gko::Executor > executor
Definition: ginkgo.hpp:745
void on_iteration_complete(const gko::LinOp *op, const gko::size_type &iteration, const gko::LinOp *residual, const gko::LinOp *solution, const gko::LinOp *residual_norm) const override
Definition: ginkgo.hpp:391
CGSolver(GinkgoExecutor &exec)
Definition: ginkgo.cpp:475
virtual void Mult(const Vector &x, Vector &y) const
Definition: ginkgo.cpp:854
void SetPrintLevel(int print_lvl)
Definition: ginkgo.hpp:626
virtual std::unique_ptr< gko::matrix::Dense< double > > create_with_type_of_impl(std::shared_ptr< const gko::Executor > exec, const gko::dim< 2 > &size, gko::size_type stride) const override
Definition: ginkgo.hpp:148
ResidualLogger(std::shared_ptr< const gko::Executor > exec, const gko::LinOp *matrix, const gko_dense *b, bool compute_real_residual=false)
Definition: ginkgo.hpp:402
VectorWrapper(std::shared_ptr< const gko::Executor > exec, gko::size_type size, Vector *mfem_vec, bool ownership=false)
Definition: ginkgo.hpp:75
GMRESSolver(GinkgoExecutor &exec, int dim=0)
Definition: ginkgo.cpp:629
virtual ~GinkgoPreconditioner()=default
double compute_norm(const gko::matrix::Dense< ValueType > *b)
Definition: ginkgo.hpp:261
OpenMP CPU Executor.
Definition: ginkgo.hpp:463
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:66
std::shared_ptr< gko::Executor > GetExecutor() const
Definition: ginkgo.hpp:489
std::shared_ptr< gko::stop::ResidualNorm<>::Factory > rel_criterion
Definition: ginkgo.hpp:699
double get_norm(const gko::matrix::Dense< ValueType > *norm)
Definition: ginkgo.hpp:250
IRSolver(GinkgoExecutor &exec)
Definition: ginkgo.cpp:819
const Vector & get_mfem_vec_const_ref() const
Definition: ginkgo.hpp:122
IcPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const bool skip_sort=false)
Definition: ginkgo.cpp:1046
std::shared_ptr< gko::stop::Combined::Factory > combined_factory
Definition: ginkgo.hpp:738
std::shared_ptr< gko::LinOpFactory > solver_gen
Definition: ginkgo.hpp:687
const std::shared_ptr< gko::LinOpFactory > GetFactory() const
Definition: ginkgo.hpp:553
FCGSolver(GinkgoExecutor &exec)
Definition: ginkgo.cpp:591
int dim
Definition: ex24.cpp:53
IcIsaiPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const int sparsity_power=1, const bool skip_sort=false)
Definition: ginkgo.cpp:1082
void on_iteration_complete(const gko::LinOp *, const gko::size_type &iteration, const gko::LinOp *residual, const gko::LinOp *solution, const gko::LinOp *residual_norm, const gko::LinOp *implicit_sq_residual_norm) const override
Definition: ginkgo.hpp:324
IluIsaiPreconditioner(GinkgoExecutor &exec, const std::string &factorization_type="exact", const int sweeps=0, const int sparsity_power=1, const bool skip_sort=false)
Definition: ginkgo.cpp:989
void SetAbsTol(double atol)
Definition: ginkgo.hpp:805
GinkgoPreconditioner(GinkgoExecutor &exec)
Definition: ginkgo.cpp:845
OperatorWrapper(std::shared_ptr< const gko::Executor > exec, gko::size_type size=0, const Operator *oper=NULL)
Definition: ginkgo.hpp:229
virtual ~GinkgoIterativeSolver()=default
std::shared_ptr< gko::LinOp > generated_precond
Definition: ginkgo.hpp:587
const double alpha
Definition: ex15.cpp:369
EnableGinkgoSolver(GinkgoExecutor &exec, bool use_implicit_res_norm)
Definition: ginkgo.hpp:790
Vector data type.
Definition: vector.hpp:58
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
Definition: vector.hpp:581
std::shared_ptr< gko::stop::ImplicitResidualNorm<>::Factory > imp_abs_criterion
Definition: ginkgo.hpp:720
Base class for solvers.
Definition: operator.hpp:682
Reference CPU Executor.
Definition: ginkgo.hpp:461
virtual void SetOperator(const Operator &op)
Definition: ginkgo.cpp:884
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
Definition: device.hpp:121
Abstract operator.
Definition: operator.hpp:24
gko::Array< T > gko_array
Definition: ginkgo.hpp:43
void apply_impl(const gko::LinOp *b, gko::LinOp *x) const override
Definition: ginkgo.cpp:202
std::shared_ptr< gko::LinOp > solver
Definition: ginkgo.hpp:692
void operator()(pointer ptr) const noexcept
Definition: ginkgo.hpp:60