deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
block_vector_base.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2004 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_block_vector_base_h
14#define dealii_block_vector_base_h
15
16
17#include <deal.II/base/config.h>
18
22
26#include <deal.II/lac/vector.h>
28
29#include <cmath>
30#include <cstddef>
31#include <iterator>
32#include <type_traits>
33#include <vector>
34
36
37
43namespace internal
44{
45 template <typename T>
46 using has_block_t = decltype(std::declval<const T>().block(0));
47
48 template <typename T>
49 constexpr bool has_block = internal::is_supported_operation<has_block_t, T>;
50
51 template <typename T>
52 using has_n_blocks_t = decltype(std::declval<const T>().n_blocks());
53
54 template <typename T>
55 constexpr bool has_n_blocks =
56 internal::is_supported_operation<has_n_blocks_t, T>;
57
58 template <typename T>
59 constexpr bool is_block_vector = has_block<T> && has_n_blocks<T>;
60} // namespace internal
61
76template <typename VectorType>
78{
79public:
85 static const bool value = internal::is_block_vector<VectorType>;
86};
87
88
89// instantiation of the static member
90template <typename VectorType>
92
93
94
95namespace internal
96{
100 namespace BlockVectorIterators
101 {
117 template <typename BlockVectorType, bool Constness>
119 {
120 public:
125
132 std::conditional_t<Constness,
133 const typename BlockVectorType::value_type,
134 typename BlockVectorType::value_type>;
135
149 using iterator_category = std::random_access_iterator_tag;
150 using difference_type = std::ptrdiff_t;
151 using reference = typename BlockVectorType::reference;
153
155 std::conditional_t<Constness,
157 typename BlockVectorType::BlockType::reference>;
158
164 std::conditional_t<Constness, const BlockVectorType, BlockVectorType>;
165
175
184
185
190
191 private:
202
203 public:
207 Iterator &
209
216 operator*() const;
217
224
229 Iterator &
231
239
244 Iterator &
246
254
259 template <bool OtherConstness>
260 bool
262
267 template <bool OtherConstness>
268 bool
270
276 template <bool OtherConstness>
277 bool
279
283 template <bool OtherConstness>
284 bool
286
290 template <bool OtherConstness>
291 bool
293
297 template <bool OtherConstness>
298 bool
300
304 template <bool OtherConstness>
307
313 operator+(const difference_type &d) const;
314
320 operator-(const difference_type &d) const;
321
326 Iterator &
328
333 Iterator &
335
346 "Your program tried to compare iterators pointing to "
347 "different block vectors. There is no reasonable way "
348 "to do this.");
349
351 private:
358
363
368 unsigned int current_block;
370
379
383 void
385
389 void
391
392 // Mark all other instances of this template as friends.
393 template <typename, bool>
394 friend class Iterator;
395 };
396 } // namespace BlockVectorIterators
397} // namespace internal
398
399
437template <typename VectorType>
438class BlockVectorBase : public ReadVector<typename VectorType::value_type>
439{
440public:
444 using BlockType = VectorType;
445
446 /*
447 * Declare standard types used in
448 * all containers. These types
449 * parallel those in the
450 * <tt>C++</tt> standard
451 * libraries
452 * <tt>std::vector<...></tt>
453 * class. This includes iterator
454 * types.
455 */
456 using value_type = typename BlockType::value_type;
458 using const_pointer = const value_type *;
459 using iterator =
463 using reference = typename BlockType::reference;
464 using const_reference = typename BlockType::const_reference;
466
476 using real_type = typename BlockType::real_type;
477
481 BlockVectorBase() = default;
482
486 BlockVectorBase(const BlockVectorBase & /*V*/) = default;
487
493 BlockVectorBase(BlockVectorBase && /*V*/) noexcept = default;
494
501 void
503
514 void
515 compress(VectorOperation::values operation);
516
520 BlockType &
521 block(const unsigned int i);
522
526 const BlockType &
527 block(const unsigned int i) const;
528
534 const BlockIndices &
536
540 unsigned int
541 n_blocks() const;
542
547 virtual size_type
548 size() const override;
549
555 std::size_t
557
576
582
588 begin() const;
589
595
601 end() const;
602
607 operator()(const size_type i) const;
608
613 operator()(const size_type i);
614
621 operator[](const size_type i) const;
622
629 operator[](const size_type i);
630
646 template <typename OtherNumber>
647 void
648 extract_subvector_to(const std::vector<size_type> &indices,
649 std::vector<OtherNumber> &values) const;
650
651 virtual void
652 extract_subvector_to(const ArrayView<const types::global_dof_index> &indices,
653 const ArrayView<value_type> &entries) const override;
654
682 template <typename ForwardIterator, typename OutputIterator>
683 void
684 extract_subvector_to(ForwardIterator indices_begin,
685 const ForwardIterator indices_end,
686 OutputIterator values_begin) const;
687
693 operator=(const value_type s);
694
699 operator=(const BlockVectorBase &V);
700
707 operator=(BlockVectorBase && /*V*/) = default; // NOLINT
708
712 template <typename VectorType2>
714 operator=(const BlockVectorBase<VectorType2> &V);
715
720 operator=(const VectorType &v);
721
726 template <typename VectorType2>
727 bool
728 operator==(const BlockVectorBase<VectorType2> &v) const;
729
734 operator*(const BlockVectorBase &V) const;
735
740 norm_sqr() const;
741
746 mean_value() const;
747
752 l1_norm() const;
753
759 l2_norm() const;
760
766 linfty_norm() const;
767
792 const BlockVectorBase &V,
793 const BlockVectorBase &W);
794
799 bool
800 in_local_range(const size_type global_index) const;
801
807 bool
808 all_zero() const;
809
815 bool
817
822 operator+=(const BlockVectorBase &V);
823
828 operator-=(const BlockVectorBase &V);
829
830
835 template <typename Number>
836 void
837 add(const std::vector<size_type> &indices, const std::vector<Number> &values);
838
843 template <typename Number>
844 void
845 add(const std::vector<size_type> &indices, const Vector<Number> &values);
846
852 template <typename Number>
853 void
854 add(const size_type n_elements,
855 const size_type *indices,
856 const Number *values);
857
862 void
863 add(const value_type s);
864
868 void
869 add(const value_type a, const BlockVectorBase &V);
870
874 void
876 const BlockVectorBase &V,
877 const value_type b,
878 const BlockVectorBase &W);
879
883 void
884 sadd(const value_type s, const BlockVectorBase &V);
885
889 void
890 sadd(const value_type s, const value_type a, const BlockVectorBase &V);
891
895 void
897 const value_type a,
898 const BlockVectorBase &V,
899 const value_type b,
900 const BlockVectorBase &W);
901
905 void
907 const value_type a,
908 const BlockVectorBase &V,
909 const value_type b,
910 const BlockVectorBase &W,
911 const value_type c,
912 const BlockVectorBase &X);
913
918 operator*=(const value_type factor);
919
924 operator/=(const value_type factor);
925
930 template <class BlockVector2>
931 void
932 scale(const BlockVector2 &v);
933
937 template <class BlockVector2>
938 void
939 equ(const value_type a, const BlockVector2 &V);
940
945 void
947
955
960 std::size_t
962
963protected:
967 std::vector<VectorType> components;
968
974
975 // Make the iterator class a friend.
976 template <typename N, bool C>
977 friend class ::internal::BlockVectorIterators::Iterator;
978
979 template <typename>
980 friend class BlockVectorBase;
981};
982
983
986/*----------------------- Inline functions ----------------------------------*/
987
988
989#ifndef DOXYGEN
990namespace internal
991{
992 namespace BlockVectorIterators
993 {
994 template <typename BlockVectorType, bool Constness>
995 inline Iterator<BlockVectorType, Constness>::Iterator(
996 const Iterator<BlockVectorType, Constness> &c)
997 : parent(c.parent)
998 , global_index(c.global_index)
999 , current_block(c.current_block)
1000 , index_within_block(c.index_within_block)
1001 , next_break_forward(c.next_break_forward)
1002 , next_break_backward(c.next_break_backward)
1003 {}
1004
1005
1006
1007 template <typename BlockVectorType, bool Constness>
1008 inline Iterator<BlockVectorType, Constness>::Iterator(
1009 const Iterator<BlockVectorType, !Constness> &c)
1010 : parent(c.parent)
1011 , global_index(c.global_index)
1012 , current_block(c.current_block)
1013 , index_within_block(c.index_within_block)
1014 , next_break_forward(c.next_break_forward)
1015 , next_break_backward(c.next_break_backward)
1016 {
1017 // Only permit copy-constructing const iterators from non-const
1018 // iterators, and not vice versa (i.e., Constness must always be
1019 // true).
1020 static_assert(Constness == true,
1021 "Constructing a non-const iterator from a const iterator "
1022 "does not make sense.");
1023 }
1024
1025
1026
1027 template <typename BlockVectorType, bool Constness>
1028 inline Iterator<BlockVectorType, Constness>::Iterator(
1029 BlockVector &parent,
1030 const size_type global_index,
1031 const size_type current_block,
1032 const size_type index_within_block,
1033 const size_type next_break_forward,
1034 const size_type next_break_backward)
1035 : parent(&parent)
1036 , global_index(global_index)
1037 , current_block(current_block)
1038 , index_within_block(index_within_block)
1039 , next_break_forward(next_break_forward)
1040 , next_break_backward(next_break_backward)
1041 {}
1042
1043
1044
1045 template <typename BlockVectorType, bool Constness>
1046 inline Iterator<BlockVectorType, Constness> &
1047 Iterator<BlockVectorType, Constness>::operator=(const Iterator &c) =
1048 default;
1049
1050
1051
1052 template <typename BlockVectorType, bool Constness>
1053 inline typename Iterator<BlockVectorType, Constness>::dereference_type
1054 Iterator<BlockVectorType, Constness>::operator*() const
1055 {
1056 return parent->block(current_block)(index_within_block);
1057 }
1058
1059
1060
1061 template <typename BlockVectorType, bool Constness>
1062 inline typename Iterator<BlockVectorType, Constness>::dereference_type
1063 Iterator<BlockVectorType, Constness>::operator[](
1064 const difference_type d) const
1065 {
1066 // if the index pointed to is
1067 // still within the block we
1068 // currently point into, then we
1069 // can save the computation of
1070 // the block
1071 if ((global_index + d >= next_break_backward) &&
1072 (global_index + d <= next_break_forward))
1073 return parent->block(current_block)(index_within_block + d);
1074
1075 // if the index is not within the
1076 // block of the block vector into
1077 // which we presently point, then
1078 // there is no way: we have to
1079 // search for the block. this can
1080 // be done through the parent
1081 // class as well.
1082 return (*parent)(global_index + d);
1083 }
1084
1085
1086
1087 template <typename BlockVectorType, bool Constness>
1088 inline Iterator<BlockVectorType, Constness> &
1089 Iterator<BlockVectorType, Constness>::operator++()
1090 {
1091 move_forward();
1092 return *this;
1093 }
1094
1095
1096
1097 template <typename BlockVectorType, bool Constness>
1098 inline Iterator<BlockVectorType, Constness>
1099 Iterator<BlockVectorType, Constness>::operator++(int)
1100 {
1101 const Iterator old_value = *this;
1102 move_forward();
1103 return old_value;
1104 }
1105
1106
1107
1108 template <typename BlockVectorType, bool Constness>
1109 inline Iterator<BlockVectorType, Constness> &
1110 Iterator<BlockVectorType, Constness>::operator--()
1111 {
1112 move_backward();
1113 return *this;
1114 }
1115
1116
1117
1118 template <typename BlockVectorType, bool Constness>
1119 inline Iterator<BlockVectorType, Constness>
1120 Iterator<BlockVectorType, Constness>::operator--(int)
1121 {
1122 const Iterator old_value = *this;
1123 move_backward();
1124 return old_value;
1125 }
1126
1127
1128
1129 template <typename BlockVectorType, bool Constness>
1130 template <bool OtherConstness>
1131 inline bool
1132 Iterator<BlockVectorType, Constness>::operator==(
1133 const Iterator<BlockVectorType, OtherConstness> &i) const
1134 {
1135 Assert(parent == i.parent, ExcPointerToDifferentVectors());
1136
1137 return (global_index == i.global_index);
1138 }
1139
1140
1141
1142 template <typename BlockVectorType, bool Constness>
1143 template <bool OtherConstness>
1144 inline bool
1145 Iterator<BlockVectorType, Constness>::operator!=(
1146 const Iterator<BlockVectorType, OtherConstness> &i) const
1147 {
1148 Assert(parent == i.parent, ExcPointerToDifferentVectors());
1149
1150 return (global_index != i.global_index);
1151 }
1152
1153
1154
1155 template <typename BlockVectorType, bool Constness>
1156 template <bool OtherConstness>
1157 inline bool
1158 Iterator<BlockVectorType, Constness>::operator<(
1159 const Iterator<BlockVectorType, OtherConstness> &i) const
1160 {
1161 Assert(parent == i.parent, ExcPointerToDifferentVectors());
1162
1163 return (global_index < i.global_index);
1164 }
1165
1166
1167
1168 template <typename BlockVectorType, bool Constness>
1169 template <bool OtherConstness>
1170 inline bool
1171 Iterator<BlockVectorType, Constness>::operator<=(
1172 const Iterator<BlockVectorType, OtherConstness> &i) const
1173 {
1174 Assert(parent == i.parent, ExcPointerToDifferentVectors());
1175
1176 return (global_index <= i.global_index);
1177 }
1178
1179
1180
1181 template <typename BlockVectorType, bool Constness>
1182 template <bool OtherConstness>
1183 inline bool
1184 Iterator<BlockVectorType, Constness>::operator>(
1185 const Iterator<BlockVectorType, OtherConstness> &i) const
1186 {
1187 Assert(parent == i.parent, ExcPointerToDifferentVectors());
1188
1189 return (global_index > i.global_index);
1190 }
1191
1192
1193
1194 template <typename BlockVectorType, bool Constness>
1195 template <bool OtherConstness>
1196 inline bool
1197 Iterator<BlockVectorType, Constness>::operator>=(
1198 const Iterator<BlockVectorType, OtherConstness> &i) const
1199 {
1200 Assert(parent == i.parent, ExcPointerToDifferentVectors());
1201
1202 return (global_index >= i.global_index);
1203 }
1204
1205
1206
1207 template <typename BlockVectorType, bool Constness>
1208 template <bool OtherConstness>
1209 inline typename Iterator<BlockVectorType, Constness>::difference_type
1210 Iterator<BlockVectorType, Constness>::operator-(
1211 const Iterator<BlockVectorType, OtherConstness> &i) const
1212 {
1213 Assert(parent == i.parent, ExcPointerToDifferentVectors());
1214
1215 return (static_cast<signed int>(global_index) -
1216 static_cast<signed int>(i.global_index));
1217 }
1218
1219
1220
1221 template <typename BlockVectorType, bool Constness>
1222 inline Iterator<BlockVectorType, Constness>
1223 Iterator<BlockVectorType, Constness>::operator+(
1224 const difference_type &d) const
1225 {
1226 // if the index pointed to is
1227 // still within the block we
1228 // currently point into, then we
1229 // can save the computation of
1230 // the block
1231 if ((global_index + d >= next_break_backward) &&
1232 (global_index + d <= next_break_forward))
1233 return Iterator(*parent,
1234 global_index + d,
1235 current_block,
1236 index_within_block + d,
1237 next_break_forward,
1238 next_break_backward);
1239 else
1240 // outside present block, so
1241 // have to seek new block
1242 // anyway
1243 return Iterator(*parent, global_index + d);
1244 }
1245
1246
1247
1248 template <typename BlockVectorType, bool Constness>
1249 inline Iterator<BlockVectorType, Constness>
1250 Iterator<BlockVectorType, Constness>::operator-(
1251 const difference_type &d) const
1252 {
1253 // if the index pointed to is
1254 // still within the block we
1255 // currently point into, then we
1256 // can save the computation of
1257 // the block
1258 if ((global_index - d >= next_break_backward) &&
1259 (global_index - d <= next_break_forward))
1260 return Iterator(*parent,
1261 global_index - d,
1262 current_block,
1263 index_within_block - d,
1264 next_break_forward,
1265 next_break_backward);
1266 else
1267 // outside present block, so
1268 // have to seek new block
1269 // anyway
1270 return Iterator(*parent, global_index - d);
1271 }
1272
1273
1274
1275 template <typename BlockVectorType, bool Constness>
1276 inline Iterator<BlockVectorType, Constness> &
1277 Iterator<BlockVectorType, Constness>::operator+=(const difference_type &d)
1278 {
1279 // if the index pointed to is
1280 // still within the block we
1281 // currently point into, then we
1282 // can save the computation of
1283 // the block
1284 if ((global_index + d >= next_break_backward) &&
1285 (global_index + d <= next_break_forward))
1286 {
1287 global_index += d;
1288 index_within_block += d;
1289 }
1290 else
1291 // outside present block, so
1292 // have to seek new block
1293 // anyway
1294 *this = Iterator(*parent, global_index + d);
1295
1296 return *this;
1297 }
1298
1299
1300
1301 template <typename BlockVectorType, bool Constness>
1302 inline Iterator<BlockVectorType, Constness> &
1303 Iterator<BlockVectorType, Constness>::operator-=(const difference_type &d)
1304 {
1305 // if the index pointed to is
1306 // still within the block we
1307 // currently point into, then we
1308 // can save the computation of
1309 // the block
1310 if ((global_index - d >= next_break_backward) &&
1311 (global_index - d <= next_break_forward))
1312 {
1313 global_index -= d;
1314 index_within_block -= d;
1315 }
1316 else
1317 // outside present block, so
1318 // have to seek new block
1319 // anyway
1320 *this = Iterator(*parent, global_index - d);
1321
1322 return *this;
1323 }
1324
1325
1326 template <typename BlockVectorType, bool Constness>
1327 Iterator<BlockVectorType, Constness>::Iterator(BlockVector &parent,
1328 const size_type global_index)
1329 : parent(&parent)
1330 , global_index(global_index)
1331 {
1332 // find which block we are
1333 // in. for this, take into
1334 // account that it happens at
1335 // times that people want to
1336 // initialize iterators
1337 // past-the-end
1338 if (global_index < parent.size())
1339 {
1340 const std::pair<size_type, size_type> indices =
1341 parent.block_indices.global_to_local(global_index);
1342 current_block = indices.first;
1343 index_within_block = indices.second;
1344
1345 next_break_backward =
1346 parent.block_indices.local_to_global(current_block, 0);
1347 next_break_forward =
1348 (parent.block_indices.local_to_global(current_block, 0) +
1349 parent.block_indices.block_size(current_block) - 1);
1350 }
1351 else
1352 // past the end. only have one
1353 // value for this
1354 {
1355 this->global_index = parent.size();
1356 current_block = parent.n_blocks();
1357 index_within_block = 0;
1358 next_break_backward = global_index;
1359 next_break_forward = numbers::invalid_size_type;
1360 };
1361 }
1362
1363
1364
1365 template <typename BlockVectorType, bool Constness>
1366 void
1367 Iterator<BlockVectorType, Constness>::move_forward()
1368 {
1369 if (global_index != next_break_forward)
1370 ++index_within_block;
1371 else
1372 {
1373 // ok, we traverse a boundary
1374 // between blocks:
1375 index_within_block = 0;
1376 ++current_block;
1377
1378 // break backwards is now old
1379 // break forward
1380 next_break_backward = next_break_forward + 1;
1381
1382 // compute new break forward
1383 if (current_block < parent->block_indices.size())
1384 next_break_forward +=
1385 parent->block_indices.block_size(current_block);
1386 else
1387 // if we are beyond the end,
1388 // then move the next
1389 // boundary arbitrarily far
1390 // away
1391 next_break_forward = numbers::invalid_size_type;
1392 };
1393
1394 ++global_index;
1395 }
1396
1397
1398
1399 template <typename BlockVectorType, bool Constness>
1400 void
1401 Iterator<BlockVectorType, Constness>::move_backward()
1402 {
1403 if (global_index != next_break_backward)
1404 --index_within_block;
1405 else if (current_block != 0)
1406 {
1407 // ok, we traverse a boundary
1408 // between blocks:
1409 --current_block;
1410 index_within_block =
1411 parent->block_indices.block_size(current_block) - 1;
1412
1413 // break forwards is now old
1414 // break backward
1415 next_break_forward = next_break_backward - 1;
1416
1417 // compute new break forward
1418 next_break_backward -=
1419 parent->block_indices.block_size(current_block);
1420 }
1421 else
1422 // current block was 0, we now
1423 // get into unspecified terrain
1424 {
1425 --current_block;
1426 index_within_block = numbers::invalid_size_type;
1427 next_break_forward = 0;
1428 next_break_backward = 0;
1429 };
1430
1431 --global_index;
1432 }
1433
1434
1435 } // namespace BlockVectorIterators
1436
1437} // namespace internal
1438
1439
1440
1441template <typename VectorType>
1444{
1445 return block_indices.total_size();
1446}
1447
1448
1449
1450template <typename VectorType>
1451inline std::size_t
1453{
1454 std::size_t local_size = 0;
1455 for (unsigned int b = 0; b < n_blocks(); ++b)
1456 local_size += block(b).locally_owned_size();
1457 return local_size;
1458}
1459
1460
1461
1462template <typename VectorType>
1463inline IndexSet
1465{
1466 IndexSet is(size());
1467
1468 // copy index sets from blocks into the global one, shifted
1469 // by the appropriate amount for each block
1470 for (unsigned int b = 0; b < n_blocks(); ++b)
1471 {
1472 IndexSet x = block(b).locally_owned_elements();
1474 }
1475
1476 is.compress();
1477
1478 return is;
1479}
1480
1481
1482
1483template <typename VectorType>
1484inline unsigned int
1486{
1487 return block_indices.size();
1488}
1489
1490
1491template <typename VectorType>
1493BlockVectorBase<VectorType>::block(const unsigned int i)
1494{
1496
1497 return components[i];
1498}
1499
1500
1501
1502template <typename VectorType>
1503inline const typename BlockVectorBase<VectorType>::BlockType &
1504BlockVectorBase<VectorType>::block(const unsigned int i) const
1505{
1507
1508 return components[i];
1509}
1510
1511
1512
1513template <typename VectorType>
1514inline const BlockIndices &
1516{
1517 return block_indices;
1518}
1519
1520
1521template <typename VectorType>
1522inline void
1524{
1525 std::vector<size_type> sizes(n_blocks());
1526
1527 for (size_type i = 0; i < n_blocks(); ++i)
1528 sizes[i] = block(i).size();
1529
1530 block_indices.reinit(sizes);
1531}
1532
1533
1534
1535template <typename VectorType>
1536inline void
1538{
1539 for (unsigned int i = 0; i < n_blocks(); ++i)
1540 block(i).compress(operation);
1541}
1542
1543
1544
1545template <typename VectorType>
1548{
1549 return iterator(*this, 0U);
1550}
1551
1552
1553
1554template <typename VectorType>
1557{
1558 return const_iterator(*this, 0U);
1559}
1560
1561
1562template <typename VectorType>
1565{
1566 return iterator(*this, size());
1567}
1568
1569
1570
1571template <typename VectorType>
1574{
1575 return const_iterator(*this, size());
1576}
1577
1578
1579template <typename VectorType>
1580inline bool
1582{
1583 const std::pair<size_type, size_type> local_index =
1584 block_indices.global_to_local(global_index);
1585
1586 return components[local_index.first].in_local_range(global_index);
1587}
1588
1589
1590template <typename VectorType>
1591bool
1593{
1594 return std::all_of(components.begin(), components.end(), [](const auto &v) {
1595 return v.all_zero();
1596 });
1597}
1598
1599
1600
1601template <typename VectorType>
1602bool
1604{
1605 for (size_type i = 0; i < n_blocks(); ++i)
1606 if (components[i].is_non_negative() == false)
1607 return false;
1608
1609 return true;
1610}
1611
1612
1613
1614template <typename VectorType>
1617 const BlockVectorBase<VectorType> &v) const
1618{
1619 Assert(n_blocks() == v.n_blocks(),
1621
1622 value_type sum = 0.;
1623 for (size_type i = 0; i < n_blocks(); ++i)
1624 sum += components[i] * v.components[i];
1625
1626 return sum;
1627}
1628
1629
1630template <typename VectorType>
1633{
1634 real_type sum = 0.;
1635 for (size_type i = 0; i < n_blocks(); ++i)
1636 sum += components[i].norm_sqr();
1637
1638 return sum;
1639}
1640
1641
1642
1643template <typename VectorType>
1646{
1647 value_type sum = 0.;
1648 // need to do static_cast as otherwise it won't work with
1649 // value_type=complex<T>
1650 for (size_type i = 0; i < n_blocks(); ++i)
1651 sum += components[i].mean_value() *
1653 components[i].size()));
1654
1656}
1657
1658
1659
1660template <typename VectorType>
1663{
1664 real_type sum = 0.;
1665 for (size_type i = 0; i < n_blocks(); ++i)
1666 sum += components[i].l1_norm();
1667
1668 return sum;
1669}
1670
1671
1672
1673template <typename VectorType>
1676{
1677 return std::sqrt(norm_sqr());
1678}
1679
1680
1681
1682template <typename VectorType>
1685{
1686 real_type sum = 0.;
1687 for (size_type i = 0; i < n_blocks(); ++i)
1688 {
1689 value_type newval = components[i].linfty_norm();
1690 if (sum < newval)
1691 sum = newval;
1692 }
1693 return sum;
1694}
1695
1696
1697
1698template <typename VectorType>
1704{
1705 AssertDimension(n_blocks(), V.n_blocks());
1707
1708 value_type sum = 0.;
1709 for (size_type i = 0; i < n_blocks(); ++i)
1710 sum += components[i].add_and_dot(a, V.components[i], W.components[i]);
1711
1712 return sum;
1713}
1714
1715
1716
1717template <typename VectorType>
1720{
1721 Assert(n_blocks() == v.n_blocks(),
1723
1724 for (size_type i = 0; i < n_blocks(); ++i)
1725 {
1726 components[i] += v.components[i];
1727 }
1728
1729 return *this;
1730}
1731
1732
1733
1734template <typename VectorType>
1737{
1738 Assert(n_blocks() == v.n_blocks(),
1740
1741 for (size_type i = 0; i < n_blocks(); ++i)
1742 {
1743 components[i] -= v.components[i];
1744 }
1745 return *this;
1746}
1747
1748
1749
1750template <typename VectorType>
1751template <typename Number>
1752inline void
1753BlockVectorBase<VectorType>::add(const std::vector<size_type> &indices,
1754 const std::vector<Number> &values)
1755{
1756 Assert(indices.size() == values.size(),
1757 ExcDimensionMismatch(indices.size(), values.size()));
1758 add(indices.size(), indices.data(), values.data());
1759}
1760
1761
1762
1763template <typename VectorType>
1764template <typename Number>
1765inline void
1766BlockVectorBase<VectorType>::add(const std::vector<size_type> &indices,
1767 const Vector<Number> &values)
1768{
1769 Assert(indices.size() == values.size(),
1770 ExcDimensionMismatch(indices.size(), values.size()));
1771 const size_type n_indices = indices.size();
1772 for (size_type i = 0; i < n_indices; ++i)
1773 (*this)(indices[i]) += values(i);
1774}
1775
1776
1777
1778template <typename VectorType>
1779template <typename Number>
1780inline void
1782 const size_type *indices,
1783 const Number *values)
1784{
1785 for (size_type i = 0; i < n_indices; ++i)
1786 (*this)(indices[i]) += values[i];
1787}
1788
1789
1790
1791template <typename VectorType>
1792void
1794{
1795 AssertIsFinite(a);
1796
1797 for (size_type i = 0; i < n_blocks(); ++i)
1798 {
1799 components[i].add(a);
1800 }
1801}
1802
1803
1804
1805template <typename VectorType>
1806void
1809{
1810 AssertIsFinite(a);
1811
1812 Assert(n_blocks() == v.n_blocks(),
1814
1815 for (size_type i = 0; i < n_blocks(); ++i)
1816 {
1817 components[i].add(a, v.components[i]);
1818 }
1819}
1820
1821
1822
1823template <typename VectorType>
1824void
1827 const value_type b,
1829{
1830 AssertIsFinite(a);
1831 AssertIsFinite(b);
1832
1833 Assert(n_blocks() == v.n_blocks(),
1835 Assert(n_blocks() == w.n_blocks(),
1836 ExcDimensionMismatch(n_blocks(), w.n_blocks()));
1837
1838
1839 for (size_type i = 0; i < n_blocks(); ++i)
1840 {
1841 components[i].add(a, v.components[i], b, w.components[i]);
1842 }
1843}
1844
1845
1846
1847template <typename VectorType>
1848void
1851{
1852 AssertIsFinite(x);
1853
1854 Assert(n_blocks() == v.n_blocks(),
1856
1857 for (size_type i = 0; i < n_blocks(); ++i)
1858 {
1859 components[i].sadd(x, v.components[i]);
1860 }
1861}
1862
1863
1864
1865template <typename VectorType>
1866void
1868 const value_type a,
1870{
1871 AssertIsFinite(x);
1872 AssertIsFinite(a);
1873
1874 Assert(n_blocks() == v.n_blocks(),
1876
1877 for (size_type i = 0; i < n_blocks(); ++i)
1878 {
1879 components[i].sadd(x, a, v.components[i]);
1880 }
1881}
1882
1883
1884
1885template <typename VectorType>
1886void
1888 const value_type a,
1890 const value_type b,
1892{
1893 AssertIsFinite(x);
1894 AssertIsFinite(a);
1895 AssertIsFinite(b);
1896
1897 Assert(n_blocks() == v.n_blocks(),
1899 Assert(n_blocks() == w.n_blocks(),
1900 ExcDimensionMismatch(n_blocks(), w.n_blocks()));
1901
1902 for (size_type i = 0; i < n_blocks(); ++i)
1903 {
1904 components[i].sadd(x, a, v.components[i], b, w.components[i]);
1905 }
1906}
1907
1908
1909
1910template <typename VectorType>
1911void
1913 const value_type a,
1915 const value_type b,
1917 const value_type c,
1919{
1920 AssertIsFinite(x);
1921 AssertIsFinite(a);
1922 AssertIsFinite(b);
1923 AssertIsFinite(c);
1924
1925 Assert(n_blocks() == v.n_blocks(),
1927 Assert(n_blocks() == w.n_blocks(),
1928 ExcDimensionMismatch(n_blocks(), w.n_blocks()));
1929 Assert(n_blocks() == y.n_blocks(),
1931
1932 for (size_type i = 0; i < n_blocks(); ++i)
1933 {
1934 components[i].sadd(
1935 x, a, v.components[i], b, w.components[i], c, y.components[i]);
1936 }
1937}
1938
1939
1940
1941template <typename VectorType>
1942template <class BlockVector2>
1943void
1944BlockVectorBase<VectorType>::scale(const BlockVector2 &v)
1945{
1946 Assert(n_blocks() == v.n_blocks(),
1947 ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1948 for (size_type i = 0; i < n_blocks(); ++i)
1949 components[i].scale(v.block(i));
1950}
1951
1952
1953
1954template <typename VectorType>
1955std::size_t
1957{
1958 return (MemoryConsumption::memory_consumption(this->block_indices) +
1959 MemoryConsumption::memory_consumption(this->components));
1960}
1961
1962
1963
1964template <typename VectorType>
1965template <class BlockVector2>
1966void
1967BlockVectorBase<VectorType>::equ(const value_type a, const BlockVector2 &v)
1968{
1969 AssertIsFinite(a);
1970
1971 Assert(n_blocks() == v.n_blocks(),
1972 ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1973
1974 for (size_type i = 0; i < n_blocks(); ++i)
1975 components[i].equ(a, v.components[i]);
1976}
1977
1978
1979
1980template <typename VectorType>
1981void
1983{
1984 for (size_type i = 0; i < n_blocks(); ++i)
1985 block(i).update_ghost_values();
1986}
1987
1988
1989
1990template <typename VectorType>
1993{
1994 if (n_blocks() > 0)
1995 return block(0).get_mpi_communicator();
1996 else
1997 return MPI_COMM_SELF;
1998}
1999
2000
2001
2002template <typename VectorType>
2005{
2006 AssertIsFinite(s);
2007
2008 for (size_type i = 0; i < n_blocks(); ++i)
2009 components[i] = s;
2010
2011 return *this;
2012}
2013
2014
2015template <typename VectorType>
2018{
2020
2021 for (size_type i = 0; i < n_blocks(); ++i)
2022 components[i] = v.components[i];
2023
2024 return *this;
2025}
2026
2027
2028template <typename VectorType>
2029template <typename VectorType2>
2032{
2034
2035 for (size_type i = 0; i < n_blocks(); ++i)
2036 components[i] = v.components[i];
2037
2038 return *this;
2039}
2040
2041
2042
2043template <typename VectorType>
2045BlockVectorBase<VectorType>::operator=(const VectorType &v)
2046{
2047 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
2048
2049 size_type index_v = 0;
2050 for (size_type b = 0; b < n_blocks(); ++b)
2051 for (size_type i = 0; i < block(b).size(); ++i, ++index_v)
2052 block(b)(i) = v(index_v);
2053
2054 return *this;
2055}
2056
2057
2058
2059template <typename VectorType>
2060template <typename VectorType2>
2061inline bool
2063 const BlockVectorBase<VectorType2> &v) const
2064{
2066
2067 for (size_type i = 0; i < n_blocks(); ++i)
2068 if (!(components[i] == v.components[i]))
2069 return false;
2070
2071 return true;
2072}
2073
2074
2075
2076template <typename VectorType>
2079{
2080 AssertIsFinite(factor);
2081
2082 for (size_type i = 0; i < n_blocks(); ++i)
2083 components[i] *= factor;
2084
2085 return *this;
2086}
2087
2088
2089
2090template <typename VectorType>
2093{
2094 AssertIsFinite(factor);
2095 Assert(factor != 0., ExcDivideByZero());
2096
2097 const value_type inverse_factor = value_type(1.) / factor;
2098
2099 for (size_type i = 0; i < n_blocks(); ++i)
2100 components[i] *= inverse_factor;
2101
2102 return *this;
2103}
2104
2105
2106template <typename VectorType>
2109{
2110 const std::pair<unsigned int, size_type> local_index =
2112 return components[local_index.first](local_index.second);
2113}
2114
2115
2116
2117template <typename VectorType>
2120{
2121 const std::pair<unsigned int, size_type> local_index =
2123 return components[local_index.first](local_index.second);
2124}
2125
2126
2127
2128template <typename VectorType>
2131{
2132 return operator()(i);
2133}
2134
2135
2136
2137template <typename VectorType>
2140{
2141 return operator()(i);
2142}
2143
2144
2145
2146template <typename VectorType>
2147template <typename OtherNumber>
2148inline void
2150 const std::vector<size_type> &indices,
2151 std::vector<OtherNumber> &values) const
2152{
2153 for (size_type i = 0; i < indices.size(); ++i)
2154 values[i] = operator()(indices[i]);
2155}
2156
2157
2158
2159template <typename VectorType>
2160inline void
2163 const ArrayView<value_type> &entries) const
2164{
2165 AssertDimension(indices.size(), entries.size());
2166 for (unsigned int i = 0; i < indices.size(); ++i)
2167 {
2168 AssertIndexRange(indices[i], size());
2169 entries[i] = (*this)[indices[i]];
2170 }
2171}
2172
2173
2174
2175template <typename VectorType>
2176template <typename ForwardIterator, typename OutputIterator>
2177inline void
2179 ForwardIterator indices_begin,
2180 const ForwardIterator indices_end,
2181 OutputIterator values_begin) const
2182{
2183 while (indices_begin != indices_end)
2184 {
2185 *values_begin = operator()(*indices_begin);
2186 ++indices_begin;
2187 ++values_begin;
2188 }
2189}
2190
2191#endif // DOXYGEN
2192
2194
2195#endif
std::ptrdiff_t difference_type
std::size_t size() const
Definition array_view.h:737
size_type block_size(const unsigned int i) const
size_type total_size() const
void reinit(const unsigned int n_blocks, const size_type n_elements_per_block)
unsigned int size() const
size_type local_to_global(const unsigned int block, const size_type index) const
size_type block_start(const unsigned int i) const
std::pair< unsigned int, size_type > global_to_local(const size_type i) const
BlockVectorBase & operator+=(const BlockVectorBase &V)
BlockVectorBase()=default
void extract_subvector_to(const std::vector< size_type > &indices, std::vector< OtherNumber > &values) const
value_type mean_value() const
virtual size_type size() const override
void add(const std::vector< size_type > &indices, const std::vector< Number > &values)
::internal::BlockVectorIterators::Iterator< BlockVectorBase, false > iterator
BlockVectorBase & operator/=(const value_type factor)
unsigned int n_blocks() const
real_type norm_sqr() const
const value_type * const_pointer
typename BlockType::const_reference const_reference
void update_ghost_values() const
std::size_t memory_consumption() const
real_type l1_norm() const
types::global_dof_index size_type
real_type linfty_norm() const
value_type add_and_dot(const value_type a, const BlockVectorBase &V, const BlockVectorBase &W)
typename BlockType::value_type value_type
value_type operator*(const BlockVectorBase &V) const
void compress(VectorOperation::values operation)
bool all_zero() const
BlockVectorBase & operator=(const value_type s)
void collect_sizes()
BlockVectorBase & operator*=(const value_type factor)
void sadd(const value_type s, const BlockVectorBase &V)
std::vector< VectorType > components
iterator begin()
bool in_local_range(const size_type global_index) const
::internal::BlockVectorIterators::Iterator< BlockVectorBase, true > const_iterator
MPI_Comm get_mpi_communicator() const
BlockVectorBase(BlockVectorBase &&) noexcept=default
BlockVectorBase(const BlockVectorBase &)=default
typename BlockType::reference reference
iterator end()
value_type operator[](const size_type i) const
BlockIndices block_indices
typename BlockType::real_type real_type
void scale(const BlockVector2 &v)
BlockType & block(const unsigned int i)
real_type l2_norm() const
value_type operator()(const size_type i) const
IndexSet locally_owned_elements() const
bool is_non_negative() const
BlockVectorBase & operator-=(const BlockVectorBase &V)
friend class ::internal::BlockVectorIterators::Iterator
bool operator==(const BlockVectorBase< VectorType2 > &v) const
std::size_t locally_owned_size() const
const BlockIndices & get_block_indices() const
void equ(const value_type a, const BlockVector2 &V)
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1814
bool operator==(const Iterator< BlockVectorType, OtherConstness > &i) const
dereference_type operator[](const difference_type d) const
Iterator & operator=(const Iterator &c)
bool operator<(const Iterator< BlockVectorType, OtherConstness > &i) const
Iterator(BlockVector &parent, const size_type global_index, const size_type current_block, const size_type index_within_block, const size_type next_break_forward, const size_type next_break_backward)
std::conditional_t< Constness, const typename BlockVectorType::value_type, typename BlockVectorType::value_type > value_type
Iterator(const Iterator< BlockVectorType, !Constness > &c)
std::conditional_t< Constness, const BlockVectorType, BlockVectorType > BlockVector
dereference_type operator*() const
Iterator operator-(const difference_type &d) const
difference_type operator-(const Iterator< BlockVectorType, OtherConstness > &i) const
std::random_access_iterator_tag iterator_category
Iterator(BlockVector &parent, const size_type global_index)
bool operator>=(const Iterator< BlockVectorType, OtherConstness > &i) const
Iterator & operator-=(const difference_type &d)
std::conditional_t< Constness, value_type, typename BlockVectorType::BlockType::reference > dereference_type
bool operator<=(const Iterator< BlockVectorType, OtherConstness > &i) const
typename BlockVectorType::reference reference
Iterator operator+(const difference_type &d) const
Iterator & operator+=(const difference_type &d)
bool operator!=(const Iterator< BlockVectorType, OtherConstness > &i) const
bool operator>(const Iterator< BlockVectorType, OtherConstness > &i) const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
static ::ExceptionBase & ExcPointerToDifferentVectors()
#define AssertIsFinite(number)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcDivideByZero()
static ::ExceptionBase & ExcDifferentBlockIndices()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static const bool value
constexpr char V
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
Tensor< 2, dim, Number > w(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
T sum(const T &t, const MPI_Comm mpi_communicator)
constexpr bool has_n_blocks
decltype(std::declval< const T >().n_blocks()) has_n_blocks_t
decltype(std::declval< const T >().block(0)) has_block_t
constexpr bool is_block_vector
constexpr bool has_block
constexpr types::global_dof_index invalid_size_type
Definition types.h:240
STL namespace.
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
Definition types.h:30
unsigned int global_dof_index
Definition types.h:92