Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
block_tensor.hpp
Go to the documentation of this file.
1
7#pragma once
8
16
17#include <algorithm>
18#include <array>
19#include <concepts>
20#include <cstddef>
21#include <initializer_list>
22#include <optional>
23#include <ranges>
24#include <stdexcept>
25#include <tuple>
26#include <type_traits>
27#include <utility>
28#include <vector>
29
30namespace uni20
31{
32namespace detail
33{
34
35template <class T> struct IsDomain : std::false_type
36{};
37
38template <class... Spaces> struct IsDomain<Domain<Spaces...>> : std::true_type
39{};
40
41template <class T> struct IsCodomain : std::false_type
42{};
43
44template <class... Spaces> struct IsCodomain<Codomain<Spaces...>> : std::true_type
45{};
46
47template <class T>
48concept PrototypeBlockFactor =
49 std::same_as<primal_space_t<T>, BlockSpace> || std::same_as<primal_space_t<T>, LocalSpace> ||
50 std::same_as<primal_space_t<T>, QNumSpace>;
51
52template <class Boundary> struct PrototypeBoundary;
53
54template <template <class...> class Boundary, class... Spaces>
55struct PrototypeBoundary<Boundary<Spaces...>> : std::bool_constant<(PrototypeBlockFactor<Spaces> && ...)>
56{};
57
58template <class Boundary> struct BoundaryBlockShape;
59
60template <template <class...> class Boundary, class... Spaces> struct BoundaryBlockShape<Boundary<Spaces...>>
61{
62 static constexpr std::size_t key_coordinate_count =
63 (std::size_t{0} + ... + (BlockTensorSpaceTraits<std::remove_cvref_t<Spaces>>::has_block_coordinate ? 1U : 0U));
64 static constexpr std::size_t dense_block_order =
65 (std::size_t{0} + ... + (BlockTensorSpaceTraits<std::remove_cvref_t<Spaces>>::has_dense_axis ? 1U : 0U));
66};
67
68inline auto factor_size(BlockSpace const& space) -> std::size_t { return space.size(); }
69inline auto factor_size(LocalSpace const& space) -> std::size_t { return space.size(); }
70
71template <Space SpaceType> auto factor_size(Dual<SpaceType> const& space) -> std::size_t
72{
73 return factor_size(space.base());
74}
75
76inline auto factor_qnum(BlockSpace const& space, std::size_t coordinate) -> QNum const& { return space[coordinate].q; }
77
78inline auto factor_qnum(LocalSpace const& space, std::size_t coordinate) -> QNum const& { return space[coordinate]; }
79
80inline auto factor_qnum(QNumSpace const& space, std::size_t) -> QNum const& { return space.qnum(); }
81
82template <Space SpaceType> auto factor_qnum(Dual<SpaceType> const& space, std::size_t coordinate) -> QNum
83{
84 return dual(factor_qnum(space.base(), coordinate));
85}
86
87inline auto factor_extent(BlockSpace const& space, std::size_t coordinate) -> std::size_t
88{
89 return space[coordinate].dim;
90}
91
92template <Space SpaceType> auto factor_extent(Dual<SpaceType> const& space, std::size_t coordinate) -> std::size_t
93{
94 return factor_extent(space.base(), coordinate);
95}
96
97template <class Boundary, class Function> void for_each_boundary_space(Boundary const& boundary, Function&& function)
98{
99 std::apply([&](auto const&... spaces) { (function(spaces), ...); }, boundary.spaces());
100}
101
102template <std::size_t KeyCoordinateCount, class DomainType, class CodomainType>
103auto boundary_factor_sizes(DomainType const& domain, CodomainType const& codomain)
104 -> std::array<std::size_t, KeyCoordinateCount>
105{
106 std::array<std::size_t, KeyCoordinateCount> sizes{};
107 std::size_t key_axis = 0;
108 auto append_size = [&](auto const& space) {
109 using space_type = std::remove_cvref_t<decltype(space)>;
110 if constexpr (BlockTensorSpaceTraits<space_type>::has_block_coordinate)
111 {
112 sizes[key_axis++] = factor_size(space);
113 }
114 };
115 for_each_boundary_space(domain, append_size);
116 for_each_boundary_space(codomain, append_size);
117 return sizes;
118}
119
120template <std::size_t KeyCoordinateCount, class DomainType, class CodomainType>
121auto is_legal_block_key(Symmetry const& symmetry, DomainType const& domain, CodomainType const& codomain,
122 BlockKey<KeyCoordinateCount> const& key) -> bool
123{
124 auto const sizes = boundary_factor_sizes<KeyCoordinateCount>(domain, codomain);
125 for (std::size_t axis = 0; axis < KeyCoordinateCount; ++axis)
126 {
127 if (key.coordinate(axis) >= sizes[axis]) return false;
128 }
129
130 QNum domain_charge = QNum::identity(symmetry);
131 QNum codomain_charge = QNum::identity(symmetry);
132 std::size_t key_axis = 0;
133 auto add_charge = [&](auto const& space, QNum& charge) {
134 using space_type = std::remove_cvref_t<decltype(space)>;
135 std::size_t coordinate = 0;
136 if constexpr (BlockTensorSpaceTraits<space_type>::has_block_coordinate)
137 {
138 coordinate = key.coordinate(key_axis++);
139 }
140 charge = charge + factor_qnum(space, coordinate);
141 };
142 for_each_boundary_space(domain, [&](auto const& space) { add_charge(space, domain_charge); });
143 for_each_boundary_space(codomain, [&](auto const& space) { add_charge(space, codomain_charge); });
144 return domain_charge == codomain_charge;
145}
146
147} // namespace detail
148
158template <typename T, class DomainType, class CodomainType, BlockTensorStorage Storage>
159 requires(detail::IsDomain<DomainType>::value && detail::IsCodomain<CodomainType>::value &&
160 detail::PrototypeBoundary<DomainType>::value && detail::PrototypeBoundary<CodomainType>::value)
162 public:
163 using element_type = T;
164 using value_type = std::remove_cv_t<T>;
165 using domain_type = DomainType;
166 using codomain_type = CodomainType;
167 using storage_policy = Storage;
168 static constexpr std::size_t static_order = domain_type::size() + codomain_type::size();
169 static constexpr std::size_t static_key_coordinate_count =
170 detail::BoundaryBlockShape<domain_type>::key_coordinate_count +
171 detail::BoundaryBlockShape<codomain_type>::key_coordinate_count;
172 static constexpr std::size_t static_dense_block_order =
173 detail::BoundaryBlockShape<domain_type>::dense_block_order +
174 detail::BoundaryBlockShape<codomain_type>::dense_block_order;
175 static_assert(static_order <= 4, "the first BlockTensor slice supports orders 0 through 4");
176 static_assert(
178 "BlockTensor storage does not provide the required block bindings");
179
181 using storage_type = typename storage_policy::template storage_t<element_type, static_key_coordinate_count,
182 static_dense_block_order>;
183 using mutable_block_type = typename storage_type::mutable_block_type;
184 using const_block_type = typename storage_type::const_block_type;
185 using backend_selector_type = typename storage_policy::backend_selector_type;
186
192 BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, std::vector<key_type> stored_keys)
194 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
195 storage_(this->make_storage(std::move(stored_keys)))
196 {}
197
199 template <class Context>
200 BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, std::vector<key_type> stored_keys,
201 Context& context)
203 std::constructible_from<
205 std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>> const&,
206 Context&, StorageInitialization>
207 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
208 storage_(this->make_storage(std::move(stored_keys), context))
209 {}
210
216 BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain,
217 std::initializer_list<key_type> stored_keys)
219 : BlockTensor(symmetry, std::move(domain), std::move(codomain), std::vector<key_type>(stored_keys))
220 {}
221
226 BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain)
228 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
229 storage_(this->make_complete_storage())
230 {}
231
233 template <class Context>
234 BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, Context& context)
236 std::constructible_from<
238 std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>> const&,
239 Context&, StorageInitialization>
240 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
241 storage_(this->make_complete_storage(context))
242 {}
243
250 std::vector<key_type> stored_keys)
252 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
253 storage_(this->make_storage(std::move(stored_keys), StorageInitialization::Uninitialized))
254 {}
255
257 template <class Context>
259 std::vector<key_type> stored_keys, Context& context)
261 std::constructible_from<
263 std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>> const&,
264 Context&, StorageInitialization>
265 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
266 storage_(this->make_storage(std::move(stored_keys), context, StorageInitialization::Uninitialized))
267 {}
268
275 std::initializer_list<key_type> stored_keys)
277 : BlockTensor(uninitialized, symmetry, std::move(domain), std::move(codomain),
278 std::vector<key_type>(stored_keys))
279 {}
280
287 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
288 storage_(this->make_complete_storage(StorageInitialization::Uninitialized))
289 {}
290
292 template <class Context>
293 BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain, Context& context)
295 std::constructible_from<
297 std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>> const&,
298 Context&, StorageInitialization>
299 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)),
300 storage_(this->make_complete_storage(context, StorageInitialization::Uninitialized))
301 {}
302
304 auto symmetry() const -> Symmetry { return symmetry_; }
305
307 auto domain() const -> domain_type const& { return domain_; }
308
310 auto codomain() const -> codomain_type const& { return codomain_; }
311
313 static constexpr auto order() noexcept -> std::size_t { return static_order; }
314
316 static constexpr auto key_coordinate_count() noexcept -> std::size_t { return static_key_coordinate_count; }
317
319 static constexpr auto dense_block_order() noexcept -> std::size_t { return static_dense_block_order; }
320
322 auto stored_block_count() const noexcept -> std::size_t { return storage_.size(); }
323
325 auto legal_block_count() const -> std::size_t
326 {
327 std::size_t count = 0;
328 this->for_each_possible_key([&](key_type const& key) {
329 if (this->is_legal(key)) ++count;
330 });
331 return count;
332 }
333
339 auto legal_block_keys() const -> std::vector<key_type>
340 {
341 std::vector<key_type> result;
342 this->for_each_possible_key([&](key_type const& key) {
343 if (this->is_legal(key)) result.push_back(key);
344 });
345 return result;
346 }
347
351 auto has_all_legal_blocks() const -> bool { return this->stored_block_count() == this->legal_block_count(); }
352
354 auto is_legal(key_type const& key) const -> bool
355 {
356 return detail::is_legal_block_key(symmetry_, domain_, codomain_, key);
357 }
358
360 auto contains(key_type const& key) const -> bool { return this->ordinal(key).has_value(); }
361
363 auto find_block(key_type const& key) -> std::optional<mutable_block_type>
364 {
365 auto const found = this->ordinal(key);
366 if (!found) return std::nullopt;
367 return this->block_by_ordinal(*found);
368 }
369
371 auto find_block(key_type const& key) const -> std::optional<const_block_type>
372 {
373 auto const found = this->ordinal(key);
374 if (!found) return std::nullopt;
375 return this->block_by_ordinal(*found);
376 }
377
381 {
382 auto const found = this->find_block(key);
383 if (!found) throw std::out_of_range("BlockTensor block key is not stored");
384 return *found;
385 }
386
389 auto block(key_type const& key) const -> const_block_type
390 {
391 auto const found = this->find_block(key);
392 if (!found) throw std::out_of_range("BlockTensor block key is not stored");
393 return *found;
394 }
395
400 auto block_by_ordinal(std::size_t ordinal) -> mutable_block_type
401 {
402 if (ordinal >= storage_.size()) throw std::out_of_range("BlockTensor block ordinal is out of range");
403 auto const& key = storage_.keys()[ordinal];
404 return storage_.block(ordinal, this->block_extents(key));
405 }
406
411 auto block_by_ordinal(std::size_t ordinal) const -> const_block_type
412 {
413 if (ordinal >= storage_.size()) throw std::out_of_range("BlockTensor block ordinal is out of range");
414 auto const& key = storage_.keys()[ordinal];
415 return storage_.block(ordinal, this->block_extents(key));
416 }
417
422 decltype(auto) diagonal_values(key_type const& key)
423 requires requires(storage_type& storage) { storage.diagonal_values(std::size_t{}); }
424 {
425 auto const found = this->ordinal(key);
426 if (!found) throw std::out_of_range("BlockTensor block key is not stored");
427 return storage_.diagonal_values(*found);
428 }
429
434 decltype(auto) diagonal_values(key_type const& key) const
435 requires requires(storage_type const& storage) { storage.diagonal_values(std::size_t{}); }
436 {
437 auto const found = this->ordinal(key);
438 if (!found) throw std::out_of_range("BlockTensor block key is not stored");
439 return storage_.diagonal_values(*found);
440 }
441
444 decltype(auto) diagonal_values_by_ordinal(std::size_t ordinal)
445 requires requires(storage_type& storage) { storage.diagonal_values(std::size_t{}); }
446 {
447 if (ordinal >= storage_.size()) throw std::out_of_range("BlockTensor block ordinal is out of range");
448 return storage_.diagonal_values(ordinal);
449 }
450
453 decltype(auto) diagonal_values_by_ordinal(std::size_t ordinal) const
454 requires requires(storage_type const& storage) { storage.diagonal_values(std::size_t{}); }
455 {
456 if (ordinal >= storage_.size()) throw std::out_of_range("BlockTensor block ordinal is out of range");
457 return storage_.diagonal_values(ordinal);
458 }
459
466 decltype(auto) async_block(key_type const& key)
467 requires AsyncLocalBlockStorageFor<storage_policy, element_type, static_key_coordinate_count,
468 static_dense_block_order>
469 {
470 auto const found = this->ordinal(key);
471 if (!found) throw std::out_of_range("BlockTensor block key is not stored");
472 return storage_.async_block(*found);
473 }
474
479 decltype(auto) async_block(key_type const& key) const
480 requires AsyncLocalBlockStorageFor<storage_policy, element_type, static_key_coordinate_count,
481 static_dense_block_order>
482 {
483 auto const found = this->ordinal(key);
484 if (!found) throw std::out_of_range("BlockTensor block key is not stored");
485 return storage_.async_block(*found);
486 }
487
492 decltype(auto) async_block_by_ordinal(std::size_t ordinal)
493 requires AsyncLocalBlockStorageFor<storage_policy, element_type, static_key_coordinate_count,
494 static_dense_block_order>
495 {
496 if (ordinal >= storage_.size()) throw std::out_of_range("BlockTensor block ordinal is out of range");
497 return storage_.async_block(ordinal);
498 }
499
504 decltype(auto) async_block_by_ordinal(std::size_t ordinal) const
505 requires AsyncLocalBlockStorageFor<storage_policy, element_type, static_key_coordinate_count,
506 static_dense_block_order>
507 {
508 if (ordinal >= storage_.size()) throw std::out_of_range("BlockTensor block ordinal is out of range");
509 return storage_.async_block(ordinal);
510 }
511
513 auto stored_keys() const noexcept -> std::span<key_type const> { return storage_.keys(); }
514
516 static constexpr auto backend_selector() noexcept -> backend_selector_type
517 {
518 return storage_policy::backend_selector();
519 }
520
522 auto storage() noexcept -> storage_type& { return storage_; }
523
525 auto storage() const noexcept -> storage_type const& { return storage_; }
526
528 decltype(auto) allocation_context() const noexcept
529 requires requires(storage_type const& storage) { storage.allocation_context(); }
530 {
531 return storage_.allocation_context();
532 }
533
539 [[nodiscard]] auto allocate_like() const -> BlockTensor
540 requires requires(storage_type const& storage) {
541 { storage.allocate_like(StorageInitialization::Zero) } -> std::same_as<storage_type>;
542 }
543 {
544 return BlockTensor(symmetry_, domain_, codomain_, storage_.allocate_like(StorageInitialization::Zero),
545 ValidatedStorageTag{});
546 }
547
551 [[nodiscard]] auto allocate_like(uninitialized_t) const -> BlockTensor
552 requires requires(storage_type const& storage) {
553 { storage.allocate_like(StorageInitialization::Uninitialized) } -> std::same_as<storage_type>;
554 }
555 {
556 return BlockTensor(symmetry_, domain_, codomain_, storage_.allocate_like(StorageInitialization::Uninitialized),
557 ValidatedStorageTag{});
558 }
559
560 private:
561 struct ValidatedStorageTag
562 {};
563
564 BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, storage_type storage,
565 ValidatedStorageTag)
566 : symmetry_(symmetry), domain_(std::move(domain)), codomain_(std::move(codomain)), storage_(std::move(storage))
567 {}
568
569 auto make_storage(std::vector<key_type> stored_keys,
570 StorageInitialization initialization = StorageInitialization::Zero) -> storage_type
571 {
572 this->validate_boundaries();
573 return this->make_storage_from_validated_keys(std::move(stored_keys), initialization);
574 }
575
576 template <class Context>
577 auto make_storage(std::vector<key_type> stored_keys, Context& context,
578 StorageInitialization initialization = StorageInitialization::Zero) -> storage_type
579 {
580 this->validate_boundaries();
581 return this->make_storage_from_validated_keys(std::move(stored_keys), context, initialization);
582 }
583
584 auto make_storage_from_validated_keys(std::vector<key_type> stored_keys,
585 StorageInitialization initialization) -> storage_type
586 {
587 return storage_type(this->make_block_specs(std::move(stored_keys)), initialization);
588 }
589
590 template <class Context>
591 auto make_storage_from_validated_keys(std::vector<key_type> stored_keys, Context& context,
592 StorageInitialization initialization) -> storage_type
593 {
594 return storage_type(this->make_block_specs(std::move(stored_keys)), context, initialization);
595 }
596
597 auto make_block_specs(std::vector<key_type> stored_keys)
598 -> std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>>
599 {
600 std::sort(stored_keys.begin(), stored_keys.end());
601 if (std::adjacent_find(stored_keys.begin(), stored_keys.end()) != stored_keys.end())
602 {
603 throw std::invalid_argument("BlockTensor stored keys must be unique");
604 }
605
606 std::vector<detail::BlockSpec<static_key_coordinate_count, static_dense_block_order>> specs;
607 specs.reserve(stored_keys.size());
608 for (key_type const& key : stored_keys)
609 {
610 if (!this->is_legal(key)) throw std::invalid_argument("BlockTensor stored key is not symmetry-legal");
611 auto const extents = this->block_extents(key);
612 static_cast<void>(detail::checked_block_size(extents));
613 specs.push_back({key, extents});
614 }
615 return specs;
616 }
617
618 auto make_complete_storage(StorageInitialization initialization = StorageInitialization::Zero) -> storage_type
619 {
620 this->validate_boundaries();
621 std::vector<key_type> stored_keys;
622 this->for_each_possible_key([&](key_type const& key) {
623 if (this->is_legal(key)) stored_keys.push_back(key);
624 });
625 return this->make_storage_from_validated_keys(std::move(stored_keys), initialization);
626 }
627
628 template <class Context>
629 auto make_complete_storage(Context& context,
630 StorageInitialization initialization = StorageInitialization::Zero) -> storage_type
631 {
632 this->validate_boundaries();
633 std::vector<key_type> stored_keys;
634 this->for_each_possible_key([&](key_type const& key) {
635 if (this->is_legal(key)) stored_keys.push_back(key);
636 });
637 return this->make_storage_from_validated_keys(std::move(stored_keys), context, initialization);
638 }
639
640 void validate_boundaries() const
641 {
642 if (!symmetry_.valid()) throw std::invalid_argument("BlockTensor requires a valid symmetry");
643 auto validate = [&](auto const& space) {
644 if (space.symmetry() != symmetry_)
645 {
646 throw std::invalid_argument("BlockTensor boundary space has the wrong symmetry");
647 }
648 };
649 detail::for_each_boundary_space(domain_, validate);
650 detail::for_each_boundary_space(codomain_, validate);
651 }
652
653 auto factor_sizes() const -> std::array<std::size_t, static_key_coordinate_count>
654 {
655 return detail::boundary_factor_sizes<static_key_coordinate_count>(domain_, codomain_);
656 }
657
658 auto block_extents(key_type const& key) const -> std::array<std::size_t, static_dense_block_order>
659 {
660 std::array<std::size_t, static_dense_block_order> extents{};
661 std::size_t key_axis = 0;
662 std::size_t dense_axis = 0;
663 auto append_extent = [&](auto const& space) {
664 using space_type = std::remove_cvref_t<decltype(space)>;
665 std::size_t coordinate = 0;
666 if constexpr (BlockTensorSpaceTraits<space_type>::has_block_coordinate)
667 {
668 coordinate = key.coordinate(key_axis++);
669 }
670 if constexpr (BlockTensorSpaceTraits<space_type>::has_dense_axis)
671 {
672 std::size_t const extent = detail::factor_extent(space, coordinate);
673 if (!std::in_range<index_type>(extent))
674 {
675 throw std::length_error("BlockTensor block extent does not fit index_type");
676 }
677 extents[dense_axis++] = extent;
678 }
679 };
680 detail::for_each_boundary_space(domain_, append_extent);
681 detail::for_each_boundary_space(codomain_, append_extent);
682 return extents;
683 }
684
685 template <class Function> void for_each_possible_key(Function&& function) const
686 {
687 auto const sizes = this->factor_sizes();
688 if (std::ranges::find(sizes, std::size_t{0}) != sizes.end()) return;
689
690 if constexpr (static_key_coordinate_count == 0)
691 {
692 function(key_type{});
693 }
694 else
695 {
696 std::array<std::size_t, static_key_coordinate_count> coordinates{};
697 while (true)
698 {
699 function(key_type{coordinates});
700 std::size_t axis = static_key_coordinate_count;
701 while (axis > 0)
702 {
703 --axis;
704 if (++coordinates[axis] < sizes[axis]) break;
705 coordinates[axis] = 0;
706 }
707 if (axis == 0 && coordinates[0] == 0) return;
708 }
709 }
710 }
711
712 auto ordinal(key_type const& key) const -> std::optional<std::size_t>
713 {
714 auto const keys = storage_.keys();
715 auto const found = std::ranges::lower_bound(keys, key);
716 if (found == keys.end() || *found != key) return std::nullopt;
717 return static_cast<std::size_t>(found - keys.begin());
718 }
719
720 Symmetry symmetry_;
721 domain_type domain_;
722 codomain_type codomain_;
723 storage_type storage_;
724};
725
726} // namespace uni20
Defines immutable block-structured tensor spaces and regularization helpers.
Classifies tensor spaces for block-key and dense-block storage.
Defines local sparse and packed-complete BlockTensor storage policies.
Opaque logical block-selection coordinates in boundary order.
Definition block_key.hpp:20
Fixed-order tensor whose blocks obey a bosonic abelian selection rule.
Definition block_tensor.hpp:161
auto is_legal(key_type const &key) const -> bool
Return whether a key is in range and satisfies charge conservation.
Definition block_tensor.hpp:354
static constexpr auto key_coordinate_count() noexcept -> std::size_t
Return the number of coordinates stored in each block key.
Definition block_tensor.hpp:316
typename storage_policy::backend_selector_type backend_selector_type
Definition block_tensor.hpp:185
auto block_by_ordinal(std::size_t ordinal) const -> const_block_type
Return a read-only block TensorView by stable canonical ordinal.
Definition block_tensor.hpp:411
auto allocate_like() const -> BlockTensor
Allocate a tensor with identical validated structure.
Definition block_tensor.hpp:539
auto symmetry() const -> Symmetry
Return the explicit symmetry context.
Definition block_tensor.hpp:304
auto stored_keys() const noexcept -> std::span< key_type const >
Return stored keys in canonical lexicographic order.
Definition block_tensor.hpp:513
auto find_block(key_type const &key) -> std::optional< mutable_block_type >
Find a writable block without changing tensor structure.
Definition block_tensor.hpp:363
auto find_block(key_type const &key) const -> std::optional< const_block_type >
Find a read-only block without changing tensor structure.
Definition block_tensor.hpp:371
typename storage_type::const_block_type const_block_type
Definition block_tensor.hpp:184
BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain)
Construct zero-initialized blocks for every symmetry-legal key.
Definition block_tensor.hpp:226
BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain, std::initializer_list< key_type > stored_keys)
Allocate uninitialized sparse blocks from an initializer list of stored keys.
Definition block_tensor.hpp:274
auto codomain() const -> codomain_type const &
Return the ordered codomain value.
Definition block_tensor.hpp:310
decltype(auto) diagonal_values_by_ordinal(std::size_t ordinal)
Return compressed writable diagonal values by stable block ordinal.
Definition block_tensor.hpp:444
typename storage_type::mutable_block_type mutable_block_type
Definition block_tensor.hpp:183
decltype(auto) diagonal_values(key_type const &key)
Return the compressed writable diagonal values for one stored key.
Definition block_tensor.hpp:422
auto domain() const -> domain_type const &
Return the ordered domain value.
Definition block_tensor.hpp:307
std::remove_cv_t< T > value_type
Definition block_tensor.hpp:164
static constexpr auto dense_block_order() noexcept -> std::size_t
Return the dense mdspan order of each numerical block.
Definition block_tensor.hpp:319
BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain)
Allocate every symmetry-legal block without numerical initialization.
Definition block_tensor.hpp:285
decltype(auto) async_block_by_ordinal(std::size_t ordinal) const
Return one independently scheduled value by stable canonical ordinal.
Definition block_tensor.hpp:504
static constexpr auto order() noexcept -> std::size_t
Return the compile-time tensor order.
Definition block_tensor.hpp:313
BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, std::initializer_list< key_type > stored_keys)
Construct a sparse tensor from an initializer list of stored keys.
Definition block_tensor.hpp:216
typename storage_policy::template storage_t< element_type, static_key_coordinate_count, static_dense_block_order > storage_type
Definition block_tensor.hpp:182
decltype(auto) async_block(key_type const &key)
Return the independently scheduled value for one stored key.
Definition block_tensor.hpp:466
BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain, std::vector< key_type > stored_keys, Context &context)
Allocate uninitialized sparse blocks in an explicit leaf allocation context.
Definition block_tensor.hpp:258
auto stored_block_count() const noexcept -> std::size_t
Return the number of stored blocks.
Definition block_tensor.hpp:322
BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain, std::vector< key_type > stored_keys)
Allocate uninitialized sparse blocks from an explicit stored-key list.
Definition block_tensor.hpp:249
decltype(auto) async_block_by_ordinal(std::size_t ordinal)
Return one independently scheduled value by stable canonical ordinal.
Definition block_tensor.hpp:492
T element_type
Definition block_tensor.hpp:163
auto has_all_legal_blocks() const -> bool
Return whether this value currently stores every legal block.
Definition block_tensor.hpp:351
auto legal_block_count() const -> std::size_t
Return the number of symmetry-legal blocks.
Definition block_tensor.hpp:325
decltype(auto) diagonal_values(key_type const &key) const
Return the compressed read-only diagonal values for one stored key.
Definition block_tensor.hpp:434
auto contains(key_type const &key) const -> bool
Return whether a key has an allocated numerical block.
Definition block_tensor.hpp:360
auto block(key_type const &key) const -> const_block_type
Return a read-only stored block.
Definition block_tensor.hpp:389
BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, std::vector< key_type > stored_keys, Context &context)
Construct a sparse tensor in an explicit leaf allocation context.
Definition block_tensor.hpp:200
auto block_by_ordinal(std::size_t ordinal) -> mutable_block_type
Return a writable block TensorView by stable canonical ordinal.
Definition block_tensor.hpp:400
decltype(auto) diagonal_values_by_ordinal(std::size_t ordinal) const
Return compressed read-only diagonal values by stable block ordinal.
Definition block_tensor.hpp:453
Storage storage_policy
Definition block_tensor.hpp:167
BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, std::vector< key_type > stored_keys)
Construct zero-initialized sparse blocks from an explicit stored-key list.
Definition block_tensor.hpp:192
BlockTensor(uninitialized_t, Symmetry symmetry, domain_type domain, codomain_type codomain, Context &context)
Allocate uninitialized complete blocks in an explicit leaf allocation context.
Definition block_tensor.hpp:293
auto storage() noexcept -> storage_type &
Return the concrete storage value.
Definition block_tensor.hpp:522
auto storage() const noexcept -> storage_type const &
Return the concrete storage value.
Definition block_tensor.hpp:525
static constexpr auto backend_selector() noexcept -> backend_selector_type
Return the default dense-leaf backend selector for this storage.
Definition block_tensor.hpp:516
DomainType domain_type
Definition block_tensor.hpp:165
BlockTensor(Symmetry symmetry, domain_type domain, codomain_type codomain, Context &context)
Construct a complete tensor in an explicit leaf allocation context.
Definition block_tensor.hpp:234
auto block(key_type const &key) -> mutable_block_type
Return a writable stored block.
Definition block_tensor.hpp:380
auto legal_block_keys() const -> std::vector< key_type >
Enumerate every symmetry-legal block key in canonical order.
Definition block_tensor.hpp:339
CodomainType codomain_type
Definition block_tensor.hpp:166
auto allocate_like(uninitialized_t) const -> BlockTensor
Allocate uninitialized blocks with identical validated structure.
Definition block_tensor.hpp:551
decltype(auto) allocation_context() const noexcept
Return the leaf context used for compatible result allocations.
Definition block_tensor.hpp:528
decltype(auto) async_block(key_type const &key) const
Return the independently scheduled value for one stored key.
Definition block_tensor.hpp:479
static auto identity(Symmetry sym) -> QNum
Return the identity irrep of a given symmetry.
Definition qnum.hpp:73
Public handle to a canonicalized direct-product symmetry specification.
Definition symmetry.hpp:24
Local BlockTensor storage with one independently scheduled async value per block.
Definition block_tensor_storage.hpp:142
Storage policy instantiated for one block scalar and tensor order.
Definition block_tensor_storage.hpp:81
BlockTensor storage which contains every symmetry-legal block.
Definition block_tensor_storage.hpp:63
BlockTensor storage whose stored key set may omit legal blocks.
Definition block_tensor_storage.hpp:58
Defines the generic categorical dual-space adaptor.
Domain
MKL computation domains accepted by domain-specific thread controls.
Definition backend_mkl.hpp:35
Defines immutable ordered local-state spaces.
Defines ordered domain and codomain space values for tensor morphisms.
Definition qnum.hpp:403
auto validate(LuRefinementPrecision< F, W, R > p, RefinementOptions< make_real_t< R > > const &options)
Definition lu_refine.hpp:28
Definition async/async.hpp:26
constexpr uninitialized_t uninitialized
Explicit allocation tag for overwrite outputs and scratch space.
Definition common/initialization.hpp:22
Codomain(Spaces &&...) -> Codomain< std::remove_cvref_t< Spaces >... >
Deduce a codomain's concrete value types.
auto dual(SpaceType const &space) -> Dual< std::remove_cvref_t< SpaceType > >
Construct an explicitly dual basis without changing occurrence order.
Definition dual_space.hpp:244
StorageInitialization
Numerical initialization requested from a storage implementation.
Definition common/initialization.hpp:26
std::size_t span
Definition presentation.cpp:2017
Defines single-irrep tensor spaces.
Request storage whose numerical values must be written before being read.
Definition common/initialization.hpp:17