56 OOMPH_CURRENT_FUNCTION,
57 OOMPH_EXCEPTION_LOCATION);
80 OOMPH_CURRENT_FUNCTION,
81 OOMPH_EXCEPTION_LOCATION);
98 OOMPH_CURRENT_FUNCTION,
99 OOMPH_EXCEPTION_LOCATION);
122 OOMPH_CURRENT_FUNCTION,
123 OOMPH_EXCEPTION_LOCATION);
160 const unsigned long& m)
172 const unsigned long& m,
173 const double& initial_val)
232 "This matrix is not square, the matrix MUST be square!",
233 OOMPH_CURRENT_FUNCTION,
234 OOMPH_EXCEPTION_LOCATION);
241 if (eigen_vals.size() !=
N)
243 eigen_vals.resize(
N);
245 if (eigen_vect.
ncol() !=
N || eigen_vect.
nrow() !=
N)
251 for (
unsigned long i = 0;
i <
N;
i++)
253 for (
unsigned long j = 0; j <
M; j++)
259 "Matrix needs to be symmetric for eigenvalues_by_jacobi()",
260 OOMPH_CURRENT_FUNCTION,
261 OOMPH_EXCEPTION_LOCATION);
264 working_matrix(
i, j) = (*this)(
i, j);
270 throw OomphLibError(
"Sorry JacobiEigenSolver::jacobi() removed because of "
271 "licencing problems.",
272 OOMPH_CURRENT_FUNCTION,
273 OOMPH_EXCEPTION_LOCATION);
281 for (
unsigned long i = 0;
i <
N;
i++)
283 for (
unsigned long j = 0; j <
M; j++)
285 eigen_vect(
i, j) = aux_eigen_vect(j,
i);
299 if (x.
nrow() != this->ncol())
301 std::ostringstream error_message_stream;
302 error_message_stream <<
"The x vector is not the right size. It is "
303 << x.
nrow() <<
", it should be " << this->
ncol()
306 OOMPH_CURRENT_FUNCTION,
307 OOMPH_EXCEPTION_LOCATION);
312 std::ostringstream error_message_stream;
314 <<
"The x vector cannot be distributed for DenseDoubleMatrix "
315 <<
"matrix-vector multiply" << std::endl;
317 OOMPH_CURRENT_FUNCTION,
318 OOMPH_EXCEPTION_LOCATION);
326 std::ostringstream error_message_stream;
328 <<
"The x vector cannot be distributed for DenseDoubleMatrix "
329 <<
"matrix-vector multiply" << std::endl;
331 OOMPH_CURRENT_FUNCTION,
332 OOMPH_EXCEPTION_LOCATION);
334 if (soln.
nrow() != this->nrow())
336 std::ostringstream error_message_stream;
338 <<
"The soln vector is setup and therefore must have the same "
339 <<
"number of rows as the matrix";
341 OOMPH_CURRENT_FUNCTION,
342 OOMPH_EXCEPTION_LOCATION);
347 std::ostringstream error_message_stream;
349 <<
"The soln vector and the x vector must have the same communicator"
352 OOMPH_CURRENT_FUNCTION,
353 OOMPH_EXCEPTION_LOCATION);
363 soln.
build(&dist, 0.0);
372 for (
unsigned long i = 0;
i <
N;
i++)
374 for (
unsigned long j = 0; j <
M; j++)
390 if (x.
nrow() != this->nrow())
392 std::ostringstream error_message_stream;
393 error_message_stream <<
"The x vector is not the right size. It is "
394 << x.
nrow() <<
", it should be " << this->
nrow()
397 OOMPH_CURRENT_FUNCTION,
398 OOMPH_EXCEPTION_LOCATION);
403 std::ostringstream error_message_stream;
405 <<
"The x vector cannot be distributed for DenseDoubleMatrix "
406 <<
"matrix-vector multiply" << std::endl;
408 OOMPH_CURRENT_FUNCTION,
409 OOMPH_EXCEPTION_LOCATION);
417 std::ostringstream error_message_stream;
419 <<
"The x vector cannot be distributed for DenseDoubleMatrix "
420 <<
"matrix-vector multiply" << std::endl;
422 OOMPH_CURRENT_FUNCTION,
423 OOMPH_EXCEPTION_LOCATION);
425 if (soln.
nrow() != this->ncol())
427 std::ostringstream error_message_stream;
429 <<
"The soln vector is setup and therefore must have the same "
430 <<
"number of columns as the matrix";
432 OOMPH_CURRENT_FUNCTION,
433 OOMPH_EXCEPTION_LOCATION);
438 std::ostringstream error_message_stream;
440 <<
"The soln vector and the x vector must have the same communicator"
443 OOMPH_CURRENT_FUNCTION,
444 OOMPH_EXCEPTION_LOCATION);
454 soln.
build(dist_pt, 0.0);
464 for (
unsigned long i = 0;
i <
N;
i++)
466 for (
unsigned long j = 0; j <
M; j++)
489 for (
unsigned i = 0;
i <
N;
i++)
495 for (
unsigned long j = 0; j <
M; j++)
505 for (
unsigned long j = 0; j <
M; j++)
509 if (
i == j || std::fabs(
Matrixdata[
M *
i + j]) > alpha * max_row)
526 if (this->
ncol() != matrix_in.
nrow())
528 std::ostringstream error_message;
530 <<
"Matrix dimensions incompatable for matrix-matrix multiplication"
531 <<
"ncol() for first matrix:" << this->
ncol()
532 <<
"nrow() for second matrix: " << matrix_in.
nrow();
535 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
540 unsigned long n_row = this->
nrow();
541 unsigned long m_col = matrix_in.
ncol();
544 result.
resize(n_row, m_col, 0.0);
549 unsigned long n_col = this->
ncol();
550 for (
unsigned long k = 0; k < n_col; k++)
552 for (
unsigned long i = 0;
i < n_row;
i++)
554 for (
unsigned long j = 0; j < m_col; j++)
556 result(
i, j) +=
Matrixdata[m_col *
i + k] * matrix_in(k, j);
588 const unsigned long& n,
589 const unsigned long& m)
590 :
CCMatrix<double>(value, row_index, column_start, n, m)
626 if (x.
nrow() != this->ncol())
628 std::ostringstream error_message_stream;
629 error_message_stream <<
"The x vector is not the right size. It is "
630 << x.
nrow() <<
", it should be " << this->
ncol()
633 OOMPH_CURRENT_FUNCTION,
634 OOMPH_EXCEPTION_LOCATION);
639 std::ostringstream error_message_stream;
641 <<
"The x vector cannot be distributed for CCDoubleMatrix "
642 <<
"matrix-vector multiply" << std::endl;
644 OOMPH_CURRENT_FUNCTION,
645 OOMPH_EXCEPTION_LOCATION);
653 std::ostringstream error_message_stream;
655 <<
"The x vector cannot be distributed for CCDoubleMatrix "
656 <<
"matrix-vector multiply" << std::endl;
658 OOMPH_CURRENT_FUNCTION,
659 OOMPH_EXCEPTION_LOCATION);
661 if (soln.
nrow() != this->nrow())
663 std::ostringstream error_message_stream;
665 <<
"The soln vector is setup and therefore must have the same "
666 <<
"number of rows as the matrix";
668 OOMPH_CURRENT_FUNCTION,
669 OOMPH_EXCEPTION_LOCATION);
674 std::ostringstream error_message_stream;
676 <<
"The soln vector and the x vector must have the same communicator"
679 OOMPH_CURRENT_FUNCTION,
680 OOMPH_EXCEPTION_LOCATION);
690 soln.
build(dist_pt, 0.0);
700 for (
unsigned long j = 0; j <
N; j++)
705 double a_ij =
Value[k];
706 soln_pt[
i] += a_ij * x_pt[j];
720 if (x.
nrow() != this->nrow())
722 std::ostringstream error_message_stream;
723 error_message_stream <<
"The x vector is not the right size. It is "
724 << x.
nrow() <<
", it should be " << this->
nrow()
727 OOMPH_CURRENT_FUNCTION,
728 OOMPH_EXCEPTION_LOCATION);
733 std::ostringstream error_message_stream;
735 <<
"The x vector cannot be distributed for CCDoubleMatrix "
736 <<
"matrix-vector multiply" << std::endl;
738 OOMPH_CURRENT_FUNCTION,
739 OOMPH_EXCEPTION_LOCATION);
747 std::ostringstream error_message_stream;
749 <<
"The x vector cannot be distributed for CCDoubleMatrix "
750 <<
"matrix-vector multiply" << std::endl;
752 OOMPH_CURRENT_FUNCTION,
753 OOMPH_EXCEPTION_LOCATION);
755 if (soln.
nrow() != this->ncol())
757 std::ostringstream error_message_stream;
759 <<
"The soln vector is setup and therefore must have the same "
760 <<
"number of columns as the matrix";
762 OOMPH_CURRENT_FUNCTION,
763 OOMPH_EXCEPTION_LOCATION);
768 std::ostringstream error_message_stream;
770 <<
"The soln vector and the x vector must have the same communicator"
773 OOMPH_CURRENT_FUNCTION,
774 OOMPH_EXCEPTION_LOCATION);
784 soln.
build(dist_pt, 0.0);
794 for (
unsigned long i = 0;
i <
N;
i++)
799 double a_ij =
Value[k];
800 soln_pt[j] += a_ij * x_pt[
i];
826 if (this->
ncol() != matrix_in.
nrow())
828 std::ostringstream error_message;
830 <<
"Matrix dimensions incompatable for matrix-matrix multiplication"
831 <<
"ncol() for first matrix:" << this->
ncol()
832 <<
"nrow() for second matrix: " << matrix_in.
nrow();
835 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
840 unsigned long N = this->
nrow();
841 unsigned long M = matrix_in.
ncol();
842 unsigned long Nnz = 0;
850 const int* matrix_in_col_start = matrix_in.
column_start();
851 const int* matrix_in_row_index = matrix_in.
row_index();
852 const double* matrix_in_value = matrix_in.
value();
855 const double* this_value = this->
value();
857 const int* this_row_index = this->
row_index();
873 std::set<unsigned> rows;
877 for (
unsigned long this_col = 0; this_col <
M; this_col++)
880 for (
int this_ptr = this_col_start[this_col];
881 this_ptr < this_col_start[this_col + 1];
885 unsigned matrix_in_col = this_row_index[this_ptr];
888 for (
int matrix_in_ptr = matrix_in_col_start[matrix_in_col];
889 matrix_in_ptr < matrix_in_col_start[matrix_in_col + 1];
893 rows.insert(matrix_in_row_index[matrix_in_ptr]);
914 for (
unsigned long this_col = 0; this_col <
M; this_col++)
917 for (
int this_ptr = this_col_start[this_col];
918 this_ptr < this_col_start[this_col + 1];
922 double this_val = this_value[this_ptr];
925 unsigned matrix_in_col = this_row_index[this_ptr];
928 for (
int matrix_in_ptr = matrix_in_col_start[matrix_in_col];
929 matrix_in_ptr < matrix_in_col_start[matrix_in_col + 1];
933 int row = matrix_in_row_index[matrix_in_ptr];
944 std::ostringstream error_message;
945 error_message <<
"Error inserting value in result";
948 OOMPH_CURRENT_FUNCTION,
949 OOMPH_EXCEPTION_LOCATION);
955 Value[ptr] = this_val * matrix_in_value[matrix_in_ptr];
961 Value[ptr] += this_val * matrix_in_value[matrix_in_ptr];
972 else if (method == 2)
975 std::map<int, double>* result_maps =
new std::map<int, double>[
M];
978 for (
unsigned long this_col = 0; this_col <
M; this_col++)
981 for (
int this_ptr = this_col_start[this_col];
982 this_ptr < this_col_start[this_col + 1];
986 double this_val = this_value[this_ptr];
989 unsigned matrix_in_col = this_row_index[this_ptr];
992 for (
int matrix_in_ptr = matrix_in_col_start[matrix_in_col];
993 matrix_in_ptr < matrix_in_col_start[matrix_in_col + 1];
997 int row = matrix_in_row_index[matrix_in_ptr];
1000 result_maps[this_col][row] +=
1001 this_val * matrix_in_value[matrix_in_ptr];
1011 for (
unsigned long col = 0; col <
M; col++)
1013 int size = result_maps[col].size();
1025 for (
unsigned long col = 0; col <
M; col++)
1028 for (std::map<int, double>::iterator
i = result_maps[col].begin();
1029 i != result_maps[col].end();
1039 delete[] result_maps;
1044 else if (method == 3)
1047 std::vector<std::vector<int>> result_rows(
N);
1048 std::vector<std::vector<double>> result_vals(
N);
1051 for (
unsigned long this_col = 0; this_col <
M; this_col++)
1054 for (
int this_ptr = this_col_start[this_col];
1055 this_ptr < this_col_start[this_col + 1];
1059 double this_val = this_value[this_ptr];
1062 unsigned matrix_in_col = this_row_index[this_ptr];
1065 for (
int matrix_in_ptr = matrix_in_col_start[matrix_in_col];
1066 matrix_in_ptr < matrix_in_col_start[matrix_in_col + 1];
1070 int row = matrix_in_row_index[matrix_in_ptr];
1073 int size = result_rows[this_col].size();
1074 for (
int i = 0;
i <= size;
i++)
1079 result_rows[this_col].push_back(row);
1080 result_vals[this_col].push_back(this_val *
1081 matrix_in_value[matrix_in_ptr]);
1083 else if (row == result_rows[this_col][
i])
1086 result_vals[this_col][
i] +=
1087 this_val * matrix_in_value[matrix_in_ptr];
1100 for (
unsigned long col = 0; col <
M; col++)
1102 int size = result_rows[col].size();
1114 for (
unsigned long col = 0; col <
N; col++)
1117 unsigned n_rows = result_rows[col].size();
1118 for (
unsigned i = 0;
i < n_rows;
i++)
1121 Value[ptr] = result_vals[col][
i];
1130 std::ostringstream error_message;
1131 error_message <<
"Incorrect method set in matrix-matrix multiply"
1132 <<
"method=" << method <<
" not allowed";
1135 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1153 long n_coln =
ncol();
1170 for (
long i = 0;
i < n_coln;
i++)
1190 B_value.push_back(
Value[j]);
1197 B_row_start.push_back(k);
1203 .
build(B_value, B_column_index, B_row_start,
nrow(),
ncol());
1223 #ifdef OOMPH_HAS_TRILINOS
1240 const double* values_pt = other_matrix.
value();
1241 const int* column_indices = other_matrix.
column_index();
1245 const unsigned nnz = other_matrix.
nnz();
1252 double* my_values_pt =
new double[
nnz];
1253 int* my_column_indices =
new int[
nnz];
1257 std::copy(values_pt, values_pt +
nnz, my_values_pt);
1258 std::copy(column_indices, column_indices +
nnz, my_column_indices);
1264 other_matrix.
ncol(),
nnz, my_values_pt, my_column_indices, my_row_start);
1273 #ifdef OOMPH_HAS_TRILINOS
1298 #ifdef OOMPH_HAS_TRILINOS
1312 const unsigned& ncol,
1328 #ifdef OOMPH_HAS_TRILINOS
1367 const bool& doc_unordered_entries)
const
1369 #ifdef OOMPH_HAS_MPI
1374 std::ostringstream warning_message;
1377 warning_message <<
"This method currently works for serial but "
1378 <<
"has not been implemented for use with MPI!\n";
1382 OOMPH_CURRENT_FUNCTION,
1383 OOMPH_EXCEPTION_LOCATION);
1388 unsigned n_rows = this->
nrow();
1394 const int* row_start_pt = this->
row_start();
1397 for (
unsigned i = 0;
i < n_rows;
i++)
1400 unsigned nnz_row_i = *(row_start_pt +
i + 1) - *(row_start_pt +
i);
1403 unsigned i_row_start = *(row_start_pt +
i);
1406 for (
unsigned j = 0; j < nnz_row_i - 1; j++)
1410 if ((*(column_index_pt + i_row_start + j + 1)) <
1411 (*(column_index_pt + i_row_start + j)))
1415 if (doc_unordered_entries)
1418 oomph_info <<
"Matrix has not been correctly sorted!"
1419 <<
"\nOn row: " <<
i <<
"\nEntry: " << j
1420 <<
"\nEntry 1 = " << *(column_index_pt + i_row_start + j)
1422 << *(column_index_pt + i_row_start + j + 1) << std::endl;
1451 #ifdef OOMPH_HAS_MPI
1456 std::ostringstream warning_message;
1459 warning_message <<
"This method currently works for serial but "
1460 <<
"has not been tested with MPI!\n";
1464 OOMPH_CURRENT_FUNCTION,
1465 OOMPH_EXCEPTION_LOCATION);
1470 unsigned n_rows = this->
nrow();
1475 double* value_pt = this->
value();
1477 const int* row_start_pt = this->
row_start();
1487 for (
unsigned i = 0;
i < n_rows;
i++)
1490 unsigned nnz_row_i = *(row_start_pt +
i + 1) - *(row_start_pt +
i);
1493 unsigned i_row_start = *(row_start_pt +
i);
1507 column_index_and_value_row_i.resize(nnz_row_i);
1510 for (
unsigned j = 0; j < nnz_row_i; j++)
1513 column_index_and_value_row_i[j] =
1514 std::make_pair(*(column_index_pt + i_row_start + j),
1515 *(value_pt + i_row_start + j));
1520 std::sort(column_index_and_value_row_i.begin(),
1521 column_index_and_value_row_i.end(),
1531 bool is_ith_entry_set =
false;
1535 for (
unsigned j = 0; j < nnz_row_i; j++)
1539 *(column_index_pt + i_row_start + j) =
1540 column_index_and_value_row_i[j].first;
1544 *(value_pt + i_row_start + j) =
1545 column_index_and_value_row_i[j].second;
1549 if (!is_ith_entry_set)
1553 if (
unsigned(*(column_index_pt + i_row_start)) >
i)
1563 is_ith_entry_set =
true;
1580 is_ith_entry_set =
true;
1615 else if (
unsigned(*(column_index_pt + i_row_start + j)) ==
i)
1623 is_ith_entry_set =
true;
1626 else if (
unsigned(*(column_index_pt + i_row_start + j)) >
i)
1634 is_ith_entry_set =
true;
1637 else if (j == nnz_row_i - 1)
1645 is_ith_entry_set =
true;
1673 const unsigned& ncol,
1711 const unsigned& nnz,
1734 std::ostringstream error_message_stream;
1735 error_message_stream <<
"This matrix has not been built.";
1737 OOMPH_CURRENT_FUNCTION,
1738 OOMPH_EXCEPTION_LOCATION);
1755 std::ostringstream error_message_stream;
1756 error_message_stream <<
"The vector rhs has not been setup";
1758 OOMPH_CURRENT_FUNCTION,
1759 OOMPH_EXCEPTION_LOCATION);
1764 std::ostringstream error_message_stream;
1765 error_message_stream
1766 <<
"The vector rhs must have the same distribution as the matrix";
1768 OOMPH_CURRENT_FUNCTION,
1769 OOMPH_EXCEPTION_LOCATION);
1776 ->backsub(rhs_copy, rhs);
1788 std::ostringstream error_message_stream;
1789 error_message_stream <<
"This matrix has not been built";
1791 OOMPH_CURRENT_FUNCTION,
1792 OOMPH_EXCEPTION_LOCATION);
1797 std::ostringstream error_message_stream;
1798 error_message_stream <<
"The distribution of the vector x must be setup";
1800 OOMPH_CURRENT_FUNCTION,
1801 OOMPH_EXCEPTION_LOCATION);
1806 std::ostringstream error_message_stream;
1807 error_message_stream <<
"The number of rows in the x vector and the "
1808 "number of columns in the "
1809 <<
"matrix must be the same";
1811 OOMPH_CURRENT_FUNCTION,
1812 OOMPH_EXCEPTION_LOCATION);
1819 std::ostringstream error_message_stream;
1820 error_message_stream
1821 <<
"The soln vector is setup and therefore must have the same "
1822 <<
"distribution as the matrix";
1824 OOMPH_CURRENT_FUNCTION,
1825 OOMPH_EXCEPTION_LOCATION);
1845 #ifdef OOMPH_HAS_TRILINOS
1849 std::ostringstream error_message_stream;
1850 error_message_stream
1851 <<
"Matrix-vector product on multiple processors with distributed "
1852 <<
"CRDoubleMatrix requires Trilinos.";
1854 OOMPH_CURRENT_FUNCTION,
1855 OOMPH_EXCEPTION_LOCATION);
1860 unsigned n = this->
nrow();
1866 for (
unsigned long i = 0;
i < n;
i++)
1872 double a_ij =
value[k];
1873 soln_pt[
i] += a_ij * x_pt[j];
1889 std::ostringstream error_message_stream;
1890 error_message_stream <<
"This matrix has not been built";
1892 OOMPH_CURRENT_FUNCTION,
1893 OOMPH_EXCEPTION_LOCATION);
1898 std::ostringstream error_message_stream;
1899 error_message_stream
1900 <<
"The x vector and this matrix must have the same distribution.";
1902 OOMPH_CURRENT_FUNCTION,
1903 OOMPH_EXCEPTION_LOCATION);
1910 std::ostringstream error_message_stream;
1911 error_message_stream
1912 <<
"The soln vector is setup and therefore must have the same "
1913 <<
"number of rows as the vector x";
1915 OOMPH_CURRENT_FUNCTION,
1916 OOMPH_EXCEPTION_LOCATION);
1927 this->distributed());
1928 soln.
build(dist_pt, 0.0);
1938 #ifdef OOMPH_HAS_TRILINOS
1942 std::ostringstream error_message_stream;
1943 error_message_stream
1944 <<
"Matrix-vector product on multiple processors with distributed "
1945 <<
"CRDoubleMatrix requires Trilinos.";
1947 OOMPH_CURRENT_FUNCTION,
1948 OOMPH_EXCEPTION_LOCATION);
1953 unsigned n = this->
nrow();
1960 for (
unsigned long i = 0;
i < n;
i++)
1965 double a_ij =
value[k];
1966 soln_pt[j] += a_ij * x_pt[
i];
1999 std::ostringstream error_message_stream;
2000 error_message_stream <<
"This matrix has not been built";
2002 OOMPH_CURRENT_FUNCTION,
2003 OOMPH_EXCEPTION_LOCATION);
2006 if (!matrix_in.
built())
2008 std::ostringstream error_message_stream;
2009 error_message_stream <<
"This matrix matrix_in has not been built";
2011 OOMPH_CURRENT_FUNCTION,
2012 OOMPH_EXCEPTION_LOCATION);
2019 std::ostringstream error_message_stream;
2020 error_message_stream
2021 <<
"The matrix result is setup and therefore must have the same "
2022 <<
"distribution as the vector x";
2024 OOMPH_CURRENT_FUNCTION,
2025 OOMPH_EXCEPTION_LOCATION);
2041 ((method == 1) || (method == 2) || (method == 3)))
2044 unsigned long N = this->
nrow();
2045 unsigned long M = matrix_in.
ncol();
2046 unsigned long Nnz = 0;
2051 int* Column_index = 0;
2054 const int* matrix_in_row_start = matrix_in.
row_start();
2055 const int* matrix_in_column_index = matrix_in.
column_index();
2056 const double* matrix_in_value = matrix_in.
value();
2059 const double* this_value = this->
value();
2060 const int* this_row_start = this->
row_start();
2070 Row_start =
new int[
N + 1];
2074 std::set<unsigned> columns;
2078 for (
unsigned long this_row = 0; this_row <
N; this_row++)
2081 for (
int this_ptr = this_row_start[this_row];
2082 this_ptr < this_row_start[this_row + 1];
2086 int matrix_in_row = this_column_index[this_ptr];
2089 for (
int matrix_in_ptr = matrix_in_row_start[matrix_in_row];
2090 matrix_in_ptr < matrix_in_row_start[matrix_in_row + 1];
2095 columns.insert(matrix_in_column_index[matrix_in_ptr]);
2099 Row_start[this_row + 1] = Row_start[this_row] + columns.size();
2109 Value =
new double[Nnz];
2110 Column_index =
new int[Nnz];
2113 for (
unsigned long i = 0;
i < Nnz;
i++)
2115 Column_index[
i] = -1;
2119 for (
unsigned long this_row = 0; this_row <
N; this_row++)
2122 for (
int this_ptr = this_row_start[this_row];
2123 this_ptr < this_row_start[this_row + 1];
2127 double this_val = this_value[this_ptr];
2130 int matrix_in_row = this_column_index[this_ptr];
2133 for (
int matrix_in_ptr = matrix_in_row_start[matrix_in_row];
2134 matrix_in_ptr < matrix_in_row_start[matrix_in_row + 1];
2138 int col = matrix_in_column_index[matrix_in_ptr];
2141 for (
int ptr = Row_start[this_row];
2142 ptr <= Row_start[this_row + 1];
2145 if (ptr == Row_start[this_row + 1])
2149 std::ostringstream error_message;
2150 error_message <<
"Error inserting value in result";
2153 OOMPH_CURRENT_FUNCTION,
2154 OOMPH_EXCEPTION_LOCATION);
2156 else if (Column_index[ptr] == -1)
2159 Column_index[ptr] = col;
2160 Value[ptr] = this_val * matrix_in_value[matrix_in_ptr];
2163 else if (Column_index[ptr] == col)
2166 Value[ptr] += this_val * matrix_in_value[matrix_in_ptr];
2177 else if (method == 2)
2180 std::map<int, double>* result_maps =
new std::map<int, double>[
N];
2183 for (
unsigned long this_row = 0; this_row <
N; this_row++)
2186 for (
int this_ptr = this_row_start[this_row];
2187 this_ptr < this_row_start[this_row + 1];
2191 double this_val = this_value[this_ptr];
2194 int matrix_in_row = this_column_index[this_ptr];
2197 for (
int matrix_in_ptr = matrix_in_row_start[matrix_in_row];
2198 matrix_in_ptr < matrix_in_row_start[matrix_in_row + 1];
2202 int col = matrix_in_column_index[matrix_in_ptr];
2205 result_maps[this_row][col] +=
2206 this_val * matrix_in_value[matrix_in_ptr];
2212 Row_start =
new int[
N + 1];
2216 for (
unsigned long row = 0; row <
N; row++)
2218 int size = result_maps[row].size();
2219 Row_start[row + 1] = Row_start[row] + size;
2226 Value =
new double[Nnz];
2227 Column_index =
new int[Nnz];
2230 for (
unsigned long row = 0; row <
N; row++)
2232 unsigned ptr = Row_start[row];
2233 for (std::map<int, double>::iterator
i = result_maps[row].begin();
2234 i != result_maps[row].end();
2237 Column_index[ptr] =
i->first;
2238 Value[ptr] =
i->second;
2244 delete[] result_maps;
2249 else if (method == 3)
2252 std::vector<std::vector<int>> result_cols(
N);
2253 std::vector<std::vector<double>> result_vals(
N);
2256 for (
unsigned long this_row = 0; this_row <
N; this_row++)
2259 for (
int this_ptr = this_row_start[this_row];
2260 this_ptr < this_row_start[this_row + 1];
2264 double this_val = this_value[this_ptr];
2267 int matrix_in_row = this_column_index[this_ptr];
2270 for (
int matrix_in_ptr = matrix_in_row_start[matrix_in_row];
2271 matrix_in_ptr < matrix_in_row_start[matrix_in_row + 1];
2275 int col = matrix_in_column_index[matrix_in_ptr];
2278 int size = result_cols[this_row].size();
2279 for (
int i = 0;
i <= size;
i++)
2284 result_cols[this_row].push_back(col);
2285 result_vals[this_row].push_back(
2286 this_val * matrix_in_value[matrix_in_ptr]);
2288 else if (col == result_cols[this_row][
i])
2291 result_vals[this_row][
i] +=
2292 this_val * matrix_in_value[matrix_in_ptr];
2301 Row_start =
new int[
N + 1];
2305 for (
unsigned long row = 0; row <
N; row++)
2307 int size = result_cols[row].size();
2308 Row_start[row + 1] = Row_start[row] + size;
2315 Value =
new double[Nnz];
2316 Column_index =
new int[Nnz];
2319 for (
unsigned long row = 0; row <
N; row++)
2321 unsigned ptr = Row_start[row];
2322 unsigned nnn = result_cols[row].size();
2323 for (
unsigned i = 0;
i < nnn;
i++)
2325 Column_index[ptr] = result_cols[row][
i];
2326 Value[ptr] = result_vals[row][
i];
2339 #ifdef OOMPH_HAS_TRILINOS
2340 bool use_ml =
false;
2347 std::ostringstream error_message;
2348 error_message <<
"Serial_matrix_matrix_multiply_method = "
2350 <<
" requires trilinos.";
2352 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2389 for (
long i = 0;
i < n_row;
i++)
2398 if (std::fabs(
value[j]) > max_row)
2400 max_row = std::fabs(
value[j]);
2411 B_value.push_back(
value[j]);
2418 B_row_start.push_back(k);
2423 .
build(this->
ncol(), B_value, B_column_index, B_row_start);
2433 #ifdef OOMPH_HAS_MPI
2454 int* dist_nnz_pt =
new int[nproc];
2464 int* dist_first_row =
new int[nproc];
2465 int* dist_nrow_local =
new int[nproc];
2467 for (
int p = 0; p < nproc; p++)
2469 nnz_global += dist_nnz_pt[p];
2475 int* nnz_offset =
new int[nproc];
2477 for (
int p = 1; p < nproc; p++)
2479 nnz_offset[p] = nnz_offset[p - 1] + dist_nnz_pt[p - 1];
2485 int* dist_row_start =
const_cast<int*
>(this->
row_start());
2486 int* dist_column_index =
const_cast<int*
>(this->
column_index());
2487 double* dist_value =
const_cast<double*
>(this->
value());
2490 int* global_row_start =
new int[
nrow + 1];
2491 int* global_column_index =
new int[nnz_global];
2492 double* global_value =
new double[nnz_global];
2495 MPI_Allgatherv(dist_row_start,
2505 MPI_Allgatherv(dist_column_index,
2508 global_column_index,
2515 MPI_Allgatherv(dist_value,
2525 global_row_start[
nrow] = nnz_global;
2528 for (
int p = 0; p < nproc; p++)
2530 for (
int i = 0;
i < dist_nrow_local[p];
i++)
2532 unsigned j = dist_first_row[p] +
i;
2533 global_row_start[j] += nnz_offset[p];
2551 global_column_index,
2555 delete[] dist_first_row;
2556 delete[] dist_nrow_local;
2557 delete[] nnz_offset;
2558 delete[] dist_nnz_pt;
2578 #ifdef OOMPH_HAS_MPI
2582 if (dist_pt->
nrow() != this->distribution_pt()->nrow())
2584 std::ostringstream error_message;
2585 error_message <<
"The number of global rows in the new distribution ("
2586 << dist_pt->
nrow() <<
") is not equal to the number"
2587 <<
" of global rows in the current distribution ("
2590 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2597 std::ostringstream error_message;
2598 error_message <<
"The new distribution and the current distribution must "
2599 <<
"have the same communicator.";
2601 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2606 std::ostringstream error_message;
2607 error_message <<
"The matrix must be build to be redistributed";
2609 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2621 int* current_row_start = this->
row_start();
2623 double* current_value = this->
value();
2638 for (
int i = 0;
i < nproc;
i++)
2655 for (
int p = 0; p < nproc; p++)
2658 if ((new_first_row[p] <
2659 (current_first_row[my_rank] + current_nrow_local[my_rank])) &&
2660 (current_first_row[my_rank] <
2661 (new_first_row[p] + new_nrow_local[p])))
2663 first_row_for_proc[p] =
2664 std::max(current_first_row[my_rank], new_first_row[p]);
2665 nrow_local_for_proc[p] =
2667 (current_first_row[my_rank] + current_nrow_local[my_rank]),
2668 (new_first_row[p] + new_nrow_local[p])) -
2669 first_row_for_proc[p];
2673 if ((new_first_row[my_rank] <
2674 (current_first_row[p] + current_nrow_local[p])) &&
2675 (current_first_row[p] <
2676 (new_first_row[my_rank] + new_nrow_local[my_rank])))
2678 first_row_from_proc[p] =
2679 std::max(current_first_row[p], new_first_row[my_rank]);
2680 nrow_local_from_proc[p] =
2681 std::min((current_first_row[p] + current_nrow_local[p]),
2682 (new_first_row[my_rank] + new_nrow_local[my_rank])) -
2683 first_row_from_proc[p];
2689 for (
int p = 0; p < nproc; p++)
2691 if (nrow_local_for_proc[p] > 0)
2693 nnz_for_proc[p] = (current_row_start[first_row_for_proc[p] -
2694 current_first_row[my_rank] +
2695 nrow_local_for_proc[p]] -
2696 current_row_start[first_row_for_proc[p] -
2697 current_first_row[my_rank]]);
2705 for (
int p = 0; p < nproc; p++)
2710 if (nrow_local_for_proc[p] > 0)
2713 MPI_Isend(&nnz_for_proc[p],
2720 send_req.push_back(req);
2724 if (nrow_local_from_proc[p] > 0)
2727 MPI_Irecv(&nnz_from_proc[p],
2734 nnz_recv_req.push_back(req);
2740 nnz_from_proc[p] = nnz_for_proc[p];
2745 int* new_row_start =
new int[new_nrow_local[my_rank] + 1];
2748 unsigned n_recv_req = nnz_recv_req.size();
2752 MPI_Waitall(n_recv_req, &nnz_recv_req[0], &recv_status[0]);
2756 unsigned next_row = 0;
2757 unsigned nnz_count = 0;
2759 for (
int p = 0; p < nproc; p++)
2762 while (new_first_row[pp] != next_row)
2766 nnz_offset[pp] = nnz_count;
2767 nnz_count += nnz_from_proc[pp];
2768 next_row += new_nrow_local[pp];
2772 int* new_column_index =
new int[nnz_count];
2773 double* new_value =
new double[nnz_count];
2777 MPI_Aint base_address;
2778 MPI_Get_address(new_value, &base_address);
2779 for (
int p = 0; p < nproc; p++)
2785 if (nrow_local_for_proc[p] > 0)
2788 MPI_Datatype types[3];
2791 MPI_Aint offsets[3];
2797 unsigned first_row_to_send =
2798 first_row_for_proc[p] - current_first_row[my_rank];
2799 MPI_Type_contiguous(nrow_local_for_proc[p], MPI_INT, &types[0]);
2800 MPI_Type_commit(&types[0]);
2802 MPI_Get_address(current_row_start + first_row_to_send,
2804 offsets[0] -= base_address;
2807 unsigned first_coef_to_send =
2808 current_row_start[first_row_to_send];
2809 MPI_Type_contiguous(nnz_for_proc[p], MPI_DOUBLE, &types[1]);
2810 MPI_Type_commit(&types[1]);
2812 MPI_Get_address(current_value + first_coef_to_send, &offsets[1]);
2813 offsets[1] -= base_address;
2816 MPI_Type_contiguous(nnz_for_proc[p], MPI_DOUBLE, &types[2]);
2817 MPI_Type_commit(&types[2]);
2819 MPI_Get_address(current_column_index + first_coef_to_send,
2821 offsets[2] -= base_address;
2824 MPI_Datatype send_type;
2825 MPI_Type_create_struct(3, len, offsets, types, &send_type);
2826 MPI_Type_commit(&send_type);
2827 MPI_Type_free(&types[0]);
2828 MPI_Type_free(&types[1]);
2829 MPI_Type_free(&types[2]);
2833 MPI_Isend(new_value,
2840 send_req.push_back(req);
2841 MPI_Type_free(&send_type);
2845 if (nrow_local_from_proc[p] > 0)
2848 MPI_Datatype types[3];
2851 MPI_Aint offsets[3];
2857 unsigned first_row_to_recv =
2858 first_row_from_proc[p] - new_first_row[my_rank];
2859 MPI_Type_contiguous(nrow_local_from_proc[p], MPI_INT, &types[0]);
2860 MPI_Type_commit(&types[0]);
2862 MPI_Get_address(new_row_start + first_row_to_recv, &offsets[0]);
2863 offsets[0] -= base_address;
2866 unsigned first_coef_to_recv = nnz_offset[p];
2867 MPI_Type_contiguous(nnz_from_proc[p], MPI_DOUBLE, &types[1]);
2868 MPI_Type_commit(&types[1]);
2870 MPI_Get_address(new_value + first_coef_to_recv, &offsets[1]);
2871 offsets[1] -= base_address;
2874 MPI_Type_contiguous(nnz_from_proc[p], MPI_INT, &types[2]);
2875 MPI_Type_commit(&types[2]);
2877 MPI_Get_address(new_column_index + first_coef_to_recv,
2879 offsets[2] -= base_address;
2882 MPI_Datatype recv_type;
2883 MPI_Type_create_struct(3, len, offsets, types, &recv_type);
2884 MPI_Type_commit(&recv_type);
2885 MPI_Type_free(&types[0]);
2886 MPI_Type_free(&types[1]);
2887 MPI_Type_free(&types[2]);
2891 MPI_Irecv(new_value,
2898 recv_req.push_back(req);
2899 MPI_Type_free(&recv_type);
2906 first_row_for_proc[my_rank] - current_first_row[my_rank];
2907 unsigned k = first_row_from_proc[my_rank] - new_first_row[my_rank];
2908 for (
unsigned i = 0;
i < nrow_local_for_proc[my_rank];
i++)
2910 new_row_start[k +
i] = current_row_start[j +
i];
2912 unsigned first_coef_to_send = current_row_start[j];
2913 for (
unsigned i = 0;
i < nnz_for_proc[my_rank];
i++)
2915 new_value[nnz_offset[p] +
i] =
2916 current_value[first_coef_to_send +
i];
2917 new_column_index[nnz_offset[p] +
i] =
2918 current_column_index[first_coef_to_send +
i];
2924 n_recv_req = recv_req.size();
2928 MPI_Waitall(n_recv_req, &recv_req[0], &recv_status[0]);
2932 for (
int p = 0; p < nproc; p++)
2934 if (nrow_local_from_proc[p] > 0)
2937 first_row_from_proc[p] - new_first_row[my_rank];
2938 unsigned last_row =
first_row + nrow_local_from_proc[p] - 1;
2939 int update = nnz_offset[p] - new_row_start[
first_row];
2942 new_row_start[
i] += update;
2946 new_row_start[dist_pt->
nrow_local()] = nnz_count;
2949 unsigned n_send_req = send_req.size();
2953 MPI_Waitall(n_send_req, &send_req[0], &send_status[0]);
2962 this->
build(dist_pt);
2964 ncol, nnz_count, new_value, new_column_index, new_row_start);
2988 int* dist_nnz_pt =
new int[nproc];
2999 int* dist_first_row =
new int[nproc];
3000 int* dist_nrow_local =
new int[nproc];
3001 for (
int p = 0; p < nproc; p++)
3010 unsigned nnz_count = 0;
3012 for (
int p = 0; p < nproc; p++)
3015 while (dist_first_row[pp] != next_row)
3019 nnz_offset[pp] = nnz_count;
3020 nnz_count += dist_nnz_pt[pp];
3021 next_row += dist_nrow_local[pp];
3025 int* dist_row_start = this->
row_start();
3027 double* dist_value = this->
value();
3030 int* global_row_start =
new int[
nrow + 1];
3031 int* global_column_index =
new int[nnz_count];
3032 double* global_value =
new double[nnz_count];
3037 MPI_Aint base_address;
3038 MPI_Get_address(global_value, &base_address);
3041 if (dist_nrow_local[my_rank] > 0)
3044 MPI_Datatype types[3];
3047 MPI_Aint offsets[3];
3053 MPI_Type_contiguous(dist_nrow_local[my_rank], MPI_INT, &types[0]);
3054 MPI_Type_commit(&types[0]);
3055 MPI_Get_address(dist_row_start, &offsets[0]);
3056 offsets[0] -= base_address;
3060 MPI_Type_contiguous(
nnz, MPI_DOUBLE, &types[1]);
3061 MPI_Type_commit(&types[1]);
3062 MPI_Get_address(dist_value, &offsets[1]);
3063 offsets[1] -= base_address;
3067 MPI_Type_contiguous(
nnz, MPI_INT, &types[2]);
3068 MPI_Type_commit(&types[2]);
3069 MPI_Get_address(dist_column_index, &offsets[2]);
3070 offsets[2] -= base_address;
3074 MPI_Datatype send_type;
3075 MPI_Type_create_struct(3, len, offsets, types, &send_type);
3076 MPI_Type_commit(&send_type);
3077 MPI_Type_free(&types[0]);
3078 MPI_Type_free(&types[1]);
3079 MPI_Type_free(&types[2]);
3082 for (
int p = 0; p < nproc; p++)
3087 MPI_Isend(global_value,
3094 send_req.push_back(req);
3097 MPI_Type_free(&send_type);
3101 for (
int p = 0; p < nproc; p++)
3107 if (dist_nrow_local[p] > 0)
3110 MPI_Datatype types[3];
3113 MPI_Aint offsets[3];
3119 MPI_Type_contiguous(dist_nrow_local[p], MPI_INT, &types[0]);
3120 MPI_Type_commit(&types[0]);
3121 MPI_Get_address(global_row_start + dist_first_row[p],
3123 offsets[0] -= base_address;
3127 MPI_Type_contiguous(dist_nnz_pt[p], MPI_DOUBLE, &types[1]);
3128 MPI_Type_commit(&types[1]);
3129 MPI_Get_address(global_value + nnz_offset[p], &offsets[1]);
3130 offsets[1] -= base_address;
3134 MPI_Type_contiguous(dist_nnz_pt[p], MPI_INT, &types[2]);
3135 MPI_Type_commit(&types[2]);
3136 MPI_Get_address(global_column_index + nnz_offset[p], &offsets[2]);
3137 offsets[2] -= base_address;
3141 MPI_Datatype recv_type;
3142 MPI_Type_create_struct(3, len, offsets, types, &recv_type);
3143 MPI_Type_commit(&recv_type);
3144 MPI_Type_free(&types[0]);
3145 MPI_Type_free(&types[1]);
3146 MPI_Type_free(&types[2]);
3150 MPI_Irecv(global_value,
3157 recv_req.push_back(req);
3158 MPI_Type_free(&recv_type);
3164 unsigned nrow_local = dist_nrow_local[my_rank];
3165 unsigned first_row = dist_first_row[my_rank];
3168 global_row_start[
first_row +
i] = dist_row_start[
i];
3170 unsigned offset = nnz_offset[my_rank];
3171 for (
int i = 0;
i <
nnz;
i++)
3173 global_value[offset +
i] = dist_value[
i];
3174 global_column_index[offset +
i] = dist_column_index[
i];
3180 unsigned n_recv_req = recv_req.size();
3184 MPI_Waitall(n_recv_req, &recv_req[0], &recv_status[0]);
3188 global_row_start[
nrow] = nnz_count;
3191 for (
int p = 0; p < nproc; p++)
3193 for (
int i = 0;
i < dist_nrow_local[p];
i++)
3195 unsigned j = dist_first_row[p] +
i;
3196 global_row_start[j] += nnz_offset[p];
3201 unsigned n_send_req = send_req.size();
3205 MPI_Waitall(n_send_req, &send_req[0], &send_status[0]);
3211 this->
build(dist_pt);
3213 ncol, nnz_count, global_value, global_column_index, global_row_start);
3217 delete[] dist_first_row;
3218 delete[] dist_nrow_local;
3219 delete[] dist_nnz_pt;
3234 int* global_row_start = this->
row_start();
3236 double* global_value = this->
value();
3243 int* dist_row_start =
new int[
nrow_local + 1];
3244 int* dist_column_index =
new int[
nnz];
3245 double* dist_value =
new double[
nnz];
3248 int offset = global_row_start[
first_row];
3251 dist_row_start[
i] = global_row_start[
first_row +
i] - offset;
3253 for (
unsigned i = 0;
i <
nnz;
i++)
3255 dist_column_index[
i] = global_column_index[offset +
i];
3256 dist_value[
i] = global_value[offset +
i];
3260 this->
build(dist_pt);
3262 ncol,
nnz, dist_value, dist_column_index, dist_row_start);
3274 unsigned long nnon_zeros = this->
nnz();
3280 unsigned long n_rows = this->
nrow();
3281 unsigned long n_rows_t = this->
ncol();
3283 #ifdef OOMPH_HAS_MPI
3288 std::ostringstream warning_message;
3291 warning_message <<
"This method currently works for serial but "
3292 <<
"has not been tested with MPI!\n";
3296 OOMPH_CURRENT_FUNCTION,
3297 OOMPH_EXCEPTION_LOCATION);
3307 const double* value_pt = this->
value();
3308 const int* row_start_pt = this->
row_start();
3323 for (
unsigned i = 0;
i < nnon_zeros;
i++)
3327 row_start_t[*(column_index_pt +
i) + 1]++;
3332 for (
unsigned i = 1;
i < n_rows_t + 1;
i++)
3335 row_start_t[
i] += row_start_t[
i - 1];
3340 unsigned i_row_s = 0;
3341 unsigned i_row_e = 0;
3357 for (
unsigned i_row = 0; i_row < n_rows; i_row++)
3364 i_row_s = *(row_start_pt + i_row);
3365 i_row_e = *(row_start_pt + i_row + 1);
3369 for (
unsigned j = i_row_s; j < i_row_e; j++)
3375 a = *(column_index_pt + j);
3386 c = counter[*(column_index_pt + j)];
3390 column_index_t[b + c] = i_row;
3391 value_t[b + c] = *(value_pt + j);
3396 counter[*(column_index_pt + j)]++;
3404 result->
build(n_rows, value_t, column_index_t, row_start_t);
3418 std::ostringstream error_message;
3419 error_message <<
"This matrix must be setup.";
3421 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3435 a += fabs(
value[j]);
3441 #ifdef OOMPH_HAS_MPI
3471 std::ostringstream error_message;
3472 error_message <<
"The matrix has not been built.\n"
3473 <<
"Please build it...\n";
3475 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3481 std::ostringstream error_message;
3482 error_message <<
"The matrix is not square. Can only get the diagonal\n"
3483 <<
"entries of a square matrix.\n";
3485 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3522 std::ostringstream error_message;
3523 error_message <<
"The matrix is not built.\n"
3524 <<
"Please build the matrix!\n";
3526 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3530 if (!matrix_in.
built())
3532 std::ostringstream error_message;
3533 error_message <<
"The matrix matrix_in is not built.\n"
3534 <<
"Please build the matrix!\n";
3536 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3540 unsigned long this_nrow = this->
nrow();
3541 unsigned long matrix_in_nrow = matrix_in.
nrow();
3542 if (this_nrow != matrix_in_nrow)
3544 std::ostringstream error_message;
3545 error_message <<
"matrix_in has a different number of rows than\n"
3546 <<
"this matrix.\n";
3548 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3551 unsigned long this_ncol = this->
ncol();
3552 unsigned long matrix_in_ncol = matrix_in.
ncol();
3553 if (this_ncol != matrix_in_ncol)
3555 std::ostringstream error_message;
3556 error_message <<
"matrix_in has a different number of columns than\n"
3557 <<
"this matrix.\n";
3559 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3566 std::ostringstream error_message;
3567 error_message <<
"matrix_in must have the same distribution as\n"
3568 <<
"this matrix.\n";
3570 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3576 if (result_matrix.
built() &&
3579 std::ostringstream error_message;
3580 error_message <<
"The result_matrix is built. "
3581 <<
"But has a different distribution from matrix_in \n"
3582 <<
"They need to be the same.\n";
3584 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3602 const int* this_row_start = this->
row_start();
3603 const int* in_column_indices = matrix_in.
column_index();
3604 const int* in_row_start = matrix_in.
row_start();
3607 const double* this_values = this->
value();
3608 const double* in_values = matrix_in.
value();
3612 res_row_start.push_back(0);
3616 for (
unsigned row_i = 0; row_i <
nrow_local; row_i++)
3619 std::map<int, double> res_row_map;
3622 for (
int i = this_row_start[row_i];
i < this_row_start[row_i + 1];
i++)
3624 res_row_map[this_column_indices[
i]] = this_values[
i];
3628 for (
int i = in_row_start[row_i];
i < in_row_start[row_i + 1];
i++)
3630 res_row_map[in_column_indices[
i]] += in_values[
i];
3634 res_row_start.push_back(res_row_start.back() + res_row_map.size());
3637 for (std::map<int, double>::iterator it = res_row_map.begin();
3638 it != res_row_map.end();
3641 res_column_indices.push_back(it->first);
3642 res_values.push_back(it->second);
3650 result_matrix.
build(
3651 this->
ncol(), res_values, res_column_indices, res_row_start);
3667 namespace CRDoubleMatrixHelpers
3677 const unsigned& nrow,
3678 const unsigned& ncol,
3689 std::ostringstream error_message;
3690 error_message <<
"Please supply the communicator.\n";
3692 OOMPH_CURRENT_FUNCTION,
3693 OOMPH_EXCEPTION_LOCATION);
3696 if (matrix_out.
built())
3698 std::ostringstream error_message;
3699 error_message <<
"The result matrix has been built.\n"
3700 <<
"Please clear the matrix.\n";
3702 OOMPH_CURRENT_FUNCTION,
3703 OOMPH_EXCEPTION_LOCATION);
3708 bool distributed =
false;
3710 comm_pt, nrow, distributed);
3713 matrix_out.
build(&locally_replicated_distribution,
3722 comm_pt, nrow, distributed);
3734 const unsigned nblockrow = matrix_pt.
nrow();
3735 const unsigned nblockcol = matrix_pt.
ncol();
3739 if (matrix_pt.
nrow() == 0)
3741 std::ostringstream error_message;
3742 error_message <<
"There are no matrices... \n";
3744 OOMPH_CURRENT_FUNCTION,
3745 OOMPH_EXCEPTION_LOCATION);
3751 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3753 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
3755 if (matrix_pt(block_row_i, block_col_i) == 0)
3757 std::ostringstream error_message;
3758 error_message <<
"The pointer martrix_pt(" << block_row_i <<
","
3759 << block_col_i <<
") is null.\n";
3761 OOMPH_CURRENT_FUNCTION,
3762 OOMPH_EXCEPTION_LOCATION);
3765 if (!matrix_pt(block_row_i, block_col_i)->built())
3767 std::ostringstream error_message;
3768 error_message <<
"The matrix at martrix_pt(" << block_row_i <<
","
3769 << block_col_i <<
") is not built.\n";
3771 OOMPH_CURRENT_FUNCTION,
3772 OOMPH_EXCEPTION_LOCATION);
3778 #ifdef OOMPH_HAS_MPI
3782 matrix_pt(0, 0)->distribution_pt()->communicator_pt();
3788 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3790 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
3794 *(matrix_pt(block_row_i, block_col_i)
3796 ->communicator_pt());
3797 if (*comm_pt != current_block_comm)
3799 std::ostringstream error_message;
3800 error_message <<
"The communicator of block martrix_pt("
3801 << block_row_i <<
"," << block_col_i
3802 <<
") is not the same as block "
3803 <<
"matrix_pt(0,0).\n";
3805 OOMPH_CURRENT_FUNCTION,
3806 OOMPH_EXCEPTION_LOCATION);
3813 if (comm_pt->nproc() > 1)
3816 bool first_distributed = matrix_pt(0, 0)->distributed();
3818 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3820 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
3823 bool current_distributed =
3824 matrix_pt(block_row_i, block_col_i)->distributed();
3826 if (first_distributed != current_distributed)
3828 std::ostringstream error_message;
3829 error_message <<
"Block matrix_pt(" << block_row_i <<
","
3830 << block_col_i <<
") and block matrix_pt(0,0) "
3831 <<
"have a different distributed boolean.\n";
3833 OOMPH_CURRENT_FUNCTION,
3834 OOMPH_EXCEPTION_LOCATION);
3845 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3848 const unsigned first_block_nrow = matrix_pt(block_row_i, 0)->
nrow();
3851 for (
unsigned block_col_i = 1; block_col_i < nblockcol; block_col_i++)
3855 const unsigned current_block_nrow =
3856 matrix_pt(block_row_i, block_col_i)->
nrow();
3858 if (first_block_nrow != current_block_nrow)
3860 std::ostringstream error_message;
3861 error_message <<
"First block has nrow = " << current_block_nrow
3862 <<
". But martrix_pt(" << block_row_i <<
","
3864 <<
") has nrow = " << current_block_nrow <<
".\n";
3866 OOMPH_CURRENT_FUNCTION,
3867 OOMPH_EXCEPTION_LOCATION);
3873 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
3876 const unsigned first_block_ncol = matrix_pt(0, block_col_i)->
ncol();
3878 for (
unsigned block_row_i = 1; block_row_i < nblockrow; block_row_i++)
3881 const unsigned current_block_ncol =
3882 matrix_pt(block_row_i, block_col_i)->
ncol();
3884 if (first_block_ncol != current_block_ncol)
3886 std::ostringstream error_message;
3887 error_message <<
"First block has ncol = " << current_block_ncol
3888 <<
". But martrix_pt(" << block_row_i <<
","
3890 <<
") has ncol = " << current_block_ncol <<
".\n";
3892 OOMPH_CURRENT_FUNCTION,
3893 OOMPH_EXCEPTION_LOCATION);
3899 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3903 *(matrix_pt(block_row_i, 0)->distribution_pt());
3906 for (
unsigned block_col_i = 1; block_col_i < nblockcol; block_col_i++)
3910 matrix_pt(block_row_i, block_col_i)->distribution_pt();
3913 if (first_dist != current_dist)
3915 std::ostringstream error_message;
3916 error_message <<
"First distribution of block row " << block_row_i
3917 <<
" is different from the distribution from "
3918 <<
"martrix_pt(" << block_row_i <<
"," << block_col_i
3921 OOMPH_CURRENT_FUNCTION,
3922 OOMPH_EXCEPTION_LOCATION);
3933 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3936 unsigned block_nrow_local = matrix_pt(block_row_i, 0)->nrow_local();
3939 for (
unsigned local_row_i = 0; local_row_i < block_nrow_local;
3942 double abs_sum_of_row = 0;
3944 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
3949 const int* row_start = block_pt->
row_start();
3950 const double* value = block_pt->
value();
3953 for (
int val_i = row_start[local_row_i];
3954 val_i < row_start[local_row_i + 1];
3957 abs_sum_of_row += fabs(value[val_i]);
3966 #ifdef OOMPH_HAS_MPI
3968 if (matrix_pt(0, 0)->distributed() && comm_pt->nproc() > 1)
3975 comm_pt->mpi_comm());
4007 const unsigned nblockrow = matrix_pt.
nrow();
4008 const unsigned nblockcol = matrix_pt.
ncol();
4012 if (matrix_pt.
nrow() == 0)
4014 std::ostringstream error_message;
4015 error_message <<
"There are no matrices... \n";
4017 OOMPH_CURRENT_FUNCTION,
4018 OOMPH_EXCEPTION_LOCATION);
4024 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4026 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
4028 if (matrix_pt(block_row_i, block_col_i) == 0)
4030 std::ostringstream error_message;
4031 error_message <<
"The pointer martrix_pt(" << block_row_i <<
","
4032 << block_col_i <<
") is null.\n";
4034 OOMPH_CURRENT_FUNCTION,
4035 OOMPH_EXCEPTION_LOCATION);
4038 if (!matrix_pt(block_row_i, block_col_i)->built())
4040 std::ostringstream error_message;
4041 error_message <<
"The matrix at martrix_pt(" << block_row_i <<
","
4042 << block_col_i <<
") is not built.\n";
4044 OOMPH_CURRENT_FUNCTION,
4045 OOMPH_EXCEPTION_LOCATION);
4052 #ifdef OOMPH_HAS_MPI
4057 matrix_pt(0, 0)->distribution_pt()->communicator_pt();
4062 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4064 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
4068 *(matrix_pt(block_row_i, block_col_i)
4070 ->communicator_pt());
4071 if (*comm_pt != current_block_comm)
4073 std::ostringstream error_message;
4074 error_message <<
"The communicator of block martrix_pt("
4075 << block_row_i <<
"," << block_col_i
4076 <<
") is not the same as block "
4077 <<
"matrix_pt(0,0).\n";
4079 OOMPH_CURRENT_FUNCTION,
4080 OOMPH_EXCEPTION_LOCATION);
4087 if (comm_pt->nproc() > 1)
4090 bool first_distributed = matrix_pt(0, 0)->distributed();
4092 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4094 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
4097 bool current_distributed =
4098 matrix_pt(block_row_i, block_col_i)->distributed();
4100 if (first_distributed != current_distributed)
4102 std::ostringstream error_message;
4103 error_message <<
"Block matrix_pt(" << block_row_i <<
","
4104 << block_col_i <<
") and block matrix_pt(0,0) "
4105 <<
"have a different distributed boolean.\n";
4107 OOMPH_CURRENT_FUNCTION,
4108 OOMPH_EXCEPTION_LOCATION);
4119 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4122 const unsigned first_block_nrow = matrix_pt(block_row_i, 0)->
nrow();
4125 for (
unsigned block_col_i = 1; block_col_i < nblockcol; block_col_i++)
4129 const unsigned current_block_nrow =
4130 matrix_pt(block_row_i, block_col_i)->
nrow();
4132 if (first_block_nrow != current_block_nrow)
4134 std::ostringstream error_message;
4135 error_message <<
"First block has nrow = " << current_block_nrow
4136 <<
". But martrix_pt(" << block_row_i <<
","
4138 <<
") has nrow = " << current_block_nrow <<
".\n";
4140 OOMPH_CURRENT_FUNCTION,
4141 OOMPH_EXCEPTION_LOCATION);
4147 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
4150 const unsigned first_block_ncol = matrix_pt(0, block_col_i)->
ncol();
4152 for (
unsigned block_row_i = 1; block_row_i < nblockrow; block_row_i++)
4155 const unsigned current_block_ncol =
4156 matrix_pt(block_row_i, block_col_i)->
ncol();
4158 if (first_block_ncol != current_block_ncol)
4160 std::ostringstream error_message;
4161 error_message <<
"First block has ncol = " << current_block_ncol
4162 <<
". But martrix_pt(" << block_row_i <<
","
4164 <<
") has ncol = " << current_block_ncol <<
".\n";
4166 OOMPH_CURRENT_FUNCTION,
4167 OOMPH_EXCEPTION_LOCATION);
4173 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4177 *(matrix_pt(block_row_i, 0)->distribution_pt());
4180 for (
unsigned block_col_i = 1; block_col_i < nblockcol; block_col_i++)
4184 matrix_pt(block_row_i, block_col_i)->distribution_pt();
4187 if (first_dist != current_dist)
4189 std::ostringstream error_message;
4190 error_message <<
"First distribution of block row " << block_row_i
4191 <<
" is different from the distribution from "
4192 <<
"martrix_pt(" << block_row_i <<
"," << block_col_i
4195 OOMPH_CURRENT_FUNCTION,
4196 OOMPH_EXCEPTION_LOCATION);
4206 double extreme_disc = 0;
4207 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4210 unsigned block_nrow_local = matrix_pt(block_row_i, 0)->nrow_local();
4213 for (
unsigned local_row_i = 0; local_row_i < block_nrow_local;
4216 double abs_sum_of_row = 0;
4218 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
4223 const int* row_start = block_pt->
row_start();
4224 const double* value = block_pt->
value();
4227 for (
int val_i = row_start[local_row_i];
4228 val_i < row_start[local_row_i + 1];
4231 abs_sum_of_row += fabs(value[val_i]);
4237 double* s_values = matrix_pt(block_row_i, block_row_i)->value();
4238 int* s_column_index =
4239 matrix_pt(block_row_i, block_row_i)->column_index();
4240 int* s_row_start = matrix_pt(block_row_i, block_row_i)->row_start();
4243 int s_first_row = matrix_pt(block_row_i, block_row_i)->first_row();
4246 double diagonal_value = 0;
4248 for (
int j = s_row_start[local_row_i];
4249 j < s_row_start[local_row_i + 1] && !found;
4252 if (s_column_index[j] ==
int(local_row_i + s_first_row))
4254 diagonal_value = s_values[j];
4262 std::ostringstream error_message;
4263 error_message <<
"The diagonal entry for the block(" << block_row_i
4264 <<
"," << block_row_i <<
")\n"
4265 <<
"on local row " << local_row_i
4266 <<
" does not exist." << std::endl;
4268 OOMPH_CURRENT_FUNCTION,
4269 OOMPH_EXCEPTION_LOCATION);
4273 abs_sum_of_row -= fabs(diagonal_value);
4277 if (diagonal_value > 0)
4279 double extreme_disc_local = diagonal_value + abs_sum_of_row;
4280 extreme_disc = std::max(extreme_disc_local, extreme_disc);
4284 double extreme_disc_local = diagonal_value - abs_sum_of_row;
4285 extreme_disc = std::min(extreme_disc_local, extreme_disc);
4291 #ifdef OOMPH_HAS_MPI
4292 double extreme_disc_local = extreme_disc;
4293 if (matrix_pt(0, 0)->distributed() && comm_pt->nproc() > 1)
4295 if (extreme_disc > 0)
4297 MPI_Allreduce(&extreme_disc,
4298 &extreme_disc_local,
4302 comm_pt->mpi_comm());
4306 MPI_Allreduce(&extreme_disc,
4307 &extreme_disc_local,
4311 comm_pt->mpi_comm());
4314 extreme_disc = extreme_disc_local;
4318 return extreme_disc;
4353 unsigned matrix_nrow = matrix_pt.
nrow();
4354 unsigned matrix_ncol = matrix_pt.
ncol();
4359 if (matrix_nrow == 0)
4361 std::ostringstream error_message;
4362 error_message <<
"There are no matrices to concatenate.\n";
4364 OOMPH_CURRENT_FUNCTION,
4365 OOMPH_EXCEPTION_LOCATION);
4369 if ((matrix_nrow == 1) && (matrix_ncol == 1))
4371 std::ostringstream warning_message;
4372 warning_message <<
"There is only one matrix to concatenate...\n"
4373 <<
"This does not require concatenating...\n";
4375 OOMPH_CURRENT_FUNCTION,
4376 OOMPH_EXCEPTION_LOCATION);
4380 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4382 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
4384 if (!(matrix_pt(block_row_i, block_col_i)->built()))
4386 std::ostringstream error_message;
4387 error_message <<
"The sub matrix (" << block_row_i <<
","
4388 << block_col_i <<
")\n"
4389 <<
"is not built. \n";
4391 OOMPH_CURRENT_FUNCTION,
4392 OOMPH_EXCEPTION_LOCATION);
4399 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4402 unsigned long current_block_nrow = matrix_pt(block_row_i, 0)->
nrow();
4405 for (
unsigned block_col_i = 1; block_col_i < matrix_ncol; block_col_i++)
4408 unsigned long subblock_nrow =
4409 matrix_pt(block_row_i, block_col_i)->
nrow();
4411 if (current_block_nrow != subblock_nrow)
4413 std::ostringstream error_message;
4414 error_message <<
"The sub matrix (" << block_row_i <<
","
4415 << block_col_i <<
")\n"
4416 <<
"requires nrow = " << current_block_nrow
4417 <<
", but has nrow = " << subblock_nrow <<
".\n";
4419 OOMPH_CURRENT_FUNCTION,
4420 OOMPH_EXCEPTION_LOCATION);
4426 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
4429 unsigned long current_block_ncol = matrix_pt(0, block_col_i)->
ncol();
4432 for (
unsigned block_row_i = 1; block_row_i < matrix_nrow; block_row_i++)
4435 unsigned long subblock_ncol =
4436 matrix_pt(block_row_i, block_col_i)->
ncol();
4438 if (current_block_ncol != subblock_ncol)
4440 std::ostringstream error_message;
4441 error_message <<
"The sub matrix (" << block_row_i <<
","
4442 << block_col_i <<
")\n"
4443 <<
"requires ncol = " << current_block_ncol
4444 <<
", but has ncol = " << subblock_ncol <<
".\n";
4446 OOMPH_CURRENT_FUNCTION,
4447 OOMPH_EXCEPTION_LOCATION);
4455 matrix_pt(0, 0)->distribution_pt()->communicator_pt();
4458 bool distributed = matrix_pt(0, 0)->distributed();
4465 unsigned tmp_nrow = 0;
4466 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4468 tmp_nrow += matrix_pt(block_row_i, 0)->
nrow();
4472 comm_pt, tmp_nrow, distributed);
4474 result_matrix.
build(&tmp_distribution);
4484 unsigned tmp_nrow = 0;
4485 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4487 tmp_nrow += matrix_pt(block_row_i, 0)->
nrow();
4490 if (tmp_nrow != result_matrix.
nrow())
4492 std::ostringstream error_message;
4493 error_message <<
"The total number of rows from the matrices to\n"
4494 <<
"concatenate does not match the nrow from the\n"
4495 <<
"result matrix\n";
4497 OOMPH_CURRENT_FUNCTION,
4498 OOMPH_EXCEPTION_LOCATION);
4512 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4514 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol;
4518 *(matrix_pt(block_row_i, block_col_i)
4520 ->communicator_pt());
4522 if (!(communicator == another_communicator))
4524 std::ostringstream error_message;
4525 error_message <<
"The OomphCommunicator of the sub matrix ("
4526 << block_row_i <<
"," << block_col_i <<
")\n"
4527 <<
"does not have the same communicator as the "
4528 "result matrix. \n";
4530 OOMPH_CURRENT_FUNCTION,
4531 OOMPH_EXCEPTION_LOCATION);
4541 if (comm_pt->nproc() != 1)
4544 const bool res_distributed = result_matrix.
distributed();
4547 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4549 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol;
4552 const bool another_distributed =
4553 matrix_pt(block_row_i, block_col_i)->distributed();
4555 if (res_distributed != another_distributed)
4557 std::ostringstream error_message;
4558 error_message <<
"The distributed boolean of the sub matrix ("
4559 << block_row_i <<
"," << block_col_i <<
")\n"
4560 <<
"is not the same as the result matrix. \n";
4562 OOMPH_CURRENT_FUNCTION,
4563 OOMPH_EXCEPTION_LOCATION);
4578 unsigned long res_ncol = 0;
4580 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
4582 sum_of_ncol_up_to_block[block_col_i] = res_ncol;
4583 res_ncol += matrix_pt(0, block_col_i)->
ncol();
4588 if ((comm_pt->nproc() == 1) || !distributed)
4593 unsigned long res_nnz = 0;
4594 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4596 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol;
4599 res_nnz += matrix_pt(block_row_i, block_col_i)->nnz();
4609 res_values.reserve(res_nnz);
4610 res_column_indices.reserve(res_nnz);
4611 res_row_start.reserve(result_matrix.
nrow() + 1);
4616 int nnz_running_sum = 0;
4619 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4622 unsigned long block_row_nrow = matrix_pt(block_row_i, 0)->
nrow();
4625 for (
unsigned row_i = 0; row_i < block_row_nrow; row_i++)
4628 res_row_start.push_back(nnz_running_sum);
4631 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol;
4636 matrix_pt(block_row_i, block_col_i);
4639 double* current_block_values = current_block_pt->
value();
4640 int* current_block_column_indices =
4642 int* current_block_row_start = current_block_pt->
row_start();
4644 for (
int val_i = current_block_row_start[row_i];
4645 val_i < current_block_row_start[row_i + 1];
4648 res_values.push_back(current_block_values[val_i]);
4649 res_column_indices.push_back(
4650 current_block_column_indices[val_i] +
4651 sum_of_ncol_up_to_block[block_col_i]);
4655 nnz_running_sum += current_block_row_start[row_i + 1] -
4656 current_block_row_start[row_i];
4662 res_row_start.push_back(res_nnz);
4665 result_matrix.
build(
4666 res_ncol, res_values, res_column_indices, res_row_start);
4671 #ifdef OOMPH_HAS_MPI
4675 bool enable_timing =
false;
4678 unsigned nproc = comm_pt->nproc();
4681 unsigned my_rank = comm_pt->my_rank();
4689 unsigned long sum_of_block_nrow = 0;
4691 double t_prep_data_start;
4703 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4707 unsigned current_block_nrow_local =
4708 matrix_pt(block_row_i, 0)->nrow_local();
4711 unsigned current_block_row_first_row =
4712 matrix_pt(block_row_i, 0)->first_row();
4715 for (
unsigned sub_local_eqn = 0;
4716 sub_local_eqn < current_block_nrow_local;
4721 unsigned long res_global_eqn =
4722 sub_local_eqn + current_block_row_first_row + sum_of_block_nrow;
4734 unsigned res_first_row = res_distribution_pt->
first_row(res_p);
4735 unsigned res_local_eqn = res_global_eqn - res_first_row;
4739 unsigned long current_row_nnz = 0;
4740 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol;
4744 int* current_block_row_start =
4745 matrix_pt(block_row_i, block_col_i)->row_start();
4748 current_row_nnz += current_block_row_start[sub_local_eqn + 1] -
4749 current_block_row_start[sub_local_eqn];
4768 column_indices_to_send[res_p].push_back(res_local_eqn);
4769 column_indices_to_send[res_p].push_back(current_row_nnz);
4770 values_to_send[res_p].push_back(res_local_eqn);
4771 values_to_send[res_p].push_back(current_row_nnz);
4775 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol;
4780 matrix_pt(block_row_i, block_col_i);
4783 double* current_block_values = current_block_pt->
value();
4784 int* current_block_column_indices =
4786 int* current_block_row_start = current_block_pt->
row_start();
4789 for (
int val_i = current_block_row_start[sub_local_eqn];
4790 val_i < current_block_row_start[sub_local_eqn + 1];
4794 values_to_send[res_p].push_back(current_block_values[val_i]);
4797 column_indices_to_send[res_p].push_back(
4798 current_block_column_indices[val_i] +
4799 sum_of_ncol_up_to_block[block_col_i]);
4805 sum_of_block_nrow += matrix_pt(block_row_i, 0)->
nrow();
4812 double t_prep_data_time = t_prep_data_finish - t_prep_data_start;
4813 oomph_info <<
"Time for prep data: " << t_prep_data_time << std::endl;
4830 double t_total_ndata_start;
4835 unsigned total_ndata = 0;
4836 for (
unsigned rank = 0; rank < nproc; rank++)
4838 if (rank != my_rank)
4840 total_ndata += values_to_send[rank].size();
4847 double t_total_ndata_time =
4848 t_total_ndata_finish - t_total_ndata_start;
4849 oomph_info <<
"Time for total_ndata: " << t_total_ndata_time
4853 double t_flat_pack_start;
4859 send_values_data.reserve(total_ndata);
4860 send_column_indices_data.reserve(total_ndata);
4863 for (
unsigned rank = 0; rank < nproc; rank++)
4867 send_displacement[rank] = send_values_data.size();
4871 if (rank != my_rank)
4875 unsigned n_data = values_to_send[rank].size();
4876 for (
unsigned j = 0; j < n_data; j++)
4878 send_values_data.push_back(values_to_send[rank][j]);
4879 send_column_indices_data.push_back(
4880 column_indices_to_send[rank][j]);
4886 send_n[rank] = send_values_data.size() - send_displacement[rank];
4892 double t_flat_pack_time = t_flat_pack_finish - t_flat_pack_start;
4893 oomph_info <<
"t_flat_pack_time: " << t_flat_pack_time << std::endl;
4896 double t_sendn_start;
4902 MPI_Alltoall(&send_n[0],
4908 comm_pt->mpi_comm());
4913 double t_sendn_time = t_sendn_finish - t_sendn_start;
4914 oomph_info <<
"t_sendn_time: " << t_sendn_time << std::endl;
4922 int receive_data_count = 0;
4923 for (
unsigned rank = 0; rank < nproc; rank++)
4925 receive_displacement[rank] = receive_data_count;
4926 receive_data_count += receive_n[rank];
4931 if (receive_data_count == 0)
4933 receive_data_count++;
4940 if (send_values_data.size() == 0)
4942 send_values_data.resize(1);
4945 double t_send_data_start;
4949 MPI_Alltoallv(&send_values_data[0],
4951 &send_displacement[0],
4953 &receive_values_data[0],
4955 &receive_displacement[0],
4957 comm_pt->mpi_comm());
4960 MPI_Alltoallv(&send_column_indices_data[0],
4962 &send_displacement[0],
4964 &receive_column_indices_data[0],
4966 &receive_displacement[0],
4968 comm_pt->mpi_comm());
4973 double t_send_data_time = t_send_data_finish - t_send_data_start;
4974 oomph_info <<
"t_send_data_time: " << t_send_data_time << std::endl;
4987 unsigned res_nrow_local = res_distribution_pt->
nrow_local();
5000 unsigned long res_nnz_local = 0;
5002 double t_locations_start;
5006 unsigned location_i = 0;
5007 unsigned my_column_indices_to_send_size =
5008 column_indices_to_send[my_rank].size();
5009 while (location_i < my_column_indices_to_send_size)
5011 unsigned current_local_eqn =
5012 column_indices_to_send[my_rank][location_i++];
5014 unsigned current_nnz = column_indices_to_send[my_rank][location_i++];
5019 value_column_locations[current_local_eqn][1] = current_nnz;
5022 res_nnz_local += current_nnz;
5025 value_column_locations[current_local_eqn][2] = location_i;
5028 location_i += current_nnz;
5034 bool data_has_been_received =
false;
5035 unsigned send_rank = 0;
5036 while (send_rank < nproc)
5038 if (receive_n[send_rank] > 0)
5040 data_has_been_received =
true;
5047 if (data_has_been_received)
5049 unsigned receive_column_indices_data_size =
5050 receive_column_indices_data.size();
5051 while (location_i < receive_column_indices_data_size)
5053 unsigned current_local_eqn =
5054 receive_column_indices_data[location_i++];
5055 unsigned current_nnz = receive_column_indices_data[location_i++];
5058 value_column_locations[current_local_eqn][0] = 1;
5061 value_column_locations[current_local_eqn][1] = current_nnz;
5064 res_nnz_local += current_nnz;
5067 value_column_locations[current_local_eqn][2] = location_i;
5070 location_i += current_nnz;
5077 double t_locations_time = t_locations_finish - t_locations_start;
5078 oomph_info <<
"t_locations_time: " << t_locations_time << std::endl;
5081 double t_fillvecs_start;
5090 res_column_indices.reserve(res_nnz_local);
5091 res_values.reserve(res_nnz_local);
5092 res_row_start.reserve(res_nrow_local + 1);
5096 int nnz_running_sum = 0;
5099 for (
unsigned local_row_i = 0; local_row_i < res_nrow_local;
5103 res_row_start.push_back(nnz_running_sum);
5105 bool data_is_from_other_proc =
5106 bool(value_column_locations[local_row_i][0]);
5108 unsigned row_i_nnz = value_column_locations[local_row_i][1];
5110 unsigned row_i_offset = value_column_locations[local_row_i][2];
5112 if (data_is_from_other_proc)
5117 res_column_indices.insert(
5118 res_column_indices.end(),
5119 receive_column_indices_data.begin() + row_i_offset,
5120 receive_column_indices_data.begin() + row_i_offset + row_i_nnz);
5122 res_values.insert(res_values.end(),
5123 receive_values_data.begin() + row_i_offset,
5124 receive_values_data.begin() + row_i_offset +
5129 res_column_indices.insert(res_column_indices.end(),
5130 column_indices_to_send[my_rank].begin() +
5132 column_indices_to_send[my_rank].begin() +
5133 row_i_offset + row_i_nnz);
5135 res_values.insert(res_values.end(),
5136 values_to_send[my_rank].begin() + row_i_offset,
5137 values_to_send[my_rank].begin() + row_i_offset +
5142 nnz_running_sum += row_i_nnz;
5146 res_row_start.push_back(res_nnz_local);
5151 double t_fillvecs_time = t_fillvecs_finish - t_fillvecs_start;
5152 oomph_info <<
"t_fillvecs_time: " << t_fillvecs_time << std::endl;
5155 double t_buildres_start;
5159 result_matrix.
build(
5160 res_ncol, res_values, res_column_indices, res_row_start);
5165 double t_buildres_time = t_buildres_finish - t_buildres_start;
5166 oomph_info <<
"t_buildres_time: " << t_buildres_time << std::endl;
5230 unsigned matrix_nrow = matrix_pt.
nrow();
5231 unsigned matrix_ncol = matrix_pt.
ncol();
5240 if (matrix_nrow == 0 || matrix_ncol == 0)
5242 std::ostringstream error_message;
5243 error_message <<
"There are no matrices to concatenate.\n";
5245 OOMPH_CURRENT_FUNCTION,
5246 OOMPH_EXCEPTION_LOCATION);
5250 if ((matrix_nrow == 1) && (matrix_ncol == 1))
5252 std::ostringstream warning_message;
5253 warning_message <<
"There is only one matrix to concatenate...\n"
5254 <<
"This does not require concatenating...\n";
5256 OOMPH_CURRENT_FUNCTION,
5257 OOMPH_EXCEPTION_LOCATION);
5264 if (matrix_nrow != row_distribution_pt.size())
5266 std::ostringstream error_message;
5267 error_message <<
"The number of row distributions must be the same as\n"
5268 <<
"the number of block rows.";
5270 OOMPH_CURRENT_FUNCTION,
5271 OOMPH_EXCEPTION_LOCATION);
5276 if (matrix_ncol != col_distribution_pt.size())
5278 std::ostringstream error_message;
5280 <<
"The number of column distributions must be the same as\n"
5281 <<
"the number of block columns.";
5283 OOMPH_CURRENT_FUNCTION,
5284 OOMPH_EXCEPTION_LOCATION);
5288 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5290 if (row_distribution_pt[block_row_i] == 0)
5292 std::ostringstream error_message;
5293 error_message <<
"The row distribution pointer in position "
5294 << block_row_i <<
" is null.\n";
5296 OOMPH_CURRENT_FUNCTION,
5297 OOMPH_EXCEPTION_LOCATION);
5302 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5304 if (col_distribution_pt[block_col_i] == 0)
5306 std::ostringstream error_message;
5307 error_message <<
"The column distribution pointer in position "
5308 << block_col_i <<
" is null.\n";
5310 OOMPH_CURRENT_FUNCTION,
5311 OOMPH_EXCEPTION_LOCATION);
5317 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5319 if (!row_distribution_pt[block_row_i]->built())
5321 std::ostringstream error_message;
5322 error_message <<
"The distribution pointer in position "
5323 << block_row_i <<
" is not built.\n";
5325 OOMPH_CURRENT_FUNCTION,
5326 OOMPH_EXCEPTION_LOCATION);
5330 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5332 if (!col_distribution_pt[block_col_i]->built())
5334 std::ostringstream error_message;
5335 error_message <<
"The distribution pointer in position "
5336 << block_col_i <<
" is not built.\n";
5338 OOMPH_CURRENT_FUNCTION,
5339 OOMPH_EXCEPTION_LOCATION);
5345 *(row_distribution_pt[0]->communicator_pt());
5347 for (
unsigned block_row_i = 1; block_row_i < matrix_nrow; block_row_i++)
5350 *(row_distribution_pt[block_row_i]->communicator_pt());
5352 if (first_row_comm != current_comm)
5354 std::ostringstream error_message;
5356 <<
"The communicator from the row distribution in position "
5357 << block_row_i <<
" is not the same as the first "
5358 <<
"communicator from row_distribution_pt";
5360 OOMPH_CURRENT_FUNCTION,
5361 OOMPH_EXCEPTION_LOCATION);
5367 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5370 *(col_distribution_pt[block_col_i]->communicator_pt());
5372 if (first_row_comm != current_comm)
5374 std::ostringstream error_message;
5376 <<
"The communicator from the col distribution in position "
5377 << block_col_i <<
" is not the same as the first "
5378 <<
"communicator from row_distribution_pt";
5380 OOMPH_CURRENT_FUNCTION,
5381 OOMPH_EXCEPTION_LOCATION);
5387 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5389 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5391 if (matrix_pt(block_row_i, block_col_i) != 0 &&
5392 !(matrix_pt(block_row_i, block_col_i)->built()))
5394 std::ostringstream error_message;
5395 error_message <<
"The sub matrix_pt(" << block_row_i <<
","
5396 << block_col_i <<
")\n"
5397 <<
"is not built.\n";
5399 OOMPH_CURRENT_FUNCTION,
5400 OOMPH_EXCEPTION_LOCATION);
5407 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5409 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5411 if (matrix_pt(block_row_i, block_col_i) != 0)
5414 *(matrix_pt(block_row_i, block_col_i)
5416 ->communicator_pt());
5417 if (first_row_comm != current_comm)
5419 std::ostringstream error_message;
5421 <<
"The sub matrix_pt(" << block_row_i <<
"," << block_col_i
5423 <<
"does not have the same communicator pointer as those in\n"
5424 <<
"(row|col)_distribution_pt.\n";
5426 OOMPH_CURRENT_FUNCTION,
5427 OOMPH_EXCEPTION_LOCATION);
5435 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5438 unsigned long current_block_nrow =
5439 row_distribution_pt[block_row_i]->nrow();
5442 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5445 if (matrix_pt(block_row_i, block_col_i) != 0)
5448 unsigned long subblock_nrow =
5449 matrix_pt(block_row_i, block_col_i)->
nrow();
5451 if (current_block_nrow != subblock_nrow)
5453 std::ostringstream error_message;
5454 error_message <<
"The sub matrix (" << block_row_i <<
","
5455 << block_col_i <<
")\n"
5456 <<
"requires nrow = " << current_block_nrow
5457 <<
", but has nrow = " << subblock_nrow <<
".\n"
5458 <<
"Either the row_distribution_pt is incorrect or "
5459 <<
"the sub matrices are incorrect.\n";
5461 OOMPH_CURRENT_FUNCTION,
5462 OOMPH_EXCEPTION_LOCATION);
5469 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5473 unsigned current_block_ncol = col_distribution_pt[block_col_i]->nrow();
5475 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5477 if (matrix_pt(block_row_i, block_col_i) != 0)
5480 unsigned subblock_ncol =
5481 matrix_pt(block_row_i, block_col_i)->
ncol();
5483 if (current_block_ncol != subblock_ncol)
5485 std::ostringstream error_message;
5486 error_message <<
"The sub matrix (" << block_row_i <<
","
5487 << block_col_i <<
")\n"
5488 <<
"requires ncol = " << current_block_ncol
5489 <<
", but has ncol = " << subblock_ncol <<
".\n"
5490 <<
"Either the col_distribution_pt is incorrect or "
5491 <<
"the sub matrices are incorrect.\n";
5493 OOMPH_CURRENT_FUNCTION,
5494 OOMPH_EXCEPTION_LOCATION);
5505 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5509 row_distribution_pt[block_row_i];
5512 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5514 if (matrix_pt(block_row_i, block_col_i) != 0)
5518 matrix_pt(block_row_i, block_col_i)->distribution_pt();
5521 if ((*block_row_distribution_pt) !=
5522 (*current_block_distribution_pt))
5524 std::ostringstream error_message;
5526 <<
"Sub block(" << block_row_i <<
"," << block_col_i <<
")"
5527 <<
"does not have the same distributoin as the first"
5528 <<
"block in this block row.\n"
5529 <<
"All distributions on a block row must be the same"
5530 <<
"for this function to concatenate matrices.\n";
5532 OOMPH_CURRENT_FUNCTION,
5533 OOMPH_EXCEPTION_LOCATION);
5542 row_distribution_pt[0]->communicator_pt();
5545 unsigned nblock_row = matrix_nrow;
5556 result_matrix.
build(&tmp_distribution);
5568 wanted_distribution);
5572 std::ostringstream error_message;
5574 <<
"The result distribution is not correct.\n"
5575 <<
"Please call the function without a result\n"
5576 <<
"distribution (clear the result matrix) or check the\n"
5577 <<
"distribution of the result matrix.\n"
5578 <<
"The result distribution must be the same as the one \n"
5580 <<
"LinearAlgebraDistributionHelpers::concatenate(...)";
5582 OOMPH_CURRENT_FUNCTION,
5583 OOMPH_EXCEPTION_LOCATION);
5605 *(row_distribution_pt[0]->communicator_pt());
5607 if (res_comm != first_comm)
5609 std::ostringstream error_message;
5610 error_message <<
"The OomphCommunicator of the result matrix is not "
5614 OOMPH_CURRENT_FUNCTION,
5615 OOMPH_EXCEPTION_LOCATION);
5623 if (comm_pt->nproc() != 1)
5626 const bool res_distributed = result_matrix.
distributed();
5629 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5631 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol;
5634 if (matrix_pt(block_row_i, block_col_i) != 0)
5636 const bool another_distributed =
5637 matrix_pt(block_row_i, block_col_i)->distributed();
5639 if (res_distributed != another_distributed)
5641 std::ostringstream error_message;
5642 error_message <<
"The distributed boolean of the sub matrix ("
5643 << block_row_i <<
"," << block_col_i <<
")\n"
5644 <<
"is not the same as the result matrix. \n";
5646 OOMPH_CURRENT_FUNCTION,
5647 OOMPH_EXCEPTION_LOCATION);
5654 const bool first_row_distribution_distributed =
5655 row_distribution_pt[0]->distributed();
5657 for (
unsigned block_row_i = 1; block_row_i < matrix_nrow; block_row_i++)
5659 const bool another_distributed =
5660 row_distribution_pt[block_row_i]->distributed();
5662 if (first_row_distribution_distributed != another_distributed)
5664 std::ostringstream error_message;
5666 <<
"The distributed boolean of row_distribution_pt["
5667 << block_row_i <<
"]\n"
5668 <<
"is not the same as the one from row_distribution_pt[0]. \n";
5670 OOMPH_CURRENT_FUNCTION,
5671 OOMPH_EXCEPTION_LOCATION);
5676 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5678 const bool another_distributed =
5679 col_distribution_pt[block_col_i]->distributed();
5681 if (first_row_distribution_distributed != another_distributed)
5683 std::ostringstream error_message;
5685 <<
"The distributed boolean of col_distribution_pt["
5686 << block_col_i <<
"]\n"
5687 <<
"is not the same as the one from row_distribution_pt[0]. \n";
5689 OOMPH_CURRENT_FUNCTION,
5690 OOMPH_EXCEPTION_LOCATION);
5700 unsigned nproc = comm_pt->nproc();
5707 unsigned res_nrow_local = res_distribution_pt->
nrow_local();
5710 unsigned nblock_col = matrix_ncol;
5714 std::vector<std::vector<unsigned>> col_offset(
5715 nproc, std::vector<unsigned>(nblock_col));
5717 for (
unsigned proc_i = 0; proc_i < nproc; proc_i++)
5719 for (
unsigned block_i = 0; block_i < nblock_col; block_i++)
5721 col_offset[proc_i][block_i] = off;
5722 off += col_distribution_pt[block_i]->nrow_local(proc_i);
5731 std::vector<std::vector<unsigned>> p_for_rows(nblock_col,
5732 std::vector<unsigned>());
5734 for (
unsigned blocki = 0; blocki < nblock_col; blocki++)
5736 int blockinrow = col_distribution_pt[blocki]->nrow();
5737 p_for_rows[blocki].resize(blockinrow);
5739 for (
int rowi = 0; rowi < blockinrow; rowi++)
5742 int b_first_row = col_distribution_pt[blocki]->first_row(p);
5743 int b_nrow_local = col_distribution_pt[blocki]->nrow_local(p);
5745 while (rowi < b_first_row || rowi >= b_nrow_local + b_first_row)
5748 b_first_row = col_distribution_pt[blocki]->first_row(p);
5749 b_nrow_local = col_distribution_pt[blocki]->nrow_local(p);
5751 p_for_rows[blocki][rowi] = p;
5757 unsigned long res_nnz = 0;
5758 for (
unsigned row_i = 0; row_i < nblock_row; row_i++)
5760 for (
unsigned col_i = 0; col_i < nblock_col; col_i++)
5762 if (matrix_pt(row_i, col_i) != 0)
5764 res_nnz += matrix_pt(row_i, col_i)->nnz();
5783 int* res_row_start =
new int[res_nrow_local + 1];
5784 int* res_column_index =
new int[res_nnz];
5785 double* res_value =
new double[res_nnz];
5788 res_row_start[0] = 0;
5791 unsigned long res_i = 0;
5792 unsigned long res_row_i = 0;
5793 for (
unsigned i = 0;
i < nblock_row;
i++)
5796 unsigned block_nrow = row_distribution_pt[
i]->nrow_local();
5797 for (
unsigned k = 0; k < block_nrow; k++)
5800 res_row_start[res_row_i + 1] = res_row_start[res_row_i];
5803 for (
unsigned j = 0; j < nblock_col; j++)
5806 if (matrix_pt(
i, j) != 0)
5809 int* b_row_start = matrix_pt(
i, j)->row_start();
5810 int* b_column_index = matrix_pt(
i, j)->column_index();
5811 double* b_value = matrix_pt(
i, j)->value();
5816 int numEleToCopy = b_row_start[k + 1] - b_row_start[k];
5817 memcpy(res_value + res_i,
5818 b_value + b_row_start[k],
5819 numEleToCopy *
sizeof(
double));
5821 for (
int l = b_row_start[k]; l < b_row_start[k + 1]; l++)
5827 unsigned p = p_for_rows[j][b_column_index[l]];
5829 int b_first_row = col_distribution_pt[j]->first_row(p);
5846 int eqn = b_column_index[l] - b_first_row;
5850 res_column_index[res_i] = col_offset[p][j] + eqn;
5851 res_row_start[res_row_i + 1]++;
5866 unsigned res_ncol = 0;
5867 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5869 res_ncol += col_distribution_pt[block_col_i]->nrow();
5874 res_ncol, res_nnz, res_value, res_column_index, res_row_start);
5892 unsigned matrix_nrow = matrix_pt.
nrow();
5893 unsigned matrix_ncol = matrix_pt.
ncol();
5896 if (matrix_nrow == 0)
5898 std::ostringstream error_message;
5899 error_message <<
"There are no matrices to concatenate.\n";
5901 OOMPH_CURRENT_FUNCTION,
5902 OOMPH_EXCEPTION_LOCATION);
5906 if (matrix_nrow != matrix_ncol)
5908 std::ostringstream error_message;
5910 <<
"The number of block rows and block columns\n"
5911 <<
"must be the same. Otherwise, call the other\n"
5912 <<
"concatenate_without_communication function, passing in\n"
5913 <<
"a Vector of distributions describing how to permute the\n"
5916 OOMPH_CURRENT_FUNCTION,
5917 OOMPH_EXCEPTION_LOCATION);
5922 block_distribution_pt, block_distribution_pt, matrix_pt, result_matrix);
//////////////////////////////////////////////////////////////// ////////////////////////////////////...
void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Multiply the transposed matrix by the vector x: soln=A^T x.
virtual void lubksub(DoubleVector &rhs)
LU back solve for given RHS.
void matrix_reduction(const double &alpha, CCDoubleMatrix &reduced_matrix)
For every row, find the maximum absolute value of the entries in this row. Set all values that are le...
virtual ~CCDoubleMatrix()
Destructor: Kill the LU factors if they have been setup.
unsigned long ncol() const
Return the number of columns of the matrix.
unsigned long nrow() const
Return the number of rows of the matrix.
CCDoubleMatrix()
Default constructor.
virtual void ludecompose()
LU decomposition using SuperLU.
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
unsigned Matrix_matrix_multiply_method
Flag to determine which matrix-matrix multiplication method is used.
/////////////////////////////////////////////////////////////// /////////////////////////////////////...
void build_without_copy(T *value, int *row_index, int *column_start, const unsigned long &nnz, const unsigned long &n, const unsigned long &m)
Function to build matrix from pointers to arrays which hold the column starts, row indices and non-ze...
int * Column_start
Start index for column.
int * Row_index
Row index.
int * column_start()
Access to C-style column_start array.
void build(const Vector< double > &value, const Vector< int > &row_index, const Vector< int > &column_start, const unsigned long &n, const unsigned long &m)
Build matrix from compressed representation. Number of nonzero entries is read off from value,...
int * row_index()
Access to C-style row index array.
A class for compressed row matrices. This is a distributable object.
void sort_entries()
Sorts the entries associated with each row of the matrix in the column index vector and the value vec...
int * column_index()
Access to C-style column index array.
int * row_start()
Access to C-style row_start array.
virtual ~CRDoubleMatrix()
Destructor.
struct oomph::CRDoubleMatrix::CRDoubleMatrixComparisonHelper Comparison_struct
void matrix_reduction(const double &alpha, CRDoubleMatrix &reduced_matrix)
For every row, find the maximum absolute value of the entries in this row. Set all values that are le...
void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Multiply the transposed matrix by the vector x: soln=A^T x.
virtual void ludecompose()
LU decomposition using SuperLU if matrix is not distributed or distributed onto a single processor.
unsigned long ncol() const
Return the number of columns of the matrix.
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
void add(const CRDoubleMatrix &matrix_in, CRDoubleMatrix &result_matrix) const
element-wise addition of this matrix with matrix_in.
bool Built
Flag to indicate whether the matrix has been built - i.e. the distribution has been setup AND the mat...
Vector< int > Index_of_diagonal_entries
Vector whose i'th entry contains the index of the last entry below or on the diagonal of the i'th row...
double inf_norm() const
returns the inf-norm of this matrix
void get_matrix_transpose(CRDoubleMatrix *result) const
Returns the transpose of this matrix.
unsigned long nnz() const
Return the number of nonzero entries (the local nnz)
CRDoubleMatrix * global_matrix() const
if this matrix is distributed then a the equivalent global matrix is built using new and returned....
void redistribute(const LinearAlgebraDistribution *const &dist_pt)
The contents of the matrix are redistributed to match the new distribution. In a non-MPI build this m...
bool built() const
access function to the Built flag - indicates whether the matrix has been build - i....
void build_without_copy(const unsigned &ncol, const unsigned &nnz, double *value, int *column_index, int *row_start)
keeps the existing distribution and just matrix that is stored without copying the matrix data
double * value()
Access to C-style value array.
unsigned long nrow() const
Return the number of rows of the matrix.
unsigned Serial_matrix_matrix_multiply_method
Flag to determine which matrix-matrix multiplication method is used (for serial (or global) matrices)
Vector< double > diagonal_entries() const
returns a Vector of diagonal entries of this matrix. This only works with square matrices....
CRDoubleMatrix()
Default constructor.
bool entries_are_sorted(const bool &doc_unordered_entries=false) const
Runs through the column index vector and checks if the entries follow the regular lexicographical ord...
CRMatrix< double > CR_matrix
Storage for the Matrix in CR Format.
virtual void lubksub(DoubleVector &rhs)
LU back solve for given RHS.
void build(const LinearAlgebraDistribution *distribution_pt, const unsigned &ncol, const Vector< double > &value, const Vector< int > &column_index, const Vector< int > &row_start)
build method: vector of values, vector of column indices, vector of row starts and number of rows and...
void clean_up_memory()
Wipe matrix data and set all values to 0.
int * row_start()
Access to C-style row_start array.
void build(const Vector< T > &value, const Vector< int > &column_index, const Vector< int > &row_start, const unsigned long &n, const unsigned long &m)
Build matrix from compressed representation. Number of nonzero entries is read off from value,...
int * column_index()
Access to C-style column index array.
void build_without_copy(T *value, int *column_index, int *row_start, const unsigned long &nnz, const unsigned long &n, const unsigned long &m)
Function to build matrix from pointers to arrays which hold the row starts, column indices and non-ze...
T get_entry(const unsigned long &i, const unsigned long &j) const
Access function that will be called by the read-only round-bracket operator (const)
Class of matrices containing doubles, and stored as a DenseMatrix<double>, but with solving functiona...
DenseDoubleMatrix()
Constructor, set the default linear solver.
virtual void lubksub(DoubleVector &rhs)
LU backsubstitution.
virtual ~DenseDoubleMatrix()
Destructor.
void matrix_reduction(const double &alpha, DenseDoubleMatrix &reduced_matrix)
For every row, find the maximum absolute value of the entries in this row. Set all values that are le...
virtual void ludecompose()
LU decomposition using DenseLU (default linea solver)
void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Multiply the transposed matrix by the vector x: soln=A^T x.
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
unsigned long nrow() const
Return the number of rows of the matrix.
unsigned long ncol() const
Return the number of columns of the matrix.
void eigenvalues_by_jacobi(Vector< double > &eigen_val, DenseMatrix< double > &eigen_vect) const
Determine eigenvalues and eigenvectors, using Jacobi rotations. Only for symmetric matrices....
Dense LU decomposition-based solve of full assembled linear system. VERY inefficient but useful to il...
//////////////////////////////////////////////////////////////////////////// ////////////////////////...
unsigned long nrow() const
Return the number of rows of the matrix.
unsigned long N
Number of rows.
double * Matrixdata
Internal representation of matrix as a pointer to data.
unsigned long ncol() const
Return the number of columns of the matrix.
unsigned long M
Number of columns.
void resize(const unsigned long &n)
Resize to a square nxn matrix; any values already present will be transfered.
void clear_distribution()
clear the distribution of this distributable linear algebra object
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
void solve(DoubleVector &rhs)
Complete LU solve (replaces matrix by its LU decomposition and overwrites RHS with solution)....
LinearSolver * Default_linear_solver_pt
LinearSolver * Linear_solver_pt
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 build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
double * values_pt()
access function to the underlying values
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
void build(const OomphCommunicator *const comm_pt, const unsigned &first_row, const unsigned &nrow_local, const unsigned &nrow=0)
Sets the distribution. Takes first_row, nrow_local and nrow as arguments. If nrow is not provided or ...
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.
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
virtual void solve(Problem *const &problem_pt, DoubleVector &result)=0
Solver: Takes pointer to problem and returns the results vector which contains the solution of the li...
virtual void clean_up_memory()
Empty virtual function that can be overloaded in specific linear solvers to clean up any memory that ...
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....
unsigned long Nnz
Number of non-zero values (i.e. size of Value array)
T * value()
Access to C-style value array.
T * Value
Internal representation of the matrix values, a pointer.
unsigned long N
Number of rows.
unsigned long M
Number of columns.
//////////////////////////////////////////////////////////////////////////// ////////////////////////...
double gershgorin_eigenvalue_estimate(const DenseMatrix< CRDoubleMatrix * > &matrix_pt)
Calculates the largest Gershgorin disc whilst preserving the sign. Let A be an n by n matrix,...
void concatenate_without_communication(const Vector< LinearAlgebraDistribution * > &row_distribution_pt, const Vector< LinearAlgebraDistribution * > &col_distribution_pt, const DenseMatrix< CRDoubleMatrix * > &matrix_pt, CRDoubleMatrix &result_matrix)
Concatenate CRDoubleMatrix matrices.
double inf_norm(const DenseMatrix< CRDoubleMatrix * > &matrix_pt)
Compute infinity (maximum) norm of sub blocks as if it was one matrix.
void concatenate(const DenseMatrix< CRDoubleMatrix * > &matrix_pt, CRDoubleMatrix &result_matrix)
Concatenate CRDoubleMatrix matrices. The in matrices are concatenated such that the block structure o...
void create_uniformly_distributed_matrix(const unsigned &nrow, const unsigned &ncol, const OomphCommunicator *const comm_pt, const Vector< double > &values, const Vector< int > &column_indices, const Vector< int > &row_start, CRDoubleMatrix &matrix_out)
Builds a uniformly distributed matrix. A locally replicated matrix is constructed then redistributed ...
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 timer()
returns the time in seconds after some point in past
void multiply(const CRDoubleMatrix *matrix, const DoubleVector &x, DoubleVector &soln)
Function to perform a matrix-vector multiplication on a oomph-lib matrix and vector using Trilinos fu...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...