1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2015 - 2020 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_vector_space_vector_h
17 #define dealii_vector_space_vector_h
18 
19 #include <deal.II/base/config.h>
20 
21 #include <deal.II/base/numbers.h>
22 
23 #include <deal.II/lac/vector_operation.h>
24 
25 #include <memory>
26 
27 
28 DEAL_II_NAMESPACE_OPEN
29 
30 // Forward declarations
31 #ifndef DOXYGEN
32 class IndexSet;
33 namespace LinearAlgebra
34 {
35   class CommunicationPatternBase;
36   template <typename Number>
37   class ReadWriteVector;
38 } // namespace LinearAlgebra
39 #endif
40 
41 namespace LinearAlgebra
42 {
43   /*! @addtogroup Vectors
44    *@{
45    */
46 
47   /**
48    * VectorSpaceVector is an abstract class that is used to define the
49    * interface that vector classes need to implement when they want to
50    * implement global operations. This class is complementary of
51    * ReadWriteVector which allows the access of individual elements but does
52    * not allow global operations.
53    */
54   template <typename Number>
55   class VectorSpaceVector
56   {
57   public:
58     using value_type = Number;
59     using size_type  = types::global_dof_index;
60     using real_type  = typename numbers::NumberTraits<Number>::real_type;
61 
62     /**
63      * Change the dimension to that of the vector V. The elements of V are not
64      * copied.
65      */
66     virtual void
67     reinit(const VectorSpaceVector<Number> &V,
68            const bool                       omit_zeroing_entries = false) = 0;
69 
70     /**
71      * Sets all elements of the vector to the scalar @p s. This operation is
72      * only allowed if @p s is equal to zero.
73      */
74     virtual VectorSpaceVector<Number> &
75     operator=(const Number s) = 0;
76 
77     /**
78      * Multiply the entire vector by a fixed factor.
79      */
80     virtual VectorSpaceVector<Number> &
81     operator*=(const Number factor) = 0;
82 
83     /**
84      * Divide the entire vector by a fixed factor.
85      */
86     virtual VectorSpaceVector<Number> &
87     operator/=(const Number factor) = 0;
88 
89     /**
90      * Add the vector @p V to the present one.
91      */
92     virtual VectorSpaceVector<Number> &
93     operator+=(const VectorSpaceVector<Number> &V) = 0;
94 
95     /**
96      * Subtract the vector @p V from the present one.
97      */
98     virtual VectorSpaceVector<Number> &
99     operator-=(const VectorSpaceVector<Number> &V) = 0;
100 
101     /**
102      * Import all the elements present in the vector's IndexSet from the input
103      * vector @p V. VectorOperation::values @p operation is used to decide if
104      * the elements in @p V should be added to the current vector or replace the
105      * current elements. The last parameter can be used if the same
106      * communication pattern is used multiple times. This can be used to improve
107      * performance.
108      */
109     virtual void
110     import(
111       const ReadWriteVector<Number> &                 V,
112       VectorOperation::values                         operation,
113       std::shared_ptr<const CommunicationPatternBase> communication_pattern =
114         std::shared_ptr<const CommunicationPatternBase>()) = 0;
115 
116     /**
117      * Return the scalar product of two vectors.
118      */
119     virtual Number operator*(const VectorSpaceVector<Number> &V) const = 0;
120 
121     /**
122      * Add @p a to all components. Note that @p a is a scalar not a vector.
123      */
124     virtual void
125     add(const Number a) = 0;
126 
127     /**
128      * Simple addition of a multiple of a vector, i.e. <tt>*this += a*V</tt>.
129      */
130     virtual void
131     add(const Number a, const VectorSpaceVector<Number> &V) = 0;
132 
133     /**
134      * Multiple addition of scaled vectors, i.e. <tt>*this += a*V+b*W</tt>.
135      */
136     virtual void
137     add(const Number                     a,
138         const VectorSpaceVector<Number> &V,
139         const Number                     b,
140         const VectorSpaceVector<Number> &W) = 0;
141 
142     /**
143      * Scaling and simple addition of a multiple of a vector, i.e. <tt>*this =
144      * s*(*this)+a*V</tt>.
145      */
146     virtual void
147     sadd(const Number                     s,
148          const Number                     a,
149          const VectorSpaceVector<Number> &V) = 0;
150 
151     /**
152      * Scale each element of this vector by the corresponding element in the
153      * argument. This function is mostly meant to simulate multiplication (and
154      * immediate re-assignment) by a diagonal scaling matrix.
155      */
156     virtual void
157     scale(const VectorSpaceVector<Number> &scaling_factors) = 0;
158 
159     /**
160      * Assignment <tt>*this = a*V</tt>.
161      */
162     virtual void
163     equ(const Number a, const VectorSpaceVector<Number> &V) = 0;
164 
165     /**
166      * Return whether the vector contains only elements with value zero.
167      */
168     virtual bool
169     all_zero() const = 0;
170 
171     /**
172      * Return the mean value of all the entries of this vector.
173      */
174     virtual value_type
175     mean_value() const = 0;
176 
177     /**
178      * Return the l<sub>1</sub> norm of the vector (i.e., the sum of the
179      * absolute values of all entries among all processors).
180      */
181     virtual real_type
182     l1_norm() const = 0;
183 
184     /**
185      * Return the l<sub>2</sub> norm of the vector (i.e., the square root of
186      * the sum of the square of all entries among all processors).
187      */
188     virtual real_type
189     l2_norm() const = 0;
190 
191     /**
192      * Return the maximum norm of the vector (i.e., the maximum absolute value
193      * among all entries and among all processors).
194      */
195     virtual real_type
196     linfty_norm() const = 0;
197 
198     /**
199      * Perform a combined operation of a vector addition and a subsequent
200      * inner product, returning the value of the inner product. In other
201      * words, the result of this function is the same as if the user called
202      * @code
203      * this->add(a, V);
204      * return_value = *this * W;
205      * @endcode
206      *
207      * The reason this function exists is that this operation involves less
208      * memory transfer than calling the two functions separately. This method
209      * only needs to load three vectors, @p this, @p V, @p W, whereas calling
210      * separate methods means to load the calling vector @p this twice. Since
211      * most vector operations are memory transfer limited, this reduces the
212      * time by 25\% (or 50\% if @p W equals @p this).
213      *
214      * For complex-valued vectors, the scalar product in the second step is
215      * implemented as
216      * $\left<v,w\right>=\sum_i v_i \bar{w_i}$.
217      */
218     virtual Number
219     add_and_dot(const Number                     a,
220                 const VectorSpaceVector<Number> &V,
221                 const VectorSpaceVector<Number> &W) = 0;
222 
223     /**
224      * This function does nothing and only exists for backward compatibility.
225      */
compress(VectorOperation::values)226     virtual void compress(VectorOperation::values)
227     {}
228 
229     /**
230      * Return the global size of the vector, equal to the sum of the number of
231      * locally owned indices among all processors.
232      */
233     virtual size_type
234     size() const = 0;
235 
236     /**
237      * Return an index set that describes which elements of this vector are
238      * owned by the current processor. As a consequence, the index sets
239      * returned on different processors if this is a distributed vector will
240      * form disjoint sets that add up to the complete index set. Obviously, if
241      * a vector is created on only one processor, then the result would
242      * satisfy
243      * @code
244      *  vec.locally_owned_elements() == complete_index_set(vec.size())
245      * @endcode
246      */
247     virtual dealii::IndexSet
248     locally_owned_elements() const = 0;
249 
250     /**
251      * Print the vector to the output stream @p out.
252      */
253     virtual void
254     print(std::ostream &     out,
255           const unsigned int precision  = 3,
256           const bool         scientific = true,
257           const bool         across     = true) const = 0;
258 
259     /**
260      * Return the memory consumption of this class in bytes.
261      */
262     virtual std::size_t
263     memory_consumption() const = 0;
264 
265     /**
266      * Destructor. Declared as virtual so that inheriting classes (which may
267      * manage their own memory) are destroyed correctly.
268      */
269     virtual ~VectorSpaceVector() = default;
270   };
271   /*@}*/
272 } // namespace LinearAlgebra
273 
274 // ---------------------------- Free functions --------------------------
275 
276 namespace LinearAlgebra
277 {
278   /**
279    * Shift all entries of the vector by a constant factor so that the mean
280    * value of the vector becomes zero.
281    */
282   template <typename Number>
283   void
set_zero_mean_value(VectorSpaceVector<Number> & vector)284   set_zero_mean_value(VectorSpaceVector<Number> &vector)
285   {
286     vector.add(-vector.mean_value());
287   }
288 } // namespace LinearAlgebra
289 
290 DEAL_II_NAMESPACE_CLOSE
291 
292 #endif
293