Ginkgo Generated from branch based on master. Ginkgo version 1.8.0
A numerical linear algebra library targeting many-core architectures
Loading...
Searching...
No Matches
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
27namespace gko {
28namespace matrix {
29
30
31template <typename ValueType>
32class Diagonal;
33
34
35} // namespace matrix
36
37
119public:
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
252protected:
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
326private:
327 dim<2> size_{};
328};
329
330
387public:
388 using AbstractFactory<LinOp, std::shared_ptr<const LinOp>>::AbstractFactory;
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
435public:
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
484template <typename IndexType>
486public:
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
605template <typename ValueType, typename IndexType>
607public:
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
660template <typename ValueType, typename IndexType>
662public:
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
684public:
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
708private:
709 std::shared_ptr<const LinOp> preconditioner_{};
710};
711
712
724public:
725 virtual ~DiagonalLinOpExtractable() = default;
726
732 virtual std::unique_ptr<LinOp> extract_diagonal_linop() const = 0;
733};
734
735
743template <typename ValueType>
745public:
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
768public:
774 virtual std::unique_ptr<LinOp> compute_absolute_linop() const = 0;
775
779 virtual void compute_absolute_inplace() = 0;
780};
781
782
794template <typename AbsoluteLinOp>
796public:
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
820public:
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
838private:
839 virtual void add_scaled_identity_impl(const LinOp* a, const LinOp* b) = 0;
840};
841
842
877template <typename ConcreteLinOp, typename PolymorphicBase = LinOp>
879 : public EnablePolymorphicObject<ConcreteLinOp, PolymorphicBase>,
880 public EnablePolymorphicAssignment<ConcreteLinOp> {
881public:
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
914protected:
915 GKO_ENABLE_SELF(ConcreteLinOp);
916};
917
918
936template <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) \
1019public: \
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 \
1048private: \
1049 _parameters_name##_type _parameters_name##_; \
1050 \
1051public: \
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_
The AbsoluteComputable is an interface that allows to get the component wise absolute of a LinOp.
Definition lin_op.hpp:767
virtual void compute_absolute_inplace()=0
Compute absolute inplace on each element.
virtual std::unique_ptr< LinOp > compute_absolute_linop() const =0
Gets the absolute LinOp.
The AbstractFactory is a generic interface template that enables easy implementation of the abstract ...
Definition abstract_factory.hpp:47
The diagonal of a LinOp implementing this interface can be extracted.
Definition lin_op.hpp:744
std::unique_ptr< LinOp > extract_diagonal_linop() const override
Extracts the diagonal entries of the matrix into a vector.
virtual std::unique_ptr< matrix::Diagonal< ValueType > > extract_diagonal() const =0
Extracts the diagonal entries of the matrix into a vector.
The diagonal of a LinOp can be extracted.
Definition lin_op.hpp:723
virtual std::unique_ptr< LinOp > extract_diagonal_linop() const =0
Extracts the diagonal entries of the matrix into a vector.
The EnableAbsoluteComputation mixin provides the default implementations of compute_absolute_linop an...
Definition lin_op.hpp:795
virtual std::unique_ptr< absolute_type > compute_absolute() const =0
Gets the AbsoluteLinOp.
std::unique_ptr< LinOp > compute_absolute_linop() const override
Gets the absolute LinOp.
Definition lin_op.hpp:801
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:346
This mixin provides a default implementation of a concrete factory.
Definition abstract_factory.hpp:126
The EnableLinOp mixin can be used to provide sensible default implementations of the majority of the ...
Definition lin_op.hpp:880
This mixin is used to enable a default PolymorphicObject::copy_from() implementation for objects that...
Definition polymorphic_object.hpp:724
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:663
A LinOpFactory represents a higher order mapping which transforms one linear operator into another.
Definition lin_op.hpp:386
Definition lin_op.hpp:118
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
LinOp(const LinOp &)=default
Copy-constructs a LinOp.
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
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
const dim< 2 > & get_size() const noexcept
Returns the size of the operator.
Definition lin_op.hpp:211
LinOp(LinOp &&other)
Move-constructs a LinOp.
Definition lin_op.hpp:247
LinOp & operator=(LinOp &&other)
Move-assigns a LinOp.
Definition lin_op.hpp:230
const LinOp * apply(ptr_param< const LinOp > b, ptr_param< LinOp > x) const
Definition lin_op.hpp:146
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
LinOp & operator=(const LinOp &)=default
Copy-assigns a LinOp.
Linear operators which support permutation should implement the Permutable interface.
Definition lin_op.hpp:485
virtual std::unique_ptr< LinOp > inverse_column_permute(const array< IndexType > *permutation_indices) const =0
Returns a LinOp representing the row permutation of the inverse permuted object.
virtual std::unique_ptr< LinOp > row_permute(const array< IndexType > *permutation_indices) const =0
Returns a LinOp representing the row permutation of the Permutable object.
virtual std::unique_ptr< LinOp > inverse_row_permute(const array< IndexType > *permutation_indices) const =0
Returns a LinOp representing the row permutation of the inverse permuted object.
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
virtual std::unique_ptr< LinOp > column_permute(const array< IndexType > *permutation_indices) const =0
Returns a LinOp representing the column permutation of the Permutable object.
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
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition polymorphic_object.hpp:235
A LinOp implementing this interface can be preconditioned.
Definition lin_op.hpp:683
virtual void set_preconditioner(std::shared_ptr< const LinOp > new_precond)
Sets the preconditioner operator used by the Preconditionable.
Definition lin_op.hpp:703
virtual std::shared_ptr< const LinOp > get_preconditioner() const
Returns the preconditioner operator used by the Preconditionable.
Definition lin_op.hpp:692
A LinOp implementing this interface can read its data from a matrix_data structure.
Definition lin_op.hpp:606
virtual void read(const device_matrix_data< ValueType, IndexType > &data)
Reads a matrix from a device_matrix_data structure.
Definition lin_op.hpp:635
virtual void read(device_matrix_data< ValueType, IndexType > &&data)
Reads a matrix from a device_matrix_data structure.
Definition lin_op.hpp:646
void read(const matrix_assembly_data< ValueType, IndexType > &data)
Reads a matrix from a matrix_assembly_data structure.
Definition lin_op.hpp:625
virtual void read(const matrix_data< ValueType, IndexType > &data)=0
Reads a matrix from a matrix_data structure.
Adds the operation M <- a I + b M for matrix M, identity operator I and scalars a and b,...
Definition lin_op.hpp:819
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
Linear operators which support transposition should implement the Transposable interface.
Definition lin_op.hpp:434
virtual std::unique_ptr< LinOp > conj_transpose() const =0
Returns a LinOp representing the conjugate transpose of the Transposable object.
virtual std::unique_ptr< LinOp > transpose() const =0
Returns a LinOp representing the transpose of the Transposable object.
A LinOp implementing this interface can write its data to a matrix_data structure.
Definition lin_op.hpp:661
virtual void write(matrix_data< ValueType, IndexType > &data) const =0
Writes a matrix to a matrix_data structure.
An array is a container which encapsulates fixed-sized arrays, stored on the Executor tied to the arr...
Definition logger.hpp:25
This type is a device-side equivalent to matrix_data.
Definition device_matrix_data.hpp:36
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...
This structure is used as an intermediate type to assemble a sparse matrix.
Definition matrix_assembly_data.hpp:60
matrix_data< ValueType, IndexType > get_ordered_data() const
Definition matrix_assembly_data.hpp:141
This class is used for function parameters in the place of raw pointers.
Definition utils_helper.hpp:43
T * get() const
Definition utils_helper.hpp:77
The Ginkgo namespace.
Definition abstract_factory.hpp:20
detail::cloned_type< Pointer > clone(const Pointer &p)
Creates a unique clone of the object pointed to by p.
Definition utils_helper.hpp:175
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
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
A type representing the dimensions of a multidimensional object.
Definition dim.hpp:27
This structure is used as an intermediate data type to store a sparse matrix.
Definition matrix_data.hpp:127