libMesh
petsc_vector.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 
21 #ifndef LIBMESH_PETSC_VECTOR_H
22 #define LIBMESH_PETSC_VECTOR_H
23 
24 
25 #include "libmesh/libmesh_config.h"
26 
27 #ifdef LIBMESH_HAVE_PETSC
28 
29 // Local includes
30 #include "libmesh/numeric_vector.h"
31 #include "libmesh/petsc_macro.h"
32 #include "libmesh/int_range.h"
33 #include "libmesh/libmesh_common.h"
34 #include "libmesh/petsc_solver_exception.h"
35 #include "libmesh/parallel_only.h"
36 #include "libmesh/enum_to_string.h"
37 
38 // PETSc include files.
39 #ifdef I
40 # define LIBMESH_SAW_I
41 #endif
42 #include <petscvec.h>
43 #ifndef LIBMESH_SAW_I
44 # undef I // Avoid complex.h contamination
45 #endif
46 
47 // C++ includes
48 #include <cstddef>
49 #include <cstring>
50 #include <vector>
51 #include <unordered_map>
52 #include <limits>
53 
54 #include <atomic>
55 #include <mutex>
56 #include <condition_variable>
57 
58 namespace libMesh
59 {
60 
61 // forward declarations
62 template <typename T> class SparseMatrix;
63 
72 template <typename T>
73 class PetscVector final : public NumericVector<T>
74 {
75 public:
76 
80  explicit
81  PetscVector (const Parallel::Communicator & comm_in,
82  const ParallelType type = AUTOMATIC);
83 
87  explicit
88  PetscVector (const Parallel::Communicator & comm_in,
89  const numeric_index_type n,
90  const ParallelType type = AUTOMATIC);
91 
96  PetscVector (const Parallel::Communicator & comm_in,
97  const numeric_index_type n,
98  const numeric_index_type n_local,
99  const ParallelType type = AUTOMATIC);
100 
106  PetscVector (const Parallel::Communicator & comm_in,
107  const numeric_index_type N,
108  const numeric_index_type n_local,
109  const std::vector<numeric_index_type> & ghost,
110  const ParallelType type = AUTOMATIC);
111 
119  PetscVector(Vec v,
120  const Parallel::Communicator & comm_in);
121 
132 
138  PetscVector (PetscVector &&) = delete;
139  PetscVector (const PetscVector &) = delete;
140  PetscVector & operator= (PetscVector &&) = delete;
141  virtual ~PetscVector ();
142 
143  virtual void close () override;
144 
148  virtual void clear () noexcept override;
149 
150  virtual void zero () override;
151 
152  virtual std::unique_ptr<NumericVector<T>> zero_clone () const override;
153 
154  virtual std::unique_ptr<NumericVector<T>> clone () const override;
155 
156  virtual void init (const numeric_index_type N,
157  const numeric_index_type n_local,
158  const bool fast=false,
159  const ParallelType type=AUTOMATIC) override;
160 
161  virtual void init (const numeric_index_type N,
162  const bool fast=false,
163  const ParallelType type=AUTOMATIC) override;
164 
165  virtual void init (const numeric_index_type N,
166  const numeric_index_type n_local,
167  const std::vector<numeric_index_type> & ghost,
168  const bool fast = false,
169  const ParallelType = AUTOMATIC) override;
170 
171  virtual void init (const NumericVector<T> & other,
172  const bool fast = false) override;
173 
174  virtual NumericVector<T> & operator= (const T s) override;
175 
176  virtual NumericVector<T> & operator= (const NumericVector<T> & v) override;
177 
178  virtual NumericVector<T> & operator= (const std::vector<T> & v) override;
179 
180  virtual Real min () const override;
181 
182  virtual Real max () const override;
183 
184  virtual T sum () const override;
185 
186  virtual Real l1_norm () const override;
187 
188  virtual Real l2_norm () const override;
189 
190  virtual Real linfty_norm () const override;
191 
192  virtual numeric_index_type size () const override;
193 
194  virtual numeric_index_type local_size() const override;
195 
196  virtual numeric_index_type first_local_index() const override;
197 
198  virtual numeric_index_type last_local_index() const override;
199 
208 
209  virtual T operator() (const numeric_index_type i) const override;
210 
211  virtual void get(const std::vector<numeric_index_type> & index,
212  T * values) const override;
213 
220  PetscScalar * get_array();
221 
228  const PetscScalar * get_array_read() const;
229 
236  void restore_array();
237 
238  virtual NumericVector<T> & operator += (const NumericVector<T> & v) override;
239 
240  virtual NumericVector<T> & operator -= (const NumericVector<T> & v) override;
241 
242  virtual void reciprocal() override;
243 
244  virtual void conjugate() override;
245 
246  virtual void set (const numeric_index_type i,
247  const T value) override;
248 
249  virtual void add (const numeric_index_type i,
250  const T value) override;
251 
252  virtual void add (const T s) override;
253 
254  virtual void add (const NumericVector<T> & v) override;
255 
256  virtual void add (const T a, const NumericVector<T> & v) override;
257 
263 
264  virtual void add_vector (const T * v,
265  const std::vector<numeric_index_type> & dof_indices) override;
266 
267  virtual void add_vector (const NumericVector<T> & v,
268  const SparseMatrix<T> & A) override;
269 
270  virtual void add_vector_transpose (const NumericVector<T> & v,
271  const SparseMatrix<T> & A) override;
272 
280  const SparseMatrix<T> & A);
281 
287 
288  virtual void insert (const T * v,
289  const std::vector<numeric_index_type> & dof_indices) override;
290 
291  virtual void scale (const T factor) override;
292 
293  virtual NumericVector<T> & operator *= (const NumericVector<T> & v) override;
294 
295  virtual NumericVector<T> & operator /= (const NumericVector<T> & v) override;
296 
297  virtual void abs() override;
298 
299  virtual T dot(const NumericVector<T> & v) const override;
300 
306  T indefinite_dot(const NumericVector<T> & v) const;
307 
308  virtual void localize (std::vector<T> & v_local) const override;
309 
310  virtual void localize (NumericVector<T> & v_local) const override;
311 
312  virtual void localize (NumericVector<T> & v_local,
313  const std::vector<numeric_index_type> & send_list) const override;
314 
315  virtual void localize (std::vector<T> & v_local,
316  const std::vector<numeric_index_type> & indices) const override;
317 
318  virtual void localize (const numeric_index_type first_local_idx,
319  const numeric_index_type last_local_idx,
320  const std::vector<numeric_index_type> & send_list) override;
321 
322  virtual void localize_to_one (std::vector<T> & v_local,
323  const processor_id_type proc_id=0) const override;
324 
325  virtual void pointwise_mult (const NumericVector<T> & vec1,
326  const NumericVector<T> & vec2) override;
327 
328  virtual void pointwise_divide (const NumericVector<T> & vec1,
329  const NumericVector<T> & vec2) override;
330 
331  virtual void print_matlab(const std::string & name = "") const override;
332 
333  virtual void create_subvector(NumericVector<T> & subvector,
334  const std::vector<numeric_index_type> & rows,
335  bool supplying_global_rows = true) const override;
336 
337  virtual void swap (NumericVector<T> & v) override;
338 
339  virtual std::size_t max_allowed_id() const override;
340 
349  Vec vec () { libmesh_assert (_vec); return _vec; }
350 
351  Vec vec () const { libmesh_assert (_vec); return _vec; }
352 
353  virtual std::unique_ptr<NumericVector<T>>
354  get_subvector(const std::vector<numeric_index_type> & rows) override;
355 
356  virtual void restore_subvector(std::unique_ptr<NumericVector<T>> subvector,
357  const std::vector<numeric_index_type> & rows) override;
358 
359 private:
360 
364  Vec _vec;
365 
371 #ifdef LIBMESH_HAVE_CXX11_THREAD
372  // We can't use std::atomic_flag here because we need load and store operations.
373  mutable std::atomic<bool> _array_is_present;
374 #else
375  mutable bool _array_is_present;
376 #endif
377 
384 
391 
396 
402  mutable Vec _local_form;
403 
412  mutable const PetscScalar * _read_only_values;
413 
422  mutable PetscScalar * _values;
423 
429  mutable std::mutex _petsc_get_restore_array_mutex;
430 
437  void _get_array(bool read_only) const;
438 
443  void _restore_array() const;
444 
448  typedef std::unordered_map<numeric_index_type,numeric_index_type> GlobalToLocalMap;
449 
455 
461 
467 
471  mutable bool _values_read_only;
472 
479  template <NormType N> Real norm () const;
480 };
481 
482 
483 /*----------------------- Inline functions ----------------------------------*/
484 
485 
486 
487 template <typename T>
488 inline
490  NumericVector<T>(comm_in, ptype),
491  _vec(nullptr),
492  _array_is_present(false),
493  _first(0),
494  _last(0),
495  _local_size(0),
496  _local_form(nullptr),
497  _read_only_values(nullptr),
498  _values(nullptr),
499  _global_to_local_map(),
500  _destroy_vec_on_exit(true),
501  _values_manually_retrieved(false),
502  _values_read_only(false)
503 {
504  this->_type = ptype;
505 }
506 
507 
508 
509 template <typename T>
510 inline
512  const numeric_index_type n,
513  const ParallelType ptype) :
514  NumericVector<T>(comm_in, ptype),
515  _vec(nullptr),
516  _array_is_present(false),
517  _first(0),
518  _last(0),
519  _local_size(0),
520  _local_form(nullptr),
521  _read_only_values(nullptr),
522  _values(nullptr),
523  _global_to_local_map(),
524  _destroy_vec_on_exit(true),
525  _values_manually_retrieved(false),
526  _values_read_only(false)
527 {
528  this->init(n, n, false, ptype);
529 }
530 
531 
532 
533 template <typename T>
534 inline
536  const numeric_index_type n,
537  const numeric_index_type n_local,
538  const ParallelType ptype) :
539  NumericVector<T>(comm_in, ptype),
540  _vec(nullptr),
541  _array_is_present(false),
542  _first(0),
543  _last(0),
544  _local_size(0),
545  _local_form(nullptr),
546  _read_only_values(nullptr),
547  _values(nullptr),
548  _global_to_local_map(),
549  _destroy_vec_on_exit(true),
550  _values_manually_retrieved(false),
551  _values_read_only(false)
552 {
553  this->init(n, n_local, false, ptype);
554 }
555 
556 
557 
558 template <typename T>
559 inline
561  const numeric_index_type n,
562  const numeric_index_type n_local,
563  const std::vector<numeric_index_type> & ghost,
564  const ParallelType ptype) :
565  NumericVector<T>(comm_in, ptype),
566  _vec(nullptr),
567  _array_is_present(false),
568  _first(0),
569  _last(0),
570  _local_size(0),
571  _local_form(nullptr),
572  _read_only_values(nullptr),
573  _values(nullptr),
574  _global_to_local_map(),
575  _destroy_vec_on_exit(true),
576  _values_manually_retrieved(false),
577  _values_read_only(false)
578 {
579  this->init(n, n_local, ghost, false, ptype);
580 }
581 
582 
583 
584 
585 
586 template <typename T>
587 inline
589  const Parallel::Communicator & comm_in) :
590  NumericVector<T>(comm_in, AUTOMATIC),
591  _vec(v),
592  _array_is_present(false),
593  _first(0),
594  _last(0),
595  _local_size(0),
596  _local_form(nullptr),
597  _read_only_values(nullptr),
598  _values(nullptr),
599  _global_to_local_map(),
600  _destroy_vec_on_exit(false),
601  _values_manually_retrieved(false),
602  _values_read_only(false)
603 {
604  this->_is_closed = true;
605  this->_is_initialized = true;
606 
607  /* We need to ask PETSc about the (local to global) ghost value
608  mapping and create the inverse mapping out of it. */
609  PetscInt petsc_local_size=0;
610  LibmeshPetscCall(VecGetLocalSize(_vec, &petsc_local_size));
611 
612  // Get the vector type from PETSc.
613  VecType ptype;
614  LibmeshPetscCall(VecGetType(_vec, &ptype));
615 
616  // PETSc supports some exotic types nowadays. Just use Vec sizes to
617  // determine whether we're SERIAL vs PARALLEL-or-GHOSTED.
618  PetscInt petsc_global_size = 0;
619  LibmeshPetscCall(VecGetSize(_vec, &petsc_global_size));
620 
621  // If we have a parallel Vec with all its DoFs on one processor, we
622  // might be unable to tell on that processor that it's not a serial
623  // vector unless we communicate.
624  bool is_serial = (petsc_local_size == petsc_global_size);
625  comm_in.min(is_serial);
626 
627 #ifdef DEBUG
628  dof_id_type sum_of_local_sizes = petsc_local_size;
629  comm_in.sum(sum_of_local_sizes);
630  libmesh_assert_equal_to(sum_of_local_sizes,
631  cast_int<dof_id_type>(petsc_global_size));
632 #endif
633 
634 #if PETSC_RELEASE_GREATER_EQUALS(3, 21, 0)
635  // Fande only implemented VecGhostGetGhostIS for VECMPI
636  if (std::strcmp(ptype, VECMPI) == 0)
637  {
638  IS ghostis;
639  LibmeshPetscCall(VecGhostGetGhostIS(_vec, &ghostis));
640 
641  Vec localrep;
642  LibmeshPetscCall(VecGhostGetLocalForm(_vec, &localrep));
643 
644  // If is a sparsely stored vector, set up our new mapping
645  // Only checking mapping is not enough to determine if a vec is ghosted
646  // We need to check if vec has a local representation
647  if (ghostis && localrep)
648  {
649  PetscInt ghost_size;
650  LibmeshPetscCall(ISGetSize(ghostis, &ghost_size));
651 
652  const PetscInt * indices;
653  LibmeshPetscCall(ISGetIndices(ghostis, &indices));
654 
655  for (const auto i : make_range(ghost_size))
656  _global_to_local_map[indices[i]] = i;
657  this->_type = GHOSTED;
658  LibmeshPetscCall(ISRestoreIndices(ghostis, &indices));
659  }
660  else
661  this->_type = PARALLEL;
662  }
663  else if (!is_serial)
664 #else // PETSc < 3.21.0
665  if (!is_serial)
666 #endif
667  {
668  ISLocalToGlobalMapping mapping = nullptr;
669  Vec localrep = nullptr;
670 
671  // Non-VECMPI types won't even let us call VecGetLocalToGlobalMapping;
672  // we'll just assume for now that no such type is ghosted
673  if (std::strcmp(ptype, VECMPI) == 0)
674  {
675  LibmeshPetscCall(VecGetLocalToGlobalMapping(_vec, &mapping));
676  LibmeshPetscCall(VecGhostGetLocalForm(_vec,&localrep));
677  }
678 
679  // If is a sparsely stored vector, set up our new mapping
680  // Only checking mapping is not enough to determine if a vec is ghosted
681  // We need to check if vec has a local representation
682  if (mapping && localrep)
683  {
684  const numeric_index_type my_local_size = static_cast<numeric_index_type>(petsc_local_size);
685  const numeric_index_type ghost_begin = static_cast<numeric_index_type>(petsc_local_size);
686  PetscInt n;
687  LibmeshPetscCall(ISLocalToGlobalMappingGetSize(mapping, &n));
688 
689  const numeric_index_type ghost_end = static_cast<numeric_index_type>(n);
690  const PetscInt * indices;
691  LibmeshPetscCall(ISLocalToGlobalMappingGetIndices(mapping,&indices));
692 
693  for (numeric_index_type i=ghost_begin; i<ghost_end; i++)
694  _global_to_local_map[indices[i]] = i-my_local_size;
695  this->_type = GHOSTED;
696  LibmeshPetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, &indices));
697  }
698  else
699  this->_type = PARALLEL;
700 
701  LibmeshPetscCall(VecGhostRestoreLocalForm(_vec,&localrep));
702  }
703  else
704  this->_type = SERIAL;
705 }
706 
707 
708 
709 
710 template <typename T>
711 inline
713 {
714  this->clear ();
715 }
716 
717 
718 
719 template <typename T>
720 inline
722  const numeric_index_type n_local,
723  const bool fast,
724  const ParallelType ptype)
725 {
726  parallel_object_only();
727 
728  PetscInt petsc_n=static_cast<PetscInt>(n);
729 
730  // Clear initialized vectors
731  if (this->initialized())
732  this->clear();
733 
734  if (ptype == AUTOMATIC)
735  {
736  if (n == n_local)
737  this->_type = SERIAL;
738  else
739  this->_type = PARALLEL;
740  }
741  else
742  this->_type = ptype;
743 
744  // We should have been given consistent settings
745  libmesh_assert ((this->_type==SERIAL && n==n_local) ||
746  (this->n_processors()==1 && n==n_local) ||
747  this->_type==PARALLEL);
748 
749  // create a sequential vector if on only 1 processor, or if asked
750  if (this->_type == SERIAL || (this->n_processors() == 1))
751  {
752  LibmeshPetscCallA(PETSC_COMM_SELF, VecCreate(PETSC_COMM_SELF, &_vec));
753  LibmeshPetscCallA(PETSC_COMM_SELF, VecSetSizes(_vec, petsc_n, petsc_n));
754  LibmeshPetscCallA(PETSC_COMM_SELF, VecSetFromOptions (_vec));
755  }
756  // or create an MPI-enabled PARALLEL vector w/o ghosting if asked
757  else if (this->_type == PARALLEL)
758  {
759 #ifdef LIBMESH_HAVE_MPI
760  PetscInt petsc_n_local=cast_int<PetscInt>(n_local);
761  libmesh_assert_less_equal (n_local, n);
762  // Use more generic function instead of VecCreateSeq/MPI
763  LibmeshPetscCall(VecCreate(this->comm().get(), &_vec));
764  LibmeshPetscCall(VecSetSizes(_vec, petsc_n_local, petsc_n));
765 #else
766  libmesh_assert_equal_to (n_local, n);
767  LibmeshPetscCallA(PETSC_COMM_SELF, VecCreate(PETSC_COMM_SELF, &_vec));
768  LibmeshPetscCallA(PETSC_COMM_SELF, VecSetSizes(_vec, petsc_n, petsc_n));
769 #endif
770  LibmeshPetscCall(VecSetFromOptions(_vec));
771  }
772  // or yell because we don't know what to do
773  else
774  libmesh_error_msg("Unsupported type " <<
775  Utility::enum_to_string(this->_type) <<
776  " for parallel init with no ghost indices supplied");
777 
778  this->_is_initialized = true;
779  this->_is_closed = true;
780 
781 
782  if (fast == false)
783  this->zero ();
784 }
785 
786 
787 
788 template <typename T>
789 inline
791  const bool fast,
792  const ParallelType ptype)
793 {
794  this->init(n,n,fast,ptype);
795 }
796 
797 
798 
799 template <typename T>
800 inline
802  const numeric_index_type n_local,
803  const std::vector<numeric_index_type> & ghost,
804  const bool fast,
805  const ParallelType ptype)
806 {
807  parallel_object_only();
808 
809  if (this->comm().size() == 1)
810  {
811  libmesh_assert(ghost.empty());
812  this->init(n, n_local, fast, ptype);
813  return;
814  }
815 
816  PetscInt petsc_n=static_cast<PetscInt>(n);
817  PetscInt petsc_n_local=static_cast<PetscInt>(n_local);
818  PetscInt petsc_n_ghost=static_cast<PetscInt>(ghost.size());
819 
820  // If the mesh is not disjoint, every processor will either have
821  // all the dofs, none of the dofs, or some non-zero dofs at the
822  // boundary between processors.
823  //
824  // However we can't assert this, because someone might want to
825  // construct a GHOSTED vector which doesn't include neighbor element
826  // dofs. Boyce tried to do so in user code, and we're going to want
827  // to do so in System::project_vector().
828  //
829  // libmesh_assert(n_local == 0 || n_local == n || !ghost.empty());
830 
831  libmesh_assert(sizeof(PetscInt) == sizeof(numeric_index_type));
832 
833  PetscInt * petsc_ghost = ghost.empty() ? LIBMESH_PETSC_NULLPTR :
834  const_cast<PetscInt *>(reinterpret_cast<const PetscInt *>(ghost.data()));
835 
836  // Clear initialized vectors
837  if (this->initialized())
838  this->clear();
839 
840  libmesh_assert(ptype == AUTOMATIC || ptype == GHOSTED);
841  this->_type = GHOSTED;
842 
843  /* Make the global-to-local ghost cell map. */
844  for (auto i : index_range(ghost))
845  {
846  _global_to_local_map[ghost[i]] = i;
847  }
848 
849  /* Create vector. */
850  LibmeshPetscCall(VecCreateGhost (this->comm().get(), petsc_n_local, petsc_n,
851  petsc_n_ghost, petsc_ghost,
852  &_vec));
853 
854  // Add a prefix so that we can at least distinguish a ghosted vector from a
855  // nonghosted vector when using a petsc option.
856  // PETSc does not fully support VecGhost on GPU yet. This change allows us to
857  // trigger a nonghosted vector to use GPU without bothering the ghosted vectors.
858  LibmeshPetscCall(PetscObjectAppendOptionsPrefix((PetscObject)_vec,"ghost_"));
859 
860  LibmeshPetscCall(VecSetFromOptions (_vec));
861 
862  this->_is_initialized = true;
863  this->_is_closed = true;
864 
865  if (fast == false)
866  this->zero ();
867 }
868 
869 
870 
871 template <typename T>
872 inline
874  const bool fast)
875 {
876  parallel_object_only();
877 
878  // Clear initialized vectors
879  if (this->initialized())
880  this->clear();
881 
882  const PetscVector<T> & v = cast_ref<const PetscVector<T> &>(other);
883 
884  // Other vector should restore array.
885  if (v.initialized())
886  {
887  v._restore_array();
888  }
889 
890  this->_global_to_local_map = v._global_to_local_map;
891 
892  // Even if we're initializing sizes based on an uninitialized or
893  // unclosed vector, *this* vector is being initialized now and is
894  // initially closed.
895  this->_is_closed = true; // v._is_closed;
896  this->_is_initialized = true; // v._is_initialized;
897 
898  this->_type = v._type;
899 
900  // We want to have a valid Vec, even if it's initially of size zero
901  LibmeshPetscCall(VecDuplicate (v._vec, &this->_vec));
902 
903  if (fast == false)
904  this->zero ();
905 }
906 
907 
908 
909 template <typename T>
910 inline
912 {
913  parallel_object_only();
914 
915  this->_restore_array();
916 
917  VecAssemblyBeginEnd(this->comm(), _vec);
918 
919  if (this->is_effectively_ghosted())
920  VecGhostUpdateBeginEnd(this->comm(), _vec, INSERT_VALUES, SCATTER_FORWARD);
921 
922  this->_is_closed = true;
923 }
924 
925 
926 
927 template <typename T>
928 inline
929 void PetscVector<T>::clear () noexcept
930 {
931  exceptionless_parallel_object_only();
932 
933  if (this->initialized())
934  this->_restore_array();
935 
936  if ((this->initialized()) && (this->_destroy_vec_on_exit))
937  {
938  // If we encounter an error here, print a warning but otherwise
939  // keep going since we may be recovering from an exception.
940  PetscErrorCode ierr = VecDestroy(&_vec);
941  if (ierr)
942  libmesh_warning("Warning: VecDestroy returned a non-zero error code which we ignored.");
943  }
944 
945  this->_is_closed = this->_is_initialized = false;
946 
947  _global_to_local_map.clear();
948 }
949 
950 
951 
952 template <typename T>
953 inline
955 {
956  parallel_object_only();
957 
958  libmesh_assert(this->closed());
959 
960  this->_restore_array();
961 
962  PetscScalar z=0.;
963 
964  if (!this->is_effectively_ghosted())
965  LibmeshPetscCall(VecSet (_vec, z));
966  else
967  {
968  /* Vectors that include ghost values require a special
969  handling. */
970  Vec loc_vec;
971  LibmeshPetscCall(VecGhostGetLocalForm (_vec,&loc_vec));
972  LibmeshPetscCall(VecSet (loc_vec, z));
973  LibmeshPetscCall(VecGhostRestoreLocalForm (_vec, &loc_vec));
974  }
975 }
976 
977 
978 
979 template <typename T>
980 inline
981 std::unique_ptr<NumericVector<T>> PetscVector<T>::zero_clone () const
982 {
983  std::unique_ptr<NumericVector<T>> cloned_vector =
984  std::make_unique<PetscVector<T>>(this->comm(), this->type());
985  cloned_vector->init(*this);
986  return cloned_vector;
987 }
988 
989 
990 
991 template <typename T>
992 inline
993 std::unique_ptr<NumericVector<T>> PetscVector<T>::clone () const
994 {
995  std::unique_ptr<NumericVector<T>> cloned_vector =
996  std::make_unique<PetscVector<T>>(this->comm(), this->type());
997  cloned_vector->init(*this, true);
998  *cloned_vector = *this;
999  return cloned_vector;
1000 }
1001 
1002 
1003 
1004 template <typename T>
1005 inline
1007 {
1008  libmesh_assert (this->initialized());
1009 
1010  PetscInt petsc_size=0;
1011 
1012  if (!this->initialized())
1013  return 0;
1014 
1015  LibmeshPetscCall(VecGetSize(_vec, &petsc_size));
1016 
1017  return static_cast<numeric_index_type>(petsc_size);
1018 }
1019 
1020 
1021 
1022 template <typename T>
1023 inline
1025 {
1026  libmesh_assert (this->initialized());
1027 
1028  PetscInt petsc_size=0;
1029 
1030  LibmeshPetscCall(VecGetLocalSize(_vec, &petsc_size));
1031 
1032  return static_cast<numeric_index_type>(petsc_size);
1033 }
1034 
1035 
1036 
1037 template <typename T>
1038 inline
1040 {
1041  libmesh_assert (this->initialized());
1042 
1043  numeric_index_type first = 0;
1044 
1045  if (_array_is_present) // Can we use cached values?
1046  first = _first;
1047  else
1048  {
1049  PetscInt petsc_first=0, petsc_last=0;
1050  LibmeshPetscCall(VecGetOwnershipRange (_vec, &petsc_first, &petsc_last));
1051  first = static_cast<numeric_index_type>(petsc_first);
1052  }
1053 
1054  return first;
1055 }
1056 
1057 
1058 
1059 template <typename T>
1060 inline
1062 {
1063  libmesh_assert (this->initialized());
1064 
1065  numeric_index_type last = 0;
1066 
1067  if (_array_is_present) // Can we use cached values?
1068  last = _last;
1069  else
1070  {
1071  PetscInt petsc_first=0, petsc_last=0;
1072  LibmeshPetscCall(VecGetOwnershipRange (_vec, &petsc_first, &petsc_last));
1073  last = static_cast<numeric_index_type>(petsc_last);
1074  }
1075 
1076  return last;
1077 }
1078 
1079 
1080 
1081 template <typename T>
1082 inline
1084 {
1085  libmesh_assert (this->initialized());
1086 
1087  numeric_index_type first=0;
1088  numeric_index_type last=0;
1089 
1090  if (_array_is_present) // Can we use cached values?
1091  {
1092  first = _first;
1093  last = _last;
1094  }
1095  else
1096  {
1097  PetscInt petsc_first=0, petsc_last=0;
1098  LibmeshPetscCall(VecGetOwnershipRange (_vec, &petsc_first, &petsc_last));
1099  first = static_cast<numeric_index_type>(petsc_first);
1100  last = static_cast<numeric_index_type>(petsc_last);
1101  }
1102 
1103 
1104  if ((i>=first) && (i<last))
1105  {
1106  return i-first;
1107  }
1108 
1109  GlobalToLocalMap::const_iterator it = _global_to_local_map.find(i);
1110 #ifndef NDEBUG
1111  const GlobalToLocalMap::const_iterator end = _global_to_local_map.end();
1112  if (it == end)
1113  {
1114  std::ostringstream error_message;
1115  error_message << "No index " << i << " in ghosted vector.\n"
1116  << "Vector contains [" << first << ',' << last << ")\n";
1117  GlobalToLocalMap::const_iterator b = _global_to_local_map.begin();
1118  if (b == end)
1119  {
1120  error_message << "And empty ghost array.\n";
1121  }
1122  else
1123  {
1124  error_message << "And ghost array {" << b->first;
1125  for (++b; b != end; ++b)
1126  error_message << ',' << b->first;
1127  error_message << "}\n";
1128  }
1129 
1130  libmesh_error_msg(error_message.str());
1131  }
1132  libmesh_assert (it != _global_to_local_map.end());
1133 #endif
1134  return it->second+last-first;
1135 }
1136 
1137 
1138 
1139 template <typename T>
1140 inline
1142 {
1143  this->_get_array(true);
1144 
1145  const numeric_index_type local_index = this->map_global_to_local_index(i);
1146 
1147 #ifndef NDEBUG
1148  if (this->is_effectively_ghosted())
1149  libmesh_assert_less (local_index, _local_size);
1150 #endif
1151 
1152  return static_cast<T>(_read_only_values[local_index]);
1153 }
1154 
1155 
1156 
1157 template <typename T>
1158 inline
1159 void PetscVector<T>::get(const std::vector<numeric_index_type> & index,
1160  T * values) const
1161 {
1162  this->_get_array(true);
1163 
1164  const std::size_t num = index.size();
1165 
1166  for (std::size_t i=0; i<num; i++)
1167  {
1168  const numeric_index_type local_index = this->map_global_to_local_index(index[i]);
1169 #ifndef NDEBUG
1170  if (this->is_effectively_ghosted())
1171  libmesh_assert_less (local_index, _local_size);
1172 #endif
1173  values[i] = static_cast<T>(_read_only_values[local_index]);
1174  }
1175 }
1176 
1177 
1178 template <typename T>
1179 inline
1181 {
1182  _get_array(false);
1183  _values_manually_retrieved = true;
1184 
1185  return _values;
1186 }
1187 
1188 
1189 template <typename T>
1190 inline
1191 const PetscScalar * PetscVector<T>::get_array_read() const
1192 {
1193  _get_array(true);
1194  _values_manually_retrieved = true;
1195 
1196  return _read_only_values;
1197 }
1198 
1199 template <typename T>
1200 inline
1202 {
1203  // \note \p _values_manually_retrieved needs to be set to \p false
1204  // \e before calling \p _restore_array()!
1205  _values_manually_retrieved = false;
1206  _restore_array();
1207 }
1208 
1209 template <typename T>
1210 inline
1212 {
1213  parallel_object_only();
1214 
1215  this->_restore_array();
1216 
1217  PetscInt index=0;
1218  PetscReal returnval=0.;
1219 
1220  LibmeshPetscCall(VecMin (_vec, &index, &returnval));
1221 
1222  // this return value is correct: VecMin returns a PetscReal
1223  return static_cast<Real>(returnval);
1224 }
1225 
1226 
1227 
1228 template <typename T>
1229 inline
1231 {
1232  parallel_object_only();
1233 
1234  this->_restore_array();
1235 
1236  PetscInt index=0;
1237  PetscReal returnval=0.;
1238 
1239  LibmeshPetscCall(VecMax (_vec, &index, &returnval));
1240 
1241  // this return value is correct: VecMax returns a PetscReal
1242  return static_cast<Real>(returnval);
1243 }
1244 
1245 
1246 
1247 template <typename T>
1248 inline
1250 {
1251  parallel_object_only();
1252 
1253  NumericVector<T>::swap(other);
1254 
1255  PetscVector<T> & v = cast_ref<PetscVector<T> &>(other);
1256 
1257  std::swap(_vec, v._vec);
1258  std::swap(_destroy_vec_on_exit, v._destroy_vec_on_exit);
1259  std::swap(_global_to_local_map, v._global_to_local_map);
1260 
1261 #ifdef LIBMESH_HAVE_CXX11_THREAD
1262  // Only truly atomic for v... but swap() doesn't really need to be thread safe!
1263  _array_is_present = v._array_is_present.exchange(_array_is_present);
1264 #else
1265  std::swap(_array_is_present, v._array_is_present);
1266 #endif
1267 
1268  std::swap(_local_form, v._local_form);
1269  std::swap(_values, v._values);
1270 }
1271 
1272 
1273 
1274 template <typename T>
1275 inline
1277 {
1278  // The PetscInt type is used for indexing, it may be either a signed
1279  // 4-byte or 8-byte integer depending on how PETSc is configured.
1280  return std::numeric_limits<PetscInt>::max();
1281 }
1282 
1283 
1284 
1285 #ifdef LIBMESH_HAVE_CXX11
1286 static_assert(sizeof(PetscInt) == sizeof(numeric_index_type),
1287  "PETSc and libMesh integer sizes must match!");
1288 #endif
1289 
1290 
1291 inline
1293 {
1294  return reinterpret_cast<PetscInt *>(const_cast<numeric_index_type *>(p));
1295 }
1296 
1297 } // namespace libMesh
1298 
1299 
1300 #endif // #ifdef LIBMESH_HAVE_PETSC
1301 #endif // LIBMESH_PETSC_VECTOR_H
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:42
virtual Real l2_norm() const override
Definition: petsc_vector.C:79
PetscVector(const Parallel::Communicator &comm_in, const ParallelType type=AUTOMATIC)
Dummy-Constructor.
Definition: petsc_vector.h:489
bool closed()
Checks that the library has been closed.
Definition: libmesh.C:331
virtual void localize(std::vector< T > &v_local) const override
Creates a copy of the global vector in the local vector v_local.
Definition: petsc_vector.C:753
This class provides a nice interface to PETSc&#39;s Vec object.
Definition: petsc_vector.h:73
void add_vector_conjugate_transpose(const NumericVector< T > &v, const SparseMatrix< T > &A)
.
Definition: petsc_vector.C:260
virtual void add_vector_transpose(const NumericVector< T > &v, const SparseMatrix< T > &A) override
Computes , i.e.
Definition: petsc_vector.C:232
virtual void zero() override
Set all entries to zero.
Definition: petsc_vector.h:954
bool _destroy_vec_on_exit
This boolean value should only be set to false for the constructor which takes a PETSc Vec object...
Definition: petsc_vector.h:460
virtual numeric_index_type size() const override
virtual Real linfty_norm() const override
Definition: petsc_vector.C:84
numeric_index_type _local_size
Size of the local values from _get_array()
Definition: petsc_vector.h:395
virtual numeric_index_type first_local_index() const override
virtual bool initialized() const
void _get_array(bool read_only) const
Queries the array (and the local form if the vector is ghosted) from PETSc.
virtual numeric_index_type local_size() const override
virtual void add(const numeric_index_type i, const T value) override
Adds value to the vector entry specified by i.
Definition: petsc_vector.C:165
void sum(T &r) const
Vec _vec
Actual PETSc vector datatype to hold vector entries.
Definition: petsc_vector.h:364
numeric_index_type _last
Last local index.
Definition: petsc_vector.h:390
Provides a uniform interface to vector storage schemes for different linear algebra libraries...
Definition: vector_fe_ex5.C:44
PetscScalar * _values
Pointer to the actual PETSc array of the values of the vector.
Definition: petsc_vector.h:422
bool _values_read_only
Whether or not the data array is for read only access.
Definition: petsc_vector.h:471
The libMesh namespace provides an interface to certain functionality in the library.
const Number zero
.
Definition: libmesh.h:297
virtual void pointwise_divide(const NumericVector< T > &vec1, const NumericVector< T > &vec2) override
Computes (summation not implied) i.e.
Definition: petsc_vector.C:979
void _restore_array() const
Restores the array (and the local form if the vector is ghosted) to PETSc.
std::atomic< bool > _array_is_present
If true, the actual PETSc array of the values of the vector is currently accessible.
Definition: petsc_vector.h:373
uint8_t processor_id_type
Definition: id_types.h:104
PetscInt * numeric_petsc_cast(const numeric_index_type *p)
virtual void swap(NumericVector< T > &v) override
Swaps the contents of this with v.
Generic sparse matrix.
Definition: vector_fe_ex5.C:46
virtual void insert(const T *v, const std::vector< numeric_index_type > &dof_indices) override
Inserts the entries of v in *this at the locations specified by v.
Definition: petsc_vector.C:350
const PetscScalar * _read_only_values
Pointer to the actual PETSc array of the values of the vector.
Definition: petsc_vector.h:412
virtual void pointwise_mult(const NumericVector< T > &vec1, const NumericVector< T > &vec2) override
Computes (summation not implied) i.e.
Definition: petsc_vector.C:955
virtual Real l1_norm() const override
Definition: petsc_vector.C:74
Vec _local_form
PETSc vector datatype to hold the local form of a ghosted vector.
Definition: petsc_vector.h:402
GlobalToLocalMap _global_to_local_map
Map that maps global to local ghost cells (will be empty if not in ghost cell mode).
Definition: petsc_vector.h:454
virtual void abs() override
Sets for each entry in the vector.
Definition: petsc_vector.C:413
void min(const T &r, T &o, Request &req) const
dof_id_type numeric_index_type
Definition: id_types.h:99
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:305
const PetscScalar * get_array_read() const
Get read only access to the raw PETSc Vector data array.
virtual NumericVector< T > & operator+=(const NumericVector< T > &v) override
Adds v to *this, .
Definition: petsc_vector.C:93
virtual void conjugate() override
Negates the imaginary component of each entry in the vector.
Definition: petsc_vector.C:153
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libmesh_assert(ctx)
virtual T operator()(const numeric_index_type i) const override
virtual void localize_to_one(std::vector< T > &v_local, const processor_id_type proc_id=0) const override
Creates a local copy of the global vector in v_local only on processor proc_id.
numeric_index_type map_global_to_local_index(const numeric_index_type i) const
virtual std::size_t max_allowed_id() const override
ParallelType _type
Type of vector.
virtual void create_subvector(NumericVector< T > &subvector, const std::vector< numeric_index_type > &rows, bool supplying_global_rows=true) const override
Fills in subvector from this vector using the indices in rows.
virtual numeric_index_type last_local_index() const override
std::string enum_to_string(const T e)
Real norm() const
Definition: petsc_vector.C:60
virtual T sum() const override
Definition: petsc_vector.C:44
std::mutex _petsc_get_restore_array_mutex
Mutex for _get_array and _restore_array.
Definition: petsc_vector.h:429
void restore_array()
Restore the data array.
ParallelType type() const
virtual std::unique_ptr< NumericVector< T > > clone() const override
Definition: petsc_vector.h:993
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
T indefinite_dot(const NumericVector< T > &v) const
Definition: petsc_vector.C:450
std::unordered_map< numeric_index_type, numeric_index_type > GlobalToLocalMap
Type for map that maps global to local ghost cells.
Definition: petsc_vector.h:448
virtual void restore_subvector(std::unique_ptr< NumericVector< T >> subvector, const std::vector< numeric_index_type > &rows) override
Restores a view into this vector using the indices in rows.
virtual void clear() noexcept override
clear() is called from the destructor, so it should not throw.
Definition: petsc_vector.h:929
virtual void init(const numeric_index_type N, const numeric_index_type n_local, const bool fast=false, const ParallelType type=AUTOMATIC) override
Change the dimension of the vector to n.
Definition: petsc_vector.h:721
static const Real b
virtual Real max() const override
static const bool value
Definition: xdr_io.C:55
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:176
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:324
numeric_index_type _first
First local index.
Definition: petsc_vector.h:383
PetscVector< T > & operator=(const PetscVector< T > &v)
Copy assignment operator.
Definition: petsc_vector.C:516
virtual void reciprocal() override
Computes the component-wise reciprocal, .
Definition: petsc_vector.C:141
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices) override
Computes , where v is a pointer and each dof_indices[i] specifies where to add value v[i]...
Definition: petsc_vector.C:182
virtual NumericVector< T > & operator*=(const NumericVector< T > &v) override
Computes the component-wise multiplication of this vector&#39;s entries by another&#39;s, ...
Definition: petsc_vector.C:387
bool _values_manually_retrieved
Whether or not the data array has been manually retrieved using get_array() or get_array_read() ...
Definition: petsc_vector.h:466
virtual void print_matlab(const std::string &name="") const override
Print the contents of the vector in Matlab&#39;s sparse matrix format.
virtual std::unique_ptr< NumericVector< T > > get_subvector(const std::vector< numeric_index_type > &rows) override
Creates a view into this vector using the indices in rows.
virtual void scale(const T factor) override
Scale each element of the vector by the given factor.
Definition: petsc_vector.C:369
PetscScalar * get_array()
Get read/write access to the raw PETSc Vector data array.
virtual std::unique_ptr< NumericVector< T > > zero_clone() const override
Definition: petsc_vector.h:981
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:153
const Elem & get(const ElemType type_in)
virtual Real min() const override
virtual void close() override
Calls the NumericVector&#39;s internal assembly routines, ensuring that the values are consistent across ...
Definition: petsc_vector.h:911
uint8_t dof_id_type
Definition: id_types.h:67
virtual NumericVector< T > & operator/=(const NumericVector< T > &v) override
Computes the component-wise division of this vector&#39;s entries by another&#39;s, .
Definition: petsc_vector.C:400
ParallelType
Defines an enum for parallel data structure types.
virtual NumericVector< T > & operator-=(const NumericVector< T > &v) override
Subtracts v from *this, .
Definition: petsc_vector.C:109
virtual T dot(const NumericVector< T > &v) const override
Definition: petsc_vector.C:429