dune-istl 2.12-git
Loading...
Searching...
No Matches
experimental/bcrsmatrix.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4// vi: set et ts=4 sw=2 sts=2:
5
6#ifndef DUNE_ISTL_EXPERIMENTAL_BCRSMATRIX_HH
7#define DUNE_ISTL_EXPERIMENTAL_BCRSMATRIX_HH
8
9#include "matrix.hh"
10#include "sparseindexranges.hh"
11
17
18#include <memory>
19#include <ranges>
20
80template<class B, class I = uint_least32_t, class A = std::allocator<B>>
81class BCRSMatrix : public Matrix<B, SparseIndexRanges<I>, A>
82{
84 using block_alloc_type = typename std::allocator_traits<A>::template rebind_alloc<B>;
88 using void_alloc_type = typename std::allocator_traits<A>::template rebind_alloc<void>;
89
94
96 struct AllocDeleter
97 {
98 template<class T>
99 void operator()(T* builder)
100 {
101 using rebound_alloc_type = typename std::allocator_traits<A>::template rebind_alloc<T>;
102 rebound_alloc_type rebound_alloc(alloc_);
103 using rebound_alloc_traits = typename std::allocator_traits<rebound_alloc_type>;
104 rebound_alloc_traits::destroy(rebound_alloc, builder);
105 rebound_alloc_traits::deallocate(rebound_alloc, builder, 1);
106 }
107 DUNE_NO_UNIQUE_ADDRESS A alloc_;
108 };
109
115
123 class DefaultBlockAssgnment
124 {
125 DefaultBlockAssgnment() = default;
126 friend class BCRSMatrix;
127 public:
129 DefaultBlockAssgnment& operator=(const B& e);
131 DefaultBlockAssgnment& operator=(const typename FieldTraits<B>::field_type& f)
132 requires (!std::same_as<B, typename FieldTraits<B>::field_type>);
133 };
134
135public:
143 using allocator_type = A;
144
151 enum BuildMode : uint_least8_t
152 {
186 unknown
187 };
188
200
201 // inherit constructors TODO check that this works
202 using Matrix<B, SparseIndexRanges<I>, A>::Matrix;
203
204 using Matrix<B, SparseIndexRanges<I>, A>::operator=;
205
207
210 const allocator_type& allocator = allocator_type())
211 : Matrix<B, SparseIndexRanges<I>, A>(other, allocator)
212 {
213 }
214
217 const allocator_type& allocator = allocator_type())
218 : Matrix<B, SparseIndexRanges<I>, A>(std::move(other), allocator)
219 {
220 }
221
231 BCRSMatrix(const BCRSMatrix& other,
232 const allocator_type& allocator = allocator_type());
235 BCRSMatrix(BCRSMatrix&& other,
236 const allocator_type& allocator = allocator_type());
237
248
251
261 size_type cols,
262 BuildMode bm,
263 const allocator_type& allocator = allocator_type());
264
274 size_type cols,
275 size_type nnz,
276 BuildMode bm,
277 const allocator_type& allocator = allocator_type());
278
290 size_type cols,
291 size_type avg,
292 double overflowRatio,
293 BuildMode bm,
294 const allocator_type& allocator = allocator_type());
295
297 void swap(BCRSMatrix& other)
298 {
299 using std::swap;
300 swap(static_cast<Matrix<B, SparseIndexRanges<I>, A>&>(*this),
301 static_cast<Matrix<B, SparseIndexRanges<I>, A>&>(other));
302 swap(builder_, other.builder_);
303 }
304
306 friend void swap(BCRSMatrix& lhs, BCRSMatrix& rhs)
307 {
308 lhs.swap(rhs);
309 }
310
316 void setBuildMode(BuildMode bm);
317
319 BuildMode buildMode() const;
320
322 void setSize(size_type rows, size_type cols, size_type nnz = 0);
323
325
335
345
347 void endrowsizes() {}
348
350 void addindex(size_type row, size_type col);
352 void endindices();
353
363 template<typename It>
365 DUNE_THROW(NotImplemented, "setIndicesNoSort is not implemented yet for BCRSMatrix row-wise build mode");
366 }
367
378 template<typename It>
379 void setIndices(size_type row, It begin, It end) {
380 DUNE_THROW(NotImplemented, "setIndices is not implemented yet for BCRSMatrix row-wise build mode");
381 }
382
384
388 {
389 using Base = typename SequencedPatternBuilder::IndexRangeBuilder;
390 using EndSentinel = typename SequencedPatternBuilder::EndSentinel;
391
393 CreateIterator(Base&& pattern_builder, BCRSMatrix* sm);
394
395 CreateIterator(const CreateIterator&) = delete;
396 CreateIterator& operator=(const CreateIterator&) = delete;
397 public:
399 CreateIterator(CreateIterator&& other) noexcept;
401 CreateIterator& operator=(CreateIterator&& other) noexcept;
404
405 private:
406 friend class BCRSMatrix;
407 BCRSMatrix* matrix_;
408 };
409
412
415
428 DefaultBlockAssgnment entry(size_type row, size_type col);
429
432
433private:
434 template<class Builder>
435 static Builder& getBuilder(BuilderVariant& builder,
436 std::string_view build_mode_name)
437 {
438 using BuilderPtrType = std::unique_ptr<Builder, AllocDeleter>;
439 if (!std::holds_alternative<BuilderPtrType>(builder))
442 "Builder "
443 << className<Builder>()
444 << " can only be used when building a BCRSMatrix with BuildMode::"
445 << build_mode_name);
446
447 const auto& ptr = std::get<BuilderPtrType>(builder);
448 if (!ptr)
451 "Builder "
452 << className<Builder>()
453 << " can only be called once the builder has been initialized");
454 return *ptr;
455 }
456
457 SequencedPatternBuilder& getSequencedPatternBuilder()
458 {
459 return getBuilder<SequencedPatternBuilder>(builder_, "row_wise");
460 }
461
462 UnsequencedPatternBuilder& getUnsequencedPatternBuilder()
463 {
464 return getBuilder<UnsequencedPatternBuilder>(builder_, "implicit");
465 }
466
467 BuilderVariant builder_;
468};
469
470// Matrix implementation
471
472template<class B, class I, class A>
474 size_type m,
475 size_type nnz,
476 BuildMode bm,
477 const allocator_type& allocator)
478 : Matrix<B, SparseIndexRanges<I>, A>(nullptr, allocator)
479{
480 setBuildMode(bm);
481 setSize(n, m, nnz);
482}
483
484template<class B, class I, class A>
486 size_type m,
487 BuildMode bm,
488 const allocator_type& allocator)
489 : BCRSMatrix(n, m, 0, bm, allocator)
490{
491}
492
493template<class B, class I, class A>
495 size_type m,
496 size_type avg,
497 double overflowRatio,
498 BuildMode bm,
499 const allocator_type& allocator)
500 : BCRSMatrix(n,
501 m,
502 static_cast<size_type>((avg * n) * overflowRatio),
503 bm,
504 allocator)
505{
506}
507
508template<class B, class I, class A>
510 const allocator_type& allocator)
511 : Matrix<B, SparseIndexRanges<I>, A>(other, allocator)
512{
513 builder_ = std::monostate{};
514}
515
516template<class B, class I, class A>
518 const allocator_type& allocator)
519 : Matrix<B, SparseIndexRanges<I>, A>(std::move(other), allocator)
520{
521 builder_ = std::move(other.builder_);
522}
523
524template<class B, class I, class A>
525void
527{
528 *this = BCRSMatrix(get_allocator());
529 switch (bm) {
530 case BuildMode::row_wise:
531 builder_ =
533 nullptr, AllocDeleter{ get_allocator() });
534 break;
535 case BuildMode::implicit: // same as BuildMode::random
536 builder_ =
538 nullptr, AllocDeleter{ get_allocator() });
539 break;
540 case BuildMode::unknown:
541 builder_ = std::monostate{};
542 break;
543 }
544}
545
546template<class B, class I, class A>
547auto
549{
550 return std::visit(
551 overload(
552 [](std::monostate) { return BuildMode::unknown; },
554 AllocDeleter>&) { return BuildMode::row_wise; },
556 AllocDeleter>&) { return BuildMode::implicit; }),
557 builder_);
558}
559
560template<class B, class I, class A>
561void
562BCRSMatrix<B, I, A>::setSize(size_type rows, size_type cols, size_type nnz)
563{
564 using seq_builder_alloc_type = typename std::allocator_traits<
565 allocator_type>::template rebind_alloc<SequencedPatternBuilder>;
566 using unseq_builder_alloc_type = typename std::allocator_traits<
567 allocator_type>::template rebind_alloc<UnsequencedPatternBuilder>;
568 const auto void_alloc = void_alloc_type(get_allocator());
569 size_type avg = (rows > 0) ? (nnz / rows) : 0;
571 overload(
572 [](std::monostate) {
574 "Cannot set size of BCRSMatrix with unknown build mode");
575 },
576 [balloc = seq_builder_alloc_type(get_allocator()),
577 void_alloc,
578 rows,
579 cols,
581 builder) mutable {
582 builder.reset(
585 balloc, builder.get(), rows, cols, avg, void_alloc);
586 },
587 [balloc = unseq_builder_alloc_type(get_allocator()),
588 void_alloc,
589 rows,
590 cols,
592 builder) mutable {
593 builder.reset(
596 balloc, builder.get(), rows, cols, avg, void_alloc);
597 }),
598 builder_);
599}
600
601template<class B, class I, class A>
602void
603BCRSMatrix<B, I, A>::setrowsize(size_type row, size_type size)
604{
605 getUnsequencedPatternBuilder().setSize(row, size);
606}
607
608template<class B, class I, class A>
609void
611{
612 getUnsequencedPatternBuilder().incrementSize(row, increment);
613}
614
615template<class B, class I, class A>
616void
617BCRSMatrix<B, I, A>::addindex(size_type row, size_type col)
618{
619 getUnsequencedPatternBuilder().addIndex(row, col);
620}
621
622template<class B, class I, class A>
623void
625{
626 using pattern_alloc_type = typename std::allocator_traits<
627 allocator_type>::template rebind_alloc<SparseIndexRanges<I>>;
628 pattern_alloc_type pattern_alloc(get_allocator());
629 std::shared_ptr<pattern_type> pt = std::allocate_shared<pattern_type>(
630 pattern_alloc, std::move(getUnsequencedPatternBuilder()));
631 *this = Matrix<B, SparseIndexRanges<I>, A>(std::move(pt), get_allocator());
632 builder_ = std::monostate{};
633}
634
635template<class B, class I, class A>
637 BCRSMatrix* sm)
638 : Base(std::move(pattern_builder))
639 , matrix_(sm)
640{
641}
642
643template<class B, class I, class A>
645 CreateIterator&& other) noexcept
646 : Base(std::move(other))
647 , matrix_(std::exchange(other.matrix_, nullptr))
648{
649}
650
651template<class B, class I, class A>
652auto
655{
656 if (this != &other) {
657 Base::operator=(std::move(other));
658 matrix_ = std::exchange(other.matrix_, nullptr);
659 }
660 return *this;
661}
662
663template<class B, class I, class A>
664auto
666{
667 Base::operator++();
668 assert(matrix_);
669 if (*this == EndSentinel()) {
670 // build pattern and allocate data when we have reached the end of the index
671 // sets
672 using pattern_alloc_type =
673 typename block_alloc_traits::template rebind_alloc<pattern_type>;
674 pattern_alloc_type pattern_alloc(matrix_->get_allocator());
675 std::shared_ptr<pattern_type> pt = std::allocate_shared<pattern_type>(
676 pattern_alloc, std::move(matrix_->getSequencedPatternBuilder()));
677 *matrix_ =
678 Matrix<B, SparseIndexRanges<I>, A>(std::move(pt), matrix_->get_allocator());
679 matrix_->builder_ = std::monostate{};
680 }
681 return *this;
682}
683
684template<class B, class I, class A>
685auto
687{
688 return { getSequencedPatternBuilder().begin(), this };
689}
690
691template<class B, class I, class A>
692auto
698
699template<class B, class I, class A>
700auto
701BCRSMatrix<B, I, A>::entry(size_type row, size_type col)
702 -> DefaultBlockAssgnment
703{
704 getUnsequencedPatternBuilder().addIndex(row, col);
705 return {};
706}
707
708template<class B, class I, class A>
709auto
711{
712 endindices();
713
714 size_type max_pattern_size = 0;
715 for (const auto& index_range : this->pattern())
716 max_pattern_size =
717 std::max<size_type>(max_pattern_size, index_range.size());
718 return CompressionStatistics{ /*avg = */ this->pattern().count() /
719 static_cast<double>(this->pattern().size()),
720 /* maximum = */ max_pattern_size,
721 /* overflow_total = */ 0,
722 /* mem_ratio = */ 1.0 };
723}
724
725template<class B, class I, class A>
726auto
728 -> DefaultBlockAssgnment&
729{
730 if (e != B{})
732 "BCRSMatrix with BuildMode::row_wise only supports default "
733 "constructed entries, but got "
734 << e);
735 return *this;
736}
737
738template<class B, class I, class A>
739auto
740BCRSMatrix<B, I, A>::DefaultBlockAssgnment::operator=(const typename FieldTraits<B>::field_type& e)
741-> DefaultBlockAssgnment&
742requires (!std::same_as<B, typename FieldTraits<B>::field_type>)
743{
744 if (e != typename FieldTraits<B>::field_type{})
745 DUNE_THROW(RangeError,
746 "BCRSMatrix with BuildMode::row_wise only supports default "
747 "constructed entries, but got "
748 << e);
749 return *this;
750}
751
752template<class B, class I, class A>
753BCRSMatrix<B, I, A>&
755{
756 if (this != &other) {
757 static_cast<Matrix<B, SparseIndexRanges<I>, A>&>(*this) =
758 static_cast<const Matrix<B, SparseIndexRanges<I>, A>&>(other);
759 builder_ = std::monostate{};
760 }
761 return *this;
762}
763
764template<class B, class I, class A>
767{
768 if (this != &other) {
769 static_cast<Matrix<B, SparseIndexRanges<I>, A>&>(*this) = std::move(other);
770 builder_ = std::move(other.builder_);
771 }
772 return *this;
773}
774
775} //namespace Dune::Experimental
776
777namespace Dune {
778template<class B, class I, class A>
779struct FieldTraits<Experimental::BCRSMatrix<B, I, A>>
780 : public FieldTraits<typename Experimental::BCRSMatrix<B, I, A>::field_type>
781{};
782
783} // namespace Dune
784
785#endif // DUNE_ISTL_EXPERIMENTAL_BCRSMATRIX_HH
A dynamic dense block matrix class.
#define DUNE_NO_UNIQUE_ADDRESS
Col col
Definition matrixmatrix.hh:351
STL namespace.
Definition experimental/bcrsmatrix.hh:21
int size() const
SLList< T, A > & operator=(const SLList< T, A > &other)
void increment()
auto overload(F &&... f)
virtual void operator()()=0
#define DUNE_THROW(E,...)
A sparse block matrix with compressed row storage.
Definition bcrsmatrix.hh:468
BCRSMatrix()
an empty matrix
Definition bcrsmatrix.hh:747
Block compressed row storage matrix.
Definition experimental/bcrsmatrix.hh:82
void setSize(size_type rows, size_type cols, size_type nnz=0)
Set the expected matrix dimensions for the currently selected build mode.
Definition experimental/bcrsmatrix.hh:562
BuildMode
Available matrix construction modes.
Definition experimental/bcrsmatrix.hh:152
@ row_wise
Fill index sets sequentially, one row after another.
Definition experimental/bcrsmatrix.hh:166
@ unknown
No build mode selected, or matrix construction has finished.
Definition experimental/bcrsmatrix.hh:186
@ implicit
Build entries in arbitrary order.
Definition experimental/bcrsmatrix.hh:182
@ random
Build entries in arbitrary order.
Definition experimental/bcrsmatrix.hh:176
void setrowsize(size_type row, size_type size)
Random/implicit build API, mirroring the historic BCRSMatrix interface.
Definition experimental/bcrsmatrix.hh:603
void endindices()
Finalize the sparsity pattern and make the matrix ready for value access.
Definition experimental/bcrsmatrix.hh:624
BuildMode buildMode() const
Return the currently active build mode.
Definition experimental/bcrsmatrix.hh:548
void setIndicesNoSort(size_type row, It begin, It end)
Set all column indices for row from the given iterator range on row-wise build mode.
Definition experimental/bcrsmatrix.hh:364
void swap(BCRSMatrix &other)
Swap the contents of two matrices, respecting allocator propagation rules.
Definition experimental/bcrsmatrix.hh:297
void setIndices(size_type row, It begin, It end)
Set all column indices for row from the given iterator range row-wise build mode.
Definition experimental/bcrsmatrix.hh:379
void setBuildMode(BuildMode bm)
Reset the matrix and select a new build mode.
Definition experimental/bcrsmatrix.hh:526
BCRSMatrix(const Matrix< B, SparseIndexRanges< I >, A > &other, const allocator_type &allocator=allocator_type())
Construct an BCRSMatrix from another Matrix.
Definition experimental/bcrsmatrix.hh:209
A allocator_type
Type of the allocator used for memory management.
Definition experimental/bcrsmatrix.hh:143
BCRSMatrix(Matrix< B, SparseIndexRanges< I >, A > &&other, const allocator_type &allocator=allocator_type())
Move-construct an BCRSMatrix from another Matrix.
Definition experimental/bcrsmatrix.hh:216
DefaultBlockAssgnment entry(size_type row, size_type col)
Insert an index in implicit/random build mode.
Definition experimental/bcrsmatrix.hh:701
SequencedPatternBuilder::EndSentinel createend()
End sentinel for row-wise construction.
Definition experimental/bcrsmatrix.hh:693
void endrowsizes()
Finalize the row-size declaration phase.
Definition experimental/bcrsmatrix.hh:347
CreateIterator createbegin()
Begin row-wise construction.
Definition experimental/bcrsmatrix.hh:686
CompressionStatistics compress()
Finalize implicit/random build and return compression statistics.
Definition experimental/bcrsmatrix.hh:710
friend void swap(BCRSMatrix &lhs, BCRSMatrix &rhs)
Swap the contents of two matrices, respecting allocator propagation rules.
Definition experimental/bcrsmatrix.hh:306
BCRSMatrix< B, I, A > & operator=(const BCRSMatrix &other)
Copy-assign an BCRSMatrix from another matrix.
Definition experimental/bcrsmatrix.hh:754
void addindex(size_type row, size_type col)
Insert the col index into a sparse row during implicit/random build.
Definition experimental/bcrsmatrix.hh:617
void incrementrowsize(size_type row, size_type increment=1)
Increment the expected number of non-zero entries in a row for random/implicit build.
Definition experimental/bcrsmatrix.hh:610
Definition experimental/bcrsmatrix.hh:190
size_type overflow_total
total number of elements written to the overflow area during construction.
Definition experimental/bcrsmatrix.hh:196
double avg
average number of non-zeroes per row.
Definition experimental/bcrsmatrix.hh:192
double mem_ratio
fraction of wasted memory resulting from non-used overflow area.
Definition experimental/bcrsmatrix.hh:198
size_type maximum
maximum number of non-zeroes per row.
Definition experimental/bcrsmatrix.hh:194
Row-wise build API.
Definition experimental/bcrsmatrix.hh:388
CreateIterator & operator++()
Advance to the next row; when the last row is completed, finalize the matrix.
Definition experimental/bcrsmatrix.hh:665
Owning matrix container built on top of MatrixView.
Definition experimental/matrix.hh:44
allocator_type get_allocator() const
Return the allocator currently associated with this matrix.
Definition experimental/matrix.hh:367
Iterator begin()
Return iterator to the first row.
Definition matrixview.hh:115
std::iter_value_t< block_iter_type > block_type
The type of blocks in the matrix.
Definition matrixview.hh:70
P pattern_type
The type used for the sparsity pattern.
Definition matrixview.hh:66
std::ranges::range_size_t< pattern_type > size_type
The type used to count elements in the row and column index sets.
Definition matrixview.hh:74
Iterator end()
Return iterator one past the last row.
Definition matrixview.hh:118
Compact storage of multiple sorted sparse index sets sharing a single allocation.
Definition sparseindexranges.hh:489
Builder that allows inserting indices into any index set in any order.
Definition sparseindexranges.hh:244
Builder that fills index sets one at a time, in sequential order.
Definition sparseindexranges.hh:329
Handle for inserting indices into the current index set of a SequencedSparseIndexRangeBuilder.
Definition sparseindexranges.hh:375
T construct(T... args)
T exchange(T... args)
T swap(T... args)
T visit(T... args)