Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
block_tensor_vector.hpp
Go to the documentation of this file.
1
7#pragma once
8
12
13#include <algorithm>
14#include <concepts>
15#include <cstddef>
16#include <functional>
17#include <stdexcept>
18#include <type_traits>
19#include <utility>
20#include <vector>
21
23{
24namespace detail
25{
26
27template <class Tensor> struct IsBlockTensorValue : std::false_type
28{};
29
30template <typename Scalar, class DomainType, class CodomainType, BlockTensorStorage Storage>
31struct IsBlockTensorValue<BlockTensor<Scalar, DomainType, CodomainType, Storage>> : std::true_type
32{};
33
34template <class View, class Tensor>
35concept CompatibleBlockVector =
36 BlockTensorView<View> && std::same_as<block_tensor_value_t<View>, typename Tensor::value_type> &&
37 std::same_as<block_tensor_domain_t<View>, typename Tensor::domain_type> &&
38 std::same_as<block_tensor_codomain_t<View>, typename Tensor::codomain_type> &&
39 std::same_as<typename block_tensor_type_t<View>::storage_policy, typename Tensor::storage_policy> &&
41
42} // namespace detail
43
51template <class Tensor> class BlockTensorVectorOps {
52 public:
53 using tensor_type = std::remove_cvref_t<Tensor>;
54 using scalar_type = typename tensor_type::value_type;
56 using domain_type = typename tensor_type::domain_type;
57 using codomain_type = typename tensor_type::codomain_type;
58 using key_type = typename tensor_type::key_type;
59 static_assert(detail::IsBlockTensorValue<tensor_type>::value,
60 "BlockTensorVectorOps requires an owning BlockTensor value");
61 static_assert(RealOrComplex<scalar_type>, "BlockTensorVectorOps requires a real or complex scalar type");
62
64 explicit BlockTensorVectorOps(tensor_type const& prototype)
65 : symmetry_(prototype.symmetry()), domain_(prototype.domain()), codomain_(prototype.codomain()),
66 dimension_(block_tensor_dimension(prototype))
67 {
68 auto const keys = prototype.stored_keys();
69 stored_keys_.assign(keys.begin(), keys.end());
70 }
71
73 [[nodiscard]] auto problem_dimension() const noexcept -> std::size_t { return dimension_; }
74
78 template <class Vector>
79 requires detail::CompatibleBlockVector<Vector, tensor_type>
80 [[nodiscard]] auto vector_dimension(Vector const& vector) const -> std::size_t
81 {
82 this->require_member(vector);
83 return dimension_;
84 }
85
88 template <class Vector>
89 requires detail::CompatibleBlockVector<Vector, tensor_type> &&
90 (std::is_lvalue_reference_v<Vector&&> || BorrowedBlockTensorView<Vector>)
91 [[nodiscard]] auto prototype_view(Vector&& vector) const
92 {
93 this->require_member(vector);
94 return as_block_tensor_view(std::as_const(vector));
95 }
96
101 [[nodiscard]] auto allocate_like(tensor_type const& vector) const -> tensor_type
102 {
103 this->require_member(vector);
104 if constexpr (requires { vector.allocate_like(uninitialized); })
105 {
106 return vector.allocate_like(uninitialized);
107 }
109 {
110 return tensor_type(uninitialized, symmetry_, domain_, codomain_);
111 }
112 else
113 {
114 return tensor_type(uninitialized, symmetry_, domain_, codomain_, stored_keys_);
115 }
116 }
117
119 template <BorrowedBlockTensorView View>
120 requires detail::CompatibleBlockVector<View, tensor_type>
121 [[nodiscard]] auto allocate_like(View const& view) const -> tensor_type
122 {
123 this->require_member(view);
125 {
126 if constexpr (requires { view.allocation_context(); })
127 return tensor_type(uninitialized, symmetry_, domain_, codomain_, view.allocation_context());
128 else
129 return tensor_type(uninitialized, symmetry_, domain_, codomain_);
130 }
131 else
132 {
133 if constexpr (requires { view.allocation_context(); })
134 return tensor_type(uninitialized, symmetry_, domain_, codomain_, stored_keys_, view.allocation_context());
135 else
136 return tensor_type(uninitialized, symmetry_, domain_, codomain_, stored_keys_);
137 }
138 }
139
141 void copy(tensor_type& output, tensor_type const& input) const
142 {
143 this->require_member(output);
144 this->require_member(input);
145 uni20::copy(output, input);
146 }
147
149 void axpy(tensor_type& output, scalar_type factor, tensor_type const& input) const
150 {
151 this->require_member(output);
152 this->require_member(input);
153 uni20::axpy(output, factor, input);
154 }
155
157 void scal(tensor_type& vector, scalar_type factor) const
158 {
159 this->require_member(vector);
160 uni20::scale(vector, factor);
161 }
162
164 void set_zero(tensor_type& vector) const
165 {
166 this->require_member(vector);
167 uni20::set_zero(vector);
168 }
169
171 [[nodiscard]] auto inner_product(tensor_type const& lhs, tensor_type const& rhs) const -> scalar_type
172 {
173 this->require_member(lhs);
174 this->require_member(rhs);
175 return uni20::inner_product_host(lhs, rhs);
176 }
177
179 [[nodiscard]] auto norm(tensor_type const& vector) const -> real_type
180 {
181 this->require_member(vector);
182 return uni20::norm_host(vector);
183 }
184
185 private:
186 [[nodiscard]] static auto block_tensor_dimension(tensor_type const& tensor) -> std::size_t
187 {
188 std::size_t dimension = 0;
189 for (std::size_t ordinal = 0; ordinal < tensor.stored_block_count(); ++ordinal)
190 {
191 auto block = tensor.block_by_ordinal(ordinal);
192 std::size_t block_dimension;
194 {
195 auto descriptor = mdspec_of(block);
196 block_dimension = static_cast<std::size_t>(diagonal_components(descriptor).extent(0));
197 }
198 else
199 {
200 block_dimension = 1;
201 for (std::size_t axis = 0; axis < tensor_type::dense_block_order(); ++axis)
202 block_dimension *= static_cast<std::size_t>(block.extent(axis));
203 }
204 dimension += block_dimension;
205 }
206 return dimension;
207 }
208
209 template <class Vector>
210 requires detail::CompatibleBlockVector<Vector, tensor_type>
211 void require_member(Vector const& vector) const
212 {
213 if (vector.symmetry() != symmetry_ || vector.domain() != domain_ || vector.codomain() != codomain_)
214 {
215 throw std::invalid_argument("BlockTensor Krylov vector has incompatible symmetry or boundaries");
216 }
217 if (!std::ranges::equal(vector.stored_keys(), stored_keys_))
218 {
219 throw std::invalid_argument("BlockTensor Krylov vector has a different stored-key pattern");
220 }
221 }
222
223 Symmetry symmetry_;
224 domain_type domain_;
225 codomain_type codomain_;
226 std::vector<key_type> stored_keys_;
227 std::size_t dimension_ = 0;
228};
229
237template <class Tensor, class Operator> class BlockTensorMatrixFreeOps : public BlockTensorVectorOps<Tensor> {
238 public:
241 using operator_type = std::remove_cvref_t<Operator>;
242 static_assert(std::invocable<operator_type&, tensor_type&, tensor_type const&>,
243 "BlockTensor matrix-free operation must be callable as operation(output, input)");
244 static_assert(std::same_as<std::invoke_result_t<operator_type&, tensor_type&, tensor_type const&>, void>,
245 "BlockTensor matrix-free operation must return void");
246
249 : base_type(prototype), operation_(std::move(operation))
250 {}
251
254 void matvec(tensor_type& output, tensor_type const& input)
255 {
256 static_cast<void>(this->vector_dimension(output));
257 static_cast<void>(this->vector_dimension(input));
258 std::invoke(operation_, output, input);
259 }
260
261 private:
262 operator_type operation_;
263};
264
265template <class Tensor, class Operator>
267
268} // namespace uni20::krylov
Defines structure-preserving linear operations on BlockTensor values.
Defines zero-copy bosonic BlockTensor factor permutations.
Fixed-order tensor whose blocks obey a bosonic abelian selection rule.
Definition block_tensor.hpp:161
General-purpose owning tensor with immediate or deferred mdspan metadata.
Definition basic_tensor.hpp:109
std::remove_cv_t< element_type > value_type
Definition basic_tensor.hpp:114
StoragePolicy storage_policy
Definition basic_tensor.hpp:115
Combine fixed BlockTensor vector algebra with an owned matrix-free apply operation.
Definition block_tensor_vector.hpp:237
BlockTensorMatrixFreeOps(tensor_type const &prototype, operator_type operation)
Freeze a vector structure and take ownership of its apply operation.
Definition block_tensor_vector.hpp:248
std::remove_cvref_t< Operator > operator_type
Definition block_tensor_vector.hpp:241
typename base_type::tensor_type tensor_type
Definition block_tensor_vector.hpp:240
void matvec(tensor_type &output, tensor_type const &input)
Apply the stored matrix-free operation as output <- OP*input.
Definition block_tensor_vector.hpp:254
Krylov vector algebra for one exact owning BlockTensor structure.
Definition block_tensor_vector.hpp:51
typename tensor_type::value_type scalar_type
Definition block_tensor_vector.hpp:54
typename tensor_type::codomain_type codomain_type
Definition block_tensor_vector.hpp:57
void copy(tensor_type &output, tensor_type const &input) const
Copy one vector into another without changing either structure.
Definition block_tensor_vector.hpp:141
auto norm(tensor_type const &vector) const -> real_type
Return the Euclidean norm as a host scalar.
Definition block_tensor_vector.hpp:179
typename tensor_type::domain_type domain_type
Definition block_tensor_vector.hpp:56
void set_zero(tensor_type &vector) const
Set every stored numerical block to zero.
Definition block_tensor_vector.hpp:164
auto prototype_view(Vector &&vector) const
Own prototype metadata while borrowing its numerical payload and allocation context.
Definition block_tensor_vector.hpp:91
auto problem_dimension() const noexcept -> std::size_t
Return the number of stored numerical degrees of freedom.
Definition block_tensor_vector.hpp:73
auto vector_dimension(Vector const &vector) const -> std::size_t
Validate a vector and return the frozen problem dimension.
Definition block_tensor_vector.hpp:80
auto allocate_like(View const &view) const -> tensor_type
Allocate owning workspace from retained view metadata and its leaf context.
Definition block_tensor_vector.hpp:121
void axpy(tensor_type &output, scalar_type factor, tensor_type const &input) const
Add a scalar multiple of one input to an output.
Definition block_tensor_vector.hpp:149
auto allocate_like(tensor_type const &vector) const -> tensor_type
Allocate a vector with the frozen structure and unspecified values.
Definition block_tensor_vector.hpp:101
make_real_t< scalar_type > real_type
Definition block_tensor_vector.hpp:55
auto inner_product(tensor_type const &lhs, tensor_type const &rhs) const -> scalar_type
Return the conjugate-linear inner product as a host scalar.
Definition block_tensor_vector.hpp:171
BlockTensorVectorOps(tensor_type const &prototype)
Freeze the Krylov vector space represented by a prototype tensor.
Definition block_tensor_vector.hpp:64
std::remove_cvref_t< Tensor > tensor_type
Definition block_tensor_vector.hpp:53
typename tensor_type::key_type key_type
Definition block_tensor_vector.hpp:58
void scal(tensor_type &vector, scalar_type factor) const
Scale one vector in place.
Definition block_tensor_vector.hpp:157
Tensor-level view of a symmetry-preserving collection of dense blocks.
Definition block_tensor_concepts.hpp:52
BlockTensorView whose destruction does not destroy its referenced numerical payload.
Definition block_tensor_concepts.hpp:101
BlockTensor storage which contains every symmetry-legal block.
Definition block_tensor_storage.hpp:63
BlockTensorView whose stored numerical blocks are generalized diagonals.
Definition block_tensor_concepts.hpp:91
Concept for types that are either real or complex.
Definition scalar_concepts.hpp:87
Concept for numeric scalar types (integer, real, or complex).
Definition scalar_concepts.hpp:81
typename make_real< T >::type make_real_t
Alias for the underlying real-valued type of T.
Definition scalar_traits.hpp:168
Definition qnum.hpp:403
Definition block_tensor_vector.hpp:23
constexpr uninitialized_t uninitialized
Explicit allocation tag for overwrite outputs and scratch space.
Definition common/initialization.hpp:22
auto inner_product_host(BackendSelector selector, async::Async< LhsTensor > const &lhs, async::Async< RhsTensor > const &rhs)
Return a nonblocking async host C++ scalar inner product through an explicit selector.
Definition linalg/async/reductions.hpp:496
void axpy(Output &output, Scalar factor, Input const &input)
Compute output += factor * input without changing either key pattern.
Definition block_tensor_linear.hpp:692
constexpr decltype(auto) mdspec_of(Tensor &tensor) noexcept(noexcept(tensor.mdspec()))
Return a tensor's immediate or descriptor-backed multidimensional metadata.
Definition tensor/concepts.hpp:50
auto norm_host(BackendSelector selector, async::Async< InputTensor > const &input)
Return a nonblocking async host C++ scalar norm through an explicit selector.
Definition linalg/async/reductions.hpp:554
void scale(Tensor &tensor, Scalar factor)
Multiply every stored numerical block by a scalar in place.
Definition block_tensor_linear.hpp:400
void copy(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< InputTensor > const &input)
Schedule a Tensor copy through an explicit backend selector.
Definition linalg/async/copy.hpp:174
auto as_block_tensor_view(Tensor &tensor)
Materialize a borrowed identity view over an existing BlockTensor view.
Definition block_tensor_permute.hpp:186
constexpr auto diagonal_components(stdex::mdspan< ElementType, Extents, LayoutPolicy, diagonal_accessor< ElementType, AccessorExtents > > const &span)
Expose the physically stored values of a generalized-diagonal mdspan.
Definition diagonal_accessor.hpp:252
void set_zero(Tensor &tensor)
Set every stored numerical block to zero without changing structure.
Definition block_tensor_linear.hpp:369