LCOV - code coverage report
Current view: top level - include/numerics - numeric_vector.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4476 (4beb67) with base a68cc6 Lines: 40 122 32.8 %
Date: 2026-06-03 20:22:46 Functions: 22 71 31.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #ifndef LIBMESH_NUMERIC_VECTOR_H
      21             : #define LIBMESH_NUMERIC_VECTOR_H
      22             : 
      23             : // Local includes
      24             : #include "libmesh/libmesh_common.h"
      25             : #include "libmesh/enum_parallel_type.h" // AUTOMATIC
      26             : #include "libmesh/id_types.h"
      27             : #include "libmesh/int_range.h"
      28             : #include "libmesh/reference_counted_object.h"
      29             : #include "libmesh/libmesh.h"
      30             : #include "libmesh/parallel_object.h"
      31             : #include "libmesh/dense_subvector.h"
      32             : #include "libmesh/dense_vector.h"
      33             : 
      34             : // C++ includes
      35             : #include <cstddef>
      36             : #include <set>
      37             : #include <vector>
      38             : #include <memory>
      39             : #include <mutex>
      40             : 
      41             : namespace libMesh
      42             : {
      43             : 
      44             : 
      45             : // forward declarations
      46             : template <typename T> class NumericVector;
      47             : template <typename T> class DenseVector;
      48             : template <typename T> class DenseSubVector;
      49             : template <typename T> class SparseMatrix;
      50             : template <typename T> class ShellMatrix;
      51             : enum SolverPackage : int;
      52             : 
      53             : /**
      54             :  * \brief Provides a uniform interface to vector storage schemes for different
      55             :  * linear algebra libraries.
      56             :  *
      57             :  * \note This class is the abstract base class for different implementations
      58             :  * of numeric vectors.  Most of the time you should use a System object to
      59             :  * create numeric vectors.  If this is not desired, you can instantiate one of
      60             :  * the derived classes (PetscVector, EigenSparseVector, etc.) or use the
      61             :  * NumericVector::build method. When creating the vector yourself, make sure
      62             :  * that you initialize the vector properly (NumericVector::init).
      63             :  *
      64             :  * \author Benjamin S. Kirk
      65             :  * \date 2003
      66             :  */
      67             : template <typename T>
      68             : class NumericVector : public ReferenceCountedObject<NumericVector<T>>,
      69             :                       public ParallelObject
      70             : {
      71             : public:
      72             : 
      73             :   /**
      74             :    * Dummy-Constructor. Dimension=0
      75             :    */
      76             :   explicit
      77             :   NumericVector (const Parallel::Communicator & comm_in,
      78             :                  const ParallelType ptype = AUTOMATIC);
      79             : 
      80             :   /**
      81             :    * Constructor. Set dimension to \p n and initialize all elements with zero.
      82             :    */
      83             :   explicit
      84             :   NumericVector (const Parallel::Communicator & comm_in,
      85             :                  const numeric_index_type n,
      86             :                  const ParallelType ptype = AUTOMATIC);
      87             : 
      88             :   /**
      89             :    * Constructor. Set local dimension to \p n_local, the global dimension
      90             :    * to \p n, and initialize all elements with zero.
      91             :    */
      92             :   NumericVector (const Parallel::Communicator & comm_in,
      93             :                  const numeric_index_type n,
      94             :                  const numeric_index_type n_local,
      95             :                  const ParallelType ptype = AUTOMATIC);
      96             : 
      97             :   /**
      98             :    * Constructor. Set local dimension to \p n_local, the global
      99             :    * dimension to \p n, but additionally reserve memory for the
     100             :    * indices specified by the \p ghost argument.
     101             :    */
     102             :   NumericVector (const Parallel::Communicator & comm_in,
     103             :                  const numeric_index_type N,
     104             :                  const numeric_index_type n_local,
     105             :                  const std::vector<numeric_index_type> & ghost,
     106             :                  const ParallelType ptype = AUTOMATIC);
     107             : 
     108             :   /**
     109             :    * This _looks_ like a copy assignment operator, but note that,
     110             :    * unlike normal copy assignment operators, it is pure virtual. This
     111             :    * function should be overridden in derived classes so that they can
     112             :    * be copied correctly via references to the base class. This design
     113             :    * usually isn't a good idea in general, but in this context it
     114             :    * works because we usually don't have a mix of different kinds of
     115             :    * NumericVectors active in the library at a single time.
     116             :    *
     117             :    * \returns A reference to *this as the base type.
     118             :    */
     119             :   virtual NumericVector<T> & operator= (const NumericVector<T> & v) = 0;
     120             : 
     121             :   /**
     122             :    * These 3 special functions can be defaulted for this class, as it
     123             :    * does not manage any memory itself.
     124             :    */
     125             :   NumericVector (NumericVector &&) = default;
     126             :   NumericVector (const NumericVector &) = default;
     127             :   NumericVector & operator= (NumericVector &&) = default;
     128             : 
     129             :   /**
     130             :    * While this class doesn't manage any memory, the derived class might and
     131             :    * users may be deleting through a pointer to this base class
     132             :    */
     133       76280 :   virtual ~NumericVector() = default;
     134             : 
     135             :   /**
     136             :    * Builds a \p NumericVector on the processors in communicator
     137             :    * \p comm using the linear solver package specified by
     138             :    * \p solver_package
     139             :    */
     140             :   static std::unique_ptr<NumericVector<T>>
     141             :   build(const Parallel::Communicator & comm,
     142             :         SolverPackage solver_package = libMesh::default_solver_package(),
     143             :         ParallelType parallel_type = AUTOMATIC);
     144             : 
     145             :   /**
     146             :    * \returns \p true if the vector has been initialized,
     147             :    * false otherwise.
     148             :    */
     149  1532130191 :   virtual bool initialized() const { return _is_initialized; }
     150             : 
     151             :   /**
     152             :    * \returns The type (SERIAL, PARALLEL, GHOSTED) of the vector.
     153             :    *
     154             :    * This is metadata reflecting what type of vector was requested,
     155             :    * which should reflect what level of replication and ghosting is
     156             :    * necessary in parallel.
     157             :    */
     158     2809389 :   ParallelType type() const { return _type; }
     159             : 
     160             :   /**
     161             :    * \returns Whether the vector is effectively serial, i.e. whether
     162             :    * all vector data is accessible on every processor.
     163             :    *
     164             :    * This is true for explicitly SERIAL vectors, but also for vectors
     165             :    * on serial (1-processor) communicators.
     166             :    */
     167             : 
     168      329670 :   bool is_effectively_serial() const
     169     4252501 :   { return (this->n_processors()==1) || (_type == SERIAL); }
     170             : 
     171             :   /**
     172             :    * \returns Whether the vector is effectively ghosted, i.e. whether
     173             :    * vector operations require handling of ghosted coefficients.
     174             :    *
     175             :    * This is true for GHOSTED vectors in parallel, but in serial
     176             :    * subclasses may return false here for GHOSTED vectors since every
     177             :    * ghosted vector is effectively serial and thus may be able to take
     178             :    * advantage of serial-specific code paths.
     179             :    */
     180             : 
     181   573492878 :   bool is_effectively_ghosted() const
     182   595574439 :   { return (this->n_processors()!=1) && (_type == GHOSTED); }
     183             : 
     184             :   /**
     185             :    * \returns The type (SERIAL, PARALLEL, GHOSTED) of the vector.
     186             :    *
     187             :    * \deprecated because it is dangerous to change the ParallelType
     188             :    * of an already-initialized NumericVector. See NumericVector::set_type()
     189             :    * for a safer, non-deprecated setter.
     190             :    */
     191             : #ifdef LIBMESH_ENABLE_DEPRECATED
     192      460348 :   ParallelType & type() { return _type; }
     193             : #endif
     194             : 
     195             :   /**
     196             :    * Allow the user to change the ParallelType of the NumericVector
     197             :    * under some circumstances. If the NumericVector has not been
     198             :    * initialized yet, then it is generally safe to change the
     199             :    * ParallelType. otherwise, if the NumericVector has already been
     200             :    * initialized with a specific type, we cannot change it without
     201             :    * doing some extra copying/reinitialization work, and we currently
     202             :    * throw an error if this is requested.
     203             :    */
     204             :   void set_type(ParallelType t);
     205             : 
     206             :   /**
     207             :    * \returns \p true if the vector is closed and ready for
     208             :    * computation, false otherwise.
     209             :    */
     210      974572 :   virtual bool closed() const { return _is_closed; }
     211             : 
     212             :   /**
     213             :    * Calls the NumericVector's internal assembly routines, ensuring
     214             :    * that the values are consistent across processors.
     215             :    */
     216             :   virtual void close () = 0;
     217             : 
     218             :   /**
     219             :    * Restores the \p NumericVector<T> to a pristine state.
     220             :    */
     221             :   virtual void clear ();
     222             : 
     223             :   /**
     224             :    * Set all entries to zero. Equivalent to \p v = 0, but more obvious and
     225             :    * faster.
     226             :    */
     227             :   virtual void zero () = 0;
     228             : 
     229             :   /**
     230             :    * \returns A smart pointer to a copy of this vector with the same
     231             :    * type, size, and partitioning, but with all zero entries.
     232             :    *
     233             :    * \note This must be overridden in the derived classes.
     234             :    */
     235             :   virtual std::unique_ptr<NumericVector<T>> zero_clone () const = 0;
     236             : 
     237             :   /**
     238             :    * \returns A copy of this vector wrapped in a smart pointer.
     239             :    *
     240             :    * \note This must be overridden in the derived classes.
     241             :    */
     242             :   virtual std::unique_ptr<NumericVector<T>> clone () const = 0;
     243             : 
     244             :   /**
     245             :    * Change the dimension of the vector to \p n. The reserved memory
     246             :    * for this vector remains unchanged if possible.  If \p n==0, all
     247             :    * memory is freed. Therefore, if you want to resize the vector and
     248             :    * release the memory not needed, you have to first call \p init(0)
     249             :    * and then \p init(n). This behaviour is analogous to that of the
     250             :    * STL containers.
     251             :    *
     252             :    * On \p fast==false, the vector is filled by zeros.
     253             :    */
     254             :   virtual void init (const numeric_index_type n,
     255             :                      const numeric_index_type n_local,
     256             :                      const bool fast = false,
     257             :                      const ParallelType ptype = AUTOMATIC) = 0;
     258             : 
     259             :   /**
     260             :    * Call \p init() with n_local = N.
     261             :    */
     262             :   virtual void init (const numeric_index_type n,
     263             :                      const bool fast = false,
     264             :                      const ParallelType ptype = AUTOMATIC) = 0;
     265             : 
     266             :   /**
     267             :    * Create a vector that holds the local indices plus those specified
     268             :    * in the \p ghost argument.
     269             :    */
     270             :   virtual void init (const numeric_index_type n,
     271             :                      const numeric_index_type n_local,
     272             :                      const std::vector<numeric_index_type> & ghost,
     273             :                      const bool fast = false,
     274             :                      const ParallelType ptype = AUTOMATIC) = 0;
     275             : 
     276             :   /**
     277             :    * Creates a vector that has the same dimension and storage type as
     278             :    * \p other, including ghost dofs.
     279             :    */
     280             :   virtual void init (const NumericVector<T> & other,
     281             :                      const bool fast = false) = 0;
     282             : 
     283             :   /**
     284             :    * Sets all entries of the vector to the value \p s.
     285             :    *
     286             :    * \returns A reference to *this.
     287             :    */
     288             :   virtual NumericVector<T> & operator= (const T s) = 0;
     289             : 
     290             :   /**
     291             :    * Sets (*this)(i) = v(i) for each entry of the vector.
     292             :    *
     293             :    * \returns A reference to *this as the base type.
     294             :    */
     295             :   virtual NumericVector<T> & operator= (const std::vector<T> & v) = 0;
     296             : 
     297             :   /**
     298             :    * \returns The minimum entry in the vector, or the minimum real
     299             :    * part in the case of complex numbers.
     300             :    */
     301             :   virtual Real min () const = 0;
     302             : 
     303             :   /**
     304             :    * \returns The maximum entry in the vector, or the maximum real
     305             :    * part in the case of complex numbers.
     306             :    */
     307             :   virtual Real max () const = 0;
     308             : 
     309             :   /**
     310             :    * \returns The sum of all values in the vector.
     311             :    */
     312             :   virtual T sum() const = 0;
     313             : 
     314             :   /**
     315             :    * \returns The \f$ \ell_1 \f$-norm of the vector, i.e. the sum of the
     316             :    * absolute values of the entries.
     317             :    */
     318             :   virtual Real l1_norm () const = 0;
     319             : 
     320             :   /**
     321             :    * \returns The \f$ \ell_2 \f$-norm of the vector, i.e. the square root
     322             :    * of the sum of the squares of the entries.
     323             :    */
     324             :   virtual Real l2_norm () const = 0;
     325             : 
     326             :   /**
     327             :    * \returns The \f$ \ell_{\infty} \f$-norm of the vector, i.e. the maximum
     328             :    * absolute value of the entries of the vector.
     329             :    */
     330             :   virtual Real linfty_norm () const = 0;
     331             : 
     332             :   /**
     333             :    * \returns The \f$ \ell_1 \f$-norm of the vector, i.e. the sum of the
     334             :    * absolute values for the specified entries in the vector.
     335             :    *
     336             :    * \note The indices must necessarily live on this processor.
     337             :    */
     338             :   virtual Real subset_l1_norm (const std::set<numeric_index_type> & indices) const;
     339             : 
     340             :   /**
     341             :    * \returns The \f$ \ell_2 \f$-norm of the vector, i.e. the square root
     342             :    * of the sum of the squares of the elements for the specified
     343             :    * entries in the vector.
     344             :    *
     345             :    * \note The indices must necessarily live on this processor.
     346             :    */
     347             :   virtual Real subset_l2_norm (const std::set<numeric_index_type> & indices) const;
     348             : 
     349             :   /**
     350             :    * \returns The maximum absolute value of the specified entries of
     351             :    * this vector, which is the \f$ \ell_{\infty} \f$-norm of a vector.
     352             :    *
     353             :    * \note The indices must necessarily live on this processor.
     354             :    */
     355             :   virtual Real subset_linfty_norm (const std::set<numeric_index_type> & indices) const;
     356             : 
     357             :   /**
     358             :    * \returns The \f$ \ell_2 \f$-norm of \f$ \vec{u} - \vec{v} \f$, where
     359             :    * \f$ \vec{u} \f$ is \p this.
     360             :   */
     361             :   Real l2_norm_diff (const NumericVector<T> & other_vec) const;
     362             : 
     363             :   /**
     364             :    * \returns The \f$ \ell_1 \f$-norm of \f$ \vec{u} - \vec{v} \f$, where
     365             :    * \f$ \vec{u} \f$ is \p this.
     366             :   */
     367             :   Real l1_norm_diff (const NumericVector<T> & other_vec) const;
     368             : 
     369             :   /**
     370             :    * \returns The size of the vector.
     371             :    */
     372             :   virtual numeric_index_type size () const = 0;
     373             : 
     374             :   /**
     375             :    * \returns The local size of the vector, i.e. \p index_stop - \p index_start.
     376             :    */
     377             :   virtual numeric_index_type local_size() const = 0;
     378             : 
     379             :   /**
     380             :    * \returns The index of the first vector element actually stored on
     381             :    * this processor.
     382             :    *
     383             :    * \note The minimum for this index is \p 0.
     384             :    */
     385             :   virtual numeric_index_type first_local_index() const = 0;
     386             : 
     387             :   /**
     388             :    * \returns The index+1 of the last vector element actually stored
     389             :    * on this processor.
     390             :    *
     391             :    * \note The maximum for this index is \p size().
     392             :    */
     393             :   virtual numeric_index_type last_local_index() const = 0;
     394             : 
     395             :   /**
     396             :    * \returns A copy of the ith entry of the vector.
     397             :    */
     398             :   virtual T operator() (const numeric_index_type i) const = 0;
     399             : 
     400             :   /**
     401             :    * \returns (*this)(i).
     402             :    */
     403           0 :   virtual T el(const numeric_index_type i) const { return (*this)(i); }
     404             : 
     405             :   /**
     406             :    * Access multiple components at once.  \p values will *not* be
     407             :    * reallocated; it should already have enough space.  The default
     408             :    * implementation calls \p operator() for each index, but some
     409             :    * implementations may supply faster methods here.
     410             :    */
     411             :   virtual void get(const std::vector<numeric_index_type> & index,
     412             :                    T * values) const;
     413             : 
     414             :   /**
     415             :    * Access multiple components at once.  \p values will be resized,
     416             :    * if necessary, and filled.  The default implementation calls \p
     417             :    * operator() for each index, but some implementations may supply
     418             :    * faster methods here.
     419             :    */
     420             :   void get(const std::vector<numeric_index_type> & index,
     421             :            std::vector<T> & values) const;
     422             : 
     423             :   /**
     424             :    * Adds \p v to *this,
     425             :    * \f$ \vec{u} \leftarrow \vec{u} + \vec{v} \f$.
     426             :    * Equivalent to \p u.add(1, v).
     427             :    *
     428             :    * \returns A reference to *this.
     429             :    */
     430             :   virtual NumericVector<T> & operator += (const NumericVector<T> & v) = 0;
     431             : 
     432             :   /**
     433             :    * Subtracts \p v from *this,
     434             :    * \f$ \vec{u} \leftarrow \vec{u} - \vec{v} \f$.
     435             :    * Equivalent to \p u.add(-1, v).
     436             :    *
     437             :    * \returns A reference to *this.
     438             :    */
     439             :   virtual NumericVector<T> & operator -= (const NumericVector<T> & v) = 0;
     440             : 
     441             :   /**
     442             :    * Scales the vector by \p a,
     443             :    * \f$ \vec{u} \leftarrow a\vec{u} \f$.
     444             :    * Equivalent to \p u.scale(a)
     445             :    *
     446             :    * \returns A reference to *this.
     447             :    */
     448       11572 :   NumericVector<T> & operator *= (const T a) { this->scale(a); return *this; }
     449             : 
     450             :   /**
     451             :    * Computes the component-wise multiplication of this vector's entries by
     452             :    * another's,
     453             :    * \f$ u_i \leftarrow u_i v_i \, \forall i\f$
     454             :    *
     455             :    * \returns A reference to *this.
     456             :    */
     457             :   virtual NumericVector<T> & operator *= (const NumericVector<T> & v) = 0;
     458             : 
     459             :   /**
     460             :    * Scales the vector by \p 1/a,
     461             :    * \f$ \vec{u} \leftarrow \frac{1}{a}\vec{u} \f$.
     462             :    * Equivalent to \p u.scale(1./a)
     463             :    *
     464             :    * \returns A reference to *this.
     465             :    */
     466        7430 :   NumericVector<T> & operator /= (const T a) { this->scale(1./a); return *this; }
     467             : 
     468             :   /**
     469             :    * Computes the component-wise division of this vector's entries by another's,
     470             :    * \f$ u_i \leftarrow \frac{u_i}{v_i} \, \forall i\f$
     471             :    *
     472             :    * \returns A reference to *this.
     473             :    */
     474             :   virtual NumericVector<T> & operator /= (const NumericVector<T> & v) = 0;
     475             : 
     476             :   /**
     477             :    * Computes the component-wise reciprocal,
     478             :    * \f$ u_i \leftarrow \frac{1}{u_i} \, \forall i\f$
     479             :    */
     480             :   virtual void reciprocal() = 0;
     481             : 
     482             :   /**
     483             :    * Negates the imaginary component of each entry in the vector.
     484             :    */
     485             :   virtual void conjugate() = 0;
     486             : 
     487             :   /**
     488             :    * Sets v(i) = \p value. Note that library implementations of this method are
     489             :    * thread safe, e.g. we will lock \p _numeric_vector_mutex before writing to the vector
     490             :    */
     491             :   virtual void set (const numeric_index_type i, const T value) = 0;
     492             : 
     493             :   /**
     494             :    * Adds \p value to the vector entry specified by \p i. Note that library implementations of this
     495             :    * method are thread safe, e.g. we will lock \p _numeric_vector_mutex before writing to the vector
     496             :    */
     497             :   virtual void add (const numeric_index_type i, const T value) = 0;
     498             : 
     499             :   /**
     500             :    * Adds \p s to each entry of the vector,
     501             :    * \f$ u_i \leftarrow u_i + s \f$
     502             :    */
     503             :   virtual void add (const T s) = 0;
     504             : 
     505             :   /**
     506             :    * Adds \p v to \p this,
     507             :    * \f$ \vec{u} \leftarrow \vec{u} + \vec{v} \f$.
     508             :    * Equivalent to calling \p operator+=().
     509             :    */
     510             :   virtual void add (const NumericVector<T> & v) = 0;
     511             : 
     512             :   /**
     513             :    * Vector addition with a scalar multiple,
     514             :    * \f$ \vec{u} \leftarrow \vec{u} + a\vec{v} \f$.
     515             :    * Equivalent to calling \p operator+=().
     516             :    */
     517             :   virtual void add (const T a, const NumericVector<T> & v) = 0;
     518             : 
     519             :   /**
     520             :    * Computes \f$ \vec{u} \leftarrow \vec{u} + \vec{v} \f$,
     521             :    * where \p v is a pointer and each \p dof_indices[i] specifies where
     522             :    * to add value \p v[i].  This should be overridden in subclasses
     523             :    * for efficiency. Note that library implementations of this
     524             :    * method are thread safe
     525             :    */
     526             :   virtual void add_vector (const T * v,
     527             :                            const std::vector<numeric_index_type> & dof_indices);
     528             : 
     529             :   /**
     530             :    * Computes \f$ \vec{u} \leftarrow \vec{u} + \vec{v} \f$,
     531             :    * where \p v is a std::vector and each \p dof_indices[i] specifies
     532             :    * where to add value \p v[i]. This method is guaranteed to be thread safe as long as library
     533             :    * implementations of \p NumericVector are used
     534             :    */
     535             :   void add_vector (const std::vector<T> & v,
     536             :                    const std::vector<numeric_index_type> & dof_indices);
     537             : 
     538             :   /**
     539             :    * Computes \f$ \vec{u} \leftarrow \vec{u} + \vec{v} \f$,
     540             :    * where \p v is a NumericVector and each \p dof_indices[i]
     541             :    * specifies where to add value \p v(i). This method is
     542             :    * guaranteed to be thread-safe as long as library implementations of \p NumericVector are used
     543             :    */
     544             :   void add_vector (const NumericVector<T> & v,
     545             :                    const std::vector<numeric_index_type> & dof_indices);
     546             : 
     547             :   /**
     548             :    * Computes \f$ \vec{u} \leftarrow \vec{u} + \vec{v} \f$,
     549             :    * where \p v is a DenseVector and each \p dof_indices[i] specifies
     550             :    * where to add value \p v(i). This method is guaranteed to be thread safe as long as library
     551             :    * implementations of \p NumericVector are used
     552             :    */
     553             :   void add_vector (const DenseVector<T> & v,
     554             :                    const std::vector<numeric_index_type> & dof_indices);
     555             : 
     556             :   /**
     557             :    * Computes \f$ \vec{u} \leftarrow \vec{u} + A \vec{v} \f$,
     558             :    * i.e. adds the product of a \p SparseMatrix \p A and a \p
     559             :    * NumericVector \p v to \p this.
     560             :    */
     561             :   virtual void add_vector (const NumericVector<T> & v,
     562             :                            const SparseMatrix<T> & A) = 0;
     563             : 
     564             :   /**
     565             :    * Computes \f$ \vec{u} \leftarrow \vec{u} + A \vec{v} \f$,
     566             :    * i.e. adds the product of a \p ShellMatrix \p A and a \p
     567             :    * NumericVector \p v to \p this.
     568             :    */
     569             :   void add_vector (const NumericVector<T> & v,
     570             :                    const ShellMatrix<T> & A);
     571             : 
     572             :   /**
     573             :    * Computes \f$ \vec{u} \leftarrow \vec{u} + A^T \vec{v} \f$,
     574             :    * i.e. adds the product of the transpose of a \p SparseMatrix \p A
     575             :    * and a \p NumericVector \p v to \p this.
     576             :    */
     577             :   virtual void add_vector_transpose (const NumericVector<T> & v,
     578             :                                      const SparseMatrix<T> & A) = 0;
     579             : 
     580             :   /**
     581             :    * Inserts the entries of \p v in *this at the locations specified by \p v. Note that library
     582             :    * implementations of this method are thread safe
     583             :    */
     584             :   virtual void insert (const T * v,
     585             :                        const std::vector<numeric_index_type> & dof_indices);
     586             : 
     587             :   /**
     588             :    * Inserts the entries of \p v in *this at the locations specified by \p v. This method is
     589             :    * guaranteed to be thread-safe as long as library implementations of \p NumericVector are used
     590             :    */
     591             :   void insert (const std::vector<T> & v,
     592             :                const std::vector<numeric_index_type> & dof_indices);
     593             : 
     594             :   /**
     595             :    * Inserts the entries of \p v in *this at the locations specified by \p v. This method is
     596             :    * guaranteed to be thread-safe as long as library implementations of \p NumericVector are used
     597             :    */
     598             :   void insert (const NumericVector<T> & v,
     599             :                const std::vector<numeric_index_type> & dof_indices);
     600             : 
     601             :   /**
     602             :    * Inserts the entries of \p v in *this at the locations specified by \p v. This method is
     603             :    * guaranteed to be thread-safe as long as library implementations of \p NumericVector are used
     604             :    */
     605             :   void insert (const DenseVector<T> & v,
     606             :                const std::vector<numeric_index_type> & dof_indices);
     607             : 
     608             :   /**
     609             :    * Inserts the entries of \p v in *this at the locations specified by \p v. This method is
     610             :    * guaranteed to be thread-safe as long as library implementations of \p NumericVector are used
     611             :    */
     612             :   void insert (const DenseSubVector<T> & v,
     613             :                const std::vector<numeric_index_type> & dof_indices);
     614             : 
     615             :   /**
     616             :    * Scale each element of the vector by the given \p factor.
     617             :    */
     618             :   virtual void scale (const T factor) = 0;
     619             : 
     620             :   /**
     621             :    * Sets \f$ u_i \leftarrow |u_i| \f$ for each entry in the vector.
     622             :    */
     623             :   virtual void abs() = 0;
     624             : 
     625             :   /**
     626             :    * \returns \f$ \vec{u} \cdot \vec{v} \f$, the dot product of
     627             :    * (*this) with the vector \p v.
     628             :    *
     629             :    * Uses the complex-conjugate of \p v in the complex-valued case.
     630             :    */
     631             :   virtual T dot(const NumericVector<T> & v) const = 0;
     632             : 
     633             :   /**
     634             :    * Creates a copy of the global vector in the local vector \p
     635             :    * v_local.
     636             :    */
     637             :   virtual void localize (std::vector<T> & v_local) const = 0;
     638             : 
     639             :   /**
     640             :    * Same, but fills a \p NumericVector<T> instead of a \p
     641             :    * std::vector.
     642             :    */
     643             :   virtual void localize (NumericVector<T> & v_local) const = 0;
     644             : 
     645             :   /**
     646             :    * Creates a local vector \p v_local containing only information
     647             :    * relevant to this processor, as defined by the \p send_list.
     648             :    */
     649             :   virtual void localize (NumericVector<T> & v_local,
     650             :                          const std::vector<numeric_index_type> & send_list) const = 0;
     651             : 
     652             :   /**
     653             :    * Fill in the local std::vector "v_local" with the global indices
     654             :    * given in "indices".
     655             :    *
     656             :    * \note The indices can be different on every processor, and the
     657             :    * same index can be localized to more than one processor.  The
     658             :    * resulting v_local can be shorter than the original, and the
     659             :    * entries will be in the order specified by indices.
     660             :    *
     661             :    * Example:
     662             :    * \verbatim
     663             :    *   On 4 procs *this = {a, b, c, d, e, f, g, h, i} is a parallel vector.
     664             :    *   On each proc, the indices arrays are set up as:
     665             :    *   proc0, indices = {1,2,4,5}
     666             :    *   proc1, indices = {2,5,6,8}
     667             :    *   proc2, indices = {2,3,6,7}
     668             :    *   proc3, indices = {0,1,2,3}
     669             :    *
     670             :    *   After calling this version of localize, the v_local vectors are:
     671             :    *   proc0, v_local = {b,c,e,f}
     672             :    *   proc1, v_local = {c,f,g,i}
     673             :    *   proc2, v_local = {c,d,g,h}
     674             :    *   proc3, v_local = {a,b,c,d}
     675             :    * \endverbatim
     676             :    *
     677             :    * This function is useful in parallel I/O routines, when you have a
     678             :    * parallel vector of solution values which you want to write a
     679             :    * subset of.
     680             :    */
     681             :   virtual void localize (std::vector<T> & v_local,
     682             :                          const std::vector<numeric_index_type> & indices) const = 0;
     683             : 
     684             :   /**
     685             :    * Updates a local vector with selected values from neighboring
     686             :    * processors, as defined by \p send_list.
     687             :    */
     688             :   virtual void localize (const numeric_index_type first_local_idx,
     689             :                          const numeric_index_type last_local_idx,
     690             :                          const std::vector<numeric_index_type> & send_list) = 0;
     691             : 
     692             :   /**
     693             :    * Creates a local copy of the global vector in \p v_local only on
     694             :    * processor \p proc_id.  By default the data is sent to processor
     695             :    * 0.  This method is useful for outputting data from one processor.
     696             :    */
     697             :   virtual void localize_to_one (std::vector<T> & v_local,
     698             :                                 const processor_id_type proc_id=0) const = 0;
     699             : 
     700             :   /**
     701             :    * \returns \p -1 when \p this is equivalent to \p other_vector
     702             :    * (up to the given \p threshold), or the first index where
     703             :    * \p abs(a[i]-b[i]) exceeds the threshold.
     704             :    */
     705             :   virtual int compare (const NumericVector<T> & other_vector,
     706             :                        const Real threshold = TOLERANCE) const;
     707             : 
     708             :   /**
     709             :    * \returns \p -1 when \p this is equivalent to \p other_vector, (up
     710             :    * to the given local relative \p threshold), or the first index
     711             :    * where \p abs(a[i]-b[i])/max(a[i],b[i]) exceeds the threshold.
     712             :    */
     713             :   virtual int local_relative_compare (const NumericVector<T> & other_vector,
     714             :                                       const Real threshold = TOLERANCE) const;
     715             : 
     716             :   /**
     717             :    * \returns \p -1 when \p this is equivalent to \p other_vector (up
     718             :    * to the given global relative \p threshold), or the first index
     719             :    * where \p abs(a[i]-b[i])/max_j(a[j],b[j]) exceeds the threshold.
     720             :    */
     721             :   virtual int global_relative_compare (const NumericVector<T> & other_vector,
     722             :                                        const Real threshold = TOLERANCE) const;
     723             : 
     724             :   /**
     725             :    * Computes \f$ u_i \leftarrow u_i v_i \f$ (summation not implied)
     726             :    * i.e. the pointwise (component-wise) product of \p vec1 and
     727             :    * \p vec2, and stores the result in \p *this.
     728             :    */
     729             :   virtual void pointwise_mult (const NumericVector<T> & vec1,
     730             :                                const NumericVector<T> & vec2) = 0;
     731             : 
     732             :   /**
     733             :    * Computes \f$ u_i \leftarrow \frac{v_{1,i}}{v_{2,i}} \f$ (summation not implied)
     734             :    * i.e. the pointwise (component-wise) division of \p vec1 and
     735             :    * \p vec2, and stores the result in \p *this.
     736             :    */
     737             :   virtual void pointwise_divide (const NumericVector<T> & vec1,
     738             :                                  const NumericVector<T> & vec2) = 0;
     739             : 
     740             :   /**
     741             :    * Prints the local contents of the vector, by default to
     742             :    * libMesh::out
     743             :    */
     744             :   virtual void print(std::ostream & os=libMesh::out) const;
     745             : 
     746             :   /**
     747             :    * Prints the global contents of the vector, by default to
     748             :    * libMesh::out
     749             :    */
     750             :   virtual void print_global(std::ostream & os=libMesh::out) const;
     751             : 
     752             :   /**
     753             :    * Same as above but allows you to use stream syntax.
     754             :    */
     755           0 :   friend std::ostream & operator << (std::ostream & os, const NumericVector<T> & v)
     756             :   {
     757           0 :     v.print_global(os);
     758           0 :     return os;
     759             :   }
     760             : 
     761             :   /**
     762             :    * Print the contents of the vector in Matlab's sparse matrix
     763             :    * format. Optionally prints the vector to the file named \p name.
     764             :    * If \p name is not specified it is dumped to the screen.
     765             :    */
     766             :   virtual void print_matlab(const std::string & filename = "") const;
     767             : 
     768             :   /**
     769             :    * Read the contents of the vector from the Matlab-script format
     770             :    * used by PETSc.
     771             :    *
     772             :    * If the size of the matrix in \p filename appears consistent with
     773             :    * the existing partitioning of \p this then the existing parallel
     774             :    * decomposition will be retained.
     775             :    * If not, then \p this will be initialized with the size from
     776             :    * the file, linearly partitioned onto the number of processors
     777             :    * available.
     778             :    */
     779             :   virtual void read_matlab(const std::string & filename);
     780             : 
     781             :   /**
     782             :    * Fills in \p subvector from this vector using the indices in \p rows.
     783             :    *
     784             :    * \p supplying_global_rows communicates whether
     785             :    * the supplied vector of rows corresponds to all the rows that
     786             :    * should be used in the subvector's index set, e.g. whether the
     787             :    * rows correspond to the global collective. If the rows supplied
     788             :    * are only the local indices, then \p supplying_global_rows should
     789             :    * be set to false
     790             :    *
     791             :    * This is currently only implemented for \p PetscVector and \p
     792             :    * EigenSparseVector.
     793             :    */
     794           0 :   virtual void create_subvector(NumericVector<T> & /* subvector */,
     795             :                                 const std::vector<numeric_index_type> & /* rows */,
     796             :                                 bool /* supplying_global_rows */ = true) const
     797             :   {
     798           0 :     libmesh_not_implemented();
     799             :   }
     800             : 
     801             :   /**
     802             :    * Creates a view into this vector using the indices in \p
     803             :    * rows. Calls to this API should always be paired with a call to \p restore_subvector,
     804             :    * else any changes made in the subvector will not be reflected in (\p this) original vector.
     805             :    *
     806             :    * This is currently only implemented for \p PetscVector and \p
     807             :    * EigenSparseVector.
     808             :    */
     809             :   virtual std::unique_ptr<NumericVector<T>>
     810           0 :   get_subvector(const std::vector<numeric_index_type> & /* rows */)
     811             :   {
     812           0 :     libmesh_not_implemented();
     813             :   }
     814             : 
     815             :   /**
     816             :    * Restores a view into this vector using the indices in \p
     817             :    * rows.  The \p subvector should have been acquired from \p
     818             :    * get_subvector() with the same rows.
     819             :    *
     820             :    * This is currently only implemented for \p PetscVector and \p
     821             :    * EigenSparseVector.
     822             :    */
     823           0 :   virtual void restore_subvector(std::unique_ptr<NumericVector<T>> /* subvector */,
     824             :                                  const std::vector<numeric_index_type> & /* rows */)
     825             :   {
     826           0 :     libmesh_not_implemented();
     827             :   }
     828             : 
     829             :   /**
     830             :    * Swaps the contents of this with \p v.  There should be enough
     831             :    * indirection in subclasses to make this an O(1) header-swap
     832             :    * operation.
     833             :    */
     834             :   virtual void swap (NumericVector<T> & v);
     835             : 
     836             :   /**
     837             :    * \returns the max number of entries (across all procs) that the
     838             :    * NumericVector can have.
     839             :    *
     840             :    * Although we define numeric_index_type, and it is typically
     841             :    * required that the NumericVector's underlying implementation's
     842             :    * indices have _size_ equal to sizeof(numeric_index_type), these
     843             :    * two types can still have different _signedness_, which affects
     844             :    * the maximum number of values which can be stored in the
     845             :    * NumericVector.
     846             :    */
     847             :   virtual std::size_t max_allowed_id() const = 0;
     848             : 
     849             :   /**
     850             :    * \returns whether or not this vector is able to be read for
     851             :    * global operations
     852             :    */
     853             :   bool readable() const;
     854             : 
     855             :   /**
     856             :    * \returns whether or not this vector and the vector \p v are
     857             :    * able to be read for global operations with one-another
     858             :    */
     859             :   bool compatible(const NumericVector<T> & v) const;
     860             : 
     861             : protected:
     862             : 
     863             :   /**
     864             :    * Flag which tracks whether the vector's values are consistent on
     865             :    * all processors after insertion or addition of values has occurred
     866             :    * on some or all processors.
     867             :    */
     868             :   bool _is_closed;
     869             : 
     870             :   /**
     871             :    * \p true once init() has been called.
     872             :    */
     873             :   bool _is_initialized;
     874             : 
     875             :   /**
     876             :    * Type of vector.
     877             :    */
     878             :   ParallelType _type;
     879             : 
     880             :   /**
     881             :    * Mutex for performing thread-safe operations
     882             :    */
     883             :   std::mutex _numeric_vector_mutex;
     884             : };
     885             : 
     886             : 
     887             : /*----------------------- Inline functions ----------------------------------*/
     888             : 
     889             : 
     890             : 
     891             : template <typename T>
     892             : inline
     893     3320820 : NumericVector<T>::NumericVector (const Parallel::Communicator & comm_in,
     894             :                                  const ParallelType ptype) :
     895             :   ParallelObject(comm_in),
     896     3155920 :   _is_closed(false),
     897     3155920 :   _is_initialized(false),
     898     3320148 :   _type(ptype)
     899             : {
     900     3232200 : }
     901             : 
     902             : 
     903             : 
     904             : template <typename T>
     905             : inline
     906           0 : NumericVector<T>::NumericVector (const Parallel::Communicator & comm_in,
     907             :                                  const numeric_index_type /*n*/,
     908             :                                  const ParallelType ptype) :
     909             :   ParallelObject(comm_in),
     910           0 :   _is_closed(false),
     911           0 :   _is_initialized(false),
     912           0 :   _type(ptype)
     913             : {
     914           0 :   libmesh_not_implemented(); // Abstract base class!
     915             :   // init(n, n, false, ptype);
     916             : }
     917             : 
     918             : 
     919             : 
     920             : template <typename T>
     921             : inline
     922           0 : NumericVector<T>::NumericVector (const Parallel::Communicator & comm_in,
     923             :                                  const numeric_index_type /*n*/,
     924             :                                  const numeric_index_type /*n_local*/,
     925             :                                  const ParallelType ptype) :
     926             :   ParallelObject(comm_in),
     927           0 :   _is_closed(false),
     928           0 :   _is_initialized(false),
     929           0 :   _type(ptype)
     930             : {
     931           0 :   libmesh_not_implemented(); // Abstract base class!
     932             :   // init(n, n_local, false, ptype);
     933             : }
     934             : 
     935             : 
     936             : 
     937             : template <typename T>
     938             : inline
     939           0 : NumericVector<T>::NumericVector (const Parallel::Communicator & comm_in,
     940             :                                  const numeric_index_type /*n*/,
     941             :                                  const numeric_index_type /*n_local*/,
     942             :                                  const std::vector<numeric_index_type> & /*ghost*/,
     943             :                                  const ParallelType ptype) :
     944             :   ParallelObject(comm_in),
     945           0 :   _is_closed(false),
     946           0 :   _is_initialized(false),
     947           0 :   _type(ptype)
     948             : {
     949           0 :   libmesh_not_implemented(); // Abstract base class!
     950             :   // init(n, n_local, ghost, false, ptype);
     951             : }
     952             : 
     953             : 
     954             : 
     955             : template <typename T>
     956             : inline
     957           0 : void NumericVector<T>::clear ()
     958             : {
     959           0 :   _is_closed      = false;
     960           0 :   _is_initialized = false;
     961           0 : }
     962             : 
     963             : 
     964             : 
     965             : template <typename T>
     966             : inline
     967     2054333 : void NumericVector<T>::get(const std::vector<numeric_index_type> & index,
     968             :                            T * values) const
     969             : {
     970           0 :   const std::size_t num = index.size();
     971    20422419 :   for (std::size_t i=0; i<num; i++)
     972             :     {
     973    18368086 :       values[i] = (*this)(index[i]);
     974             :     }
     975     2054333 : }
     976             : 
     977             : 
     978             : 
     979             : template <typename T>
     980             : inline
     981    95559144 : void NumericVector<T>::get(const std::vector<numeric_index_type> & index,
     982             :                            std::vector<T> & values) const
     983             : {
     984    17213819 :   const std::size_t num = index.size();
     985    95559144 :   values.resize(num);
     986    95559144 :   if (!num)
     987       24428 :     return;
     988             : 
     989    95276907 :   this->get(index, values.data());
     990             : }
     991             : 
     992             : 
     993             : 
     994             : template <typename T>
     995             : inline
     996           0 : void NumericVector<T>::add_vector(const std::vector<T> & v,
     997             :                                   const std::vector<numeric_index_type> & dof_indices)
     998             : {
     999           0 :   libmesh_assert(v.size() == dof_indices.size());
    1000           0 :   if (!v.empty())
    1001           0 :     this->add_vector(v.data(), dof_indices);
    1002           0 : }
    1003             : 
    1004             : 
    1005             : 
    1006             : template <typename T>
    1007             : inline
    1008    19557562 : void NumericVector<T>::add_vector(const DenseVector<T> & v,
    1009             :                                   const std::vector<numeric_index_type> & dof_indices)
    1010             : {
    1011     1886303 :   libmesh_assert(v.size() == dof_indices.size());
    1012    21476893 :   if (!v.empty())
    1013    21476893 :     this->add_vector(&v(0), dof_indices);
    1014    19557562 : }
    1015             : 
    1016             : 
    1017             : 
    1018             : template <typename T>
    1019             : inline
    1020           0 : void NumericVector<T>::insert(const std::vector<T> & v,
    1021             :                               const std::vector<numeric_index_type> & dof_indices)
    1022             : {
    1023           0 :   libmesh_assert(v.size() == dof_indices.size());
    1024           0 :   if (!v.empty())
    1025           0 :     this->insert(v.data(), dof_indices);
    1026           0 : }
    1027             : 
    1028             : 
    1029             : 
    1030             : template <typename T>
    1031             : inline
    1032           0 : void NumericVector<T>::insert(const DenseVector<T> & v,
    1033             :                               const std::vector<numeric_index_type> & dof_indices)
    1034             : {
    1035           0 :   libmesh_assert(v.size() == dof_indices.size());
    1036           0 :   if (!v.empty())
    1037           0 :     this->insert(&v(0), dof_indices);
    1038           0 : }
    1039             : 
    1040             : 
    1041             : 
    1042             : template <typename T>
    1043             : inline
    1044        1728 : void NumericVector<T>::insert(const DenseSubVector<T> & v,
    1045             :                               const std::vector<numeric_index_type> & dof_indices)
    1046             : {
    1047           0 :   libmesh_assert(v.size() == dof_indices.size());
    1048        1728 :   if (!v.empty())
    1049        1728 :     this->insert(&v(0), dof_indices);
    1050        1728 : }
    1051             : 
    1052             : 
    1053             : 
    1054             : // Full specialization of the print() member for complex
    1055             : // variables.  This must precede the non-specialized
    1056             : // version, at least according to icc v7.1
    1057             : template <>
    1058             : inline
    1059           0 : void NumericVector<Complex>::print(std::ostream & os) const
    1060             : {
    1061             :   libmesh_assert (this->initialized());
    1062           0 :   os << "Size\tglobal =  " << this->size()
    1063           0 :      << "\t\tlocal =  " << this->local_size() << std::endl;
    1064             : 
    1065             :   // std::complex<>::operator<<() is defined, but use this form
    1066           0 :   os << "#\tReal part\t\tImaginary part" << std::endl;
    1067           0 :   for (auto i : index_range(*this))
    1068           0 :     os << i << "\t"
    1069           0 :        << (*this)(i).real() << "\t\t"
    1070           0 :        << (*this)(i).imag() << std::endl;
    1071           0 : }
    1072             : 
    1073             : 
    1074             : 
    1075             : template <typename T>
    1076             : inline
    1077           0 : void NumericVector<T>::print(std::ostream & os) const
    1078             : {
    1079           0 :   libmesh_assert (this->initialized());
    1080           0 :   os << "Size\tglobal =  " << this->size()
    1081           0 :      << "\t\tlocal =  " << this->local_size() << std::endl;
    1082             : 
    1083           0 :   os << "#\tValue" << std::endl;
    1084           0 :   for (auto i : index_range(*this))
    1085           0 :     os << i << "\t" << (*this)(i) << std::endl;
    1086           0 : }
    1087             : 
    1088             : 
    1089             : 
    1090             : template <>
    1091             : inline
    1092           0 : void NumericVector<Complex>::print_global(std::ostream & os) const
    1093             : {
    1094             :   libmesh_assert (this->initialized());
    1095             : 
    1096           0 :   std::vector<Complex> v(this->size());
    1097           0 :   this->localize(v);
    1098             : 
    1099             :   // Right now we only want one copy of the output
    1100           0 :   if (this->processor_id())
    1101             :     return;
    1102             : 
    1103           0 :   os << "Size\tglobal =  " << this->size() << std::endl;
    1104           0 :   os << "#\tReal part\t\tImaginary part" << std::endl;
    1105           0 :   for (auto i : make_range(v.size()))
    1106           0 :     os << i << "\t"
    1107           0 :        << v[i].real() << "\t\t"
    1108             :        << v[i].imag() << std::endl;
    1109             : }
    1110             : 
    1111             : 
    1112             : template <typename T>
    1113             : inline
    1114           0 : void NumericVector<T>::print_global(std::ostream & os) const
    1115             : {
    1116           0 :   libmesh_assert (this->initialized());
    1117             : 
    1118           0 :   std::vector<T> v(this->size());
    1119           0 :   this->localize(v);
    1120             : 
    1121             :   // Right now we only want one copy of the output
    1122           0 :   if (this->processor_id())
    1123           0 :     return;
    1124             : 
    1125           0 :   os << "Size\tglobal =  " << this->size() << std::endl;
    1126           0 :   os << "#\tValue" << std::endl;
    1127           0 :   for (auto i : make_range(v.size()))
    1128           0 :     os << i << "\t" << v[i] << std::endl;
    1129             : }
    1130             : 
    1131             : 
    1132             : 
    1133             : template <typename T>
    1134             : inline
    1135       28720 : void  NumericVector<T>::swap (NumericVector<T> & v)
    1136             : {
    1137       28720 :   std::swap(_is_closed, v._is_closed);
    1138       28720 :   std::swap(_is_initialized, v._is_initialized);
    1139       28720 :   std::swap(_type, v._type);
    1140       28720 : }
    1141             : 
    1142             : template <typename T>
    1143             : auto
    1144             : l1_norm(const NumericVector<T> & vec)
    1145             : {
    1146             :   return vec.l1_norm();
    1147             : }
    1148             : 
    1149             : template <typename T>
    1150             : auto
    1151             : l1_norm_diff(const NumericVector<T> & vec1, const NumericVector<T> & vec2)
    1152             : {
    1153             :   return vec1.l1_norm_diff(vec2);
    1154             : }
    1155             : 
    1156             : } // namespace libMesh
    1157             : 
    1158             : 
    1159             : // Workaround for weird boost/NumericVector interaction bug
    1160             : #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
    1161             : #include <boost/mpl/bool.hpp>
    1162             : 
    1163             : namespace boost { namespace multiprecision { namespace detail {
    1164             : template <typename T, typename To>
    1165             : struct is_lossy_conversion<libMesh::NumericVector<T>, To> {
    1166             :   typedef boost::mpl::true_ type;
    1167             :   static const bool value = type::value;
    1168             : };
    1169             : }}}
    1170             : #endif
    1171             : 
    1172             : 
    1173             : #endif  // LIBMESH_NUMERIC_VECTOR_H

Generated by: LCOV version 1.14