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