Reference documentation for deal.II version 8.4.2
sparse_matrix_ez.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2002 - 2016 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii__sparse_matrix_ez_h
17 #define dealii__sparse_matrix_ez_h
18 
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/base/subscriptor.h>
22 #include <deal.II/base/smartpointer.h>
23 #include <deal.II/lac/exceptions.h>
24 
25 #include <vector>
26 
27 DEAL_II_NAMESPACE_OPEN
28 
29 template<typename number> class Vector;
30 template<typename number> class FullMatrix;
31 
97 template <typename number>
98 class SparseMatrixEZ : public Subscriptor
99 {
100 public:
105 
110  struct Entry
111  {
115  Entry();
116 
120  Entry (const size_type column,
121  const number &value);
122 
126  size_type column;
127 
131  number value;
132 
136  static const size_type invalid = numbers::invalid_size_type;
137  };
138 
143  struct RowInfo
144  {
148  RowInfo (size_type start = Entry::invalid);
149 
153  size_type start;
157  unsigned short length;
161  unsigned short diagonal;
165  static const unsigned short
166  invalid_diagonal = static_cast<unsigned short>(-1);
167  };
168 
169 public:
170 
175  {
176  private:
180  class Accessor
181  {
182  public:
187  Accessor (const SparseMatrixEZ<number> *matrix,
188  const size_type row,
189  const unsigned short index);
190 
194  size_type row() const;
195 
199  unsigned short index() const;
200 
204  size_type column() const;
205 
209  number value() const;
210 
211  protected:
216 
220  size_type a_row;
221 
225  unsigned short a_index;
226 
230  friend class const_iterator;
231  };
232 
233  public:
238  const size_type row,
239  const unsigned short index);
240 
244  const_iterator &operator++ ();
245 
249  const_iterator &operator++ (int);
250 
254  const Accessor &operator* () const;
255 
259  const Accessor *operator-> () const;
260 
264  bool operator == (const const_iterator &) const;
268  bool operator != (const const_iterator &) const;
269 
274  bool operator < (const const_iterator &) const;
275 
276  private:
281 
289  };
290 
295  typedef number value_type;
296 
304  SparseMatrixEZ ();
305 
313  SparseMatrixEZ (const SparseMatrixEZ &);
314 
321  explicit SparseMatrixEZ (const size_type n_rows,
322  const size_type n_columns,
323  const size_type default_row_length = 0,
324  const unsigned int default_increment = 1);
325 
330  ~SparseMatrixEZ ();
331 
336 
345  SparseMatrixEZ<number> &operator = (const double d);
346 
354  void reinit (const size_type n_rows,
355  const size_type n_columns,
356  size_type default_row_length = 0,
357  unsigned int default_increment = 1,
358  size_type reserve = 0);
359 
364  void clear ();
366 
374  bool empty () const;
375 
380  size_type m () const;
381 
386  size_type n () const;
387 
391  size_type get_row_length (const size_type row) const;
392 
396  size_type n_nonzero_elements () const;
397 
402  std::size_t memory_consumption () const;
403 
409  template <class StreamType>
410  void print_statistics (StreamType &s, bool full = false);
411 
421  void compute_statistics (size_type &used,
422  size_type &allocated,
423  size_type &reserved,
424  std::vector<size_type> &used_by_line,
425  const bool compute_by_line) const;
427 
447  void set (const size_type i, const size_type j,
448  const number value, const bool elide_zero_values = true);
449 
455  void add (const size_type i,
456  const size_type j,
457  const number value);
458 
473  template <typename number2>
474  void add (const std::vector<size_type> &indices,
475  const FullMatrix<number2> &full_matrix,
476  const bool elide_zero_values = true);
477 
483  template <typename number2>
484  void add (const std::vector<size_type> &row_indices,
485  const std::vector<size_type> &col_indices,
486  const FullMatrix<number2> &full_matrix,
487  const bool elide_zero_values = true);
488 
498  template <typename number2>
499  void add (const size_type row,
500  const std::vector<size_type> &col_indices,
501  const std::vector<number2> &values,
502  const bool elide_zero_values = true);
503 
513  template <typename number2>
514  void add (const size_type row,
515  const size_type n_cols,
516  const size_type *col_indices,
517  const number2 *values,
518  const bool elide_zero_values = true,
519  const bool col_indices_are_sorted = false);
520 
542  template <typename MatrixType>
544  copy_from (const MatrixType &source, const bool elide_zero_values = true);
545 
553  template <typename MatrixType>
554  void add (const number factor,
555  const MatrixType &matrix);
557 
570  number operator () (const size_type i,
571  const size_type j) const;
572 
577  number el (const size_type i,
578  const size_type j) const;
580 
588  template <typename somenumber>
589  void vmult (Vector<somenumber> &dst,
590  const Vector<somenumber> &src) const;
591 
597  template <typename somenumber>
598  void Tvmult (Vector<somenumber> &dst,
599  const Vector<somenumber> &src) const;
600 
605  template <typename somenumber>
606  void vmult_add (Vector<somenumber> &dst,
607  const Vector<somenumber> &src) const;
608 
614  template <typename somenumber>
615  void Tvmult_add (Vector<somenumber> &dst,
616  const Vector<somenumber> &src) const;
618 
625  number l2_norm () const;
627 
636  template <typename somenumber>
638  const Vector<somenumber> &src,
639  const number omega = 1.) const;
640 
644  template <typename somenumber>
646  const Vector<somenumber> &src,
647  const number om = 1.,
648  const std::vector<std::size_t> &pos_right_of_diagonal = std::vector<std::size_t>()) const;
649 
654  template <typename somenumber>
656  const Vector<somenumber> &src,
657  const number om = 1.) const;
658 
663  template <typename somenumber>
665  const Vector<somenumber> &src,
666  const number om = 1.) const;
667 
676  template <typename MatrixTypeA, typename MatrixTypeB>
677  void conjugate_add (const MatrixTypeA &A,
678  const MatrixTypeB &B,
679  const bool transpose = false);
681 
688  const_iterator begin () const;
689 
693  const_iterator end () const;
694 
699  const_iterator begin (const size_type r) const;
700 
705  const_iterator end (const size_type r) const;
707 
715  void print (std::ostream &out) const;
716 
737  void print_formatted (std::ostream &out,
738  const unsigned int precision = 3,
739  const bool scientific = true,
740  const unsigned int width = 0,
741  const char *zero_string = " ",
742  const double denominator = 1.) const;
743 
749  void block_write (std::ostream &out) const;
750 
761  void block_read (std::istream &in);
763 
772  DeclException0(ExcNoDiagonal);
773 
777  DeclException2 (ExcInvalidEntry,
778  int, int,
779  << "The entry with index (" << arg1 << ',' << arg2
780  << ") does not exist.");
781 
782  DeclException2(ExcEntryAllocationFailure,
783  int, int,
784  << "An entry with index (" << arg1 << ',' << arg2
785  << ") cannot be allocated.");
787 private:
792  const Entry *locate (const size_type row,
793  const size_type col) const;
794 
799  Entry *locate (const size_type row,
800  const size_type col);
801 
805  Entry *allocate (const size_type row,
806  const size_type col);
807 
813  template <typename somenumber>
815  const Vector<somenumber> &src,
816  const size_type begin_row,
817  const size_type end_row) const;
818 
824  template <typename somenumber>
826  const size_type begin_row,
827  const size_type end_row,
828  somenumber *partial_sum) const;
829 
835  template <typename somenumber>
837  const Vector<somenumber> &v,
838  const size_type begin_row,
839  const size_type end_row,
840  somenumber *partial_sum) const;
841 
845  size_type n_columns;
846 
850  std::vector<RowInfo> row_info;
851 
855  std::vector<Entry> data;
856 
860  unsigned int increment;
861 
866 };
867 
871 /*---------------------- Inline functions -----------------------------------*/
872 
873 template <typename number>
874 inline
876  const number &value)
877  :
878  column(column),
879  value(value)
880 {}
881 
882 
883 
884 template <typename number>
885 inline
887  :
888  column(invalid),
889  value(0)
890 {}
891 
892 
893 template <typename number>
894 inline
896  :
897  start(start),
898  length(0),
899  diagonal(invalid_diagonal)
900 {}
901 
902 
903 //---------------------------------------------------------------------------
904 template <typename number>
905 inline
908  const size_type r,
909  const unsigned short i)
910  :
911  matrix(matrix),
912  a_row(r),
913  a_index(i)
914 {}
915 
916 
917 template <typename number>
918 inline
921 {
922  return a_row;
923 }
924 
925 
926 template <typename number>
927 inline
930 {
931  return matrix->data[matrix->row_info[a_row].start+a_index].column;
932 }
933 
934 
935 template <typename number>
936 inline
937 unsigned short
939 {
940  return a_index;
941 }
942 
943 
944 
945 template <typename number>
946 inline
947 number
949 {
950  return matrix->data[matrix->row_info[a_row].start+a_index].value;
951 }
952 
953 
954 template <typename number>
955 inline
958  const size_type r,
959  const unsigned short i)
960  :
961  accessor(matrix, r, i)
962 {
963  // Finish if this is the end()
964  if (r==accessor.matrix->m() && i==0) return;
965 
966  // Make sure we never construct an
967  // iterator pointing to a
968  // non-existing entry
969 
970  // If the index points beyond the
971  // end of the row, try the next
972  // row.
973  if (accessor.a_index >= accessor.matrix->row_info[accessor.a_row].length)
974  {
975  do
976  {
977  ++accessor.a_row;
978  }
979  // Beware! If the next row is
980  // empty, iterate until a
981  // non-empty row is found or we
982  // hit the end of the matrix.
983  while (accessor.a_row < accessor.matrix->m()
984  && accessor.matrix->row_info[accessor.a_row].length == 0);
985  }
986 }
987 
988 
989 template <typename number>
990 inline
993 {
994  Assert (accessor.a_row < accessor.matrix->m(), ExcIteratorPastEnd());
995 
996  // Increment column index
997  ++(accessor.a_index);
998  // If index exceeds number of
999  // entries in this row, proceed
1000  // with next row.
1001  if (accessor.a_index >= accessor.matrix->row_info[accessor.a_row].length)
1002  {
1003  accessor.a_index = 0;
1004  // Do this loop to avoid
1005  // elements in empty rows
1006  do
1007  {
1008  ++accessor.a_row;
1009  }
1010  while (accessor.a_row < accessor.matrix->m()
1011  && accessor.matrix->row_info[accessor.a_row].length == 0);
1012  }
1013  return *this;
1014 }
1015 
1016 
1017 template <typename number>
1018 inline
1021 {
1022  return accessor;
1023 }
1024 
1025 
1026 template <typename number>
1027 inline
1030 {
1031  return &accessor;
1032 }
1033 
1034 
1035 template <typename number>
1036 inline
1037 bool
1039  const const_iterator &other) const
1040 {
1041  return (accessor.row() == other.accessor.row() &&
1042  accessor.index() == other.accessor.index());
1043 }
1044 
1045 
1046 template <typename number>
1047 inline
1048 bool
1050 operator != (const const_iterator &other) const
1051 {
1052  return ! (*this == other);
1053 }
1054 
1055 
1056 template <typename number>
1057 inline
1058 bool
1060 operator < (const const_iterator &other) const
1061 {
1062  return (accessor.row() < other.accessor.row() ||
1063  (accessor.row() == other.accessor.row() &&
1064  accessor.index() < other.accessor.index()));
1065 }
1066 
1067 
1068 //---------------------------------------------------------------------------
1069 template <typename number>
1070 inline
1072 {
1073  return row_info.size();
1074 }
1075 
1076 
1077 template <typename number>
1078 inline
1080 {
1081  return n_columns;
1082 }
1083 
1084 
1085 template <typename number>
1086 inline
1088 SparseMatrixEZ<number>::locate (const size_type row,
1089  const size_type col)
1090 {
1091  Assert (row<m(), ExcIndexRange(row,0,m()));
1092  Assert (col<n(), ExcIndexRange(col,0,n()));
1093 
1094  const RowInfo &r = row_info[row];
1095  const size_type end = r.start + r.length;
1096  for (size_type i=r.start; i<end; ++i)
1097  {
1098  Entry *const entry = &data[i];
1099  if (entry->column == col)
1100  return entry;
1101  if (entry->column == Entry::invalid)
1102  return 0;
1103  }
1104  return 0;
1105 }
1106 
1107 
1108 
1109 template <typename number>
1110 inline
1111 const typename SparseMatrixEZ<number>::Entry *
1112 SparseMatrixEZ<number>::locate (const size_type row,
1113  const size_type col) const
1114 {
1115  SparseMatrixEZ<number> *t = const_cast<SparseMatrixEZ<number>*> (this);
1116  return t->locate(row,col);
1117 }
1118 
1119 
1120 template <typename number>
1121 inline
1124  const size_type col)
1125 {
1126  Assert (row<m(), ExcIndexRange(row,0,m()));
1127  Assert (col<n(), ExcIndexRange(col,0,n()));
1128 
1129  RowInfo &r = row_info[row];
1130  const size_type end = r.start + r.length;
1131 
1132  size_type i = r.start;
1133  // If diagonal exists and this
1134  // column is higher, start only
1135  // after diagonal.
1136  if (r.diagonal != RowInfo::invalid_diagonal && col >= row)
1137  i += r.diagonal;
1138  // Find position of entry
1139  while (i<end && data[i].column < col) ++i;
1140 
1141  // entry found
1142  if (i != end && data[i].column == col)
1143  return &data[i];
1144 
1145  // Now, we must insert the new
1146  // entry and move all successive
1147  // entries back.
1148 
1149  // If no more space is available
1150  // for this row, insert new
1151  // elements into the vector.
1152 //TODO:[GK] We should not extend this row if i<end
1153  if (row != row_info.size()-1)
1154  {
1155  if (end >= row_info[row+1].start)
1156  {
1157  // Failure if increment 0
1158  Assert(increment!=0,ExcEntryAllocationFailure(row,col));
1159 
1160  // Insert new entries
1161  data.insert(data.begin()+end, increment, Entry());
1162  // Update starts of
1163  // following rows
1164  for (size_type rn=row+1; rn<row_info.size(); ++rn)
1165  row_info[rn].start += increment;
1166  }
1167  }
1168  else
1169  {
1170  if (end >= data.size())
1171  {
1172  // Here, appending a block
1173  // does not increase
1174  // performance.
1175  data.push_back(Entry());
1176  }
1177  }
1178 
1179  Entry *entry = &data[i];
1180  // Save original entry
1181  Entry temp = *entry;
1182  // Insert new entry here to
1183  // make sure all entries
1184  // are ordered by column
1185  // index
1186  entry->column = col;
1187  entry->value = 0;
1188  // Update row_info
1189  ++r.length;
1190  if (col == row)
1191  r.diagonal = i - r.start;
1192  else if (col<row && r.diagonal!= RowInfo::invalid_diagonal)
1193  ++r.diagonal;
1194 
1195  if (i == end)
1196  return entry;
1197 
1198  // Move all entries in this
1199  // row up by one
1200  for (size_type j = i+1; j < end; ++j)
1201  {
1202  // There should be no invalid
1203  // entry below end
1204  Assert (data[j].column != Entry::invalid, ExcInternalError());
1205 
1206 //TODO[GK]: This could be done more efficiently by moving starting at the top rather than swapping starting at the bottom
1207  std::swap (data[j], temp);
1208  }
1209  Assert (data[end].column == Entry::invalid, ExcInternalError());
1210 
1211  data[end] = temp;
1212 
1213  return entry;
1214 }
1215 
1216 
1217 
1218 template <typename number>
1219 inline
1220 void SparseMatrixEZ<number>::set (const size_type i,
1221  const size_type j,
1222  const number value,
1223  const bool elide_zero_values)
1224 {
1225  AssertIsFinite(value);
1226 
1227  Assert (i<m(), ExcIndexRange(i,0,m()));
1228  Assert (j<n(), ExcIndexRange(j,0,n()));
1229 
1230  if (elide_zero_values && value == 0.)
1231  {
1232  Entry *entry = locate(i,j);
1233  if (entry != 0)
1234  entry->value = 0.;
1235  }
1236  else
1237  {
1238  Entry *entry = allocate(i,j);
1239  entry->value = value;
1240  }
1241 }
1242 
1243 
1244 
1245 template <typename number>
1246 inline
1247 void SparseMatrixEZ<number>::add (const size_type i,
1248  const size_type j,
1249  const number value)
1250 {
1251 
1252  AssertIsFinite(value);
1253 
1254  Assert (i<m(), ExcIndexRange(i,0,m()));
1255  Assert (j<n(), ExcIndexRange(j,0,n()));
1256 
1257  // ignore zero additions
1258  if (value == 0)
1259  return;
1260 
1261  Entry *entry = allocate(i,j);
1262  entry->value += value;
1263 }
1264 
1265 
1266 template <typename number>
1267 template <typename number2>
1268 void SparseMatrixEZ<number>::add (const std::vector<size_type> &indices,
1269  const FullMatrix<number2> &full_matrix,
1270  const bool elide_zero_values)
1271 {
1272 //TODO: This function can surely be made more efficient
1273  for (size_type i=0; i<indices.size(); ++i)
1274  for (size_type j=0; j<indices.size(); ++j)
1275  if ((full_matrix(i,j) != 0) || (elide_zero_values == false))
1276  add (indices[i], indices[j], full_matrix(i,j));
1277 }
1278 
1279 
1280 
1281 template <typename number>
1282 template <typename number2>
1283 void SparseMatrixEZ<number>::add (const std::vector<size_type> &row_indices,
1284  const std::vector<size_type> &col_indices,
1285  const FullMatrix<number2> &full_matrix,
1286  const bool elide_zero_values)
1287 {
1288 //TODO: This function can surely be made more efficient
1289  for (size_type i=0; i<row_indices.size(); ++i)
1290  for (size_type j=0; j<col_indices.size(); ++j)
1291  if ((full_matrix(i,j) != 0) || (elide_zero_values == false))
1292  add (row_indices[i], col_indices[j], full_matrix(i,j));
1293 }
1294 
1295 
1296 
1297 
1298 template <typename number>
1299 template <typename number2>
1300 void SparseMatrixEZ<number>::add (const size_type row,
1301  const std::vector<size_type> &col_indices,
1302  const std::vector<number2> &values,
1303  const bool elide_zero_values)
1304 {
1305 //TODO: This function can surely be made more efficient
1306  for (size_type j=0; j<col_indices.size(); ++j)
1307  if ((values[j] != 0) || (elide_zero_values == false))
1308  add (row, col_indices[j], values[j]);
1309 }
1310 
1311 
1312 
1313 template <typename number>
1314 template <typename number2>
1315 void SparseMatrixEZ<number>::add (const size_type row,
1316  const size_type n_cols,
1317  const size_type *col_indices,
1318  const number2 *values,
1319  const bool elide_zero_values,
1320  const bool /*col_indices_are_sorted*/)
1321 {
1322 //TODO: This function can surely be made more efficient
1323  for (size_type j=0; j<n_cols; ++j)
1324  if ((values[j] != 0) || (elide_zero_values == false))
1325  add (row, col_indices[j], values[j]);
1326 }
1327 
1328 
1329 
1330 
1331 template <typename number>
1332 inline
1333 number SparseMatrixEZ<number>::el (const size_type i,
1334  const size_type j) const
1335 {
1336  const Entry *entry = locate(i,j);
1337  if (entry)
1338  return entry->value;
1339  return 0.;
1340 }
1341 
1342 
1343 
1344 template <typename number>
1345 inline
1346 number SparseMatrixEZ<number>::operator() (const size_type i,
1347  const size_type j) const
1348 {
1349  const Entry *entry = locate(i,j);
1350  if (entry)
1351  return entry->value;
1352  Assert(false, ExcInvalidEntry(i,j));
1353  return 0.;
1354 }
1355 
1356 
1357 template <typename number>
1358 inline
1361 {
1362  const_iterator result(this, 0, 0);
1363  return result;
1364 }
1365 
1366 template <typename number>
1367 inline
1370 {
1371  return const_iterator(this, m(), 0);
1372 }
1373 
1374 template <typename number>
1375 inline
1377 SparseMatrixEZ<number>::begin (const size_type r) const
1378 {
1379  Assert (r<m(), ExcIndexRange(r,0,m()));
1380  const_iterator result (this, r, 0);
1381  return result;
1382 }
1383 
1384 template <typename number>
1385 inline
1387 SparseMatrixEZ<number>::end (const size_type r) const
1388 {
1389  Assert (r<m(), ExcIndexRange(r,0,m()));
1390  const_iterator result(this, r+1, 0);
1391  return result;
1392 }
1393 
1394 template<typename number>
1395 template <typename MatrixType>
1396 inline
1398 SparseMatrixEZ<number>::copy_from (const MatrixType &M, const bool elide_zero_values)
1399 {
1400  reinit(M.m(),
1401  M.n(),
1403  this->increment);
1404 
1405  // loop over the elements of the argument matrix row by row, as suggested
1406  // in the documentation of the sparse matrix iterator class, and
1407  // copy them into the current object
1408  for (size_type row = 0; row < M.m(); ++row)
1409  {
1410  const typename MatrixType::const_iterator end_row = M.end(row);
1411  for (typename MatrixType::const_iterator entry = M.begin(row);
1412  entry != end_row; ++entry)
1413  set(row, entry->column(), entry->value(), elide_zero_values);
1414  }
1415 
1416  return *this;
1417 }
1418 
1419 template<typename number>
1420 template <typename MatrixType>
1421 inline
1422 void
1423 SparseMatrixEZ<number>::add (const number factor,
1424  const MatrixType &M)
1425 {
1426  Assert (M.m() == m(), ExcDimensionMismatch(M.m(), m()));
1427  Assert (M.n() == n(), ExcDimensionMismatch(M.n(), n()));
1428 
1429  if (factor == 0.)
1430  return;
1431 
1432  // loop over the elements of the argument matrix row by row, as suggested
1433  // in the documentation of the sparse matrix iterator class, and
1434  // add them into the current object
1435  for (size_type row = 0; row < M.m(); ++row)
1436  {
1437  const typename MatrixType::const_iterator end_row = M.end(row);
1438  for (typename MatrixType::const_iterator entry = M.begin(row);
1439  entry != end_row; ++entry)
1440  if (entry->value() != 0)
1441  add(row, entry->column(), factor * entry->value());
1442  }
1443 }
1444 
1445 
1446 
1447 template<typename number>
1448 template <typename MatrixTypeA, typename MatrixTypeB>
1449 inline void
1451  const MatrixTypeB &B,
1452  const bool transpose)
1453 {
1454 // Compute the result
1455 // r_ij = \sum_kl b_ik b_jl a_kl
1456 
1457 // Assert (n() == B.m(), ExcDimensionMismatch(n(), B.m()));
1458 // Assert (m() == B.m(), ExcDimensionMismatch(m(), B.m()));
1459 // Assert (A.n() == B.n(), ExcDimensionMismatch(A.n(), B.n()));
1460 // Assert (A.m() == B.n(), ExcDimensionMismatch(A.m(), B.n()));
1461 
1462  // Somehow, we have to avoid making
1463  // this an operation of complexity
1464  // n^2. For the transpose case, we
1465  // can go through the non-zero
1466  // elements of A^-1 and use the
1467  // corresponding rows of B only.
1468  // For the non-transpose case, we
1469  // must find a trick.
1470  typename MatrixTypeB::const_iterator b1 = B.begin();
1471  const typename MatrixTypeB::const_iterator b_final = B.end();
1472  if (transpose)
1473  while (b1 != b_final)
1474  {
1475  const size_type i = b1->column();
1476  const size_type k = b1->row();
1477  typename MatrixTypeB::const_iterator b2 = B.begin();
1478  while (b2 != b_final)
1479  {
1480  const size_type j = b2->column();
1481  const size_type l = b2->row();
1482 
1483  const typename MatrixTypeA::value_type a = A.el(k,l);
1484 
1485  if (a != 0.)
1486  add (i, j, a * b1->value() * b2->value());
1487  ++b2;
1488  }
1489  ++b1;
1490  }
1491  else
1492  {
1493  // Determine minimal and
1494  // maximal row for a column in
1495  // advance.
1496 
1497  std::vector<size_type> minrow(B.n(), B.m());
1498  std::vector<size_type> maxrow(B.n(), 0);
1499  while (b1 != b_final)
1500  {
1501  const size_type r = b1->row();
1502  if (r < minrow[b1->column()])
1503  minrow[b1->column()] = r;
1504  if (r > maxrow[b1->column()])
1505  maxrow[b1->column()] = r;
1506  ++b1;
1507  }
1508 
1509  typename MatrixTypeA::const_iterator ai = A.begin();
1510  const typename MatrixTypeA::const_iterator ae = A.end();
1511 
1512  while (ai != ae)
1513  {
1514  const typename MatrixTypeA::value_type a = ai->value();
1515  // Don't do anything if
1516  // this entry is zero.
1517  if (a == 0.) continue;
1518 
1519  // Now, loop over all rows
1520  // having possibly a
1521  // nonzero entry in column
1522  // ai->row()
1523  b1 = B.begin(minrow[ai->row()]);
1524  const typename MatrixTypeB::const_iterator
1525  be1 = B.end(maxrow[ai->row()]);
1526  const typename MatrixTypeB::const_iterator
1527  be2 = B.end(maxrow[ai->column()]);
1528 
1529  while (b1 != be1)
1530  {
1531  const double b1v = b1->value();
1532  // We need the product
1533  // of both. If it is
1534  // zero, we can save
1535  // the work
1536  if (b1->column() == ai->row() && (b1v != 0.))
1537  {
1538  const size_type i = b1->row();
1539 
1540  typename MatrixTypeB::const_iterator
1541  b2 = B.begin(minrow[ai->column()]);
1542  while (b2 != be2)
1543  {
1544  if (b2->column() == ai->column())
1545  {
1546  const size_type j = b2->row();
1547  add (i, j, a * b1v * b2->value());
1548  }
1549  ++b2;
1550  }
1551  }
1552  ++b1;
1553  }
1554  ++ai;
1555  }
1556  }
1557 }
1558 
1559 
1560 template <typename number>
1561 template <class StreamType>
1562 inline
1563 void
1564 SparseMatrixEZ<number>::print_statistics(StreamType &out, bool full)
1565 {
1566  size_type used;
1567  size_type allocated;
1568  size_type reserved;
1569  std::vector<size_type> used_by_line;
1570 
1571  compute_statistics (used, allocated, reserved, used_by_line, full);
1572 
1573  out << "SparseMatrixEZ:used entries:" << used << std::endl
1574  << "SparseMatrixEZ:allocated entries:" << allocated << std::endl
1575  << "SparseMatrixEZ:reserved entries:" << reserved << std::endl;
1576 
1577  if (full)
1578  {
1579  for (size_type i=0; i< used_by_line.size(); ++i)
1580  if (used_by_line[i] != 0)
1581  out << "SparseMatrixEZ:entries\t" << i
1582  << "\trows\t" << used_by_line[i]
1583  << std::endl;
1584 
1585  }
1586 }
1587 
1588 
1589 DEAL_II_NAMESPACE_CLOSE
1590 
1591 #endif
1592 /*---------------------------- sparse_matrix.h ---------------------------*/
size_type get_row_length(const size_type row) const
const types::global_dof_index invalid_size_type
Definition: types.h:173
void Tvmult_add(Vector< somenumber > &dst, const Vector< somenumber > &src) const
void add(const size_type i, const size_type j, const number value)
DeclException2(ExcInvalidEntry, int, int,<< "The entry with index ("<< arg1<< ','<< arg2<< ") does not exist.")
unsigned int increment
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
number operator()(const size_type i, const size_type j) const
SparseMatrixEZ< number > & copy_from(const MatrixType &source, const bool elide_zero_values=true)
void set(const size_type i, const size_type j, const number value, const bool elide_zero_values=true)
void conjugate_add(const MatrixTypeA &A, const MatrixTypeB &B, const bool transpose=false)
size_type n() const
void block_read(std::istream &in)
bool operator<(const const_iterator &) const
void vmult_add(Vector< somenumber > &dst, const Vector< somenumber > &src) const
void vmult(Vector< somenumber > &dst, const Vector< somenumber > &src) const
static const size_type invalid
const Accessor & operator*() const
std::size_t memory_consumption() const
void threaded_matrix_norm_square(const Vector< somenumber > &v, const size_type begin_row, const size_type end_row, somenumber *partial_sum) const
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
DeclException0(ExcNoDiagonal)
bool operator==(const const_iterator &) const
void print(std::ostream &out) const
void precondition_SOR(Vector< somenumber > &dst, const Vector< somenumber > &src, const number om=1.) const
SparseMatrixEZ< number > & operator=(const SparseMatrixEZ< number > &)
Accessor(const SparseMatrixEZ< number > *matrix, const size_type row, const unsigned short index)
unsigned int global_dof_index
Definition: types.h:88
#define Assert(cond, exc)
Definition: exceptions.h:294
void reinit(const size_type n_rows, const size_type n_columns, size_type default_row_length=0, unsigned int default_increment=1, size_type reserve=0)
bool operator!=(const const_iterator &) const
const_iterator(const SparseMatrixEZ< number > *matrix, const size_type row, const unsigned short index)
const SparseMatrixEZ< number > * matrix
std::vector< Entry > data
Entry * allocate(const size_type row, const size_type col)
void print_statistics(StreamType &s, bool full=false)
RowInfo(size_type start=Entry::invalid)
void block_write(std::ostream &out) const
types::global_dof_index size_type
const Accessor * operator->() const
void precondition_TSOR(Vector< somenumber > &dst, const Vector< somenumber > &src, const number om=1.) const
number el(const size_type i, const size_type j) const
const Entry * locate(const size_type row, const size_type col) const
const_iterator begin() const
void precondition_Jacobi(Vector< somenumber > &dst, const Vector< somenumber > &src, const number omega=1.) const
void threaded_vmult(Vector< somenumber > &dst, const Vector< somenumber > &src, const size_type begin_row, const size_type end_row) const
void Tvmult(Vector< somenumber > &dst, const Vector< somenumber > &src) const
bool empty() const
static const unsigned short invalid_diagonal
number l2_norm() 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
const_iterator end() const
#define AssertIsFinite(number)
Definition: exceptions.h:1096
unsigned int saved_default_row_length
size_type m() const
std::vector< RowInfo > row_info
size_type n_nonzero_elements() 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