deal.II version GIT relicensing-1853-g8a8889c127 2024-09-13 15:30:00+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: LGPL-2.1-or-later
4// Copyright (C) 2004 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_block_vector_base_h
16#define dealii_block_vector_base_h
17
18
19#include <deal.II/base/config.h>
20
25
29#include <deal.II/lac/vector.h>
31
32#include <cmath>
33#include <cstddef>
34#include <iterator>
35#include <type_traits>
36#include <vector>
37
39
40
46namespace internal
47{
48 template <typename T>
49 using has_block_t = decltype(std::declval<const T>().block(0));
50
51 template <typename T>
52 constexpr bool has_block = internal::is_supported_operation<has_block_t, T>;
53
54 template <typename T>
55 using has_n_blocks_t = decltype(std::declval<const T>().n_blocks());
56
57 template <typename T>
58 constexpr bool has_n_blocks =
59 internal::is_supported_operation<has_n_blocks_t, T>;
60
61 template <typename T>
62 constexpr bool is_block_vector = has_block<T> && has_n_blocks<T>;
63} // namespace internal
64
79template <typename VectorType>
81{
82public:
88 static const bool value = internal::is_block_vector<VectorType>;
89};
90
91
92// instantiation of the static member
93template <typename VectorType>
95
96
97
98namespace internal
99{
103 namespace BlockVectorIterators
104 {
120 template <typename BlockVectorType, bool Constness>
122 {
123 public:
128
135 std::conditional_t<Constness,
136 const typename BlockVectorType::value_type,
137 typename BlockVectorType::value_type>;
138
152 using iterator_category = std::random_access_iterator_tag;
153 using difference_type = std::ptrdiff_t;
154 using reference = typename BlockVectorType::reference;
156
158 std::conditional_t<Constness,
160 typename BlockVectorType::BlockType::reference>;
161
167 std::conditional_t<Constness, const BlockVectorType, BlockVectorType>;
168
178
187
188
193
194 private:
205
206 public:
210 Iterator &
212
219 operator*() const;
220
227
232 Iterator &
234
242
247 Iterator &
249
257
262 template <bool OtherConstness>
263 bool
265
270 template <bool OtherConstness>
271 bool
273
279 template <bool OtherConstness>
280 bool
282
286 template <bool OtherConstness>
287 bool
289
293 template <bool OtherConstness>
294 bool
296
300 template <bool OtherConstness>
301 bool
303
307 template <bool OtherConstness>
310
316 operator+(const difference_type &d) const;
317
323 operator-(const difference_type &d) const;
324
329 Iterator &
331
336 Iterator &
338
349 "Your program tried to compare iterators pointing to "
350 "different block vectors. There is no reasonable way "
351 "to do this.");
352
354 private:
361
366
371 unsigned int current_block;
373
382
386 void
388
392 void
394
395 // Mark all other instances of this template as friends.
396 template <typename, bool>
397 friend class Iterator;
398 };
399 } // namespace BlockVectorIterators
400} // namespace internal
401
402
440template <typename VectorType>
442 public ReadVector<typename VectorType::value_type>
443{
444public:
448 using BlockType = VectorType;
449
450 /*
451 * Declare standard types used in
452 * all containers. These types
453 * parallel those in the
454 * <tt>C++</tt> standard
455 * libraries
456 * <tt>std::vector<...></tt>
457 * class. This includes iterator
458 * types.
459 */
460 using value_type = typename BlockType::value_type;
462 using const_pointer = const value_type *;
463 using iterator =
467 using reference = typename BlockType::reference;
468 using const_reference = typename BlockType::const_reference;
470
480 using real_type = typename BlockType::real_type;
481
485 BlockVectorBase() = default;
486
490 BlockVectorBase(const BlockVectorBase & /*V*/) = default;
491
497 BlockVectorBase(BlockVectorBase && /*V*/) noexcept = default;
498
505 void
507
518 void
519 compress(VectorOperation::values operation);
520
524 BlockType &
525 block(const unsigned int i);
526
530 const BlockType &
531 block(const unsigned int i) const;
532
538 const BlockIndices &
540
544 unsigned int
545 n_blocks() const;
546
551 virtual size_type
552 size() const override;
553
559 std::size_t
561
580
586
592 begin() const;
593
599
605 end() const;
606
611 operator()(const size_type i) const;
612
617 operator()(const size_type i);
618
625 operator[](const size_type i) const;
626
633 operator[](const size_type i);
634
650 template <typename OtherNumber>
651 void
652 extract_subvector_to(const std::vector<size_type> &indices,
653 std::vector<OtherNumber> &values) const;
654
655 virtual void
656 extract_subvector_to(const ArrayView<const types::global_dof_index> &indices,
657 ArrayView<value_type> &entries) const override;
658
686 template <typename ForwardIterator, typename OutputIterator>
687 void
688 extract_subvector_to(ForwardIterator indices_begin,
689 const ForwardIterator indices_end,
690 OutputIterator values_begin) const;
691
697 operator=(const value_type s);
698
703 operator=(const BlockVectorBase &V);
704
711 operator=(BlockVectorBase && /*V*/) = default; // NOLINT
712
716 template <typename VectorType2>
718 operator=(const BlockVectorBase<VectorType2> &V);
719
724 operator=(const VectorType &v);
725
730 template <typename VectorType2>
731 bool
732 operator==(const BlockVectorBase<VectorType2> &v) const;
733
738 operator*(const BlockVectorBase &V) const;
739
744 norm_sqr() const;
745
750 mean_value() const;
751
756 l1_norm() const;
757
763 l2_norm() const;
764
770 linfty_norm() const;
771
796 const BlockVectorBase &V,
797 const BlockVectorBase &W);
798
803 bool
804 in_local_range(const size_type global_index) const;
805
811 bool
812 all_zero() const;
813
819 bool
821
826 operator+=(const BlockVectorBase &V);
827
832 operator-=(const BlockVectorBase &V);
833
834
839 template <typename Number>
840 void
841 add(const std::vector<size_type> &indices, const std::vector<Number> &values);
842
847 template <typename Number>
848 void
849 add(const std::vector<size_type> &indices, const Vector<Number> &values);
850
856 template <typename Number>
857 void
858 add(const size_type n_elements,
859 const size_type *indices,
860 const Number *values);
861
866 void
867 add(const value_type s);
868
872 void
873 add(const value_type a, const BlockVectorBase &V);
874
878 void
880 const BlockVectorBase &V,
881 const value_type b,
882 const BlockVectorBase &W);
883
887 void
888 sadd(const value_type s, const BlockVectorBase &V);
889
893 void
894 sadd(const value_type s, const value_type a, const BlockVectorBase &V);
895
899 void
901 const value_type a,
902 const BlockVectorBase &V,
903 const value_type b,
904 const BlockVectorBase &W);
905
909 void
911 const value_type a,
912 const BlockVectorBase &V,
913 const value_type b,
914 const BlockVectorBase &W,
915 const value_type c,
916 const BlockVectorBase &X);
917
922 operator*=(const value_type factor);
923
928 operator/=(const value_type factor);
929
934 template <class BlockVector2>
935 void
936 scale(const BlockVector2 &v);
937
941 template <class BlockVector2>
942 void
943 equ(const value_type a, const BlockVector2 &V);
944
949 void
951
959
964 std::size_t
966
967protected:
971 std::vector<VectorType> components;
972
978
979 // Make the iterator class a friend.
980 template <typename N, bool C>
981 friend class ::internal::BlockVectorIterators::Iterator;
982
983 template <typename>
984 friend class BlockVectorBase;
985};
986
987
990/*----------------------- Inline functions ----------------------------------*/
991
992
993#ifndef DOXYGEN
994namespace internal
995{
996 namespace BlockVectorIterators
997 {
998 template <typename BlockVectorType, bool Constness>
999 inline Iterator<BlockVectorType, Constness>::Iterator(
1000 const Iterator<BlockVectorType, Constness> &c)
1001 : parent(c.parent)
1002 , global_index(c.global_index)
1003 , current_block(c.current_block)
1004 , index_within_block(c.index_within_block)
1005 , next_break_forward(c.next_break_forward)
1006 , next_break_backward(c.next_break_backward)
1007 {}
1008
1009
1010
1011 template <typename BlockVectorType, bool Constness>
1012 inline Iterator<BlockVectorType, Constness>::Iterator(
1013 const Iterator<BlockVectorType, !Constness> &c)
1014 : parent(c.parent)
1015 , global_index(c.global_index)
1016 , current_block(c.current_block)
1017 , index_within_block(c.index_within_block)
1018 , next_break_forward(c.next_break_forward)
1019 , next_break_backward(c.next_break_backward)
1020 {
1021 // Only permit copy-constructing const iterators from non-const
1022 // iterators, and not vice versa (i.e., Constness must always be
1023 // true).
1024 static_assert(Constness == true,
1025 "Constructing a non-const iterator from a const iterator "
1026 "does not make sense.");
1027 }
1028
1029
1030
1031 template <typename BlockVectorType, bool Constness>
1032 inline Iterator<BlockVectorType, Constness>::Iterator(
1033 BlockVector &parent,
1034 const size_type global_index,
1035 const size_type current_block,
1036 const size_type index_within_block,
1037 const size_type next_break_forward,
1038 const size_type next_break_backward)
1039 : parent(&parent)
1040 , global_index(global_index)
1041 , current_block(current_block)
1042 , index_within_block(index_within_block)
1043 , next_break_forward(next_break_forward)
1044 , next_break_backward(next_break_backward)
1045 {}
1046
1047
1048
1049 template <typename BlockVectorType, bool Constness>
1050 inline Iterator<BlockVectorType, Constness> &
1051 Iterator<BlockVectorType, Constness>::operator=(const Iterator &c)
1052 {
1053 parent = c.parent;
1054 global_index = c.global_index;
1055 index_within_block = c.index_within_block;
1056 current_block = c.current_block;
1057 next_break_forward = c.next_break_forward;
1058 next_break_backward = c.next_break_backward;
1059
1060 return *this;
1061 }
1062
1063
1064
1065 template <typename BlockVectorType, bool Constness>
1066 inline typename Iterator<BlockVectorType, Constness>::dereference_type
1067 Iterator<BlockVectorType, Constness>::operator*() const
1068 {
1069 return parent->block(current_block)(index_within_block);
1070 }
1071
1072
1073
1074 template <typename BlockVectorType, bool Constness>
1075 inline typename Iterator<BlockVectorType, Constness>::dereference_type
1076 Iterator<BlockVectorType, Constness>::operator[](
1077 const difference_type d) const
1078 {
1079 // if the index pointed to is
1080 // still within the block we
1081 // currently point into, then we
1082 // can save the computation of
1083 // the block
1084 if ((global_index + d >= next_break_backward) &&
1085 (global_index + d <= next_break_forward))
1086 return parent->block(current_block)(index_within_block + d);
1087
1088 // if the index is not within the
1089 // block of the block vector into
1090 // which we presently point, then
1091 // there is no way: we have to
1092 // search for the block. this can
1093 // be done through the parent
1094 // class as well.
1095 return (*parent)(global_index + d);
1096 }
1097
1098
1099
1100 template <typename BlockVectorType, bool Constness>
1101 inline Iterator<BlockVectorType, Constness> &
1102 Iterator<BlockVectorType, Constness>::operator++()
1103 {
1104 move_forward();
1105 return *this;
1106 }
1107
1108
1109
1110 template <typename BlockVectorType, bool Constness>
1111 inline Iterator<BlockVectorType, Constness>
1112 Iterator<BlockVectorType, Constness>::operator++(int)
1113 {
1114 const Iterator old_value = *this;
1115 move_forward();
1116 return old_value;
1117 }
1118
1119
1120
1121 template <typename BlockVectorType, bool Constness>
1122 inline Iterator<BlockVectorType, Constness> &
1123 Iterator<BlockVectorType, Constness>::operator--()
1124 {
1125 move_backward();
1126 return *this;
1127 }
1128
1129
1130
1131 template <typename BlockVectorType, bool Constness>
1132 inline Iterator<BlockVectorType, Constness>
1133 Iterator<BlockVectorType, Constness>::operator--(int)
1134 {
1135 const Iterator old_value = *this;
1136 move_backward();
1137 return old_value;
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 bool
1210 Iterator<BlockVectorType, Constness>::operator>=(
1211 const Iterator<BlockVectorType, OtherConstness> &i) const
1212 {
1213 Assert(parent == i.parent, ExcPointerToDifferentVectors());
1214
1215 return (global_index >= i.global_index);
1216 }
1217
1218
1219
1220 template <typename BlockVectorType, bool Constness>
1221 template <bool OtherConstness>
1222 inline typename Iterator<BlockVectorType, Constness>::difference_type
1223 Iterator<BlockVectorType, Constness>::operator-(
1224 const Iterator<BlockVectorType, OtherConstness> &i) const
1225 {
1226 Assert(parent == i.parent, ExcPointerToDifferentVectors());
1227
1228 return (static_cast<signed int>(global_index) -
1229 static_cast<signed int>(i.global_index));
1230 }
1231
1232
1233
1234 template <typename BlockVectorType, bool Constness>
1235 inline Iterator<BlockVectorType, Constness>
1236 Iterator<BlockVectorType, Constness>::operator+(
1237 const difference_type &d) const
1238 {
1239 // if the index pointed to is
1240 // still within the block we
1241 // currently point into, then we
1242 // can save the computation of
1243 // the block
1244 if ((global_index + d >= next_break_backward) &&
1245 (global_index + d <= next_break_forward))
1246 return Iterator(*parent,
1247 global_index + d,
1248 current_block,
1249 index_within_block + d,
1250 next_break_forward,
1251 next_break_backward);
1252 else
1253 // outside present block, so
1254 // have to seek new block
1255 // anyway
1256 return Iterator(*parent, global_index + d);
1257 }
1258
1259
1260
1261 template <typename BlockVectorType, bool Constness>
1262 inline Iterator<BlockVectorType, Constness>
1263 Iterator<BlockVectorType, Constness>::operator-(
1264 const difference_type &d) const
1265 {
1266 // if the index pointed to is
1267 // still within the block we
1268 // currently point into, then we
1269 // can save the computation of
1270 // the block
1271 if ((global_index - d >= next_break_backward) &&
1272 (global_index - d <= next_break_forward))
1273 return Iterator(*parent,
1274 global_index - d,
1275 current_block,
1276 index_within_block - d,
1277 next_break_forward,
1278 next_break_backward);
1279 else
1280 // outside present block, so
1281 // have to seek new block
1282 // anyway
1283 return Iterator(*parent, global_index - d);
1284 }
1285
1286
1287
1288 template <typename BlockVectorType, bool Constness>
1289 inline Iterator<BlockVectorType, Constness> &
1290 Iterator<BlockVectorType, Constness>::operator+=(const difference_type &d)
1291 {
1292 // if the index pointed to is
1293 // still within the block we
1294 // currently point into, then we
1295 // can save the computation of
1296 // the block
1297 if ((global_index + d >= next_break_backward) &&
1298 (global_index + d <= next_break_forward))
1299 {
1300 global_index += d;
1301 index_within_block += d;
1302 }
1303 else
1304 // outside present block, so
1305 // have to seek new block
1306 // anyway
1307 *this = Iterator(*parent, global_index + d);
1308
1309 return *this;
1310 }
1311
1312
1313
1314 template <typename BlockVectorType, bool Constness>
1315 inline Iterator<BlockVectorType, Constness> &
1316 Iterator<BlockVectorType, Constness>::operator-=(const difference_type &d)
1317 {
1318 // if the index pointed to is
1319 // still within the block we
1320 // currently point into, then we
1321 // can save the computation of
1322 // the block
1323 if ((global_index - d >= next_break_backward) &&
1324 (global_index - d <= next_break_forward))
1325 {
1326 global_index -= d;
1327 index_within_block -= d;
1328 }
1329 else
1330 // outside present block, so
1331 // have to seek new block
1332 // anyway
1333 *this = Iterator(*parent, global_index - d);
1334
1335 return *this;
1336 }
1337
1338
1339 template <typename BlockVectorType, bool Constness>
1340 Iterator<BlockVectorType, Constness>::Iterator(BlockVector &parent,
1341 const size_type global_index)
1342 : parent(&parent)
1343 , global_index(global_index)
1344 {
1345 // find which block we are
1346 // in. for this, take into
1347 // account that it happens at
1348 // times that people want to
1349 // initialize iterators
1350 // past-the-end
1351 if (global_index < parent.size())
1352 {
1353 const std::pair<size_type, size_type> indices =
1354 parent.block_indices.global_to_local(global_index);
1355 current_block = indices.first;
1356 index_within_block = indices.second;
1357
1358 next_break_backward =
1359 parent.block_indices.local_to_global(current_block, 0);
1360 next_break_forward =
1361 (parent.block_indices.local_to_global(current_block, 0) +
1362 parent.block_indices.block_size(current_block) - 1);
1363 }
1364 else
1365 // past the end. only have one
1366 // value for this
1367 {
1368 this->global_index = parent.size();
1369 current_block = parent.n_blocks();
1370 index_within_block = 0;
1371 next_break_backward = global_index;
1372 next_break_forward = numbers::invalid_size_type;
1373 };
1374 }
1375
1376
1377
1378 template <typename BlockVectorType, bool Constness>
1379 void
1380 Iterator<BlockVectorType, Constness>::move_forward()
1381 {
1382 if (global_index != next_break_forward)
1383 ++index_within_block;
1384 else
1385 {
1386 // ok, we traverse a boundary
1387 // between blocks:
1388 index_within_block = 0;
1389 ++current_block;
1390
1391 // break backwards is now old
1392 // break forward
1393 next_break_backward = next_break_forward + 1;
1394
1395 // compute new break forward
1396 if (current_block < parent->block_indices.size())
1397 next_break_forward +=
1398 parent->block_indices.block_size(current_block);
1399 else
1400 // if we are beyond the end,
1401 // then move the next
1402 // boundary arbitrarily far
1403 // away
1404 next_break_forward = numbers::invalid_size_type;
1405 };
1406
1407 ++global_index;
1408 }
1409
1410
1411
1412 template <typename BlockVectorType, bool Constness>
1413 void
1414 Iterator<BlockVectorType, Constness>::move_backward()
1415 {
1416 if (global_index != next_break_backward)
1417 --index_within_block;
1418 else if (current_block != 0)
1419 {
1420 // ok, we traverse a boundary
1421 // between blocks:
1422 --current_block;
1423 index_within_block =
1424 parent->block_indices.block_size(current_block) - 1;
1425
1426 // break forwards is now old
1427 // break backward
1428 next_break_forward = next_break_backward - 1;
1429
1430 // compute new break forward
1431 next_break_backward -=
1432 parent->block_indices.block_size(current_block);
1433 }
1434 else
1435 // current block was 0, we now
1436 // get into unspecified terrain
1437 {
1438 --current_block;
1439 index_within_block = numbers::invalid_size_type;
1440 next_break_forward = 0;
1441 next_break_backward = 0;
1442 };
1443
1444 --global_index;
1445 }
1446
1447
1448 } // namespace BlockVectorIterators
1449
1450} // namespace internal
1451
1452
1453
1454template <typename VectorType>
1457{
1458 return block_indices.total_size();
1459}
1460
1461
1462
1463template <typename VectorType>
1464inline std::size_t
1466{
1467 std::size_t local_size = 0;
1468 for (unsigned int b = 0; b < n_blocks(); ++b)
1469 local_size += block(b).locally_owned_size();
1470 return local_size;
1471}
1472
1473
1474
1475template <typename VectorType>
1476inline IndexSet
1478{
1479 IndexSet is(size());
1480
1481 // copy index sets from blocks into the global one, shifted
1482 // by the appropriate amount for each block
1483 for (unsigned int b = 0; b < n_blocks(); ++b)
1484 {
1485 IndexSet x = block(b).locally_owned_elements();
1487 }
1488
1489 is.compress();
1490
1491 return is;
1492}
1493
1494
1495
1496template <typename VectorType>
1497inline unsigned int
1499{
1500 return block_indices.size();
1501}
1502
1503
1504template <typename VectorType>
1506BlockVectorBase<VectorType>::block(const unsigned int i)
1507{
1509
1510 return components[i];
1511}
1512
1513
1514
1515template <typename VectorType>
1516inline const typename BlockVectorBase<VectorType>::BlockType &
1517BlockVectorBase<VectorType>::block(const unsigned int i) const
1518{
1520
1521 return components[i];
1522}
1523
1524
1525
1526template <typename VectorType>
1527inline const BlockIndices &
1529{
1530 return block_indices;
1531}
1532
1533
1534template <typename VectorType>
1535inline void
1537{
1538 std::vector<size_type> sizes(n_blocks());
1539
1540 for (size_type i = 0; i < n_blocks(); ++i)
1541 sizes[i] = block(i).size();
1542
1543 block_indices.reinit(sizes);
1544}
1545
1546
1547
1548template <typename VectorType>
1549inline void
1551{
1552 for (unsigned int i = 0; i < n_blocks(); ++i)
1553 block(i).compress(operation);
1554}
1555
1556
1557
1558template <typename VectorType>
1561{
1562 return iterator(*this, 0U);
1563}
1564
1565
1566
1567template <typename VectorType>
1570{
1571 return const_iterator(*this, 0U);
1572}
1573
1574
1575template <typename VectorType>
1578{
1579 return iterator(*this, size());
1580}
1581
1582
1583
1584template <typename VectorType>
1587{
1588 return const_iterator(*this, size());
1589}
1590
1591
1592template <typename VectorType>
1593inline bool
1595{
1596 const std::pair<size_type, size_type> local_index =
1597 block_indices.global_to_local(global_index);
1598
1599 return components[local_index.first].in_local_range(global_index);
1600}
1601
1602
1603template <typename VectorType>
1604bool
1606{
1607 for (size_type i = 0; i < n_blocks(); ++i)
1608 if (components[i].all_zero() == false)
1609 return false;
1610
1611 return true;
1612}
1613
1614
1615
1616template <typename VectorType>
1617bool
1619{
1620 for (size_type i = 0; i < n_blocks(); ++i)
1621 if (components[i].is_non_negative() == false)
1622 return false;
1623
1624 return true;
1625}
1626
1627
1628
1629template <typename VectorType>
1632 const BlockVectorBase<VectorType> &v) const
1633{
1634 Assert(n_blocks() == v.n_blocks(),
1636
1637 value_type sum = 0.;
1638 for (size_type i = 0; i < n_blocks(); ++i)
1639 sum += components[i] * v.components[i];
1640
1641 return sum;
1642}
1643
1644
1645template <typename VectorType>
1648{
1649 real_type sum = 0.;
1650 for (size_type i = 0; i < n_blocks(); ++i)
1651 sum += components[i].norm_sqr();
1652
1653 return sum;
1654}
1655
1656
1657
1658template <typename VectorType>
1661{
1662 value_type sum = 0.;
1663 // need to do static_cast as otherwise it won't work with
1664 // value_type=complex<T>
1665 for (size_type i = 0; i < n_blocks(); ++i)
1666 sum += components[i].mean_value() *
1668 components[i].size()));
1669
1671}
1672
1673
1674
1675template <typename VectorType>
1678{
1679 real_type sum = 0.;
1680 for (size_type i = 0; i < n_blocks(); ++i)
1681 sum += components[i].l1_norm();
1682
1683 return sum;
1684}
1685
1686
1687
1688template <typename VectorType>
1691{
1692 return std::sqrt(norm_sqr());
1693}
1694
1695
1696
1697template <typename VectorType>
1700{
1701 real_type sum = 0.;
1702 for (size_type i = 0; i < n_blocks(); ++i)
1703 {
1704 value_type newval = components[i].linfty_norm();
1705 if (sum < newval)
1706 sum = newval;
1707 }
1708 return sum;
1709}
1710
1711
1712
1713template <typename VectorType>
1719{
1722
1723 value_type sum = 0.;
1724 for (size_type i = 0; i < n_blocks(); ++i)
1725 sum += components[i].add_and_dot(a, V.components[i], W.components[i]);
1726
1727 return sum;
1728}
1729
1730
1731
1732template <typename VectorType>
1735{
1736 Assert(n_blocks() == v.n_blocks(),
1738
1739 for (size_type i = 0; i < n_blocks(); ++i)
1740 {
1741 components[i] += v.components[i];
1742 }
1743
1744 return *this;
1745}
1746
1747
1748
1749template <typename VectorType>
1752{
1753 Assert(n_blocks() == v.n_blocks(),
1755
1756 for (size_type i = 0; i < n_blocks(); ++i)
1757 {
1758 components[i] -= v.components[i];
1759 }
1760 return *this;
1761}
1762
1763
1764
1765template <typename VectorType>
1766template <typename Number>
1767inline void
1768BlockVectorBase<VectorType>::add(const std::vector<size_type> &indices,
1769 const std::vector<Number> &values)
1770{
1771 Assert(indices.size() == values.size(),
1772 ExcDimensionMismatch(indices.size(), values.size()));
1773 add(indices.size(), indices.data(), values.data());
1774}
1775
1776
1777
1778template <typename VectorType>
1779template <typename Number>
1780inline void
1781BlockVectorBase<VectorType>::add(const std::vector<size_type> &indices,
1782 const Vector<Number> &values)
1783{
1784 Assert(indices.size() == values.size(),
1785 ExcDimensionMismatch(indices.size(), values.size()));
1786 const size_type n_indices = indices.size();
1787 for (size_type i = 0; i < n_indices; ++i)
1788 (*this)(indices[i]) += values(i);
1789}
1790
1791
1792
1793template <typename VectorType>
1794template <typename Number>
1795inline void
1797 const size_type *indices,
1798 const Number *values)
1799{
1800 for (size_type i = 0; i < n_indices; ++i)
1801 (*this)(indices[i]) += values[i];
1802}
1803
1804
1805
1806template <typename VectorType>
1807void
1809{
1810 AssertIsFinite(a);
1811
1812 for (size_type i = 0; i < n_blocks(); ++i)
1813 {
1814 components[i].add(a);
1815 }
1816}
1817
1818
1819
1820template <typename VectorType>
1821void
1824{
1825 AssertIsFinite(a);
1826
1827 Assert(n_blocks() == v.n_blocks(),
1829
1830 for (size_type i = 0; i < n_blocks(); ++i)
1831 {
1832 components[i].add(a, v.components[i]);
1833 }
1834}
1835
1836
1837
1838template <typename VectorType>
1839void
1842 const value_type b,
1844{
1845 AssertIsFinite(a);
1846 AssertIsFinite(b);
1847
1848 Assert(n_blocks() == v.n_blocks(),
1850 Assert(n_blocks() == w.n_blocks(),
1851 ExcDimensionMismatch(n_blocks(), w.n_blocks()));
1852
1853
1854 for (size_type i = 0; i < n_blocks(); ++i)
1855 {
1856 components[i].add(a, v.components[i], b, w.components[i]);
1857 }
1858}
1859
1860
1861
1862template <typename VectorType>
1863void
1866{
1867 AssertIsFinite(x);
1868
1869 Assert(n_blocks() == v.n_blocks(),
1871
1872 for (size_type i = 0; i < n_blocks(); ++i)
1873 {
1874 components[i].sadd(x, v.components[i]);
1875 }
1876}
1877
1878
1879
1880template <typename VectorType>
1881void
1883 const value_type a,
1885{
1886 AssertIsFinite(x);
1887 AssertIsFinite(a);
1888
1889 Assert(n_blocks() == v.n_blocks(),
1891
1892 for (size_type i = 0; i < n_blocks(); ++i)
1893 {
1894 components[i].sadd(x, a, v.components[i]);
1895 }
1896}
1897
1898
1899
1900template <typename VectorType>
1901void
1903 const value_type a,
1905 const value_type b,
1907{
1908 AssertIsFinite(x);
1909 AssertIsFinite(a);
1910 AssertIsFinite(b);
1911
1912 Assert(n_blocks() == v.n_blocks(),
1914 Assert(n_blocks() == w.n_blocks(),
1915 ExcDimensionMismatch(n_blocks(), w.n_blocks()));
1916
1917 for (size_type i = 0; i < n_blocks(); ++i)
1918 {
1919 components[i].sadd(x, a, v.components[i], b, w.components[i]);
1920 }
1921}
1922
1923
1924
1925template <typename VectorType>
1926void
1928 const value_type a,
1930 const value_type b,
1932 const value_type c,
1934{
1935 AssertIsFinite(x);
1936 AssertIsFinite(a);
1937 AssertIsFinite(b);
1938 AssertIsFinite(c);
1939
1940 Assert(n_blocks() == v.n_blocks(),
1942 Assert(n_blocks() == w.n_blocks(),
1943 ExcDimensionMismatch(n_blocks(), w.n_blocks()));
1944 Assert(n_blocks() == y.n_blocks(),
1946
1947 for (size_type i = 0; i < n_blocks(); ++i)
1948 {
1949 components[i].sadd(
1950 x, a, v.components[i], b, w.components[i], c, y.components[i]);
1951 }
1952}
1953
1954
1955
1956template <typename VectorType>
1957template <class BlockVector2>
1958void
1959BlockVectorBase<VectorType>::scale(const BlockVector2 &v)
1960{
1961 Assert(n_blocks() == v.n_blocks(),
1962 ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1963 for (size_type i = 0; i < n_blocks(); ++i)
1964 components[i].scale(v.block(i));
1965}
1966
1967
1968
1969template <typename VectorType>
1970std::size_t
1972{
1973 return (MemoryConsumption::memory_consumption(this->block_indices) +
1974 MemoryConsumption::memory_consumption(this->components));
1975}
1976
1977
1978
1979template <typename VectorType>
1980template <class BlockVector2>
1981void
1982BlockVectorBase<VectorType>::equ(const value_type a, const BlockVector2 &v)
1983{
1984 AssertIsFinite(a);
1985
1986 Assert(n_blocks() == v.n_blocks(),
1987 ExcDimensionMismatch(n_blocks(), v.n_blocks()));
1988
1989 for (size_type i = 0; i < n_blocks(); ++i)
1990 components[i].equ(a, v.components[i]);
1991}
1992
1993
1994
1995template <typename VectorType>
1996void
1998{
1999 for (size_type i = 0; i < n_blocks(); ++i)
2000 block(i).update_ghost_values();
2001}
2002
2003
2004
2005template <typename VectorType>
2008{
2009 if (n_blocks() > 0)
2010 return block(0).get_mpi_communicator();
2011 else
2012 return MPI_COMM_SELF;
2013}
2014
2015
2016
2017template <typename VectorType>
2020{
2021 AssertIsFinite(s);
2022
2023 for (size_type i = 0; i < n_blocks(); ++i)
2024 components[i] = s;
2025
2026 return *this;
2027}
2028
2029
2030template <typename VectorType>
2033{
2035
2036 for (size_type i = 0; i < n_blocks(); ++i)
2037 components[i] = v.components[i];
2038
2039 return *this;
2040}
2041
2042
2043template <typename VectorType>
2044template <typename VectorType2>
2047{
2049
2050 for (size_type i = 0; i < n_blocks(); ++i)
2051 components[i] = v.components[i];
2052
2053 return *this;
2054}
2055
2056
2057
2058template <typename VectorType>
2060BlockVectorBase<VectorType>::operator=(const VectorType &v)
2061{
2062 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
2063
2064 size_type index_v = 0;
2065 for (size_type b = 0; b < n_blocks(); ++b)
2066 for (size_type i = 0; i < block(b).size(); ++i, ++index_v)
2067 block(b)(i) = v(index_v);
2068
2069 return *this;
2070}
2071
2072
2073
2074template <typename VectorType>
2075template <typename VectorType2>
2076inline bool
2078 const BlockVectorBase<VectorType2> &v) const
2079{
2081
2082 for (size_type i = 0; i < n_blocks(); ++i)
2083 if (!(components[i] == v.components[i]))
2084 return false;
2085
2086 return true;
2087}
2088
2089
2090
2091template <typename VectorType>
2094{
2095 AssertIsFinite(factor);
2096
2097 for (size_type i = 0; i < n_blocks(); ++i)
2098 components[i] *= factor;
2099
2100 return *this;
2101}
2102
2103
2104
2105template <typename VectorType>
2108{
2109 AssertIsFinite(factor);
2110 Assert(factor != 0., ExcDivideByZero());
2111
2112 const value_type inverse_factor = value_type(1.) / factor;
2113
2114 for (size_type i = 0; i < n_blocks(); ++i)
2115 components[i] *= inverse_factor;
2116
2117 return *this;
2118}
2119
2120
2121template <typename VectorType>
2124{
2125 const std::pair<unsigned int, size_type> local_index =
2127 return components[local_index.first](local_index.second);
2128}
2129
2130
2131
2132template <typename VectorType>
2135{
2136 const std::pair<unsigned int, size_type> local_index =
2138 return components[local_index.first](local_index.second);
2139}
2140
2141
2142
2143template <typename VectorType>
2146{
2147 return operator()(i);
2148}
2149
2150
2151
2152template <typename VectorType>
2155{
2156 return operator()(i);
2157}
2158
2159
2160
2161template <typename VectorType>
2162template <typename OtherNumber>
2163inline void
2165 const std::vector<size_type> &indices,
2166 std::vector<OtherNumber> &values) const
2167{
2168 for (size_type i = 0; i < indices.size(); ++i)
2169 values[i] = operator()(indices[i]);
2170}
2171
2172
2173
2174template <typename VectorType>
2175inline void
2178 ArrayView<value_type> &entries) const
2179{
2180 AssertDimension(indices.size(), entries.size());
2181 for (unsigned int i = 0; i < indices.size(); ++i)
2182 {
2183 AssertIndexRange(indices[i], size());
2184 entries[i] = (*this)[indices[i]];
2185 }
2186}
2187
2188
2189
2190template <typename VectorType>
2191template <typename ForwardIterator, typename OutputIterator>
2192inline void
2194 ForwardIterator indices_begin,
2195 const ForwardIterator indices_end,
2196 OutputIterator values_begin) const
2197{
2198 while (indices_begin != indices_end)
2199 {
2200 *values_begin = operator()(*indices_begin);
2201 ++indices_begin;
2202 ++values_begin;
2203 }
2204}
2205
2206#endif // DOXYGEN
2207
2209
2210#endif
std::size_t size() const
Definition array_view.h:684
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:1831
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:500
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:501
#define Assert(cond, exc)
static ::ExceptionBase & ExcPointerToDifferentVectors()
#define AssertIsFinite(number)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
#define DeclExceptionMsg(Exception, defaulttext)
Definition exceptions.h:489
static ::ExceptionBase & ExcDivideByZero()
static ::ExceptionBase & ExcDifferentBlockIndices()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static const bool value
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
const types::global_dof_index invalid_size_type
Definition types.h:233
STL namespace.
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
Definition types.h:32
unsigned int global_dof_index
Definition types.h:81