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
petsc_vector_base.cc
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
14
15#ifdef DEAL_II_WITH_PETSC
16
18
22
23# include <boost/container/small_vector.hpp>
24
25# include <cmath>
26
27#endif // DEAL_II_WITH_PETSC
28
30
31#ifdef DEAL_II_WITH_PETSC
32
33namespace PETScWrappers
34{
35 namespace internal
36 {
37# ifndef DOXYGEN
38 VectorReference::operator PetscScalar() const
39 {
40 AssertIndexRange(index, vector.size());
41
42 // The vector may have ghost entries. In that case, we first need to
43 // figure out which elements we own locally, then get a pointer to the
44 // elements that are stored here (both the ones we own as well as the
45 // ghost elements). In this array, the locally owned elements come first
46 // followed by the ghost elements whose position we can get from an
47 // index set.
48 if (vector.ghosted)
49 {
50 PetscInt begin, end;
51 PetscErrorCode ierr =
52 VecGetOwnershipRange(vector.vector, &begin, &end);
53 AssertThrow(ierr == 0, ExcPETScError(ierr));
54
55 Vec locally_stored_elements = nullptr;
56 ierr = VecGhostGetLocalForm(vector.vector, &locally_stored_elements);
57 AssertThrow(ierr == 0, ExcPETScError(ierr));
58
59 PetscInt lsize;
60 ierr = VecGetSize(locally_stored_elements, &lsize);
61 AssertThrow(ierr == 0, ExcPETScError(ierr));
62
63 const PetscScalar *ptr;
64 ierr = VecGetArrayRead(locally_stored_elements, &ptr);
65 AssertThrow(ierr == 0, ExcPETScError(ierr));
66
67 PetscScalar value;
68
69 if (index >= static_cast<size_type>(begin) &&
70 index < static_cast<size_type>(end))
71 {
72 // local entry
73 value = *(ptr + index - begin);
74 }
75 else
76 {
77 // ghost entry
78 Assert(vector.ghost_indices.is_element(index),
80 "You are trying to access an element of a vector "
81 "that is neither a locally owned element nor a "
82 "ghost element of the vector."));
83 const size_type ghostidx =
84 vector.ghost_indices.index_within_set(index);
85
86 AssertIndexRange(ghostidx + end - begin, lsize);
87 value = *(ptr + ghostidx + end - begin);
88 }
89
90 ierr = VecRestoreArrayRead(locally_stored_elements, &ptr);
91 AssertThrow(ierr == 0, ExcPETScError(ierr));
92
93 ierr =
94 VecGhostRestoreLocalForm(vector.vector, &locally_stored_elements);
95 AssertThrow(ierr == 0, ExcPETScError(ierr));
96
97 return value;
98 }
99
100
101 // first verify that the requested
102 // element is actually locally
103 // available
104 PetscInt begin, end;
105
106 PetscErrorCode ierr = VecGetOwnershipRange(vector.vector, &begin, &end);
107 AssertThrow(ierr == 0, ExcPETScError(ierr));
108
109 AssertThrow((index >= static_cast<size_type>(begin)) &&
110 (index < static_cast<size_type>(end)),
111 ExcAccessToNonlocalElement(index, begin, end - 1));
112
113 const PetscScalar *ptr;
114 PetscScalar value;
115 ierr = VecGetArrayRead(vector.vector, &ptr);
116 AssertThrow(ierr == 0, ExcPETScError(ierr));
117 value = *(ptr + index - begin);
118 ierr = VecRestoreArrayRead(vector.vector, &ptr);
119 AssertThrow(ierr == 0, ExcPETScError(ierr));
120
121 return value;
122 }
123# endif
124 } // namespace internal
125
127 : vector(nullptr)
128 , ghosted(false)
129 , last_action(VectorOperation::unknown)
130 , ghost_vector(nullptr)
131 , ghost_vector_array(nullptr)
132 {}
133
134
135
137 : ghosted(v.ghosted)
138 , ghost_indices(v.ghost_indices)
139 , last_action(VectorOperation::unknown)
140 , ghost_vector(nullptr)
141 , ghost_vector_array(nullptr)
142 {
143 PetscErrorCode ierr = VecDuplicate(v.vector, &vector);
144 AssertThrow(ierr == 0, ExcPETScError(ierr));
145
146 ierr = VecCopy(v.vector, vector);
147 AssertThrow(ierr == 0, ExcPETScError(ierr));
148 if (ghosted)
150 }
151
152
153
155 : vector(v)
156 , ghosted(false)
157 , last_action(VectorOperation::unknown)
158 , ghost_vector(nullptr)
159 , ghost_vector_array(nullptr)
160 {
161 const PetscErrorCode ierr =
162 PetscObjectReference(reinterpret_cast<PetscObject>(vector));
163 AssertNothrow(ierr == 0, ExcPETScError(ierr));
165 if (ghosted)
167 }
168
169
170
172 {
173 if (ghosted)
175
176 const PetscErrorCode ierr = VecDestroy(&vector);
177 AssertNothrow(ierr == 0, ExcPETScError(ierr));
178 }
179
180
181
182 void
184 {
186 ExcMessage("Cannot assign a new Vec"));
187
188 if (ghosted)
190
191 PetscErrorCode ierr =
192 PetscObjectReference(reinterpret_cast<PetscObject>(v));
193 AssertThrow(ierr == 0, ExcPETScError(ierr));
194 ierr = VecDestroy(&vector);
195 AssertThrow(ierr == 0, ExcPETScError(ierr));
196 vector = v;
198 if (ghosted)
200 }
201
202
203
204 namespace
205 {
206 template <typename Iterator, typename OutType>
207 class ConvertingIterator
208 {
209 Iterator m_iterator;
210
211 public:
212 using difference_type =
213 typename std::iterator_traits<Iterator>::difference_type;
214 using value_type = OutType;
215 using pointer = OutType *;
216 using reference = OutType &;
217 using iterator_category = std::forward_iterator_tag;
218
219 ConvertingIterator(const Iterator &iterator)
221 {}
222
223 OutType
224 operator*() const
225 {
226 return static_cast<OutType>(std::real(*m_iterator));
227 }
228
229 ConvertingIterator &
230 operator++()
231 {
232 ++m_iterator;
233 return *this;
234 }
235
236 ConvertingIterator
237 operator++(int)
238 {
239 ConvertingIterator old = *this;
240 ++m_iterator;
241 return old;
242 }
243
244 bool
245 operator==(const ConvertingIterator &other) const
246 {
247 return this->m_iterator == other.m_iterator;
248 }
249
250 bool
251 operator!=(const ConvertingIterator &other) const
252 {
253 return this->m_iterator != other.m_iterator;
254 }
255 };
256 } // namespace
257
258
259
260 void
262 {
263 // Reset ghost data
264 ghosted = false;
266
267 // There's no API to infer ghost indices from a PETSc Vec which
268 // unfortunately doesn't allow integer entries. We use the
269 // "ConvertingIterator" class above to do an implicit conversion when
270 // sorting and adding ghost indices below.
271 PetscErrorCode ierr;
272 Vec ghosted_vec;
273 ierr = VecGhostGetLocalForm(vector, &ghosted_vec);
274 AssertThrow(ierr == 0, ExcPETScError(ierr));
275 if (ghosted_vec && ghosted_vec != vector)
277 Vec tvector;
278 PetscScalar *array;
279 PetscInt ghost_start_index, end_index, n_elements_stored_locally;
280
281 ierr = VecGhostRestoreLocalForm(vector, &ghosted_vec);
282 AssertThrow(ierr == 0, ExcPETScError(ierr));
283
284 ierr = VecGetOwnershipRange(vector, &ghost_start_index, &end_index);
285 AssertThrow(ierr == 0, ExcPETScError(ierr));
286 ierr = VecDuplicate(vector, &tvector);
287 AssertThrow(ierr == 0, ExcPETScError(ierr));
288 ierr = VecGetArray(tvector, &array);
289 AssertThrow(ierr == 0, ExcPETScError(ierr));
290
291 // Store the indices we care about in the vector, so that we can then
292 // exchange this information between processes. It is unfortunate that
293 // we have to store integers in floating point numbers. Let's at least
294 // make sure we do that in a way that ensures that when we get these
295 // numbers back as integers later on, we get the same thing.
296 for (PetscInt i = 0; i < end_index - ghost_start_index; i++)
297 {
298 Assert(static_cast<PetscInt>(std::real(static_cast<PetscScalar>(
299 ghost_start_index + i))) == (ghost_start_index + i),
301 array[i] = ghost_start_index + i;
302 }
303
304 ierr = VecRestoreArray(tvector, &array);
305 AssertThrow(ierr == 0, ExcPETScError(ierr));
306 ierr = VecGhostUpdateBegin(tvector, INSERT_VALUES, SCATTER_FORWARD);
307 AssertThrow(ierr == 0, ExcPETScError(ierr));
308 ierr = VecGhostUpdateEnd(tvector, INSERT_VALUES, SCATTER_FORWARD);
309 AssertThrow(ierr == 0, ExcPETScError(ierr));
310 ierr = VecGhostGetLocalForm(tvector, &ghosted_vec);
311 AssertThrow(ierr == 0, ExcPETScError(ierr));
312 ierr = VecGetLocalSize(ghosted_vec, &n_elements_stored_locally);
313 AssertThrow(ierr == 0, ExcPETScError(ierr));
314 ierr = VecGetArrayRead(ghosted_vec, (const PetscScalar **)&array);
315 AssertThrow(ierr == 0, ExcPETScError(ierr));
316
317 // Populate the 'ghosted' flag and the ghost_indices variable. The
318 // latter is an index set that is most efficiently filled by
319 // sorting the indices to add. At the same time, we don't want to
320 // sort the indices stored in a PETSc-owned array; so if the array
321 // is already sorted, pass that to the IndexSet variable, and if
322 // not then copy the indices, sort them, and then add those.
323 ghosted = true;
324 ghost_indices.set_size(this->size());
325
326 ConvertingIterator<PetscScalar *, types::global_dof_index> begin_ghosts(
327 &array[end_index - ghost_start_index]);
328 ConvertingIterator<PetscScalar *, types::global_dof_index> end_ghosts(
329 &array[n_elements_stored_locally]);
330 if (std::is_sorted(&array[end_index - ghost_start_index],
331 &array[n_elements_stored_locally],
332 [](PetscScalar left, PetscScalar right) {
333 return static_cast<PetscInt>(std::real(left)) <
334 static_cast<PetscInt>(std::real(right));
335 }))
336 {
337 ghost_indices.add_indices(begin_ghosts, end_ghosts);
338 }
339 else
340 {
341 std::vector<PetscInt> sorted_indices(begin_ghosts, end_ghosts);
342 std::sort(sorted_indices.begin(), sorted_indices.end());
343 ghost_indices.add_indices(sorted_indices.begin(),
344 sorted_indices.end());
347
348 ierr = VecRestoreArrayRead(ghosted_vec, (const PetscScalar **)&array);
349 AssertThrow(ierr == 0, ExcPETScError(ierr));
350 ierr = VecGhostRestoreLocalForm(tvector, &ghosted_vec);
351 AssertThrow(ierr == 0, ExcPETScError(ierr));
352 ierr = VecDestroy(&tvector);
353 AssertThrow(ierr == 0, ExcPETScError(ierr));
354 }
355 else
356 {
357 ierr = VecGhostRestoreLocalForm(vector, &ghosted_vec);
358 AssertThrow(ierr == 0, ExcPETScError(ierr));
359 }
360 }
361
362
363
364 void
366 {
367 AssertThrow(ghosted, ExcMessage("Vector is not ghosted"));
368
369 AssertThrow(ghost_vector == nullptr && ghost_vector_array == nullptr,
371 "Ghost vector is already acquired for the vector."));
372
373 PetscErrorCode ierr = VecGhostGetLocalForm(vector, &ghost_vector);
374 AssertThrow(ierr == 0, ExcPETScError(ierr));
375 ierr = VecGetArrayRead(ghost_vector, &ghost_vector_array);
376 AssertThrow(ierr == 0, ExcPETScError(ierr));
377 }
378
379
380
381 void
383 {
384 AssertThrow(ghost_vector != nullptr,
385 ExcInternalError("Ghost vector is not acquired"));
386
387 PetscErrorCode ierr =
388 VecRestoreArrayRead(ghost_vector, &ghost_vector_array);
389 AssertThrow(ierr == 0, ExcPETScError(ierr));
390 ierr = VecGhostRestoreLocalForm(vector, &ghost_vector);
391 AssertThrow(ierr == 0, ExcPETScError(ierr));
392
393 ghost_vector = nullptr;
394 ghost_vector_array = nullptr;
395 }
396
397
398
399 void
401 {
402 if (ghosted)
404
405 const PetscErrorCode ierr = VecDestroy(&vector);
406 AssertThrow(ierr == 0, ExcPETScError(ierr));
407
408 ghosted = false;
411 }
412
413
414
415 VectorBase &
417 {
418 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
419
420 PetscErrorCode ierr = VecCopy(v, vector);
421 AssertThrow(ierr == 0, ExcPETScError(ierr));
422
423 return *this;
424 }
425
426
427
428 VectorBase &
429 VectorBase::operator=(const PetscScalar s)
430 {
431 if (s != PetscScalar(0))
434
435 // TODO[TH]: assert(is_compressed())
436
437 // First set the elements of the locally owned part of
438 // the vector to 's':
439 PetscErrorCode ierr = VecSet(vector, s);
440 AssertThrow(ierr == 0, ExcPETScError(ierr));
441
442 // If the vector has ghost elements, then the assertion
443 // above checks that s==0. In that case, we're simply
444 // zeroing out the entire vector and need to also do
445 // that for the ghost entries of the vector.
446 if (has_ghost_elements())
447 {
448 Vec ghost = nullptr;
449 ierr = VecGhostGetLocalForm(vector, &ghost);
450 AssertThrow(ierr == 0, ExcPETScError(ierr));
451
452 ierr = VecSet(ghost, s);
453 AssertThrow(ierr == 0, ExcPETScError(ierr));
454
455 ierr = VecGhostRestoreLocalForm(vector, &ghost);
456 AssertThrow(ierr == 0, ExcPETScError(ierr));
457 }
458
459 return *this;
460 }
461
462
463
464 bool
466 {
467 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
468
469 PetscBool flag;
470 const PetscErrorCode ierr = VecEqual(vector, v.vector, &flag);
471 AssertThrow(ierr == 0, ExcPETScError(ierr));
472
473 return (flag == PETSC_TRUE);
474 }
475
476
477
478 bool
480 {
481 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
482
483 PetscBool flag;
484 const PetscErrorCode ierr = VecEqual(vector, v.vector, &flag);
485 AssertThrow(ierr == 0, ExcPETScError(ierr));
486
487 return (flag == PETSC_FALSE);
488 }
489
490
491
494 {
495 PetscInt sz;
496 const PetscErrorCode ierr = VecGetSize(vector, &sz);
497 AssertThrow(ierr == 0, ExcPETScError(ierr));
498
499 return sz;
500 }
501
502
503
506 {
507 PetscInt sz;
508 const PetscErrorCode ierr = VecGetLocalSize(vector, &sz);
509 AssertThrow(ierr == 0, ExcPETScError(ierr));
510
511 return sz;
512 }
513
514
515
516 std::pair<VectorBase::size_type, VectorBase::size_type>
518 {
519 PetscInt begin, end;
520 const PetscErrorCode ierr =
521 VecGetOwnershipRange(static_cast<const Vec &>(vector), &begin, &end);
522 AssertThrow(ierr == 0, ExcPETScError(ierr));
523
524 return std::make_pair(begin, end);
525 }
526
527
528
529 void
530 VectorBase::set(const std::vector<size_type> &indices,
531 const std::vector<PetscScalar> &values)
532 {
533 Assert(indices.size() == values.size(),
534 ExcMessage("Function called with arguments of different sizes"));
535 do_set_add_operation(indices.size(), indices.data(), values.data(), false);
536 }
537
538
539
540 void
541 VectorBase::add(const std::vector<size_type> &indices,
542 const std::vector<PetscScalar> &values)
543 {
544 Assert(indices.size() == values.size(),
545 ExcMessage("Function called with arguments of different sizes"));
546 do_set_add_operation(indices.size(), indices.data(), values.data(), true);
547 }
548
549
550
551 void
552 VectorBase::add(const std::vector<size_type> &indices,
553 const ::Vector<PetscScalar> &values)
554 {
555 Assert(indices.size() == values.size(),
556 ExcMessage("Function called with arguments of different sizes"));
557 do_set_add_operation(indices.size(), indices.data(), values.begin(), true);
558 }
559
560
561
562 void
563 VectorBase::add(const size_type n_elements,
564 const size_type *indices,
565 const PetscScalar *values)
566 {
567 do_set_add_operation(n_elements, indices, values, true);
568 }
569
570
571
572 PetscScalar
574 {
575 Assert(size() == vec.size(), ExcDimensionMismatch(size(), vec.size()));
576
577 PetscScalar result;
578
579 // For complex vectors, VecDot() computes
580 // val = (x,y) = y^H x,
581 // where y^H denotes the conjugate transpose of y.
582 // Note that this corresponds to the usual "mathematicians'"
583 // complex inner product where the SECOND argument gets the
584 // complex conjugate, which is also how we document this
585 // operation.
586 const PetscErrorCode ierr = VecDot(vec.vector, vector, &result);
587 AssertThrow(ierr == 0, ExcPETScError(ierr));
588
589 return result;
590 }
591
592
593
594 PetscScalar
595 VectorBase::add_and_dot(const PetscScalar a,
596 const VectorBase &V,
597 const VectorBase &W)
598 {
599 this->add(a, V);
600 return *this * W;
601 }
602
603
604
605 void
607 {
608 Assert(has_ghost_elements() == false,
609 ExcMessage("Calling compress() is only useful if a vector "
610 "has been written into, but this is a vector with ghost "
611 "elements and consequently is read-only. It does "
612 "not make sense to call compress() for such "
613 "vectors."));
614
615 {
616 if constexpr (running_in_debug_mode())
617 {
618 // Check that all processors agree that last_action is the same (or
619 // none!)
620
621 int my_int_last_action = last_action;
622 int all_int_last_action;
623
624 const int ierr = MPI_Allreduce(&my_int_last_action,
625 &all_int_last_action,
626 1,
627 MPI_INT,
628 MPI_BOR,
630 AssertThrowMPI(ierr);
631
632 AssertThrow(all_int_last_action !=
635 "Error: not all processors agree on the last "
636 "VectorOperation before this compress() call."));
637 }
638 }
639
643 "Missing compress() or calling with wrong VectorOperation argument."));
644
645 // note that one may think that
646 // we only need to do something
647 // if in fact the state is
648 // anything but
649 // last_action::unknown. but
650 // that's not true: one
651 // frequently gets into
652 // situations where only one
653 // processor (or a subset of
654 // processors) actually writes
655 // something into a vector, but
656 // we still need to call
657 // VecAssemblyBegin/End on all
658 // processors.
659 PetscErrorCode ierr = VecAssemblyBegin(vector);
660 AssertThrow(ierr == 0, ExcPETScError(ierr));
661 ierr = VecAssemblyEnd(vector);
662 AssertThrow(ierr == 0, ExcPETScError(ierr));
663
664 // reset the last action field to
665 // indicate that we're back to a
666 // pristine state
668 }
669
670
671
674 {
675 const real_type d = l2_norm();
676 return d * d;
677 }
678
679
680
681 PetscScalar
683 {
684 // We can only use our more efficient
685 // routine in the serial case.
686 if (dynamic_cast<const PETScWrappers::MPI::Vector *>(this) != nullptr)
687 {
688 PetscScalar sum;
689 const PetscErrorCode ierr = VecSum(vector, &sum);
690 AssertThrow(ierr == 0, ExcPETScError(ierr));
691 return sum / static_cast<PetscReal>(size());
692 }
693
694 // get a representation of the vector and
695 // loop over all the elements
696 const PetscScalar *start_ptr;
697 PetscErrorCode ierr = VecGetArrayRead(vector, &start_ptr);
698 AssertThrow(ierr == 0, ExcPETScError(ierr));
699
700 PetscScalar mean = 0;
701 {
702 PetscScalar 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 {
711 sum0 += *ptr++;
712 sum1 += *ptr++;
713 sum2 += *ptr++;
714 sum3 += *ptr++;
715 }
716 // add up remaining elements
717 while (ptr != start_ptr + locally_owned_size())
718 sum0 += *ptr++;
719
720 mean =
721 Utilities::MPI::sum(sum0 + sum1 + sum2 + sum3, get_mpi_communicator()) /
722 static_cast<PetscReal>(size());
723 }
724
725 // restore the representation of the
726 // vector
727 ierr = VecRestoreArrayRead(vector, &start_ptr);
728 AssertThrow(ierr == 0, ExcPETScError(ierr));
729
730 return mean;
731 }
732
733
736 {
737 real_type d;
738
739 const PetscErrorCode ierr = VecNorm(vector, NORM_1, &d);
740 AssertThrow(ierr == 0, ExcPETScError(ierr));
741
742 return d;
743 }
744
745
746
749 {
750 real_type d;
751
752 const PetscErrorCode ierr = VecNorm(vector, NORM_2, &d);
753 AssertThrow(ierr == 0, ExcPETScError(ierr));
754
755 return d;
756 }
757
758
759
762 {
763 // get a representation of the vector and
764 // loop over all the elements
765 const PetscScalar *start_ptr;
766 PetscErrorCode ierr = VecGetArrayRead(vector, &start_ptr);
767 AssertThrow(ierr == 0, ExcPETScError(ierr));
768
769 real_type norm = 0;
770 {
771 real_type sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;
772
773 // use modern processors better by
774 // allowing pipelined commands to be
775 // executed in parallel
776 const PetscScalar *ptr = start_ptr;
777 const PetscScalar *eptr = ptr + (locally_owned_size() / 4) * 4;
778 while (ptr != eptr)
779 {
784 }
785 // add up remaining elements
786 while (ptr != start_ptr + locally_owned_size())
788
789 norm = std::pow(Utilities::MPI::sum(sum0 + sum1 + sum2 + sum3,
791 1. / p);
792 }
793
794 // restore the representation of the
795 // vector
796 ierr = VecRestoreArrayRead(vector, &start_ptr);
797 AssertThrow(ierr == 0, ExcPETScError(ierr));
798
799 return norm;
800 }
801
802
803
806 {
807 real_type d;
808
809 const PetscErrorCode ierr = VecNorm(vector, NORM_INFINITY, &d);
810 AssertThrow(ierr == 0, ExcPETScError(ierr));
811
812 return d;
813 }
814
815
816
817 bool
819 {
820 const PetscScalar *start_ptr;
821 PetscErrorCode ierr = VecGetArrayRead(vector, &start_ptr);
822 AssertThrow(ierr == 0, ExcPETScError(ierr));
823
824 const bool local_all_zero =
825 std::all_of(start_ptr,
826 start_ptr + locally_owned_size(),
827 numbers::value_is_zero<PetscScalar>);
828
829 ierr = VecRestoreArrayRead(vector, &start_ptr);
830 AssertThrow(ierr == 0, ExcPETScError(ierr));
831
832 return Utilities::MPI::logical_and(local_all_zero, get_mpi_communicator());
833 }
834
835
836
837 VectorBase &
838 VectorBase::operator*=(const PetscScalar a)
839 {
842
843 const PetscErrorCode ierr = VecScale(vector, a);
844 AssertThrow(ierr == 0, ExcPETScError(ierr));
845
846 return *this;
847 }
848
849
850
851 VectorBase &
852 VectorBase::operator/=(const PetscScalar a)
853 {
856
857 const PetscScalar factor = 1. / a;
858 AssertIsFinite(factor);
859
860 const PetscErrorCode ierr = VecScale(vector, factor);
861 AssertThrow(ierr == 0, ExcPETScError(ierr));
862
863 return *this;
864 }
865
866
867
868 VectorBase &
870 {
872 const PetscErrorCode ierr = VecAXPY(vector, 1, v);
873 AssertThrow(ierr == 0, ExcPETScError(ierr));
874
875 return *this;
876 }
877
878
879
880 VectorBase &
882 {
884 const PetscErrorCode ierr = VecAXPY(vector, -1, v);
885 AssertThrow(ierr == 0, ExcPETScError(ierr));
886
887 return *this;
888 }
889
890
891
892 void
893 VectorBase::add(const PetscScalar s)
894 {
897
898 const PetscErrorCode ierr = VecShift(vector, s);
899 AssertThrow(ierr == 0, ExcPETScError(ierr));
900 }
901
902
903
904 void
905 VectorBase::add(const PetscScalar a, const VectorBase &v)
906 {
909
910 const PetscErrorCode ierr = VecAXPY(vector, a, v);
911 AssertThrow(ierr == 0, ExcPETScError(ierr));
912 }
913
914
915
916 void
917 VectorBase::add(const PetscScalar a,
918 const VectorBase &v,
919 const PetscScalar b,
920 const VectorBase &w)
921 {
925
926 const PetscScalar weights[2] = {a, b};
927 Vec addends[2] = {v.vector, w.vector};
928
929 const PetscErrorCode ierr = VecMAXPY(vector, 2, weights, addends);
930 AssertThrow(ierr == 0, ExcPETScError(ierr));
931 }
932
933
934
935 void
936 VectorBase::sadd(const PetscScalar s, const VectorBase &v)
937 {
940
941 const PetscErrorCode ierr = VecAYPX(vector, s, v);
942 AssertThrow(ierr == 0, ExcPETScError(ierr));
943 }
944
945
946
947 void
948 VectorBase::sadd(const PetscScalar s,
949 const PetscScalar a,
950 const VectorBase &v)
951 {
955
956 // there is nothing like a AXPAY
957 // operation in PETSc, so do it in two
958 // steps
959 *this *= s;
960 add(a, v);
961 }
962
963
964
965 void
967 {
969 const PetscErrorCode ierr = VecPointwiseMult(vector, factors, vector);
970 AssertThrow(ierr == 0, ExcPETScError(ierr));
971 }
972
973
974
975 void
976 VectorBase::equ(const PetscScalar a, const VectorBase &v)
977 {
980
981 Assert(size() == v.size(), ExcDimensionMismatch(size(), v.size()));
982
983 const PetscErrorCode ierr = VecAXPBY(vector, a, 0.0, v.vector);
984 AssertThrow(ierr == 0, ExcPETScError(ierr));
985 }
986
987
988
989 void
990 VectorBase::write_ascii(const PetscViewerFormat format)
991 {
992 // TODO[TH]:assert(is_compressed())
993 MPI_Comm comm = PetscObjectComm((PetscObject)vector);
994
995 // Set options
996 PetscErrorCode ierr =
997 PetscViewerPushFormat(PETSC_VIEWER_STDOUT_(comm), format);
998 AssertThrow(ierr == 0, ExcPETScError(ierr));
999
1000 // Write to screen
1001 ierr = VecView(vector, PETSC_VIEWER_STDOUT_(comm));
1002 AssertThrow(ierr == 0, ExcPETScError(ierr));
1003 ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_(comm));
1004 AssertThrow(ierr == 0, ExcPETScError(ierr));
1005 }
1006
1007
1008
1009 void
1010 VectorBase::print(std::ostream &out,
1011 const unsigned int precision,
1012 const bool scientific,
1013 const bool across) const
1014 {
1015 AssertThrow(out.fail() == false, ExcIO());
1016
1017 // get a representation of the vector and
1018 // loop over all the elements
1019 const PetscScalar *val;
1020 PetscErrorCode ierr = VecGetArrayRead(vector, &val);
1021
1022 AssertThrow(ierr == 0, ExcPETScError(ierr));
1023
1024 // save the state of out stream
1025 const std::ios::fmtflags old_flags = out.flags();
1026 const unsigned int old_precision = out.precision(precision);
1027
1028 out.precision(precision);
1029 if (scientific)
1030 out.setf(std::ios::scientific, std::ios::floatfield);
1031 else
1032 out.setf(std::ios::fixed, std::ios::floatfield);
1033
1034 if (across)
1035 for (size_type i = 0; i < locally_owned_size(); ++i)
1036 out << val[i] << ' ';
1037 else
1038 for (size_type i = 0; i < locally_owned_size(); ++i)
1039 out << val[i] << std::endl;
1040 out << std::endl;
1041
1042 // reset output format
1043 out.flags(old_flags);
1044 out.precision(old_precision);
1045
1046 // restore the representation of the
1047 // vector
1048 ierr = VecRestoreArrayRead(vector, &val);
1049 AssertThrow(ierr == 0, ExcPETScError(ierr));
1050
1051 AssertThrow(out.fail() == false, ExcIO());
1052 }
1053
1054
1055
1056 void
1058 {
1059 std::swap(this->vector, v.vector);
1060 std::swap(this->ghosted, v.ghosted);
1061 std::swap(this->last_action, v.last_action);
1062 // missing swap for IndexSet
1063 IndexSet t(this->ghost_indices);
1064 this->ghost_indices = v.ghost_indices;
1065 v.ghost_indices = std::move(t);
1066 std::swap(this->ghost_vector, v.ghost_vector);
1067 std::swap(this->ghost_vector_array, v.ghost_vector_array);
1068 }
1069
1070
1071 VectorBase::operator const Vec &() const
1072 {
1073 return vector;
1074 }
1075
1076
1077 Vec &
1079 {
1080 return vector;
1081 }
1082
1083
1084 std::size_t
1086 {
1087 std::size_t mem = sizeof(Vec) + sizeof(last_action) +
1090
1091 // TH: I am relatively sure that PETSc is
1092 // storing the local data in a contiguous
1093 // block without indices:
1094 mem += locally_owned_size() * sizeof(PetscScalar);
1095 // assume that PETSc is storing one index
1096 // and one double per ghost element
1097 if (ghosted)
1098 mem += ghost_indices.n_elements() * (sizeof(PetscScalar) + sizeof(int));
1099
1100 // TODO[TH]: size of constant memory for PETSc?
1101 return mem;
1102 }
1103
1104
1105
1106 void
1108 const size_type *indices,
1109 const PetscScalar *values,
1110 const bool add_values)
1111 {
1112 const VectorOperation::values action =
1115 internal::VectorReference::ExcWrongMode(action, last_action));
1117
1118 boost::container::small_vector<PetscInt, 200> petsc_indices(n_elements);
1119 for (size_type i = 0; i < n_elements; ++i)
1120 {
1121 const auto petsc_index = static_cast<PetscInt>(indices[i]);
1122 AssertIntegerConversion(petsc_index, indices[i]);
1123 petsc_indices[i] = petsc_index;
1124 }
1125
1126 const InsertMode mode = (add_values ? ADD_VALUES : INSERT_VALUES);
1127 const PetscErrorCode ierr = VecSetValues(
1128 vector, petsc_indices.size(), petsc_indices.data(), values, mode);
1129 AssertThrow(ierr == 0, ExcPETScError(ierr));
1130
1131 last_action = action;
1132 }
1133
1134} // namespace PETScWrappers
1135
1136
1137#endif // DEAL_II_WITH_PETSC
*  iterator end()
*  *  iterator begin()
*  *  reference operator*() const
std::ptrdiff_t difference_type
*  *  iterator & operator++()
*  *  iterator()=default
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:1917
void set_size(const size_type size)
Definition index_set.h:1747
void clear()
Definition index_set.h:1735
void compress() const
Definition index_set.h:1767
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1814
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)
const PetscScalar * ghost_vector_array
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
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
constexpr bool running_in_debug_mode()
Definition config.h:76
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define AssertIntegerConversion(index1, index2)
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)
const MPI_Comm comm
Definition mpi.cc:912
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
T sum(const T &t, const MPI_Comm mpi_communicator)
bool logical_and(const bool t, const MPI_Comm mpi_communicator)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
Iterator m_iterator