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
sparse_matrix_ez.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) 2002 - 2026 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_sparse_matrix_ez_h
14#define dealii_sparse_matrix_ez_h
15
16
17#include <deal.II/base/config.h>
18
23#include <deal.II/base/types.h>
24
26
27#include <vector>
28
30
31// Forward declarations
32#ifndef DOXYGEN
33template <typename number>
34class Vector;
35template <typename number>
36class FullMatrix;
37#endif
38
103template <typename number>
105{
106public:
111
118 struct Traits
119 {
124 static const bool zero_addition_can_be_elided = true;
125 };
126
131 struct Entry
132 {
136 Entry();
137
141 Entry(const size_type column, const number &value);
142
147
151 number value;
152
157 };
158
163 struct RowInfo
164 {
169
177 unsigned short length;
181 unsigned short diagonal;
185 static const unsigned short invalid_diagonal =
186 static_cast<unsigned short>(-1);
187 };
188
189public:
194 {
195 private:
200 {
201 public:
207 const size_type row,
208 const unsigned short index);
209
214 row() const;
215
219 unsigned short
220 index() const;
221
226 column() const;
227
231 number
232 value() const;
233
234 protected:
239
244
248 unsigned short a_index;
249
250 // Make enclosing class a friend.
251 friend class const_iterator;
252 };
253
254 public:
259 const size_type row,
260 const unsigned short index);
261
266 operator++();
267
271 const Accessor &
272 operator*() const;
273
277 const Accessor *
278 operator->() const;
279
283 bool
284 operator==(const const_iterator &) const;
288 bool
289 operator!=(const const_iterator &) const;
290
295 bool
296 operator<(const const_iterator &) const;
297
298 private:
303 };
304
309 using value_type = number;
310
319
328
335 explicit SparseMatrixEZ(const size_type n_rows,
336 const size_type n_columns,
337 const size_type default_row_length = 0,
338 const unsigned int default_increment = 1);
339
343 ~SparseMatrixEZ() override = default;
344
350
360 operator=(const double d);
361
369 void
370 reinit(const size_type n_rows,
371 const size_type n_columns,
372 const size_type default_row_length = 0,
373 const unsigned int default_increment = 1,
374 const size_type reserve = 0);
375
380 void
391 bool
392 empty() const;
393
399 m() const;
400
406 n() const;
407
412 get_row_length(const size_type row) const;
413
419
424 std::size_t
426
432 template <typename StreamType>
433 void
434 print_statistics(StreamType &s, bool full = false);
435
445 void
447 size_type &allocated,
448 size_type &reserved,
449 std::vector<size_type> &used_by_line,
450 const bool compute_by_line) const;
473 void
474 set(const size_type i,
475 const size_type j,
476 const number value,
477 const bool elide_zero_values = true);
478
489 void
490 add(const size_type i, const size_type j, const number value);
491
506 template <typename number2>
507 void
508 add(const std::vector<size_type> &indices,
509 const FullMatrix<number2> &full_matrix,
510 const bool elide_zero_values = true);
511
517 template <typename number2>
518 void
519 add(const std::vector<size_type> &row_indices,
520 const std::vector<size_type> &col_indices,
521 const FullMatrix<number2> &full_matrix,
522 const bool elide_zero_values = true);
523
533 template <typename number2>
534 void
535 add(const size_type row,
536 const std::vector<size_type> &col_indices,
537 const std::vector<number2> &values,
538 const bool elide_zero_values = true);
539
549 template <typename number2>
550 void
551 add(const size_type row,
552 const size_type n_cols,
553 const size_type *col_indices,
554 const number2 *values,
555 const bool elide_zero_values = true,
556 const bool col_indices_are_sorted = false);
557
558
563 operator*=(const number factor);
564
569 operator/=(const number factor);
570
592 template <typename MatrixType>
594 copy_from(const MatrixType &source, const bool elide_zero_values = true);
595
603 template <typename MatrixType>
604 void
605 add(const number factor, const MatrixType &matrix);
620 number
621 operator()(const size_type i, const size_type j) const;
622
627 number
628 el(const size_type i, const size_type j) const;
629
634 number
635 diag_element(const size_type i) const;
636
642 number &
643 diag_element(const size_type i);
644
654 template <typename somenumber>
655 void
657
663 template <typename somenumber>
664 void
666
671 template <typename somenumber>
672 void
674
680 template <typename somenumber>
681 void
691 number
692 l2_norm() const;
703 template <typename somenumber>
704 void
706 const Vector<somenumber> &src,
707 const number omega = 1.) const;
708
712 template <typename somenumber>
713 void
715 const Vector<somenumber> &src,
716 const number om = 1.,
717 const std::vector<std::size_t> &pos_right_of_diagonal =
718 std::vector<std::size_t>()) const;
719
724 template <typename somenumber>
725 void
727 const Vector<somenumber> &src,
728 const number om = 1.) const;
729
734 template <typename somenumber>
735 void
737 const Vector<somenumber> &src,
738 const number om = 1.) const;
739
748 template <typename MatrixTypeA, typename MatrixTypeB>
749 void
750 conjugate_add(const MatrixTypeA &A,
751 const MatrixTypeB &B,
752 const bool transpose = false);
762 begin() const;
763
768 end() const;
769
775 begin(const size_type r) const;
776
782 end(const size_type r) const;
792 void
793 print(std::ostream &out) const;
794
817 void
818 print_formatted(std::ostream &out,
819 const unsigned int precision = 3,
820 const bool scientific = true,
821 const unsigned int width = 0,
822 const char *zero_string = " ",
823 const double denominator = 1.,
824 const char *separator = " ") const;
825
831 void
832 block_write(std::ostream &out) const;
833
844 void
845 block_read(std::istream &in);
857
862 int,
863 int,
864 << "The entry with index (" << arg1 << ',' << arg2
865 << ") does not exist.");
866
868 int,
869 int,
870 << "An entry with index (" << arg1 << ',' << arg2
871 << ") cannot be allocated.");
874protected:
885 void
886 prepare_add();
887
892 void
893 prepare_set();
894
895private:
900 const Entry *
901 locate(const size_type row, const size_type col) const;
902
907 Entry *
908 locate(const size_type row, const size_type col);
909
913 Entry *
914 allocate(const size_type row, const size_type col);
915
921 template <typename somenumber>
922 void
924 const Vector<somenumber> &src,
925 const size_type begin_row,
926 const size_type end_row) const;
927
933 template <typename somenumber>
934 void
936 const size_type begin_row,
937 const size_type end_row,
938 somenumber *partial_sum) const;
939
945 template <typename somenumber>
946 void
948 const Vector<somenumber> &v,
949 const size_type begin_row,
950 const size_type end_row,
951 somenumber *partial_sum) const;
952
957
961 std::vector<RowInfo> row_info;
962
966 std::vector<Entry> data;
967
971 unsigned int increment;
972
977
978 // To allow it calling private prepare_add() and prepare_set().
979 template <typename>
980 friend class BlockMatrixBase;
981};
982
986/*---------------------- Inline functions -----------------------------------*/
987
988template <typename number>
990 const number &value)
991 : column(column)
992 , value(value)
993{}
994
995
996
997template <typename number>
999 : column(invalid)
1000 , value(0)
1001{}
1002
1003
1004template <typename number>
1006 : start(start)
1007 , length(0)
1008 , diagonal(invalid_diagonal)
1009{}
1010
1011
1012//---------------------------------------------------------------------------
1013template <typename number>
1015 const SparseMatrixEZ<number> *matrix,
1016 const size_type r,
1017 const unsigned short i)
1018 : matrix(matrix)
1019 , a_row(r)
1020 , a_index(i)
1021{}
1022
1023
1024template <typename number>
1027{
1028 return a_row;
1029}
1030
1031
1032template <typename number>
1035{
1036 return matrix->data[matrix->row_info[a_row].start + a_index].column;
1037}
1038
1039
1040template <typename number>
1041inline unsigned short
1043{
1044 return a_index;
1045}
1046
1047
1048
1049template <typename number>
1050inline number
1052{
1053 return matrix->data[matrix->row_info[a_row].start + a_index].value;
1054}
1055
1056
1057template <typename number>
1059 const SparseMatrixEZ<number> *matrix,
1060 const size_type r,
1061 const unsigned short i)
1062 : accessor(matrix, r, i)
1063{
1064 // Finish if this is the end()
1065 if (r == accessor.matrix->m() && i == 0)
1066 return;
1067
1068 // Make sure we never construct an
1069 // iterator pointing to a
1070 // non-existing entry
1071
1072 // If the index points beyond the
1073 // end of the row, try the next
1074 // row.
1075 if (accessor.a_index >= accessor.matrix->row_info[accessor.a_row].length)
1076 {
1077 do
1078 {
1079 ++accessor.a_row;
1080 }
1081 // Beware! If the next row is
1082 // empty, iterate until a
1083 // non-empty row is found or we
1084 // hit the end of the matrix.
1085 while (accessor.a_row < accessor.matrix->m() &&
1086 accessor.matrix->row_info[accessor.a_row].length == 0);
1087 }
1088}
1089
1090
1091template <typename number>
1094{
1095 Assert(accessor.a_row < accessor.matrix->m(), ExcIteratorPastEnd());
1096
1097 // Increment column index
1098 ++(accessor.a_index);
1099 // If index exceeds number of
1100 // entries in this row, proceed
1101 // with next row.
1102 if (accessor.a_index >= accessor.matrix->row_info[accessor.a_row].length)
1103 {
1104 accessor.a_index = 0;
1105 // Do this loop to avoid
1106 // elements in empty rows
1107 do
1108 {
1109 ++accessor.a_row;
1110 }
1111 while (accessor.a_row < accessor.matrix->m() &&
1112 accessor.matrix->row_info[accessor.a_row].length == 0);
1113 }
1114 return *this;
1115}
1116
1117
1118template <typename number>
1121{
1122 return accessor;
1123}
1124
1125
1126template <typename number>
1129{
1130 return &accessor;
1131}
1132
1133
1134template <typename number>
1135inline bool
1137 const const_iterator &other) const
1138{
1139 return (accessor.row() == other.accessor.row() &&
1140 accessor.index() == other.accessor.index());
1141}
1142
1143
1144template <typename number>
1145inline bool
1147 const const_iterator &other) const
1148{
1149 return !(*this == other);
1150}
1151
1152
1153template <typename number>
1154inline bool
1156 const const_iterator &other) const
1157{
1158 return (accessor.row() < other.accessor.row() ||
1159 (accessor.row() == other.accessor.row() &&
1160 accessor.index() < other.accessor.index()));
1161}
1162
1163
1164//---------------------------------------------------------------------------
1165template <typename number>
1168{
1169 return row_info.size();
1170}
1171
1172
1173template <typename number>
1176{
1177 return n_columns;
1178}
1179
1180
1181template <typename number>
1182inline typename SparseMatrixEZ<number>::Entry *
1184{
1185 AssertIndexRange(row, m());
1186 AssertIndexRange(col, n());
1187
1188 const RowInfo &r = row_info[row];
1189 const size_type end = r.start + r.length;
1190 for (size_type i = r.start; i < end; ++i)
1191 {
1192 Entry *const entry = &data[i];
1193 if (entry->column == col)
1194 return entry;
1195 if (entry->column == Entry::invalid)
1196 return nullptr;
1197 }
1198 return nullptr;
1199}
1200
1201
1202
1203template <typename number>
1204inline const typename SparseMatrixEZ<number>::Entry *
1206{
1207 SparseMatrixEZ<number> *t = const_cast<SparseMatrixEZ<number> *>(this);
1208 return t->locate(row, col);
1209}
1210
1211
1212template <typename number>
1213inline typename SparseMatrixEZ<number>::Entry *
1215{
1216 AssertIndexRange(row, m());
1217 AssertIndexRange(col, n());
1218
1219 RowInfo &r = row_info[row];
1220 const size_type end = r.start + r.length;
1221
1222 size_type i = r.start;
1223 // If diagonal exists and this
1224 // column is higher, start only
1225 // after diagonal.
1226 if (r.diagonal != RowInfo::invalid_diagonal && col >= row)
1227 i += r.diagonal;
1228 // Find position of entry
1229 while (i < end && data[i].column < col)
1230 ++i;
1231
1232 // entry found
1233 if (i != end && data[i].column == col)
1234 return &data[i];
1235
1236 // Now, we must insert the new
1237 // entry and move all successive
1238 // entries back.
1239
1240 // If no more space is available
1241 // for this row, insert new
1242 // elements into the vector.
1243 // TODO:[GK] We should not extend this row if i<end
1244 if (row != row_info.size() - 1)
1245 {
1246 if (end >= row_info[row + 1].start)
1247 {
1248 // Failure if increment 0
1250
1251 // Insert new entries
1252 data.insert(data.begin() + end, increment, Entry());
1253 // Update starts of
1254 // following rows
1255 for (size_type rn = row + 1; rn < row_info.size(); ++rn)
1256 row_info[rn].start += increment;
1257 }
1258 }
1259 else
1260 {
1261 if (end >= data.size())
1262 {
1263 // Here, appending a block
1264 // does not increase
1265 // performance.
1266 data.push_back(Entry());
1267 }
1268 }
1269
1270 Entry *entry = &data[i];
1271 // Save original entry
1272 Entry temp = *entry;
1273 // Insert new entry here to
1274 // make sure all entries
1275 // are ordered by column
1276 // index
1277 entry->column = col;
1278 entry->value = 0;
1279 // Update row_info
1280 ++r.length;
1281 if (col == row)
1282 r.diagonal = i - r.start;
1283 else if (col < row && r.diagonal != RowInfo::invalid_diagonal)
1284 ++r.diagonal;
1285
1286 if (i == end)
1287 return entry;
1288
1289 // Move all entries in this
1290 // row up by one
1291 for (size_type j = i + 1; j < end; ++j)
1292 {
1293 // There should be no invalid
1294 // entry below end
1295 Assert(data[j].column != Entry::invalid, ExcInternalError());
1296
1297 // TODO[GK]: This could be done more efficiently by moving starting at the
1298 // top rather than swapping starting at the bottom
1299 std::swap(data[j], temp);
1300 }
1302
1303 data[end] = temp;
1304
1305 return entry;
1306}
1307
1308
1309
1310template <typename number>
1311inline void
1313 const size_type j,
1314 const number value,
1315 const bool elide_zero_values)
1316{
1317 AssertIsFinite(value);
1318
1319 AssertIndexRange(i, m());
1320 AssertIndexRange(j, n());
1321
1322 if (elide_zero_values && value == 0.)
1323 {
1324 Entry *entry = locate(i, j);
1325 if (entry != nullptr)
1326 entry->value = 0.;
1327 }
1328 else
1329 {
1330 Entry *entry = allocate(i, j);
1331 entry->value = value;
1332 }
1333}
1334
1335
1336
1337template <typename number>
1338inline void
1340 const size_type j,
1341 const number value)
1342{
1343 AssertIsFinite(value);
1344
1345 AssertIndexRange(i, m());
1346 AssertIndexRange(j, n());
1347
1348 // ignore zero additions
1349 if (std::abs(value) == 0.)
1350 return;
1351
1352 Entry *entry = allocate(i, j);
1353 entry->value += value;
1354}
1355
1356
1357template <typename number>
1358template <typename number2>
1359void
1360SparseMatrixEZ<number>::add(const std::vector<size_type> &indices,
1361 const FullMatrix<number2> &full_matrix,
1362 const bool elide_zero_values)
1363{
1364 // TODO: This function can surely be made more efficient
1365 for (size_type i = 0; i < indices.size(); ++i)
1366 for (size_type j = 0; j < indices.size(); ++j)
1367 if ((full_matrix(i, j) != 0) || (elide_zero_values == false))
1368 add(indices[i], indices[j], full_matrix(i, j));
1369}
1370
1371
1372
1373template <typename number>
1374template <typename number2>
1375void
1376SparseMatrixEZ<number>::add(const std::vector<size_type> &row_indices,
1377 const std::vector<size_type> &col_indices,
1378 const FullMatrix<number2> &full_matrix,
1379 const bool elide_zero_values)
1380{
1381 // TODO: This function can surely be made more efficient
1382 for (size_type i = 0; i < row_indices.size(); ++i)
1383 for (size_type j = 0; j < col_indices.size(); ++j)
1384 if ((full_matrix(i, j) != 0) || (elide_zero_values == false))
1385 add(row_indices[i], col_indices[j], full_matrix(i, j));
1386}
1387
1388
1389
1390template <typename number>
1391template <typename number2>
1392void
1394 const std::vector<size_type> &col_indices,
1395 const std::vector<number2> &values,
1396 const bool elide_zero_values)
1397{
1398 // TODO: This function can surely be made more efficient
1399 for (size_type j = 0; j < col_indices.size(); ++j)
1400 if ((values[j] != 0) || (elide_zero_values == false))
1401 add(row, col_indices[j], values[j]);
1402}
1403
1404
1405
1406template <typename number>
1407template <typename number2>
1408void
1410 const size_type n_cols,
1411 const size_type *col_indices,
1412 const number2 *values,
1413 const bool elide_zero_values,
1414 const bool /*col_indices_are_sorted*/)
1415{
1416 // TODO: This function can surely be made more efficient
1417 for (size_type j = 0; j < n_cols; ++j)
1418 if ((std::abs(values[j]) != 0) || (elide_zero_values == false))
1419 add(row, col_indices[j], values[j]);
1420}
1421
1422
1423template <typename number>
1426{
1427 for (Entry &entry : data)
1428 entry.value *= factor;
1429
1430 return *this;
1431}
1432
1433
1434
1435template <typename number>
1438{
1439 Assert(factor != number(), ExcDivideByZero());
1440
1441 const number factor_inv = number(1.) / factor;
1442
1443 for (Entry &entry : data)
1444 entry.value *= factor_inv;
1445
1446 return *this;
1447}
1448
1449
1450template <typename number>
1451inline number
1453{
1454 const Entry *entry = locate(i, j);
1455 if (entry)
1456 return entry->value;
1457 else
1458 return 0.;
1459}
1460
1461template <typename number>
1462inline number
1464{
1465 Assert(m() == n(), ExcNotQuadratic());
1466 AssertIndexRange(i, m());
1467
1468 const Entry *entry = locate(i, i);
1469 if (entry)
1470 return entry->value;
1471 else
1472 return 0.;
1473}
1474
1475
1476
1477template <typename number>
1478inline number &
1480{
1481 Assert(m() == n(), ExcNotQuadratic());
1482 AssertIndexRange(i, m());
1483
1484 Entry *entry = locate(i, i);
1485 if (!entry)
1486 {
1487 set(i, i, number());
1488 entry = locate(i, i);
1489 }
1490
1491 return entry->value;
1492}
1493
1494
1495
1496template <typename number>
1497inline number
1499{
1500 const Entry *entry = locate(i, j);
1501 if (entry)
1502 return entry->value;
1503 Assert(false, ExcInvalidEntry(i, j));
1504 return 0.;
1505}
1506
1507
1508template <typename number>
1511{
1512 const_iterator result(this, 0, 0);
1513 return result;
1514}
1515
1516template <typename number>
1519{
1520 return const_iterator(this, m(), 0);
1521}
1522
1523template <typename number>
1526{
1527 AssertIndexRange(r, m());
1528 const_iterator result(this, r, 0);
1529 return result;
1530}
1531
1532template <typename number>
1535{
1536 AssertIndexRange(r, m());
1537 const_iterator result(this, r + 1, 0);
1538 return result;
1539}
1540
1541template <typename number>
1542template <typename MatrixType>
1545 const bool elide_zero_values)
1546{
1547 reinit(M.m(), M.n(), this->saved_default_row_length, this->increment);
1548
1549 // loop over the elements of the argument matrix row by row, as suggested
1550 // in the documentation of the sparse matrix iterator class, and
1551 // copy them into the current object
1552 for (size_type row = 0; row < M.m(); ++row)
1553 {
1554 const typename MatrixType::const_iterator end_row = M.end(row);
1555 for (typename MatrixType::const_iterator entry = M.begin(row);
1556 entry != end_row;
1557 ++entry)
1558 set(row, entry->column(), entry->value(), elide_zero_values);
1559 }
1560
1561 return *this;
1562}
1563
1564template <typename number>
1565template <typename MatrixType>
1566inline void
1567SparseMatrixEZ<number>::add(const number factor, const MatrixType &M)
1568{
1569 Assert(M.m() == m(), ExcDimensionMismatch(M.m(), m()));
1570 Assert(M.n() == n(), ExcDimensionMismatch(M.n(), n()));
1571
1572 if (factor == 0.)
1573 return;
1574
1575 // loop over the elements of the argument matrix row by row, as suggested
1576 // in the documentation of the sparse matrix iterator class, and
1577 // add them into the current object
1578 for (size_type row = 0; row < M.m(); ++row)
1579 {
1580 const typename MatrixType::const_iterator end_row = M.end(row);
1581 for (typename MatrixType::const_iterator entry = M.begin(row);
1582 entry != end_row;
1583 ++entry)
1584 if (entry->value() != 0)
1585 add(row, entry->column(), factor * entry->value());
1586 }
1587}
1588
1589
1590
1591template <typename number>
1592template <typename MatrixTypeA, typename MatrixTypeB>
1593inline void
1595 const MatrixTypeB &B,
1596 const bool transpose)
1597{
1598 // Compute the result
1599 // r_ij = \sum_kl b_ik b_jl a_kl
1600
1601 // Assert (n() == B.m(), ExcDimensionMismatch(n(), B.m()));
1602 // Assert (m() == B.m(), ExcDimensionMismatch(m(), B.m()));
1603 // Assert (A.n() == B.n(), ExcDimensionMismatch(A.n(), B.n()));
1604 // Assert (A.m() == B.n(), ExcDimensionMismatch(A.m(), B.n()));
1605
1606 // Somehow, we have to avoid making
1607 // this an operation of complexity
1608 // n^2. For the transpose case, we
1609 // can go through the non-zero
1610 // elements of A^-1 and use the
1611 // corresponding rows of B only.
1612 // For the non-transpose case, we
1613 // must find a trick.
1614 typename MatrixTypeB::const_iterator b1 = B.begin();
1615 const typename MatrixTypeB::const_iterator b_final = B.end();
1616 if (transpose)
1617 while (b1 != b_final)
1618 {
1619 const size_type i = b1->column();
1620 const size_type k = b1->row();
1621 typename MatrixTypeB::const_iterator b2 = B.begin();
1622 while (b2 != b_final)
1623 {
1624 const size_type j = b2->column();
1625 const size_type l = b2->row();
1626
1627 const typename MatrixTypeA::value_type a = A.el(k, l);
1628
1629 if (a != 0.)
1630 add(i, j, a * b1->value() * b2->value());
1631 ++b2;
1632 }
1633 ++b1;
1634 }
1635 else
1636 {
1637 // Determine minimal and
1638 // maximal row for a column in
1639 // advance.
1640
1641 std::vector<size_type> minrow(B.n(), B.m());
1642 std::vector<size_type> maxrow(B.n(), 0);
1643 while (b1 != b_final)
1644 {
1645 const size_type r = b1->row();
1646 if (r < minrow[b1->column()])
1647 minrow[b1->column()] = r;
1648 if (r > maxrow[b1->column()])
1649 maxrow[b1->column()] = r;
1650 ++b1;
1651 }
1652
1653 typename MatrixTypeA::const_iterator ai = A.begin();
1654 const typename MatrixTypeA::const_iterator ae = A.end();
1655
1656 while (ai != ae)
1657 {
1658 const typename MatrixTypeA::value_type a = ai->value();
1659 // Don't do anything if
1660 // this entry is zero.
1661 if (a == 0.)
1662 continue;
1663
1664 // Now, loop over all rows
1665 // having possibly a
1666 // nonzero entry in column
1667 // ai->row()
1668 b1 = B.begin(minrow[ai->row()]);
1669 const typename MatrixTypeB::const_iterator be1 =
1670 B.end(maxrow[ai->row()]);
1671 const typename MatrixTypeB::const_iterator be2 =
1672 B.end(maxrow[ai->column()]);
1673
1674 while (b1 != be1)
1675 {
1676 const double b1v = b1->value();
1677 // We need the product
1678 // of both. If it is
1679 // zero, we can save
1680 // the work
1681 if (b1->column() == ai->row() && (b1v != 0.))
1682 {
1683 const size_type i = b1->row();
1684
1685 typename MatrixTypeB::const_iterator b2 =
1686 B.begin(minrow[ai->column()]);
1687 while (b2 != be2)
1688 {
1689 if (b2->column() == ai->column())
1690 {
1691 const size_type j = b2->row();
1692 add(i, j, a * b1v * b2->value());
1693 }
1694 ++b2;
1695 }
1696 }
1697 ++b1;
1698 }
1699 ++ai;
1700 }
1701 }
1702}
1703
1704
1705template <typename number>
1706template <typename StreamType>
1707inline void
1709{
1710 size_type used;
1711 size_type allocated;
1712 size_type reserved;
1713 std::vector<size_type> used_by_line;
1714
1715 compute_statistics(used, allocated, reserved, used_by_line, full);
1716
1717 out << "SparseMatrixEZ:used entries:" << used << std::endl
1718 << "SparseMatrixEZ:allocated entries:" << allocated << std::endl
1719 << "SparseMatrixEZ:reserved entries:" << reserved << std::endl;
1720
1721 if (full)
1722 {
1723 for (size_type i = 0; i < used_by_line.size(); ++i)
1724 if (used_by_line[i] != 0)
1725 out << "SparseMatrixEZ:entries\t" << i << "\trows\t"
1726 << used_by_line[i] << std::endl;
1727 }
1728}
1729
1730
1731template <typename number>
1732inline void
1734{
1735 // nothing to do here
1736}
1737
1738
1739
1740template <typename number>
1741inline void
1743{
1744 // nothing to do here
1745}
1746
1748
1749#endif
*  *  const_iterator()=default
const SparseMatrixEZ< number > * matrix
Accessor(const SparseMatrixEZ< number > *matrix, const size_type row, const unsigned short index)
const Accessor & operator*() const
const_iterator(const SparseMatrixEZ< number > *matrix, const size_type row, const unsigned short index)
bool operator<(const const_iterator &) const
bool operator==(const const_iterator &) const
bool operator!=(const const_iterator &) const
const Accessor * operator->() const
void print_formatted(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const unsigned int width=0, const char *zero_string=" ", const double denominator=1., const char *separator=" ") const
void block_read(std::istream &in)
SparseMatrixEZ< number > & copy_from(const MatrixType &source, const bool elide_zero_values=true)
std::vector< Entry > data
void print_statistics(StreamType &s, bool full=false)
void Tvmult_add(Vector< somenumber > &dst, const Vector< somenumber > &src) const
void block_write(std::ostream &out) const
void compute_statistics(size_type &used, size_type &allocated, size_type &reserved, std::vector< size_type > &used_by_line, const bool compute_by_line) const
SparseMatrixEZ(const SparseMatrixEZ &)
bool empty() const
unsigned int increment
number operator()(const size_type i, const size_type j) const
const Entry * locate(const size_type row, const size_type col) const
size_type n() const
~SparseMatrixEZ() override=default
size_type m() const
Entry * allocate(const size_type row, const size_type col)
void threaded_matrix_scalar_product(const Vector< somenumber > &u, const Vector< somenumber > &v, const size_type begin_row, const size_type end_row, somenumber *partial_sum) const
size_type get_row_length(const size_type row) const
void precondition_TSOR(Vector< somenumber > &dst, const Vector< somenumber > &src, const number om=1.) const
std::size_t memory_consumption() const
size_type n_nonzero_elements() const
void print(std::ostream &out) const
SparseMatrixEZ< number > & operator=(const SparseMatrixEZ< number > &)
SparseMatrixEZ(const size_type n_rows, const size_type n_columns, const size_type default_row_length=0, const unsigned int default_increment=1)
void conjugate_add(const MatrixTypeA &A, const MatrixTypeB &B, const bool transpose=false)
void Tvmult(Vector< somenumber > &dst, const Vector< somenumber > &src) const
SparseMatrixEZ< number > & operator=(const double d)
void threaded_vmult(Vector< somenumber > &dst, const Vector< somenumber > &src, const size_type begin_row, const size_type end_row) const
void vmult_add(Vector< somenumber > &dst, const Vector< somenumber > &src) const
SparseMatrixEZ & operator*=(const number factor)
void reinit(const size_type n_rows, const size_type n_columns, const size_type default_row_length=0, const unsigned int default_increment=1, const size_type reserve=0)
void precondition_Jacobi(Vector< somenumber > &dst, const Vector< somenumber > &src, const number omega=1.) const
const_iterator end() const
void precondition_SSOR(Vector< somenumber > &dst, const Vector< somenumber > &src, const number om=1., const std::vector< std::size_t > &pos_right_of_diagonal=std::vector< std::size_t >()) const
std::vector< RowInfo > row_info
SparseMatrixEZ & operator/=(const number factor)
number el(const size_type i, const size_type j) const
const_iterator begin() const
void threaded_matrix_norm_square(const Vector< somenumber > &v, const size_type begin_row, const size_type end_row, somenumber *partial_sum) const
number l2_norm() const
unsigned int saved_default_row_length
void set(const size_type i, const size_type j, const number value, const bool elide_zero_values=true)
number diag_element(const size_type i) const
void add(const size_type i, const size_type j, const number value)
void precondition_SOR(Vector< somenumber > &dst, const Vector< somenumber > &src, const number om=1.) const
void vmult(Vector< somenumber > &dst, const Vector< somenumber > &src) const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
DerivativeForm< 1, spacedim, dim, Number > transpose(const DerivativeForm< 1, dim, spacedim, Number > &DF)
#define DeclException0(Exception0)
static ::ExceptionBase & ExcInvalidEntry(int arg1, int arg2)
static ::ExceptionBase & ExcNoDiagonal()
#define Assert(cond, exc)
static ::ExceptionBase & ExcIteratorPastEnd()
#define AssertIsFinite(number)
#define DeclException2(Exception2, type1, type2, outsequence)
static ::ExceptionBase & ExcEntryAllocationFailure(int arg1, int arg2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDivideByZero()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcNotQuadratic()
constexpr types::global_dof_index invalid_size_type
Definition types.h:240
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int global_dof_index
Definition types.h:92
static const size_type invalid
static const unsigned short invalid_diagonal
RowInfo(const size_type start=Entry::invalid)
static const bool zero_addition_can_be_elided