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
21namespace Dune::Experimental {
80template<class B, class I = uint_least32_t, class A = std::allocator<B>>
81class BCRSMatrix : public Matrix<B, SparseIndexRanges<I, typename std::allocator_traits<A>::template rebind_alloc<I>>, A>
82{
85
87 using block_alloc_type = typename std::allocator_traits<A>::template rebind_alloc<B>;
91 using void_alloc_type = typename std::allocator_traits<A>::template rebind_alloc<void>;
92
97
99 struct AllocDeleter
100 {
101 template<class T>
102 void operator()(T* builder)
103 {
104 using rebound_alloc_type = typename std::allocator_traits<A>::template rebind_alloc<T>;
105 rebound_alloc_type rebound_alloc(alloc_);
106 using rebound_alloc_traits = typename std::allocator_traits<rebound_alloc_type>;
107 rebound_alloc_traits::destroy(rebound_alloc, builder);
108 rebound_alloc_traits::deallocate(rebound_alloc, builder, 1);
109 }
110 DUNE_NO_UNIQUE_ADDRESS A alloc_;
111 };
112
118
126 class DefaultBlockAssgnment
127 {
128 DefaultBlockAssgnment() = default;
129 friend class BCRSMatrix;
130 public:
132 DefaultBlockAssgnment& operator=(const B& e);
134 DefaultBlockAssgnment& operator=(const typename FieldTraits<B>::field_type& f)
135 requires (!std::same_as<B, typename FieldTraits<B>::field_type>);
136 };
137
138public:
140 using typename BaseMatrix::block_type;
142 using typename BaseMatrix::size_type;
144 using typename BaseMatrix::pattern_type;
146 using allocator_type = A;
147
154 enum BuildMode : uint_least8_t
155 {
189 unknown
190 };
191
203
204 // inherit constructors
205 using BaseMatrix::BaseMatrix;
206
207 // inherit assignment operators
208 using BaseMatrix::operator=;
209
210 // inherit allocator getter
212
214 BCRSMatrix(const BaseMatrix& other,
215 const allocator_type& allocator = allocator_type())
216 : BaseMatrix(other, allocator)
217 {
218 }
219
222 const allocator_type& allocator = allocator_type())
223 : BaseMatrix(std::move(other), allocator)
224 {
225 }
226
236 BCRSMatrix(const BCRSMatrix& other,
237 const allocator_type& allocator = allocator_type());
240 BCRSMatrix(BCRSMatrix&& other,
241 const allocator_type& allocator = allocator_type());
242
253
256
266 size_type cols,
267 BuildMode bm,
268 const allocator_type& allocator = allocator_type());
269
279 size_type cols,
280 size_type nnz,
281 BuildMode bm,
282 const allocator_type& allocator = allocator_type());
283
295 size_type cols,
296 size_type avg,
297 double overflowRatio,
298 BuildMode bm,
299 const allocator_type& allocator = allocator_type());
300
302 void swap(BCRSMatrix& other)
303 {
304 using std::swap;
305 swap(static_cast<BaseMatrix&>(*this),
306 static_cast<BaseMatrix&>(other));
307 swap(builder_, other.builder_);
308 }
309
311 friend void swap(BCRSMatrix& lhs, BCRSMatrix& rhs)
312 {
313 lhs.swap(rhs);
314 }
315
321 void setBuildMode(BuildMode bm);
322
324 BuildMode buildMode() const;
325
327 void setSize(size_type rows, size_type cols, size_type nnz = 0);
328
330
340
350
352 void endrowsizes() {}
353
355 void addindex(size_type row, size_type col);
357 void endindices();
358
368 template<typename It>
370 DUNE_THROW(NotImplemented, "setIndicesNoSort is not implemented yet for BCRSMatrix row-wise build mode");
371 }
372
383 template<typename It>
384 void setIndices(size_type row, It begin, It end) {
385 DUNE_THROW(NotImplemented, "setIndices is not implemented yet for BCRSMatrix row-wise build mode");
386 }
387
389
393 {
394 using Base = typename SequencedPatternBuilder::IndexRangeBuilder;
395 using EndSentinel = typename SequencedPatternBuilder::EndSentinel;
396
398 CreateIterator(Base&& pattern_builder, BCRSMatrix* sm);
399
400 CreateIterator(const CreateIterator&) = delete;
401 CreateIterator& operator=(const CreateIterator&) = delete;
402 public:
404 CreateIterator(CreateIterator&& other) noexcept;
406 CreateIterator& operator=(CreateIterator&& other) noexcept;
409
410 private:
411 friend class BCRSMatrix;
412 BCRSMatrix* matrix_;
413 };
414
417
420
433 DefaultBlockAssgnment entry(size_type row, size_type col);
434
437
438private:
439 template<class Builder>
440 static Builder& getBuilder(BuilderVariant& builder,
441 std::string_view build_mode_name)
442 {
443 using BuilderPtrType = std::unique_ptr<Builder, AllocDeleter>;
444 if (!std::holds_alternative<BuilderPtrType>(builder))
447 "Builder "
448 << className<Builder>()
449 << " can only be used when building a BCRSMatrix with BuildMode::"
450 << build_mode_name);
451
452 const auto& ptr = std::get<BuilderPtrType>(builder);
453 if (!ptr)
456 "Builder "
457 << className<Builder>()
458 << " can only be called once the builder has been initialized");
459 return *ptr;
460 }
461
462 SequencedPatternBuilder& getSequencedPatternBuilder()
463 {
464 return getBuilder<SequencedPatternBuilder>(builder_, "row_wise");
465 }
466
467 UnsequencedPatternBuilder& getUnsequencedPatternBuilder()
468 {
469 return getBuilder<UnsequencedPatternBuilder>(builder_, "implicit");
470 }
471
472 BuilderVariant builder_;
473};
474
475// Matrix implementation
476
477template<class B, class I, class A>
479 size_type m,
480 size_type nnz,
481 BuildMode bm,
482 const allocator_type& allocator)
483 : BaseMatrix(nullptr, allocator)
484{
485 setBuildMode(bm);
486 setSize(n, m, nnz);
487}
488
489template<class B, class I, class A>
491 size_type m,
492 BuildMode bm,
493 const allocator_type& allocator)
494 : BCRSMatrix(n, m, 0, bm, allocator)
495{
496}
497
498template<class B, class I, class A>
500 size_type m,
501 size_type avg,
502 double overflowRatio,
503 BuildMode bm,
504 const allocator_type& allocator)
505 : BCRSMatrix(n,
506 m,
507 static_cast<size_type>((avg * n) * overflowRatio),
508 bm,
509 allocator)
510{
511}
512
513template<class B, class I, class A>
515 const allocator_type& allocator)
516 : BaseMatrix(other, allocator)
517{
518 builder_ = std::monostate{};
519}
520
521template<class B, class I, class A>
523 const allocator_type& allocator)
524 : BaseMatrix(std::move(other), allocator)
525{
526 builder_ = std::move(other.builder_);
527}
528
529template<class B, class I, class A>
530void
532{
533 *this = BCRSMatrix(get_allocator());
534 switch (bm) {
535 case BuildMode::row_wise:
536 builder_ =
538 nullptr, AllocDeleter{ get_allocator() });
539 break;
540 case BuildMode::implicit: // same as BuildMode::random
541 builder_ =
543 nullptr, AllocDeleter{ get_allocator() });
544 break;
545 case BuildMode::unknown:
546 builder_ = std::monostate{};
547 break;
548 }
549}
550
551template<class B, class I, class A>
552auto
554{
555 return std::visit(
556 overload(
557 [](std::monostate) { return BuildMode::unknown; },
559 AllocDeleter>&) { return BuildMode::row_wise; },
561 AllocDeleter>&) { return BuildMode::implicit; }),
562 builder_);
563}
564
565template<class B, class I, class A>
566void
567BCRSMatrix<B, I, A>::setSize(size_type rows, size_type cols, size_type nnz)
568{
569 using seq_builder_alloc_type = typename std::allocator_traits<
570 allocator_type>::template rebind_alloc<SequencedPatternBuilder>;
571 using unseq_builder_alloc_type = typename std::allocator_traits<
572 allocator_type>::template rebind_alloc<UnsequencedPatternBuilder>;
573 const auto void_alloc = void_alloc_type(get_allocator());
574 size_type avg = (rows > 0) ? (nnz / rows) : 0;
576 overload(
577 [](std::monostate) {
579 "Cannot set size of BCRSMatrix with unknown build mode");
580 },
581 [balloc = seq_builder_alloc_type(get_allocator()),
582 void_alloc,
583 rows,
584 cols,
586 builder) mutable {
587 builder.reset(
590 balloc, builder.get(), rows, cols, avg, void_alloc);
591 },
592 [balloc = unseq_builder_alloc_type(get_allocator()),
593 void_alloc,
594 rows,
595 cols,
597 builder) mutable {
598 builder.reset(
601 balloc, builder.get(), rows, cols, avg, void_alloc);
602 }),
603 builder_);
604}
605
606template<class B, class I, class A>
607void
608BCRSMatrix<B, I, A>::setrowsize(size_type row, size_type size)
609{
610 getUnsequencedPatternBuilder().setSize(row, size);
611}
612
613template<class B, class I, class A>
614void
616{
617 getUnsequencedPatternBuilder().incrementSize(row, increment);
618}
619
620template<class B, class I, class A>
621void
622BCRSMatrix<B, I, A>::addindex(size_type row, size_type col)
623{
624 getUnsequencedPatternBuilder().addIndex(row, col);
625}
626
627template<class B, class I, class A>
628void
630{
631 using pattern_alloc_type = typename std::allocator_traits<
632 allocator_type>::template rebind_alloc<SparseIndexRanges<I>>;
633 pattern_alloc_type pattern_alloc(get_allocator());
634 std::shared_ptr<pattern_type> pt = std::allocate_shared<pattern_type>(
635 pattern_alloc, std::move(getUnsequencedPatternBuilder()));
636 *this = BaseMatrix(std::move(pt), get_allocator());
637 builder_ = std::monostate{};
638}
639
640template<class B, class I, class A>
642 BCRSMatrix* sm)
643 : Base(std::move(pattern_builder))
644 , matrix_(sm)
645{
646}
647
648template<class B, class I, class A>
650 CreateIterator&& other) noexcept
651 : Base(std::move(other))
652 , matrix_(std::exchange(other.matrix_, nullptr))
653{
654}
655
656template<class B, class I, class A>
657auto
660{
661 if (this != &other) {
662 Base::operator=(std::move(other));
663 matrix_ = std::exchange(other.matrix_, nullptr);
664 }
665 return *this;
666}
667
668template<class B, class I, class A>
669auto
671{
672 Base::operator++();
673 assert(matrix_);
674 if (*this == EndSentinel()) {
675 // build pattern and allocate data when we have reached the end of the index
676 // sets
677 using pattern_alloc_type =
678 typename block_alloc_traits::template rebind_alloc<pattern_type>;
679 pattern_alloc_type pattern_alloc(matrix_->get_allocator());
680 std::shared_ptr<pattern_type> pt = std::allocate_shared<pattern_type>(
681 pattern_alloc, std::move(matrix_->getSequencedPatternBuilder()));
682 *matrix_ = BaseMatrix(std::move(pt), matrix_->get_allocator());
683 matrix_->builder_ = std::monostate{};
684 }
685 return *this;
686}
687
688template<class B, class I, class A>
689auto
691{
692 return { getSequencedPatternBuilder().begin(), this };
693}
694
695template<class B, class I, class A>
696auto
702
703template<class B, class I, class A>
704auto
705BCRSMatrix<B, I, A>::entry(size_type row, size_type col)
706 -> DefaultBlockAssgnment
707{
708 getUnsequencedPatternBuilder().addIndex(row, col);
709 return {};
710}
711
712template<class B, class I, class A>
713auto
715{
716 endindices();
717
718 size_type max_pattern_size = 0;
719 for (const auto& index_range : this->pattern())
720 max_pattern_size =
721 std::max<size_type>(max_pattern_size, index_range.size());
722 return CompressionStatistics{ /*avg = */ this->pattern().count() /
723 static_cast<double>(this->pattern().size()),
724 /* maximum = */ max_pattern_size,
725 /* overflow_total = */ 0,
726 /* mem_ratio = */ 1.0 };
727}
728
729template<class B, class I, class A>
730auto
732 -> DefaultBlockAssgnment&
733{
734 if (e != B{})
736 "BCRSMatrix with BuildMode::row_wise only supports default "
737 "constructed entries, but got "
738 << e);
739 return *this;
740}
741
742template<class B, class I, class A>
743auto
744BCRSMatrix<B, I, A>::DefaultBlockAssgnment::operator=(const typename FieldTraits<B>::field_type& e)
745-> DefaultBlockAssgnment&
746requires (!std::same_as<B, typename FieldTraits<B>::field_type>)
747{
748 if (e != typename FieldTraits<B>::field_type{})
749 DUNE_THROW(RangeError,
750 "BCRSMatrix with BuildMode::row_wise only supports default "
751 "constructed entries, but got "
752 << e);
753 return *this;
754}
755
756template<class B, class I, class A>
757BCRSMatrix<B, I, A>&
759{
760 if (this != &other) {
761 static_cast<BaseMatrix&>(*this) =
762 static_cast<const BaseMatrix&>(other);
763 builder_ = std::monostate{};
764 }
765 return *this;
766}
767
768template<class B, class I, class A>
771{
772 if (this != &other) {
773 static_cast<BaseMatrix&>(*this) = std::move(other);
774 builder_ = std::move(other.builder_);
775 }
776 return *this;
777}
778
779} //namespace Dune::Experimental
780
781namespace Dune {
782template<class B, class I, class A>
783struct FieldTraits<Experimental::BCRSMatrix<B, I, A>>
784 : public FieldTraits<typename Experimental::BCRSMatrix<B, I, A>::field_type>
785{};
786
787} // namespace Dune
788
789#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 defaultmatrixvectortraits.hh:14
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:567
BCRSMatrix(const BaseMatrix &other, const allocator_type &allocator=allocator_type())
Construct an BCRSMatrix from another Matrix.
Definition experimental/bcrsmatrix.hh:214
BuildMode
Available matrix construction modes.
Definition experimental/bcrsmatrix.hh:155
@ row_wise
Fill index sets sequentially, one row after another.
Definition experimental/bcrsmatrix.hh:169
@ unknown
No build mode selected, or matrix construction has finished.
Definition experimental/bcrsmatrix.hh:189
@ implicit
Build entries in arbitrary order.
Definition experimental/bcrsmatrix.hh:185
@ random
Build entries in arbitrary order.
Definition experimental/bcrsmatrix.hh:179
void setrowsize(size_type row, size_type size)
Random/implicit build API, mirroring the historic BCRSMatrix interface.
Definition experimental/bcrsmatrix.hh:608
void endindices()
Finalize the sparsity pattern and make the matrix ready for value access.
Definition experimental/bcrsmatrix.hh:629
BuildMode buildMode() const
Return the currently active build mode.
Definition experimental/bcrsmatrix.hh:553
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:369
void swap(BCRSMatrix &other)
Swap the contents of two matrices, respecting allocator propagation rules.
Definition experimental/bcrsmatrix.hh:302
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:384
void setBuildMode(BuildMode bm)
Reset the matrix and select a new build mode.
Definition experimental/bcrsmatrix.hh:531
A allocator_type
Type of the allocator used for memory management.
Definition experimental/bcrsmatrix.hh:146
DefaultBlockAssgnment entry(size_type row, size_type col)
Insert an index in implicit/random build mode.
Definition experimental/bcrsmatrix.hh:705
SequencedPatternBuilder::EndSentinel createend()
End sentinel for row-wise construction.
Definition experimental/bcrsmatrix.hh:697
void endrowsizes()
Finalize the row-size declaration phase.
Definition experimental/bcrsmatrix.hh:352
CreateIterator createbegin()
Begin row-wise construction.
Definition experimental/bcrsmatrix.hh:690
CompressionStatistics compress()
Finalize implicit/random build and return compression statistics.
Definition experimental/bcrsmatrix.hh:714
friend void swap(BCRSMatrix &lhs, BCRSMatrix &rhs)
Swap the contents of two matrices, respecting allocator propagation rules.
Definition experimental/bcrsmatrix.hh:311
BCRSMatrix< B, I, A > & operator=(const BCRSMatrix &other)
Copy-assign an BCRSMatrix from another matrix.
Definition experimental/bcrsmatrix.hh:758
void addindex(size_type row, size_type col)
Insert the col index into a sparse row during implicit/random build.
Definition experimental/bcrsmatrix.hh:622
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:615
BCRSMatrix(BaseMatrix &&other, const allocator_type &allocator=allocator_type())
Move-construct an BCRSMatrix from another Matrix.
Definition experimental/bcrsmatrix.hh:221
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
Definition experimental/bcrsmatrix.hh:193
size_type overflow_total
total number of elements written to the overflow area during construction.
Definition experimental/bcrsmatrix.hh:199
double avg
average number of non-zeroes per row.
Definition experimental/bcrsmatrix.hh:195
double mem_ratio
fraction of wasted memory resulting from non-used overflow area.
Definition experimental/bcrsmatrix.hh:201
size_type maximum
maximum number of non-zeroes per row.
Definition experimental/bcrsmatrix.hh:197
Row-wise build API.
Definition experimental/bcrsmatrix.hh:393
CreateIterator & operator++()
Advance to the next row; when the last row is completed, finalize the matrix.
Definition experimental/bcrsmatrix.hh:670
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
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)