Reference documentation for deal.II version 8.5.1
block_matrix_base.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2017 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__block_matrix_base_h
17 #define dealii__block_matrix_base_h
18 
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/base/table.h>
22 #include <deal.II/base/thread_management.h>
23 #include <deal.II/base/utilities.h>
24 #include <deal.II/base/smartpointer.h>
25 #include <deal.II/base/memory_consumption.h>
26 #include <deal.II/lac/block_indices.h>
27 #include <deal.II/lac/exceptions.h>
28 #include <deal.II/lac/full_matrix.h>
29 #include <deal.II/lac/matrix_iterator.h>
30 #include <deal.II/lac/vector.h>
31 
32 #include <cmath>
33 
34 DEAL_II_NAMESPACE_OPEN
35 
36 
37 template <typename> class MatrixIterator;
38 
39 
40 
51 {
56  template <class BlockMatrixType>
58  {
59  public:
64 
68  typedef typename BlockMatrixType::value_type value_type;
69 
73  AccessorBase ();
74 
78  unsigned int block_row() const;
79 
83  unsigned int block_column() const;
84 
85  protected:
89  unsigned int row_block;
90 
94  unsigned int col_block;
95 
99  template <typename>
100  friend class MatrixIterator;
101  };
102 
103 
104 
108  template <class BlockMatrixType, bool Constness>
109  class Accessor;
110 
111 
115  template <class BlockMatrixType>
116  class Accessor<BlockMatrixType, false>
117  :
118  public AccessorBase<BlockMatrixType>
119  {
120  public:
125 
129  typedef BlockMatrixType MatrixType;
130 
134  typedef typename BlockMatrixType::value_type value_type;
135 
144  Accessor (BlockMatrixType *m,
145  const size_type row,
146  const size_type col);
147 
151  size_type row() const;
152 
156  size_type column() const;
157 
161  value_type value() const;
162 
166  void set_value(value_type newval) const;
167 
168  protected:
172  BlockMatrixType *matrix;
173 
177  typename BlockMatrixType::BlockType::iterator base_iterator;
178 
182  void advance ();
183 
187  bool operator == (const Accessor &a) const;
188 
189  template <typename> friend class MatrixIterator;
190  friend class Accessor<BlockMatrixType, true>;
191  };
192 
197  template <class BlockMatrixType>
198  class Accessor<BlockMatrixType, true>
199  :
200  public AccessorBase<BlockMatrixType>
201  {
202  public:
207 
211  typedef const BlockMatrixType MatrixType;
212 
216  typedef typename BlockMatrixType::value_type value_type;
217 
226  Accessor (const BlockMatrixType *m,
227  const size_type row,
228  const size_type col);
229 
234 
238  size_type row() const;
239 
243  size_type column() const;
244 
248  value_type value() const;
249  protected:
253  const BlockMatrixType *matrix;
254 
258  typename BlockMatrixType::BlockType::const_iterator base_iterator;
259 
263  void advance ();
264 
268  bool operator == (const Accessor &a) const;
269 
273  template <typename>
274  friend class ::MatrixIterator;
275  };
276 }
277 
278 
279 
340 template <typename MatrixType>
342 {
343 public:
347  typedef MatrixType BlockType;
348 
354  typedef value_type *pointer;
355  typedef const value_type *const_pointer;
356  typedef value_type &reference;
357  typedef const value_type &const_reference;
358  typedef types::global_dof_index size_type;
359 
360  typedef
362  iterator;
363 
364  typedef
367 
368 
372  BlockMatrixBase ();
373 
377  ~BlockMatrixBase ();
378 
395  template <class BlockMatrixType>
397  copy_from (const BlockMatrixType &source);
398 
402  BlockType &
403  block (const unsigned int row,
404  const unsigned int column);
405 
406 
411  const BlockType &
412  block (const unsigned int row,
413  const unsigned int column) const;
414 
419  size_type m () const;
420 
425  size_type n () const;
426 
427 
432  unsigned int n_block_rows () const;
433 
438  unsigned int n_block_cols () const;
439 
445  void set (const size_type i,
446  const size_type j,
447  const value_type value);
448 
464  template <typename number>
465  void set (const std::vector<size_type> &indices,
466  const FullMatrix<number> &full_matrix,
467  const bool elide_zero_values = false);
468 
474  template <typename number>
475  void set (const std::vector<size_type> &row_indices,
476  const std::vector<size_type> &col_indices,
477  const FullMatrix<number> &full_matrix,
478  const bool elide_zero_values = false);
479 
490  template <typename number>
491  void set (const size_type row,
492  const std::vector<size_type> &col_indices,
493  const std::vector<number> &values,
494  const bool elide_zero_values = false);
495 
505  template <typename number>
506  void set (const size_type row,
507  const size_type n_cols,
508  const size_type *col_indices,
509  const number *values,
510  const bool elide_zero_values = false);
511 
517  void add (const size_type i,
518  const size_type j,
519  const value_type value);
520 
535  template <typename number>
536  void add (const std::vector<size_type> &indices,
537  const FullMatrix<number> &full_matrix,
538  const bool elide_zero_values = true);
539 
545  template <typename number>
546  void add (const std::vector<size_type> &row_indices,
547  const std::vector<size_type> &col_indices,
548  const FullMatrix<number> &full_matrix,
549  const bool elide_zero_values = true);
550 
560  template <typename number>
561  void add (const size_type row,
562  const std::vector<size_type> &col_indices,
563  const std::vector<number> &values,
564  const bool elide_zero_values = true);
565 
575  template <typename number>
576  void add (const size_type row,
577  const size_type n_cols,
578  const size_type *col_indices,
579  const number *values,
580  const bool elide_zero_values = true,
581  const bool col_indices_are_sorted = false);
582 
594  void add (const value_type factor,
595  const BlockMatrixBase<MatrixType> &matrix);
596 
603  value_type operator () (const size_type i,
604  const size_type j) const;
605 
614  value_type el (const size_type i,
615  const size_type j) const;
616 
627  value_type diag_element (const size_type i) const;
628 
637  void compress (::VectorOperation::values operation);
638 
642  BlockMatrixBase &operator *= (const value_type factor);
643 
647  BlockMatrixBase &operator /= (const value_type factor);
648 
653  template <class BlockVectorType>
654  void vmult_add (BlockVectorType &dst,
655  const BlockVectorType &src) const;
656 
662  template <class BlockVectorType>
663  void Tvmult_add (BlockVectorType &dst,
664  const BlockVectorType &src) const;
665 
678  template <class BlockVectorType>
679  value_type
680  matrix_norm_square (const BlockVectorType &v) const;
681 
685  template <class BlockVectorType>
686  value_type
687  matrix_scalar_product (const BlockVectorType &u,
688  const BlockVectorType &v) const;
689 
693  template <class BlockVectorType>
694  value_type residual (BlockVectorType &dst,
695  const BlockVectorType &x,
696  const BlockVectorType &b) const;
697 
704  void print (std::ostream &out,
705  const bool alternative_output = false) const;
706 
710  iterator begin ();
711 
715  iterator end ();
716 
720  iterator begin (const size_type r);
721 
725  iterator end (const size_type r);
729  const_iterator begin () const;
730 
734  const_iterator end () const;
735 
739  const_iterator begin (const size_type r) const;
740 
744  const_iterator end (const size_type r) const;
745 
749  const BlockIndices &get_row_indices () const;
750 
754  const BlockIndices &get_column_indices () const;
755 
761  std::size_t memory_consumption () const;
762 
772  int, int, int, int,
773  << "The blocks [" << arg1 << ',' << arg2 << "] and ["
774  << arg3 << ',' << arg4 << "] have differing row numbers.");
779  int, int, int, int,
780  << "The blocks [" << arg1 << ',' << arg2 << "] and ["
781  << arg3 << ',' << arg4 << "] have differing column numbers.");
783 protected:
796  void clear ();
797 
802  BlockIndices column_block_indices;
803 
808 
827  void collect_sizes ();
828 
839  template <class BlockVectorType>
840  void vmult_block_block (BlockVectorType &dst,
841  const BlockVectorType &src) const;
842 
853  template <class BlockVectorType,
854  class VectorType>
855  void vmult_block_nonblock (BlockVectorType &dst,
856  const VectorType &src) const;
857 
868  template <class BlockVectorType,
869  class VectorType>
870  void vmult_nonblock_block (VectorType &dst,
871  const BlockVectorType &src) const;
872 
883  template <class VectorType>
884  void vmult_nonblock_nonblock (VectorType &dst,
885  const VectorType &src) const;
886 
898  template <class BlockVectorType>
899  void Tvmult_block_block (BlockVectorType &dst,
900  const BlockVectorType &src) const;
901 
912  template <class BlockVectorType,
913  class VectorType>
914  void Tvmult_block_nonblock (BlockVectorType &dst,
915  const VectorType &src) const;
916 
927  template <class BlockVectorType,
928  class VectorType>
929  void Tvmult_nonblock_block (VectorType &dst,
930  const BlockVectorType &src) const;
931 
942  template <class VectorType>
943  void Tvmult_nonblock_nonblock (VectorType &dst,
944  const VectorType &src) const;
945 
946 
947 protected:
948 
955  void prepare_add_operation();
956 
961  void prepare_set_operation();
962 
963 
964 private:
965 
975  {
980  std::vector<size_type> counter_within_block;
981 
986  std::vector<std::vector<size_type> > column_indices;
987 
992  std::vector<std::vector<value_type> > column_values;
993 
999 
1010  {
1011  return *this;
1012  }
1013  };
1014 
1021  TemporaryData temporary_data;
1022 
1027  template <typename, bool>
1029 
1030  template <typename>
1031  friend class MatrixIterator;
1032 };
1033 
1034 
1037 #ifndef DOXYGEN
1038 /* ------------------------- Template functions ---------------------- */
1039 
1040 
1041 namespace BlockMatrixIterators
1042 {
1043  template <class BlockMatrixType>
1044  inline
1046  :
1047  row_block(0),
1048  col_block(0)
1049  {}
1050 
1051 
1052  template <class BlockMatrixType>
1053  inline
1054  unsigned int
1055  AccessorBase<BlockMatrixType>::block_row() const
1056  {
1057  Assert (row_block != numbers::invalid_unsigned_int,
1058  ExcIteratorPastEnd());
1059 
1060  return row_block;
1061  }
1062 
1063 
1064  template <class BlockMatrixType>
1065  inline
1066  unsigned int
1067  AccessorBase<BlockMatrixType>::block_column() const
1068  {
1069  Assert (col_block != numbers::invalid_unsigned_int,
1070  ExcIteratorPastEnd());
1071 
1072  return col_block;
1073  }
1074 
1075 
1076  template <class BlockMatrixType>
1077  inline
1078  Accessor<BlockMatrixType, true>::Accessor (
1079  const BlockMatrixType *matrix,
1080  const size_type row,
1081  const size_type col)
1082  :
1083  matrix(matrix),
1084  base_iterator(matrix->block(0,0).begin())
1085  {
1086  (void)col;
1087  Assert(col==0, ExcNotImplemented());
1088 
1089  // check if this is a regular row or
1090  // the end of the matrix
1091  if (row < matrix->m())
1092  {
1093  const std::pair<unsigned int,size_type> indices
1094  = matrix->row_block_indices.global_to_local(row);
1095 
1096  // find the first block that does
1097  // have an entry in this row
1098  for (unsigned int bc=0; bc<matrix->n_block_cols(); ++bc)
1099  {
1100  base_iterator
1101  = matrix->block(indices.first, bc).begin(indices.second);
1102  if (base_iterator !=
1103  matrix->block(indices.first, bc).end(indices.second))
1104  {
1105  this->row_block = indices.first;
1106  this->col_block = bc;
1107  return;
1108  }
1109  }
1110 
1111  // hm, there is no block that has
1112  // an entry in this column. we need
1113  // to take the next entry then,
1114  // which may be the first entry of
1115  // the next row, or recursively the
1116  // next row, or so on
1117  *this = Accessor (matrix, row+1, 0);
1118  }
1119  else
1120  {
1121  // we were asked to create the end
1122  // iterator for this matrix
1123  this->row_block = numbers::invalid_unsigned_int;
1124  this->col_block = numbers::invalid_unsigned_int;
1125  }
1126  }
1127 
1128 
1129 // template <class BlockMatrixType>
1130 // inline
1131 // Accessor<BlockMatrixType, true>::Accessor (const Accessor<BlockMatrixType, true>& other)
1132 // :
1133 // matrix(other.matrix),
1134 // base_iterator(other.base_iterator)
1135 // {
1136 // this->row_block = other.row_block;
1137 // this->col_block = other.col_block;
1138 // }
1139 
1140 
1141  template <class BlockMatrixType>
1142  inline
1143  Accessor<BlockMatrixType, true>::Accessor (const Accessor<BlockMatrixType, false> &other)
1144  :
1145  matrix(other.matrix),
1146  base_iterator(other.base_iterator)
1147  {
1148  this->row_block = other.row_block;
1149  this->col_block = other.col_block;
1150  }
1151 
1152 
1153  template <class BlockMatrixType>
1154  inline
1155  typename Accessor<BlockMatrixType, true>::size_type
1156  Accessor<BlockMatrixType, true>::row() const
1157  {
1158  Assert (this->row_block != numbers::invalid_unsigned_int,
1159  ExcIteratorPastEnd());
1160 
1161  return (matrix->row_block_indices.local_to_global(this->row_block, 0) +
1162  base_iterator->row());
1163  }
1164 
1165 
1166  template <class BlockMatrixType>
1167  inline
1168  typename Accessor<BlockMatrixType, true>::size_type
1169  Accessor<BlockMatrixType, true>::column() const
1170  {
1171  Assert (this->col_block != numbers::invalid_unsigned_int,
1172  ExcIteratorPastEnd());
1173 
1174  return (matrix->column_block_indices.local_to_global(this->col_block,0) +
1175  base_iterator->column());
1176  }
1177 
1178 
1179  template <class BlockMatrixType>
1180  inline
1181  typename Accessor<BlockMatrixType, true>::value_type
1182  Accessor<BlockMatrixType, true>::value () const
1183  {
1184  Assert (this->row_block != numbers::invalid_unsigned_int,
1185  ExcIteratorPastEnd());
1186  Assert (this->col_block != numbers::invalid_unsigned_int,
1187  ExcIteratorPastEnd());
1188 
1189  return base_iterator->value();
1190  }
1191 
1192 
1193 
1194  template <class BlockMatrixType>
1195  inline
1196  void
1197  Accessor<BlockMatrixType, true>::advance ()
1198  {
1199  Assert (this->row_block != numbers::invalid_unsigned_int,
1200  ExcIteratorPastEnd());
1201  Assert (this->col_block != numbers::invalid_unsigned_int,
1202  ExcIteratorPastEnd());
1203 
1204  // Remember current row inside block
1205  size_type local_row = base_iterator->row();
1206 
1207  // Advance one element inside the
1208  // current block
1209  ++base_iterator;
1210 
1211  // while we hit the end of the row of a
1212  // block (which may happen multiple
1213  // times if rows inside a block are
1214  // empty), we have to jump to the next
1215  // block and take the
1216  while (base_iterator ==
1217  matrix->block(this->row_block, this->col_block).end(local_row))
1218  {
1219  // jump to next block in this block
1220  // row, if possible, otherwise go
1221  // to next row
1222  if (this->col_block < matrix->n_block_cols()-1)
1223  {
1224  ++this->col_block;
1225  base_iterator
1226  = matrix->block(this->row_block, this->col_block).begin(local_row);
1227  }
1228  else
1229  {
1230  // jump back to next row in
1231  // first block column
1232  this->col_block = 0;
1233  ++local_row;
1234 
1235  // see if this has brought us
1236  // past the number of rows in
1237  // this block. if so see
1238  // whether we've just fallen
1239  // off the end of the whole
1240  // matrix
1241  if (local_row == matrix->block(this->row_block, this->col_block).m())
1242  {
1243  local_row = 0;
1244  ++this->row_block;
1245  if (this->row_block == matrix->n_block_rows())
1246  {
1247  this->row_block = numbers::invalid_unsigned_int;
1248  this->col_block = numbers::invalid_unsigned_int;
1249  return;
1250  }
1251  }
1252 
1253  base_iterator
1254  = matrix->block(this->row_block, this->col_block).begin(local_row);
1255  }
1256  }
1257  }
1258 
1259 
1260  template <class BlockMatrixType>
1261  inline
1262  bool
1263  Accessor<BlockMatrixType, true>::operator == (const Accessor &a) const
1264  {
1265  if (matrix != a.matrix)
1266  return false;
1267 
1268  if (this->row_block == a.row_block
1269  && this->col_block == a.col_block)
1270  // end iterators do not necessarily
1271  // have to have the same
1272  // base_iterator representation, but
1273  // valid iterators have to
1274  return (((this->row_block == numbers::invalid_unsigned_int)
1275  &&
1276  (this->col_block == numbers::invalid_unsigned_int))
1277  ||
1278  (base_iterator == a.base_iterator));
1279 
1280  return false;
1281  }
1282 
1283 //----------------------------------------------------------------------//
1284 
1285 
1286  template <class BlockMatrixType>
1287  inline
1288  Accessor<BlockMatrixType, false>::Accessor (
1289  BlockMatrixType *matrix,
1290  const size_type row,
1291  const size_type col)
1292  :
1293  matrix(matrix),
1294  base_iterator(matrix->block(0,0).begin())
1295  {
1296  (void)col;
1297  Assert(col==0, ExcNotImplemented());
1298  // check if this is a regular row or
1299  // the end of the matrix
1300  if (row < matrix->m())
1301  {
1302  const std::pair<unsigned int,size_type> indices
1303  = matrix->row_block_indices.global_to_local(row);
1304 
1305  // find the first block that does
1306  // have an entry in this row
1307  for (size_type bc=0; bc<matrix->n_block_cols(); ++bc)
1308  {
1309  base_iterator
1310  = matrix->block(indices.first, bc).begin(indices.second);
1311  if (base_iterator !=
1312  matrix->block(indices.first, bc).end(indices.second))
1313  {
1314  this->row_block = indices.first;
1315  this->col_block = bc;
1316  return;
1317  }
1318  }
1319 
1320  // hm, there is no block that has
1321  // an entry in this column. we need
1322  // to take the next entry then,
1323  // which may be the first entry of
1324  // the next row, or recursively the
1325  // next row, or so on
1326  *this = Accessor (matrix, row+1, 0);
1327  }
1328  else
1329  {
1330  // we were asked to create the end
1331  // iterator for this matrix
1332  this->row_block = numbers::invalid_size_type;
1333  this->col_block = numbers::invalid_size_type;
1334  }
1335  }
1336 
1337 
1338  template <class BlockMatrixType>
1339  inline
1340  typename Accessor<BlockMatrixType, false>::size_type
1341  Accessor<BlockMatrixType, false>::row() const
1342  {
1343  Assert (this->row_block != numbers::invalid_size_type,
1344  ExcIteratorPastEnd());
1345 
1346  return (matrix->row_block_indices.local_to_global(this->row_block, 0) +
1347  base_iterator->row());
1348  }
1349 
1350 
1351  template <class BlockMatrixType>
1352  inline
1353  typename Accessor<BlockMatrixType, false>::size_type
1354  Accessor<BlockMatrixType, false>::column() const
1355  {
1356  Assert (this->col_block != numbers::invalid_size_type,
1357  ExcIteratorPastEnd());
1358 
1359  return (matrix->column_block_indices.local_to_global(this->col_block,0) +
1360  base_iterator->column());
1361  }
1362 
1363 
1364  template <class BlockMatrixType>
1365  inline
1366  typename Accessor<BlockMatrixType, false>::value_type
1367  Accessor<BlockMatrixType, false>::value () const
1368  {
1369  Assert (this->row_block != numbers::invalid_size_type,
1370  ExcIteratorPastEnd());
1371  Assert (this->col_block != numbers::invalid_size_type,
1372  ExcIteratorPastEnd());
1373 
1374  return base_iterator->value();
1375  }
1376 
1377 
1378 
1379  template <class BlockMatrixType>
1380  inline
1381  void
1382  Accessor<BlockMatrixType, false>::set_value (typename Accessor<BlockMatrixType, false>::value_type newval) const
1383  {
1384  Assert (this->row_block != numbers::invalid_size_type,
1385  ExcIteratorPastEnd());
1386  Assert (this->col_block != numbers::invalid_size_type,
1387  ExcIteratorPastEnd());
1388 
1389  base_iterator->value() = newval;
1390  }
1391 
1392 
1393 
1394  template <class BlockMatrixType>
1395  inline
1396  void
1397  Accessor<BlockMatrixType, false>::advance ()
1398  {
1399  Assert (this->row_block != numbers::invalid_size_type,
1400  ExcIteratorPastEnd());
1401  Assert (this->col_block != numbers::invalid_size_type,
1402  ExcIteratorPastEnd());
1403 
1404  // Remember current row inside block
1405  size_type local_row = base_iterator->row();
1406 
1407  // Advance one element inside the
1408  // current block
1409  ++base_iterator;
1410 
1411  // while we hit the end of the row of a
1412  // block (which may happen multiple
1413  // times if rows inside a block are
1414  // empty), we have to jump to the next
1415  // block and take the
1416  while (base_iterator ==
1417  matrix->block(this->row_block, this->col_block).end(local_row))
1418  {
1419  // jump to next block in this block
1420  // row, if possible, otherwise go
1421  // to next row
1422  if (this->col_block < matrix->n_block_cols()-1)
1423  {
1424  ++this->col_block;
1425  base_iterator
1426  = matrix->block(this->row_block, this->col_block).begin(local_row);
1427  }
1428  else
1429  {
1430  // jump back to next row in
1431  // first block column
1432  this->col_block = 0;
1433  ++local_row;
1434 
1435  // see if this has brought us
1436  // past the number of rows in
1437  // this block. if so see
1438  // whether we've just fallen
1439  // off the end of the whole
1440  // matrix
1441  if (local_row == matrix->block(this->row_block, this->col_block).m())
1442  {
1443  local_row = 0;
1444  ++this->row_block;
1445  if (this->row_block == matrix->n_block_rows())
1446  {
1447  this->row_block = numbers::invalid_size_type;
1448  this->col_block = numbers::invalid_size_type;
1449  return;
1450  }
1451  }
1452 
1453  base_iterator
1454  = matrix->block(this->row_block, this->col_block).begin(local_row);
1455  }
1456  }
1457  }
1458 
1459 
1460 
1461  template <class BlockMatrixType>
1462  inline
1463  bool
1464  Accessor<BlockMatrixType, false>::operator == (const Accessor &a) const
1465  {
1466  if (matrix != a.matrix)
1467  return false;
1468 
1469  if (this->row_block == a.row_block
1470  && this->col_block == a.col_block)
1471  // end iterators do not necessarily
1472  // have to have the same
1473  // base_iterator representation, but
1474  // valid iterators have to
1475  return (((this->row_block == numbers::invalid_size_type)
1476  &&
1477  (this->col_block == numbers::invalid_size_type))
1478  ||
1479  (base_iterator == a.base_iterator));
1480 
1481  return false;
1482  }
1483 }
1484 
1485 
1486 //---------------------------------------------------------------------------
1487 
1488 
1489 template <typename MatrixType>
1490 inline
1492 {}
1493 
1494 template <typename MatrixType>
1495 inline
1497 {
1498  try
1499  {
1500  clear ();
1501  }
1502  catch (...)
1503  {}
1504 }
1505 
1506 
1507 template <class MatrixType>
1508 template <class BlockMatrixType>
1509 inline
1512 copy_from (const BlockMatrixType &source)
1513 {
1514  for (unsigned int r=0; r<n_block_rows(); ++r)
1515  for (unsigned int c=0; c<n_block_cols(); ++c)
1516  block(r,c).copy_from (source.block(r,c));
1517 
1518  return *this;
1519 }
1520 
1521 
1522 template <class MatrixType>
1523 std::size_t
1525 {
1526  std::size_t mem =
1527  MemoryConsumption::memory_consumption(row_block_indices)+
1528  MemoryConsumption::memory_consumption(column_block_indices)+
1530  MemoryConsumption::memory_consumption(temporary_data.counter_within_block)+
1531  MemoryConsumption::memory_consumption(temporary_data.column_indices)+
1532  MemoryConsumption::memory_consumption(temporary_data.column_values)+
1533  sizeof(temporary_data.mutex);
1534 
1535  for (unsigned int r=0; r<n_block_rows(); ++r)
1536  for (unsigned int c=0; c<n_block_cols(); ++c)
1537  {
1538  MatrixType *p = this->sub_objects[r][c];
1540  }
1541 
1542  return mem;
1543 }
1544 
1545 
1546 
1547 template <class MatrixType>
1548 inline
1549 void
1551 {
1552  for (unsigned int r=0; r<n_block_rows(); ++r)
1553  for (unsigned int c=0; c<n_block_cols(); ++c)
1554  {
1555  MatrixType *p = this->sub_objects[r][c];
1556  this->sub_objects[r][c] = 0;
1557  delete p;
1558  }
1559  sub_objects.reinit (0,0);
1560 
1561  // reset block indices to empty
1562  row_block_indices = column_block_indices = BlockIndices ();
1563 }
1564 
1565 
1566 
1567 template <class MatrixType>
1568 inline
1570 BlockMatrixBase<MatrixType>::block (const unsigned int row,
1571  const unsigned int column)
1572 {
1573  Assert (row<n_block_rows(),
1574  ExcIndexRange (row, 0, n_block_rows()));
1575  Assert (column<n_block_cols(),
1576  ExcIndexRange (column, 0, n_block_cols()));
1577 
1578  return *sub_objects[row][column];
1579 }
1580 
1581 
1582 
1583 template <class MatrixType>
1584 inline
1586 BlockMatrixBase<MatrixType>::block (const unsigned int row,
1587  const unsigned int column) const
1588 {
1589  Assert (row<n_block_rows(),
1590  ExcIndexRange (row, 0, n_block_rows()));
1591  Assert (column<n_block_cols(),
1592  ExcIndexRange (column, 0, n_block_cols()));
1593 
1594  return *sub_objects[row][column];
1595 }
1596 
1597 
1598 template <class MatrixType>
1599 inline
1600 typename BlockMatrixBase<MatrixType>::size_type
1602 {
1603  return row_block_indices.total_size();
1604 }
1605 
1606 
1607 
1608 template <class MatrixType>
1609 inline
1610 typename BlockMatrixBase<MatrixType>::size_type
1612 {
1613  return column_block_indices.total_size();
1614 }
1615 
1616 
1617 
1618 template <class MatrixType>
1619 inline
1620 unsigned int
1622 {
1623  return column_block_indices.size();
1624 }
1625 
1626 
1627 
1628 template <class MatrixType>
1629 inline
1630 unsigned int
1632 {
1633  return row_block_indices.size();
1634 }
1635 
1636 
1637 
1638 // Write the single set manually,
1639 // since the other function has a lot
1640 // of overhead in that case.
1641 template <class MatrixType>
1642 inline
1643 void
1644 BlockMatrixBase<MatrixType>::set (const size_type i,
1645  const size_type j,
1646  const value_type value)
1647 {
1648  prepare_set_operation();
1649 
1650  AssertIsFinite(value);
1651 
1652  const std::pair<unsigned int,size_type>
1653  row_index = row_block_indices.global_to_local (i),
1654  col_index = column_block_indices.global_to_local (j);
1655  block(row_index.first,col_index.first).set (row_index.second,
1656  col_index.second,
1657  value);
1658 }
1659 
1660 
1661 
1662 template <class MatrixType>
1663 template <typename number>
1664 inline
1665 void
1666 BlockMatrixBase<MatrixType>::set (const std::vector<size_type> &row_indices,
1667  const std::vector<size_type> &col_indices,
1668  const FullMatrix<number> &values,
1669  const bool elide_zero_values)
1670 {
1671  Assert (row_indices.size() == values.m(),
1672  ExcDimensionMismatch(row_indices.size(), values.m()));
1673  Assert (col_indices.size() == values.n(),
1674  ExcDimensionMismatch(col_indices.size(), values.n()));
1675 
1676  for (size_type i=0; i<row_indices.size(); ++i)
1677  set (row_indices[i], col_indices.size(), &col_indices[0], &values(i,0),
1678  elide_zero_values);
1679 }
1680 
1681 
1682 
1683 template <class MatrixType>
1684 template <typename number>
1685 inline
1686 void
1687 BlockMatrixBase<MatrixType>::set (const std::vector<size_type> &indices,
1688  const FullMatrix<number> &values,
1689  const bool elide_zero_values)
1690 {
1691  Assert (indices.size() == values.m(),
1692  ExcDimensionMismatch(indices.size(), values.m()));
1693  Assert (values.n() == values.m(), ExcNotQuadratic());
1694 
1695  for (size_type i=0; i<indices.size(); ++i)
1696  set (indices[i], indices.size(), &indices[0], &values(i,0),
1697  elide_zero_values);
1698 }
1699 
1700 
1701 
1702 template <class MatrixType>
1703 template <typename number>
1704 inline
1705 void
1706 BlockMatrixBase<MatrixType>::set (const size_type row,
1707  const std::vector<size_type> &col_indices,
1708  const std::vector<number> &values,
1709  const bool elide_zero_values)
1710 {
1711  Assert (col_indices.size() == values.size(),
1712  ExcDimensionMismatch(col_indices.size(), values.size()));
1713 
1714  set (row, col_indices.size(), &col_indices[0], &values[0],
1715  elide_zero_values);
1716 }
1717 
1718 
1719 
1720 // This is a very messy function, since
1721 // we need to calculate to each position
1722 // the location in the global array.
1723 template <class MatrixType>
1724 template <typename number>
1725 inline
1726 void
1727 BlockMatrixBase<MatrixType>::set (const size_type row,
1728  const size_type n_cols,
1729  const size_type *col_indices,
1730  const number *values,
1731  const bool elide_zero_values)
1732 {
1733  prepare_set_operation();
1734 
1735  // lock access to the temporary data structure to
1736  // allow multiple threads to call this function concurrently
1737  Threads::Mutex::ScopedLock lock (temporary_data.mutex);
1738 
1739  // Resize scratch arrays
1740  if (temporary_data.column_indices.size() < this->n_block_cols())
1741  {
1742  temporary_data.column_indices.resize (this->n_block_cols());
1743  temporary_data.column_values.resize (this->n_block_cols());
1744  temporary_data.counter_within_block.resize (this->n_block_cols());
1745  }
1746 
1747  // Resize sub-arrays to n_cols. This
1748  // is a bit wasteful, but we resize
1749  // only a few times (then the maximum
1750  // row length won't increase that
1751  // much any more). At least we know
1752  // that all arrays are going to be of
1753  // the same size, so we can check
1754  // whether the size of one is large
1755  // enough before actually going
1756  // through all of them.
1757  if (temporary_data.column_indices[0].size() < n_cols)
1758  {
1759  for (unsigned int i=0; i<this->n_block_cols(); ++i)
1760  {
1761  temporary_data.column_indices[i].resize(n_cols);
1762  temporary_data.column_values[i].resize(n_cols);
1763  }
1764  }
1765 
1766  // Reset the number of added elements
1767  // in each block to zero.
1768  for (unsigned int i=0; i<this->n_block_cols(); ++i)
1769  temporary_data.counter_within_block[i] = 0;
1770 
1771  // Go through the column indices to
1772  // find out which portions of the
1773  // values should be set in which
1774  // block of the matrix. We need to
1775  // touch all the data, since we can't
1776  // be sure that the data of one block
1777  // is stored contiguously (in fact,
1778  // indices will be intermixed when it
1779  // comes from an element matrix).
1780  for (size_type j=0; j<n_cols; ++j)
1781  {
1782  number value = values[j];
1783 
1784  if (value == number() && elide_zero_values == true)
1785  continue;
1786 
1787  const std::pair<unsigned int, size_type>
1788  col_index = this->column_block_indices.global_to_local(col_indices[j]);
1789 
1790  const size_type local_index = temporary_data.counter_within_block[col_index.first]++;
1791 
1792  temporary_data.column_indices[col_index.first][local_index] = col_index.second;
1793  temporary_data.column_values[col_index.first][local_index] = value;
1794  }
1795 
1796 #ifdef DEBUG
1797  // If in debug mode, do a check whether
1798  // the right length has been obtained.
1799  size_type length = 0;
1800  for (unsigned int i=0; i<this->n_block_cols(); ++i)
1801  length += temporary_data.counter_within_block[i];
1802  Assert (length <= n_cols, ExcInternalError());
1803 #endif
1804 
1805  // Now we found out about where the
1806  // individual columns should start and
1807  // where we should start reading out
1808  // data. Now let's write the data into
1809  // the individual blocks!
1810  const std::pair<unsigned int,size_type>
1811  row_index = this->row_block_indices.global_to_local (row);
1812  for (unsigned int block_col=0; block_col<n_block_cols(); ++block_col)
1813  {
1814  if (temporary_data.counter_within_block[block_col] == 0)
1815  continue;
1816 
1817  block(row_index.first, block_col).set
1818  (row_index.second,
1819  temporary_data.counter_within_block[block_col],
1820  &temporary_data.column_indices[block_col][0],
1821  &temporary_data.column_values[block_col][0],
1822  false);
1823  }
1824 }
1825 
1826 
1827 
1828 template <class MatrixType>
1829 inline
1830 void
1831 BlockMatrixBase<MatrixType>::add (const size_type i,
1832  const size_type j,
1833  const value_type value)
1834 {
1835 
1836  AssertIsFinite(value);
1837 
1838  prepare_add_operation();
1839 
1840  // save some cycles for zero additions, but
1841  // only if it is safe for the matrix we are
1842  // working with
1843  typedef typename MatrixType::Traits MatrixTraits;
1844  if ((MatrixTraits::zero_addition_can_be_elided == true)
1845  &&
1846  (value == value_type()))
1847  return;
1848 
1849  const std::pair<unsigned int,size_type>
1850  row_index = row_block_indices.global_to_local (i),
1851  col_index = column_block_indices.global_to_local (j);
1852  block(row_index.first,col_index.first).add (row_index.second,
1853  col_index.second,
1854  value);
1855 }
1856 
1857 
1858 
1859 template <class MatrixType>
1860 template <typename number>
1861 inline
1862 void
1863 BlockMatrixBase<MatrixType>::add (const std::vector<size_type> &row_indices,
1864  const std::vector<size_type> &col_indices,
1865  const FullMatrix<number> &values,
1866  const bool elide_zero_values)
1867 {
1868  Assert (row_indices.size() == values.m(),
1869  ExcDimensionMismatch(row_indices.size(), values.m()));
1870  Assert (col_indices.size() == values.n(),
1871  ExcDimensionMismatch(col_indices.size(), values.n()));
1872 
1873  for (size_type i=0; i<row_indices.size(); ++i)
1874  add (row_indices[i], col_indices.size(), &col_indices[0], &values(i,0),
1875  elide_zero_values);
1876 }
1877 
1878 
1879 
1880 template <class MatrixType>
1881 template <typename number>
1882 inline
1883 void
1884 BlockMatrixBase<MatrixType>::add (const std::vector<size_type> &indices,
1885  const FullMatrix<number> &values,
1886  const bool elide_zero_values)
1887 {
1888  Assert (indices.size() == values.m(),
1889  ExcDimensionMismatch(indices.size(), values.m()));
1890  Assert (values.n() == values.m(), ExcNotQuadratic());
1891 
1892  for (size_type i=0; i<indices.size(); ++i)
1893  add (indices[i], indices.size(), &indices[0], &values(i,0),
1894  elide_zero_values);
1895 }
1896 
1897 
1898 
1899 template <class MatrixType>
1900 template <typename number>
1901 inline
1902 void
1903 BlockMatrixBase<MatrixType>::add (const size_type row,
1904  const std::vector<size_type> &col_indices,
1905  const std::vector<number> &values,
1906  const bool elide_zero_values)
1907 {
1908  Assert (col_indices.size() == values.size(),
1909  ExcDimensionMismatch(col_indices.size(), values.size()));
1910 
1911  add (row, col_indices.size(), &col_indices[0], &values[0],
1912  elide_zero_values);
1913 }
1914 
1915 
1916 
1917 // This is a very messy function, since
1918 // we need to calculate to each position
1919 // the location in the global array.
1920 template <class MatrixType>
1921 template <typename number>
1922 inline
1923 void
1924 BlockMatrixBase<MatrixType>::add (const size_type row,
1925  const size_type n_cols,
1926  const size_type *col_indices,
1927  const number *values,
1928  const bool elide_zero_values,
1929  const bool col_indices_are_sorted)
1930 {
1931  prepare_add_operation();
1932 
1933  // TODO: Look over this to find out
1934  // whether we can do that more
1935  // efficiently.
1936  if (col_indices_are_sorted == true)
1937  {
1938 #ifdef DEBUG
1939  // check whether indices really are
1940  // sorted.
1941  size_type before = col_indices[0];
1942  for (size_type i=1; i<n_cols; ++i)
1943  if (col_indices[i] <= before)
1944  Assert (false, ExcMessage ("Flag col_indices_are_sorted is set, but "
1945  "indices appear to not be sorted."))
1946  else
1947  before = col_indices[i];
1948 #endif
1949  const std::pair<unsigned int,size_type>
1950  row_index = this->row_block_indices.global_to_local (row);
1951 
1952  if (this->n_block_cols() > 1)
1953  {
1954  const size_type *first_block = Utilities::lower_bound (col_indices,
1955  col_indices+n_cols,
1956  this->column_block_indices.block_start(1));
1957 
1958  const size_type n_zero_block_indices = first_block - col_indices;
1959  block(row_index.first, 0).add (row_index.second,
1960  n_zero_block_indices,
1961  col_indices,
1962  values,
1963  elide_zero_values,
1964  col_indices_are_sorted);
1965 
1966  if (n_zero_block_indices < n_cols)
1967  this->add(row, n_cols - n_zero_block_indices, first_block,
1968  values + n_zero_block_indices, elide_zero_values,
1969  false);
1970  }
1971  else
1972  {
1973  block(row_index.first, 0). add (row_index.second,
1974  n_cols,
1975  col_indices,
1976  values,
1977  elide_zero_values,
1978  col_indices_are_sorted);
1979  }
1980 
1981  return;
1982  }
1983 
1984  // Lock scratch arrays, then resize them
1985  Threads::Mutex::ScopedLock lock (temporary_data.mutex);
1986 
1987  if (temporary_data.column_indices.size() < this->n_block_cols())
1988  {
1989  temporary_data.column_indices.resize (this->n_block_cols());
1990  temporary_data.column_values.resize (this->n_block_cols());
1991  temporary_data.counter_within_block.resize (this->n_block_cols());
1992  }
1993 
1994  // Resize sub-arrays to n_cols. This
1995  // is a bit wasteful, but we resize
1996  // only a few times (then the maximum
1997  // row length won't increase that
1998  // much any more). At least we know
1999  // that all arrays are going to be of
2000  // the same size, so we can check
2001  // whether the size of one is large
2002  // enough before actually going
2003  // through all of them.
2004  if (temporary_data.column_indices[0].size() < n_cols)
2005  {
2006  for (unsigned int i=0; i<this->n_block_cols(); ++i)
2007  {
2008  temporary_data.column_indices[i].resize(n_cols);
2009  temporary_data.column_values[i].resize(n_cols);
2010  }
2011  }
2012 
2013  // Reset the number of added elements
2014  // in each block to zero.
2015  for (unsigned int i=0; i<this->n_block_cols(); ++i)
2016  temporary_data.counter_within_block[i] = 0;
2017 
2018  // Go through the column indices to
2019  // find out which portions of the
2020  // values should be written into
2021  // which block of the matrix. We need
2022  // to touch all the data, since we
2023  // can't be sure that the data of one
2024  // block is stored contiguously (in
2025  // fact, data will be intermixed when
2026  // it comes from an element matrix).
2027  for (size_type j=0; j<n_cols; ++j)
2028  {
2029  number value = values[j];
2030 
2031  if (value == number() && elide_zero_values == true)
2032  continue;
2033 
2034  const std::pair<unsigned int, size_type>
2035  col_index = this->column_block_indices.global_to_local(col_indices[j]);
2036 
2037  const size_type local_index = temporary_data.counter_within_block[col_index.first]++;
2038 
2039  temporary_data.column_indices[col_index.first][local_index] = col_index.second;
2040  temporary_data.column_values[col_index.first][local_index] = value;
2041  }
2042 
2043 #ifdef DEBUG
2044  // If in debug mode, do a check whether
2045  // the right length has been obtained.
2046  size_type length = 0;
2047  for (unsigned int i=0; i<this->n_block_cols(); ++i)
2048  length += temporary_data.counter_within_block[i];
2049  Assert (length <= n_cols, ExcInternalError());
2050 #endif
2051 
2052  // Now we found out about where the
2053  // individual columns should start and
2054  // where we should start reading out
2055  // data. Now let's write the data into
2056  // the individual blocks!
2057  const std::pair<unsigned int,size_type>
2058  row_index = this->row_block_indices.global_to_local (row);
2059  for (unsigned int block_col=0; block_col<n_block_cols(); ++block_col)
2060  {
2061  if (temporary_data.counter_within_block[block_col] == 0)
2062  continue;
2063 
2064  block(row_index.first, block_col).add
2065  (row_index.second,
2066  temporary_data.counter_within_block[block_col],
2067  &temporary_data.column_indices[block_col][0],
2068  &temporary_data.column_values[block_col][0],
2069  false,
2070  col_indices_are_sorted);
2071  }
2072 }
2073 
2074 
2075 
2076 template <class MatrixType>
2077 inline
2078 void
2079 BlockMatrixBase<MatrixType>::add (const value_type factor,
2080  const BlockMatrixBase<MatrixType> &matrix)
2081 {
2082  AssertIsFinite(factor);
2083 
2084  prepare_add_operation();
2085 
2086  // save some cycles for zero additions, but
2087  // only if it is safe for the matrix we are
2088  // working with
2089  typedef typename MatrixType::Traits MatrixTraits;
2090  if ((MatrixTraits::zero_addition_can_be_elided == true)
2091  &&
2092  (factor == 0))
2093  return;
2094 
2095  for (unsigned int row=0; row<n_block_rows(); ++row)
2096  for (unsigned int col=0; col<n_block_cols(); ++col)
2097  // This function should throw if the sparsity
2098  // patterns of the two blocks differ
2099  block(row, col).add(factor, matrix.block(row,col));
2100 }
2101 
2102 
2103 
2104 template <class MatrixType>
2105 inline
2108  const size_type j) const
2109 {
2110  const std::pair<unsigned int,size_type>
2111  row_index = row_block_indices.global_to_local (i),
2112  col_index = column_block_indices.global_to_local (j);
2113  return block(row_index.first,col_index.first) (row_index.second,
2114  col_index.second);
2115 }
2116 
2117 
2118 
2119 template <class MatrixType>
2120 inline
2122 BlockMatrixBase<MatrixType>::el (const size_type i,
2123  const size_type j) const
2124 {
2125  const std::pair<unsigned int,size_type>
2126  row_index = row_block_indices.global_to_local (i),
2127  col_index = column_block_indices.global_to_local (j);
2128  return block(row_index.first,col_index.first).el (row_index.second,
2129  col_index.second);
2130 }
2131 
2132 
2133 
2134 template <class MatrixType>
2135 inline
2137 BlockMatrixBase<MatrixType>::diag_element (const size_type i) const
2138 {
2139  Assert (n_block_rows() == n_block_cols(),
2140  ExcNotQuadratic());
2141 
2142  const std::pair<unsigned int,size_type>
2143  index = row_block_indices.global_to_local (i);
2144  return block(index.first,index.first).diag_element(index.second);
2145 }
2146 
2147 
2148 
2149 template <class MatrixType>
2150 inline
2151 void
2153 {
2154  for (unsigned int r=0; r<n_block_rows(); ++r)
2155  for (unsigned int c=0; c<n_block_cols(); ++c)
2156  block(r,c).compress (operation);
2157 }
2158 
2159 
2160 
2161 template <class MatrixType>
2162 inline
2164 BlockMatrixBase<MatrixType>::operator *= (const value_type factor)
2165 {
2166  Assert (n_block_cols() != 0, ExcNotInitialized());
2167  Assert (n_block_rows() != 0, ExcNotInitialized());
2168 
2169  for (unsigned int r=0; r<n_block_rows(); ++r)
2170  for (unsigned int c=0; c<n_block_cols(); ++c)
2171  block(r,c) *= factor;
2172 
2173  return *this;
2174 }
2175 
2176 
2177 
2178 template <class MatrixType>
2179 inline
2181 BlockMatrixBase<MatrixType>::operator /= (const value_type factor)
2182 {
2183  Assert (n_block_cols() != 0, ExcNotInitialized());
2184  Assert (n_block_rows() != 0, ExcNotInitialized());
2185  Assert (factor !=0, ExcDivideByZero());
2186 
2187  const value_type factor_inv = 1. / factor;
2188 
2189  for (unsigned int r=0; r<n_block_rows(); ++r)
2190  for (unsigned int c=0; c<n_block_cols(); ++c)
2191  block(r,c) *= factor_inv;
2192 
2193  return *this;
2194 }
2195 
2196 
2197 
2198 template <class MatrixType>
2199 const BlockIndices &
2201 {
2202  return this->row_block_indices;
2203 }
2204 
2205 
2206 
2207 template <class MatrixType>
2208 const BlockIndices &
2210 {
2211  return this->column_block_indices;
2212 }
2213 
2214 
2215 
2216 template <class MatrixType>
2217 template <class BlockVectorType>
2218 void
2220 vmult_block_block (BlockVectorType &dst,
2221  const BlockVectorType &src) const
2222 {
2223  Assert (dst.n_blocks() == n_block_rows(),
2224  ExcDimensionMismatch(dst.n_blocks(), n_block_rows()));
2225  Assert (src.n_blocks() == n_block_cols(),
2226  ExcDimensionMismatch(src.n_blocks(), n_block_cols()));
2227 
2228  for (size_type row=0; row<n_block_rows(); ++row)
2229  {
2230  block(row,0).vmult (dst.block(row),
2231  src.block(0));
2232  for (size_type col=1; col<n_block_cols(); ++col)
2233  block(row,col).vmult_add (dst.block(row),
2234  src.block(col));
2235  };
2236 }
2237 
2238 
2239 
2240 template <class MatrixType>
2241 template <class BlockVectorType,
2242  class VectorType>
2243 void
2245 vmult_nonblock_block (VectorType &dst,
2246  const BlockVectorType &src) const
2247 {
2248  Assert (n_block_rows() == 1,
2249  ExcDimensionMismatch(1, n_block_rows()));
2250  Assert (src.n_blocks() == n_block_cols(),
2251  ExcDimensionMismatch(src.n_blocks(), n_block_cols()));
2252 
2253  block(0,0).vmult (dst, src.block(0));
2254  for (size_type col=1; col<n_block_cols(); ++col)
2255  block(0,col).vmult_add (dst, src.block(col));
2256 }
2257 
2258 
2259 
2260 template <class MatrixType>
2261 template <class BlockVectorType,
2262  class VectorType>
2263 void
2265 vmult_block_nonblock (BlockVectorType &dst,
2266  const VectorType &src) const
2267 {
2268  Assert (dst.n_blocks() == n_block_rows(),
2269  ExcDimensionMismatch(dst.n_blocks(), n_block_rows()));
2270  Assert (1 == n_block_cols(),
2271  ExcDimensionMismatch(1, n_block_cols()));
2272 
2273  for (size_type row=0; row<n_block_rows(); ++row)
2274  block(row,0).vmult (dst.block(row),
2275  src);
2276 }
2277 
2278 
2279 
2280 template <class MatrixType>
2281 template <class VectorType>
2282 void
2284 vmult_nonblock_nonblock (VectorType &dst,
2285  const VectorType &src) const
2286 {
2287  Assert (1 == n_block_rows(),
2288  ExcDimensionMismatch(1, n_block_rows()));
2289  Assert (1 == n_block_cols(),
2290  ExcDimensionMismatch(1, n_block_cols()));
2291 
2292  block(0,0).vmult (dst, src);
2293 }
2294 
2295 
2296 
2297 template <class MatrixType>
2298 template <class BlockVectorType>
2299 void
2300 BlockMatrixBase<MatrixType>::vmult_add (BlockVectorType &dst,
2301  const BlockVectorType &src) const
2302 {
2303  Assert (dst.n_blocks() == n_block_rows(),
2304  ExcDimensionMismatch(dst.n_blocks(), n_block_rows()));
2305  Assert (src.n_blocks() == n_block_cols(),
2306  ExcDimensionMismatch(src.n_blocks(), n_block_cols()));
2307 
2308  for (unsigned int row=0; row<n_block_rows(); ++row)
2309  for (unsigned int col=0; col<n_block_cols(); ++col)
2310  block(row,col).vmult_add (dst.block(row),
2311  src.block(col));
2312 }
2313 
2314 
2315 
2316 
2317 template <class MatrixType>
2318 template <class BlockVectorType>
2319 void
2321 Tvmult_block_block (BlockVectorType &dst,
2322  const BlockVectorType &src) const
2323 {
2324  Assert (dst.n_blocks() == n_block_cols(),
2325  ExcDimensionMismatch(dst.n_blocks(), n_block_cols()));
2326  Assert (src.n_blocks() == n_block_rows(),
2327  ExcDimensionMismatch(src.n_blocks(), n_block_rows()));
2328 
2329  dst = 0.;
2330 
2331  for (unsigned int row=0; row<n_block_rows(); ++row)
2332  {
2333  for (unsigned int col=0; col<n_block_cols(); ++col)
2334  block(row,col).Tvmult_add (dst.block(col),
2335  src.block(row));
2336  };
2337 }
2338 
2339 
2340 
2341 template <class MatrixType>
2342 template <class BlockVectorType,
2343  class VectorType>
2344 void
2346 Tvmult_block_nonblock (BlockVectorType &dst,
2347  const VectorType &src) const
2348 {
2349  Assert (dst.n_blocks() == n_block_cols(),
2350  ExcDimensionMismatch(dst.n_blocks(), n_block_cols()));
2351  Assert (1 == n_block_rows(),
2352  ExcDimensionMismatch(1, n_block_rows()));
2353 
2354  dst = 0.;
2355 
2356  for (unsigned int col=0; col<n_block_cols(); ++col)
2357  block(0,col).Tvmult_add (dst.block(col), src);
2358 }
2359 
2360 
2361 
2362 template <class MatrixType>
2363 template <class BlockVectorType,
2364  class VectorType>
2365 void
2367 Tvmult_nonblock_block (VectorType &dst,
2368  const BlockVectorType &src) const
2369 {
2370  Assert (1 == n_block_cols(),
2371  ExcDimensionMismatch(1, n_block_cols()));
2372  Assert (src.n_blocks() == n_block_rows(),
2373  ExcDimensionMismatch(src.n_blocks(), n_block_rows()));
2374 
2375  block(0,0).Tvmult (dst, src.block(0));
2376 
2377  for (size_type row=1; row<n_block_rows(); ++row)
2378  block(row,0).Tvmult_add (dst, src.block(row));
2379 }
2380 
2381 
2382 
2383 template <class MatrixType>
2384 template <class VectorType>
2385 void
2387 Tvmult_nonblock_nonblock (VectorType &dst,
2388  const VectorType &src) const
2389 {
2390  Assert (1 == n_block_cols(),
2391  ExcDimensionMismatch(1, n_block_cols()));
2392  Assert (1 == n_block_rows(),
2393  ExcDimensionMismatch(1, n_block_rows()));
2394 
2395  block(0,0).Tvmult (dst, src);
2396 }
2397 
2398 
2399 
2400 template <class MatrixType>
2401 template <class BlockVectorType>
2402 void
2403 BlockMatrixBase<MatrixType>::Tvmult_add (BlockVectorType &dst,
2404  const BlockVectorType &src) const
2405 {
2406  Assert (dst.n_blocks() == n_block_cols(),
2407  ExcDimensionMismatch(dst.n_blocks(), n_block_cols()));
2408  Assert (src.n_blocks() == n_block_rows(),
2409  ExcDimensionMismatch(src.n_blocks(), n_block_rows()));
2410 
2411  for (unsigned int row=0; row<n_block_rows(); ++row)
2412  for (unsigned int col=0; col<n_block_cols(); ++col)
2413  block(row,col).Tvmult_add (dst.block(col),
2414  src.block(row));
2415 }
2416 
2417 
2418 
2419 template <class MatrixType>
2420 template <class BlockVectorType>
2422 BlockMatrixBase<MatrixType>::matrix_norm_square (const BlockVectorType &v) const
2423 {
2424  Assert (n_block_rows() == n_block_cols(), ExcNotQuadratic());
2425  Assert (v.n_blocks() == n_block_rows(),
2426  ExcDimensionMismatch(v.n_blocks(), n_block_rows()));
2427 
2428  value_type norm_sqr = 0;
2429  for (unsigned int row=0; row<n_block_rows(); ++row)
2430  for (unsigned int col=0; col<n_block_cols(); ++col)
2431  if (row==col)
2432  norm_sqr += block(row,col).matrix_norm_square (v.block(row));
2433  else
2434  norm_sqr += block(row,col).matrix_scalar_product (v.block(row),
2435  v.block(col));
2436  return norm_sqr;
2437 }
2438 
2439 
2440 
2441 template <class MatrixType>
2442 template <class BlockVectorType>
2445 matrix_scalar_product (const BlockVectorType &u,
2446  const BlockVectorType &v) const
2447 {
2448  Assert (u.n_blocks() == n_block_rows(),
2449  ExcDimensionMismatch(u.n_blocks(), n_block_rows()));
2450  Assert (v.n_blocks() == n_block_cols(),
2451  ExcDimensionMismatch(v.n_blocks(), n_block_cols()));
2452 
2453  value_type result = 0;
2454  for (unsigned int row=0; row<n_block_rows(); ++row)
2455  for (unsigned int col=0; col<n_block_cols(); ++col)
2456  result += block(row,col).matrix_scalar_product (u.block(row),
2457  v.block(col));
2458  return result;
2459 }
2460 
2461 
2462 
2463 template <class MatrixType>
2464 template <class BlockVectorType>
2467 residual (BlockVectorType &dst,
2468  const BlockVectorType &x,
2469  const BlockVectorType &b) const
2470 {
2471  Assert (dst.n_blocks() == n_block_rows(),
2472  ExcDimensionMismatch(dst.n_blocks(), n_block_rows()));
2473  Assert (b.n_blocks() == n_block_rows(),
2474  ExcDimensionMismatch(b.n_blocks(), n_block_rows()));
2475  Assert (x.n_blocks() == n_block_cols(),
2476  ExcDimensionMismatch(x.n_blocks(), n_block_cols()));
2477  // in block notation, the residual is
2478  // r_i = b_i - \sum_j A_ij x_j.
2479  // this can be written as
2480  // r_i = b_i - A_i0 x_0 - \sum_{j>0} A_ij x_j.
2481  //
2482  // for the first two terms, we can
2483  // call the residual function of
2484  // A_i0. for the other terms, we
2485  // use vmult_add. however, we want
2486  // to subtract, so in order to
2487  // avoid a temporary vector, we
2488  // perform a sign change of the
2489  // first two term before, and after
2490  // adding up
2491  for (unsigned int row=0; row<n_block_rows(); ++row)
2492  {
2493  block(row,0).residual (dst.block(row),
2494  x.block(0),
2495  b.block(row));
2496 
2497  for (size_type i=0; i<dst.block(row).size(); ++i)
2498  dst.block(row)(i) = -dst.block(row)(i);
2499 
2500  for (unsigned int col=1; col<n_block_cols(); ++col)
2501  block(row,col).vmult_add (dst.block(row),
2502  x.block(col));
2503 
2504  for (size_type i=0; i<dst.block(row).size(); ++i)
2505  dst.block(row)(i) = -dst.block(row)(i);
2506  };
2507 
2508  value_type res = 0;
2509  for (size_type row=0; row<n_block_rows(); ++row)
2510  res += dst.block(row).norm_sqr ();
2511  return std::sqrt(res);
2512 }
2513 
2514 
2515 
2516 template <class MatrixType>
2517 inline
2518 void
2519 BlockMatrixBase<MatrixType>::print (std::ostream &out,
2520  const bool alternative_output) const
2521 {
2522  for (unsigned int row=0; row<n_block_rows(); ++row)
2523  for (unsigned int col=0; col<n_block_cols(); ++col)
2524  {
2525  if (!alternative_output)
2526  out << "Block (" << row << ", " << col << ")" << std::endl;
2527 
2528  block(row, col).print(out, alternative_output);
2529  }
2530 }
2531 
2532 
2533 
2534 template <class MatrixType>
2535 inline
2538 {
2539  return const_iterator(this, 0);
2540 }
2541 
2542 
2543 
2544 template <class MatrixType>
2545 inline
2548 {
2549  return const_iterator(this, m());
2550 }
2551 
2552 
2553 
2554 template <class MatrixType>
2555 inline
2557 BlockMatrixBase<MatrixType>::begin (const size_type r) const
2558 {
2559  Assert (r<m(), ExcIndexRange(r,0,m()));
2560  return const_iterator(this, r);
2561 }
2562 
2563 
2564 
2565 template <class MatrixType>
2566 inline
2568 BlockMatrixBase<MatrixType>::end (const size_type r) const
2569 {
2570  Assert (r<m(), ExcIndexRange(r,0,m()));
2571  return const_iterator(this, r+1);
2572 }
2573 
2574 
2575 
2576 template <class MatrixType>
2577 inline
2580 {
2581  return iterator(this, 0);
2582 }
2583 
2584 
2585 
2586 template <class MatrixType>
2587 inline
2590 {
2591  return iterator(this, m());
2592 }
2593 
2594 
2595 
2596 template <class MatrixType>
2597 inline
2599 BlockMatrixBase<MatrixType>::begin (const size_type r)
2600 {
2601  Assert (r<m(), ExcIndexRange(r,0,m()));
2602  return iterator(this, r);
2603 }
2604 
2605 
2606 
2607 template <class MatrixType>
2608 inline
2610 BlockMatrixBase<MatrixType>::end (const size_type r)
2611 {
2612  Assert (r<m(), ExcIndexRange(r,0,m()));
2613  return iterator(this, r+1);
2614 }
2615 
2616 
2617 
2618 template <class MatrixType>
2619 void
2621 {
2622  std::vector<size_type> row_sizes (this->n_block_rows());
2623  std::vector<size_type> col_sizes (this->n_block_cols());
2624 
2625  // first find out the row sizes
2626  // from the first block column
2627  for (unsigned int r=0; r<this->n_block_rows(); ++r)
2628  row_sizes[r] = sub_objects[r][0]->m();
2629  // then check that the following
2630  // block columns have the same
2631  // sizes
2632  for (unsigned int c=1; c<this->n_block_cols(); ++c)
2633  for (unsigned int r=0; r<this->n_block_rows(); ++r)
2634  Assert (row_sizes[r] == sub_objects[r][c]->m(),
2635  ExcIncompatibleRowNumbers (r,0,r,c));
2636 
2637  // finally initialize the row
2638  // indices with this array
2639  this->row_block_indices.reinit (row_sizes);
2640 
2641 
2642  // then do the same with the columns
2643  for (unsigned int c=0; c<this->n_block_cols(); ++c)
2644  col_sizes[c] = sub_objects[0][c]->n();
2645  for (unsigned int r=1; r<this->n_block_rows(); ++r)
2646  for (unsigned int c=0; c<this->n_block_cols(); ++c)
2647  Assert (col_sizes[c] == sub_objects[r][c]->n(),
2648  ExcIncompatibleRowNumbers (0,c,r,c));
2649 
2650  // finally initialize the row
2651  // indices with this array
2652  this->column_block_indices.reinit (col_sizes);
2653 }
2654 
2655 
2656 
2657 template <class MatrixType>
2658 void
2660 {
2661  for (unsigned int row=0; row<n_block_rows(); ++row)
2662  for (unsigned int col=0; col<n_block_cols(); ++col)
2663  block(row, col).prepare_add();
2664 }
2665 
2666 
2667 
2668 template <class MatrixType>
2669 void
2671 {
2672  for (unsigned int row=0; row<n_block_rows(); ++row)
2673  for (unsigned int col=0; col<n_block_cols(); ++col)
2674  block(row, col).prepare_set();
2675 }
2676 
2677 #endif // DOXYGEN
2678 
2679 
2680 DEAL_II_NAMESPACE_CLOSE
2681 
2682 #endif // dealii__block_matrix_base_h
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:618
size_type m() const
const types::global_dof_index invalid_size_type
Definition: types.h:179
static const unsigned int invalid_unsigned_int
Definition: types.h:170
void collect_sizes()
void vmult_block_nonblock(BlockVectorType &dst, const VectorType &src) const
BlockMatrixBase & copy_from(const BlockMatrixType &source)
void Tvmult_add(BlockVectorType &dst, const BlockVectorType &src) const
static ::ExceptionBase & ExcIncompatibleColNumbers(int arg1, int arg2, int arg3, int arg4)
TemporaryData & operator=(const TemporaryData &)
std::vector< size_type > counter_within_block
std::vector< std::vector< size_type > > column_indices
void set(const size_type i, const size_type j, const value_type value)
value_type operator()(const size_type i, const size_type j) const
BlockMatrixType::value_type value_type
void vmult_nonblock_block(VectorType &dst, const BlockVectorType &src) const
value_type diag_element(const size_type i) const
static ::ExceptionBase & ExcNotInitialized()
void Tvmult_block_nonblock(BlockVectorType &dst, const VectorType &src) const
void add(const size_type i, const size_type j, const value_type value)
value_type matrix_norm_square(const BlockVectorType &v) const
void Tvmult_block_block(BlockVectorType &dst, const BlockVectorType &src) const
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
void Tvmult_nonblock_block(VectorType &dst, const BlockVectorType &src) const
TemporaryData temporary_data
static ::ExceptionBase & ExcDivideByZero()
types::global_dof_index size_type
std::size_t memory_consumption() const
void vmult_block_block(BlockVectorType &dst, const BlockVectorType &src) const
BlockMatrixBase & operator*=(const value_type factor)
void print(std::ostream &out, const bool alternative_output=false) const
void vmult_add(BlockVectorType &dst, const BlockVectorType &src) const
void Tvmult_nonblock_nonblock(VectorType &dst, const VectorType &src) const
const BlockIndices & get_row_indices() const
std::vector< std::vector< value_type > > column_values
BlockMatrixBase & operator/=(const value_type factor)
unsigned int n_block_cols() const
static ::ExceptionBase & ExcMessage(std::string arg1)
size_type n() const
unsigned int global_dof_index
Definition: types.h:88
#define Assert(cond, exc)
Definition: exceptions.h:313
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
number value_type
void prepare_add_operation()
value_type el(const size_type i, const size_type j) const
const BlockIndices & get_column_indices() const
iterator end()
BlockType::value_type value_type
BlockMatrixType::BlockType::const_iterator base_iterator
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
value_type residual(BlockVectorType &dst, const BlockVectorType &x, const BlockVectorType &b) const
unsigned int block_column() const
static ::ExceptionBase & ExcIteratorPastEnd()
static ::ExceptionBase & ExcNotQuadratic()
std_cxx11::enable_if< std_cxx11::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
unsigned int block_row() const
void vmult_nonblock_nonblock(VectorType &dst, const VectorType &src) const
BlockType & block(const unsigned int row, const unsigned int column)
#define DeclException4(Exception4, type1, type2, type3, type4, outsequence)
Definition: exceptions.h:600
Table< 2, SmartPointer< BlockType, BlockMatrixBase< MatrixType > > > sub_objects
static ::ExceptionBase & ExcNotImplemented()
BlockIndices row_block_indices
Definition: table.h:33
unsigned int n_block_rows() const
value_type matrix_scalar_product(const BlockVectorType &u, const BlockVectorType &v) const
#define AssertIsFinite(number)
Definition: exceptions.h:1197
size_type m() const
void compress(::VectorOperation::values operation)
static ::ExceptionBase & ExcIncompatibleRowNumbers(int arg1, int arg2, int arg3, int arg4)
size_type n() const
void prepare_set_operation()
static ::ExceptionBase & ExcInternalError()
iterator begin()