double_vector.h
Go to the documentation of this file.
1 //LIC// ====================================================================
2 //LIC// This file forms part of oomph-lib, the object-oriented,
3 //LIC// multi-physics finite-element library, available
4 //LIC// at http://www.oomph-lib.org.
5 //LIC//
6 //LIC// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 #ifndef OOMPH_DOUBLE_VECTOR_CLASS_HEADER
31 #define OOMPH_DOUBLE_VECTOR_CLASS_HEADER
32 
33 // Config header generated by autoconfig
34 #ifdef HAVE_CONFIG_H
35  #include <oomph-lib-config.h>
36 #endif
37 
38 #ifdef OOMPH_HAS_MPI
39 #include "mpi.h"
40 #endif
41 
42 // c++ headers
43 #include <algorithm>
44 #include <ostream>
45 
46 // oomph headers
48 
49 
50 namespace oomph{
51 
52 class CRDoubleMatrix;
53 
54 //=============================================================================
55 /// \short A vector in the mathematical sense, initially developed for
56 /// linear algebra type applications.
57 /// If MPI then this vector can be distributed - its distribution is
58 /// described by the LinearAlgebraDistribution object at Distribution_pt.
59 /// Data is stored in a C-style pointer vector (double*)
60 //=============================================================================
62 {
63 
64  public :
65 
66  /// \short Constructor for an uninitialized DoubleVector
68  : Values_pt(0), Internal_values(true), Built(false)
69  {}
70 
71  /// \short Constructor. Assembles a DoubleVector with a prescribed
72  /// distribution. Additionally every entry can be set (with argument v -
73  /// defaults to 0).
74  DoubleVector(const LinearAlgebraDistribution* const &dist_pt,
75  const double& v=0.0)
76  : Values_pt(0), Internal_values(true), Built(false)
77  {
78  this->build(dist_pt,v);
79  }
80 
81  /// \short Constructor. Assembles a DoubleVector with a prescribed
82  /// distribution. Additionally every entry can be set (with argument v -
83  /// defaults to 0).
85  const double& v=0.0)
86  : Values_pt(0), Internal_values(true), Built(false)
87  {
88  this->build(dist,v);
89  }
90 
91  /// Destructor - just calls this->clear() to delete the distribution and data
93  {
94  this->clear();
95  }
96 
97  /// Copy constructor
98  DoubleVector(const DoubleVector& new_vector)
100  Values_pt(0), Internal_values(true), Built(false)
101  {
102  this->build(new_vector);
103  }
104 
105  /// assignment operator
106  void operator=(const DoubleVector& old_vector)
107  {
108  this->build(old_vector);
109  }
110 
111  /// \short Just copys the argument DoubleVector
112  void build(const DoubleVector& old_vector);
113 
114  /// \short Assembles a DoubleVector with distribution dist, if v is specified
115  /// each element is set to v, otherwise each element is set to 0.0
116  void build(const LinearAlgebraDistribution& dist,
117  const double& v)
118  {
119  this->build(&dist,v);
120  }
121 
122  /// \short Assembles a DoubleVector with distribution dist, if v is specified
123  /// each element is set to v, otherwise each element is set to 0.0
124  void build(const LinearAlgebraDistribution* const &dist_pt,
125  const double& v);
126 
127  /// \short Assembles a DoubleVector with a distribution dist and coefficients
128  /// taken from the vector v.
129  /// Note. The vector v MUST be of length nrow()
131  const Vector<double>& v)
132  {
133  this->build(&dist,v);
134  }
135 
136  /// \short Assembles a DoubleVector with a distribution dist and coefficients
137  /// taken from the vector v.
138  /// Note. The vector v MUST be of length nrow()
139  void build(const LinearAlgebraDistribution* const &dist_pt,
140  const Vector<double>& v);
141 
142  /// \short initialise the whole vector with value v
143  void initialise(const double& v);
144 
145  /// \short initialise the vector with coefficient from the vector v.
146  /// Note: The vector v must be of length
147  void initialise(const Vector<double> v);
148 
149  /// \short wipes the DoubleVector
150  void clear()
151  {
152  if (Internal_values)
153  {
154  delete[] Values_pt;
155  }
156  Values_pt = 0;
157  this->clear_distribution();
158  Built=false;
159  }
160 
161  // indicates whether this DoubleVector is built
162  bool built() const { return Built; }
163 
164  /// \short Allows are external data to be used by this vector.
165  /// WARNING: The size of the external data must correspond to the
166  /// LinearAlgebraDistribution dist_pt argument.
167  /// 1. When a rebuild method is called new internal values are created.
168  /// 2. It is not possible to redistribute(...) a vector with external
169  /// values .
170  /// 3. External values are only deleted by this vector if
171  /// delete_external_values = true.
172  void set_external_values(const LinearAlgebraDistribution* const& dist_pt,
173  double* external_values,
174  bool delete_external_values)
175  {
176  // clean the memory
177  this->clear();
178 
179  // Set the distribution
180  this->build_distribution(dist_pt);
181  // Say that it's built
182  Built = true;
183 
184  // set the external values
185  set_external_values(external_values,delete_external_values);
186  }
187 
188  /// \short Allows are external data to be used by this vector.
189  /// WARNING: The size of the external data must correspond to the
190  /// distribution of this vector.
191  /// 1. When a rebuild method is called new internal values are created.
192  /// 2. It is not possible to redistribute(...) a vector with external
193  /// values .
194  /// 3. External values are only deleted by this vector if
195  /// delete_external_values = true.
196  void set_external_values(double* external_values,
197  bool delete_external_values)
198  {
199 #ifdef PARANOID
200  // check that this distribution is setup
201  if (!this->distribution_built())
202  {
203  // if this vector does not own the double* values then it cannot be
204  // distributed.
205  // note: this is not stictly necessary - would just need to be careful
206  // with delete[] below.
207  std::ostringstream error_message;
208  error_message << "The distribution of the vector must be setup before "
209  << "external values can be set";
210  throw OomphLibError(error_message.str(),
211  OOMPH_CURRENT_FUNCTION,
212  OOMPH_EXCEPTION_LOCATION);
213  }
214 #endif
215  if (Internal_values)
216  {
217  delete[] Values_pt;
218  }
219  Values_pt = external_values;
220  Internal_values = delete_external_values;
221  }
222 
223  /// \short The contents of the vector are redistributed to match the new
224  /// distribution. In a non-MPI rebuild this method works, but does nothing.
225  /// \b NOTE 1: The current distribution and the new distribution must have
226  /// the same number of global rows.
227  /// \b NOTE 2: The current distribution and the new distribution must have
228  /// the same Communicator.
229  void redistribute(const LinearAlgebraDistribution* const& dist_pt);
230 
231  /// \short [] access function to the (local) values of this vector
232  double& operator[](int i);
233 
234  /// \short == operator
235  bool operator==(const DoubleVector& v);
236 
237  /// \short += operator with another vector
238  void operator+=(const DoubleVector& v);
239 
240  /// \short -= operator with another vector
241  void operator-=(const DoubleVector& v);
242 
243  /// \short multiply by a double
244  void operator*=(const double& d);
245 
246  /// \short divide by a double
247  void operator/=(const double& d);
248 
249  /// \short [] access function to the (local) values of this vector
250  const double& operator[](int i) const;
251 
252  /// \short Ouput operator for DoubleVector
253  friend std::ostream& operator<< (std::ostream &out, const DoubleVector& v);
254 
255  /// \short returns the maximum coefficient
256  double max() const;
257 
258  /// access function to the underlying values
259  double* values_pt() {return Values_pt;}
260 
261  /// \short access function to the underlying values (const version)
262  double* values_pt() const {return Values_pt;}
263 
264  /// output the global contents of the vector
265  void output(std::ostream &outfile,const int& output_precision = -1) const;
266 
267  /// output the global contents of the vector
268  void output(std::string filename,const int& output_precision = -1) const
269  {
270  // Open file
271  std::ofstream some_file;
272  some_file.open(filename.c_str());
273  output(some_file,output_precision);
274  some_file.close();
275  }
276 
277  /// output the local contents of the vector
278  void output_local_values(std::ostream &outfile,
279  const int& output_precision = -1) const;
280 
281  /// output the local contents of the vector
283  const int& output_precision = -1) const
284  {
285  // Open file
286  std::ofstream some_file;
287  some_file.open(filename.c_str());
288  output_local_values(some_file,output_precision);
289  some_file.close();
290  }
291 
292  /// output the local contents of the vector
293  void output_local_values_with_offset(std::ostream &outfile,
294  const int& output_precision = -1) const;
295 
296  /// output the local contents of the vector
298  const int& output_precision = -1) const
299  {
300  // Open file
301  std::ofstream some_file;
302  some_file.open(filename.c_str());
303  output_local_values_with_offset(some_file,output_precision);
304  some_file.close();
305  }
306 
307  /// compute the dot product of this vector with the vector vec.
308  double dot(const DoubleVector& vec) const;
309 
310  /// compute the 2 norm of this vector
311  double norm() const;
312 
313  /// compute the A-norm using the matrix at matrix_pt
314  double norm(const CRDoubleMatrix* matrix_pt) const;
315 
316  private :
317 
318  /// the local vector
319  double* Values_pt;
320 
321  /// \short Boolean flag to indicate whether the vector's data (values_pt)
322  /// is owned by this vector.
324 
325  /// indicates that the vector has been built and is usable
326  bool Built;
327 
328 }; //end of DoubleVector
329 
330 //=================================================================
331 /// Namespace for helper functions for DoubleVectors
332 //=================================================================
333 namespace DoubleVectorHelpers
334 {
335  /// \short Concatenate DoubleVectors.
336  /// Takes a Vector of DoubleVectors. If the out vector is built, we will not
337  /// build a new distribution. Otherwise we build a uniform distribution.
338  ///
339  /// The rows of the out vector is seen "as it is" in the in vectors.
340  /// For example, if we have DoubleVectors with distributions A and B,
341  /// distributed across two processors (p0 and p1),
342  ///
343  /// A: [a0] (on p0) B: [b0] (on p0)
344  /// [a1] (on p1) [b1] (on P1),
345  ///
346  /// then the out_vector is
347  ///
348  /// [a0 (on p0)
349  /// a1] (on p0)
350  /// [b0] (on p1)
351  /// b1] (on p1),
352  ///
353  /// Communication is required between processors. The sum of the global number
354  /// of rows in the in vectors must equal to the global number of rows in the
355  /// out vector. This condition must be met if one is to supply an out vector
356  /// with a distribution, otherwise we can let the function generate the
357  /// out vector distribution itself.
358  void concatenate(const Vector<DoubleVector*> &in_vector_pt,
359  DoubleVector &out_vector);
360 
361  /// \short Wrapper around the other concatenate(...) function.
362  /// Be careful with Vector of vectors. If the DoubleVectors are resized,
363  /// there could be reallocation of memory. If we wanted to use the function
364  /// which takes a Vector of pointers to DoubleVectors, we would either have
365  /// to invoke new and remember to delete, or create a temporary Vector to
366  /// store pointers to the DoubleVector objects.
367  /// This wrapper is meant to make life easier for the user by avoiding calls
368  /// to new/delete AND without creating a temporary vector of pointers to
369  /// DoubleVectors.
370  /// If we had C++ 11, this would be so much nicer since we can use smart
371  /// pointers which will delete themselves, so we do not have to remember
372  /// to delete!
373  void concatenate(Vector<DoubleVector> &in_vector,
374  DoubleVector &out_vector);
375 
376  /// \short Split a DoubleVector into the out DoubleVectors.
377  /// Let vec_A be the in Vector, and let vec_B and vec_C be the out vectors.
378  /// Then the splitting of vec_A is depicted below:
379  /// vec_A: [a0 (on p0)
380  /// a1] (on p0)
381  /// [a2 (on p1)
382  /// a3] (on p1)
383  ///
384  /// vec_B: [a0] (on p0) vec_C: [a2] (on p0)
385  /// [a1] (on p1) [a3] (on p1)
386  ///
387  /// Communication is required between processors.
388  /// The out_vector_pt must contain pointers to DoubleVector which has already
389  /// been built with the correct distribution; the sum of the number of global
390  /// row of the out vectors must be the same the the number of global rows of
391  /// the in vector.
392  void split(const DoubleVector &in_vector,
393  Vector<DoubleVector*> &out_vector_pt);
394 
395  /// \short Wrapper around the other split(...) function.
396  /// Be careful with Vector of vectors. If the DoubleVectors are resized,
397  /// there could be reallocation of memory. If we wanted to use the function
398  /// which takes a Vector of pointers to DoubleVectors, we would either have
399  /// to invoke new and remember to delete, or create a temporary Vector to
400  /// store pointers to the DoubleVector objects.
401  /// This wrapper is meant to make life easier for the user by avoiding calls
402  /// to new/delete AND without creating a temporary vector of pointers to
403  /// DoubleVectors.
404  /// If we had C++ 11, this would be so much nicer since we can use smart
405  /// pointers which will delete themselves, so we do not have to remember
406  /// to delete!
407  void split(const DoubleVector &in_vector,
408  Vector<DoubleVector> &out_vector);
409 
410  /// \short Concatenate DoubleVectors.
411  /// Takes a Vector of DoubleVectors. If the out vector is built, we will not
412  /// build a new distribution. Otherwise a new distribution will be built
413  /// using LinearAlgebraDistribution::concatenate(...).
414  ///
415  /// The out vector has its rows permuted according to the individual
416  /// distributions of the in vectors. For example, if we have DoubleVectors
417  /// with distributions A and B, distributed across two processors
418  /// (p0 and p1),
419  ///
420  /// A: [a0] (on p0) B: [b0] (on p0)
421  /// [a1] (on p1) [b1] (on P1),
422  ///
423  /// then the out_vector is
424  ///
425  /// [a0 (on p0)
426  /// b0] (on p0)
427  /// [a1 (on p1)
428  /// b1] (on p1),
429  ///
430  /// as opposed to
431  ///
432  /// [a0 (on p0)
433  /// a1] (on p0)
434  /// [b0 (on p1)
435  /// b1] (on p1).
436  ///
437  /// Note (1): The out vector may not be uniformly distributed even
438  /// if the the in vectors have uniform distributions. The nrow_local of the
439  /// out vector will be the sum of the nrow_local of the in vectors.
440  /// Try this out with two distributions of global rows 3 and 5, uniformly
441  /// distributed across two processors. Compare this against a distribution
442  /// of global row 8 distributed across two processors.
443  ///
444  /// There are no MPI send and receive, the data stays on the processor
445  /// as defined by the distributions from the in vectors.
447  const Vector<DoubleVector*> &in_vector_pt, DoubleVector &out_vector);
448 
449  /// \short Wrapper around the other concatenate_without_communication(...)
450  /// function.
451  /// Be careful with Vector of vectors. If the DoubleVectors are resized,
452  /// there could be reallocation of memory. If we wanted to use the function
453  /// which takes a Vector of pointers to DoubleVectors, we would either have
454  /// to invoke new and remember to delete, or create a temporary Vector to
455  /// store pointers to the DoubleVector objects.
456  /// This wrapper is meant to make life easier for the user by avoiding calls
457  /// to new/delete AND without creating a temporary vector of pointers to
458  /// DoubleVectors.
459  /// If we had C++ 11, this would be so much nicer since we can use smart
460  /// pointers which will delete themselves, so we do not have to remember
461  /// to delete!
463  Vector<DoubleVector> &in_vector, DoubleVector &out_vector);
464 
465  /// \short Split a DoubleVector into the out DoubleVectors.
466  /// Data stays on its current processor, no data is sent between processors.
467  /// This results in our vectors which are a permutation of the in vector.
468  ///
469  /// Let vec_A be the in Vector, and let vec_B and vec_C be the out vectors.
470  /// Then the splitting of vec_A is depicted below:
471  /// vec_A: [a0 (on p0)
472  /// a1] (on p0)
473  /// [a2 (on p1)
474  /// a3] (on p1)
475  ///
476  /// vec_B: [a0] (on p0) vec_C: [a1] (on p0)
477  /// [a2] (on p1) [a3] (on p1).
478  ///
479  /// This means that the distribution of the in vector MUST be a
480  /// concatenation of the out vector distributions, refer to
481  /// LinearAlgebraDistributionHelpers::concatenate(...) to concatenate
482  /// distributions.
483  void split_without_communication(const DoubleVector &in_vector,
484  Vector<DoubleVector*> &out_vector_pt);
485 
486  /// \short Wrapper around the other split_without_communication(...)
487  /// function.
488  /// Be careful with Vector of vectors. If the DoubleVectors are resized,
489  /// there could be reallocation of memory. If we wanted to use the function
490  /// which takes a Vector of pointers to DoubleVectors, we would either have
491  /// to invoke new and remember to delete, or create a temporary Vector to
492  /// store pointers to the DoubleVector objects.
493  /// This wrapper is meant to make life easier for the user by avoiding calls
494  /// to new/delete AND without creating a temporary vector of pointers to
495  /// DoubleVectors.
496  /// If we had C++ 11, this would be so much nicer since we can use smart
497  /// pointers which will delete themselves, so we do not have to remember
498  /// to delete!
499  void split_without_communication(const DoubleVector &in_vector,
500  Vector<DoubleVector> &out_vector);
501 
502 } // end of DoubleVectorHelpers namespace
503 
504 } // end of oomph namespace
505 #endif
double * values_pt() const
access function to the underlying values (const version)
void clear()
wipes the DoubleVector
void redistribute(const LinearAlgebraDistribution *const &dist_pt)
The contents of the vector are redistributed to match the new distribution. In a non-MPI rebuild this...
DoubleVector()
Constructor for an uninitialized DoubleVector.
Definition: double_vector.h:67
bool operator==(const DoubleVector &v)
== operator
double * values_pt()
access function to the underlying values
cstr elem_len * i
Definition: cfortran.h:607
DoubleVector(const DoubleVector &new_vector)
Copy constructor.
Definition: double_vector.h:98
void output_local_values(std::ostream &outfile, const int &output_precision=-1) const
output the local contents of the vector
DoubleVector(const LinearAlgebraDistribution *const &dist_pt, const double &v=0.0)
Constructor. Assembles a DoubleVector with a prescribed distribution. Additionally every entry can be...
Definition: double_vector.h:74
double & operator[](int i)
[] access function to the (local) values of this vector
void split_without_communication(const DoubleVector &in_vector, Vector< DoubleVector *> &out_vector_pt)
Split a DoubleVector into the out DoubleVectors. Data stays on its current processor, no data is sent between processors. This results in our vectors which are a permutation of the in vector.
~DoubleVector()
Destructor - just calls this->clear() to delete the distribution and data.
Definition: double_vector.h:92
void operator=(const DoubleVector &old_vector)
assignment operator
void build(const LinearAlgebraDistribution &dist, const double &v)
Assembles a DoubleVector with distribution dist, if v is specified each element is set to v...
DoubleVector(const LinearAlgebraDistribution &dist, const double &v=0.0)
Constructor. Assembles a DoubleVector with a prescribed distribution. Additionally every entry can be...
Definition: double_vector.h:84
friend std::ostream & operator<<(std::ostream &out, const DoubleVector &v)
Ouput operator for DoubleVector.
void set_external_values(double *external_values, bool delete_external_values)
Allows are external data to be used by this vector. WARNING: The size of the external data must corre...
void concatenate_without_communication(const Vector< DoubleVector *> &in_vector_pt, DoubleVector &out_vector)
Concatenate DoubleVectors. Takes a Vector of DoubleVectors. If the out vector is built, we will not build a new distribution. Otherwise a new distribution will be built using LinearAlgebraDistribution::concatenate(...).
bool built() const
bool Internal_values
Boolean flag to indicate whether the vector&#39;s data (values_pt) is owned by this vector.
void operator-=(const DoubleVector &v)
-= operator with another vector
void operator/=(const double &d)
divide by a double
void operator+=(const DoubleVector &v)
+= operator with another vector
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
Base class for any linear algebra object that is distributable. Just contains storage for the LinearA...
double * Values_pt
the local vector
void initialise(const double &v)
initialise the whole vector with value v
void build(const LinearAlgebraDistribution &dist, const Vector< double > &v)
Assembles a DoubleVector with a distribution dist and coefficients taken from the vector v...
void clear_distribution()
clear the distribution of this distributable linear algebra object
bool Built
indicates that the vector has been built and is usable
void output_local_values_with_offset(std::string filename, const int &output_precision=-1) const
output the local contents of the vector
void set_external_values(const LinearAlgebraDistribution *const &dist_pt, double *external_values, bool delete_external_values)
Allows are external data to be used by this vector. WARNING: The size of the external data must corre...
double dot(const DoubleVector &vec) const
compute the dot product of this vector with the vector vec.
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn&#39;t been defined.
void output(std::string filename, const int &output_precision=-1) const
output the global contents of the vector
void output_local_values_with_offset(std::ostream &outfile, const int &output_precision=-1) const
output the local contents of the vector
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
setup the distribution of this distributable linear algebra object
void operator*=(const double &d)
multiply by a double
void concatenate(const Vector< DoubleVector *> &in_vector_pt, DoubleVector &out_vector)
Concatenate DoubleVectors. Takes a Vector of DoubleVectors. If the out vector is built, we will not build a new distribution. Otherwise we build a uniform distribution.
A vector in the mathematical sense, initially developed for linear algebra type applications. If MPI then this vector can be distributed - its distribution is described by the LinearAlgebraDistribution object at Distribution_pt. Data is stored in a C-style pointer vector (double*)
Definition: double_vector.h:61
double norm() const
compute the 2 norm of this vector
A class for compressed row matrices. This is a distributable object.
Definition: matrices.h:872
void output(std::ostream &outfile, const int &output_precision=-1) const
output the global contents of the vector
void split(const DoubleVector &in_vector, Vector< DoubleVector *> &out_vector_pt)
Split a DoubleVector into the out DoubleVectors. Let vec_A be the in Vector, and let vec_B and vec_C ...
void output_local_values(std::string filename, const int &output_precision=-1) const
output the local contents of the vector
double max() const
returns the maximum coefficient