Ginkgo  Generated from pipelines/2457497073 branch based on develop. Ginkgo version 2.0.0
A numerical linear algebra library targeting many-core architectures
lin_op.hpp
1 // SPDX-FileCopyrightText: 2017 - 2026 The Ginkgo authors
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #ifndef GKO_PUBLIC_CORE_BASE_LIN_OP_HPP_
6 #define GKO_PUBLIC_CORE_BASE_LIN_OP_HPP_
7 
8 
9 #include <memory>
10 #include <type_traits>
11 #include <utility>
12 
13 #include <ginkgo/core/base/abstract_factory.hpp>
14 #include <ginkgo/core/base/device_matrix_data.hpp>
15 #include <ginkgo/core/base/dim.hpp>
16 #include <ginkgo/core/base/exception_helpers.hpp>
17 #include <ginkgo/core/base/math.hpp>
18 #include <ginkgo/core/base/matrix_assembly_data.hpp>
19 #include <ginkgo/core/base/matrix_data.hpp>
20 #include <ginkgo/core/base/polymorphic_object.hpp>
21 #include <ginkgo/core/base/types.hpp>
22 #include <ginkgo/core/base/utils.hpp>
23 #include <ginkgo/core/log/logger.hpp>
24 
25 
26 namespace gko {
27 namespace matrix {
28 
29 
30 template <typename ValueType>
31 class Diagonal;
32 
33 
34 } // namespace matrix
35 
36 
117 class LinOp : public EnableAbstractPolymorphicObject<LinOp> {
118 public:
128  {
129  this->template log<log::Logger::linop_apply_started>(this, b.get(),
130  x.get());
131  this->validate_application_parameters(b.get(), x.get());
132  auto exec = this->get_executor();
133  this->apply_impl(make_temporary_clone(exec, b).get(),
134  make_temporary_clone(exec, x).get());
135  this->template log<log::Logger::linop_apply_completed>(this, b.get(),
136  x.get());
137  }
138 
139 
150  {
151  this->template log<log::Logger::linop_advanced_apply_started>(
152  this, alpha.get(), b.get(), beta.get(), x.get());
153  this->validate_application_parameters(alpha.get(), b.get(), beta.get(),
154  x.get());
155  auto exec = this->get_executor();
156  this->apply_impl(make_temporary_clone(exec, alpha).get(),
157  make_temporary_clone(exec, b).get(),
158  make_temporary_clone(exec, beta).get(),
159  make_temporary_clone(exec, x).get());
160  this->template log<log::Logger::linop_advanced_apply_completed>(
161  this, alpha.get(), b.get(), beta.get(), x.get());
162  }
163 
169  const dim<2>& get_size() const noexcept { return size_; }
170 
178  virtual bool apply_uses_initial_guess() const { return false; }
179 
181  LinOp& operator=(const LinOp&) = default;
182 
189  {
190  if (this != &other) {
192  this->set_size(other.get_size());
193  other.set_size({});
194  }
195  return *this;
196  }
197 
199  LinOp(const LinOp&) = default;
200 
205  LinOp(LinOp&& other)
206  : EnableAbstractPolymorphicObject<LinOp>(std::move(other)),
207  size_{std::exchange(other.size_, dim<2>{})}
208  {}
209 
210 protected:
217  explicit LinOp(std::shared_ptr<const Executor> exec,
218  const dim<2>& size = dim<2>{})
219  : EnableAbstractPolymorphicObject<LinOp>(exec), size_{size}
220  {}
221 
227  void set_size(const dim<2>& value) noexcept { size_ = value; }
228 
238  virtual void apply_impl(const LinOp* b, LinOp* x) const = 0;
239 
249  virtual void apply_impl(const LinOp* alpha, const LinOp* b,
250  const LinOp* beta, LinOp* x) const = 0;
251 
259  void validate_application_parameters(const LinOp* b, const LinOp* x) const
260  {
261  GKO_ASSERT_CONFORMANT(this, b);
262  GKO_ASSERT_EQUAL_ROWS(this, x);
263  GKO_ASSERT_EQUAL_COLS(b, x);
264  }
265 
275  void validate_application_parameters(const LinOp* alpha, const LinOp* b,
276  const LinOp* beta,
277  const LinOp* x) const
278  {
279  this->validate_application_parameters(b, x);
280  GKO_ASSERT_EQUAL_DIMENSIONS(alpha, dim<2>(1, 1));
281  GKO_ASSERT_EQUAL_DIMENSIONS(beta, dim<2>(1, 1));
282  }
283 
284 private:
285  dim<2> size_{};
286 };
287 
288 
345 public:
347 
348  std::unique_ptr<LinOp> generate(std::shared_ptr<const LinOp> input) const
349  {
350  this->template log<log::Logger::linop_factory_generate_started>(
351  this, input.get());
352  const auto exec = this->get_executor();
353  std::unique_ptr<LinOp> generated;
354  if (input->get_executor() == exec) {
355  generated = this->AbstractFactory::generate(input);
356  } else {
357  generated =
358  this->AbstractFactory::generate(gko::clone(exec, input));
359  }
360  this->template log<log::Logger::linop_factory_generate_completed>(
361  this, input.get(), generated.get());
362  return generated;
363  }
364 };
365 
366 
393 public:
394  virtual ~Transposable() = default;
395 
401  virtual std::unique_ptr<LinOp> transpose() const = 0;
402 
409  virtual std::unique_ptr<LinOp> conj_transpose() const = 0;
410 };
411 
412 
442 template <typename IndexType>
443 class Permutable {
444 public:
445  virtual ~Permutable() = default;
446 
461  virtual std::unique_ptr<LinOp> permute(
462  const array<IndexType>* permutation_indices) const
463  {
464  return as<Permutable>(this->row_permute(permutation_indices))
465  ->column_permute(permutation_indices);
466  }
467 
482  virtual std::unique_ptr<LinOp> inverse_permute(
483  const array<IndexType>* permutation_indices) const
484  {
485  return as<Permutable>(this->inverse_row_permute(permutation_indices))
486  ->inverse_column_permute(permutation_indices);
487  }
488 
502  virtual std::unique_ptr<LinOp> row_permute(
503  const array<IndexType>* permutation_indices) const = 0;
504 
519  virtual std::unique_ptr<LinOp> column_permute(
520  const array<IndexType>* permutation_indices) const = 0;
521 
535  virtual std::unique_ptr<LinOp> inverse_row_permute(
536  const array<IndexType>* permutation_indices) const = 0;
537 
552  virtual std::unique_ptr<LinOp> inverse_column_permute(
553  const array<IndexType>* permutation_indices) const = 0;
554 };
555 
556 
563 template <typename ValueType, typename IndexType>
565 public:
566  using value_type = ValueType;
567  using index_type = IndexType;
568 
569  virtual ~ReadableFromMatrixData() = default;
570 
576  virtual void read(const matrix_data<ValueType, IndexType>& data) = 0;
577 
584  {
585  this->read(data.get_ordered_data());
586  }
587 
594  {
595  this->read(data.copy_to_host());
596  }
597 
605  {
606  this->read(data.copy_to_host());
607  data.empty_out();
608  }
609 };
610 
611 
618 template <typename ValueType, typename IndexType>
620 public:
621  using value_type = ValueType;
622  using index_type = IndexType;
623 
624  virtual ~WritableToMatrixData() = default;
625 
631  virtual void write(matrix_data<ValueType, IndexType>& data) const = 0;
632 };
633 
634 
642 public:
643  virtual ~Preconditionable() = default;
644 
650  virtual std::shared_ptr<const LinOp> get_preconditioner() const
651  {
652  return preconditioner_;
653  }
654 
661  virtual void set_preconditioner(std::shared_ptr<const LinOp> new_precond)
662  {
663  preconditioner_ = new_precond;
664  }
665 
666 private:
667  std::shared_ptr<const LinOp> preconditioner_{};
668 };
669 
670 
682 public:
683  virtual ~DiagonalLinOpExtractable() = default;
684 
690  virtual std::unique_ptr<LinOp> extract_diagonal_linop() const = 0;
691 };
692 
693 
701 template <typename ValueType>
703 public:
704  using value_type = ValueType;
705 
706  virtual ~DiagonalExtractable() = default;
707 
708  std::unique_ptr<LinOp> extract_diagonal_linop() const override;
709 
715  virtual std::unique_ptr<matrix::Diagonal<ValueType>> extract_diagonal()
716  const = 0;
717 };
718 
719 
726 public:
732  virtual std::unique_ptr<LinOp> compute_absolute_linop() const = 0;
733 
737  virtual void compute_absolute_inplace() = 0;
738 };
739 
740 
752 template <typename AbsoluteLinOp>
754 public:
755  using absolute_type = AbsoluteLinOp;
756 
757  virtual ~EnableAbsoluteComputation() = default;
758 
759  std::unique_ptr<LinOp> compute_absolute_linop() const override
760  {
761  return this->compute_absolute();
762  }
763 
769  virtual std::unique_ptr<absolute_type> compute_absolute() const = 0;
770 };
771 
772 
778 public:
787  ptr_param<const LinOp> const b)
788  {
789  GKO_ASSERT_IS_SCALAR(a);
790  GKO_ASSERT_IS_SCALAR(b);
791  auto ae = make_temporary_clone(as<LinOp>(this)->get_executor(), a);
792  auto be = make_temporary_clone(as<LinOp>(this)->get_executor(), b);
793  add_scaled_identity_impl(ae.get(), be.get());
794  }
795 
796 private:
797  virtual void add_scaled_identity_impl(const LinOp* a, const LinOp* b) = 0;
798 };
799 
800 
835 template <typename ConcreteLinOp, typename PolymorphicBase = LinOp>
837  : public EnablePolymorphicObject<ConcreteLinOp, PolymorphicBase>,
838  public EnablePolymorphicAssignment<ConcreteLinOp> {
839 public:
840  using EnablePolymorphicObject<ConcreteLinOp,
841  PolymorphicBase>::EnablePolymorphicObject;
842  using PolymorphicBase::apply;
843 
844 protected:
845  GKO_ENABLE_SELF(ConcreteLinOp);
846 };
847 
848 
866 template <typename ConcreteFactory, typename ConcreteLinOp,
867  typename ParametersType, typename PolymorphicBase = LinOpFactory>
869  EnableDefaultFactory<ConcreteFactory, ConcreteLinOp, ParametersType,
870  PolymorphicBase>;
871 
872 
948 #define GKO_ENABLE_LIN_OP_FACTORY(_lin_op, _parameters_name, _factory_name) \
949 public: \
950  const _parameters_name##_type& get_##_parameters_name() const \
951  { \
952  return _parameters_name##_; \
953  } \
954  \
955  class _factory_name \
956  : public ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
957  _parameters_name##_type> { \
958  friend class ::gko::EnablePolymorphicObject<_factory_name, \
959  ::gko::LinOpFactory>; \
960  friend class ::gko::enable_parameters_type<_parameters_name##_type, \
961  _factory_name>; \
962  explicit _factory_name(std::shared_ptr<const ::gko::Executor> exec) \
963  : ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
964  _parameters_name##_type>( \
965  std::move(exec)) \
966  {} \
967  explicit _factory_name(std::shared_ptr<const ::gko::Executor> exec, \
968  const _parameters_name##_type& parameters) \
969  : ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
970  _parameters_name##_type>( \
971  std::move(exec), parameters) \
972  {} \
973  }; \
974  friend ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
975  _parameters_name##_type>; \
976  \
977  \
978 private: \
979  _parameters_name##_type _parameters_name##_; \
980  \
981 public: \
982  static_assert(true, \
983  "This assert is used to counter the false positive extra " \
984  "semi-colon warnings")
985 
986 
987 } // namespace gko
988 
989 
990 #endif // GKO_PUBLIC_CORE_BASE_LIN_OP_HPP_
gko::device_matrix_data::copy_to_host
host_type copy_to_host() const
Copies the device_matrix_data entries to the host to return a regular matrix_data object with the sam...
gko::read
std::unique_ptr< MatrixType > read(StreamType &&is, MatrixArgs &&... args)
Reads a matrix stored in matrix market format from an input stream.
Definition: mtx_io.hpp:160
gko::ScaledIdentityAddable::add_scaled_identity
void add_scaled_identity(ptr_param< const LinOp > const a, ptr_param< const LinOp > const b)
Scales this and adds another scalar times the identity to it.
Definition: lin_op.hpp:786
gko::LinOp
Definition: lin_op.hpp:117
gko::Preconditionable
A LinOp implementing this interface can be preconditioned.
Definition: lin_op.hpp:641
gko::DiagonalExtractable
The diagonal of a LinOp implementing this interface can be extracted.
Definition: lin_op.hpp:702
gko::AbstractFactory
The AbstractFactory is a generic interface template that enables easy implementation of the abstract ...
Definition: abstract_factory.hpp:45
gko::DiagonalLinOpExtractable
The diagonal of a LinOp can be extracted.
Definition: lin_op.hpp:681
gko::LinOp::LinOp
LinOp(LinOp &&other)
Move-constructs a LinOp.
Definition: lin_op.hpp:205
gko::AbstractFactory::generate
std::unique_ptr< abstract_product_type > generate(Args &&... args) const
Creates a new product from the given components.
Definition: abstract_factory.hpp:67
gko::Permutable::permute
virtual std::unique_ptr< LinOp > permute(const array< IndexType > *permutation_indices) const
Returns a LinOp representing the symmetric row and column permutation of the Permutable object.
Definition: lin_op.hpp:461
gko::EnableAbstractPolymorphicObject
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition: polymorphic_object.hpp:354
gko::Transposable
Linear operators which support transposition should implement the Transposable interface.
Definition: lin_op.hpp:392
gko::AbsoluteComputable
The AbsoluteComputable is an interface that allows to get the component wise absolute of a LinOp.
Definition: lin_op.hpp:725
gko::ptr_param::get
T * get() const
Definition: utils_helper.hpp:75
gko::AbsoluteComputable::compute_absolute_linop
virtual std::unique_ptr< LinOp > compute_absolute_linop() const =0
Gets the absolute LinOp.
gko::EnableDefaultFactory
This mixin provides a default implementation of a concrete factory.
Definition: abstract_factory.hpp:124
gko::EnablePolymorphicAssignment
This mixin is used to enable a default PolymorphicObject::copy_from() implementation for objects that...
Definition: polymorphic_object.hpp:743
gko::LinOp::apply
void apply(ptr_param< const LinOp > b, ptr_param< LinOp > x) const
Applies a linear operator to a vector (or a sequence of vectors).
Definition: lin_op.hpp:127
gko::clone
detail::cloned_type< Pointer > clone(const Pointer &p)
Creates a unique clone of the object pointed to by p.
Definition: utils_helper.hpp:173
gko::Permutable
Linear operators which support permutation should implement the Permutable interface.
Definition: lin_op.hpp:443
gko::LinOp::operator=
LinOp & operator=(LinOp &&other)
Move-assigns a LinOp.
Definition: lin_op.hpp:188
gko::Preconditionable::get_preconditioner
virtual std::shared_ptr< const LinOp > get_preconditioner() const
Returns the preconditioner operator used by the Preconditionable.
Definition: lin_op.hpp:650
gko
The Ginkgo namespace.
Definition: abstract_factory.hpp:20
gko::ReadableFromMatrixData::read
virtual void read(const device_matrix_data< ValueType, IndexType > &data)
Reads a matrix from a device_matrix_data structure.
Definition: lin_op.hpp:593
gko::array< IndexType >
gko::ReadableFromMatrixData::read
void read(const matrix_assembly_data< ValueType, IndexType > &data)
Reads a matrix from a matrix_assembly_data structure.
Definition: lin_op.hpp:583
gko::dim< 2 >
gko::matrix_data
This structure is used as an intermediate data type to store a sparse matrix.
Definition: matrix_data.hpp:126
gko::LinOp::apply_uses_initial_guess
virtual bool apply_uses_initial_guess() const
Returns true if the linear operator uses the data given in x as an initial guess.
Definition: lin_op.hpp:178
gko::Permutable::inverse_permute
virtual std::unique_ptr< LinOp > inverse_permute(const array< IndexType > *permutation_indices) const
Returns a LinOp representing the symmetric inverse row and column permutation of the Permutable objec...
Definition: lin_op.hpp:482
gko::matrix::Diagonal
This class is a utility which efficiently implements the diagonal matrix (a linear operator which sca...
Definition: lin_op.hpp:31
gko::matrix_assembly_data::get_ordered_data
matrix_data< ValueType, IndexType > get_ordered_data() const
Definition: matrix_assembly_data.hpp:142
gko::Preconditionable::set_preconditioner
virtual void set_preconditioner(std::shared_ptr< const LinOp > new_precond)
Sets the preconditioner operator used by the Preconditionable.
Definition: lin_op.hpp:661
gko::ptr_param
This class is used for function parameters in the place of raw pointers.
Definition: utils_helper.hpp:41
gko::LinOp::apply
void apply(ptr_param< const LinOp > alpha, ptr_param< const LinOp > b, ptr_param< const LinOp > beta, ptr_param< LinOp > x) const
Performs the operation x = alpha * op(b) + beta * x.
Definition: lin_op.hpp:148
gko::AbsoluteComputable::compute_absolute_inplace
virtual void compute_absolute_inplace()=0
Compute absolute inplace on each element.
gko::ReadableFromMatrixData::read
virtual void read(device_matrix_data< ValueType, IndexType > &&data)
Reads a matrix from a device_matrix_data structure.
Definition: lin_op.hpp:604
gko::ReadableFromMatrixData
A LinOp implementing this interface can read its data from a matrix_data structure.
Definition: lin_op.hpp:564
gko::WritableToMatrixData
A LinOp implementing this interface can write its data to a matrix_data structure.
Definition: lin_op.hpp:619
gko::LinOp::operator=
LinOp & operator=(const LinOp &)=default
Copy-assigns a LinOp.
gko::write
void write(StreamType &&os, MatrixPtrType &&matrix, layout_type layout=detail::mtx_io_traits< std::remove_cv_t< detail::pointee< MatrixPtrType >>>::default_layout)
Writes a matrix into an output stream in matrix market format.
Definition: mtx_io.hpp:299
gko::transpose
batch_dim< 2, DimensionType > transpose(const batch_dim< 2, DimensionType > &input)
Returns a batch_dim object with its dimensions swapped for batched operators.
Definition: batch_dim.hpp:119
gko::ScaledIdentityAddable
Adds the operation M <- a I + b M for matrix M, identity operator I and scalars a and b,...
Definition: lin_op.hpp:777
gko::matrix_assembly_data
This structure is used as an intermediate type to assemble a sparse matrix.
Definition: matrix_assembly_data.hpp:59
gko::EnableAbsoluteComputation::compute_absolute
virtual std::unique_ptr< absolute_type > compute_absolute() const =0
Gets the AbsoluteLinOp.
gko::make_temporary_clone
detail::temporary_clone< detail::pointee< Ptr > > make_temporary_clone(std::shared_ptr< const Executor > exec, Ptr &&ptr)
Creates a temporary_clone.
Definition: temporary_clone.hpp:208
gko::EnableAbsoluteComputation
The EnableAbsoluteComputation mixin provides the default implementations of compute_absolute_linop an...
Definition: lin_op.hpp:753
gko::LinOpFactory
A LinOpFactory represents a higher order mapping which transforms one linear operator into another.
Definition: lin_op.hpp:343
gko::EnableAbsoluteComputation::compute_absolute_linop
std::unique_ptr< LinOp > compute_absolute_linop() const override
Gets the absolute LinOp.
Definition: lin_op.hpp:759
gko::PolymorphicObject::get_executor
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition: polymorphic_object.hpp:243
gko::LinOp::get_size
const dim< 2 > & get_size() const noexcept
Returns the size of the operator.
Definition: lin_op.hpp:169
gko::device_matrix_data
This type is a device-side equivalent to matrix_data.
Definition: device_matrix_data.hpp:36
gko::EnableLinOp
The EnableLinOp mixin can be used to provide sensible default implementations of the majority of the ...
Definition: lin_op.hpp:836
gko::LinOp::LinOp
LinOp(const LinOp &)=default
Copy-constructs a LinOp.
gko::EnablePolymorphicObject
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition: polymorphic_object.hpp:667