vector_split_without_communication.cc File Reference
#include "generic.h"

Functions

template<typename myType >
void construct_vector (myType given_array[], unsigned given_arraysize, Vector< myType > &result_vector)
 
template<typename myType >
void output_vector (Vector< myType > &given_vector)
 
void create_vector_ascend_row (unsigned const nrow, const OomphCommunicator *const comm_pt, bool const distributed, DoubleVector &my_vec)
 
void fill_in_sub_vectors (const OomphCommunicator *const comm_pt, const bool distributed, Vector< unsigned > &dimvector, Vector< DoubleVector > &my_vecs)
 
void create_vectors_to_cat (const unsigned nvectors, unsigned dimarray[], const OomphCommunicator *const comm_pt, Vector< DoubleVector > &my_vecs)
 
void create_vectors_to_split (unsigned nrowarray[], const OomphCommunicator *const comm_pt, const bool distributed, Vector< DoubleVector > &out_vector)
 
int main (int argc, char *argv[])
 

Function Documentation

◆ construct_vector()

template<typename myType >
void construct_vector ( myType  given_array[],
unsigned  given_arraysize,
Vector< myType > &  result_vector 
)
36 {
37  // Clear and reserve the required memory.
38  result_vector.clear();
39  result_vector.reserve(given_arraysize);
40 
41  for (unsigned i = 0; i < given_arraysize; i++)
42  {
43  result_vector.push_back(given_array[i]);
44  }
45 }
int i
Definition: BiCGSTAB_step_by_step.cpp:9

References i.

Referenced by create_vectors_to_cat().

◆ create_vector_ascend_row()

void create_vector_ascend_row ( unsigned const  nrow,
const OomphCommunicator *const  comm_pt,
bool const  distributed,
DoubleVector my_vec 
)
65 {
66  // Clear the block
67  my_vec.clear();
68 
69  // Create the distribution.
70  LinearAlgebraDistribution distri(comm_pt,nrow,distributed);
71 
72  // Build the vector
73  my_vec.build(distri,0.0);
74 
75  // The number of rows this processor is responsible for.
76  unsigned nrow_local = distri.nrow_local();
77 
78  // The first_row will be used as an offset for the values to insert.
79  unsigned first_row = distri.first_row();
80 
81  // Fill in values...
82  for (unsigned row_i = 0; row_i < nrow_local; row_i++)
83  {
84  my_vec[row_i] = first_row + row_i + 1; // Use natural numbers
85  }
86 }
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
Definition: double_vector.cc:35
void clear()
wipes the DoubleVector
Definition: double_vector.h:142
Definition: linear_algebra_distribution.h:64

References oomph::DoubleVector::build(), oomph::DoubleVector::clear(), oomph::LinearAlgebraDistribution::first_row(), and oomph::LinearAlgebraDistribution::nrow_local().

Referenced by fill_in_sub_vectors().

◆ create_vectors_to_cat()

void create_vectors_to_cat ( const unsigned  nvectors,
unsigned  dimarray[],
const OomphCommunicator *const  comm_pt,
Vector< DoubleVector > &  my_vecs 
)
112 {
113  // Convert dimarray into a Vector so it is easier to manage.
114  Vector<unsigned> dimvector;
115  construct_vector(dimarray,nvectors,dimvector);
116 
117  // Fill in each sub DoubleVector using create_double_vector_ascend_row(...)
118  bool distributed = true;
119  fill_in_sub_vectors(comm_pt,distributed,dimvector,my_vecs);
120 }
void fill_in_sub_vectors(const OomphCommunicator *const comm_pt, const bool distributed, Vector< unsigned > &dimvector, Vector< DoubleVector > &my_vecs)
Definition: vector_split_without_communication.cc:90
void construct_vector(myType given_array[], unsigned given_arraysize, Vector< myType > &result_vector)
Definition: vector_split_without_communication.cc:34

References construct_vector(), and fill_in_sub_vectors().

◆ create_vectors_to_split()

void create_vectors_to_split ( unsigned  nrowarray[],
const OomphCommunicator *const  comm_pt,
const bool  distributed,
Vector< DoubleVector > &  out_vector 
)
128 {
129  // The number of out vectors.
130  unsigned nvectors = out_vector.size();
131 
132  // Fill in each sub DoubleVector using create_double_vector_ascend_row(...)
133  for (unsigned vec_i = 0; vec_i < nvectors; vec_i++)
134  {
135  // Create the distribution
136  LinearAlgebraDistribution dist(comm_pt,nrowarray[vec_i],distributed);
137  out_vector[vec_i].build(dist);
138  }
139 }

Referenced by main().

◆ fill_in_sub_vectors()

void fill_in_sub_vectors ( const OomphCommunicator *const  comm_pt,
const bool  distributed,
Vector< unsigned > &  dimvector,
Vector< DoubleVector > &  my_vecs 
)
94 {
95  unsigned nvectors = my_vecs.size();
96 
97  for (unsigned vec_i = 0; vec_i < nvectors; vec_i++)
98  {
99  unsigned vec_size = dimvector[vec_i];
100  create_vector_ascend_row(vec_size,comm_pt,distributed,
101  my_vecs[vec_i]);
102  }
103 }
void create_vector_ascend_row(unsigned const nrow, const OomphCommunicator *const comm_pt, bool const distributed, DoubleVector &my_vec)
Definition: vector_split_without_communication.cc:61

References create_vector_ascend_row().

Referenced by create_vectors_to_cat().

◆ main()

int main ( int argc  ,
char argv[] 
)

Driver code: Testing DoubleVectorHelpers::split_without_communication(...) This is the reverse of DoubleVectorHelpers::concatenate_without_communication(...), demonstrated in self_test/mpi/vector_concatenation_without_communication/

There is a "strong" relationship between the distributions of the in_vector and the out vectors: The distribution of the in_vector must be the same as the concatenation of the out vectors as defined by LinearAlgebraDistributionHelpers::concatenate(...).

To see why, we demonstrate this on two cores, p0 and p1, and out vectors v1, v2 and v3 with lengths 7, 5 and 3 respectively. As seen in the driver code distribution_concatenation, we have:

v1: nrow = 7 nrow_local p0 = 3 nrow_local p1 = 4

v2: nrow = 5 nrow_local p0 = 2 nrow_local p1 = 3

v3: nrow = 3 nrow_local p0 = 1 nrow_local p1 = 2

If no communication takes place, i.e. all data on p0 stays on p0 (and similarly for p1), the in vector MUST have the following distribution: in_vec: nrow = 15 nrow_local p0 = 3+2+1 = 6 nrow_local p1 = 4+3+2 = 9

In this driver test, we split a vector of length 15 into vectors of length 7, 5 and 3, ensuring that the above relationship is maintained. The script validate.sh should run this program on 1, 2, 3 and 4 cores.

180 {
181 #ifdef OOMPH_HAS_MPI
182  // Initialise MPI
183  MPI_Helpers::init(argc,argv);
184 #endif
185 
186  // Get the global oomph-lib communicator
187  const OomphCommunicator* const comm_pt = MPI_Helpers::communicator_pt();
188 
189  // my rank
190  unsigned my_rank = comm_pt->my_rank();
191 
192  // number of out vectors
193  unsigned nvectors = 3;
194 
195  // Supply the number of global rows of the vectors
196  unsigned nrowarray[] = {7,5,3};
197 
198  // To create an in_vector with the correct distribution, we first create
199  // the out vectors, then store their distribution pointers in a Vector.
200 
201  // The out vectors
202  Vector<DoubleVector> out_vector(nvectors);
203 
204  bool distributed = true;
205 
206  // Create the vectors and get the pointers to them.
207  // This may be a bit long winded but we do not want to create pointers
208  // to objects using "new" since then we will have to remember to call
209  // delete and null the pointers. This is considered bad practice, memory
210  // management should be done automatically with smart pointers.
211  // We could use smart pointers but it is only available in C++11,
212  // or use boost smart pointers, but we do not have boost...
213  // /rant.
214 
215  // Create the vectors to split the vector into.
216  create_vectors_to_split(nrowarray,comm_pt,distributed,out_vector);
217 
218  // Pointers to the out distributions
219  Vector<LinearAlgebraDistribution*> out_distribution_pt(nvectors,0);
220  for (unsigned vec_i = 0; vec_i < nvectors; vec_i++)
221  {
222  out_distribution_pt[vec_i] = out_vector[vec_i].distribution_pt();
223  }
224 
225  // Create the in vector distribution by concatenating the distributions
226  // from out vectors.
227  LinearAlgebraDistribution in_distribution;
229  in_distribution);
230 
231  // Create the in vector with natural numbers.
232  DoubleVector in_vector(in_distribution,0.0);
233 
234  double* in_values_pt = in_vector.values_pt();
235  unsigned in_nrow_local = in_vector.nrow_local();
236  unsigned in_first_row = in_vector.first_row();
237 
238  // Fill in the values:
239  for (unsigned row_i = 0; row_i < in_nrow_local; row_i++)
240  {
241  in_values_pt[row_i] = in_first_row + row_i + 1;
242  }
243 
244  // Now split the vector.
246  out_vector);
247  unsigned nproc = comm_pt->nproc();
248 
249  // The output file name.
250  std::ostringstream outfile_stream;
251  outfile_stream << "out_NP"<<nproc<<"R"<< my_rank;
252 
253  // The output file.
254  std::ofstream out_file;
255  out_file.open(outfile_stream.str().c_str());
256 
257  // Output data from all out vectors:
258  // nrow()
259  // first_row()
260  // nrow_local()
261  // distributed()
262  // values
263  for (unsigned vec_i = 0; vec_i < nvectors; vec_i++)
264  {
265  // The values and nrow local.
266  double* out_values = out_vector[vec_i].values_pt();
267  unsigned out_nrow_local = out_vector[vec_i].nrow_local();
268 
269  out_file << out_vector[vec_i].nrow() << "\n";
270  out_file << out_vector[vec_i].first_row() << "\n";
271  out_file << out_nrow_local << "\n";
272  out_file << out_vector[vec_i].distributed() << "\n";
273 
274  for (unsigned val_i = 0; val_i < out_nrow_local; val_i++)
275  {
276  out_file << out_values[val_i] << "\n";
277  }
278  }
279 
280  out_file.close();
281 
282 #ifdef OOMPH_HAS_MPI
283  // finalize MPI
284  MPI_Helpers::finalize();
285 #endif
286  return(EXIT_SUCCESS);
287 } // end_of_main
Definition: double_vector.h:58
Definition: communicator.h:54
int my_rank() const
my rank
Definition: communicator.h:176
int nproc() const
number of processors
Definition: communicator.h:157
void split_without_communication(const DoubleVector &in_vector, Vector< DoubleVector * > &out_vector_pt)
Definition: double_vector.cc:2075
void concatenate(const Vector< DoubleVector * > &in_vector_pt, DoubleVector &out_vector)
Definition: double_vector.cc:993
void create_vectors_to_split(unsigned nrowarray[], const OomphCommunicator *const comm_pt, const bool distributed, Vector< DoubleVector > &out_vector)
Definition: vector_split_without_communication.cc:126

References oomph::MPI_Helpers::communicator_pt(), oomph::LinearAlgebraDistributionHelpers::concatenate(), create_vectors_to_split(), oomph::MPI_Helpers::finalize(), oomph::DistributableLinearAlgebraObject::first_row(), oomph::MPI_Helpers::init(), oomph::OomphCommunicator::my_rank(), oomph::OomphCommunicator::nproc(), oomph::DistributableLinearAlgebraObject::nrow_local(), oomph::DoubleVectorHelpers::split_without_communication(), and oomph::DoubleVector::values_pt().

◆ output_vector()

template<typename myType >
void output_vector ( Vector< myType > &  given_vector)
50 {
51  typename Vector<myType>::iterator it;
52 
53  for(it = given_vector.begin(); it != given_vector.end(); ++it)
54  {
55  oomph_info << *it << std::endl;
56  }
57 }
OomphInfo oomph_info
Definition: oomph_definitions.cc:319

References oomph::oomph_info.