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-2022 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
46namespace 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
62
63 /// Constructor. Assembles a DoubleVector with a prescribed
64 /// distribution. Additionally every entry can be set (with argument v -
65 /// defaults to 0).
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()
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.
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
double * values_pt() const
access function to the underlying values (const version)
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....
DoubleVector()
Constructor for an uninitialized DoubleVector.
Definition: double_vector.h:61
void build(const DoubleVector &old_vector)
Just copys the argument 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...
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
friend std::ostream & operator<<(std::ostream &out, const DoubleVector &v)
Ouput operator for DoubleVector.
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
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,...
double * values_pt()
access function to the underlying values
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.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...