Reference documentation for deal.II version 9.1.0-pre
block_vector_base.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2018 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.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_block_vector_base_h
17 #define dealii_block_vector_base_h
18 
19 
20 #include <deal.II/base/config.h>
21 
22 #include <deal.II/base/exceptions.h>
23 #include <deal.II/base/memory_consumption.h>
24 #include <deal.II/base/numbers.h>
25 #include <deal.II/base/subscriptor.h>
26 
27 #include <deal.II/lac/block_indices.h>
28 #include <deal.II/lac/exceptions.h>
29 #include <deal.II/lac/vector.h>
30 #include <deal.II/lac/vector_operation.h>
31 
32 #include <cmath>
33 #include <cstddef>
34 #include <iterator>
35 #include <vector>
36 
37 DEAL_II_NAMESPACE_OPEN
38 
39 
44 template <typename>
46 
47 
64 template <typename VectorType>
66 {
67 private:
68  struct yes_type
69  {
70  char c[1];
71  };
72  struct no_type
73  {
74  char c[2];
75  };
76 
81  template <typename T>
82  static yes_type
84 
89  static no_type
91 
92 public:
98  static const bool value =
99  (sizeof(check_for_block_vector((VectorType *)nullptr)) == sizeof(yes_type));
100 };
101 
102 
103 // instantiation of the static member
104 template <typename VectorType>
106 
107 
108 
109 namespace internal
110 {
116  namespace BlockVectorIterators
117  {
122  template <class BlockVectorType, bool Constness>
123  struct Types
124  {};
125 
126 
127 
134  template <class BlockVectorType>
135  struct Types<BlockVectorType, false>
136  {
141  using Vector = typename BlockVectorType::BlockType;
142 
147  using BlockVector = BlockVectorType;
148 
153 
158  using dereference_type = typename Vector::reference;
159  };
160 
161 
162 
169  template <class BlockVectorType>
170  struct Types<BlockVectorType, true>
171  {
176  using Vector = const typename BlockVectorType::BlockType;
177 
182  using BlockVector = const BlockVectorType;
183 
188  using value_type = const typename BlockVector::value_type;
189 
196  };
197 
198 
216  template <class BlockVectorType, bool Constness>
217  class Iterator
218  {
219  public:
224 
231 
237  using iterator_category = std::random_access_iterator_tag;
238  using difference_type = std::ptrdiff_t;
239  using reference = typename BlockVectorType::reference;
240  using pointer = value_type *;
241 
242  using dereference_type =
244 
249  using BlockVector =
251 
260  Iterator(BlockVector &parent, const size_type global_index);
261 
270 
271 
275  Iterator(const Iterator &c);
276 
277  private:
282  Iterator(BlockVector & parent,
283  const size_type global_index,
284  const size_type current_block,
285  const size_type index_within_block,
286  const size_type next_break_forward,
287  const size_type next_break_backward);
288 
289  public:
293  Iterator &
294  operator=(const Iterator &c);
295 
301  dereference_type operator*() const;
302 
307  dereference_type operator[](const difference_type d) const;
308 
313  Iterator &
314  operator++();
315 
321  Iterator
322  operator++(int);
323 
328  Iterator &
329  operator--();
330 
336  Iterator
337  operator--(int);
338 
343  template <bool OtherConstness>
344  bool
345  operator==(const Iterator<BlockVectorType, OtherConstness> &i) const;
346 
351  template <bool OtherConstness>
352  bool
353  operator!=(const Iterator<BlockVectorType, OtherConstness> &i) const;
354 
360  template <bool OtherConstness>
361  bool
362  operator<(const Iterator<BlockVectorType, OtherConstness> &i) const;
363 
367  template <bool OtherConstness>
368  bool
369  operator<=(const Iterator<BlockVectorType, OtherConstness> &i) const;
370 
374  template <bool OtherConstness>
375  bool
376  operator>(const Iterator<BlockVectorType, OtherConstness> &i) const;
377 
381  template <bool OtherConstness>
382  bool
383  operator>=(const Iterator<BlockVectorType, OtherConstness> &i) const;
384 
388  template <bool OtherConstness>
389  difference_type
391 
396  Iterator
397  operator+(const difference_type &d) const;
398 
403  Iterator
404  operator-(const difference_type &d) const;
405 
410  Iterator &
411  operator+=(const difference_type &d);
412 
417  Iterator &
418  operator-=(const difference_type &d);
419 
429  DeclExceptionMsg(ExcPointerToDifferentVectors,
430  "Your program tried to compare iterators pointing to "
431  "different block vectors. There is no reasonable way "
432  "to do this.");
433 
435  private:
442 
447 
452  unsigned int current_block;
453  size_type index_within_block;
454 
462  size_type next_break_backward;
463 
467  void
468  move_forward();
469 
473  void
474  move_backward();
475 
476 
480  template <typename, bool>
481  friend class Iterator;
482  };
483  } // namespace BlockVectorIterators
484 } // namespace internal
485 
486 
525 template <class VectorType>
526 class BlockVectorBase : public Subscriptor
527 {
528 public:
532  using BlockType = VectorType;
533 
534  /*
535  * Declare standard types used in
536  * all containers. These types
537  * parallel those in the
538  * <tt>C++</tt> standard
539  * libraries
540  * <tt>std::vector<...></tt>
541  * class. This includes iterator
542  * types.
543  */
544  using value_type = typename BlockType::value_type;
545  using pointer = value_type *;
546  using const_pointer = const value_type *;
547  using iterator =
549  using const_iterator =
551  using reference = typename BlockType::reference;
552  using const_reference = typename BlockType::const_reference;
553  using size_type = types::global_dof_index;
554 
564  using real_type = typename BlockType::real_type;
565 
569  BlockVectorBase() = default;
570 
574  BlockVectorBase(const BlockVectorBase & /*V*/) = default;
575 
581  BlockVectorBase(BlockVectorBase && /*V*/) noexcept = default;
582 
589  void
590  collect_sizes();
591 
602  void
603  compress(::VectorOperation::values operation);
604 
608  BlockType &
609  block(const unsigned int i);
610 
614  const BlockType &
615  block(const unsigned int i) const;
616 
622  const BlockIndices &
623  get_block_indices() const;
624 
628  unsigned int
629  n_blocks() const;
630 
635  std::size_t
636  size() const;
637 
654  IndexSet
655  locally_owned_elements() const;
656 
660  iterator
661  begin();
662 
668  begin() const;
669 
673  iterator
674  end();
675 
681  end() const;
682 
686  value_type
687  operator()(const size_type i) const;
688 
692  reference
693  operator()(const size_type i);
694 
700  value_type operator[](const size_type i) const;
701 
707  reference operator[](const size_type i);
708 
724  template <typename OtherNumber>
725  void
726  extract_subvector_to(const std::vector<size_type> &indices,
727  std::vector<OtherNumber> & values) const;
728 
756  template <typename ForwardIterator, typename OutputIterator>
757  void
758  extract_subvector_to(ForwardIterator indices_begin,
759  const ForwardIterator indices_end,
760  OutputIterator values_begin) const;
761 
767  operator=(const value_type s);
768 
773  operator=(const BlockVectorBase &V);
774 
781  operator=(BlockVectorBase && /*V*/) = default; // NOLINT
782 
786  template <class VectorType2>
788  operator=(const BlockVectorBase<VectorType2> &V);
789 
794  operator=(const VectorType &v);
795 
800  template <class VectorType2>
801  bool
802  operator==(const BlockVectorBase<VectorType2> &v) const;
803 
807  value_type operator*(const BlockVectorBase &V) const;
808 
812  real_type
813  norm_sqr() const;
814 
818  value_type
819  mean_value() const;
820 
824  real_type
825  l1_norm() const;
826 
831  real_type
832  l2_norm() const;
833 
838  real_type
839  linfty_norm() const;
840 
863  value_type
864  add_and_dot(const value_type a,
865  const BlockVectorBase &V,
866  const BlockVectorBase &W);
867 
872  bool
873  in_local_range(const size_type global_index) const;
874 
880  bool
881  all_zero() const;
882 
888  bool
889  is_non_negative() const;
890 
895  operator+=(const BlockVectorBase &V);
896 
901  operator-=(const BlockVectorBase &V);
902 
903 
908  template <typename Number>
909  void
910  add(const std::vector<size_type> &indices, const std::vector<Number> &values);
911 
916  template <typename Number>
917  void
918  add(const std::vector<size_type> &indices, const Vector<Number> &values);
919 
925  template <typename Number>
926  void
927  add(const size_type n_elements,
928  const size_type *indices,
929  const Number * values);
930 
935  void
936  add(const value_type s);
937 
941  void
942  add(const value_type a, const BlockVectorBase &V);
943 
947  void
948  add(const value_type a,
949  const BlockVectorBase &V,
950  const value_type b,
951  const BlockVectorBase &W);
952 
956  void
957  sadd(const value_type s, const BlockVectorBase &V);
958 
962  void
963  sadd(const value_type s, const value_type a, const BlockVectorBase &V);
964 
968  void
969  sadd(const value_type s,
970  const value_type a,
971  const BlockVectorBase &V,
972  const value_type b,
973  const BlockVectorBase &W);
974 
978  void
979  sadd(const value_type s,
980  const value_type a,
981  const BlockVectorBase &V,
982  const value_type b,
983  const BlockVectorBase &W,
984  const value_type c,
985  const BlockVectorBase &X);
986 
991  operator*=(const value_type factor);
992 
997  operator/=(const value_type factor);
998 
1003  template <class BlockVector2>
1004  void
1005  scale(const BlockVector2 &v);
1006 
1010  template <class BlockVector2>
1011  void
1012  equ(const value_type a, const BlockVector2 &V);
1013 
1017  void
1018  equ(const value_type a,
1019  const BlockVectorBase &V,
1020  const value_type b,
1021  const BlockVectorBase &W);
1022 
1027  void
1028  update_ghost_values() const;
1029 
1034  std::size_t
1035  memory_consumption() const;
1036 
1037 protected:
1041  std::vector<VectorType> components;
1042 
1047  BlockIndices block_indices;
1048 
1052  template <typename N, bool C>
1053  friend class ::internal::BlockVectorIterators::Iterator;
1054 
1055  template <typename>
1056  friend class BlockVectorBase;
1057 };
1058 
1059 
1062 /*----------------------- Inline functions ----------------------------------*/
1063 
1064 
1065 #ifndef DOXYGEN
1066 namespace internal
1067 {
1068  namespace BlockVectorIterators
1069  {
1070  template <class BlockVectorType, bool Constness>
1071  inline Iterator<BlockVectorType, Constness>::Iterator(
1072  const Iterator<BlockVectorType, Constness> &c)
1073  : parent(c.parent)
1074  , global_index(c.global_index)
1075  , current_block(c.current_block)
1076  , index_within_block(c.index_within_block)
1077  , next_break_forward(c.next_break_forward)
1078  , next_break_backward(c.next_break_backward)
1079  {}
1080 
1081 
1082 
1083  template <class BlockVectorType, bool Constness>
1084  inline Iterator<BlockVectorType, Constness>::Iterator(
1085  const Iterator<BlockVectorType, !Constness> &c)
1086  : parent(c.parent)
1087  , global_index(c.global_index)
1088  , current_block(c.current_block)
1089  , index_within_block(c.index_within_block)
1090  , next_break_forward(c.next_break_forward)
1091  , next_break_backward(c.next_break_backward)
1092  {
1093  // Only permit copy-constructing const iterators from non-const
1094  // iterators, and not vice versa (i.e., Constness must always be
1095  // true).
1096  static_assert(Constness == true,
1097  "Constructing a non-const iterator from a const iterator "
1098  "does not make sense.");
1099  }
1100 
1101 
1102 
1103  template <class BlockVectorType, bool Constness>
1104  inline Iterator<BlockVectorType, Constness>::Iterator(
1105  BlockVector & parent,
1106  const size_type global_index,
1107  const size_type current_block,
1108  const size_type index_within_block,
1109  const size_type next_break_forward,
1110  const size_type next_break_backward)
1111  : parent(&parent)
1112  , global_index(global_index)
1113  , current_block(current_block)
1114  , index_within_block(index_within_block)
1115  , next_break_forward(next_break_forward)
1116  , next_break_backward(next_break_backward)
1117  {}
1118 
1119 
1120 
1121  template <class BlockVectorType, bool Constness>
1122  inline Iterator<BlockVectorType, Constness> &
1123  Iterator<BlockVectorType, Constness>::operator=(const Iterator &c)
1124  {
1125  parent = c.parent;
1126  global_index = c.global_index;
1127  index_within_block = c.index_within_block;
1128  current_block = c.current_block;
1129  next_break_forward = c.next_break_forward;
1130  next_break_backward = c.next_break_backward;
1131 
1132  return *this;
1133  }
1134 
1135 
1136 
1137  template <class BlockVectorType, bool Constness>
1138  inline typename Iterator<BlockVectorType, Constness>::dereference_type
1140  {
1141  return parent->block(current_block)(index_within_block);
1142  }
1143 
1144 
1145 
1146  template <class BlockVectorType, bool Constness>
1147  inline typename Iterator<BlockVectorType, Constness>::dereference_type
1148  Iterator<BlockVectorType, Constness>::
1149  operator[](const difference_type d) const
1150  {
1151  // if the index pointed to is
1152  // still within the block we
1153  // currently point into, then we
1154  // can save the computation of
1155  // the block
1156  if ((global_index + d >= next_break_backward) &&
1157  (global_index + d <= next_break_forward))
1158  return parent->block(current_block)(index_within_block + d);
1159 
1160  // if the index is not within the
1161  // block of the block vector into
1162  // which we presently point, then
1163  // there is no way: we have to
1164  // search for the block. this can
1165  // be done through the parent
1166  // class as well.
1167  return (*parent)(global_index + d);
1168  }
1169 
1170 
1171 
1172  template <class BlockVectorType, bool Constness>
1173  inline Iterator<BlockVectorType, Constness> &
1174  Iterator<BlockVectorType, Constness>::operator++()
1175  {
1176  move_forward();
1177  return *this;
1178  }
1179 
1180 
1181 
1182  template <class BlockVectorType, bool Constness>
1183  inline Iterator<BlockVectorType, Constness>
1184  Iterator<BlockVectorType, Constness>::operator++(int)
1185  {
1186  const Iterator old_value = *this;
1187  move_forward();
1188  return old_value;
1189  }
1190 
1191 
1192 
1193  template <class BlockVectorType, bool Constness>
1194  inline Iterator<BlockVectorType, Constness> &
1195  Iterator<BlockVectorType, Constness>::operator--()
1196  {
1197  move_backward();
1198  return *this;
1199  }
1200 
1201 
1202 
1203  template <class BlockVectorType, bool Constness>
1204  inline Iterator<BlockVectorType, Constness>
1205  Iterator<BlockVectorType, Constness>::operator--(int)
1206  {
1207  const Iterator old_value = *this;
1208  move_backward();
1209  return old_value;
1210  }
1211 
1212 
1213 
1214  template <class BlockVectorType, bool Constness>
1215  template <bool OtherConstness>
1216  inline bool
1217  Iterator<BlockVectorType, Constness>::
1218  operator==(const Iterator<BlockVectorType, OtherConstness> &i) const
1219  {
1220  Assert(parent == i.parent, ExcPointerToDifferentVectors());
1221 
1222  return (global_index == i.global_index);
1223  }
1224 
1225 
1226 
1227  template <class BlockVectorType, bool Constness>
1228  template <bool OtherConstness>
1229  inline bool
1230  Iterator<BlockVectorType, Constness>::
1231  operator!=(const Iterator<BlockVectorType, OtherConstness> &i) const
1232  {
1233  Assert(parent == i.parent, ExcPointerToDifferentVectors());
1234 
1235  return (global_index != i.global_index);
1236  }
1237 
1238 
1239 
1240  template <class BlockVectorType, bool Constness>
1241  template <bool OtherConstness>
1242  inline bool
1243  Iterator<BlockVectorType, Constness>::
1244  operator<(const Iterator<BlockVectorType, OtherConstness> &i) const
1245  {
1246  Assert(parent == i.parent, ExcPointerToDifferentVectors());
1247 
1248  return (global_index < i.global_index);
1249  }
1250 
1251 
1252 
1253  template <class BlockVectorType, bool Constness>
1254  template <bool OtherConstness>
1255  inline bool
1256  Iterator<BlockVectorType, Constness>::
1257  operator<=(const Iterator<BlockVectorType, OtherConstness> &i) const
1258  {
1259  Assert(parent == i.parent, ExcPointerToDifferentVectors());
1260 
1261  return (global_index <= i.global_index);
1262  }
1263 
1264 
1265 
1266  template <class BlockVectorType, bool Constness>
1267  template <bool OtherConstness>
1268  inline bool
1269  Iterator<BlockVectorType, Constness>::
1270  operator>(const Iterator<BlockVectorType, OtherConstness> &i) const
1271  {
1272  Assert(parent == i.parent, ExcPointerToDifferentVectors());
1273 
1274  return (global_index > i.global_index);
1275  }
1276 
1277 
1278 
1279  template <class BlockVectorType, bool Constness>
1280  template <bool OtherConstness>
1281  inline bool
1282  Iterator<BlockVectorType, Constness>::
1283  operator>=(const Iterator<BlockVectorType, OtherConstness> &i) const
1284  {
1285  Assert(parent == i.parent, ExcPointerToDifferentVectors());
1286 
1287  return (global_index >= i.global_index);
1288  }
1289 
1290 
1291 
1292  template <class BlockVectorType, bool Constness>
1293  template <bool OtherConstness>
1294  inline typename Iterator<BlockVectorType, Constness>::difference_type
1296  operator-(const Iterator<BlockVectorType, OtherConstness> &i) const
1297  {
1298  Assert(parent == i.parent, ExcPointerToDifferentVectors());
1299 
1300  return (static_cast<signed int>(global_index) -
1301  static_cast<signed int>(i.global_index));
1302  }
1303 
1304 
1305 
1306  template <class BlockVectorType, bool Constness>
1307  inline Iterator<BlockVectorType, Constness>
1309  operator+(const difference_type &d) const
1310  {
1311  // if the index pointed to is
1312  // still within the block we
1313  // currently point into, then we
1314  // can save the computation of
1315  // the block
1316  if ((global_index + d >= next_break_backward) &&
1317  (global_index + d <= next_break_forward))
1318  return Iterator(*parent,
1319  global_index + d,
1320  current_block,
1321  index_within_block + d,
1322  next_break_forward,
1323  next_break_backward);
1324  else
1325  // outside present block, so
1326  // have to seek new block
1327  // anyway
1328  return Iterator(*parent, global_index + d);
1329  }
1330 
1331 
1332 
1333  template <class BlockVectorType, bool Constness>
1334  inline Iterator<BlockVectorType, Constness>
1336  operator-(const difference_type &d) const
1337  {
1338  // if the index pointed to is
1339  // still within the block we
1340  // currently point into, then we
1341  // can save the computation of
1342  // the block
1343  if ((global_index - d >= next_break_backward) &&
1344  (global_index - d <= next_break_forward))
1345  return Iterator(*parent,
1346  global_index - d,
1347  current_block,
1348  index_within_block - d,
1349  next_break_forward,
1350  next_break_backward);
1351  else
1352  // outside present block, so
1353  // have to seek new block
1354  // anyway
1355  return Iterator(*parent, global_index - d);
1356  }
1357 
1358 
1359 
1360  template <class BlockVectorType, bool Constness>
1361  inline Iterator<BlockVectorType, Constness> &
1362  Iterator<BlockVectorType, Constness>::operator+=(const difference_type &d)
1363  {
1364  // if the index pointed to is
1365  // still within the block we
1366  // currently point into, then we
1367  // can save the computation of
1368  // the block
1369  if ((global_index + d >= next_break_backward) &&
1370  (global_index + d <= next_break_forward))
1371  {
1372  global_index += d;
1373  index_within_block += d;
1374  }
1375  else
1376  // outside present block, so
1377  // have to seek new block
1378  // anyway
1379  *this = Iterator(*parent, global_index + d);
1380 
1381  return *this;
1382  }
1383 
1384 
1385 
1386  template <class BlockVectorType, bool Constness>
1387  inline Iterator<BlockVectorType, Constness> &
1388  Iterator<BlockVectorType, Constness>::operator-=(const difference_type &d)
1389  {
1390  // if the index pointed to is
1391  // still within the block we
1392  // currently point into, then we
1393  // can save the computation of
1394  // the block
1395  if ((global_index - d >= next_break_backward) &&
1396  (global_index - d <= next_break_forward))
1397  {
1398  global_index -= d;
1399  index_within_block -= d;
1400  }
1401  else
1402  // outside present block, so
1403  // have to seek new block
1404  // anyway
1405  *this = Iterator(*parent, global_index - d);
1406 
1407  return *this;
1408  }
1409 
1410 
1411  template <class BlockVectorType, bool Constness>
1412  Iterator<BlockVectorType, Constness>::Iterator(BlockVector & parent,
1413  const size_type global_index)
1414  : parent(&parent)
1415  , global_index(global_index)
1416  {
1417  // find which block we are
1418  // in. for this, take into
1419  // account that it happens at
1420  // times that people want to
1421  // initialize iterators
1422  // past-the-end
1423  if (global_index < parent.size())
1424  {
1425  const std::pair<size_type, size_type> indices =
1426  parent.block_indices.global_to_local(global_index);
1427  current_block = indices.first;
1428  index_within_block = indices.second;
1429 
1430  next_break_backward =
1431  parent.block_indices.local_to_global(current_block, 0);
1432  next_break_forward =
1433  (parent.block_indices.local_to_global(current_block, 0) +
1434  parent.block_indices.block_size(current_block) - 1);
1435  }
1436  else
1437  // past the end. only have one
1438  // value for this
1439  {
1440  this->global_index = parent.size();
1441  current_block = parent.n_blocks();
1442  index_within_block = 0;
1443  next_break_backward = global_index;
1444  next_break_forward = numbers::invalid_size_type;
1445  };
1446  }
1447 
1448 
1449 
1450  template <class BlockVectorType, bool Constness>
1451  void
1452  Iterator<BlockVectorType, Constness>::move_forward()
1453  {
1454  if (global_index != next_break_forward)
1455  ++index_within_block;
1456  else
1457  {
1458  // ok, we traverse a boundary
1459  // between blocks:
1460  index_within_block = 0;
1461  ++current_block;
1462 
1463  // break backwards is now old
1464  // break forward
1465  next_break_backward = next_break_forward + 1;
1466 
1467  // compute new break forward
1468  if (current_block < parent->block_indices.size())
1469  next_break_forward +=
1470  parent->block_indices.block_size(current_block);
1471  else
1472  // if we are beyond the end,
1473  // then move the next
1474  // boundary arbitrarily far
1475  // away
1476  next_break_forward = numbers::invalid_size_type;
1477  };
1478 
1479  ++global_index;
1480  }
1481 
1482 
1483 
1484  template <class BlockVectorType, bool Constness>
1485  void
1486  Iterator<BlockVectorType, Constness>::move_backward()
1487  {
1488  if (global_index != next_break_backward)
1489  --index_within_block;
1490  else if (current_block != 0)
1491  {
1492  // ok, we traverse a boundary
1493  // between blocks:
1494  --current_block;
1495  index_within_block =
1496  parent->block_indices.block_size(current_block) - 1;
1497 
1498  // break forwards is now old
1499  // break backward
1500  next_break_forward = next_break_backward - 1;
1501 
1502  // compute new break forward
1503  next_break_backward -=
1504  parent->block_indices.block_size(current_block);
1505  }
1506  else
1507  // current block was 0, we now
1508  // get into unspecified terrain
1509  {
1510  --current_block;
1511  index_within_block = numbers::invalid_size_type;
1512  next_break_forward = 0;
1513  next_break_backward = 0;
1514  };
1515 
1516  --global_index;
1517  }
1518 
1519 
1520  } // namespace BlockVectorIterators
1521 
1522 } // namespace internal
1523 
1524 
1525 
1526 template <class VectorType>
1527 inline std::size_t
1529 {
1530  return block_indices.total_size();
1531 }
1532 
1533 
1534 
1535 template <class VectorType>
1536 inline IndexSet
1538 {
1539  IndexSet is(size());
1540 
1541  // copy index sets from blocks into the global one, shifted
1542  // by the appropriate amount for each block
1543  for (unsigned int b = 0; b < n_blocks(); ++b)
1544  {
1545  IndexSet x = block(b).locally_owned_elements();
1546  is.add_indices(x, block_indices.block_start(b));
1547  }
1548 
1549  is.compress();
1550 
1551  return is;
1552 }
1553 
1554 
1555 
1556 template <class VectorType>
1557 inline unsigned int
1559 {
1560  return block_indices.size();
1561 }
1562 
1563 
1564 template <class VectorType>
1566 BlockVectorBase<VectorType>::block(const unsigned int i)
1567 {
1568  Assert(i < n_blocks(), ExcIndexRange(i, 0, n_blocks()));
1569 
1570  return components[i];
1571 }
1572 
1573 
1574 
1575 template <class VectorType>
1576 inline const typename BlockVectorBase<VectorType>::BlockType &
1577 BlockVectorBase<VectorType>::block(const unsigned int i) const
1578 {
1579  Assert(i < n_blocks(), ExcIndexRange(i, 0, n_blocks()));
1580 
1581  return components[i];
1582 }
1583 
1584 
1585 
1586 template <class VectorType>
1587 inline const BlockIndices &
1589 {
1590  return block_indices;
1591 }
1592 
1593 
1594 template <class VectorType>
1595 inline void
1597 {
1598  std::vector<size_type> sizes(n_blocks());
1599 
1600  for (size_type i = 0; i < n_blocks(); ++i)
1601  sizes[i] = block(i).size();
1602 
1603  block_indices.reinit(sizes);
1604 }
1605 
1606 
1607 
1608 template <class VectorType>
1609 inline void
1611  ::VectorOperation::values operation)
1612 {
1613  for (unsigned int i = 0; i < n_blocks(); ++i)
1614  block(i).compress(operation);
1615 }
1616 
1617 
1618 
1619 template <class VectorType>
1622 {
1623  return iterator(*this, 0U);
1624 }
1625 
1626 
1627 
1628 template <class VectorType>
1631 {
1632  return const_iterator(*this, 0U);
1633 }
1634 
1635 
1636 template <class VectorType>
1639 {
1640  return iterator(*this, size());
1641 }
1642 
1643 
1644 
1645 template <class VectorType>
1648 {
1649  return const_iterator(*this, size());
1650 }
1651 
1652 
1653 template <class VectorType>
1654 inline bool
1655 BlockVectorBase<VectorType>::in_local_range(const size_type global_index) const
1656 {
1657  const std::pair<size_type, size_type> local_index =
1658  block_indices.global_to_local(global_index);
1659 
1660  return components[local_index.first].in_local_range(global_index);
1661 }
1662 
1663 
1664 template <class VectorType>
1665 bool
1667 {
1668  for (size_type i = 0; i < n_blocks(); ++i)
1669  if (components[i].all_zero() == false)
1670  return false;
1671 
1672  return true;
1673 }
1674 
1675 
1676 
1677 template <class VectorType>
1678 bool
1680 {
1681  for (size_type i = 0; i < n_blocks(); ++i)
1682  if (components[i].is_non_negative() == false)
1683  return false;
1684 
1685  return true;
1686 }
1687 
1688 
1689 
1690 template <class VectorType>
1691 typename BlockVectorBase<VectorType>::value_type BlockVectorBase<VectorType>::
1693 {
1694  Assert(n_blocks() == v.n_blocks(),
1695  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1696 
1697  value_type sum = 0.;
1698  for (size_type i = 0; i < n_blocks(); ++i)
1699  sum += components[i] * v.components[i];
1700 
1701  return sum;
1702 }
1703 
1704 
1705 template <class VectorType>
1708 {
1709  real_type sum = 0.;
1710  for (size_type i = 0; i < n_blocks(); ++i)
1711  sum += components[i].norm_sqr();
1712 
1713  return sum;
1714 }
1715 
1716 
1717 
1718 template <class VectorType>
1719 typename BlockVectorBase<VectorType>::value_type
1721 {
1722  value_type sum = 0.;
1723  // need to do static_cast as otherwise it won't work with
1724  // value_type=complex<T>
1725  for (size_type i = 0; i < n_blocks(); ++i)
1726  sum += components[i].mean_value() *
1728  components[i].size()));
1729 
1730  return sum / (typename numbers::NumberTraits<value_type>::real_type(size()));
1731 }
1732 
1733 
1734 
1735 template <class VectorType>
1738 {
1739  real_type sum = 0.;
1740  for (size_type i = 0; i < n_blocks(); ++i)
1741  sum += components[i].l1_norm();
1742 
1743  return sum;
1744 }
1745 
1746 
1747 
1748 template <class VectorType>
1751 {
1752  return std::sqrt(norm_sqr());
1753 }
1754 
1755 
1756 
1757 template <class VectorType>
1760 {
1761  real_type sum = 0.;
1762  for (size_type i = 0; i < n_blocks(); ++i)
1763  {
1764  value_type newval = components[i].linfty_norm();
1765  if (sum < newval)
1766  sum = newval;
1767  }
1768  return sum;
1769 }
1770 
1771 
1772 
1773 template <class VectorType>
1774 typename BlockVectorBase<VectorType>::value_type
1776  const typename BlockVectorBase<VectorType>::value_type a,
1777  const BlockVectorBase<VectorType> & V,
1778  const BlockVectorBase<VectorType> & W)
1779 {
1780  AssertDimension(n_blocks(), V.n_blocks());
1781  AssertDimension(n_blocks(), W.n_blocks());
1782 
1783  value_type sum = 0.;
1784  for (size_type i = 0; i < n_blocks(); ++i)
1785  sum += components[i].add_and_dot(a, V.components[i], W.components[i]);
1786 
1787  return sum;
1788 }
1789 
1790 
1791 
1792 template <class VectorType>
1795 {
1796  Assert(n_blocks() == v.n_blocks(),
1797  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1798 
1799  for (size_type i = 0; i < n_blocks(); ++i)
1800  {
1801  components[i] += v.components[i];
1802  }
1803 
1804  return *this;
1805 }
1806 
1807 
1808 
1809 template <class VectorType>
1812 {
1813  Assert(n_blocks() == v.n_blocks(),
1814  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1815 
1816  for (size_type i = 0; i < n_blocks(); ++i)
1817  {
1818  components[i] -= v.components[i];
1819  }
1820  return *this;
1821 }
1822 
1823 
1824 
1825 template <class VectorType>
1826 template <typename Number>
1827 inline void
1828 BlockVectorBase<VectorType>::add(const std::vector<size_type> &indices,
1829  const std::vector<Number> & values)
1830 {
1831  Assert(indices.size() == values.size(),
1832  ExcDimensionMismatch(indices.size(), values.size()));
1833  add(indices.size(), indices.data(), values.data());
1834 }
1835 
1836 
1837 
1838 template <class VectorType>
1839 template <typename Number>
1840 inline void
1841 BlockVectorBase<VectorType>::add(const std::vector<size_type> &indices,
1842  const Vector<Number> & values)
1843 {
1844  Assert(indices.size() == values.size(),
1845  ExcDimensionMismatch(indices.size(), values.size()));
1846  const size_type n_indices = indices.size();
1847  for (size_type i = 0; i < n_indices; ++i)
1848  (*this)(indices[i]) += values(i);
1849 }
1850 
1851 
1852 
1853 template <class VectorType>
1854 template <typename Number>
1855 inline void
1856 BlockVectorBase<VectorType>::add(const size_type n_indices,
1857  const size_type *indices,
1858  const Number * values)
1859 {
1860  for (size_type i = 0; i < n_indices; ++i)
1861  (*this)(indices[i]) += values[i];
1862 }
1863 
1864 
1865 
1866 template <class VectorType>
1867 void
1868 BlockVectorBase<VectorType>::add(const value_type a)
1869 {
1870  AssertIsFinite(a);
1871 
1872  for (size_type i = 0; i < n_blocks(); ++i)
1873  {
1874  components[i].add(a);
1875  }
1876 }
1877 
1878 
1879 
1880 template <class VectorType>
1881 void
1882 BlockVectorBase<VectorType>::add(const value_type a,
1883  const BlockVectorBase<VectorType> &v)
1884 {
1885  AssertIsFinite(a);
1886 
1887  Assert(n_blocks() == v.n_blocks(),
1888  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1889 
1890  for (size_type i = 0; i < n_blocks(); ++i)
1891  {
1892  components[i].add(a, v.components[i]);
1893  }
1894 }
1895 
1896 
1897 
1898 template <class VectorType>
1899 void
1900 BlockVectorBase<VectorType>::add(const value_type a,
1901  const BlockVectorBase<VectorType> &v,
1902  const value_type b,
1903  const BlockVectorBase<VectorType> &w)
1904 {
1905  AssertIsFinite(a);
1906  AssertIsFinite(b);
1907 
1908  Assert(n_blocks() == v.n_blocks(),
1909  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1910  Assert(n_blocks() == w.n_blocks(),
1911  ExcDimensionMismatch(n_blocks(), w.n_blocks()));
1912 
1913 
1914  for (size_type i = 0; i < n_blocks(); ++i)
1915  {
1916  components[i].add(a, v.components[i], b, w.components[i]);
1917  }
1918 }
1919 
1920 
1921 
1922 template <class VectorType>
1923 void
1924 BlockVectorBase<VectorType>::sadd(const value_type x,
1925  const BlockVectorBase<VectorType> &v)
1926 {
1927  AssertIsFinite(x);
1928 
1929  Assert(n_blocks() == v.n_blocks(),
1930  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1931 
1932  for (size_type i = 0; i < n_blocks(); ++i)
1933  {
1934  components[i].sadd(x, v.components[i]);
1935  }
1936 }
1937 
1938 
1939 
1940 template <class VectorType>
1941 void
1942 BlockVectorBase<VectorType>::sadd(const value_type x,
1943  const value_type a,
1944  const BlockVectorBase<VectorType> &v)
1945 {
1946  AssertIsFinite(x);
1947  AssertIsFinite(a);
1948 
1949  Assert(n_blocks() == v.n_blocks(),
1950  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1951 
1952  for (size_type i = 0; i < n_blocks(); ++i)
1953  {
1954  components[i].sadd(x, a, v.components[i]);
1955  }
1956 }
1957 
1958 
1959 
1960 template <class VectorType>
1961 void
1962 BlockVectorBase<VectorType>::sadd(const value_type x,
1963  const value_type a,
1964  const BlockVectorBase<VectorType> &v,
1965  const value_type b,
1966  const BlockVectorBase<VectorType> &w)
1967 {
1968  AssertIsFinite(x);
1969  AssertIsFinite(a);
1970  AssertIsFinite(b);
1971 
1972  Assert(n_blocks() == v.n_blocks(),
1973  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1974  Assert(n_blocks() == w.n_blocks(),
1975  ExcDimensionMismatch(n_blocks(), w.n_blocks()));
1976 
1977  for (size_type i = 0; i < n_blocks(); ++i)
1978  {
1979  components[i].sadd(x, a, v.components[i], b, w.components[i]);
1980  }
1981 }
1982 
1983 
1984 
1985 template <class VectorType>
1986 void
1987 BlockVectorBase<VectorType>::sadd(const value_type x,
1988  const value_type a,
1989  const BlockVectorBase<VectorType> &v,
1990  const value_type b,
1991  const BlockVectorBase<VectorType> &w,
1992  const value_type c,
1993  const BlockVectorBase<VectorType> &y)
1994 {
1995  AssertIsFinite(x);
1996  AssertIsFinite(a);
1997  AssertIsFinite(b);
1998  AssertIsFinite(c);
1999 
2000  Assert(n_blocks() == v.n_blocks(),
2001  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
2002  Assert(n_blocks() == w.n_blocks(),
2003  ExcDimensionMismatch(n_blocks(), w.n_blocks()));
2004  Assert(n_blocks() == y.n_blocks(),
2005  ExcDimensionMismatch(n_blocks(), y.n_blocks()));
2006 
2007  for (size_type i = 0; i < n_blocks(); ++i)
2008  {
2009  components[i].sadd(
2010  x, a, v.components[i], b, w.components[i], c, y.components[i]);
2011  }
2012 }
2013 
2014 
2015 
2016 template <class VectorType>
2017 template <class BlockVector2>
2018 void
2019 BlockVectorBase<VectorType>::scale(const BlockVector2 &v)
2020 {
2021  Assert(n_blocks() == v.n_blocks(),
2022  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
2023  for (size_type i = 0; i < n_blocks(); ++i)
2024  components[i].scale(v.block(i));
2025 }
2026 
2027 
2028 
2029 template <class VectorType>
2030 void
2031 BlockVectorBase<VectorType>::equ(const value_type a,
2032  const BlockVectorBase<VectorType> &v,
2033  const value_type b,
2034  const BlockVectorBase<VectorType> &w)
2035 {
2036  AssertIsFinite(a);
2037  AssertIsFinite(b);
2038 
2039  Assert(n_blocks() == v.n_blocks(),
2040  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
2041  Assert(n_blocks() == w.n_blocks(),
2042  ExcDimensionMismatch(n_blocks(), w.n_blocks()));
2043 
2044  for (size_type i = 0; i < n_blocks(); ++i)
2045  {
2046  components[i].equ(a, v.components[i], b, w.components[i]);
2047  }
2048 }
2049 
2050 
2051 
2052 template <class VectorType>
2053 std::size_t
2055 {
2056  return (MemoryConsumption::memory_consumption(this->block_indices) +
2057  MemoryConsumption::memory_consumption(this->components));
2058 }
2059 
2060 
2061 
2062 template <class VectorType>
2063 template <class BlockVector2>
2064 void
2065 BlockVectorBase<VectorType>::equ(const value_type a, const BlockVector2 &v)
2066 {
2067  AssertIsFinite(a);
2068 
2069  Assert(n_blocks() == v.n_blocks(),
2070  ExcDimensionMismatch(n_blocks(), v.n_blocks()));
2071 
2072  for (size_type i = 0; i < n_blocks(); ++i)
2073  components[i].equ(a, v.components[i]);
2074 }
2075 
2076 
2077 
2078 template <class VectorType>
2079 void
2081 {
2082  for (size_type i = 0; i < n_blocks(); ++i)
2083  block(i).update_ghost_values();
2084 }
2085 
2086 
2087 
2088 template <class VectorType>
2090 BlockVectorBase<VectorType>::operator=(const value_type s)
2091 {
2092  AssertIsFinite(s);
2093 
2094  for (size_type i = 0; i < n_blocks(); ++i)
2095  components[i] = s;
2096 
2097  return *this;
2098 }
2099 
2100 
2101 template <class VectorType>
2104 {
2105  AssertDimension(n_blocks(), v.n_blocks());
2106 
2107  for (size_type i = 0; i < n_blocks(); ++i)
2108  components[i] = v.components[i];
2109 
2110  return *this;
2111 }
2112 
2113 
2114 template <class VectorType>
2115 template <class VectorType2>
2118 {
2119  AssertDimension(n_blocks(), v.n_blocks());
2120 
2121  for (size_type i = 0; i < n_blocks(); ++i)
2122  components[i] = v.components[i];
2123 
2124  return *this;
2125 }
2126 
2127 
2128 
2129 template <class VectorType>
2131 BlockVectorBase<VectorType>::operator=(const VectorType &v)
2132 {
2133  Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
2134 
2135  size_type index_v = 0;
2136  for (size_type b = 0; b < n_blocks(); ++b)
2137  for (size_type i = 0; i < block(b).size(); ++i, ++index_v)
2138  block(b)(i) = v(index_v);
2139 
2140  return *this;
2141 }
2142 
2143 
2144 
2145 template <class VectorType>
2146 template <class VectorType2>
2147 inline bool
2150 {
2151  Assert(block_indices == v.block_indices, ExcDifferentBlockIndices());
2152 
2153  for (size_type i = 0; i < n_blocks(); ++i)
2154  if (!(components[i] == v.components[i]))
2155  return false;
2156 
2157  return true;
2158 }
2159 
2160 
2161 
2162 template <class VectorType>
2164 BlockVectorBase<VectorType>::operator*=(const value_type factor)
2165 {
2166  AssertIsFinite(factor);
2167 
2168  for (size_type i = 0; i < n_blocks(); ++i)
2169  components[i] *= factor;
2170 
2171  return *this;
2172 }
2173 
2174 
2175 
2176 template <class VectorType>
2178 BlockVectorBase<VectorType>::operator/=(const value_type factor)
2179 {
2180  AssertIsFinite(factor);
2181  Assert(factor != 0., ExcDivideByZero());
2182 
2183  for (size_type i = 0; i < n_blocks(); ++i)
2184  components[i] /= factor;
2185 
2186  return *this;
2187 }
2188 
2189 
2190 template <class VectorType>
2191 inline typename BlockVectorBase<VectorType>::value_type
2192 BlockVectorBase<VectorType>::operator()(const size_type i) const
2193 {
2194  const std::pair<unsigned int, size_type> local_index =
2195  block_indices.global_to_local(i);
2196  return components[local_index.first](local_index.second);
2197 }
2198 
2199 
2200 
2201 template <class VectorType>
2202 inline typename BlockVectorBase<VectorType>::reference
2203 BlockVectorBase<VectorType>::operator()(const size_type i)
2204 {
2205  const std::pair<unsigned int, size_type> local_index =
2206  block_indices.global_to_local(i);
2207  return components[local_index.first](local_index.second);
2208 }
2209 
2210 
2211 
2212 template <class VectorType>
2213 inline typename BlockVectorBase<VectorType>::value_type
2214  BlockVectorBase<VectorType>::operator[](const size_type i) const
2215 {
2216  return operator()(i);
2217 }
2218 
2219 
2220 
2221 template <class VectorType>
2222 inline typename BlockVectorBase<VectorType>::reference
2223  BlockVectorBase<VectorType>::operator[](const size_type i)
2224 {
2225  return operator()(i);
2226 }
2227 
2228 
2229 
2230 template <typename VectorType>
2231 template <typename OtherNumber>
2232 inline void
2234  const std::vector<size_type> &indices,
2235  std::vector<OtherNumber> & values) const
2236 {
2237  for (size_type i = 0; i < indices.size(); ++i)
2238  values[i] = operator()(indices[i]);
2239 }
2240 
2241 
2242 
2243 template <typename VectorType>
2244 template <typename ForwardIterator, typename OutputIterator>
2245 inline void
2247  ForwardIterator indices_begin,
2248  const ForwardIterator indices_end,
2249  OutputIterator values_begin) const
2250 {
2251  while (indices_begin != indices_end)
2252  {
2253  *values_begin = operator()(*indices_begin);
2254  indices_begin++;
2255  values_begin++;
2256  }
2257 }
2258 
2259 #endif // DOXYGEN
2260 
2261 DEAL_II_NAMESPACE_CLOSE
2262 
2263 #endif
const types::global_dof_index invalid_size_type
Definition: types.h:182
static yes_type check_for_block_vector(const BlockVectorBase< T > *)
std::size_t size() const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1366
bool operator==(const BlockVectorBase< VectorType2 > &v) const
void add(const std::vector< size_type > &indices, const std::vector< Number > &values)
void compress(::VectorOperation::values operation)
real_type linfty_norm() const
typename Types< BlockVectorType, Constness >::value_type value_type
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition: index_set.h:1652
real_type norm_sqr() const
void collect_sizes()
STL namespace.
unsigned int n_blocks() const
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
static::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
static::ExceptionBase & ExcDivideByZero()
value_type operator[](const size_type i) const
unsigned long long int global_dof_index
Definition: types.h:72
BlockVectorBase & operator/=(const value_type factor)
value_type add_and_dot(const value_type a, const BlockVectorBase &V, const BlockVectorBase &W)
void scale(const BlockVector2 &v)
bool is_non_negative() const
std::random_access_iterator_tag iterator_category
value_type operator()(const size_type i) const
BlockIndices block_indices
size_type block_start(const unsigned int i) const
bool in_local_range(const size_type global_index) const
#define Assert(cond, exc)
Definition: exceptions.h:1227
void update_ghost_values() const
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
const BlockIndices & get_block_indices() const
void reinit(const unsigned int n_blocks, const size_type n_elements_per_block)
#define DeclExceptionMsg(Exception, defaulttext)
Definition: exceptions.h:397
size_type total_size() const
value_type mean_value() const
bool all_zero() const
static::ExceptionBase & ExcDifferentBlockIndices()
void compress() const
Definition: index_set.h:1619
static const bool value
std::pair< unsigned int, size_type > global_to_local(const size_type i) const
BlockVectorBase & operator+=(const BlockVectorBase &V)
std::vector< VectorType > components
size_type block_size(const unsigned int i) const
BlockVectorBase & operator*=(const value_type factor)
void sadd(const value_type s, const BlockVectorBase &V)
BlockVectorBase & operator-=(const BlockVectorBase &V)
typename BlockType::real_type real_type
iterator end()
value_type operator*(const BlockVectorBase &V) const
real_type l2_norm() const
IndexSet locally_owned_elements() const
unsigned int size() const
BlockType & block(const unsigned int i)
size_type local_to_global(const unsigned int block, const size_type index) const
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
iterator begin()
BlockVectorBase & operator=(const value_type s)
void extract_subvector_to(const std::vector< size_type > &indices, std::vector< OtherNumber > &values) const
#define AssertIsFinite(number)
Definition: exceptions.h:1428
real_type l1_norm() const
void equ(const value_type a, const BlockVector2 &V)
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
std::size_t memory_consumption() const
typename BaseClass::value_type value_type
Definition: block_vector.h:84