oomph::DoubleMultiVector Class Reference

#include <double_multi_vector.h>

+ Inheritance diagram for oomph::DoubleMultiVector:

Public Member Functions

 DoubleMultiVector ()
 Constructor for an uninitialized DoubleMultiVector. More...
 
 DoubleMultiVector (const unsigned &n_vector, const LinearAlgebraDistribution *const &dist_pt, const double &v=0.0)
 
 DoubleMultiVector (const unsigned &n_vector, const LinearAlgebraDistribution &dist, const double &v=0.0)
 
 DoubleMultiVector (const unsigned &n_vector, const DoubleMultiVector &old_vector, const double &initial_value=0.0)
 
 DoubleMultiVector (const DoubleMultiVector &old_vector, const std::vector< int > &index, const bool &deep_copy=true)
 
 DoubleMultiVector (const DoubleMultiVector &new_vector)
 Copy constructor. More...
 
 ~DoubleMultiVector ()
 
void operator= (const DoubleMultiVector &old_vector)
 assignment operator (deep copy) More...
 
unsigned nvector () const
 Return the number of vectors. More...
 
void shallow_build (const DoubleMultiVector &old_vector)
 Provide a (shallow) copy of the old vector. More...
 
void shallow_build (const unsigned &n_vector, const LinearAlgebraDistribution &dist)
 
void shallow_build (const unsigned &n_vector, const LinearAlgebraDistribution *const &dist_pt)
 
void build (const DoubleMultiVector &old_vector)
 Provides a (deep) copy of the old_vector. More...
 
void build (const unsigned &n_vector, const LinearAlgebraDistribution &dist, const double &initial_value=0.0)
 
void build (const unsigned &n_vector, const LinearAlgebraDistribution *const &dist_pt, const double &initial_value=0.0)
 
void initialise (const double &initial_value)
 initialise the whole vector with value v More...
 
void clear ()
 wipes the DoubleVector More...
 
bool built () const
 
void redistribute (const LinearAlgebraDistribution *const &dist_pt)
 
doubleoperator() (int v, int i) const
 [] access function to the (local) values of the v-th vector More...
 
bool operator== (const DoubleMultiVector &vec)
 == operator More...
 
void operator+= (DoubleMultiVector vec)
 += operator More...
 
void operator-= (DoubleMultiVector vec)
 -= operator More...
 
void operator*= (const double &scalar_value)
 Multiply by a scalar. More...
 
double ** values ()
 access function to the underlying values More...
 
double ** values () const
 access function to the underlying values (const version) More...
 
doublevalues (const unsigned &i)
 access function to the i-th vector's data More...
 
doublevalues (const unsigned &i) const
 access function to the i-th vector's data (const version) More...
 
DoubleVectordoublevector (const unsigned &i)
 access to the DoubleVector representatoin More...
 
const DoubleVectordoublevector (const unsigned &i) const
 access to the DoubleVector representation (const version) More...
 
void output (std::ostream &outfile) const
 output the contents of the vector More...
 
void output (std::string filename)
 output the contents of the vector More...
 
void dot (const DoubleMultiVector &vec, std::vector< double > &result) const
 compute the 2 norm of this vector More...
 
void norm (std::vector< double > &result) const
 compute the 2 norm of this vector More...
 
- Public Member Functions inherited from oomph::DistributableLinearAlgebraObject
 DistributableLinearAlgebraObject ()
 Default constructor - create a distribution. More...
 
 DistributableLinearAlgebraObject (const DistributableLinearAlgebraObject &matrix)=delete
 Broken copy constructor. More...
 
void operator= (const DistributableLinearAlgebraObject &)=delete
 Broken assignment operator. More...
 
virtual ~DistributableLinearAlgebraObject ()
 Destructor. More...
 
LinearAlgebraDistributiondistribution_pt () const
 access to the LinearAlgebraDistribution More...
 
unsigned nrow () const
 access function to the number of global rows. More...
 
unsigned nrow_local () const
 access function for the num of local rows on this processor. More...
 
unsigned nrow_local (const unsigned &p) const
 access function for the num of local rows on this processor. More...
 
unsigned first_row () const
 access function for the first row on this processor More...
 
unsigned first_row (const unsigned &p) const
 access function for the first row on this processor More...
 
bool distributed () const
 distribution is serial or distributed More...
 
bool distribution_built () const
 
void build_distribution (const LinearAlgebraDistribution *const dist_pt)
 
void build_distribution (const LinearAlgebraDistribution &dist)
 

Private Member Functions

void setup_doublevector_representation ()
 compute the A-norm using the matrix at matrix_pt More...
 

Private Attributes

double ** Values
 
unsigned Nvector
 The number of vectors. More...
 
bool Internal_values
 
bool Built
 indicates that the vector has been built and is usable More...
 
Vector< DoubleVectorInternal_doublevector
 Need a vector of DoubleVectors to interface with our linear solvers. More...
 

Additional Inherited Members

- Protected Member Functions inherited from oomph::DistributableLinearAlgebraObject
void clear_distribution ()
 

Detailed Description

A multi vector in the mathematical sense, initially developed for linear algebra type applications. If MPI then this multi 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*)

Constructor & Destructor Documentation

◆ DoubleMultiVector() [1/6]

oomph::DoubleMultiVector::DoubleMultiVector ( )
inline

Constructor for an uninitialized DoubleMultiVector.

60  : Values(0), Nvector(0), Internal_values(true), Built(false)
61  {
62  }
unsigned Nvector
The number of vectors.
Definition: double_multi_vector.h:1005
double ** Values
Definition: double_multi_vector.h:1002
bool Built
indicates that the vector has been built and is usable
Definition: double_multi_vector.h:1012
bool Internal_values
Definition: double_multi_vector.h:1009

◆ DoubleMultiVector() [2/6]

oomph::DoubleMultiVector::DoubleMultiVector ( const unsigned n_vector,
const LinearAlgebraDistribution *const &  dist_pt,
const double v = 0.0 
)
inline

Constructor. Assembles a DoubleMultiVector consisting of n_vector vectors, each with a prescribed distribution. Additionally every entry can be set (with argument v - defaults to 0).

71  : Values(0), Nvector(n_vector), Internal_values(true), Built(false)
72  {
73  this->build(n_vector, dist_pt, v);
75  }
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
void setup_doublevector_representation()
compute the A-norm using the matrix at matrix_pt
Definition: double_multi_vector.h:988
void build(const DoubleMultiVector &old_vector)
Provides a (deep) copy of the old_vector.
Definition: double_multi_vector.h:281

References build(), setup_doublevector_representation(), and v.

◆ DoubleMultiVector() [3/6]

oomph::DoubleMultiVector::DoubleMultiVector ( const unsigned n_vector,
const LinearAlgebraDistribution dist,
const double v = 0.0 
)
inline

Constructor. Assembles a DoubleMultiVector consisting of n_vector vectors, each with a prescribed distribution. Additionally every entry can be set (with argument v - defaults to 0).

84  : Values(0), Nvector(n_vector), Internal_values(true), Built(false)
85  {
86  this->build(n_vector, dist, v);
88  }

References build(), setup_doublevector_representation(), and v.

◆ DoubleMultiVector() [4/6]

oomph::DoubleMultiVector::DoubleMultiVector ( const unsigned n_vector,
const DoubleMultiVector old_vector,
const double initial_value = 0.0 
)
inline

Constructor. Build a multivector using the same distribution of the input vector with n_vector columns and initialised to the value v

96  : Values(0), Nvector(n_vector), Internal_values(true), Built(false)
97  {
98  this->build(n_vector, old_vector.distribution_pt(), initial_value);
100  }

References build(), oomph::DistributableLinearAlgebraObject::distribution_pt(), and setup_doublevector_representation().

◆ DoubleMultiVector() [5/6]

oomph::DoubleMultiVector::DoubleMultiVector ( const DoubleMultiVector old_vector,
const std::vector< int > &  index,
const bool deep_copy = true 
)
inline

Constructor that builds a multivector from selected columns of the input multivector. The boolean controls whether it is a shallow or deep copy (default deep)

108  : Values(0), Nvector(0), Internal_values(deep_copy), Built(false)
109  {
110  // Build the storage based on the size of index
111  unsigned n_vector = index.size();
112  if (deep_copy)
113  {
114  // Create an entirely new data structure
115  this->build(n_vector, old_vector.distribution_pt());
116  // Now (deep) copy the data across
117  const unsigned n_row_local = this->nrow_local();
118  for (unsigned v = 0; v < n_vector; v++)
119  {
120  for (unsigned i = 0; i < n_row_local; i++)
121  {
122  Values[v][i] = old_vector(index[v], i);
123  }
124  }
125  }
126  // Otherwise it's a shallow copy
127  else
128  {
129  this->shallow_build(n_vector, old_vector.distribution_pt());
130  // Now shallow copy the pointers accross
131  for (unsigned v = 0; v < n_vector; ++v)
132  {
133  Values[v] = old_vector.values(index[v]);
134  }
135  }
137  }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
unsigned nrow_local() const
access function for the num of local rows on this processor.
Definition: linear_algebra_distribution.h:469
void shallow_build(const DoubleMultiVector &old_vector)
Provide a (shallow) copy of the old vector.
Definition: double_multi_vector.h:217
void deep_copy(const CRDoubleMatrix *const in_matrix_pt, CRDoubleMatrix &out_matrix)
Create a deep copy of the matrix pointed to by in_matrix_pt.
Definition: matrices.h:3490
std::vector< float > Values
Definition: sparse_setter.cpp:48

References build(), oomph::CRDoubleMatrixHelpers::deep_copy(), oomph::DistributableLinearAlgebraObject::distribution_pt(), i, oomph::DistributableLinearAlgebraObject::nrow_local(), setup_doublevector_representation(), shallow_build(), v, and values().

◆ DoubleMultiVector() [6/6]

oomph::DoubleMultiVector::DoubleMultiVector ( const DoubleMultiVector new_vector)
inline

Copy constructor.

186  Values(0),
187  Nvector(0),
188  Internal_values(true),
189  Built(false)
190  {
191  this->build(new_vector);
193  }
DistributableLinearAlgebraObject()
Default constructor - create a distribution.
Definition: linear_algebra_distribution.h:438

References build(), and setup_doublevector_representation().

◆ ~DoubleMultiVector()

oomph::DoubleMultiVector::~DoubleMultiVector ( )
inline

Destructor - just calls this->clear() to delete the distribution and data

199  {
200  this->clear();
201  }
void clear()
wipes the DoubleVector
Definition: double_multi_vector.h:387

References clear().

Member Function Documentation

◆ build() [1/3]

void oomph::DoubleMultiVector::build ( const DoubleMultiVector old_vector)
inline

Provides a (deep) copy of the old_vector.

282  {
283  // Only bother if the old_vector is not the same as current vector
284  if (!(*this == old_vector))
285  {
286  // the vector owns the internal data
287  Internal_values = true;
288 
289  // Copy the number of vectors
290  Nvector = old_vector.nvector();
291  // reset the distribution and resize the data
292  this->build(Nvector, old_vector.distribution_pt(), 0.0);
293 
294  // copy the data
295  if (this->distribution_built())
296  {
297  unsigned n_row_local = this->nrow_local();
298  double** const old_vector_values = old_vector.values();
299  for (unsigned i = 0; i < n_row_local; i++)
300  {
301  for (unsigned v = 0; v < Nvector; v++)
302  {
303  Values[v][i] = old_vector_values[v][i];
304  }
305  }
306  }
307  }
308  }
bool distribution_built() const
Definition: linear_algebra_distribution.h:500

References oomph::DistributableLinearAlgebraObject::distribution_built(), oomph::DistributableLinearAlgebraObject::distribution_pt(), i, Internal_values, oomph::DistributableLinearAlgebraObject::nrow_local(), nvector(), Nvector, v, and values().

Referenced by build(), DoubleMultiVector(), and operator=().

◆ build() [2/3]

void oomph::DoubleMultiVector::build ( const unsigned n_vector,
const LinearAlgebraDistribution dist,
const double initial_value = 0.0 
)
inline

Assembles a DoubleMultiVector with n_vector vectors, a distribution dist, if v is specified each element is set to v, otherwise each element is set to 0.0

316  {
317  this->build(n_vector, &dist, initial_value);
318  }

References build().

◆ build() [3/3]

void oomph::DoubleMultiVector::build ( const unsigned n_vector,
const LinearAlgebraDistribution *const &  dist_pt,
const double initial_value = 0.0 
)
inline

Assembles a DoubleMultiVector with n_vector vectors, each with a distribution dist, if v is specified each element is set to v, otherwise each element is set to 0.0

326  {
327  // clean the memory
328  this->clear();
329 
330  // the vector owns the internal data
331  Internal_values = true;
332 
333  // Set the distribution
334  this->build_distribution(dist_pt);
335 
336  // update the values
337  if (dist_pt->built())
338  {
339  // Set the number of vectors
340  Nvector = n_vector;
341  // Build the array of pointers to each vector's data
342  Values = new double*[n_vector];
343  // Now build the contiguous array of real data
344  const unsigned n_row_local = this->nrow_local();
345  double* values = new double[n_row_local * n_vector];
346  // set the data
347  for (unsigned v = 0; v < n_vector; v++)
348  {
349  Values[v] = &values[v * n_row_local];
350  for (unsigned i = 0; i < n_row_local; i++)
351  {
352  Values[v][i] = initial_value;
353  }
354  }
355  Built = true;
356  }
357  else
358  {
359  Built = false;
360  }
361  }
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
Definition: linear_algebra_distribution.h:507
double ** values()
access function to the underlying values
Definition: double_multi_vector.h:668

References oomph::DistributableLinearAlgebraObject::build_distribution(), Built, oomph::LinearAlgebraDistribution::built(), clear(), i, Internal_values, oomph::DistributableLinearAlgebraObject::nrow_local(), Nvector, v, and values().

◆ built()

bool oomph::DoubleMultiVector::built ( ) const
inline
414  {
415  return Built;
416  }

References Built.

Referenced by dot(), norm(), operator+=(), operator-=(), and operator==().

◆ clear()

void oomph::DoubleMultiVector::clear ( )
inline

wipes the DoubleVector

initialise the vector with coefficient from the vector v. Note: The vector v must be of length

388  {
389  // Return if nothing to do
390  if (Values == 0)
391  {
392  return;
393  }
394 
395  // If we are in charge of the data then delete it
396  if (Internal_values)
397  {
398  // Delete the double storage arrays at once
399  //(they were allocated as a contiguous block)
400  delete[] Values[0];
401  }
402 
403  // Always Delete the pointers to the arrays
404  delete[] Values;
405 
406  // Then set the pointer (to a pointer) to null
407  Values = 0;
408  this->clear_distribution();
409  Built = false;
410  }
void clear_distribution()
Definition: linear_algebra_distribution.h:522

References Built, oomph::DistributableLinearAlgebraObject::clear_distribution(), Internal_values, and Values.

Referenced by build(), shallow_build(), and ~DoubleMultiVector().

◆ dot()

void oomph::DoubleMultiVector::dot ( const DoubleMultiVector vec,
std::vector< double > &  result 
) const
inline

compute the 2 norm of this vector

810  {
811 #ifdef PARANOID
812  // paranoid check that the vector is setup
813  if (!this->built())
814  {
815  std::ostringstream error_message;
816  error_message << "This vector must be setup.";
817  throw OomphLibError(error_message.str(),
820  }
821  if (!vec.built())
822  {
823  std::ostringstream error_message;
824  error_message << "The input vector be setup.";
825  throw OomphLibError(error_message.str(),
828  }
829  if (*this->distribution_pt() != *vec.distribution_pt())
830  {
831  std::ostringstream error_message;
832  error_message << "The distribution of this vector and the vector vec "
833  << "must be the same."
834  << "\n\n this: " << *this->distribution_pt()
835  << "\n vec: " << *vec.distribution_pt();
836  throw OomphLibError(error_message.str(),
839  }
840 #endif
841 
842  // compute the local norm
843  unsigned nrow_local = this->nrow_local();
844  int n_vector = this->nvector();
845  double n[n_vector];
846  for (int v = 0; v < n_vector; v++)
847  {
848  // Initialise
849  n[v] = 0.0;
850  const double* vec_values_pt = vec.values(v);
851  for (unsigned i = 0; i < nrow_local; i++)
852  {
853  n[v] += Values[v][i] * vec_values_pt[i];
854  }
855  }
856 
857  // if this vector is distributed and on multiple processors then gather
858 #ifdef OOMPH_HAS_MPI
859  double n2[n_vector];
860  for (int v = 0; v < n_vector; v++)
861  {
862  n2[v] = n[v];
863  }
864 
865  if (this->distributed() &&
866  this->distribution_pt()->communicator_pt()->nproc() > 1)
867  {
868  MPI_Allreduce(&n,
869  &n2,
870  n_vector,
871  MPI_DOUBLE,
872  MPI_SUM,
873  this->distribution_pt()->communicator_pt()->mpi_comm());
874  }
875  for (int v = 0; v < n_vector; v++)
876  {
877  n[v] = n2[v];
878  }
879 #endif
880 
881  result.resize(n_vector);
882  for (int v = 0; v < n_vector; v++)
883  {
884  result[v] = n[v];
885  }
886  }
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
bool distributed() const
distribution is serial or distributed
Definition: linear_algebra_distribution.h:493
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
Definition: linear_algebra_distribution.h:457
bool built() const
Definition: double_multi_vector.h:413
unsigned nvector() const
Return the number of vectors.
Definition: double_multi_vector.h:211
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86

References built(), oomph::DistributableLinearAlgebraObject::distributed(), oomph::DistributableLinearAlgebraObject::distribution_pt(), i, n, oomph::DistributableLinearAlgebraObject::nrow_local(), nvector(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, v, and values().

Referenced by Anasazi::MultiVecTraits< double, oomph::DoubleMultiVector >::MvDot().

◆ doublevector() [1/2]

DoubleVector& oomph::DoubleMultiVector::doublevector ( const unsigned i)
inline

access to the DoubleVector representatoin

693  {
694  return Internal_doublevector[i];
695  }
Vector< DoubleVector > Internal_doublevector
Need a vector of DoubleVectors to interface with our linear solvers.
Definition: double_multi_vector.h:1015

References i, and Internal_doublevector.

◆ doublevector() [2/2]

const DoubleVector& oomph::DoubleMultiVector::doublevector ( const unsigned i) const
inline

access to the DoubleVector representation (const version)

699  {
700  return Internal_doublevector[i];
701  }

References i, and Internal_doublevector.

◆ initialise()

void oomph::DoubleMultiVector::initialise ( const double initial_value)
inline

initialise the whole vector with value v

365  {
366  if (Built)
367  {
368  const unsigned n_vector = this->Nvector;
369  const unsigned n_row_local = this->nrow_local();
370 
371  // set the residuals
372  for (unsigned v = 0; v < n_vector; v++)
373  {
374  for (unsigned i = 0; i < n_row_local; i++)
375  {
376  Values[v][i] = initial_value;
377  }
378  }
379  }
380  }

References Built, i, oomph::DistributableLinearAlgebraObject::nrow_local(), Nvector, and v.

Referenced by Anasazi::MultiVecTraits< double, oomph::DoubleMultiVector >::MvInit().

◆ norm()

void oomph::DoubleMultiVector::norm ( std::vector< double > &  result) const
inline

compute the 2 norm of this vector

890  {
891 #ifdef PARANOID
892  // paranoid check that the vector is setup
893  if (!this->built())
894  {
895  std::ostringstream error_message;
896  error_message << "This vector must be setup.";
897  throw OomphLibError(error_message.str(),
900  }
901 #endif
902 
903  // compute the local norm
904  unsigned nrow_local = this->nrow_local();
905  int n_vector = this->nvector();
906  double n[n_vector];
907  for (int v = 0; v < n_vector; v++)
908  {
909  n[v] = 0.0;
910  for (unsigned i = 0; i < nrow_local; i++)
911  {
912  n[v] += Values[v][i] * Values[v][i];
913  }
914  }
915 
916  // if this vector is distributed and on multiple processors then gather
917 #ifdef OOMPH_HAS_MPI
918  double n2[n_vector];
919  for (int v = 0; v < n_vector; v++)
920  {
921  n2[v] = n[v];
922  }
923  if (this->distributed() &&
924  this->distribution_pt()->communicator_pt()->nproc() > 1)
925  {
926  MPI_Allreduce(&n,
927  &n2,
928  n_vector,
929  MPI_DOUBLE,
930  MPI_SUM,
931  this->distribution_pt()->communicator_pt()->mpi_comm());
932  }
933  for (int v = 0; v < n_vector; v++)
934  {
935  n[v] = n2[v];
936  }
937 #endif
938 
939  // Now sqrt the norm and fill in result
940  result.resize(n_vector);
941  for (int v = 0; v < n_vector; v++)
942  {
943  result[v] = sqrt(n[v]);
944  }
945  }
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134

References built(), oomph::DistributableLinearAlgebraObject::distributed(), oomph::DistributableLinearAlgebraObject::distribution_pt(), i, n, oomph::DistributableLinearAlgebraObject::nrow_local(), nvector(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, sqrt(), and v.

Referenced by Anasazi::MultiVecTraits< double, oomph::DoubleMultiVector >::MvNorm().

◆ nvector()

◆ operator()()

double& oomph::DoubleMultiVector::operator() ( int  v,
int  i 
) const
inline

[] access function to the (local) values of the v-th vector

485  {
486 #ifdef RANGE_CHECKING
487  std::ostringstream error_message;
488  bool error = false;
489  if (v > int(Nvector))
490  {
491  error_message << "Range Error: Vector " << v
492  << "is not in the range (0," << Nvector - 1 << ")";
493  error = true;
494  }
495 
496  if (i >= int(this->nrow_local()))
497  {
498  error_message << "Range Error: " << i << " is not in the range (0,"
499  << this->nrow_local() - 1 << ")";
500  error = true;
501  }
502 
503  if (error)
504  {
505  throw OomphLibError(error_message.str(),
508  }
509 #endif
510  return Values[v][i];
511  }
int error
Definition: calibrate.py:297

References calibrate::error, i, oomph::DistributableLinearAlgebraObject::nrow_local(), Nvector, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, and v.

◆ operator*=()

void oomph::DoubleMultiVector::operator*= ( const double scalar_value)
inline

Multiply by a scalar.

643  {
644 #ifdef PARANOID
645  // PARANOID check that this vector is setup
646  if (!this->distribution_built())
647  {
648  std::ostringstream error_message;
649  error_message << "This vector must be setup.";
650  throw OomphLibError(error_message.str(),
653  }
654 #endif
655  const unsigned n_vector = this->nvector();
656  const unsigned n_row_local = this->nrow_local();
657  for (unsigned v = 0; v < n_vector; ++v)
658  {
659  for (unsigned i = 0; i < n_row_local; ++i)
660  {
661  Values[v][i] *= scalar_value;
662  }
663  }
664  }

References oomph::DistributableLinearAlgebraObject::distribution_built(), i, oomph::DistributableLinearAlgebraObject::nrow_local(), nvector(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, and v.

◆ operator+=()

void oomph::DoubleMultiVector::operator+= ( DoubleMultiVector  vec)
inline

+= operator

550  {
551 #ifdef PARANOID
552  // PARANOID check that this vector is setup
553  if (!this->built())
554  {
555  std::ostringstream error_message;
556  error_message << "This vector must be setup.";
557  throw OomphLibError(error_message.str(),
560  }
561  // PARANOID check that the vector v is setup
562  if (!vec.built())
563  {
564  std::ostringstream error_message;
565  error_message << "The vector v must be setup.";
566  throw OomphLibError(error_message.str(),
569  }
570  // PARANOID check that the vectors have the same distribution
571  if (!(*vec.distribution_pt() == *this->distribution_pt()))
572  {
573  std::ostringstream error_message;
574  error_message << "The vector v and this vector must have the same "
575  << "distribution.";
576  throw OomphLibError(error_message.str(),
579  }
580 #endif //
581 
582 
583  double** v_values = vec.values();
584  const unsigned n_vector = this->nvector();
585  const unsigned n_row_local = this->nrow_local();
586  for (unsigned v = 0; v < n_vector; ++v)
587  {
588  for (unsigned i = 0; i < n_row_local; ++i)
589  {
590  Values[v][i] += v_values[v][i];
591  }
592  }
593  }

References built(), oomph::DistributableLinearAlgebraObject::distribution_pt(), i, oomph::DistributableLinearAlgebraObject::nrow_local(), nvector(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, v, and values().

◆ operator-=()

void oomph::DoubleMultiVector::operator-= ( DoubleMultiVector  vec)
inline

-= operator

597  {
598 #ifdef PARANOID
599  // PARANOID check that this vector is setup
600  if (!this->distribution_built())
601  {
602  std::ostringstream error_message;
603  error_message << "This vector must be setup.";
604  throw OomphLibError(error_message.str(),
607  }
608  // PARANOID check that the vector v is setup
609  if (!vec.built())
610  {
611  std::ostringstream error_message;
612  error_message << "The vector v must be setup.";
613  throw OomphLibError(error_message.str(),
616  }
617  // PARANOID check that the vectors have the same distribution
618  if (!(*vec.distribution_pt() == *this->distribution_pt()))
619  {
620  std::ostringstream error_message;
621  error_message << "The vector v and this vector must have the same "
622  << "distribution.";
623  throw OomphLibError(error_message.str(),
626  }
627 #endif
628 
629  double** v_values = vec.values();
630  const unsigned n_vector = this->nvector();
631  const unsigned n_row_local = this->nrow_local();
632  for (unsigned v = 0; v < n_vector; ++v)
633  {
634  for (unsigned i = 0; i < n_row_local; ++i)
635  {
636  Values[v][i] -= v_values[v][i];
637  }
638  }
639  }

References built(), oomph::DistributableLinearAlgebraObject::distribution_built(), oomph::DistributableLinearAlgebraObject::distribution_pt(), i, oomph::DistributableLinearAlgebraObject::nrow_local(), nvector(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, v, and values().

◆ operator=()

void oomph::DoubleMultiVector::operator= ( const DoubleMultiVector old_vector)
inline

assignment operator (deep copy)

205  {
206  this->build(old_vector);
208  }

References build(), and setup_doublevector_representation().

◆ operator==()

bool oomph::DoubleMultiVector::operator== ( const DoubleMultiVector vec)
inline

== operator

515  {
516  // if vec is not setup return false
517  if (vec.built() && !this->built())
518  {
519  return false;
520  }
521  else if (!vec.built() && this->built())
522  {
523  return false;
524  }
525  else if (!vec.built() && !this->built())
526  {
527  return true;
528  }
529  else
530  {
531  double** const v_values = vec.values();
532  const unsigned n_row_local = this->nrow_local();
533  const unsigned n_vector = this->nvector();
534  for (unsigned v = 0; v < n_vector; ++v)
535  {
536  for (unsigned i = 0; i < n_row_local; ++i)
537  {
538  if (Values[v][i] != v_values[v][i])
539  {
540  return false;
541  }
542  }
543  }
544  return true;
545  }
546  }

References built(), i, oomph::DistributableLinearAlgebraObject::nrow_local(), nvector(), v, and values().

◆ output() [1/2]

void oomph::DoubleMultiVector::output ( std::ostream &  outfile) const
inline

output the contents of the vector

705  {
706  // temp pointer to values
707  double** temp;
708 
709  // Number of vectors
710  unsigned n_vector = this->nvector();
711 
712  // number of global row
713  unsigned nrow = this->nrow();
714 
715 #ifdef OOMPH_HAS_MPI
716 
717  // number of local rows
718  int nrow_local = this->nrow_local();
719 
720  // gather from all processors
721  if (this->distributed() &&
722  this->distribution_pt()->communicator_pt()->nproc() > 1)
723  {
724  // number of processors
725  int nproc = this->distribution_pt()->communicator_pt()->nproc();
726 
727  // number of gobal row
728  unsigned nrow = this->nrow();
729 
730  // get the vector of first_row s and nrow_local s
731  int* dist_first_row = new int[nproc];
732  int* dist_nrow_local = new int[nproc];
733  for (int p = 0; p < nproc; p++)
734  {
735  dist_first_row[p] = this->first_row(p);
736  dist_nrow_local[p] = this->nrow_local(p);
737  }
738 
739  // gather
740  temp = new double*[n_vector];
741  double* temp_value = new double[nrow * n_vector];
742  for (unsigned v = 0; v < n_vector; v++)
743  {
744  temp[v] = &temp_value[v * nrow];
745  }
746 
747  // Now do an all gather for each vector
748  // Possibly costly in terms of extra communication, but it's only
749  // output!
750  for (unsigned v = 0; v < n_vector; ++v)
751  {
752  MPI_Allgatherv(
753  Values[v],
754  nrow_local,
755  MPI_DOUBLE,
756  temp[v],
757  dist_nrow_local,
758  dist_first_row,
759  MPI_DOUBLE,
760  this->distribution_pt()->communicator_pt()->mpi_comm());
761  }
762 
763  // clean up
764  delete[] dist_first_row;
765  delete[] dist_nrow_local;
766  }
767  else
768  {
769  temp = Values;
770  }
771 #else
772  temp = Values;
773 #endif
774 
775  // output
776  for (unsigned i = 0; i < nrow; i++)
777  {
778  outfile << i << " ";
779  for (unsigned v = 0; v < n_vector; v++)
780  {
781  outfile << temp[v][i] << " ";
782  }
783  outfile << "\n";
784  }
785 
786  // clean up if required
787 #ifdef OOMPH_HAS_MPI
788  if (this->distributed() &&
789  this->distribution_pt()->communicator_pt()->nproc() > 1)
790  {
791  delete[] temp[0];
792  delete[] temp;
793  }
794 #endif
795  }
float * p
Definition: Tutorial_Map_using.cpp:9
unsigned nrow() const
access function to the number of global rows.
Definition: linear_algebra_distribution.h:463
unsigned first_row() const
access function for the first row on this processor
Definition: linear_algebra_distribution.h:481
OomphCommunicator * communicator_pt() const
const access to the communicator pointer
Definition: linear_algebra_distribution.h:335
int nproc() const
number of processors
Definition: communicator.h:157

References oomph::LinearAlgebraDistribution::communicator_pt(), oomph::DistributableLinearAlgebraObject::distributed(), oomph::DistributableLinearAlgebraObject::distribution_pt(), oomph::DistributableLinearAlgebraObject::first_row(), i, oomph::OomphCommunicator::nproc(), oomph::DistributableLinearAlgebraObject::nrow(), oomph::DistributableLinearAlgebraObject::nrow_local(), nvector(), p, v, and Values.

Referenced by Anasazi::MultiVecTraits< double, oomph::DoubleMultiVector >::MvPrint(), and output().

◆ output() [2/2]

void oomph::DoubleMultiVector::output ( std::string  filename)
inline

output the contents of the vector

799  {
800  // Open file
801  std::ofstream some_file;
802  some_file.open(filename.c_str());
803  output(some_file);
804  some_file.close();
805  }
void output(std::ostream &outfile) const
output the contents of the vector
Definition: double_multi_vector.h:704
string filename
Definition: MergeRestartFiles.py:39

References MergeRestartFiles::filename, and output().

◆ redistribute()

void oomph::DoubleMultiVector::redistribute ( const LinearAlgebraDistribution *const &  dist_pt)

Allows are external data to be used by this vector. WARNING: The size of the external data must correspond to the LinearAlgebraDistribution dist_pt argument.

  1. When a rebuild method is called new internal values are created.
  2. It is not possible to redistribute(...) a vector with external values .
  3. External values are only deleted by this vector if delete_external_values = true. Allows are external data to be used by this vector. WARNING: The size of the external data must correspond to the distribution of this vector.
  1. When a rebuild method is called new internal values are created.
  2. It is not possible to redistribute(...) a vector with external values .
  3. External values are only deleted by this vector if delete_external_values = true. The contents of the vector are redistributed to match the new distribution. In a non-MPI rebuild this method works, but does nothing. NOTE 1: The current distribution and the new distribution must have the same number of global rows. NOTE 2: The current distribution and the new distribution must have the same Communicator.

The contents of the vector are redistributed to match the new distribution. In a non-MPI rebuild this method works, but does nothing. NOTE 1: The current distribution and the new distribution must have the same number of global rows. NOTE 2: The current distribution and the new distribution must have the same Communicator.

39  {
40 #ifdef OOMPH_HAS_MPI
41 #ifdef PARANOID
42  if (!Internal_values)
43  {
44  // if this vector does not own the double* values then it cannot be
45  // distributed.
46  // note: this is not stictly necessary - would just need to be careful
47  // with delete[] below.
48  std::ostringstream error_message;
49  error_message
50  << "This multi vector does not own its data (i.e. data has been "
51  << "passed in via set_external_values() and therefore "
52  << "cannot be redistributed";
53  throw OomphLibError(
54  error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
55  }
56  // paranoid check that the nrows for both distributions is the
57  // same
58  if (dist_pt->nrow() != this->nrow())
59  {
60  std::ostringstream error_message;
61  error_message << "The number of global rows in the new distribution ("
62  << dist_pt->nrow() << ") is not equal to the number"
63  << " of global rows in the current distribution ("
64  << this->nrow() << ").\n";
65  throw OomphLibError(
66  error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
67  }
68  // paranoid check that the current distribution and the new distribution
69  // have the same Communicator
70  OomphCommunicator temp_comm(*dist_pt->communicator_pt());
71  if (!(temp_comm == *this->distribution_pt()->communicator_pt()))
72  {
73  std::ostringstream error_message;
74  error_message << "The new distribution and the current distribution must "
75  << "have the same communicator.";
76  throw OomphLibError(
77  error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
78  }
79 #endif
80 
81  // check the distributions are not the same
82  if (!((*this->distribution_pt()) == *dist_pt))
83  {
84  // Cache the number of vectors
85  const unsigned n_vector = this->Nvector;
86 
87  // get the rank and the number of processors
88  int my_rank = this->distribution_pt()->communicator_pt()->my_rank();
89  int nproc = this->distribution_pt()->communicator_pt()->nproc();
90 
91  // if both vectors are distributed
92  if (this->distributed() && dist_pt->distributed())
93  {
94  // new nrow_local and first_row data
95  Vector<unsigned> new_first_row_data(nproc);
96  Vector<unsigned> new_nrow_local_data(nproc);
97  Vector<unsigned> current_first_row_data(nproc);
98  Vector<unsigned> current_nrow_local_data(nproc);
99  for (int i = 0; i < nproc; i++)
100  {
101  new_first_row_data[i] = dist_pt->first_row(i);
102  new_nrow_local_data[i] = dist_pt->nrow_local(i);
103  current_first_row_data[i] = this->first_row(i);
104  current_nrow_local_data[i] = this->nrow_local(i);
105  }
106 
107  // compute which local rows are expected to be received from each
108  // processor / sent to each processor
109  Vector<unsigned> new_first_row_for_proc(nproc);
110  Vector<unsigned> new_nrow_local_for_proc(nproc);
111  Vector<unsigned> new_first_row_from_proc(nproc);
112  Vector<unsigned> new_nrow_local_from_proc(nproc);
113 
114  // for every processor compute first_row and nrow_local that will
115  // will sent and received by this processor
116  for (int p = 0; p < nproc; p++)
117  {
118  // start with data to be sent
119  if ((new_first_row_data[p] < (current_first_row_data[my_rank] +
120  current_nrow_local_data[my_rank])) &&
121  (current_first_row_data[my_rank] <
122  (new_first_row_data[p] + new_nrow_local_data[p])))
123  {
124  new_first_row_for_proc[p] =
125  std::max(current_first_row_data[my_rank], new_first_row_data[p]);
126  new_nrow_local_for_proc[p] =
127  std::min((current_first_row_data[my_rank] +
128  current_nrow_local_data[my_rank]),
129  (new_first_row_data[p] + new_nrow_local_data[p])) -
130  new_first_row_for_proc[p];
131  }
132 
133  // and data to be received
134  if ((new_first_row_data[my_rank] <
135  (current_first_row_data[p] + current_nrow_local_data[p])) &&
136  (current_first_row_data[p] <
137  (new_first_row_data[my_rank] + new_nrow_local_data[my_rank])))
138  {
139  new_first_row_from_proc[p] =
140  std::max(current_first_row_data[p], new_first_row_data[my_rank]);
141  new_nrow_local_from_proc[p] =
142  std::min(
143  (current_first_row_data[p] + current_nrow_local_data[p]),
144  (new_first_row_data[my_rank] + new_nrow_local_data[my_rank])) -
145  new_first_row_from_proc[p];
146  }
147  }
148 
149  // Storage for the new data
150  double** temp_data = new double*[n_vector];
151  double* contiguous_temp_data =
152  new double[n_vector * new_nrow_local_data[my_rank]];
153  for (unsigned v = 0; v < n_vector; ++v)
154  {
155  temp_data[v] =
156  &contiguous_temp_data[v * new_nrow_local_data[my_rank]];
157  }
158 
159  // "send to self" or copy Data that does not need to be sent else where
160  // to temp_data
161  if (new_nrow_local_for_proc[my_rank] != 0)
162  {
163  unsigned j =
164  new_first_row_for_proc[my_rank] - current_first_row_data[my_rank];
165  unsigned k =
166  new_first_row_for_proc[my_rank] - new_first_row_data[my_rank];
167  for (unsigned i = 0; i < new_nrow_local_for_proc[my_rank]; i++)
168  {
169  for (unsigned v = 0; v < n_vector; ++v)
170  {
171  temp_data[v][k + i] = Values[v][j + i];
172  }
173  }
174  }
175 
176  // send and receive circularly
177  for (int p = 1; p < nproc; p++)
178  {
179  // next processor to send to
180  unsigned dest_p = (my_rank + p) % nproc;
181 
182  // next processor to receive from
183  unsigned source_p = (nproc + my_rank - p) % nproc;
184 
185  // send and receive the value
186  MPI_Status status;
187  for (unsigned v = 0; v < n_vector; v++)
188  {
189  MPI_Sendrecv(Values[v] + new_first_row_for_proc[dest_p] -
190  current_first_row_data[my_rank],
191  new_nrow_local_for_proc[dest_p],
192  MPI_DOUBLE,
193  dest_p,
194  1,
195  temp_data[v] + new_first_row_from_proc[source_p] -
196  new_first_row_data[my_rank],
197  new_nrow_local_from_proc[source_p],
198  MPI_DOUBLE,
199  source_p,
200  1,
201  this->distribution_pt()->communicator_pt()->mpi_comm(),
202  &status);
203  }
204  }
205 
206  // copy from temp data to Values_pt
207  delete[] Values[0];
208  delete[] Values;
209  Values = temp_data;
210  }
211  // if this vector is distributed but the new distributed is global
212  else if (this->distributed() && !dist_pt->distributed())
213  {
214  // copy existing Values_pt to temp_data
215  unsigned n_local_data = this->nrow_local();
216  double** temp_data = new double*[n_vector];
217  // New continguous data
218  double* contiguous_temp_data = new double[n_vector * n_local_data];
219  for (unsigned v = 0; v < n_vector; ++v)
220  {
221  temp_data[v] = &contiguous_temp_data[v * n_local_data];
222  for (unsigned i = 0; i < n_local_data; i++)
223  {
224  temp_data[v][i] = Values[v][i];
225  }
226  }
227 
228  // clear and resize Values_pt
229  delete[] Values[0];
230  double* values = new double[this->nrow() * n_vector];
231  for (unsigned v = 0; v < n_vector; v++)
232  {
233  Values[v] = &values[v * this->nrow()];
234  }
235 
236  // create a int vector of first rows
237  int* dist_first_row = new int[nproc];
238  int* dist_nrow_local = new int[nproc];
239  for (int p = 0; p < nproc; p++)
240  {
241  dist_first_row[p] = this->first_row(p);
242  dist_nrow_local[p] = this->nrow_local(p);
243  }
244 
245  // gather the local vectors from all processors on all processors
246  int my_local_data(this->nrow_local());
247 
248  // Loop over all vectors
249  for (unsigned v = 0; v < n_vector; v++)
250  {
251  MPI_Allgatherv(
252  temp_data[v],
253  my_local_data,
254  MPI_DOUBLE,
255  Values[v],
256  dist_nrow_local,
257  dist_first_row,
258  MPI_DOUBLE,
259  this->distribution_pt()->communicator_pt()->mpi_comm());
260  }
261 
262  // update the distribution
263  this->build_distribution(dist_pt);
264 
265  // delete the temp_data
266  delete[] temp_data[0];
267  delete[] temp_data;
268 
269  // clean up
270  delete[] dist_first_row;
271  delete[] dist_nrow_local;
272  }
273 
274  // if this vector is not distrubted but the target vector is
275  else if (!this->distributed() && dist_pt->distributed())
276  {
277  // cache the new nrow_local
278  unsigned nrow_local = dist_pt->nrow_local();
279 
280  // and first_row
281  unsigned first_row = dist_pt->first_row();
282 
283  const unsigned n_local_data = nrow_local;
284  double** temp_data = new double*[n_vector];
285  double* contiguous_temp_data = new double[n_vector * n_local_data];
286 
287  // copy the data
288  for (unsigned v = 0; v < n_vector; v++)
289  {
290  temp_data[v] = &contiguous_temp_data[v * n_local_data];
291  for (unsigned i = 0; i < n_local_data; i++)
292  {
293  temp_data[v][i] = Values[v][first_row + i];
294  }
295  }
296 
297  // copy to Values_pt
298  delete[] Values[0];
299  delete[] Values;
300  Values = temp_data;
301 
302  // update the distribution
303  this->build_distribution(dist_pt);
304  }
305 
306  // copy the Distribution
307  this->build_distribution(dist_pt);
308  }
309 #endif
310 
311  // Update the doublevector representation
313  }
int my_rank() const
my rank
Definition: communicator.h:176
#define min(a, b)
Definition: datatypes.h:22
#define max(a, b)
Definition: datatypes.h:23
char char char int int * k
Definition: level2_impl.h:374
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References oomph::DistributableLinearAlgebraObject::build_distribution(), oomph::LinearAlgebraDistribution::communicator_pt(), oomph::LinearAlgebraDistribution::distributed(), oomph::DistributableLinearAlgebraObject::distributed(), oomph::DistributableLinearAlgebraObject::distribution_pt(), oomph::LinearAlgebraDistribution::first_row(), oomph::DistributableLinearAlgebraObject::first_row(), i, Internal_values, j, k, max, min, oomph::OomphCommunicator::my_rank(), oomph::OomphCommunicator::nproc(), oomph::LinearAlgebraDistribution::nrow(), oomph::DistributableLinearAlgebraObject::nrow(), oomph::LinearAlgebraDistribution::nrow_local(), oomph::DistributableLinearAlgebraObject::nrow_local(), Nvector, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, p, setup_doublevector_representation(), v, values(), and Values.

◆ setup_doublevector_representation()

void oomph::DoubleMultiVector::setup_doublevector_representation ( )
inlineprivate

compute the A-norm using the matrix at matrix_pt

Setup the doublevector representation

989  {
990  const unsigned n_vector = this->nvector();
991  Internal_doublevector.resize(n_vector);
992  // Loop over all and set the external values of the DoubleVectors
993  for (unsigned v = 0; v < n_vector; v++)
994  {
995  Internal_doublevector[v].set_external_values(
996  this->distribution_pt(), this->values(v), false);
997  }
998  }

References oomph::DistributableLinearAlgebraObject::distribution_pt(), Internal_doublevector, nvector(), v, and values().

Referenced by DoubleMultiVector(), operator=(), and redistribute().

◆ shallow_build() [1/3]

void oomph::DoubleMultiVector::shallow_build ( const DoubleMultiVector old_vector)
inline

Provide a (shallow) copy of the old vector.

218  {
219  // Only bother if the old_vector is not the same as current vector
220  if (!(*this == old_vector))
221  {
222  // the vector does not own the internal data
223  Internal_values = false;
224 
225  // Copy the number of vectors
226  Nvector = old_vector.nvector();
227  // Allocate storage for pointers to the values
228  this->shallow_build(Nvector, old_vector.distribution_pt());
229 
230  // copy all the pointers accross
231  if (this->distribution_built())
232  {
233  for (unsigned v = 0; v < Nvector; ++v)
234  {
235  Values[v] = old_vector.values(v);
236  }
237  }
238  }
239  }

References oomph::DistributableLinearAlgebraObject::distribution_built(), oomph::DistributableLinearAlgebraObject::distribution_pt(), Internal_values, nvector(), Nvector, v, and values().

Referenced by DoubleMultiVector(), and shallow_build().

◆ shallow_build() [2/3]

void oomph::DoubleMultiVector::shallow_build ( const unsigned n_vector,
const LinearAlgebraDistribution dist 
)
inline

Build the storage for pointers to vectors with a given distribution, but do not populate the pointers

245  {
246  this->shallow_build(n_vector, &dist);
247  }

References shallow_build().

◆ shallow_build() [3/3]

void oomph::DoubleMultiVector::shallow_build ( const unsigned n_vector,
const LinearAlgebraDistribution *const &  dist_pt 
)
inline

Build the storage for pointers to vectors with a given distribution, but do not populate the pointers

254  {
255  // clean the memory
256  this->clear();
257 
258  // The vector does not own the data
259  Internal_values = false;
260 
261  // Set the distribution
262  this->build_distribution(dist_pt);
263 
264  // update the values
265  if (dist_pt->built())
266  {
267  // Set the number of vectors
268  Nvector = n_vector;
269  // Build the array of pointers to each vector's data
270  Values = new double*[n_vector];
271  Built = true;
272  }
273  else
274  {
275  Built = false;
276  }
277  }

References oomph::DistributableLinearAlgebraObject::build_distribution(), Built, oomph::LinearAlgebraDistribution::built(), clear(), Internal_values, and Nvector.

◆ values() [1/4]

double** oomph::DoubleMultiVector::values ( )
inline

access function to the underlying values

669  {
670  return Values;
671  }

References Values.

Referenced by build(), dot(), DoubleMultiVector(), operator+=(), operator-=(), operator==(), redistribute(), setup_doublevector_representation(), and shallow_build().

◆ values() [2/4]

double** oomph::DoubleMultiVector::values ( ) const
inline

access function to the underlying values (const version)

675  {
676  return Values;
677  }

References Values.

◆ values() [3/4]

double* oomph::DoubleMultiVector::values ( const unsigned i)
inline

access function to the i-th vector's data

681  {
682  return Values[i];
683  }

References i.

◆ values() [4/4]

double* oomph::DoubleMultiVector::values ( const unsigned i) const
inline

access function to the i-th vector's data (const version)

687  {
688  return Values[i];
689  }

References i.

Member Data Documentation

◆ Built

bool oomph::DoubleMultiVector::Built
private

indicates that the vector has been built and is usable

Referenced by build(), built(), clear(), initialise(), and shallow_build().

◆ Internal_doublevector

Vector<DoubleVector> oomph::DoubleMultiVector::Internal_doublevector
private

Need a vector of DoubleVectors to interface with our linear solvers.

Referenced by doublevector(), and setup_doublevector_representation().

◆ Internal_values

bool oomph::DoubleMultiVector::Internal_values
private

Boolean flag to indicate whether the vector's data (values_pt) is owned by this vector.

Referenced by build(), clear(), redistribute(), and shallow_build().

◆ Nvector

unsigned oomph::DoubleMultiVector::Nvector
private

The number of vectors.

Referenced by build(), initialise(), nvector(), operator()(), redistribute(), and shallow_build().

◆ Values

double** oomph::DoubleMultiVector::Values
private

the local data, need a pointer to a pointer so that the individual vectors can be extracted

Referenced by clear(), output(), redistribute(), and values().


The documentation for this class was generated from the following files: