deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
chunk_sparsity_pattern.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2008 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_chunk_sparsity_pattern_h
14#define dealii_chunk_sparsity_pattern_h
15
16
17#include <deal.II/base/config.h>
18
21
23
24#include <iostream>
25#include <vector>
26
28
29
30// Forward declaration
31#ifndef DOXYGEN
32template <typename>
34#endif
35
47{
48 // forward declaration
49 class Iterator;
50
61 {
62 public:
67
72
77
83 row() const;
84
88 std::size_t
90
96 column() const;
97
107 bool
109
110
114 bool
115 operator==(const Accessor &) const;
116
117
125 bool
126 operator<(const Accessor &) const;
127
128 protected:
133
138
143
148
152 void
154
155 // Grant access to iterator class.
156 friend class Iterator;
157 };
158
159
160
165 {
166 public:
171
177
181 Iterator &
183
189
193 const Accessor &
194 operator*() const;
195
199 const Accessor *
200 operator->() const;
201
205 bool
206 operator==(const Iterator &) const;
207
211 bool
212 operator!=(const Iterator &) const;
213
221 bool
222 operator<(const Iterator &) const;
223
224 private:
229 };
230} // namespace ChunkSparsityPatternIterators
231
232
233
243{
244public:
254
263
279
286
303
315 const size_type n,
316 const size_type max_chunks_per_row,
317 const size_type chunk_size);
318
330 const size_type n,
331 const std::vector<size_type> &row_lengths,
332 const size_type chunk_size);
333
343 const size_type max_per_row,
344 const size_type chunk_size);
345
356 const std::vector<size_type> &row_lengths,
357 const size_type chunk_size);
358
362 ~ChunkSparsityPattern() override = default;
363
371
380 void
381 reinit(const size_type m,
382 const size_type n,
383 const size_type max_per_row,
384 const size_type chunk_size);
385
400 void
401 reinit(const size_type m,
402 const size_type n,
403 const std::vector<size_type> &row_lengths,
404 const size_type chunk_size);
405
409 void
410 reinit(const size_type m,
411 const size_type n,
412 const ArrayView<const size_type> &row_lengths,
413 const size_type chunk_size);
414
427 void
428 compress();
429
505 template <typename ForwardIterator>
506 void
508 const size_type n_cols,
509 const ForwardIterator begin,
510 const ForwardIterator end,
511 const size_type chunk_size);
512
518 template <typename SparsityPatternType>
519 void
520 copy_from(const SparsityPatternType &dsp, const size_type chunk_size);
521
529 template <typename number>
530 void
531 copy_from(const FullMatrix<number> &matrix, const size_type chunk_size);
532
550 template <typename Sparsity>
551 void
552 create_from(const size_type m,
553 const size_type n,
554 const Sparsity &sparsity_pattern_for_chunks,
555 const size_type chunk_size,
556 const bool optimize_diagonal = true);
557
562 bool
563 empty() const;
564
570
577 max_entries_per_row() const;
578
585 void
586 add(const size_type i, const size_type j);
587
595 void
596 symmetrize();
597
602 inline size_type
603 n_rows() const;
604
609 inline size_type
610 n_cols() const;
611
615 bool
616 exists(const size_type i, const size_type j) const;
617
622 row_length(const size_type row) const;
623
631 bandwidth() const;
632
642 n_nonzero_elements() const;
643
647 bool
649
662 bool
664
671 begin() const;
672
677 end() const;
678
688 begin(const size_type r) const;
689
699 end(const size_type r) const;
700
711 void
712 block_write(std::ostream &out) const;
713
727 void
728 block_read(std::istream &in);
729
735 void
736 print(std::ostream &out) const;
737
751 void
752 print_gnuplot(std::ostream &out) const;
753
758 std::size_t
759 memory_consumption() const;
760
769 size_type,
770 << "The provided number is invalid here: " << arg1);
775 size_type,
776 size_type,
777 << "The given index " << arg1 << " should be less than "
778 << arg2 << '.');
783 size_type,
784 size_type,
785 << "Upon entering a new entry to row " << arg1
786 << ": there was no free entry any more. " << std::endl
787 << "(Maximum number of entries for this row: " << arg2
788 << "; maybe the matrix is already compressed?)");
795 "The operation you attempted is only allowed after the SparsityPattern "
796 "has been set up and compress() was called.");
803 "The operation you attempted changes the structure of the SparsityPattern "
804 "and is not possible after compress() has been called.");
813 size_type,
814 size_type,
815 << "The iterators denote a range of " << arg1
816 << " elements, but the given number of rows was " << arg2);
825 size_type,
826 << "The number of partitions you gave is " << arg1
827 << ", but must be greater than zero.");
832 size_type,
833 size_type,
834 << "The array has size " << arg1 << " but should have size "
835 << arg2);
837private:
842
847
852
858
859 // Make all the chunk sparse matrix kinds friends.
860 template <typename>
861 friend class ChunkSparseMatrix;
862
863 // Make the accessor class a friend.
865};
866
867
869/*---------------------- Inline functions -----------------------------------*/
870
871#ifndef DOXYGEN
872
874{
875 inline Accessor::Accessor(const ChunkSparsityPattern *sparsity_pattern,
876 const size_type row)
877 : sparsity_pattern(sparsity_pattern)
878 , reduced_accessor(row == sparsity_pattern->n_rows() ?
879 *sparsity_pattern->sparsity_pattern.end() :
880 *sparsity_pattern->sparsity_pattern.begin(
881 row / sparsity_pattern->get_chunk_size()))
882 , chunk_row(row == sparsity_pattern->n_rows() ?
883 0 :
884 row % sparsity_pattern->get_chunk_size())
885 , chunk_col(0)
886 {}
887
888
889
890 inline Accessor::Accessor(const ChunkSparsityPattern *sparsity_pattern)
891 : sparsity_pattern(sparsity_pattern)
892 , reduced_accessor(*sparsity_pattern->sparsity_pattern.end())
893 , chunk_row(0)
894 , chunk_col(0)
895 {}
896
897
898
899 inline bool
900 Accessor::is_valid_entry() const
901 {
902 return reduced_accessor.is_valid_entry() &&
903 sparsity_pattern->get_chunk_size() * reduced_accessor.row() +
904 chunk_row <
905 sparsity_pattern->n_rows() &&
906 sparsity_pattern->get_chunk_size() * reduced_accessor.column() +
907 chunk_col <
908 sparsity_pattern->n_cols();
909 }
910
911
912
913 inline Accessor::size_type
914 Accessor::row() const
915 {
916 Assert(is_valid_entry() == true, ExcInvalidIterator());
917
918 return sparsity_pattern->get_chunk_size() * reduced_accessor.row() +
919 chunk_row;
920 }
921
922
923
924 inline Accessor::size_type
925 Accessor::column() const
926 {
927 Assert(is_valid_entry() == true, ExcInvalidIterator());
928
929 return sparsity_pattern->get_chunk_size() * reduced_accessor.column() +
930 chunk_col;
931 }
932
933
934
935 inline std::size_t
936 Accessor::reduced_index() const
937 {
938 Assert(is_valid_entry() == true, ExcInvalidIterator());
939
940 return reduced_accessor.linear_index;
941 }
942
943
944
945 inline bool
946 Accessor::operator==(const Accessor &other) const
947 {
948 // no need to check for equality of sparsity patterns as this is done in
949 // the reduced case already and every ChunkSparsityPattern has its own
950 // reduced sparsity pattern
951 return (reduced_accessor == other.reduced_accessor &&
952 chunk_row == other.chunk_row && chunk_col == other.chunk_col);
953 }
954
955
956
957 inline bool
958 Accessor::operator<(const Accessor &other) const
959 {
960 Assert(sparsity_pattern == other.sparsity_pattern, ExcInternalError());
961
962 if (chunk_row != other.chunk_row)
963 {
964 if (reduced_accessor.linear_index ==
965 reduced_accessor.container->n_nonzero_elements())
966 return false;
967 if (other.reduced_accessor.linear_index ==
968 reduced_accessor.container->n_nonzero_elements())
969 return true;
970
971 const auto global_row = sparsity_pattern->get_chunk_size() *
972 reduced_accessor.row() +
973 chunk_row,
974 other_global_row = sparsity_pattern->get_chunk_size() *
975 other.reduced_accessor.row() +
976 other.chunk_row;
977 if (global_row < other_global_row)
978 return true;
979 else if (global_row > other_global_row)
980 return false;
981 }
982
983 return (
984 reduced_accessor.linear_index < other.reduced_accessor.linear_index ||
985 (reduced_accessor.linear_index == other.reduced_accessor.linear_index &&
986 chunk_col < other.chunk_col));
987 }
988
989
990 inline void
991 Accessor::advance()
992 {
993 const auto chunk_size = sparsity_pattern->get_chunk_size();
994 Assert(chunk_row < chunk_size && chunk_col < chunk_size,
996 Assert(reduced_accessor.row() * chunk_size + chunk_row <
997 sparsity_pattern->n_rows() &&
998 reduced_accessor.column() * chunk_size + chunk_col <
999 sparsity_pattern->n_cols(),
1001 if (chunk_size == 1)
1002 {
1003 reduced_accessor.advance();
1004 return;
1005 }
1006
1007 ++chunk_col;
1008
1009 // end of chunk
1010 if (chunk_col == chunk_size ||
1011 reduced_accessor.column() * chunk_size + chunk_col ==
1012 sparsity_pattern->n_cols())
1013 {
1014 const auto reduced_row = reduced_accessor.row();
1015 // end of row
1016 if (reduced_accessor.linear_index + 1 ==
1017 reduced_accessor.container->rowstart[reduced_row + 1])
1018 {
1019 ++chunk_row;
1020
1021 chunk_col = 0;
1022
1023 // end of chunk rows or end of matrix
1024 if (chunk_row == chunk_size ||
1025 (reduced_row * chunk_size + chunk_row ==
1026 sparsity_pattern->n_rows()))
1027 {
1028 chunk_row = 0;
1029 reduced_accessor.advance();
1030 }
1031 // go back to the beginning of the same reduced row but with
1032 // chunk_row increased by one
1033 else
1034 reduced_accessor.linear_index =
1035 reduced_accessor.container->rowstart[reduced_row];
1036 }
1037 // advance within chunk
1038 else
1039 {
1040 reduced_accessor.advance();
1041 chunk_col = 0;
1042 }
1043 }
1044 }
1045
1046
1047
1048 inline Iterator::Iterator(const ChunkSparsityPattern *sparsity_pattern,
1049 const size_type row)
1050 : accessor(sparsity_pattern, row)
1051 {}
1052
1053
1054
1055 inline Iterator &
1056 Iterator::operator++()
1057 {
1058 accessor.advance();
1059 return *this;
1060 }
1061
1062
1063
1064 inline Iterator
1065 Iterator::operator++(int)
1066 {
1067 const Iterator iter = *this;
1068 accessor.advance();
1069 return iter;
1070 }
1071
1072
1073
1074 inline const Accessor &
1075 Iterator::operator*() const
1076 {
1077 return accessor;
1078 }
1079
1080
1081
1082 inline const Accessor *
1083 Iterator::operator->() const
1084 {
1085 return &accessor;
1086 }
1087
1088
1089 inline bool
1090 Iterator::operator==(const Iterator &other) const
1091 {
1092 return (accessor == other.accessor);
1093 }
1094
1095
1096
1097 inline bool
1098 Iterator::operator!=(const Iterator &other) const
1099 {
1100 return !(accessor == other.accessor);
1101 }
1102
1103
1104 inline bool
1105 Iterator::operator<(const Iterator &other) const
1106 {
1107 return accessor < other.accessor;
1108 }
1109
1110} // namespace ChunkSparsityPatternIterators
1111
1112
1113
1116{
1117 return {this, 0};
1118}
1119
1120
1123{
1124 return {this, n_rows()};
1125}
1126
1127
1128
1130ChunkSparsityPattern::begin(const size_type r) const
1131{
1133 return {this, r};
1134}
1135
1136
1137
1139ChunkSparsityPattern::end(const size_type r) const
1140{
1142 return {this, r + 1};
1143}
1144
1145
1146
1149{
1150 return rows;
1151}
1152
1153
1156{
1157 return cols;
1158}
1159
1160
1161
1164{
1165 return chunk_size;
1166}
1167
1168
1169
1170inline bool
1172{
1174}
1175
1176
1177
1178template <typename ForwardIterator>
1179void
1180ChunkSparsityPattern::copy_from(const size_type n_rows,
1181 const size_type n_cols,
1182 const ForwardIterator begin,
1183 const ForwardIterator end,
1184 const size_type chunk_size)
1185{
1186 Assert(static_cast<size_type>(std::distance(begin, end)) == n_rows,
1187 ExcIteratorRange(std::distance(begin, end), n_rows));
1188
1189 // first determine row lengths for each row. if the matrix is quadratic,
1190 // then we might have to add an additional entry for the diagonal, if that
1191 // is not yet present. as we have to call compress anyway later on, don't
1192 // bother to check whether that diagonal entry is in a certain row or not
1193 const bool is_square = (n_rows == n_cols);
1194 std::vector<size_type> row_lengths;
1195 row_lengths.reserve(n_rows);
1196 for (ForwardIterator i = begin; i != end; ++i)
1197 row_lengths.push_back(std::distance(i->begin(), i->end()) +
1198 (is_square ? 1 : 0));
1199 reinit(n_rows, n_cols, row_lengths, chunk_size);
1200
1201 // now enter all the elements into the matrix
1202 size_type row = 0;
1203 using inner_iterator =
1204 typename std::iterator_traits<ForwardIterator>::value_type::const_iterator;
1205 for (ForwardIterator i = begin; i != end; ++i, ++row)
1206 {
1207 const inner_iterator end_of_row = i->end();
1208 for (inner_iterator j = i->begin(); j != end_of_row; ++j)
1209 {
1210 const size_type col =
1211 internal::SparsityPatternTools::get_column_index_from_iterator(*j);
1212 Assert(col < n_cols, ExcInvalidIndex(col, n_cols));
1213
1214 add(row, col);
1215 }
1216 }
1217
1218 // finally compress everything. this also sorts the entries within each row
1219 compress();
1220}
1221
1222
1223#endif // DOXYGEN
1224
1226
1227#endif
*  iterator end()
*  *  iterator begin()
SparsityPatternIterators::Accessor reduced_accessor
Accessor(const ChunkSparsityPattern *matrix, const size_type row)
bool operator<(const Accessor &) const
Accessor(const ChunkSparsityPattern *matrix)
bool operator==(const Accessor &) const
bool operator!=(const Iterator &) const
bool operator==(const Iterator &) const
Iterator(const ChunkSparsityPattern *sp, const size_type row)
bool operator<(const Iterator &) const
const Accessor * operator->() const
const Accessor & operator*() const
void create_from(const size_type m, const size_type n, const Sparsity &sparsity_pattern_for_chunks, const size_type chunk_size, const bool optimize_diagonal=true)
void add(const size_type i, const size_type j)
void block_write(std::ostream &out) const
~ChunkSparsityPattern() override=default
static const size_type invalid_entry
std::size_t memory_consumption() const
types::global_dof_index size_type
bool exists(const size_type i, const size_type j) const
iterator end() const
iterator end(const size_type r) const
void reinit(const size_type m, const size_type n, const size_type max_per_row, const size_type chunk_size)
void print_gnuplot(std::ostream &out) const
void block_read(std::istream &in)
bool is_compressed() const
ChunkSparsityPattern & operator=(const ChunkSparsityPattern &)
size_type max_entries_per_row() const
size_type n_cols() const
size_type n_nonzero_elements() const
size_type row_length(const size_type row) const
iterator begin() const
void print(std::ostream &out) const
size_type get_chunk_size() const
void copy_from(const size_type n_rows, const size_type n_cols, const ForwardIterator begin, const ForwardIterator end, const size_type chunk_size)
size_type n_rows() const
iterator begin(const size_type r) const
static constexpr size_type invalid_entry
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DeclException0(Exception0)
static ::ExceptionBase & ExcInvalidIterator()
static ::ExceptionBase & ExcInvalidNumberOfPartitions(size_type arg1)
static ::ExceptionBase & ExcNotEnoughSpace(size_type arg1, size_type arg2)
static ::ExceptionBase & ExcMETISNotInstalled()
#define Assert(cond, exc)
static ::ExceptionBase & ExcNotCompressed()
static ::ExceptionBase & ExcIteratorPastEnd()
static ::ExceptionBase & ExcMatrixIsCompressed()
#define DeclException2(Exception2, type1, type2, outsequence)
#define AssertIndexRange(index, range)
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcInvalidArraySize(size_type arg1, size_type arg2)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcEmptyObject()
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcInvalidIndex(size_type arg1, size_type arg2)
static ::ExceptionBase & ExcIteratorRange(size_type arg1, size_type arg2)
static ::ExceptionBase & ExcInvalidNumber(size_type arg1)
unsigned int global_dof_index
Definition types.h:92