37 if (!(*
this == old_vector))
49 const double* old_vector_values = old_vector.
values_pt();
104 if (dist_pt->
built())
141 if (v.size() != this->nrow())
143 std::ostringstream error_message;
144 error_message <<
"The vector passed to initialise(...) must be of length "
147 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
150 unsigned begin_first_row = this->
first_row();
151 unsigned end = begin_first_row + this->
nrow_local();
153 std::copy(v.begin() + begin_first_row, v.begin() + end,
Values_pt);
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 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
184 if (dist_pt->
nrow() != this->nrow())
186 std::ostringstream error_message;
187 error_message <<
"The number of global rows in the new distribution ("
188 << dist_pt->
nrow() <<
") is not equal to the number"
189 <<
" of global rows in the current distribution ("
190 << this->
nrow() <<
").\n";
192 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
199 std::ostringstream error_message;
200 error_message <<
"The new distribution and the current distribution must "
201 <<
"have the same communicator.";
203 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
222 for (
int i = 0;
i < nproc;
i++)
239 for (
int p = 0; p < nproc; p++)
242 if ((new_first_row_data[p] < (current_first_row_data[my_rank] +
243 current_nrow_local_data[my_rank])) &&
244 (current_first_row_data[my_rank] <
245 (new_first_row_data[p] + new_nrow_local_data[p])))
247 new_first_row_for_proc[p] =
248 std::max(current_first_row_data[my_rank], new_first_row_data[p]);
249 new_nrow_local_for_proc[p] =
250 std::min((current_first_row_data[my_rank] +
251 current_nrow_local_data[my_rank]),
252 (new_first_row_data[p] + new_nrow_local_data[p])) -
253 new_first_row_for_proc[p];
257 if ((new_first_row_data[my_rank] <
258 (current_first_row_data[p] + current_nrow_local_data[p])) &&
259 (current_first_row_data[p] <
260 (new_first_row_data[my_rank] + new_nrow_local_data[my_rank])))
262 new_first_row_from_proc[p] =
263 std::max(current_first_row_data[p], new_first_row_data[my_rank]);
264 new_nrow_local_from_proc[p] =
266 (current_first_row_data[p] + current_nrow_local_data[p]),
267 (new_first_row_data[my_rank] + new_nrow_local_data[my_rank])) -
268 new_first_row_from_proc[p];
273 double* temp_data =
new double[new_nrow_local_data[my_rank]];
277 if (new_nrow_local_for_proc[my_rank] != 0)
280 new_first_row_for_proc[my_rank] - current_first_row_data[my_rank];
282 new_first_row_for_proc[my_rank] - new_first_row_data[my_rank];
283 for (
unsigned i = 0;
i < new_nrow_local_for_proc[my_rank];
i++)
290 for (
int p = 1; p < nproc; p++)
293 unsigned dest_p = (my_rank + p) % nproc;
296 unsigned source_p = (nproc + my_rank - p) % nproc;
300 MPI_Sendrecv(
Values_pt + new_first_row_for_proc[dest_p] -
301 current_first_row_data[my_rank],
302 new_nrow_local_for_proc[dest_p],
306 temp_data + new_first_row_from_proc[source_p] -
307 new_first_row_data[my_rank],
308 new_nrow_local_from_proc[source_p],
343 int* dist_first_row =
new int[nproc];
344 int* dist_nrow_local =
new int[nproc];
345 for (
int p = 0; p < nproc; p++)
353 MPI_Allgatherv(temp_data,
369 delete[] dist_first_row;
370 delete[] dist_nrow_local;
410 #ifdef RANGE_CHECKING
413 std::ostringstream error_message;
414 error_message <<
"Range Error: " <<
i <<
" is not in the range (0,"
417 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
429 if (v.
built() && !this->built())
433 else if (!v.
built() && this->built())
437 else if (!v.
built() && !this->built())
443 const double* v_values_pt = v.
values_pt();
465 std::ostringstream error_message;
466 error_message <<
"This vector must be setup.";
468 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
473 std::ostringstream error_message;
474 error_message <<
"The vector v must be setup.";
476 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
481 std::ostringstream error_message;
482 error_message <<
"The vector v and this vector must have the same "
485 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
510 std::ostringstream error_message;
511 error_message <<
"This vector must be setup.";
513 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
518 std::ostringstream error_message;
519 error_message <<
"The vector v must be setup.";
521 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
526 std::ostringstream error_message;
527 error_message <<
"The vector v and this vector must have the same "
530 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
555 std::ostringstream error_msg;
556 error_msg <<
"DoubleVector must be set up.";
558 error_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
579 double divisor = (1.0 / d);
588 #ifdef RANGE_CHECKING
591 std::ostringstream error_message;
592 error_message <<
"Range Error: " <<
i <<
" is not in the range (0,"
595 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
611 for (
unsigned i = 0;
i <
nrow;
i++)
636 double local_max =
max;
637 MPI_Allreduce(&local_max,
654 const int& output_precision)
const
675 unsigned nrow = this->
nrow();
678 int* dist_first_row =
new int[nproc];
679 int* dist_nrow_local =
new int[nproc];
680 for (
int p = 0; p < nproc; p++)
687 temp =
new double[
nrow];
698 delete[] dist_first_row;
699 delete[] dist_nrow_local;
711 std::streamsize old_precision = 0;
712 if (output_precision > 0)
714 old_precision = outfile.precision();
715 outfile << std::setprecision(output_precision);
718 for (
unsigned i = 0;
i <
nrow;
i++)
720 outfile <<
i <<
" " << temp[
i] << std::endl;
724 if (output_precision > 0)
726 outfile << std::setprecision(old_precision);
743 const int& output_precision)
const
750 std::streamsize old_precision = 0;
751 if (output_precision > 0)
753 old_precision = outfile.precision();
754 outfile << std::setprecision(output_precision);
763 if (output_precision > 0)
765 outfile << std::setprecision(old_precision);
773 std::ostream& outfile,
const int& output_precision)
const
783 std::streamsize old_precision = 0;
784 if (output_precision > 0)
786 old_precision = outfile.precision();
787 outfile << std::setprecision(output_precision);
796 if (output_precision > 0)
798 outfile << std::setprecision(old_precision);
811 std::ostringstream error_message;
812 error_message <<
"This vector must be setup.";
814 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
818 std::ostringstream error_message;
819 error_message <<
"The input vector be setup.";
821 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
825 std::ostringstream error_message;
826 error_message <<
"The distribution of this vector and the vector vec "
827 <<
"must be the same."
831 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
838 const double* vec_values_pt = vec.
values_pt();
873 std::ostringstream error_message;
874 error_message <<
"This vector must be setup.";
876 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
920 std::ostringstream error_message;
921 error_message <<
"This vector must be setup.";
923 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
925 if (!matrix_pt->
built())
927 std::ostringstream error_message;
928 error_message <<
"The input matrix be built.";
930 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
934 std::ostringstream error_message;
935 error_message <<
"The distribution of this vector and the matrix at "
936 <<
"matrix_pt must be the same";
938 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
945 return sqrt(this->
dot(x));
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
1030 <<
" is not built.\n"
1031 <<
"I cannot concatenate an unbuilt vector.\n";
1033 OOMPH_CURRENT_FUNCTION,
1034 OOMPH_EXCEPTION_LOCATION);
1041 in_vector_pt[0]->distribution_pt()->communicator_pt();
1044 bool distributed = in_vector_pt[0]->distributed();
1047 if (!out_vector.
built())
1050 unsigned tmp_nrow = 0;
1051 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1053 tmp_nrow += in_vector_pt[vec_i]->nrow();
1065 unsigned in_nrow = 0;
1066 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1068 in_nrow += in_vector_pt[vec_i]->nrow();
1071 if (in_nrow != out_vector.
nrow())
1073 std::ostringstream error_message;
1074 error_message <<
"The sum of nrow of the in vectors does not match\n"
1075 <<
"the nrow of the out vector.\n";
1077 OOMPH_CURRENT_FUNCTION,
1078 OOMPH_EXCEPTION_LOCATION);
1089 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1093 *(in_vector_pt[vec_i]->distribution_pt()->communicator_pt());
1095 if (out_comm != in_comm)
1097 std::ostringstream error_message;
1098 error_message <<
"The vector in position " << vec_i <<
" has a\n"
1099 <<
"different communicator from the out vector.\n";
1101 OOMPH_CURRENT_FUNCTION,
1102 OOMPH_EXCEPTION_LOCATION);
1107 if (out_comm.nproc() != 1)
1109 const bool out_distributed = out_vector.
distributed();
1110 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1112 if (out_distributed != in_vector_pt[vec_i]->distributed())
1114 std::ostringstream error_message;
1115 error_message <<
"The vector in position " << vec_i <<
" has a\n"
1116 <<
"different distributed boolean from "
1117 <<
"the out vector.\n";
1119 OOMPH_CURRENT_FUNCTION,
1120 OOMPH_EXCEPTION_LOCATION);
1128 if ((comm_pt->nproc() == 1) || !distributed)
1138 double* out_value_pt = out_vector.
values_pt();
1141 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1144 unsigned in_nrow = in_vector_pt[vec_i]->nrow();
1147 double* in_value_pt = in_vector_pt[vec_i]->values_pt();
1150 for (
unsigned i = 0;
i < in_nrow;
i++)
1152 out_value_pt[out_i++] = in_value_pt[
i];
1159 #ifdef OOMPH_HAS_MPI
1161 unsigned nproc = comm_pt->nproc();
1164 unsigned my_rank = comm_pt->my_rank();
1171 unsigned long sum_of_vec_nrow = 0;
1181 for (
unsigned in_vec_i = 0; in_vec_i < nvectors; in_vec_i++)
1184 unsigned in_vec_nrow_local = in_vector_pt[in_vec_i]->nrow_local();
1185 unsigned in_vec_first_row = in_vector_pt[in_vec_i]->first_row();
1187 for (
unsigned in_row_i = 0; in_row_i < in_vec_nrow_local; in_row_i++)
1190 unsigned out_global_eqn =
1191 in_row_i + in_vec_first_row + sum_of_vec_nrow;
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(
1211 (*in_vector_pt[in_vec_i])[in_row_i]);
1215 sum_of_vec_nrow += in_vector_pt[in_vec_i]->nrow();
1231 unsigned total_ndata = 0;
1232 for (
unsigned rank = 0; rank < nproc; rank++)
1234 if (rank != my_rank)
1236 total_ndata += values_to_send[rank].size();
1243 send_values_data.reserve(total_ndata);
1246 for (
unsigned rank = 0; rank < nproc; rank++)
1249 send_displacement[rank] = send_values_data.size();
1253 if (rank != my_rank)
1256 unsigned n_data = values_to_send[rank].size();
1257 for (
unsigned j = 0; j < n_data; j++)
1259 send_values_data.push_back(values_to_send[rank][j]);
1264 send_n[rank] = send_values_data.size() - send_displacement[rank];
1269 MPI_Alltoall(&send_n[0],
1275 comm_pt->mpi_comm());
1280 int receive_data_count = 0;
1281 for (
unsigned rank = 0; rank < nproc; rank++)
1283 receive_displacement[rank] = receive_data_count;
1284 receive_data_count += receive_n[rank];
1289 if (receive_data_count == 0)
1291 receive_data_count++;
1297 if (send_values_data.size() == 0)
1299 send_values_data.resize(1);
1303 MPI_Alltoallv(&send_values_data[0],
1305 &send_displacement[0],
1307 &receive_values_data[0],
1309 &receive_displacement[0],
1311 comm_pt->mpi_comm());
1319 unsigned location_i = 0;
1320 unsigned my_values_to_send_size = values_to_send[my_rank].size();
1321 while (location_i < my_values_to_send_size)
1323 out_vector[unsigned(values_to_send[my_rank][location_i])] =
1324 values_to_send[my_rank][location_i + 1];
1331 bool data_has_been_received =
false;
1332 unsigned send_rank = 0;
1333 while (send_rank < nproc)
1335 if (receive_n[send_rank] > 0)
1337 data_has_been_received =
true;
1344 if (data_has_been_received)
1346 unsigned receive_values_data_size = receive_values_data.size();
1347 while (location_i < receive_values_data_size)
1349 out_vector[unsigned(receive_values_data[location_i])] =
1350 receive_values_data[location_i + 1];
1356 std::ostringstream error_message;
1357 error_message <<
"I don't know what to do with distributed vectors\n"
1358 <<
"without MPI... :(";
1360 OOMPH_CURRENT_FUNCTION,
1361 OOMPH_EXCEPTION_LOCATION);
1383 const unsigned n_in_vector = in_vector.size();
1387 for (
unsigned i = 0;
i < n_in_vector;
i++)
1389 in_vector_pt[
i] = &in_vector[
i];
1417 unsigned nvec = out_vector_pt.size();
1421 if (!in_vector.
built())
1423 std::ostringstream error_message;
1424 error_message <<
"The in_vector is not built.\n"
1425 <<
"Please build it!.\n";
1427 OOMPH_CURRENT_FUNCTION,
1428 OOMPH_EXCEPTION_LOCATION);
1432 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
1434 if (!out_vector_pt[vec_i]->built())
1436 std::ostringstream error_message;
1437 error_message <<
"The vector at position " << vec_i
1438 <<
" is not built.\n"
1439 <<
"Please build it!.\n";
1441 OOMPH_CURRENT_FUNCTION,
1442 OOMPH_EXCEPTION_LOCATION);
1448 unsigned out_nrow_sum = 0;
1449 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
1451 out_nrow_sum += out_vector_pt[vec_i]->nrow();
1454 if (in_vector.
nrow() != out_nrow_sum)
1456 std::ostringstream error_message;
1457 error_message <<
"The global number of rows in the in_vector\n"
1458 <<
"is not equal to the sum of the global nrows\n"
1459 <<
"of the in vectors.\n";
1461 OOMPH_CURRENT_FUNCTION,
1462 OOMPH_EXCEPTION_LOCATION);
1470 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
1473 *(out_vector_pt[vec_i]->distribution_pt()->communicator_pt());
1475 if (in_vector_comm != dist_i_comm)
1477 std::ostringstream error_message;
1478 error_message <<
"The communicator for the distribution in the \n"
1479 <<
"position " << vec_i
1480 <<
" is not the same as the in_vector\n";
1482 OOMPH_CURRENT_FUNCTION,
1483 OOMPH_EXCEPTION_LOCATION);
1490 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
1492 if (para_distributed != out_vector_pt[vec_i]->distributed())
1494 std::ostringstream error_message;
1496 <<
"The vector in position " << vec_i <<
" does not \n"
1497 <<
" have the same distributed boolean as the in_vector\n";
1499 OOMPH_CURRENT_FUNCTION,
1500 OOMPH_EXCEPTION_LOCATION);
1514 if ((comm_pt->nproc() == 1) || !distributed)
1520 unsigned in_vec_i = 0;
1521 double* in_value_pt = in_vector.
values_pt();
1524 for (
unsigned out_vec_i = 0; out_vec_i < nvec; out_vec_i++)
1527 unsigned out_nrow = out_vector_pt[out_vec_i]->nrow();
1528 double* out_value_pt = out_vector_pt[out_vec_i]->values_pt();
1531 for (
unsigned out_val_i = 0; out_val_i < out_nrow; out_val_i++)
1533 out_value_pt[out_val_i] = in_value_pt[in_vec_i++];
1540 #ifdef OOMPH_HAS_MPI
1557 unsigned nproc = comm_pt->nproc();
1560 unsigned my_rank = comm_pt->my_rank();
1568 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
1570 sum_of_out_nrow[vec_i + 1] =
1571 sum_of_out_nrow[vec_i] + out_vector_pt[vec_i]->nrow();
1575 unsigned in_nrow_local = in_vector.
nrow_local();
1576 for (
unsigned in_local_eqn = 0; in_local_eqn < in_nrow_local;
1580 unsigned in_global_eqn = in_local_eqn + in_vector.
first_row();
1583 unsigned out_vector_i = 0;
1584 while (in_global_eqn < sum_of_out_nrow[out_vector_i] ||
1585 in_global_eqn >= sum_of_out_nrow[out_vector_i + 1])
1592 unsigned out_global_eqn =
1593 in_global_eqn - sum_of_out_nrow[out_vector_i];
1597 out_vector_pt[out_vector_i]->distribution_pt()->rank_of_global_row(
1601 unsigned out_local_eqn =
1603 out_vector_pt[out_vector_i]->distribution_pt()->first_row(out_p);
1609 values_to_send[out_p].push_back(out_vector_i);
1612 values_to_send[out_p].push_back(out_local_eqn);
1615 values_to_send[out_p].push_back(in_vector[in_local_eqn]);
1631 unsigned total_ndata = 0;
1632 for (
unsigned rank = 0; rank < nproc; rank++)
1634 if (rank != my_rank)
1636 total_ndata += values_to_send[rank].size();
1643 send_values_data.reserve(total_ndata);
1646 for (
unsigned rank = 0; rank < nproc; rank++)
1649 send_displacement[rank] = send_values_data.size();
1653 if (rank != my_rank)
1656 unsigned n_data = values_to_send[rank].size();
1657 for (
unsigned j = 0; j < n_data; j++)
1659 send_values_data.push_back(values_to_send[rank][j]);
1664 send_n[rank] = send_values_data.size() - send_displacement[rank];
1669 MPI_Alltoall(&send_n[0],
1675 comm_pt->mpi_comm());
1680 int receive_data_count = 0;
1681 for (
unsigned rank = 0; rank < nproc; rank++)
1683 receive_displacement[rank] = receive_data_count;
1684 receive_data_count += receive_n[rank];
1689 if (receive_data_count == 0)
1691 receive_data_count++;
1697 if (send_values_data.size() == 0)
1699 send_values_data.resize(1);
1703 MPI_Alltoallv(&send_values_data[0],
1705 &send_displacement[0],
1707 &receive_values_data[0],
1709 &receive_displacement[0],
1711 comm_pt->mpi_comm());
1720 unsigned location_i = 0;
1722 unsigned my_values_to_send_size = values_to_send[my_rank].size();
1723 while (location_i < my_values_to_send_size)
1726 unsigned out_vector_i =
1727 unsigned(values_to_send[my_rank][location_i++]);
1730 unsigned out_local_eqn =
1731 unsigned(values_to_send[my_rank][location_i++]);
1734 double out_value = values_to_send[my_rank][location_i++];
1737 (*out_vector_pt[out_vector_i])[out_local_eqn] = out_value;
1744 bool data_has_been_received =
false;
1745 unsigned send_rank = 0;
1746 while (send_rank < nproc)
1748 if (receive_n[send_rank] > 0)
1750 data_has_been_received =
true;
1759 if (data_has_been_received)
1762 unsigned receive_values_data_size = receive_values_data.size();
1763 while (location_i < receive_values_data_size)
1766 unsigned out_vector_i = unsigned(receive_values_data[location_i++]);
1769 unsigned out_local_eqn =
1770 unsigned(receive_values_data[location_i++]);
1773 double out_value = receive_values_data[location_i++];
1776 (*out_vector_pt[out_vector_i])[out_local_eqn] = out_value;
1781 std::ostringstream error_message;
1782 error_message <<
"You have a distributed vector but with no mpi...\n"
1783 <<
"I don't know what to do :( \n";
1785 error_message.str(),
"RYARAYERR", OOMPH_EXCEPTION_LOCATION);
1807 const unsigned n_out_vector = out_vector.size();
1810 for (
unsigned i = 0;
i < n_out_vector;
i++)
1812 out_vector_pt[
i] = &out_vector[
i];
1860 unsigned nvectors = in_vector_pt.size();
1867 std::ostringstream error_message;
1868 error_message <<
"There is no vector to concatenate...\n"
1869 <<
"Perhaps you forgot to fill in_vector_pt?\n";
1871 OOMPH_CURRENT_FUNCTION,
1872 OOMPH_EXCEPTION_LOCATION);
1878 std::ostringstream warning_message;
1879 warning_message <<
"There is only one vector to concatenate...\n"
1880 <<
"This does not require concatenating...\n";
1882 OOMPH_CURRENT_FUNCTION,
1883 OOMPH_EXCEPTION_LOCATION);
1887 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1889 if (!in_vector_pt[vec_i]->built())
1891 std::ostringstream error_message;
1892 error_message <<
"The vector in position " << vec_i
1893 <<
" is not built.\n"
1894 <<
"I cannot concatenate an unbuilt vector.\n";
1896 OOMPH_CURRENT_FUNCTION,
1897 OOMPH_EXCEPTION_LOCATION);
1903 if (!out_vector.
built())
1906 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1908 in_distribution_pt[vec_i] = in_vector_pt[vec_i]->distribution_pt();
1914 out_vector.
build(tmp_distribution, 0.0);
1925 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1929 *(in_vector_pt[vec_i]->distribution_pt()->communicator_pt());
1931 if (out_comm != in_comm)
1933 std::ostringstream error_message;
1934 error_message <<
"The vector in position " << vec_i <<
" has a\n"
1935 <<
"different communicator from the out vector.\n";
1937 OOMPH_CURRENT_FUNCTION,
1938 OOMPH_EXCEPTION_LOCATION);
1943 if (out_comm.nproc() > 1)
1945 const bool out_distributed = out_vector.
distributed();
1946 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1948 if (out_distributed != in_vector_pt[vec_i]->distributed())
1950 std::ostringstream error_message;
1951 error_message <<
"The vector in position " << vec_i <<
" has a\n"
1952 <<
"different distributed boolean from the "
1955 OOMPH_CURRENT_FUNCTION,
1956 OOMPH_EXCEPTION_LOCATION);
1969 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
1971 in_distribution_pt[vec_i] = in_vector_pt[vec_i]->distribution_pt();
1982 if (tmp_distribution != out_distribution)
1984 std::ostringstream error_message;
1985 error_message <<
"The distribution of the out vector is not correct.\n"
1986 <<
"Please call the function with a cleared out vector,\n"
1987 <<
"or compare the distribution of the out vector with\n"
1988 <<
"the distribution created by\n"
1989 <<
"LinearAlgebraDistributionHelpers::concatenate(...)\n";
1991 OOMPH_CURRENT_FUNCTION,
1992 OOMPH_EXCEPTION_LOCATION);
1996 tmp_distribution.
clear();
1997 out_distribution.
clear();
2001 unsigned out_value_offset = 0;
2003 double* out_value_pt = out_vector.
values_pt();
2006 for (
unsigned vec_i = 0; vec_i < nvectors; vec_i++)
2010 unsigned in_vector_nrow_local = in_vector_pt[vec_i]->nrow_local();
2011 double* in_vector_value_pt = in_vector_pt[vec_i]->values_pt();
2014 for (
unsigned val_i = 0; val_i < in_vector_nrow_local; val_i++)
2016 out_value_pt[out_value_offset + val_i] = in_vector_value_pt[val_i];
2020 out_value_offset += in_vector_nrow_local;
2042 const unsigned n_in_vector = in_vector.size();
2046 for (
unsigned i = 0;
i < n_in_vector;
i++)
2048 in_vector_pt[
i] = &in_vector[
i];
2079 unsigned nvec = out_vector_pt.size();
2083 if (!in_vector.
built())
2085 std::ostringstream error_message;
2086 error_message <<
"The in_vector is not built.\n"
2087 <<
"Please build it!.\n";
2089 OOMPH_CURRENT_FUNCTION,
2090 OOMPH_EXCEPTION_LOCATION);
2094 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
2096 if (!out_vector_pt[vec_i]->built())
2098 std::ostringstream error_message;
2099 error_message <<
"The vector at position " << vec_i
2100 <<
" is not built.\n"
2101 <<
"Please build it!.\n";
2103 OOMPH_CURRENT_FUNCTION,
2104 OOMPH_EXCEPTION_LOCATION);
2113 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
2115 tmp_out_distribution_pt[vec_i] =
2116 out_vector_pt[vec_i]->distribution_pt();
2125 std::ostringstream error_message;
2126 error_message <<
"The distribution from the in vector is incorrect.\n"
2127 <<
"It must be a concatenation of all the distributions\n"
2128 <<
"from the out vectors.\n";
2130 OOMPH_CURRENT_FUNCTION,
2131 OOMPH_EXCEPTION_LOCATION);
2135 tmp_distribution.
clear();
2142 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
2145 *(out_vector_pt[vec_i]->distribution_pt()->communicator_pt());
2147 if (in_vector_comm != vec_i_comm)
2149 std::ostringstream error_message;
2150 error_message <<
"The communicator for the vector in position\n"
2151 << vec_i <<
" is not the same as the in_vector\n"
2154 OOMPH_CURRENT_FUNCTION,
2155 OOMPH_EXCEPTION_LOCATION);
2161 if (in_vector_comm.nproc() > 1)
2164 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
2166 if (in_distributed != out_vector_pt[vec_i]->distributed())
2168 std::ostringstream error_message;
2169 error_message <<
"The vector in position " << vec_i
2170 <<
" does not have\n"
2171 <<
"the same distributed boolean as the in vector";
2173 OOMPH_CURRENT_FUNCTION,
2174 OOMPH_EXCEPTION_LOCATION);
2182 double* in_value_pt = in_vector.
values_pt();
2183 unsigned in_value_offset = 0;
2184 for (
unsigned vec_i = 0; vec_i < nvec; vec_i++)
2187 unsigned out_nrow_local = out_vector_pt[vec_i]->nrow_local();
2188 double* out_value_pt = out_vector_pt[vec_i]->values_pt();
2191 for (
unsigned val_i = 0; val_i < out_nrow_local; val_i++)
2193 out_value_pt[val_i] = in_value_pt[in_value_offset + val_i];
2197 in_value_offset += out_nrow_local;
2219 const unsigned n_out_vector = out_vector.size();
2223 for (
unsigned i = 0;
i < n_out_vector;
i++)
2225 out_vector_pt[
i] = &out_vector[
i];
A class for compressed row matrices. This is a distributable object.
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
bool built() const
access function to the Built flag - indicates whether the matrix has been build - i....
bool distributed() const
distribution is serial or distributed
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
unsigned nrow() const
access function to the number of global rows.
bool distribution_built() const
if the communicator_pt is null then the distribution is not setup then false is returned,...
unsigned nrow_local() const
access function for the num of local rows on this processor.
unsigned first_row() const
access function for the first row on this processor
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....
void initialise(const double &v)
initialise the whole vector with value v
void operator+=(const DoubleVector &v)
+= operator with another vector
void output_local_values(std::ostream &outfile, const int &output_precision=-1) const
output the local contents of the vector
double max() const
returns the maximum coefficient
bool operator==(const DoubleVector &v)
== operator
void operator*=(const double &d)
multiply by a double
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
double * values_pt()
access function to the underlying values
void redistribute(const LinearAlgebraDistribution *const &dist_pt)
The contents of the vector are redistributed to match the new distribution. In a non-MPI rebuild this...
double norm() const
compute the 2 norm of this vector
bool Internal_values
Boolean flag to indicate whether the vector's data (values_pt) is owned by this vector.
void output(std::ostream &outfile, const int &output_precision=-1) const
output the global contents of the vector
void operator-=(const DoubleVector &v)
-= operator with another vector
void operator/=(const double &d)
divide by a double
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 clear()
wipes the DoubleVector
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...
bool distributed() const
access function to the distributed - indicates whether the distribution is serial or distributed
unsigned first_row() const
access function for the first row on this processor. If not distributed then this is just zero.
OomphCommunicator * communicator_pt() const
const access to the communicator pointer
bool built() const
if the communicator_pt is null then the distribution is not setup then false is returned,...
unsigned nrow() const
access function to the number of global rows.
void clear()
clears the distribution
unsigned nrow_local() const
access function for the num of local rows on this processor. If no MPI then Nrow is returned.
unsigned rank_of_global_row(const unsigned i) const
return the processor rank of the global row number i
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
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,...
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...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
std::ostream & operator<<(std::ostream &out, const DoubleVector &v)
output operator