deal.II version GIT relicensing-1972-g22a7b89abe 2024-10-11 21:20: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
petsc_vector_base.cc
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2004 - 2023 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
16
17#ifdef DEAL_II_WITH_PETSC
18
20
24
25# include <cmath>
26
28
29namespace PETScWrappers
30{
31 namespace internal
32 {
33# ifndef DOXYGEN
34 VectorReference::operator PetscScalar() const
35 {
36 AssertIndexRange(index, vector.size());
37
38 // The vector may have ghost entries. In that case, we first need to
39 // figure out which elements we own locally, then get a pointer to the
40 // elements that are stored here (both the ones we own as well as the
41 // ghost elements). In this array, the locally owned elements come first
42 // followed by the ghost elements whose position we can get from an
43 // index set.
44 if (vector.ghosted)
45 {
46 PetscInt begin, end;
47 PetscErrorCode ierr =
48 VecGetOwnershipRange(vector.vector, &begin, &end);
49 AssertThrow(ierr == 0, ExcPETScError(ierr));
50
51 Vec locally_stored_elements = nullptr;
52 ierr = VecGhostGetLocalForm(vector.vector, &locally_stored_elements);
53 AssertThrow(ierr == 0, ExcPETScError(ierr));
54
55 PetscInt lsize;
56 ierr = VecGetSize(locally_stored_elements, &lsize);
57 AssertThrow(ierr == 0, ExcPETScError(ierr));
58
59 const PetscScalar *ptr;
60 ierr = VecGetArrayRead(locally_stored_elements, &ptr);
61 AssertThrow(ierr == 0, ExcPETScError(ierr));
62
63 PetscScalar value;
64
65 if (index >= static_cast<size_type>(begin) &&
66 index < static_cast<size_type>(end))
67 {
68 // local entry
69 value = *(ptr + index - begin);
70 }
71 else
72 {
73 // ghost entry
74 Assert(vector.ghost_indices.is_element(index),
76 "You are trying to access an element of a vector "
77 "that is neither a locally owned element nor a "
78 "ghost element of the vector."));
79 const size_type ghostidx =
80 vector.ghost_indices.index_within_set(index);
81
82 AssertIndexRange(ghostidx + end - begin, lsize);
83 value = *(ptr + ghostidx + end - begin);
84 }
85
86 ierr = VecRestoreArrayRead(locally_stored_elements, &ptr);
87 AssertThrow(ierr == 0, ExcPETScError(ierr));
88
89 ierr =
90 VecGhostRestoreLocalForm(vector.vector, &locally_stored_elements);
91 AssertThrow(ierr == 0, ExcPETScError(ierr));
92
93 return value;
94 }
95
96
97 // first verify that the requested
98 // element is actually locally
99 // available
100 PetscInt begin, end;
101
102 PetscErrorCode ierr = VecGetOwnershipRange(vector.vector, &begin, &end);
103 AssertThrow(ierr == 0, ExcPETScError(ierr));
104
105 AssertThrow((index >= static_cast<size_type>(begin)) &&
106 (index < static_cast<size_type>(end)),
107 ExcAccessToNonlocalElement(index, begin, end - 1));
108
109 const PetscScalar *ptr;
110 PetscScalar value;
111 ierr = VecGetArrayRead(vector.vector, &ptr);
112 AssertThrow(ierr == 0, ExcPETScError(ierr));
113 value = *(ptr + index - begin);
114 ierr = VecRestoreArrayRead(vector.vector, &ptr);
115 AssertThrow(ierr == 0, ExcPETScError(ierr));
116
117 return value;
118 }
119# endif
120 } // namespace internal
121
123 : vector(nullptr)
124 , ghosted(false)
125 , last_action(VectorOperation::unknown)
126 {}
127
128
129
131 : Subscriptor()
132 , ghosted(v.ghosted)
133 , ghost_indices(v.ghost_indices)
134 , last_action(VectorOperation::unknown)
135 {
138
141 }
142
143
144
146 : Subscriptor()
147 , vector(v)
148 , ghosted(false)
149 , last_action(VectorOperation::unknown)
150 {
151 const PetscErrorCode ierr =
152 PetscObjectReference(reinterpret_cast<PetscObject>(vector));
154 (void)ierr;
156 }
157
158
159
166
167
168
169 void
171 {
173 ExcMessage("Cannot assign a new Vec"));
175 PetscObjectReference(reinterpret_cast<PetscObject>(v));
179 vector = v;
181 }
182
183
184
185 namespace
186 {
187 template <typename Iterator, typename OutType>
188 class ConvertingIterator
189 {
190 Iterator m_iterator;
191
192 public:
193 using difference_type =
194 typename std::iterator_traits<Iterator>::difference_type;
195 using value_type = OutType;
196 using pointer = OutType *;
197 using reference = OutType &;
198 using iterator_category = std::forward_iterator_tag;
199
200 ConvertingIterator(const Iterator &iterator)
201 : m_iterator(iterator)
202 {}
203
204 OutType
205 operator*() const
206 {
207 return static_cast<OutType>(std::real(*m_iterator));
208 }
209
210 ConvertingIterator &
211 operator++()
212 {
213 ++m_iterator;
214 return *this;
215 }
216
217 ConvertingIterator
218 operator++(int)
219 {
220 ConvertingIterator old = *this;
221 ++m_iterator;
222 return old;
223 }
224
225 bool
226 operator==(const ConvertingIterator &other) const
227 {
228 return this->m_iterator == other.m_iterator;
229 }
230
231 bool
232 operator!=(const ConvertingIterator &other) const
233 {
234 return this->m_iterator != other.m_iterator;
235 }
236 };
237 } // namespace
238
239
240
241 void
243 {
244 // Reset ghost data
245 ghosted = false;
247
248 // There's no API to infer ghost indices from a PETSc Vec which
249 // unfortunately doesn't allow integer entries. We use the
250 // "ConvertingIterator" class above to do an implicit conversion when
251 // sorting and adding ghost indices below.
253 Vec ghosted_vec;
257 {
258 Vec tvector;
259 PetscScalar *array;
261
264
269 ierr = VecGetArray(tvector, &array);
271
272 // Store the indices we care about in the vector, so that we can then
273 // exchange this information between processes. It is unfortunate that
274 // we have to store integers in floating point numbers. Let's at least
275 // make sure we do that in a way that ensures that when we get these
276 // numbers back as integers later on, we get the same thing.
277 for (PetscInt i = 0; i < end_index - ghost_start_index; i++)
278 {
279 Assert(static_cast<PetscInt>(std::real(static_cast<PetscScalar>(
280 ghost_start_index + i))) == (ghost_start_index + i),
282 array[i] = ghost_start_index + i;
283 }
284
285 ierr = VecRestoreArray(tvector, &array);
295 ierr = VecGetArrayRead(ghosted_vec, (const PetscScalar **)&array);
297
298 // Populate the 'ghosted' flag and the ghost_indices variable. The
299 // latter is an index set that is most efficiently filled by
300 // sorting the indices to add. At the same time, we don't want to
301 // sort the indices stored in a PETSc-owned array; so if the array
302 // is already sorted, pass that to the IndexSet variable, and if
303 // not then copy the indices, sort them, and then add those.
304 ghosted = true;
305 ghost_indices.set_size(this->size());
306
308 &array[end_index - ghost_start_index]);
311 if (std::is_sorted(&array[end_index - ghost_start_index],
313 [](PetscScalar left, PetscScalar right) {
314 return static_cast<PetscInt>(std::real(left)) <
315 static_cast<PetscInt>(std::real(right));
316 }))
317 {
319 }
320 else
321 {
322 std::vector<PetscInt> sorted_indices(begin_ghosts, end_ghosts);
323 std::sort(sorted_indices.begin(), sorted_indices.end());
325 sorted_indices.end());
326 }
328
329 ierr = VecRestoreArrayRead(ghosted_vec, (const PetscScalar **)&array);
335 }
336 else
337 {
340 }
341 }
342
343
344 void
354
355
356
357 VectorBase &
359 {
360 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
361
364
365 return *this;
366 }
367
368
369
370 VectorBase &
371 VectorBase::operator=(const PetscScalar s)
372 {
374
375 // TODO[TH]: assert(is_compressed())
376
379
380 if (has_ghost_elements())
381 {
382 Vec ghost = nullptr;
385
386 ierr = VecSet(ghost, s);
388
391 }
392
393 return *this;
394 }
395
396
397
398 bool
400 {
401 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
402
403 PetscBool flag;
404 const PetscErrorCode ierr = VecEqual(vector, v.vector, &flag);
406
407 return (flag == PETSC_TRUE);
408 }
409
410
411
412 bool
414 {
415 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
416
417 PetscBool flag;
418 const PetscErrorCode ierr = VecEqual(vector, v.vector, &flag);
420
421 return (flag == PETSC_FALSE);
422 }
423
424
425
428 {
429 PetscInt sz;
432
433 return sz;
434 }
435
436
437
440 {
441 PetscInt sz;
444
445 return sz;
446 }
447
448
449
450 std::pair<VectorBase::size_type, VectorBase::size_type>
452 {
453 PetscInt begin, end;
454 const PetscErrorCode ierr =
455 VecGetOwnershipRange(static_cast<const Vec &>(vector), &begin, &end);
457
458 return std::make_pair(begin, end);
459 }
460
461
462
463 void
464 VectorBase::set(const std::vector<size_type> &indices,
465 const std::vector<PetscScalar> &values)
466 {
467 Assert(indices.size() == values.size(),
468 ExcMessage("Function called with arguments of different sizes"));
469 do_set_add_operation(indices.size(), indices.data(), values.data(), false);
470 }
471
472
473
474 void
475 VectorBase::add(const std::vector<size_type> &indices,
476 const std::vector<PetscScalar> &values)
477 {
478 Assert(indices.size() == values.size(),
479 ExcMessage("Function called with arguments of different sizes"));
480 do_set_add_operation(indices.size(), indices.data(), values.data(), true);
481 }
482
483
484
485 void
486 VectorBase::add(const std::vector<size_type> &indices,
487 const ::Vector<PetscScalar> &values)
488 {
489 Assert(indices.size() == values.size(),
490 ExcMessage("Function called with arguments of different sizes"));
491 do_set_add_operation(indices.size(), indices.data(), values.begin(), true);
492 }
493
494
495
496 void
497 VectorBase::add(const size_type n_elements,
498 const size_type *indices,
499 const PetscScalar *values)
500 {
501 do_set_add_operation(n_elements, indices, values, true);
502 }
503
504
505
506 PetscScalar
508 {
509 Assert(size() == vec.size(), ExcDimensionMismatch(size(), vec.size()));
510
511 PetscScalar result;
512
513 // For complex vectors, VecDot() computes
514 // val = (x,y) = y^H x,
515 // where y^H denotes the conjugate transpose of y.
516 // Note that this corresponds to the usual "mathematicians'"
517 // complex inner product where the SECOND argument gets the
518 // complex conjugate, which is also how we document this
519 // operation.
520 const PetscErrorCode ierr = VecDot(vec.vector, vector, &result);
522
523 return result;
524 }
525
526
527
528 PetscScalar
529 VectorBase::add_and_dot(const PetscScalar a,
530 const VectorBase &V,
531 const VectorBase &W)
532 {
533 this->add(a, V);
534 return *this * W;
535 }
536
537
538
539 void
541 {
542 Assert(has_ghost_elements() == false,
543 ExcMessage("Calling compress() is only useful if a vector "
544 "has been written into, but this is a vector with ghost "
545 "elements and consequently is read-only. It does "
546 "not make sense to call compress() for such "
547 "vectors."));
548
549 {
550# ifdef DEBUG
551 // Check that all processors agree that last_action is the same (or none!)
552
555
558 1,
559 MPI_INT,
560 MPI_BOR,
563
566 ExcMessage("Error: not all processors agree on the last "
567 "VectorOperation before this compress() call."));
568# endif
569 }
570
574 "Missing compress() or calling with wrong VectorOperation argument."));
575
576 // note that one may think that
577 // we only need to do something
578 // if in fact the state is
579 // anything but
580 // last_action::unknown. but
581 // that's not true: one
582 // frequently gets into
583 // situations where only one
584 // processor (or a subset of
585 // processors) actually writes
586 // something into a vector, but
587 // we still need to call
588 // VecAssemblyBegin/End on all
589 // processors.
594
595 // reset the last action field to
596 // indicate that we're back to a
597 // pristine state
599 }
600
601
602
605 {
606 const real_type d = l2_norm();
607 return d * d;
608 }
609
610
611
612 PetscScalar
614 {
615 // We can only use our more efficient
616 // routine in the serial case.
617 if (dynamic_cast<const PETScWrappers::MPI::Vector *>(this) != nullptr)
618 {
619 PetscScalar sum;
620 const PetscErrorCode ierr = VecSum(vector, &sum);
622 return sum / static_cast<PetscReal>(size());
623 }
624
625 // get a representation of the vector and
626 // loop over all the elements
627 const PetscScalar *start_ptr;
630
631 PetscScalar mean = 0;
632 {
633 PetscScalar sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;
634
635 // use modern processors better by
636 // allowing pipelined commands to be
637 // executed in parallel
638 const PetscScalar *ptr = start_ptr;
639 const PetscScalar *eptr = ptr + (locally_owned_size() / 4) * 4;
640 while (ptr != eptr)
641 {
642 sum0 += *ptr++;
643 sum1 += *ptr++;
644 sum2 += *ptr++;
645 sum3 += *ptr++;
646 }
647 // add up remaining elements
648 while (ptr != start_ptr + locally_owned_size())
649 sum0 += *ptr++;
650
651 mean =
653 static_cast<PetscReal>(size());
654 }
655
656 // restore the representation of the
657 // vector
660
661 return mean;
662 }
663
664
667 {
668 real_type d;
669
672
673 return d;
674 }
675
676
677
680 {
681 real_type d;
682
685
686 return d;
687 }
688
689
690
693 {
694 // get a representation of the vector and
695 // loop over all the elements
696 const PetscScalar *start_ptr;
699
700 real_type norm = 0;
701 {
702 real_type sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;
703
704 // use modern processors better by
705 // allowing pipelined commands to be
706 // executed in parallel
707 const PetscScalar *ptr = start_ptr;
708 const PetscScalar *eptr = ptr + (locally_owned_size() / 4) * 4;
709 while (ptr != eptr)
710 {
715 }
716 // add up remaining elements
717 while (ptr != start_ptr + locally_owned_size())
719
722 1. / p);
723 }
724
725 // restore the representation of the
726 // vector
729
730 return norm;
731 }
732
733
734
737 {
738 real_type d;
739
742
743 return d;
744 }
745
746
747
748 bool
750 {
751 // get a representation of the vector and
752 // loop over all the elements
753 const PetscScalar *start_ptr;
756
757 const PetscScalar *ptr = start_ptr,
759 bool flag = true;
760 while (ptr != eptr)
761 {
762 if (*ptr != value_type())
763 {
764 flag = false;
765 break;
766 }
767 ++ptr;
768 }
769
770 // restore the representation of the
771 // vector
774
775 return flag;
776 }
777
778
779 namespace internal
780 {
781 template <typename T>
782 bool
783 is_non_negative(const T &t)
784 {
785 return t >= 0;
786 }
787
788
789
790 template <typename T>
791 bool
792 is_non_negative(const std::complex<T> &)
793 {
794 Assert(false,
795 ExcMessage("You can't ask a complex value "
796 "whether it is non-negative."));
797 return true;
798 }
799 } // namespace internal
800
801
802
803 VectorBase &
804 VectorBase::operator*=(const PetscScalar a)
805 {
808
811
812 return *this;
813 }
814
815
816
817 VectorBase &
818 VectorBase::operator/=(const PetscScalar a)
819 {
822
823 const PetscScalar factor = 1. / a;
824 AssertIsFinite(factor);
825
826 const PetscErrorCode ierr = VecScale(vector, factor);
828
829 return *this;
830 }
831
832
833
834 VectorBase &
836 {
838 const PetscErrorCode ierr = VecAXPY(vector, 1, v);
840
841 return *this;
842 }
843
844
845
846 VectorBase &
848 {
850 const PetscErrorCode ierr = VecAXPY(vector, -1, v);
852
853 return *this;
854 }
855
856
857
858 void
859 VectorBase::add(const PetscScalar s)
860 {
863
866 }
867
868
869
870 void
871 VectorBase::add(const PetscScalar a, const VectorBase &v)
872 {
875
876 const PetscErrorCode ierr = VecAXPY(vector, a, v);
878 }
879
880
881
882 void
883 VectorBase::add(const PetscScalar a,
884 const VectorBase &v,
885 const PetscScalar b,
886 const VectorBase &w)
887 {
891
892 const PetscScalar weights[2] = {a, b};
893 Vec addends[2] = {v.vector, w.vector};
894
895 const PetscErrorCode ierr = VecMAXPY(vector, 2, weights, addends);
897 }
898
899
900
901 void
902 VectorBase::sadd(const PetscScalar s, const VectorBase &v)
903 {
906
907 const PetscErrorCode ierr = VecAYPX(vector, s, v);
909 }
910
911
912
913 void
914 VectorBase::sadd(const PetscScalar s,
915 const PetscScalar a,
916 const VectorBase &v)
917 {
921
922 // there is nothing like a AXPAY
923 // operation in PETSc, so do it in two
924 // steps
925 *this *= s;
926 add(a, v);
927 }
928
929
930
931 void
938
939
940
941 void
942 VectorBase::equ(const PetscScalar a, const VectorBase &v)
943 {
946
947 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
948
949 const PetscErrorCode ierr = VecAXPBY(vector, a, 0.0, v.vector);
951 }
952
953
954
955 void
956 VectorBase::write_ascii(const PetscViewerFormat format)
957 {
958 // TODO[TH]:assert(is_compressed())
960
961 // Set options
965
966 // Write to screen
971 }
972
973
974
975 void
976 VectorBase::print(std::ostream &out,
977 const unsigned int precision,
978 const bool scientific,
979 const bool across) const
980 {
981 AssertThrow(out.fail() == false, ExcIO());
982
983 // get a representation of the vector and
984 // loop over all the elements
985 const PetscScalar *val;
987
989
990 // save the state of out stream
991 const std::ios::fmtflags old_flags = out.flags();
992 const unsigned int old_precision = out.precision(precision);
993
994 out.precision(precision);
995 if (scientific)
996 out.setf(std::ios::scientific, std::ios::floatfield);
997 else
998 out.setf(std::ios::fixed, std::ios::floatfield);
999
1000 if (across)
1001 for (size_type i = 0; i < locally_owned_size(); ++i)
1002 out << val[i] << ' ';
1003 else
1004 for (size_type i = 0; i < locally_owned_size(); ++i)
1005 out << val[i] << std::endl;
1006 out << std::endl;
1007
1008 // reset output format
1009 out.flags(old_flags);
1010 out.precision(old_precision);
1011
1012 // restore the representation of the
1013 // vector
1016
1017 AssertThrow(out.fail() == false, ExcIO());
1018 }
1019
1020
1021
1022 void
1024 {
1025 std::swap(this->vector, v.vector);
1026 std::swap(this->ghosted, v.ghosted);
1027 std::swap(this->last_action, v.last_action);
1028 // missing swap for IndexSet
1029 IndexSet t(this->ghost_indices);
1030 this->ghost_indices = v.ghost_indices;
1031 v.ghost_indices = t;
1032 }
1033
1034
1035 VectorBase::operator const Vec &() const
1036 {
1037 return vector;
1038 }
1039
1040
1041 Vec &
1043 {
1044 return vector;
1045 }
1046
1047
1048 std::size_t
1050 {
1051 std::size_t mem = sizeof(Vec) + sizeof(last_action) +
1054
1055 // TH: I am relatively sure that PETSc is
1056 // storing the local data in a contiguous
1057 // block without indices:
1058 mem += locally_owned_size() * sizeof(PetscScalar);
1059 // assume that PETSc is storing one index
1060 // and one double per ghost element
1061 if (ghosted)
1062 mem += ghost_indices.n_elements() * (sizeof(PetscScalar) + sizeof(int));
1063
1064 // TODO[TH]: size of constant memory for PETSc?
1065 return mem;
1066 }
1067
1068
1069
1070 void
1072 const size_type *indices,
1073 const PetscScalar *values,
1074 const bool add_values)
1075 {
1079 internal::VectorReference::ExcWrongMode(action, last_action));
1081
1082 std::vector<PetscInt> petsc_indices(n_elements);
1083 for (size_type i = 0; i < n_elements; ++i)
1084 {
1085 const auto petsc_index = static_cast<PetscInt>(indices[i]);
1088 }
1089
1090 const InsertMode mode = (add_values ? ADD_VALUES : INSERT_VALUES);
1092 vector, petsc_indices.size(), petsc_indices.data(), values, mode);
1094
1096 }
1097
1098} // namespace PETScWrappers
1099
1101
1102#endif // DEAL_II_WITH_PETSC
bool operator!=(const AlignedVector< T > &lhs, const AlignedVector< T > &rhs)
bool operator==(const AlignedVector< T > &lhs, const AlignedVector< T > &rhs)
size_type n_elements() const
Definition index_set.h:1934
void set_size(const size_type size)
Definition index_set.h:1764
void clear()
Definition index_set.h:1752
void compress() const
Definition index_set.h:1784
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1831
real_type lp_norm(const real_type p) const
VectorBase & operator+=(const VectorBase &V)
PetscScalar mean_value() const
VectorOperation::values last_action
PetscScalar operator*(const VectorBase &vec) const
bool operator==(const VectorBase &v) const
VectorBase & operator*=(const PetscScalar factor)
VectorBase & operator-=(const VectorBase &V)
bool operator!=(const VectorBase &v) const
std::size_t memory_consumption() const
VectorBase & operator/=(const PetscScalar factor)
MPI_Comm get_mpi_communicator() const
void scale(const VectorBase &scaling_factors)
std::pair< size_type, size_type > local_range() const
void sadd(const PetscScalar s, const VectorBase &V)
void compress(const VectorOperation::values operation)
void set(const std::vector< size_type > &indices, const std::vector< PetscScalar > &values)
void print(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const bool across=true) const
PetscScalar add_and_dot(const PetscScalar a, const VectorBase &V, const VectorBase &W)
void swap(VectorBase &v) noexcept
void add(const std::vector< size_type > &indices, const std::vector< PetscScalar > &values)
void write_ascii(const PetscViewerFormat format=PETSC_VIEWER_DEFAULT)
bool has_ghost_elements() const
size_type locally_owned_size() const
void equ(const PetscScalar a, const VectorBase &V)
void do_set_add_operation(const size_type n_elements, const size_type *indices, const PetscScalar *values, const bool add_values)
VectorBase & operator=(const VectorBase &)
size_type size() const override
std::enable_if_t< std::is_floating_point_v< T > &&std::is_floating_point_v< U >, typename ProductType< std::complex< T >, std::complex< U > >::type > operator*(const std::complex< T > &left, const std::complex< U > &right)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:498
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:499
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcGhostsPresent()
#define Assert(cond, exc)
#define AssertIsFinite(number)
#define AssertThrowMPI(error_code)
#define AssertNothrow(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
#define AssertIntegerConversion(index1, index2)
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
bool is_non_negative(const T &t)
T sum(const T &t, const MPI_Comm mpi_communicator)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
*braid_SplitCommworld & comm
Iterator m_iterator
SynchronousIterators< Iterators > operator++(SynchronousIterators< Iterators > &a)