42 if (!(*
this == old_vector))
54 const double* old_vector_values = old_vector.
values_pt();
55 std::copy(old_vector_values,
56 old_vector_values+nrow_local,
138 if (v.size()!=this->
nrow())
140 std::ostringstream error_message;
141 error_message <<
"The vector passed to initialise(...) must be of length " 144 OOMPH_CURRENT_FUNCTION,
145 OOMPH_EXCEPTION_LOCATION);
148 unsigned begin_first_row = this->
first_row();
149 unsigned end = begin_first_row + this->
nrow_local();
151 std::copy(v.begin() + begin_first_row,
175 std::ostringstream error_message;
176 error_message <<
"This vector does not own its data (i.e. it has been " 177 <<
"passed in via set_external_values() and therefore " 178 <<
"cannot be redistributed";
180 OOMPH_CURRENT_FUNCTION,
181 OOMPH_EXCEPTION_LOCATION);
185 if (dist_pt->
nrow() != this->
nrow())
187 std::ostringstream error_message;
188 error_message <<
"The number of global rows in the new distribution (" 189 << dist_pt->
nrow() <<
") is not equal to the number" 190 <<
" of global rows in the current distribution (" 191 << this->
nrow() <<
").\n";
193 OOMPH_CURRENT_FUNCTION,
194 OOMPH_EXCEPTION_LOCATION);
201 std::ostringstream error_message;
202 error_message <<
"The new distribution and the current distribution must " 203 <<
"have the same communicator.";
205 OOMPH_CURRENT_FUNCTION,
206 OOMPH_EXCEPTION_LOCATION);
227 for (
int i = 0;
i < nproc;
i++)
244 for (
int p = 0; p < nproc; p++)
247 if ((new_first_row_data[p] < (current_first_row_data[my_rank] +
248 current_nrow_local_data[my_rank])) &&
249 (current_first_row_data[my_rank] < (new_first_row_data[p] +
250 new_nrow_local_data[p])))
252 new_first_row_for_proc[p] =
253 std::max(current_first_row_data[my_rank],
254 new_first_row_data[p]);
255 new_nrow_local_for_proc[p] =
256 std::min((current_first_row_data[my_rank] +
257 current_nrow_local_data[my_rank]),
258 (new_first_row_data[p] +
259 new_nrow_local_data[p])) - new_first_row_for_proc[p];
263 if ((new_first_row_data[my_rank] < (current_first_row_data[p] +
264 current_nrow_local_data[p]))
265 && (current_first_row_data[p] < (new_first_row_data[my_rank] +
266 new_nrow_local_data[my_rank])))
268 new_first_row_from_proc[p] =
269 std::max(current_first_row_data[p],
270 new_first_row_data[my_rank]);
271 new_nrow_local_from_proc[p] =
272 std::min((current_first_row_data[p] +
273 current_nrow_local_data[p]),
274 (new_first_row_data[my_rank] +
275 new_nrow_local_data[my_rank]))-new_first_row_from_proc[p];
280 double* temp_data =
new double[new_nrow_local_data[my_rank]];
284 if (new_nrow_local_for_proc[my_rank] != 0)
286 unsigned j = new_first_row_for_proc[my_rank] -
287 current_first_row_data[my_rank];
288 unsigned k = new_first_row_for_proc[my_rank] -
289 new_first_row_data[my_rank];
290 for (
unsigned i = 0;
i < new_nrow_local_for_proc[my_rank];
i++)
297 for (
int p = 1; p < nproc; p++)
300 unsigned dest_p = (my_rank + p)%nproc;
303 unsigned source_p = (nproc + my_rank - p)%nproc;
307 MPI_Sendrecv(
Values_pt + new_first_row_for_proc[dest_p] -
308 current_first_row_data[my_rank],
309 new_nrow_local_for_proc[dest_p],MPI_DOUBLE,dest_p,1,
310 temp_data + new_first_row_from_proc[source_p] -
311 new_first_row_data[my_rank],
312 new_nrow_local_from_proc[source_p],MPI_DOUBLE,source_p,1,
345 int* dist_first_row =
new int[nproc];
346 int* dist_nrow_local =
new int[nproc];
347 for (
int p = 0; p < nproc; p++)
355 MPI_Allgatherv(temp_data,my_nrow_local,MPI_DOUBLE,
356 Values_pt,dist_nrow_local,dist_first_row,MPI_DOUBLE,
366 delete[] dist_first_row;
367 delete[] dist_nrow_local;
409 #ifdef RANGE_CHECKING 412 std::ostringstream error_message;
413 error_message <<
"Range Error: " << i
414 <<
" is not in the range (0," 417 OOMPH_CURRENT_FUNCTION,
418 OOMPH_EXCEPTION_LOCATION);
444 const double* v_values_pt = v.
values_pt();
466 std::ostringstream error_message;
467 error_message <<
"This vector must be setup.";
469 OOMPH_CURRENT_FUNCTION,
470 OOMPH_EXCEPTION_LOCATION);
475 std::ostringstream error_message;
476 error_message <<
"The vector v must be setup.";
478 OOMPH_CURRENT_FUNCTION,
479 OOMPH_EXCEPTION_LOCATION);
484 std::ostringstream error_message;
485 error_message <<
"The vector v and this vector must have the same " 488 OOMPH_CURRENT_FUNCTION,
489 OOMPH_EXCEPTION_LOCATION);
514 std::ostringstream error_message;
515 error_message <<
"This vector must be setup.";
517 OOMPH_CURRENT_FUNCTION,
518 OOMPH_EXCEPTION_LOCATION);
523 std::ostringstream error_message;
524 error_message <<
"The vector v must be setup.";
526 OOMPH_CURRENT_FUNCTION,
527 OOMPH_EXCEPTION_LOCATION);
532 std::ostringstream error_message;
533 error_message <<
"The vector v and this vector must have the same " 536 OOMPH_CURRENT_FUNCTION,
537 OOMPH_EXCEPTION_LOCATION);
562 std::ostringstream error_msg;
563 error_msg <<
"DoubleVector must be set up.";
565 OOMPH_CURRENT_FUNCTION,
566 OOMPH_EXCEPTION_LOCATION);
587 double divisor = (1.0/d);
596 #ifdef RANGE_CHECKING 599 std::ostringstream error_message;
600 error_message <<
"Range Error: " << i
601 <<
" is not in the range (0," 604 OOMPH_CURRENT_FUNCTION,
605 OOMPH_EXCEPTION_LOCATION);
621 for (
unsigned i = 0;
i <
nrow;
i++)
646 double local_max =
max;
647 MPI_Allreduce(&local_max,&max,1,MPI_DOUBLE,MPI_MAX,
660 const int &output_precision)
const 681 unsigned nrow = this->
nrow();
684 int* dist_first_row =
new int[nproc];
685 int* dist_nrow_local =
new int[nproc];
686 for (
int p = 0; p < nproc; p++)
693 temp =
new double[
nrow];
694 MPI_Allgatherv(
Values_pt,nrow_local,MPI_DOUBLE,
695 temp,dist_nrow_local,dist_first_row,MPI_DOUBLE,
699 delete[] dist_first_row;
700 delete[] dist_nrow_local;
712 std::streamsize old_precision=0;
713 if(output_precision > 0)
715 old_precision = outfile.precision();
716 outfile << std::setprecision(output_precision);
719 for (
unsigned i = 0;
i <
nrow;
i++)
721 outfile <<
i <<
" " << temp[
i] << std::endl;
725 if(output_precision > 0)
727 outfile << std::setprecision(old_precision);
744 const int &output_precision)
const 751 std::streamsize old_precision=0;
752 if(output_precision > 0)
754 old_precision = outfile.precision();
755 outfile << std::setprecision(output_precision);
764 if(output_precision > 0)
766 outfile << std::setprecision(old_precision);
774 std::ostream &outfile,
const int &output_precision)
const 784 std::streamsize old_precision=0;
785 if(output_precision > 0)
787 old_precision = outfile.precision();
788 outfile << std::setprecision(output_precision);
797 if(output_precision > 0)
799 outfile << std::setprecision(old_precision);
812 std::ostringstream error_message;
813 error_message <<
"This vector must be setup.";
815 OOMPH_CURRENT_FUNCTION,
816 OOMPH_EXCEPTION_LOCATION);
820 std::ostringstream error_message;
821 error_message <<
"The input vector be setup.";
823 OOMPH_CURRENT_FUNCTION,
824 OOMPH_EXCEPTION_LOCATION);
828 std::ostringstream error_message;
829 error_message <<
"The distribution of this vector and the vector vec " 830 <<
"must be the same." 834 OOMPH_CURRENT_FUNCTION,
835 OOMPH_EXCEPTION_LOCATION);
842 const double* vec_values_pt = vec.
values_pt();
854 MPI_Allreduce(&n,&n2,1,MPI_DOUBLE,MPI_SUM,
873 std::ostringstream error_message;
874 error_message <<
"This vector must be setup.";
876 OOMPH_CURRENT_FUNCTION,
877 OOMPH_EXCEPTION_LOCATION);
895 MPI_Allreduce(&n,&n2,1,MPI_DOUBLE,MPI_SUM,
917 std::ostringstream error_message;
918 error_message <<
"This vector must be setup.";
920 OOMPH_CURRENT_FUNCTION,
921 OOMPH_EXCEPTION_LOCATION);
923 if (!matrix_pt->
built())
925 std::ostringstream error_message;
926 error_message <<
"The input matrix be built.";
928 OOMPH_CURRENT_FUNCTION,
929 OOMPH_EXCEPTION_LOCATION);
933 std::ostringstream error_message;
934 error_message <<
"The distribution of this vector and the matrix at " 935 <<
"matrix_pt must be the same";
937 OOMPH_CURRENT_FUNCTION,
938 OOMPH_EXCEPTION_LOCATION);
945 return sqrt(this->
dot(x));
954 for(
unsigned i=1, ni=v.nrow_local();
i<ni;
i++)
966 namespace DoubleVectorHelpers
997 unsigned nvectors = in_vector_pt.size();
1004 std::ostringstream error_message;
1005 error_message <<
"There is no vector to concatenate...\n" 1006 <<
"Perhaps you forgot to fill in_vector_pt?\n";
1008 OOMPH_CURRENT_FUNCTION,
1009 OOMPH_EXCEPTION_LOCATION);
1015 std::ostringstream warning_message;
1016 warning_message <<
"There is only one vector to concatenate...\n" 1017 <<
"This does not require concatenating...\n";
1019 OOMPH_CURRENT_FUNCTION,
1020 OOMPH_EXCEPTION_LOCATION);
1024 for(
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1026 if(!in_vector_pt[vec_i]->
built())
1028 std::ostringstream error_message;
1029 error_message <<
"The vector in position " <<vec_i<<
" is not built.\n" 1030 <<
"I cannot concatenate an unbuilt vector.\n";
1032 OOMPH_CURRENT_FUNCTION,
1033 OOMPH_EXCEPTION_LOCATION);
1040 = in_vector_pt[0]->distribution_pt()->communicator_pt();
1043 bool distributed = in_vector_pt[0]->distributed();
1046 if(!out_vector.
built())
1049 unsigned tmp_nrow = 0;
1050 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1052 tmp_nrow += in_vector_pt[vec_i]->nrow();
1064 unsigned in_nrow = 0;
1065 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1067 in_nrow += in_vector_pt[vec_i]->nrow();
1070 if(in_nrow != out_vector.
nrow())
1072 std::ostringstream error_message;
1073 error_message <<
"The sum of nrow of the in vectors does not match\n" 1074 <<
"the nrow of the out vector.\n";
1076 OOMPH_CURRENT_FUNCTION,
1077 OOMPH_EXCEPTION_LOCATION);
1088 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1092 = *(in_vector_pt[vec_i]->distribution_pt()->communicator_pt());
1094 if(out_comm != in_comm)
1096 std::ostringstream error_message;
1097 error_message <<
"The vector in position "<<vec_i <<
" has a\n" 1098 <<
"different communicator from the out vector.\n";
1100 OOMPH_CURRENT_FUNCTION,
1101 OOMPH_EXCEPTION_LOCATION);
1106 if(out_comm.nproc() != 1)
1108 const bool out_distributed = out_vector.
distributed();
1109 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1111 if(out_distributed != in_vector_pt[vec_i]->
distributed())
1113 std::ostringstream error_message;
1114 error_message <<
"The vector in position "<<vec_i <<
" has a\n" 1115 <<
"different distributed boolean from " 1116 <<
"the out vector.\n";
1118 OOMPH_CURRENT_FUNCTION,
1119 OOMPH_EXCEPTION_LOCATION);
1127 if((comm_pt->nproc() == 1) || !distributed )
1137 double* out_value_pt = out_vector.
values_pt();
1140 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1143 unsigned in_nrow = in_vector_pt[vec_i]->nrow();
1146 double* in_value_pt = in_vector_pt[vec_i]->values_pt();
1149 for (
unsigned i = 0;
i < in_nrow;
i++)
1151 out_value_pt[out_i++] = in_value_pt[
i];
1158 #ifdef OOMPH_HAS_MPI 1160 unsigned nproc = comm_pt->nproc();
1163 unsigned my_rank = comm_pt->my_rank();
1170 unsigned long sum_of_vec_nrow = 0;
1180 for (
unsigned in_vec_i = 0; in_vec_i < nvectors; in_vec_i++)
1183 unsigned in_vec_nrow_local = in_vector_pt[in_vec_i]->nrow_local();
1184 unsigned in_vec_first_row = in_vector_pt[in_vec_i]->first_row();
1186 for (
unsigned in_row_i = 0;
1187 in_row_i < in_vec_nrow_local; in_row_i++)
1190 unsigned out_global_eqn = in_row_i
1191 + in_vec_first_row + sum_of_vec_nrow;
1198 unsigned out_p = out_distribution_pt
1205 unsigned out_first_row = out_distribution_pt->
first_row(out_p);
1206 unsigned out_local_eqn = out_global_eqn - out_first_row;
1209 values_to_send[out_p].push_back(out_local_eqn);
1210 values_to_send[out_p].push_back((*in_vector_pt[in_vec_i])[in_row_i]);
1214 sum_of_vec_nrow += in_vector_pt[in_vec_i]->nrow();
1230 unsigned total_ndata = 0;
1231 for (
unsigned rank = 0; rank < nproc; rank++)
1235 total_ndata += values_to_send[rank].size();
1242 send_values_data.reserve(total_ndata);
1245 for (
unsigned rank = 0; rank < nproc; rank++)
1248 send_displacement[rank] = send_values_data.size();
1252 if (rank != my_rank)
1255 unsigned n_data = values_to_send[rank].size();
1256 for (
unsigned j = 0; j < n_data; j++)
1258 send_values_data.push_back(values_to_send[rank][j]);
1263 send_n[rank] = send_values_data.size() - send_displacement[rank];
1268 MPI_Alltoall(&send_n[0],1,MPI_INT,&receive_n[0],1,MPI_INT,
1269 comm_pt->mpi_comm());
1274 int receive_data_count = 0;
1275 for (
unsigned rank = 0; rank < nproc; rank++)
1277 receive_displacement[rank] = receive_data_count;
1278 receive_data_count += receive_n[rank];
1283 if(receive_data_count == 0){receive_data_count++;}
1288 if(send_values_data.size() == 0){send_values_data.resize(1);}
1291 MPI_Alltoallv(&send_values_data[0],&send_n[0],&send_displacement[0],
1293 &receive_values_data[0],&receive_n[0],
1294 &receive_displacement[0],
1296 comm_pt->mpi_comm());
1304 unsigned location_i = 0;
1305 unsigned my_values_to_send_size = values_to_send[my_rank].size();
1306 while(location_i < my_values_to_send_size)
1308 out_vector[unsigned(values_to_send[my_rank][location_i])]
1309 = values_to_send[my_rank][location_i+1];
1316 bool data_has_been_received =
false;
1317 unsigned send_rank = 0;
1318 while(send_rank < nproc)
1320 if(receive_n[send_rank] > 0)
1322 data_has_been_received =
true;
1329 if(data_has_been_received)
1331 unsigned receive_values_data_size = receive_values_data.size();
1332 while(location_i < receive_values_data_size)
1334 out_vector[unsigned(receive_values_data[location_i])]
1335 = receive_values_data[location_i+1];
1341 std::ostringstream error_message;
1342 error_message <<
"I don't know what to do with distributed vectors\n" 1343 <<
"without MPI... :(";
1345 OOMPH_CURRENT_FUNCTION,
1346 OOMPH_EXCEPTION_LOCATION);
1370 const unsigned n_in_vector = in_vector.size();
1374 for (
unsigned i = 0;
i < n_in_vector;
i++)
1376 in_vector_pt[
i] = &in_vector[
i];
1404 unsigned nvec = out_vector_pt.size();
1408 if(!in_vector.
built())
1410 std::ostringstream error_message;
1411 error_message <<
"The in_vector is not built.\n" 1412 <<
"Please build it!.\n";
1414 OOMPH_CURRENT_FUNCTION,
1415 OOMPH_EXCEPTION_LOCATION);
1419 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
1421 if(!out_vector_pt[vec_i]->
built())
1423 std::ostringstream error_message;
1424 error_message <<
"The vector at position " << vec_i
1425 <<
" is not built.\n" 1426 <<
"Please build it!.\n";
1428 OOMPH_CURRENT_FUNCTION,
1429 OOMPH_EXCEPTION_LOCATION);
1435 unsigned out_nrow_sum = 0;
1436 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
1438 out_nrow_sum += out_vector_pt[vec_i]->nrow();
1441 if(in_vector.
nrow() != out_nrow_sum)
1443 std::ostringstream error_message;
1444 error_message <<
"The global number of rows in the in_vector\n" 1445 <<
"is not equal to the sum of the global nrows\n" 1446 <<
"of the in vectors.\n";
1448 OOMPH_CURRENT_FUNCTION,
1449 OOMPH_EXCEPTION_LOCATION);
1457 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
1460 = *(out_vector_pt[vec_i]->distribution_pt()->communicator_pt());
1462 if(in_vector_comm != dist_i_comm)
1464 std::ostringstream error_message;
1465 error_message <<
"The communicator for the distribution in the \n" 1466 <<
"position " << vec_i <<
" is not the same as the in_vector\n";
1468 OOMPH_CURRENT_FUNCTION,
1469 OOMPH_EXCEPTION_LOCATION);
1476 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
1478 if(para_distributed != out_vector_pt[vec_i]->
distributed())
1480 std::ostringstream error_message;
1481 error_message <<
"The vector in position " << vec_i <<
" does not \n" 1482 <<
" have the same distributed boolean as the in_vector\n";
1484 OOMPH_CURRENT_FUNCTION,
1485 OOMPH_EXCEPTION_LOCATION);
1499 if((comm_pt->nproc() == 1) || !distributed)
1505 unsigned in_vec_i = 0;
1506 double* in_value_pt = in_vector.
values_pt();
1509 for (
unsigned out_vec_i = 0; out_vec_i < nvec; out_vec_i++)
1512 unsigned out_nrow = out_vector_pt[out_vec_i]->nrow();
1513 double* out_value_pt = out_vector_pt[out_vec_i]->values_pt();
1516 for (
unsigned out_val_i = 0; out_val_i < out_nrow; out_val_i++)
1518 out_value_pt[out_val_i] = in_value_pt[in_vec_i++];
1525 #ifdef OOMPH_HAS_MPI 1542 unsigned nproc = comm_pt->nproc();
1545 unsigned my_rank = comm_pt->my_rank();
1553 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
1555 sum_of_out_nrow[vec_i+1] = sum_of_out_nrow[vec_i]
1556 + out_vector_pt[vec_i]->nrow();
1560 unsigned in_nrow_local = in_vector.
nrow_local();
1561 for (
unsigned in_local_eqn = 0;
1562 in_local_eqn < in_nrow_local; in_local_eqn++)
1565 unsigned in_global_eqn = in_local_eqn + in_vector.
first_row();
1568 unsigned out_vector_i = 0;
1569 while(in_global_eqn < sum_of_out_nrow[out_vector_i]
1570 || in_global_eqn >= sum_of_out_nrow[out_vector_i+1])
1577 unsigned out_global_eqn = in_global_eqn
1578 - sum_of_out_nrow[out_vector_i];
1582 = out_vector_pt[out_vector_i]->distribution_pt()
1583 ->rank_of_global_row(out_global_eqn);
1586 unsigned out_local_eqn
1587 = out_global_eqn - out_vector_pt[out_vector_i]
1588 ->distribution_pt()->first_row(out_p);
1594 values_to_send[out_p].push_back(out_vector_i);
1597 values_to_send[out_p].push_back(out_local_eqn);
1600 values_to_send[out_p].push_back(in_vector[in_local_eqn]);
1616 unsigned total_ndata = 0;
1617 for (
unsigned rank = 0; rank < nproc; rank++)
1621 total_ndata += values_to_send[rank].size();
1628 send_values_data.reserve(total_ndata);
1631 for (
unsigned rank = 0; rank < nproc; rank++)
1634 send_displacement[rank] = send_values_data.size();
1638 if (rank != my_rank)
1641 unsigned n_data = values_to_send[rank].size();
1642 for (
unsigned j = 0; j < n_data; j++)
1644 send_values_data.push_back(values_to_send[rank][j]);
1649 send_n[rank] = send_values_data.size() - send_displacement[rank];
1654 MPI_Alltoall(&send_n[0],1,MPI_INT,&receive_n[0],1,MPI_INT,
1655 comm_pt->mpi_comm());
1660 int receive_data_count = 0;
1661 for (
unsigned rank = 0; rank < nproc; rank++)
1663 receive_displacement[rank] = receive_data_count;
1664 receive_data_count += receive_n[rank];
1669 if(receive_data_count == 0){receive_data_count++;}
1674 if(send_values_data.size() == 0){send_values_data.resize(1);}
1677 MPI_Alltoallv(&send_values_data[0],&send_n[0],&send_displacement[0],
1679 &receive_values_data[0],&receive_n[0],
1680 &receive_displacement[0],
1682 comm_pt->mpi_comm());
1691 unsigned location_i = 0;
1693 unsigned my_values_to_send_size = values_to_send[my_rank].size();
1694 while(location_i < my_values_to_send_size)
1697 unsigned out_vector_i
1698 = unsigned(values_to_send[my_rank][location_i++]);
1701 unsigned out_local_eqn
1702 = unsigned(values_to_send[my_rank][location_i++]);
1705 double out_value = values_to_send[my_rank][location_i++];
1708 (*out_vector_pt[out_vector_i])[out_local_eqn] = out_value;
1714 bool data_has_been_received =
false;
1715 unsigned send_rank = 0;
1716 while(send_rank < nproc)
1718 if(receive_n[send_rank] > 0)
1720 data_has_been_received =
true;
1729 if(data_has_been_received)
1732 unsigned receive_values_data_size = receive_values_data.size();
1733 while(location_i < receive_values_data_size)
1736 unsigned out_vector_i = unsigned(receive_values_data[location_i++]);
1739 unsigned out_local_eqn = unsigned(receive_values_data[location_i++]);
1742 double out_value = receive_values_data[location_i++];
1745 (*out_vector_pt[out_vector_i])[out_local_eqn] = out_value;
1750 std::ostringstream error_message;
1751 error_message <<
"You have a distributed vector but with no mpi...\n" 1752 <<
"I don't know what to do :( \n";
1755 OOMPH_EXCEPTION_LOCATION);
1778 const unsigned n_out_vector = out_vector.size();
1781 for (
unsigned i = 0;
i < n_out_vector;
i++)
1783 out_vector_pt[
i] = &out_vector[
i];
1832 unsigned nvectors = in_vector_pt.size();
1839 std::ostringstream error_message;
1840 error_message <<
"There is no vector to concatenate...\n" 1841 <<
"Perhaps you forgot to fill in_vector_pt?\n";
1843 OOMPH_CURRENT_FUNCTION,
1844 OOMPH_EXCEPTION_LOCATION);
1850 std::ostringstream warning_message;
1851 warning_message <<
"There is only one vector to concatenate...\n" 1852 <<
"This does not require concatenating...\n";
1854 OOMPH_CURRENT_FUNCTION,
1855 OOMPH_EXCEPTION_LOCATION);
1859 for(
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1861 if(!in_vector_pt[vec_i]->
built())
1863 std::ostringstream error_message;
1864 error_message <<
"The vector in position " <<vec_i<<
" is not built.\n" 1865 <<
"I cannot concatenate an unbuilt vector.\n";
1867 OOMPH_CURRENT_FUNCTION,
1868 OOMPH_EXCEPTION_LOCATION);
1874 if(!out_vector.
built())
1877 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1879 in_distribution_pt[vec_i] = in_vector_pt[vec_i]->distribution_pt();
1885 out_vector.
build(tmp_distribution,0.0);
1896 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1900 = *(in_vector_pt[vec_i]->distribution_pt()->communicator_pt());
1902 if(out_comm != in_comm)
1904 std::ostringstream error_message;
1905 error_message <<
"The vector in position "<<vec_i <<
" has a\n" 1906 <<
"different communicator from the out vector.\n";
1908 OOMPH_CURRENT_FUNCTION,
1909 OOMPH_EXCEPTION_LOCATION);
1914 if(out_comm.nproc() > 1)
1916 const bool out_distributed = out_vector.
distributed();
1917 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1919 if(out_distributed != in_vector_pt[vec_i]->
distributed())
1921 std::ostringstream error_message;
1922 error_message <<
"The vector in position "<<vec_i <<
" has a\n" 1923 <<
"different distributed boolean from the " 1926 OOMPH_CURRENT_FUNCTION,
1927 OOMPH_EXCEPTION_LOCATION);
1940 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1942 in_distribution_pt[vec_i] = in_vector_pt[vec_i]->distribution_pt();
1953 if(tmp_distribution != out_distribution)
1955 std::ostringstream error_message;
1956 error_message <<
"The distribution of the out vector is not correct.\n" 1957 <<
"Please call the function with a cleared out vector,\n" 1958 <<
"or compare the distribution of the out vector with\n" 1959 <<
"the distribution created by\n" 1960 <<
"LinearAlgebraDistributionHelpers::concatenate(...)\n";
1962 OOMPH_CURRENT_FUNCTION,
1963 OOMPH_EXCEPTION_LOCATION);
1967 tmp_distribution.
clear();
1968 out_distribution.
clear();
1972 unsigned out_value_offset = 0;
1974 double* out_value_pt = out_vector.
values_pt();
1977 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1981 unsigned in_vector_nrow_local = in_vector_pt[vec_i]->nrow_local();
1982 double* in_vector_value_pt = in_vector_pt[vec_i]->values_pt();
1985 for (
unsigned val_i = 0; val_i < in_vector_nrow_local; val_i++)
1987 out_value_pt[out_value_offset + val_i] = in_vector_value_pt[val_i];
1991 out_value_offset += in_vector_nrow_local;
2014 const unsigned n_in_vector = in_vector.size();
2018 for (
unsigned i = 0;
i < n_in_vector;
i++)
2020 in_vector_pt[
i] = &in_vector[
i];
2051 unsigned nvec = out_vector_pt.size();
2055 if(!in_vector.
built())
2057 std::ostringstream error_message;
2058 error_message <<
"The in_vector is not built.\n" 2059 <<
"Please build it!.\n";
2061 OOMPH_CURRENT_FUNCTION,
2062 OOMPH_EXCEPTION_LOCATION);
2066 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
2068 if(!out_vector_pt[vec_i]->
built())
2070 std::ostringstream error_message;
2071 error_message <<
"The vector at position " << vec_i
2072 <<
" is not built.\n" 2073 <<
"Please build it!.\n";
2075 OOMPH_CURRENT_FUNCTION,
2076 OOMPH_EXCEPTION_LOCATION);
2085 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
2087 tmp_out_distribution_pt[vec_i] = out_vector_pt[vec_i]->distribution_pt();
2096 std::ostringstream error_message;
2097 error_message <<
"The distribution from the in vector is incorrect.\n" 2098 <<
"It must be a concatenation of all the distributions\n" 2099 <<
"from the out vectors.\n";
2101 OOMPH_CURRENT_FUNCTION,
2102 OOMPH_EXCEPTION_LOCATION);
2106 tmp_distribution.
clear();
2113 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
2116 = *(out_vector_pt[vec_i]->distribution_pt()->communicator_pt());
2118 if(in_vector_comm != vec_i_comm)
2120 std::ostringstream error_message;
2121 error_message <<
"The communicator for the vector in position\n" 2122 << vec_i <<
" is not the same as the in_vector\n" 2125 OOMPH_CURRENT_FUNCTION,
2126 OOMPH_EXCEPTION_LOCATION);
2132 if(in_vector_comm.nproc()>1)
2135 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
2137 if(in_distributed != out_vector_pt[vec_i]->
distributed())
2139 std::ostringstream error_message;
2140 error_message <<
"The vector in position " << vec_i
2141 <<
" does not have\n" 2142 <<
"the same distributed boolean as the in vector";
2144 OOMPH_CURRENT_FUNCTION,
2145 OOMPH_EXCEPTION_LOCATION);
2153 double* in_value_pt = in_vector.
values_pt();
2154 unsigned in_value_offset = 0;
2155 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
2158 unsigned out_nrow_local = out_vector_pt[vec_i]->nrow_local();
2159 double* out_value_pt = out_vector_pt[vec_i]->values_pt();
2162 for (
unsigned val_i = 0; val_i < out_nrow_local; val_i++)
2164 out_value_pt[val_i] = in_value_pt[in_value_offset + val_i];
2168 in_value_offset += out_nrow_local;
2190 const unsigned n_out_vector = out_vector.size();
2194 for (
unsigned i = 0;
i < n_out_vector;
i++)
2196 out_vector_pt[
i] = &out_vector[
i];
2200 in_vector,out_vector_pt);
void clear()
wipes the DoubleVector
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
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...
bool operator==(const DoubleVector &v)
== operator
bool built() const
access function to the Built flag - indicates whether the matrix has been build - i...
double * values_pt()
access function to the underlying values
void output_local_values(std::ostream &outfile, const int &output_precision=-1) const
output the local contents of the vector
void concatenate(const Vector< LinearAlgebraDistribution *> &in_distribution_pt, LinearAlgebraDistribution &out_distribution)
Takes a vector of LinearAlgebraDistribution objects and concatenates them such that the nrow_local of...
double & operator[](int i)
[] access function to the (local) values of this vector
OomphCommunicator * communicator_pt() const
const access to the communicator pointer
void split_without_communication(const DoubleVector &in_vector, Vector< DoubleVector *> &out_vector_pt)
Split a DoubleVector into the out DoubleVectors. Data stays on its current processor, no data is sent between processors. This results in our vectors which are a permutation of the in vector.
void concatenate_without_communication(Vector< DoubleVector > &in_vector, DoubleVector &out_vector)
Wrapper around the other concatenate_without_communication(...) function. Be careful with Vector of v...
unsigned nrow() const
access function to the number of global rows.
unsigned first_row() const
access function for the first row on this processor. If not distributed then this is just zero...
bool distributed() const
access function to the distributed - indicates whether the distribution is serial or distributed ...
friend std::ostream & operator<<(std::ostream &out, const DoubleVector &v)
Ouput operator for DoubleVector.
void concatenate_without_communication(const Vector< DoubleVector *> &in_vector_pt, DoubleVector &out_vector)
Concatenate DoubleVectors. Takes a Vector of DoubleVectors. If the out vector is built, we will not build a new distribution. Otherwise a new distribution will be built using LinearAlgebraDistribution::concatenate(...).
bool Internal_values
Boolean flag to indicate whether the vector's data (values_pt) is owned by this vector.
void operator-=(const DoubleVector &v)
-= operator with another vector
bool distribution_built() const
void operator/=(const double &d)
divide by a double
bool distributed() const
distribution is serial or distributed
void operator+=(const DoubleVector &v)
+= operator with another vector
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
double * Values_pt
the local vector
void initialise(const double &v)
initialise the whole vector with value v
unsigned nrow_local() const
access function for the num of local rows on this processor. If no MPI then Nrow is returned...
unsigned first_row() const
access function for the first row on this processor
unsigned rank_of_global_row(const unsigned i) const
return the processor rank of the global row number i
bool Built
indicates that the vector has been built and is usable
void split(const DoubleVector &in_vector, Vector< DoubleVector > &out_vector)
Wrapper around the other split(...) function. Be careful with Vector of vectors. If the DoubleVectors...
unsigned nrow() const
access function to the number of global rows.
double dot(const DoubleVector &vec) const
compute the dot product of this vector with the vector vec.
void output_local_values_with_offset(std::ostream &outfile, const int &output_precision=-1) const
output the local contents of the vector
void concatenate(Vector< DoubleVector > &in_vector, DoubleVector &out_vector)
Wrapper around the other concatenate(...) function. Be careful with Vector of vectors. If the DoubleVectors are resized, there could be reallocation of memory. If we wanted to use the function which takes a Vector of pointers to DoubleVectors, we would either have to invoke new and remember to delete, or create a temporary Vector to store pointers to the DoubleVector objects. This wrapper is meant to make life easier for the user by avoiding calls to new/delete AND without creating a temporary vector of pointers to DoubleVectors. If we had C++ 11, this would be so much nicer since we can use smart pointers which will delete themselves, so we do not have to remember to delete!
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
setup the distribution of this distributable linear algebra object
void operator*=(const double &d)
multiply by a double
unsigned nrow_local() const
access function for the num of local rows on this 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, we will not build a new distribution. Otherwise we build a uniform distribution.
void split_without_communication(const DoubleVector &in_vector, Vector< DoubleVector > &out_vector)
Wrapper around the other split_without_communication(...) function. Be careful with Vector of vectors...
A vector in the mathematical sense, initially developed for linear algebra type applications. If MPI then this vector can be distributed - its distribution is described by the LinearAlgebraDistribution object at Distribution_pt. Data is stored in a C-style pointer vector (double*)
void clear()
clears the distribution
double norm() const
compute the 2 norm of this vector
A class for compressed row matrices. This is a distributable object.
void output(std::ostream &outfile, const int &output_precision=-1) const
output the global contents of the vector
void split(const DoubleVector &in_vector, Vector< DoubleVector *> &out_vector_pt)
Split a DoubleVector into the out DoubleVectors. Let vec_A be the in Vector, and let vec_B and vec_C ...
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
double max() const
returns the maximum coefficient
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...