Ginkgo  Generated from pipelines/1478841010 branch based on develop. Ginkgo version 1.9.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 #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:
130  {
131  this->template log<log::Logger::linop_apply_started>(this, b.get(),
132  x.get());
133  this->validate_application_parameters(b.get(), x.get());
134  auto exec = this->get_executor();
135  this->apply_impl(make_temporary_clone(exec, b).get(),
136  make_temporary_clone(exec, x).get());
137  this->template log<log::Logger::linop_apply_completed>(this, b.get(),
138  x.get());
139  return this;
140  }
141 
146  {
147  this->template log<log::Logger::linop_apply_started>(this, b.get(),
148  x.get());
149  this->validate_application_parameters(b.get(), x.get());
150  auto exec = this->get_executor();
151  this->apply_impl(make_temporary_clone(exec, b).get(),
152  make_temporary_clone(exec, x).get());
153  this->template log<log::Logger::linop_apply_completed>(this, b.get(),
154  x.get());
155  return this;
156  }
157 
170  {
171  this->template log<log::Logger::linop_advanced_apply_started>(
172  this, alpha.get(), b.get(), beta.get(), x.get());
173  this->validate_application_parameters(alpha.get(), b.get(), beta.get(),
174  x.get());
175  auto exec = this->get_executor();
176  this->apply_impl(make_temporary_clone(exec, alpha).get(),
177  make_temporary_clone(exec, b).get(),
178  make_temporary_clone(exec, beta).get(),
179  make_temporary_clone(exec, x).get());
180  this->template log<log::Logger::linop_advanced_apply_completed>(
181  this, alpha.get(), b.get(), beta.get(), x.get());
182  return this;
183  }
184 
190  {
191  this->template log<log::Logger::linop_advanced_apply_started>(
192  this, alpha.get(), b.get(), beta.get(), x.get());
193  this->validate_application_parameters(alpha.get(), b.get(), beta.get(),
194  x.get());
195  auto exec = this->get_executor();
196  this->apply_impl(make_temporary_clone(exec, alpha).get(),
197  make_temporary_clone(exec, b).get(),
198  make_temporary_clone(exec, beta).get(),
199  make_temporary_clone(exec, x).get());
200  this->template log<log::Logger::linop_advanced_apply_completed>(
201  this, alpha.get(), b.get(), beta.get(), x.get());
202  return this;
203  }
204 
210  const dim<2>& get_size() const noexcept { return size_; }
211 
219  virtual bool apply_uses_initial_guess() const { return false; }
220 
222  LinOp& operator=(const LinOp&) = default;
223 
230  {
231  if (this != &other) {
233  this->set_size(other.get_size());
234  other.set_size({});
235  }
236  return *this;
237  }
238 
240  LinOp(const LinOp&) = default;
241 
246  LinOp(LinOp&& other)
247  : EnableAbstractPolymorphicObject<LinOp>(std::move(other)),
248  size_{std::exchange(other.size_, dim<2>{})}
249  {}
250 
251 protected:
258  explicit LinOp(std::shared_ptr<const Executor> exec,
259  const dim<2>& size = dim<2>{})
260  : EnableAbstractPolymorphicObject<LinOp>(exec), size_{size}
261  {}
262 
268  void set_size(const dim<2>& value) noexcept { size_ = value; }
269 
279  virtual void apply_impl(const LinOp* b, LinOp* x) const = 0;
280 
290  virtual void apply_impl(const LinOp* alpha, const LinOp* b,
291  const LinOp* beta, LinOp* x) const = 0;
292 
300  void validate_application_parameters(const LinOp* b, const LinOp* x) const
301  {
302  GKO_ASSERT_CONFORMANT(this, b);
303  GKO_ASSERT_EQUAL_ROWS(this, x);
304  GKO_ASSERT_EQUAL_COLS(b, x);
305  }
306 
316  void validate_application_parameters(const LinOp* alpha, const LinOp* b,
317  const LinOp* beta,
318  const LinOp* x) const
319  {
320  this->validate_application_parameters(b, x);
321  GKO_ASSERT_EQUAL_DIMENSIONS(alpha, dim<2>(1, 1));
322  GKO_ASSERT_EQUAL_DIMENSIONS(beta, dim<2>(1, 1));
323  }
324 
325 private:
326  dim<2> size_{};
327 };
328 
329 
386 public:
388 
389  std::unique_ptr<LinOp> generate(std::shared_ptr<const LinOp> input) const
390  {
391  this->template log<log::Logger::linop_factory_generate_started>(
392  this, input.get());
393  const auto exec = this->get_executor();
394  std::unique_ptr<LinOp> generated;
395  if (input->get_executor() == exec) {
396  generated = this->AbstractFactory::generate(input);
397  } else {
398  generated =
399  this->AbstractFactory::generate(gko::clone(exec, input));
400  }
401  this->template log<log::Logger::linop_factory_generate_completed>(
402  this, input.get(), generated.get());
403  return generated;
404  }
405 };
406 
407 
434 public:
435  virtual ~Transposable() = default;
436 
442  virtual std::unique_ptr<LinOp> transpose() const = 0;
443 
450  virtual std::unique_ptr<LinOp> conj_transpose() const = 0;
451 };
452 
453 
483 template <typename IndexType>
484 class Permutable {
485 public:
486  virtual ~Permutable() = default;
487 
502  virtual std::unique_ptr<LinOp> permute(
503  const array<IndexType>* permutation_indices) const
504  {
505  return as<Permutable>(this->row_permute(permutation_indices))
506  ->column_permute(permutation_indices);
507  }
508 
523  virtual std::unique_ptr<LinOp> inverse_permute(
524  const array<IndexType>* permutation_indices) const
525  {
526  return as<Permutable>(this->inverse_row_permute(permutation_indices))
527  ->inverse_column_permute(permutation_indices);
528  }
529 
543  virtual std::unique_ptr<LinOp> row_permute(
544  const array<IndexType>* permutation_indices) const = 0;
545 
560  virtual std::unique_ptr<LinOp> column_permute(
561  const array<IndexType>* permutation_indices) const = 0;
562 
576  virtual std::unique_ptr<LinOp> inverse_row_permute(
577  const array<IndexType>* permutation_indices) const = 0;
578 
593  virtual std::unique_ptr<LinOp> inverse_column_permute(
594  const array<IndexType>* permutation_indices) const = 0;
595 };
596 
597 
604 template <typename ValueType, typename IndexType>
606 public:
607  using value_type = ValueType;
608  using index_type = IndexType;
609 
610  virtual ~ReadableFromMatrixData() = default;
611 
617  virtual void read(const matrix_data<ValueType, IndexType>& data) = 0;
618 
625  {
626  this->read(data.get_ordered_data());
627  }
628 
635  {
636  this->read(data.copy_to_host());
637  }
638 
646  {
647  this->read(data.copy_to_host());
648  data.empty_out();
649  }
650 };
651 
652 
659 template <typename ValueType, typename IndexType>
661 public:
662  using value_type = ValueType;
663  using index_type = IndexType;
664 
665  virtual ~WritableToMatrixData() = default;
666 
672  virtual void write(matrix_data<ValueType, IndexType>& data) const = 0;
673 };
674 
675 
683 public:
684  virtual ~Preconditionable() = default;
685 
691  virtual std::shared_ptr<const LinOp> get_preconditioner() const
692  {
693  return preconditioner_;
694  }
695 
702  virtual void set_preconditioner(std::shared_ptr<const LinOp> new_precond)
703  {
704  preconditioner_ = new_precond;
705  }
706 
707 private:
708  std::shared_ptr<const LinOp> preconditioner_{};
709 };
710 
711 
723 public:
724  virtual ~DiagonalLinOpExtractable() = default;
725 
731  virtual std::unique_ptr<LinOp> extract_diagonal_linop() const = 0;
732 };
733 
734 
742 template <typename ValueType>
744 public:
745  using value_type = ValueType;
746 
747  virtual ~DiagonalExtractable() = default;
748 
749  std::unique_ptr<LinOp> extract_diagonal_linop() const override;
750 
756  virtual std::unique_ptr<matrix::Diagonal<ValueType>> extract_diagonal()
757  const = 0;
758 };
759 
760 
767 public:
773  virtual std::unique_ptr<LinOp> compute_absolute_linop() const = 0;
774 
778  virtual void compute_absolute_inplace() = 0;
779 };
780 
781 
793 template <typename AbsoluteLinOp>
795 public:
796  using absolute_type = AbsoluteLinOp;
797 
798  virtual ~EnableAbsoluteComputation() = default;
799 
800  std::unique_ptr<LinOp> compute_absolute_linop() const override
801  {
802  return this->compute_absolute();
803  }
804 
810  virtual std::unique_ptr<absolute_type> compute_absolute() const = 0;
811 };
812 
813 
819 public:
828  ptr_param<const LinOp> const b)
829  {
830  GKO_ASSERT_IS_SCALAR(a);
831  GKO_ASSERT_IS_SCALAR(b);
832  auto ae = make_temporary_clone(as<LinOp>(this)->get_executor(), a);
833  auto be = make_temporary_clone(as<LinOp>(this)->get_executor(), b);
834  add_scaled_identity_impl(ae.get(), be.get());
835  }
836 
837 private:
838  virtual void add_scaled_identity_impl(const LinOp* a, const LinOp* b) = 0;
839 };
840 
841 
876 template <typename ConcreteLinOp, typename PolymorphicBase = LinOp>
878  : public EnablePolymorphicObject<ConcreteLinOp, PolymorphicBase>,
879  public EnablePolymorphicAssignment<ConcreteLinOp> {
880 public:
881  using EnablePolymorphicObject<ConcreteLinOp,
882  PolymorphicBase>::EnablePolymorphicObject;
883 
884  const ConcreteLinOp* apply(ptr_param<const LinOp> b,
885  ptr_param<LinOp> x) const
886  {
887  PolymorphicBase::apply(b, x);
888  return self();
889  }
890 
891  ConcreteLinOp* apply(ptr_param<const LinOp> b, ptr_param<LinOp> x)
892  {
893  PolymorphicBase::apply(b, x);
894  return self();
895  }
896 
897  const ConcreteLinOp* apply(ptr_param<const LinOp> alpha,
900  ptr_param<LinOp> x) const
901  {
902  PolymorphicBase::apply(alpha, b, beta, x);
903  return self();
904  }
905 
906  ConcreteLinOp* apply(ptr_param<const LinOp> alpha, ptr_param<const LinOp> b,
908  {
909  PolymorphicBase::apply(alpha, b, beta, x);
910  return self();
911  }
912 
913 protected:
914  GKO_ENABLE_SELF(ConcreteLinOp);
915 };
916 
917 
935 template <typename ConcreteFactory, typename ConcreteLinOp,
936  typename ParametersType, typename PolymorphicBase = LinOpFactory>
938  EnableDefaultFactory<ConcreteFactory, ConcreteLinOp, ParametersType,
939  PolymorphicBase>;
940 
941 
1017 #define GKO_ENABLE_LIN_OP_FACTORY(_lin_op, _parameters_name, _factory_name) \
1018 public: \
1019  const _parameters_name##_type& get_##_parameters_name() const \
1020  { \
1021  return _parameters_name##_; \
1022  } \
1023  \
1024  class _factory_name \
1025  : public ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
1026  _parameters_name##_type> { \
1027  friend class ::gko::EnablePolymorphicObject<_factory_name, \
1028  ::gko::LinOpFactory>; \
1029  friend class ::gko::enable_parameters_type<_parameters_name##_type, \
1030  _factory_name>; \
1031  explicit _factory_name(std::shared_ptr<const ::gko::Executor> exec) \
1032  : ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
1033  _parameters_name##_type>( \
1034  std::move(exec)) \
1035  {} \
1036  explicit _factory_name(std::shared_ptr<const ::gko::Executor> exec, \
1037  const _parameters_name##_type& parameters) \
1038  : ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
1039  _parameters_name##_type>( \
1040  std::move(exec), parameters) \
1041  {} \
1042  }; \
1043  friend ::gko::EnableDefaultLinOpFactory<_factory_name, _lin_op, \
1044  _parameters_name##_type>; \
1045  \
1046  \
1047 private: \
1048  _parameters_name##_type _parameters_name##_; \
1049  \
1050 public: \
1051  static_assert(true, \
1052  "This assert is used to counter the false positive extra " \
1053  "semi-colon warnings")
1054 
1055 
1056 } // namespace gko
1057 
1058 
1059 #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:159
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:827
gko::LinOp
Definition: lin_op.hpp:117
gko::Preconditionable
A LinOp implementing this interface can be preconditioned.
Definition: lin_op.hpp:682
gko::DiagonalExtractable
The diagonal of a LinOp implementing this interface can be extracted.
Definition: lin_op.hpp:743
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:145
gko::DiagonalLinOpExtractable
The diagonal of a LinOp can be extracted.
Definition: lin_op.hpp:722
gko::LinOp::LinOp
LinOp(LinOp &&other)
Move-constructs a LinOp.
Definition: lin_op.hpp:246
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:502
gko::EnableAbstractPolymorphicObject
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition: polymorphic_object.hpp:345
gko::Transposable
Linear operators which support transposition should implement the Transposable interface.
Definition: lin_op.hpp:433
gko::AbsoluteComputable
The AbsoluteComputable is an interface that allows to get the component wise absolute of a LinOp.
Definition: lin_op.hpp:766
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:168
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:723
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:484
gko::LinOp::operator=
LinOp & operator=(LinOp &&other)
Move-assigns a LinOp.
Definition: lin_op.hpp:229
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:691
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:634
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:129
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:624
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:219
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:523
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:295
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:188
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:140
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:702
gko::ptr_param
This class is used for function parameters in the place of raw pointers.
Definition: utils_helper.hpp:41
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:645
gko::ReadableFromMatrixData
A LinOp implementing this interface can read its data from a matrix_data structure.
Definition: lin_op.hpp:605
gko::WritableToMatrixData
A LinOp implementing this interface can write its data to a matrix_data structure.
Definition: lin_op.hpp:660
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: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:818
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:794
gko::LinOpFactory
A LinOpFactory represents a higher order mapping which transforms one linear operator into another.
Definition: lin_op.hpp:384
gko::EnableAbsoluteComputation::compute_absolute_linop
std::unique_ptr< LinOp > compute_absolute_linop() const override
Gets the absolute LinOp.
Definition: lin_op.hpp:800
gko::PolymorphicObject::get_executor
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition: polymorphic_object.hpp:234
gko::LinOp::get_size
const dim< 2 > & get_size() const noexcept
Returns the size of the operator.
Definition: lin_op.hpp:210
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:877
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:661