libMesh
Loading...
Searching...
No Matches
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
58namespace libMesh
59{
60
61// forward declarations
62template <typename T> class SparseMatrix;
63
72template <typename T>
73class PetscVector final : public NumericVector<T>
74{
75public:
76
80 explicit
83
87 explicit
89 const numeric_index_type n,
91
97 const numeric_index_type n,
98 const numeric_index_type n_local,
100
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
120 const Parallel::Communicator & comm_in);
121
132
139 PetscVector (const 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
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
262 using NumericVector<T>::add_vector;
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
286 using NumericVector<T>::insert;
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
359private:
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
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
487template <typename T>
488inline
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
509template <typename T>
510inline
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
533template <typename T>
534inline
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
558template <typename T>
559inline
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
586template <typename T>
587inline
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
710template <typename T>
711inline
713{
714 this->clear ();
715}
716
717
718
719template <typename T>
720inline
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
788template <typename T>
789inline
791 const bool fast,
792 const ParallelType ptype)
793{
794 this->init(n,n,fast,ptype);
795}
796
797
798
799template <typename T>
800inline
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
871template <typename T>
872inline
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
909template <typename T>
910inline
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
927template <typename T>
928inline
929void 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
952template <typename T>
953inline
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
979template <typename T>
980inline
981std::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
991template <typename T>
992inline
993std::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
1004template <typename T>
1005inline
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
1022template <typename T>
1023inline
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
1037template <typename T>
1038inline
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
1059template <typename T>
1060inline
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
1081template <typename T>
1082inline
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
1139template <typename T>
1140inline
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
1157template <typename T>
1158inline
1159void 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
1178template <typename T>
1179inline
1181{
1182 _get_array(false);
1183 _values_manually_retrieved = true;
1184
1185 return _values;
1186}
1187
1188
1189template <typename T>
1190inline
1191const 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
1199template <typename T>
1200inline
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
1209template <typename T>
1210inline
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
1228template <typename T>
1229inline
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
1247template <typename T>
1248inline
1250{
1251 parallel_object_only();
1252
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
1274template <typename T>
1275inline
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
1286static_assert(sizeof(PetscInt) == sizeof(numeric_index_type),
1287 "PETSc and libMesh integer sizes must match!");
1288#endif
1289
1290
1291inline
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
void min(const T &r, T &o, Request &req) const
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
ParallelType type() const
virtual void swap(NumericVector< T > &v)
Swaps the contents of this with v.
ParallelType _type
Type of vector.
virtual bool initialized() const
bool _is_initialized
true once init() has been called.
bool _is_closed
Flag which tracks whether the vector's values are consistent on all processors after insertion or add...
This class provides a nice interface to PETSc's Vec object.
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.
Vec _local_form
PETSc vector datatype to hold the local form of a ghosted vector.
PetscVector(PetscVector &&)=delete
This class manages a C-style struct (Vec) manually, so we don't want to allow any automatic copy/move...
virtual std::unique_ptr< NumericVector< T > > zero_clone() const override
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.
PetscVector(Vec v, const Parallel::Communicator &comm_in)
Constructor.
virtual Real min() const override
PetscVector(const PetscVector &)=delete
virtual Real linfty_norm() const override
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].
virtual void set(const numeric_index_type i, const T value) override
Sets v(i) = value.
virtual numeric_index_type size() const override
virtual void close() override
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
PetscVector(const Parallel::Communicator &comm_in, const ParallelType type=AUTOMATIC)
Dummy-Constructor.
virtual void add_vector_transpose(const NumericVector< T > &v, const SparseMatrix< T > &A) override
Computes , i.e.
std::mutex _petsc_get_restore_array_mutex
Mutex for _get_array and _restore_array.
numeric_index_type _first
First local index.
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.
bool _values_read_only
Whether or not the data array is for read only access.
PetscVector(const Parallel::Communicator &comm_in, const numeric_index_type n, const ParallelType type=AUTOMATIC)
Constructor.
virtual numeric_index_type first_local_index() const override
bool _values_manually_retrieved
Whether or not the data array has been manually retrieved using get_array() or get_array_read()
virtual std::size_t max_allowed_id() const override
void _get_array(bool read_only) const
Queries the array (and the local form if the vector is ghosted) from PETSc.
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.
virtual void conjugate() override
Negates the imaginary component of each entry in the vector.
virtual void swap(NumericVector< T > &v) override
Swaps the contents of this with v.
virtual Real max() const override
PetscScalar * _values
Pointer to the actual PETSc array of the values of the vector.
void _restore_array() const
Restores the array (and the local form if the vector is ghosted) to PETSc.
numeric_index_type _local_size
Size of the local values from _get_array()
virtual void print_matlab(const std::string &name="") const override
Print the contents of the vector in Matlab's sparse matrix format.
virtual void pointwise_mult(const NumericVector< T > &vec1, const NumericVector< T > &vec2) override
Computes (summation not implied) i.e.
numeric_index_type _last
Last local index.
virtual void scale(const T factor) override
Scale each element of the vector by the given factor.
virtual void pointwise_divide(const NumericVector< T > &vec1, const NumericVector< T > &vec2) override
Computes (summation not implied) i.e.
numeric_index_type map_global_to_local_index(const numeric_index_type i) const
virtual Real l2_norm() const override
void restore_array()
Restore the data array.
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.
const PetscScalar * _read_only_values
Pointer to the actual PETSc array of the values of the vector.
virtual numeric_index_type last_local_index() const override
PetscVector(const Parallel::Communicator &comm_in, const numeric_index_type N, const numeric_index_type n_local, const std::vector< numeric_index_type > &ghost, const ParallelType type=AUTOMATIC)
Constructor.
virtual T operator()(const numeric_index_type i) const override
virtual std::unique_ptr< NumericVector< T > > clone() const override
virtual numeric_index_type local_size() const override
virtual void get(const std::vector< numeric_index_type > &index, T *values) const override
Access multiple components at once.
const PetscScalar * get_array_read() const
Get read only access to the raw PETSc Vector data array.
virtual void localize(std::vector< T > &v_local) const override
Creates a copy of the global vector in the local vector v_local.
std::atomic< bool > _array_is_present
If true, the actual PETSc array of the values of the vector is currently accessible.
PetscVector(const Parallel::Communicator &comm_in, const numeric_index_type n, const numeric_index_type n_local, const ParallelType type=AUTOMATIC)
Constructor.
std::unordered_map< numeric_index_type, numeric_index_type > GlobalToLocalMap
Type for map that maps global to local ghost cells.
GlobalToLocalMap _global_to_local_map
Map that maps global to local ghost cells (will be empty if not in ghost cell mode).
virtual Real l1_norm() const override
T indefinite_dot(const NumericVector< T > &v) const
PetscVector< T > & operator=(const PetscVector< T > &v)
Copy assignment operator.
virtual void add(const numeric_index_type i, const T value) override
Adds value to the vector entry specified by i.
virtual void zero() override
Set all entries to zero.
virtual void reciprocal() override
Computes the component-wise reciprocal, .
virtual void clear() noexcept override
clear() is called from the destructor, so it should not throw.
virtual T dot(const NumericVector< T > &v) const override
Vec _vec
Actual PETSc vector datatype to hold vector entries.
void add_vector_conjugate_transpose(const NumericVector< T > &v, const SparseMatrix< T > &A)
.
virtual T sum() const override
virtual void abs() override
Sets for each entry in the vector.
bool _destroy_vec_on_exit
This boolean value should only be set to false for the constructor which takes a PETSc Vec object.
PetscScalar * get_array()
Get read/write access to the raw PETSc Vector data array.
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.
Generic sparse matrix.
static const Real b
std::string enum_to_string(const T e)
The libMesh namespace provides an interface to certain functionality in the library.
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
ParallelType
Defines an enum for parallel data structure types.
bool closed()
Checks that the library has been closed.
Definition libmesh.C:331
libmesh_assert(ctx)
const Number zero
.
Definition libmesh.h:297
dof_id_type numeric_index_type
Definition id_types.h:99
PetscInt * numeric_petsc_cast(const numeric_index_type *p)
bool initialized()
Checks that library initialization has been done.
Definition libmesh.C:324
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
Definition id_types.h:104
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
static const bool value
Definition xdr_io.C:55