Ginkgo  Generated from pipelines/1330831941 branch based on master. Ginkgo version 1.8.0
A numerical linear algebra library targeting many-core architectures
lin_op.hpp
1 // SPDX-FileCopyrightText: 2017 - 2024 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 
14 #include <ginkgo/core/base/abstract_factory.hpp>
15 #include <ginkgo/core/base/device_matrix_data.hpp>
16 #include <ginkgo/core/base/dim.hpp>
17 #include <ginkgo/core/base/exception_helpers.hpp>
18 #include <ginkgo/core/base/math.hpp>
19 #include <ginkgo/core/base/matrix_assembly_data.hpp>
20 #include <ginkgo/core/base/matrix_data.hpp>
21 #include <ginkgo/core/base/polymorphic_object.hpp>
22 #include <ginkgo/core/base/types.hpp>
23 #include <ginkgo/core/base/utils.hpp>
24 #include <ginkgo/core/log/logger.hpp>
25 
26 
27 namespace gko {
28 namespace matrix {
29 
30 
31 template <typename ValueType>
32 class Diagonal;
33 
34 
35 } // namespace matrix
36 
37 
118 class LinOp : public EnableAbstractPolymorphicObject<LinOp> {
119 public:
131  {
132  this->template log<log::Logger::linop_apply_started>(this, b.get(),
133  x.get());
134  this->validate_application_parameters(b.get(), x.get());
135  auto exec = this->get_executor();
136  this->apply_impl(make_temporary_clone(exec, b).get(),
137  make_temporary_clone(exec, x).get());
138  this->template log<log::Logger::linop_apply_completed>(this, b.get(),
139  x.get());
140  return this;
141  }
142 
147  {
148  this->template log<log::Logger::linop_apply_started>(this, b.get(),
149  x.get());
150  this->validate_application_parameters(b.get(), x.get());
151  auto exec = this->get_executor();
152  this->apply_impl(make_temporary_clone(exec, b).get(),
153  make_temporary_clone(exec, x).get());
154  this->template log<log::Logger::linop_apply_completed>(this, b.get(),
155  x.get());
156  return this;
157  }
158 
171  {
172  this->template log<log::Logger::linop_advanced_apply_started>(
173  this, alpha.get(), b.get(), beta.get(), x.get());
174  this->validate_application_parameters(alpha.get(), b.get(), beta.get(),
175  x.get());
176  auto exec = this->get_executor();
177  this->apply_impl(make_temporary_clone(exec, alpha).get(),
178  make_temporary_clone(exec, b).get(),
179  make_temporary_clone(exec, beta).get(),
180  make_temporary_clone(exec, x).get());
181  this->template log<log::Logger::linop_advanced_apply_completed>(
182  this, alpha.get(), b.get(), beta.get(), x.get());
183  return this;
184  }
185 
191  {
192  this->template log<log::Logger::linop_advanced_apply_started>(
193  this, alpha.get(), b.get(), beta.get(), x.get());
194  this->validate_application_parameters(alpha.get(), b.get(), beta.get(),
195  x.get());
196  auto exec = this->get_executor();
197  this->apply_impl(make_temporary_clone(exec, alpha).get(),
198  make_temporary_clone(exec, b).get(),
199  make_temporary_clone(exec, beta).get(),
200  make_temporary_clone(exec, x).get());
201  this->template log<log::Logger::linop_advanced_apply_completed>(
202  this, alpha.get(), b.get(), beta.get(), x.get());
203  return this;
204  }
205 
211  const dim<2>& get_size() const noexcept { return size_; }
212 
220  virtual bool apply_uses_initial_guess() const { return false; }
221 
223  LinOp& operator=(const LinOp&) = default;
224 
231  {
232  if (this != &other) {
234  this->set_size(other.get_size());
235  other.set_size({});
236  }
237  return *this;
238  }
239 
241  LinOp(const LinOp&) = default;
242 
247  LinOp(LinOp&& other)
248  : EnableAbstractPolymorphicObject<LinOp>(std::move(other)),
249  size_{std::exchange(other.size_, dim<2>{})}
250  {}
251 
252 protected:
259  explicit LinOp(std::shared_ptr<const Executor> exec,
260  const dim<2>& size = dim<2>{})
261  : EnableAbstractPolymorphicObject<LinOp>(exec), size_{size}
262  {}
263 
269  void set_size(const dim<2>& value) noexcept { size_ = value; }
270 
280  virtual void apply_impl(const LinOp* b, LinOp* x) const = 0;
281 
291  virtual void apply_impl(const LinOp* alpha, const LinOp* b,
292  const LinOp* beta, LinOp* x) const = 0;
293 
301  void validate_application_parameters(const LinOp* b, const LinOp* x) const
302  {
303  GKO_ASSERT_CONFORMANT(this, b);
304  GKO_ASSERT_EQUAL_ROWS(this, x);
305  GKO_ASSERT_EQUAL_COLS(b, x);
306  }
307 
317  void validate_application_parameters(const LinOp* alpha, const LinOp* b,
318  const LinOp* beta,
319  const LinOp* x) const
320  {
321  this->validate_application_parameters(b, x);
322  GKO_ASSERT_EQUAL_DIMENSIONS(alpha, dim<2>(1, 1));
323  GKO_ASSERT_EQUAL_DIMENSIONS(beta, dim<2>(1, 1));
324  }
325 
326 private:
327  dim<2> size_{};
328 };
329 
330 
387 public:
389 
390  std::unique_ptr<LinOp> generate(std::shared_ptr<const LinOp> input) const
391  {
392  this->template log<log::Logger::linop_factory_generate_started>(
393  this, input.get());
394  const auto exec = this->get_executor();
395  std::unique_ptr<LinOp> generated;
396  if (input->get_executor() == exec) {
397  generated = this->AbstractFactory::generate(input);
398  } else {
399  generated =
400  this->AbstractFactory::generate(gko::clone(exec, input));
401  }
402  this->template log<log::Logger::linop_factory_generate_completed>(
403  this, input.get(), generated.get());
404  return generated;
405  }
406 };
407 
408 
435 public:
436  virtual ~Transposable() = default;
437 
443  virtual std::unique_ptr<LinOp> transpose() const = 0;
444 
451  virtual std::unique_ptr<LinOp> conj_transpose() const = 0;
452 };
453 
454 
484 template <typename IndexType>
485 class Permutable {
486 public:
487  virtual ~Permutable() = default;
488 
503  virtual std::unique_ptr<LinOp> permute(
504  const array<IndexType>* permutation_indices) const
505  {
506  return as<Permutable>(this->row_permute(permutation_indices))
507  ->column_permute(permutation_indices);
508  }
509 
524  virtual std::unique_ptr<LinOp> inverse_permute(
525  const array<IndexType>* permutation_indices) const
526  {
527  return as<Permutable>(this->inverse_row_permute(permutation_indices))
528  ->inverse_column_permute(permutation_indices);
529  }
530 
544  virtual std::unique_ptr<LinOp> row_permute(
545  const array<IndexType>* permutation_indices) const = 0;
546 
561  virtual std::unique_ptr<LinOp> column_permute(
562  const array<IndexType>* permutation_indices) const = 0;
563 
577  virtual std::unique_ptr<LinOp> inverse_row_permute(
578  const array<IndexType>* permutation_indices) const = 0;
579 
594  virtual std::unique_ptr<LinOp> inverse_column_permute(
595  const array<IndexType>* permutation_indices) const = 0;
596 };
597 
598 
605 template <typename ValueType, typename IndexType>
607 public:
608  using value_type = ValueType;
609  using index_type = IndexType;
610 
611  virtual ~ReadableFromMatrixData() = default;
612 
618  virtual void read(const matrix_data<ValueType, IndexType>& data) = 0;
619 
626  {
627  this->read(data.get_ordered_data());
628  }
629 
636  {
637  this->read(data.copy_to_host());
638  }
639 
647  {
648  this->read(data.copy_to_host());
649  data.empty_out();
650  }
651 };
652 
653 
660 template <typename ValueType, typename IndexType>
662 public:
663  using value_type = ValueType;
664  using index_type = IndexType;
665 
666  virtual ~WritableToMatrixData() = default;
667 
673  virtual void write(matrix_data<ValueType, IndexType>& data) const = 0;
674 };
675 
676 
684 public:
685  virtual ~Preconditionable() = default;
686 
692  virtual std::shared_ptr<const LinOp> get_preconditioner() const
693  {
694  return preconditioner_;
695  }
696 
703  virtual void set_preconditioner(std::shared_ptr<const LinOp> new_precond)
704  {
705  preconditioner_ = new_precond;
706  }
707 
708 private:
709  std::shared_ptr<const LinOp> preconditioner_{};
710 };
711 
712 
724 public:
725  virtual ~DiagonalLinOpExtractable() = default;
726 
732  virtual std::unique_ptr<LinOp> extract_diagonal_linop() const = 0;
733 };
734 
735 
743 template <typename ValueType>
745 public:
746  using value_type = ValueType;
747 
748  virtual ~DiagonalExtractable() = default;
749 
750  std::unique_ptr<LinOp> extract_diagonal_linop() const override;
751 
757  virtual std::unique_ptr<matrix::Diagonal<ValueType>> extract_diagonal()
758  const = 0;
759 };
760 
761 
768 public:
774  virtual std::unique_ptr<LinOp> compute_absolute_linop() const = 0;
775 
779  virtual void compute_absolute_inplace() = 0;
780 };
781 
782 
794 template <typename AbsoluteLinOp>
796 public:
797  using absolute_type = AbsoluteLinOp;
798 
799  virtual ~EnableAbsoluteComputation() = default;
800 
801  std::unique_ptr<LinOp> compute_absolute_linop() const override
802  {
803  return this->compute_absolute();
804  }
805 
811  virtual std::unique_ptr<absolute_type> compute_absolute() const = 0;
812 };
813 
814 
820 public:
829  ptr_param<const LinOp> const b)
830  {
831  GKO_ASSERT_IS_SCALAR(a);
832  GKO_ASSERT_IS_SCALAR(b);
833  auto ae = make_temporary_clone(as<LinOp>(this)->get_executor(), a);
834  auto be = make_temporary_clone(as<LinOp>(this)->get_executor(), b);
835  add_scaled_identity_impl(ae.get(), be.get());
836  }
837 
838 private:
839  virtual void add_scaled_identity_impl(const LinOp* a, const LinOp* b) = 0;
840 };
841 
842 
877 template <typename ConcreteLinOp, typename PolymorphicBase = LinOp>
879  : public EnablePolymorphicObject<ConcreteLinOp, PolymorphicBase>,
880  public EnablePolymorphicAssignment<ConcreteLinOp> {
881 public:
882  using EnablePolymorphicObject<ConcreteLinOp,
883  PolymorphicBase>::EnablePolymorphicObject;
884 
885  const ConcreteLinOp* apply(ptr_param<const LinOp> b,
886  ptr_param<LinOp> x) const
887  {
888  PolymorphicBase::apply(b, x);
889  return self();
890  }
891 
892  ConcreteLinOp* apply(ptr_param<const LinOp> b, ptr_param<LinOp> x)
893  {
894  PolymorphicBase::apply(b, x);
895  return self();
896  }
897 
898  const ConcreteLinOp* apply(ptr_param<const LinOp> alpha,
901  ptr_param<LinOp> x) const
902  {
903  PolymorphicBase::apply(alpha, b, beta, x);
904  return self();
905  }
906 
907  ConcreteLinOp* apply(ptr_param<const LinOp> alpha, ptr_param<const LinOp> b,
909  {
910  PolymorphicBase::apply(alpha, b, beta, x);
911  return self();
912  }
913 
914 protected:
915  GKO_ENABLE_SELF(ConcreteLinOp);
916 };
917 
918 
936 template <typename ConcreteFactory, typename ConcreteLinOp,
937  typename ParametersType, typename PolymorphicBase = LinOpFactory>
939  EnableDefaultFactory<ConcreteFactory, ConcreteLinOp, ParametersType,
940  PolymorphicBase>;
941 
942 
1018 #define GKO_ENABLE_LIN_OP_FACTORY(_lin_op, _parameters_name, _factory_name) \
1019 public: \
1020  const _parameters_name##_type& get_##_parameters_name() const \
1021  { \
1022  return _parameters_name##_; \
1023  } \
1024  \
1025  class _factory_name \
1026  : public ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
1027  _parameters_name##_type> { \
1028  friend class ::gko::EnablePolymorphicObject<_factory_name, \
1029  ::gko::LinOpFactory>; \
1030  friend class ::gko::enable_parameters_type<_parameters_name##_type, \
1031  _factory_name>; \
1032  explicit _factory_name(std::shared_ptr<const ::gko::Executor> exec) \
1033  : ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
1034  _parameters_name##_type>( \
1035  std::move(exec)) \
1036  {} \
1037  explicit _factory_name(std::shared_ptr<const ::gko::Executor> exec, \
1038  const _parameters_name##_type& parameters) \
1039  : ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
1040  _parameters_name##_type>( \
1041  std::move(exec), parameters) \
1042  {} \
1043  }; \
1044  friend ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
1045  _parameters_name##_type>; \
1046  \
1047  \
1048 private: \
1049  _parameters_name##_type _parameters_name##_; \
1050  \
1051 public: \
1052  static_assert(true, \
1053  "This assert is used to counter the false positive extra " \
1054  "semi-colon warnings")
1055 
1056 
1057 } // namespace gko
1058 
1059 
1060 #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:828
gko::LinOp
Definition: lin_op.hpp:118
gko::Preconditionable
A LinOp implementing this interface can be preconditioned.
Definition: lin_op.hpp:683
gko::DiagonalExtractable
The diagonal of a LinOp implementing this interface can be extracted.
Definition: lin_op.hpp:744
gko::AbstractFactory
The AbstractFactory is a generic interface template that enables easy implementation of the abstract ...
Definition: abstract_factory.hpp:45
gko::LinOp::apply
const LinOp * apply(ptr_param< const LinOp > b, ptr_param< LinOp > x) const
Definition: lin_op.hpp:146
gko::DiagonalLinOpExtractable
The diagonal of a LinOp can be extracted.
Definition: lin_op.hpp:723
gko::LinOp::LinOp
LinOp(LinOp &&other)
Move-constructs a LinOp.
Definition: lin_op.hpp:247
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:503
gko::EnableAbstractPolymorphicObject
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition: polymorphic_object.hpp:346
gko::Transposable
Linear operators which support transposition should implement the Transposable interface.
Definition: lin_op.hpp:434
gko::AbsoluteComputable
The AbsoluteComputable is an interface that allows to get the component wise absolute of a LinOp.
Definition: lin_op.hpp:767
gko::LinOp::apply
LinOp * apply(ptr_param< const LinOp > alpha, ptr_param< const LinOp > b, ptr_param< const LinOp > beta, ptr_param< LinOp > x)
Performs the operation x = alpha * op(b) + beta * x.
Definition: lin_op.hpp:169
gko::ptr_param::get
T * get() const
Definition: utils_helper.hpp:77
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:724
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:175
gko::Permutable
Linear operators which support permutation should implement the Permutable interface.
Definition: lin_op.hpp:485
gko::LinOp::operator=
LinOp & operator=(LinOp &&other)
Move-assigns a LinOp.
Definition: lin_op.hpp:230
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:692
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:635
gko::LinOp::apply
LinOp * apply(ptr_param< const LinOp > b, ptr_param< LinOp > x)
Applies a linear operator to a vector (or a sequence of vectors).
Definition: lin_op.hpp:130
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:625
gko::dim< 2 >
gko::matrix_data
This structure is used as an intermediate data type to store a sparse matrix.
Definition: matrix_data.hpp:127
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:220
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:524
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:296
gko::LinOp::apply
const LinOp * apply(ptr_param< const LinOp > alpha, ptr_param< const LinOp > b, ptr_param< const LinOp > beta, ptr_param< LinOp > x) const
Definition: lin_op.hpp:189
gko::matrix::Diagonal
This class is a utility which efficiently implements the diagonal matrix (a linear operator which sca...
Definition: lin_op.hpp:32
gko::matrix_assembly_data::get_ordered_data
matrix_data< ValueType, IndexType > get_ordered_data() const
Definition: matrix_assembly_data.hpp:141
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:703
gko::ptr_param
This class is used for function parameters in the place of raw pointers.
Definition: utils_helper.hpp:43
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:646
gko::ReadableFromMatrixData
A LinOp implementing this interface can read its data from a matrix_data structure.
Definition: lin_op.hpp:606
gko::WritableToMatrixData
A LinOp implementing this interface can write its data to a matrix_data structure.
Definition: lin_op.hpp:661
gko::LinOp::operator=
LinOp & operator=(const LinOp &)=default
Copy-assigns a LinOp.
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:120
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:819
gko::matrix_assembly_data
This structure is used as an intermediate type to assemble a sparse matrix.
Definition: matrix_assembly_data.hpp:60
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:209
gko::EnableAbsoluteComputation
The EnableAbsoluteComputation mixin provides the default implementations of compute_absolute_linop an...
Definition: lin_op.hpp:795
gko::LinOpFactory
A LinOpFactory represents a higher order mapping which transforms one linear operator into another.
Definition: lin_op.hpp:385
gko::EnableAbsoluteComputation::compute_absolute_linop
std::unique_ptr< LinOp > compute_absolute_linop() const override
Gets the absolute LinOp.
Definition: lin_op.hpp:801
gko::PolymorphicObject::get_executor
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition: polymorphic_object.hpp:235
gko::LinOp::get_size
const dim< 2 > & get_size() const noexcept
Returns the size of the operator.
Definition: lin_op.hpp:211
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:878
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:662