Ginkgo Generated from branch based on main. Ginkgo version 1.9.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#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
26namespace gko {
27namespace matrix {
28
29
30template <typename ValueType>
31class Diagonal;
32
33
34} // namespace matrix
35
36
118public:
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 {
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());
181 this, alpha.get(), b.get(), beta.get(), x.get());
182 return this;
183 }
184
190 {
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());
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) {
232 EnableAbstractPolymorphicObject<LinOp>::operator=(std::move(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)
248 size_{std::exchange(other.size_, dim<2>{})}
249 {}
250
251protected:
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
325private:
326 dim<2> size_{};
327};
328
329
385 : public AbstractFactory<LinOp, std::shared_ptr<const LinOp>> {
386public:
387 using AbstractFactory<LinOp, std::shared_ptr<const LinOp>>::AbstractFactory;
388
389 std::unique_ptr<LinOp> generate(std::shared_ptr<const LinOp> input) const
390 {
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 }
402 this, input.get(), generated.get());
403 return generated;
404 }
405};
406
407
434public:
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
483template <typename IndexType>
485public:
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
604template <typename ValueType, typename IndexType>
606public:
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
659template <typename ValueType, typename IndexType>
661public:
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
683public:
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
707private:
708 std::shared_ptr<const LinOp> preconditioner_{};
709};
710
711
723public:
724 virtual ~DiagonalLinOpExtractable() = default;
725
731 virtual std::unique_ptr<LinOp> extract_diagonal_linop() const = 0;
732};
733
734
742template <typename ValueType>
744public:
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
767public:
773 virtual std::unique_ptr<LinOp> compute_absolute_linop() const = 0;
774
778 virtual void compute_absolute_inplace() = 0;
779};
780
781
793template <typename AbsoluteLinOp>
795public:
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
819public:
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
837private:
838 virtual void add_scaled_identity_impl(const LinOp* a, const LinOp* b) = 0;
839};
840
841
876template <typename ConcreteLinOp, typename PolymorphicBase = LinOp>
878 : public EnablePolymorphicObject<ConcreteLinOp, PolymorphicBase>,
879 public EnablePolymorphicAssignment<ConcreteLinOp> {
880public:
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
913protected:
914 GKO_ENABLE_SELF(ConcreteLinOp);
915};
916
917
935template <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) \
1018public: \
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 \
1047private: \
1048 _parameters_name##_type _parameters_name##_; \
1049 \
1050public: \
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_
The AbsoluteComputable is an interface that allows to get the component wise absolute of a LinOp.
Definition lin_op.hpp:766
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.
std::unique_ptr< abstract_product_type > generate(Args &&... args) const
Creates a new product from the given components.
Definition abstract_factory.hpp:67
The diagonal of a LinOp implementing this interface can be extracted.
Definition lin_op.hpp:743
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:722
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:794
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:800
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:345
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:879
This mixin is used to enable a default PolymorphicObject::copy_from() implementation for objects that...
Definition polymorphic_object.hpp:723
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:662
A LinOpFactory represents a higher order mapping which transforms one linear operator into another.
Definition lin_op.hpp:385
Definition lin_op.hpp:117
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
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:219
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
const dim< 2 > & get_size() const noexcept
Returns the size of the operator.
Definition lin_op.hpp:210
LinOp(LinOp &&other)
Move-constructs a LinOp.
Definition lin_op.hpp:246
LinOp & operator=(LinOp &&other)
Move-assigns a LinOp.
Definition lin_op.hpp:229
const LinOp * apply(ptr_param< const LinOp > b, ptr_param< LinOp > x) const
Definition lin_op.hpp:145
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
LinOp & operator=(const LinOp &)=default
Copy-assigns a LinOp.
Linear operators which support permutation should implement the Permutable interface.
Definition lin_op.hpp:484
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:523
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:502
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition polymorphic_object.hpp:234
A LinOp implementing this interface can be preconditioned.
Definition lin_op.hpp:682
virtual void set_preconditioner(std::shared_ptr< const LinOp > new_precond)
Sets the preconditioner operator used by the Preconditionable.
Definition lin_op.hpp:702
virtual std::shared_ptr< const LinOp > get_preconditioner() const
Returns the preconditioner operator used by the Preconditionable.
Definition lin_op.hpp:691
A LinOp implementing this interface can read its data from a matrix_data structure.
Definition lin_op.hpp:605
virtual void read(const device_matrix_data< ValueType, IndexType > &data)
Reads a matrix from a device_matrix_data structure.
Definition lin_op.hpp:634
virtual void read(device_matrix_data< ValueType, IndexType > &&data)
Reads a matrix from a device_matrix_data structure.
Definition lin_op.hpp:645
void read(const matrix_assembly_data< ValueType, IndexType > &data)
Reads a matrix from a matrix_assembly_data structure.
Definition lin_op.hpp:624
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:818
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
Linear operators which support transposition should implement the Transposable interface.
Definition lin_op.hpp:433
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:660
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 array.hpp:166
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 class is a utility which efficiently implements the diagonal matrix (a linear operator which sca...
Definition diagonal.hpp:53
This structure is used as an intermediate type to assemble a sparse matrix.
Definition matrix_assembly_data.hpp:59
matrix_data< ValueType, IndexType > get_ordered_data() const
Definition matrix_assembly_data.hpp:140
This class is used for function parameters in the place of raw pointers.
Definition utils_helper.hpp:41
T * get() const
Definition utils_helper.hpp:75
EnableDefaultFactory< ConcreteFactory, ConcreteLinOp, ParametersType, PolymorphicBase > EnableDefaultLinOpFactory
This is an alias for the EnableDefaultFactory mixin, which correctly sets the template parameters to ...
Definition lin_op.hpp:937
The logger namespace .
Definition convergence.hpp:22
The matrix namespace.
Definition dense_cache.hpp:15
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:173
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
std::decay_t< T > * as(U *obj)
Performs polymorphic type conversion.
Definition utils_helper.hpp:307
STL namespace.
A type representing the dimensions of a multidimensional object.
Definition dim.hpp:26
This structure is used as an intermediate data type to store a sparse matrix.
Definition matrix_data.hpp:126