61 OOMPH_CURRENT_FUNCTION,
62 OOMPH_EXCEPTION_LOCATION);
86 OOMPH_CURRENT_FUNCTION,
87 OOMPH_EXCEPTION_LOCATION);
104 OOMPH_CURRENT_FUNCTION,
105 OOMPH_EXCEPTION_LOCATION);
129 OOMPH_CURRENT_FUNCTION,
130 OOMPH_EXCEPTION_LOCATION);
167 const unsigned long &m) :
179 const unsigned long &m,
180 const double &initial_val) :
240 "This matrix is not square, the matrix MUST be square!",
241 OOMPH_CURRENT_FUNCTION,
242 OOMPH_EXCEPTION_LOCATION);
249 if (eigen_vals.size()!=
N)
251 eigen_vals.resize(
N);
253 if (eigen_vect.
ncol()!=
N || eigen_vect.
nrow()!=
N)
259 for (
unsigned long i=0;
i<
N;
i++)
261 for (
unsigned long j=0;j<
M;j++)
267 "Matrix needs to be symmetric for eigenvalues_by_jacobi()",
268 OOMPH_CURRENT_FUNCTION,
269 OOMPH_EXCEPTION_LOCATION);
272 working_matrix(
i,j)=(*this)(
i,j);
279 "Sorry JacobiEigenSolver::jacobi() removed because of licencing problems.",
280 OOMPH_CURRENT_FUNCTION,
281 OOMPH_EXCEPTION_LOCATION);
289 for (
unsigned long i=0;
i<
N;
i++)
291 for (
unsigned long j=0;j<
M;j++)
293 eigen_vect(
i,j)=aux_eigen_vect(j,
i);
309 std::ostringstream error_message_stream;
311 <<
"The x vector is not the right size. It is " << x.
nrow()
312 <<
", it should be " << this->
ncol() << std::endl;
314 OOMPH_CURRENT_FUNCTION,
315 OOMPH_EXCEPTION_LOCATION);
320 std::ostringstream error_message_stream;
322 <<
"The x vector cannot be distributed for DenseDoubleMatrix " 323 <<
"matrix-vector multiply" << std::endl;
325 OOMPH_CURRENT_FUNCTION,
326 OOMPH_EXCEPTION_LOCATION);
334 std::ostringstream error_message_stream;
336 <<
"The x vector cannot be distributed for DenseDoubleMatrix " 337 <<
"matrix-vector multiply" << std::endl;
339 OOMPH_CURRENT_FUNCTION,
340 OOMPH_EXCEPTION_LOCATION);
344 std::ostringstream error_message_stream;
346 <<
"The soln vector is setup and therefore must have the same " 347 <<
"number of rows as the matrix";
349 OOMPH_CURRENT_FUNCTION,
350 OOMPH_EXCEPTION_LOCATION);
355 std::ostringstream error_message_stream;
357 <<
"The soln vector and the x vector must have the same communicator" 360 OOMPH_CURRENT_FUNCTION,
361 OOMPH_EXCEPTION_LOCATION);
371 soln.
build(&dist,0.0);
380 for (
unsigned long i=0;
i<
N;
i++)
382 for (
unsigned long j=0;j<
M;j++)
400 std::ostringstream error_message_stream;
402 <<
"The x vector is not the right size. It is " << x.
nrow()
403 <<
", it should be " << this->
nrow() << std::endl;
405 OOMPH_CURRENT_FUNCTION,
406 OOMPH_EXCEPTION_LOCATION);
411 std::ostringstream error_message_stream;
413 <<
"The x vector cannot be distributed for DenseDoubleMatrix " 414 <<
"matrix-vector multiply" << std::endl;
416 OOMPH_CURRENT_FUNCTION,
417 OOMPH_EXCEPTION_LOCATION);
425 std::ostringstream error_message_stream;
427 <<
"The x vector cannot be distributed for DenseDoubleMatrix " 428 <<
"matrix-vector multiply" << std::endl;
430 OOMPH_CURRENT_FUNCTION,
431 OOMPH_EXCEPTION_LOCATION);
435 std::ostringstream error_message_stream;
437 <<
"The soln vector is setup and therefore must have the same " 438 <<
"number of columns as the matrix";
440 OOMPH_CURRENT_FUNCTION,
441 OOMPH_EXCEPTION_LOCATION);
446 std::ostringstream error_message_stream;
448 <<
"The soln vector and the x vector must have the same communicator" 451 OOMPH_CURRENT_FUNCTION,
452 OOMPH_EXCEPTION_LOCATION);
463 soln.
build(dist_pt,0.0);
473 for (
unsigned long i=0;
i<
N;
i++)
475 for (
unsigned long j=0;j<
M;j++)
500 for(
unsigned i=0;
i<
N;
i++)
506 for(
unsigned long j=0;j<
M;j++)
516 for(
unsigned long j=0;j<
M;j++)
538 if ( this->
ncol() != matrix_in.
nrow() )
540 std::ostringstream error_message;
542 <<
"Matrix dimensions incompatable for matrix-matrix multiplication" 543 <<
"ncol() for first matrix:" << this->
ncol()
544 <<
"nrow() for second matrix: " << matrix_in.
nrow();
547 OOMPH_CURRENT_FUNCTION,
548 OOMPH_EXCEPTION_LOCATION);
553 unsigned long n_row = this->
nrow();
554 unsigned long m_col = matrix_in.
ncol();
557 result.
resize(n_row, m_col, 0.0);
562 unsigned long n_col=this->
ncol();
563 for (
unsigned long k=0; k<n_col; k++)
565 for (
unsigned long i=0;
i<n_row;
i++)
567 for (
unsigned long j=0; j<m_col; j++)
602 const unsigned long &n,
603 const unsigned long &m) :
604 CCMatrix<double>(value,row_index,column_start,n,m)
639 std::ostringstream error_message_stream;
641 <<
"The x vector is not the right size. It is " << x.
nrow()
642 <<
", it should be " << this->
ncol() << std::endl;
644 OOMPH_CURRENT_FUNCTION,
645 OOMPH_EXCEPTION_LOCATION);
650 std::ostringstream error_message_stream;
652 <<
"The x vector cannot be distributed for CCDoubleMatrix " 653 <<
"matrix-vector multiply" << std::endl;
655 OOMPH_CURRENT_FUNCTION,
656 OOMPH_EXCEPTION_LOCATION);
664 std::ostringstream error_message_stream;
666 <<
"The x vector cannot be distributed for CCDoubleMatrix " 667 <<
"matrix-vector multiply" << std::endl;
669 OOMPH_CURRENT_FUNCTION,
670 OOMPH_EXCEPTION_LOCATION);
674 std::ostringstream error_message_stream;
676 <<
"The soln vector is setup and therefore must have the same " 677 <<
"number of rows as the matrix";
679 OOMPH_CURRENT_FUNCTION,
680 OOMPH_EXCEPTION_LOCATION);
685 std::ostringstream error_message_stream;
687 <<
"The soln vector and the x vector must have the same communicator" 690 OOMPH_CURRENT_FUNCTION,
691 OOMPH_EXCEPTION_LOCATION);
702 soln.
build(dist_pt,0.0);
712 for (
unsigned long j=0;j<
N;j++)
717 double a_ij =
Value[k];
718 soln_pt[
i] += a_ij*x_pt[j];
736 std::ostringstream error_message_stream;
738 <<
"The x vector is not the right size. It is " << x.
nrow()
739 <<
", it should be " << this->
nrow() << std::endl;
741 OOMPH_CURRENT_FUNCTION,
742 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);
761 std::ostringstream error_message_stream;
763 <<
"The x vector cannot be distributed for CCDoubleMatrix " 764 <<
"matrix-vector multiply" << std::endl;
766 OOMPH_CURRENT_FUNCTION,
767 OOMPH_EXCEPTION_LOCATION);
771 std::ostringstream error_message_stream;
773 <<
"The soln vector is setup and therefore must have the same " 774 <<
"number of columns as the matrix";
776 OOMPH_CURRENT_FUNCTION,
777 OOMPH_EXCEPTION_LOCATION);
782 std::ostringstream error_message_stream;
784 <<
"The soln vector and the x vector must have the same communicator" 787 OOMPH_CURRENT_FUNCTION,
788 OOMPH_EXCEPTION_LOCATION);
799 soln.
build(dist_pt,0.0);
809 for (
unsigned long i=0;
i<
N;
i++)
815 double a_ij=
Value[k];
816 soln_pt[j]+=a_ij*x_pt[
i];
844 if ( this->
ncol() != matrix_in.
nrow() )
846 std::ostringstream error_message;
848 <<
"Matrix dimensions incompatable for matrix-matrix multiplication" 849 <<
"ncol() for first matrix:" << this->
ncol()
850 <<
"nrow() for second matrix: " << matrix_in.
nrow();
853 OOMPH_CURRENT_FUNCTION,
854 OOMPH_EXCEPTION_LOCATION);
859 unsigned long N = this->
nrow();
860 unsigned long M = matrix_in.
ncol();
861 unsigned long Nnz = 0;
869 const int* matrix_in_col_start = matrix_in.
column_start();
870 const int* matrix_in_row_index = matrix_in.
row_index();
871 const double* matrix_in_value = matrix_in.
value();
874 const double* this_value = this->
value();
876 const int* this_row_index = this->
row_index();
888 Column_start =
new int[M+1];
892 std::set<unsigned> rows;
896 for (
unsigned long this_col = 0; this_col<
M; this_col++)
899 for (
int this_ptr = this_col_start[this_col];
900 this_ptr < this_col_start[this_col+1];
904 unsigned matrix_in_col = this_row_index[this_ptr];
907 for (
int matrix_in_ptr = matrix_in_col_start[matrix_in_col];
908 matrix_in_ptr < matrix_in_col_start[matrix_in_col+1];
912 rows.insert(matrix_in_row_index[matrix_in_ptr]);
916 Column_start[this_col+1] = Column_start[this_col] + rows.size();
923 Nnz = Column_start[
M];
926 Value =
new double[
Nnz];
927 Row_index =
new int[
Nnz];
930 for (
unsigned long i=0;
i<
Nnz;
i++)
934 for (
unsigned long this_col = 0; this_col<
M; this_col++)
937 for (
int this_ptr = this_col_start[this_col];
938 this_ptr < this_col_start[this_col+1];
942 double this_val = this_value[this_ptr];
945 unsigned matrix_in_col = this_row_index[this_ptr];
948 for (
int matrix_in_ptr = matrix_in_col_start[matrix_in_col];
949 matrix_in_ptr < matrix_in_col_start[matrix_in_col+1];
953 int row = matrix_in_row_index[matrix_in_ptr];
956 for(
int ptr = Column_start[this_col];
957 ptr <= Column_start[this_col+1];
960 if (ptr == Column_start[this_col+1])
964 std::ostringstream error_message;
965 error_message <<
"Error inserting value in result";
968 OOMPH_CURRENT_FUNCTION,
969 OOMPH_EXCEPTION_LOCATION);
971 else if (Row_index[ptr] == -1 )
974 Row_index[ptr] = row;
975 Value[ptr] = this_val * matrix_in_value[matrix_in_ptr];
978 else if ( Row_index[ptr] == row )
981 Value[ptr] += this_val * matrix_in_value[matrix_in_ptr];
995 std::map<int,double>* result_maps =
new std::map<int,double>[
M];
998 for (
unsigned long this_col = 0; this_col<
M; this_col++)
1001 for (
int this_ptr = this_col_start[this_col];
1002 this_ptr < this_col_start[this_col+1];
1006 double this_val = this_value[this_ptr];
1009 unsigned matrix_in_col = this_row_index[this_ptr];
1012 for (
int matrix_in_ptr = matrix_in_col_start[matrix_in_col];
1013 matrix_in_ptr < matrix_in_col_start[matrix_in_col+1];
1017 int row = matrix_in_row_index[matrix_in_ptr];
1020 result_maps[this_col][row] +=
1021 this_val * matrix_in_value[matrix_in_ptr];
1027 Column_start =
new int[M+1];
1030 Column_start[0] = 0;
1031 for (
unsigned long col=0; col<
M; col++)
1033 int size = result_maps[col].size();
1034 Column_start[col+1] = Column_start[col] + size;
1038 Nnz = Column_start[
M];
1041 Value =
new double[
Nnz];
1042 Row_index =
new int[
Nnz];
1045 for (
unsigned long col=0; col<
M; col++)
1047 unsigned ptr = Column_start[col];
1048 for (std::map<int,double>::iterator
i = result_maps[col].begin();
1049 i != result_maps[col].end();
1052 Row_index[ptr]=
i->first;
1053 Value[ptr] =
i->second;
1059 delete[] result_maps;
1067 std::vector< std::vector<int> > result_rows(N);
1068 std::vector< std::vector<double> > result_vals(N);
1071 for (
unsigned long this_col = 0; this_col<
M; this_col++)
1074 for (
int this_ptr = this_col_start[this_col];
1075 this_ptr < this_col_start[this_col+1];
1079 double this_val = this_value[this_ptr];
1082 unsigned matrix_in_col = this_row_index[this_ptr];
1085 for (
int matrix_in_ptr = matrix_in_col_start[matrix_in_col];
1086 matrix_in_ptr < matrix_in_col_start[matrix_in_col+1];
1090 int row = matrix_in_row_index[matrix_in_ptr];
1093 int size = result_rows[this_col].size();
1094 for (
int i = 0;
i<=size;
i++)
1099 result_rows[this_col].push_back(row);
1100 result_vals[this_col].push_back(
1101 this_val*matrix_in_value[matrix_in_ptr]);
1103 else if (row==result_rows[this_col][
i])
1106 result_vals[this_col][
i] +=
1107 this_val * matrix_in_value[matrix_in_ptr];
1116 Column_start =
new int[M+1];
1119 Column_start[0] = 0;
1120 for (
unsigned long col=0; col<
M; col++)
1122 int size = result_rows[col].size();
1123 Column_start[col+1] = Column_start[col] + size;
1127 Nnz = Column_start[
M];
1130 Value =
new double[
Nnz];
1131 Row_index =
new int[
Nnz];
1134 for (
unsigned long col=0; col<
N; col++)
1136 unsigned ptr = Column_start[col];
1137 unsigned n_rows=result_rows[col].size();
1138 for (
unsigned i = 0;
i < n_rows ;
i++)
1140 Row_index[ptr] = result_rows[col][
i];
1141 Value[ptr] = result_vals[col][
i];
1150 std::ostringstream error_message;
1151 error_message <<
"Incorrect method set in matrix-matrix multiply" 1152 <<
"method=" << method <<
" not allowed";
1155 OOMPH_CURRENT_FUNCTION,
1156 OOMPH_EXCEPTION_LOCATION);
1192 for(
long i=0;
i<n_coln;
i++)
1207 for(
long j=Column_start[
i];j<Column_start[
i+1];j++)
1213 B_value.push_back(
Value[j]);
1220 B_row_start.push_back(k);
1247 #ifdef OOMPH_HAS_TRILINOS 1249 Serial_matrix_matrix_multiply_method = 2;
1251 Serial_matrix_matrix_multiply_method = 2;
1264 const double* values_pt = other_matrix.
value();
1265 const int* column_indices = other_matrix.
column_index();
1266 const int* row_start = other_matrix.
row_start();
1269 const unsigned nnz = other_matrix.
nnz();
1273 const unsigned nrow_local = other_matrix.
nrow_local();
1276 double* my_values_pt =
new double[
nnz];
1277 int* my_column_indices =
new int[
nnz];
1278 int* my_row_start =
new int[nrow_local+1];
1281 std::copy(values_pt,values_pt+nnz,my_values_pt);
1282 std::copy(column_indices,column_indices+nnz,my_column_indices);
1283 std::copy(row_start,row_start+nrow_local+1,my_row_start);
1288 my_column_indices,my_row_start);
1297 #ifdef OOMPH_HAS_TRILINOS 1299 Serial_matrix_matrix_multiply_method = 2;
1301 Serial_matrix_matrix_multiply_method = 2;
1313 this->build_distribution(distribution_pt);
1322 #ifdef OOMPH_HAS_TRILINOS 1324 Serial_matrix_matrix_multiply_method = 2;
1326 Serial_matrix_matrix_multiply_method = 2;
1337 const unsigned&
ncol,
1343 CR_matrix.build(value,column_index,row_start,dist_pt->
nrow_local(),
ncol);
1346 this->build_distribution(dist_pt);
1352 #ifdef OOMPH_HAS_TRILINOS 1354 Serial_matrix_matrix_multiply_method = 2;
1356 Serial_matrix_matrix_multiply_method = 2;
1380 this->build_distribution(distribution_pt);
1392 #ifdef OOMPH_HAS_MPI 1394 if (this->distributed())
1397 std::ostringstream warning_message;
1400 warning_message <<
"This method currently works for serial but " 1401 <<
"has not been implemented for use with MPI!\n";
1405 OOMPH_CURRENT_FUNCTION,
1406 OOMPH_EXCEPTION_LOCATION);
1411 unsigned n_rows=this->
nrow();
1416 const int* column_index_pt=this->column_index();
1417 const int* row_start_pt=this->row_start();
1420 for (
unsigned i=0;
i<n_rows;
i++)
1423 unsigned nnz_row_i=*(row_start_pt+
i+1)-*(row_start_pt+
i);
1426 unsigned i_row_start=*(row_start_pt+
i);
1429 for (
unsigned j=0;j<nnz_row_i-1;j++)
1433 if ((*(column_index_pt+i_row_start+j+1))<
1434 (*(column_index_pt+i_row_start+j)))
1438 if (doc_unordered_entries)
1441 oomph_info <<
"Matrix has not been correctly sorted!" 1442 <<
"\nOn row: " <<
i 1444 <<
"\nEntry 1 = " << *(column_index_pt+i_row_start+j)
1445 <<
"\nEntry 2 = " << *(column_index_pt+i_row_start+j+1)
1475 #ifdef OOMPH_HAS_MPI 1477 if (this->distributed())
1480 std::ostringstream warning_message;
1483 warning_message <<
"This method currently works for serial but " 1484 <<
"has not been tested with MPI!\n";
1488 OOMPH_CURRENT_FUNCTION,
1489 OOMPH_EXCEPTION_LOCATION);
1494 unsigned n_rows=this->
nrow();
1499 double* value_pt=this->
value();
1500 int* column_index_pt=this->column_index();
1501 const int* row_start_pt=this->row_start();
1504 Index_of_diagonal_entries.resize(n_rows,0);
1511 for (
unsigned i=0;
i<n_rows;
i++)
1514 unsigned nnz_row_i=*(row_start_pt+
i+1)-*(row_start_pt+
i);
1517 unsigned i_row_start=*(row_start_pt+
i);
1524 Index_of_diagonal_entries[
i]=0;
1531 column_index_and_value_row_i.resize(nnz_row_i);
1534 for (
unsigned j=0;j<nnz_row_i;j++)
1537 column_index_and_value_row_i[j]=
1538 std::make_pair(*(column_index_pt+i_row_start+j),
1539 *(value_pt+i_row_start+j));
1543 std::sort(column_index_and_value_row_i.begin(),
1544 column_index_and_value_row_i.end(),
1554 bool is_ith_entry_set=
false;
1558 for (
unsigned j=0;j<nnz_row_i;j++)
1562 *(column_index_pt+i_row_start+j)=column_index_and_value_row_i[j].first;
1566 *(value_pt+i_row_start+j)=column_index_and_value_row_i[j].second;
1570 if (!is_ith_entry_set)
1574 if (
unsigned(*(column_index_pt+i_row_start))>
i)
1580 Index_of_diagonal_entries[
i]=-1;
1584 is_ith_entry_set=
true;
1597 Index_of_diagonal_entries[
i]=i_row_start+j;
1601 is_ith_entry_set=
true;
1635 else if (
unsigned(*(column_index_pt+i_row_start+j))==
i)
1639 Index_of_diagonal_entries[
i]=i_row_start+j;
1643 is_ith_entry_set=
true;
1646 else if (
unsigned(*(column_index_pt+i_row_start+j))>
i)
1650 Index_of_diagonal_entries[
i]=i_row_start+j-1;
1654 is_ith_entry_set=
true;
1657 else if (j==nnz_row_i-1)
1661 Index_of_diagonal_entries[
i]=i_row_start+j;
1665 is_ith_entry_set=
true;
1679 this->clear_distribution();
1680 CR_matrix.clean_up_memory();
1693 const unsigned&
ncol,
1702 this->build_distribution(distribution_pt);
1708 this->
build(ncol,value,column_index,row_start);
1720 CR_matrix.clean_up_memory();
1721 CR_matrix.build(value,column_index,row_start,
1722 this->nrow_local(),ncol);
1732 const unsigned&
nnz,
1738 CR_matrix.clean_up_memory();
1739 CR_matrix.build_without_copy(value,column_index,row_start,nnz,
1740 this->nrow_local(),ncol);
1755 std::ostringstream error_message_stream;
1756 error_message_stream
1757 <<
"This matrix has not been built.";
1759 OOMPH_CURRENT_FUNCTION,
1760 OOMPH_EXCEPTION_LOCATION);
1778 std::ostringstream error_message_stream;
1779 error_message_stream
1780 <<
"The vector rhs has not been setup";
1782 OOMPH_CURRENT_FUNCTION,
1783 OOMPH_EXCEPTION_LOCATION);
1788 std::ostringstream error_message_stream;
1789 error_message_stream
1790 <<
"The vector rhs must have the same distribution as the matrix";
1792 OOMPH_CURRENT_FUNCTION,
1793 OOMPH_EXCEPTION_LOCATION);
1811 std::ostringstream error_message_stream;
1812 error_message_stream
1813 <<
"This matrix has not been built";
1815 OOMPH_CURRENT_FUNCTION,
1816 OOMPH_EXCEPTION_LOCATION);
1821 std::ostringstream error_message_stream;
1822 error_message_stream
1823 <<
"The distribution of the vector x must be setup";
1825 OOMPH_CURRENT_FUNCTION,
1826 OOMPH_EXCEPTION_LOCATION);
1831 std::ostringstream error_message_stream;
1832 error_message_stream
1833 <<
"The number of rows in the x vector and the number of columns in the " 1834 <<
"matrix must be the same";
1836 OOMPH_CURRENT_FUNCTION,
1837 OOMPH_EXCEPTION_LOCATION);
1844 std::ostringstream error_message_stream;
1845 error_message_stream
1846 <<
"The soln vector is setup and therefore must have the same " 1847 <<
"distribution as the matrix";
1849 OOMPH_CURRENT_FUNCTION,
1850 OOMPH_EXCEPTION_LOCATION);
1859 soln.
build(this->distribution_pt(),0.0);
1867 if (this->distributed() &&
1868 this->distribution_pt()->communicator_pt()->nproc() > 1)
1870 #ifdef OOMPH_HAS_TRILINOS 1874 std::ostringstream error_message_stream;
1875 error_message_stream
1876 <<
"Matrix-vector product on multiple processors with distributed " 1877 <<
"CRDoubleMatrix requires Trilinos.";
1879 OOMPH_CURRENT_FUNCTION,
1880 OOMPH_EXCEPTION_LOCATION);
1885 unsigned n = this->
nrow();
1886 const int* row_start = CR_matrix.row_start();
1887 const int* column_index = CR_matrix.column_index();
1888 const double*
value = CR_matrix.value();
1891 for (
unsigned long i=0;
i<n;
i++)
1894 for (
long k=row_start[
i];k<row_start[
i+1];k++)
1896 unsigned long j=column_index[k];
1897 double a_ij=value[k];
1898 soln_pt[
i]+=a_ij*x_pt[j];
1914 std::ostringstream error_message_stream;
1915 error_message_stream
1916 <<
"This matrix has not been built";
1918 OOMPH_CURRENT_FUNCTION,
1919 OOMPH_EXCEPTION_LOCATION);
1924 std::ostringstream error_message_stream;
1925 error_message_stream
1926 <<
"The x vector and this matrix must have the same distribution.";
1928 OOMPH_CURRENT_FUNCTION,
1929 OOMPH_EXCEPTION_LOCATION);
1936 std::ostringstream error_message_stream;
1937 error_message_stream
1938 <<
"The soln vector is setup and therefore must have the same " 1939 <<
"number of rows as the vector x";
1941 OOMPH_CURRENT_FUNCTION,
1942 OOMPH_EXCEPTION_LOCATION);
1952 this->
ncol(),this->distributed());
1953 soln.
build(dist_pt,0.0);
1960 if (this->distributed() &&
1961 this->distribution_pt()->communicator_pt()->nproc() > 1)
1963 #ifdef OOMPH_HAS_TRILINOS 1967 std::ostringstream error_message_stream;
1968 error_message_stream
1969 <<
"Matrix-vector product on multiple processors with distributed " 1970 <<
"CRDoubleMatrix requires Trilinos.";
1972 OOMPH_CURRENT_FUNCTION,
1973 OOMPH_EXCEPTION_LOCATION);
1978 unsigned n = this->
nrow();
1979 const int* row_start = CR_matrix.row_start();
1980 const int* column_index = CR_matrix.column_index();
1981 const double*
value = CR_matrix.value();
1985 for (
unsigned long i=0;
i<n;
i++)
1987 for (
long k=row_start[
i];k<row_start[
i+1];k++)
1989 unsigned long j=column_index[k];
1990 double a_ij=value[k];
1991 soln_pt[j]+=a_ij*x_pt[
i];
2024 std::ostringstream error_message_stream;
2025 error_message_stream
2026 <<
"This matrix has not been built";
2028 OOMPH_CURRENT_FUNCTION,
2029 OOMPH_EXCEPTION_LOCATION);
2032 if (!matrix_in.
built())
2034 std::ostringstream error_message_stream;
2035 error_message_stream
2036 <<
"This matrix matrix_in has not been built";
2038 OOMPH_CURRENT_FUNCTION,
2039 OOMPH_EXCEPTION_LOCATION);
2046 std::ostringstream error_message_stream;
2047 error_message_stream
2048 <<
"The matrix result is setup and therefore must have the same " 2049 <<
"distribution as the vector x";
2051 OOMPH_CURRENT_FUNCTION,
2052 OOMPH_EXCEPTION_LOCATION);
2060 result.
build(this->distribution_pt());
2064 unsigned method = Serial_matrix_matrix_multiply_method;
2067 if (!this->distributed() && !matrix_in.
distributed() &&
2068 ((method == 1) || (method == 2) || (method == 3)))
2071 unsigned long N = this->
nrow();
2072 unsigned long M = matrix_in.
ncol();
2073 unsigned long Nnz = 0;
2078 int* Column_index = 0;
2081 const int* matrix_in_row_start = matrix_in.
row_start();
2082 const int* matrix_in_column_index = matrix_in.
column_index();
2083 const double* matrix_in_value = matrix_in.
value();
2086 const double* this_value = this->
value();
2087 const int* this_row_start = this->row_start();
2088 const int* this_column_index = this->column_index();
2097 Row_start =
new int[N+1];
2101 std::set<unsigned> columns;
2105 for (
unsigned long this_row = 0; this_row<
N; this_row++)
2108 for (
int this_ptr = this_row_start[this_row];
2109 this_ptr < this_row_start[this_row+1];
2113 int matrix_in_row = this_column_index[this_ptr];
2116 for (
int matrix_in_ptr = matrix_in_row_start[matrix_in_row];
2117 matrix_in_ptr < matrix_in_row_start[matrix_in_row+1];
2121 columns.insert(matrix_in_column_index[matrix_in_ptr]);
2125 Row_start[this_row+1] = Row_start[this_row] + columns.size();
2135 Value =
new double[
Nnz];
2136 Column_index =
new int[
Nnz];
2139 for (
unsigned long i=0;
i<
Nnz;
i++)
2141 Column_index[
i] = -1;
2145 for (
unsigned long this_row = 0; this_row<
N; this_row++)
2148 for (
int this_ptr = this_row_start[this_row];
2149 this_ptr < this_row_start[this_row+1];
2153 double this_val = this_value[this_ptr];
2156 int matrix_in_row = this_column_index[this_ptr];
2159 for (
int matrix_in_ptr = matrix_in_row_start[matrix_in_row];
2160 matrix_in_ptr < matrix_in_row_start[matrix_in_row+1];
2164 int col = matrix_in_column_index[matrix_in_ptr];
2167 for(
int ptr = Row_start[this_row];
2168 ptr <= Row_start[this_row+1];
2171 if (ptr == Row_start[this_row+1])
2175 std::ostringstream error_message;
2176 error_message <<
"Error inserting value in result";
2179 OOMPH_CURRENT_FUNCTION,
2180 OOMPH_EXCEPTION_LOCATION);
2182 else if ( Column_index[ptr] == -1 )
2185 Column_index[ptr] = col;
2186 Value[ptr] = this_val * matrix_in_value[matrix_in_ptr];
2189 else if ( Column_index[ptr] == col )
2192 Value[ptr] += this_val * matrix_in_value[matrix_in_ptr];
2206 std::map<int,double>* result_maps =
new std::map<int,double>[
N];
2209 for (
unsigned long this_row = 0; this_row<
N; this_row++)
2212 for (
int this_ptr = this_row_start[this_row];
2213 this_ptr < this_row_start[this_row+1];
2217 double this_val = this_value[this_ptr];
2220 int matrix_in_row = this_column_index[this_ptr];
2223 for (
int matrix_in_ptr = matrix_in_row_start[matrix_in_row];
2224 matrix_in_ptr < matrix_in_row_start[matrix_in_row+1];
2228 int col = matrix_in_column_index[matrix_in_ptr];
2231 result_maps[this_row][col] += this_val * matrix_in_value[matrix_in_ptr];
2237 Row_start =
new int[N+1];
2241 for (
unsigned long row=0; row<
N; row++)
2243 int size = result_maps[row].size();
2244 Row_start[row+1] = Row_start[row] + size;
2251 Value =
new double[
Nnz];
2252 Column_index =
new int[
Nnz];
2255 for (
unsigned long row=0; row<
N; row++)
2257 unsigned ptr = Row_start[row];
2258 for (std::map<int,double>::iterator
i = result_maps[row].begin();
2259 i != result_maps[row].end();
2262 Column_index[ptr]=
i->first;
2263 Value[ptr] =
i->second;
2269 delete[] result_maps;
2277 std::vector< std::vector<int> > result_cols(N);
2278 std::vector< std::vector<double> > result_vals(N);
2281 for (
unsigned long this_row = 0; this_row<
N; this_row++)
2284 for (
int this_ptr = this_row_start[this_row];
2285 this_ptr < this_row_start[this_row+1];
2289 double this_val = this_value[this_ptr];
2292 int matrix_in_row = this_column_index[this_ptr];
2295 for (
int matrix_in_ptr = matrix_in_row_start[matrix_in_row];
2296 matrix_in_ptr < matrix_in_row_start[matrix_in_row+1];
2300 int col = matrix_in_column_index[matrix_in_ptr];
2303 int size = result_cols[this_row].size();
2304 for (
int i = 0;
i<=size;
i++)
2309 result_cols[this_row].push_back(col);
2310 result_vals[this_row].push_back(
2311 this_val*matrix_in_value[matrix_in_ptr]);
2313 else if (col==result_cols[this_row][
i])
2316 result_vals[this_row][
i] += this_val *
2317 matrix_in_value[matrix_in_ptr];
2326 Row_start =
new int[N+1];
2330 for (
unsigned long row=0; row<
N; row++)
2332 int size = result_cols[row].size();
2333 Row_start[row+1] = Row_start[row] + size;
2340 Value =
new double[
Nnz];
2341 Column_index =
new int[
Nnz];
2344 for (
unsigned long row=0; row<
N; row++)
2346 unsigned ptr = Row_start[row];
2347 unsigned nnn=result_cols[row].size();
2348 for (
unsigned i = 0;
i < nnn;
i++)
2350 Column_index[ptr] = result_cols[row][
i];
2351 Value[ptr] = result_vals[row][
i];
2364 #ifdef OOMPH_HAS_TRILINOS 2365 bool use_ml =
false;
2372 std::ostringstream error_message;
2373 error_message <<
"Serial_matrix_matrix_multiply_method = " 2374 << Serial_matrix_matrix_multiply_method
2375 <<
" requires trilinos.";
2377 OOMPH_CURRENT_FUNCTION,
2378 OOMPH_EXCEPTION_LOCATION);
2396 long n_row=nrow_local();
2405 const int* row_start = CR_matrix.row_start();
2406 const int* column_index = CR_matrix.column_index();
2407 const double*
value = CR_matrix.value();
2416 for(
long i=0;
i<n_row;
i++)
2422 for(
long j=row_start[
i];j<row_start[
i+1];j++)
2425 if(std::fabs(value[j])>max_row)
2427 max_row=std::fabs(value[j]);
2432 for(
long j=row_start[
i];j<row_start[
i+1];j++)
2436 if(
i==column_index[j] || std::fabs(value[j])>alpha*max_row )
2438 B_value.push_back(value[j]);
2439 B_column_index.push_back(column_index[j]);
2445 B_row_start.push_back(k);
2450 build(this->
ncol(),B_value,B_column_index,B_row_start);
2460 #ifdef OOMPH_HAS_MPI 2462 if (!this->distributed() ||
2463 this->distribution_pt()->communicator_pt()->nproc() == 1)
2472 unsigned nrow_local = this->nrow_local();
2478 int nproc = this->distribution_pt()->communicator_pt()->nproc();
2481 int* dist_nnz_pt =
new int[nproc];
2482 MPI_Allgather(&nnz,1,MPI_INT,
2483 dist_nnz_pt,1,MPI_INT,
2484 this->distribution_pt()->communicator_pt()->mpi_comm());
2487 int* dist_first_row =
new int[nproc];
2488 int* dist_nrow_local =
new int[nproc];
2490 for (
int p = 0; p < nproc; p++)
2492 nnz_global += dist_nnz_pt[p];
2493 dist_first_row[p] = this->first_row(p);
2494 dist_nrow_local[p] = this->nrow_local(p);
2498 int* nnz_offset =
new int[nproc];
2500 for (
int p = 1; p < nproc; p++)
2502 nnz_offset[p] = nnz_offset[p-1] + dist_nnz_pt[p-1];
2508 int* dist_row_start =
const_cast<int*
>(this->row_start());
2509 int* dist_column_index =
const_cast<int*
>(this->column_index());
2510 double* dist_value =
const_cast<double*
>(this->
value());
2513 int* global_row_start =
new int[nrow+1];
2514 int* global_column_index =
new int[nnz_global];
2515 double* global_value =
new double[nnz_global];
2518 MPI_Allgatherv(dist_row_start,nrow_local,MPI_INT,
2519 global_row_start,dist_nrow_local,dist_first_row,MPI_INT,
2520 this->distribution_pt()->communicator_pt()->mpi_comm());
2523 MPI_Allgatherv(dist_column_index,nnz,MPI_INT,
2524 global_column_index,dist_nnz_pt,nnz_offset,MPI_INT,
2525 this->distribution_pt()->communicator_pt()->mpi_comm());
2528 MPI_Allgatherv(dist_value,nnz,MPI_DOUBLE,
2529 global_value,dist_nnz_pt,nnz_offset,MPI_DOUBLE,
2530 this->distribution_pt()->communicator_pt()->mpi_comm());
2533 global_row_start[
nrow] = nnz_global;
2536 for (
int p = 0; p < nproc; p++)
2538 for (
int i = 0;
i < dist_nrow_local[p];
i++)
2540 unsigned j = dist_first_row[p] +
i;
2541 global_row_start[j]+=nnz_offset[p];
2557 global_column_index,global_row_start);
2560 delete dist_first_row;
2561 delete dist_nrow_local;
2583 #ifdef OOMPH_HAS_MPI 2587 if (dist_pt->
nrow() != this->distribution_pt()->nrow())
2589 std::ostringstream error_message;
2590 error_message <<
"The number of global rows in the new distribution (" 2591 << dist_pt->
nrow() <<
") is not equal to the number" 2592 <<
" of global rows in the current distribution (" 2593 << this->distribution_pt()->nrow() <<
").\n";
2595 OOMPH_CURRENT_FUNCTION,
2596 OOMPH_EXCEPTION_LOCATION);
2601 if (!(temp_comm == *this->distribution_pt()->communicator_pt()))
2603 std::ostringstream error_message;
2604 error_message <<
"The new distribution and the current distribution must " 2605 <<
"have the same communicator.";
2607 OOMPH_CURRENT_FUNCTION,
2608 OOMPH_EXCEPTION_LOCATION);
2613 std::ostringstream error_message;
2614 error_message <<
"The matrix must be build to be redistributed";
2616 OOMPH_CURRENT_FUNCTION,
2617 OOMPH_EXCEPTION_LOCATION);
2623 if (!((*this->distribution_pt()) == *dist_pt))
2629 int* current_row_start = this->row_start();
2630 int* current_column_index = this->column_index();
2631 double* current_value = this->
value();
2634 int my_rank = this->distribution_pt()->communicator_pt()->my_rank();
2635 int nproc = this->distribution_pt()->communicator_pt()->nproc();
2639 if (this->distributed() && dist_pt->
distributed())
2647 for (
int i = 0;
i < nproc;
i++)
2651 current_first_row[
i] = this->first_row(
i);
2652 current_nrow_local[
i] = this->nrow_local(
i);
2664 for (
int p = 0; p < nproc; p++)
2667 if ((new_first_row[p] < (current_first_row[my_rank] +
2668 current_nrow_local[my_rank])) &&
2669 (current_first_row[my_rank] < (new_first_row[p] +
2670 new_nrow_local[p])))
2672 first_row_for_proc[p] =
2673 std::max(current_first_row[my_rank],
2675 nrow_local_for_proc[p] =
2676 std::min((current_first_row[my_rank] +
2677 current_nrow_local[my_rank]),
2679 new_nrow_local[p])) - first_row_for_proc[p];
2683 if ((new_first_row[my_rank] < (current_first_row[p] +
2684 current_nrow_local[p]))
2685 && (current_first_row[p] < (new_first_row[my_rank] +
2686 new_nrow_local[my_rank])))
2688 first_row_from_proc[p] =
2689 std::max(current_first_row[p],
2690 new_first_row[my_rank]);
2691 nrow_local_from_proc[p] =
2692 std::min((current_first_row[p] +
2693 current_nrow_local[p]),
2694 (new_first_row[my_rank] +
2695 new_nrow_local[my_rank]))-first_row_from_proc[p];
2701 for (
int p = 0; p < nproc; p++)
2703 if (nrow_local_for_proc[p] > 0)
2705 nnz_for_proc[p] = (current_row_start[first_row_for_proc[p]-
2706 current_first_row[my_rank]+
2707 nrow_local_for_proc[p]]-
2708 current_row_start[first_row_for_proc[p]-
2709 current_first_row[my_rank]]);
2717 for (
int p = 0; p < nproc; p++)
2722 if (nrow_local_for_proc[p] > 0)
2725 MPI_Isend(&nnz_for_proc[p],1,MPI_UNSIGNED,p,0,
2726 this->distribution_pt()->communicator_pt()->mpi_comm(),&req);
2727 send_req.push_back(req);
2731 if (nrow_local_from_proc[p] > 0)
2734 MPI_Irecv(&nnz_from_proc[p],1,MPI_UNSIGNED,p,0,
2735 this->distribution_pt()->communicator_pt()->mpi_comm(),&req);
2736 nnz_recv_req.push_back(req);
2742 nnz_from_proc[p] = nnz_for_proc[p];
2747 int* new_row_start =
new int[new_nrow_local[my_rank]+1];
2750 unsigned n_recv_req = nnz_recv_req.size();
2754 MPI_Waitall(n_recv_req,&nnz_recv_req[0],&recv_status[0]);
2758 unsigned next_row = 0;
2759 unsigned nnz_count = 0;
2761 for (
int p = 0; p < nproc; p++)
2764 while (new_first_row[pp] != next_row) { pp++; }
2765 nnz_offset[pp] = nnz_count;
2766 nnz_count+= nnz_from_proc[pp];
2767 next_row += new_nrow_local[pp];
2771 int* new_column_index =
new int[nnz_count];
2772 double* new_value =
new double[nnz_count];
2776 MPI_Aint base_address;
2777 MPI_Get_address(new_value,&base_address);
2778 for (
int p = 0; p < nproc; p++)
2784 if (nrow_local_for_proc[p] > 0)
2787 MPI_Datatype types[3];
2790 MPI_Aint offsets[3];
2796 unsigned first_row_to_send = first_row_for_proc[p] -
2797 current_first_row[my_rank];
2798 MPI_Type_contiguous(nrow_local_for_proc[p],MPI_INT,
2800 MPI_Type_commit(&types[0]);
2802 MPI_Get_address(current_row_start+first_row_to_send,&offsets[0]);
2803 offsets[0] -= base_address;
2806 unsigned first_coef_to_send
2807 = current_row_start[first_row_to_send];
2808 MPI_Type_contiguous(nnz_for_proc[p],MPI_DOUBLE,
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,
2818 MPI_Type_commit(&types[2]);
2820 MPI_Get_address(current_column_index+first_coef_to_send,&offsets[2]);
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,1,send_type,p,1,
2834 this->distribution_pt()->communicator_pt()->mpi_comm(),&req);
2835 send_req.push_back(req);
2836 MPI_Type_free(&send_type);
2840 if (nrow_local_from_proc[p] > 0)
2843 MPI_Datatype types[3];
2846 MPI_Aint offsets[3];
2852 unsigned first_row_to_recv = first_row_from_proc[p] -
2853 new_first_row[my_rank];
2854 MPI_Type_contiguous(nrow_local_from_proc[p],MPI_INT,
2856 MPI_Type_commit(&types[0]);
2858 MPI_Get_address(new_row_start+first_row_to_recv,&offsets[0]);
2859 offsets[0] -= base_address;
2862 unsigned first_coef_to_recv = nnz_offset[p];
2863 MPI_Type_contiguous(nnz_from_proc[p],MPI_DOUBLE,
2865 MPI_Type_commit(&types[1]);
2867 MPI_Get_address(new_value+first_coef_to_recv,&offsets[1]);
2868 offsets[1] -= base_address;
2871 MPI_Type_contiguous(nnz_from_proc[p],MPI_INT,
2873 MPI_Type_commit(&types[2]);
2875 MPI_Get_address(new_column_index+first_coef_to_recv,&offsets[2]);
2876 offsets[2] -= base_address;
2879 MPI_Datatype recv_type;
2880 MPI_Type_create_struct(3,len,offsets,types,&recv_type);
2881 MPI_Type_commit(&recv_type);
2882 MPI_Type_free(&types[0]);
2883 MPI_Type_free(&types[1]);
2884 MPI_Type_free(&types[2]);
2888 MPI_Irecv(new_value,1,recv_type,p,1,
2889 this->distribution_pt()->communicator_pt()->mpi_comm(),&req);
2890 recv_req.push_back(req);
2891 MPI_Type_free(&recv_type);
2897 unsigned j = first_row_for_proc[my_rank] -
2898 current_first_row[my_rank];
2899 unsigned k = first_row_from_proc[my_rank] -
2900 new_first_row[my_rank];
2901 for (
unsigned i = 0;
i < nrow_local_for_proc[my_rank];
i++)
2903 new_row_start[k+
i] = current_row_start[j+
i];
2905 unsigned first_coef_to_send = current_row_start[j];
2906 for (
unsigned i = 0;
i < nnz_for_proc[my_rank];
i++)
2908 new_value[nnz_offset[p]+
i]=current_value[first_coef_to_send+
i];
2909 new_column_index[nnz_offset[p]+
i]
2910 =current_column_index[first_coef_to_send+
i];
2916 n_recv_req = recv_req.size();
2920 MPI_Waitall(n_recv_req,&recv_req[0],&recv_status[0]);
2924 for (
int p = 0; p < nproc; p++)
2926 if (nrow_local_from_proc[p] > 0)
2928 unsigned first_row = first_row_from_proc[p]-new_first_row[my_rank];
2929 unsigned last_row = first_row + nrow_local_from_proc[p]-1;
2930 int update = nnz_offset[p] - new_row_start[first_row];
2931 for (
unsigned i = first_row;
i <= last_row;
i++)
2933 new_row_start[
i]+=update;
2937 new_row_start[dist_pt->
nrow_local()] = nnz_count;
2940 unsigned n_send_req = send_req.size();
2944 MPI_Waitall(n_send_req,&send_req[0],&send_status[0]);
2953 this->
build(dist_pt);
2955 new_value,new_column_index,
2968 else if (this->distributed() && !dist_pt->
distributed())
2978 int nproc = this->distribution_pt()->communicator_pt()->nproc();
2981 int* dist_nnz_pt =
new int[nproc];
2982 MPI_Allgather(&nnz,1,MPI_INT,
2983 dist_nnz_pt,1,MPI_INT,
2984 this->distribution_pt()->communicator_pt()->mpi_comm());
2988 int* dist_first_row =
new int[nproc];
2989 int* dist_nrow_local =
new int[nproc];
2990 for (
int p = 0; p < nproc; p++)
2992 dist_first_row[p] = this->first_row(p);
2993 dist_nrow_local[p] = this->nrow_local(p);
2999 unsigned nnz_count = 0;
3001 for (
int p = 0; p < nproc; p++)
3004 while (dist_first_row[pp] != next_row) { pp++; }
3005 nnz_offset[pp] = nnz_count;
3006 nnz_count+=dist_nnz_pt[pp];
3007 next_row+=dist_nrow_local[pp];
3011 int* dist_row_start = this->row_start();
3012 int* dist_column_index = this->column_index();
3013 double* dist_value = this->
value();
3016 int* global_row_start =
new int[nrow+1];
3017 int* global_column_index =
new int[nnz_count];
3018 double* global_value =
new double[nnz_count];
3023 MPI_Aint base_address;
3024 MPI_Get_address(global_value,&base_address);
3027 if (dist_nrow_local[my_rank] > 0)
3030 MPI_Datatype types[3];
3033 MPI_Aint offsets[3];
3039 MPI_Type_contiguous(dist_nrow_local[my_rank],MPI_INT,&types[0]);
3040 MPI_Type_commit(&types[0]);
3041 MPI_Get_address(dist_row_start,&offsets[0]);
3042 offsets[0] -= base_address;
3046 MPI_Type_contiguous(nnz,MPI_DOUBLE,&types[1]);
3047 MPI_Type_commit(&types[1]);
3048 MPI_Get_address(dist_value,&offsets[1]);
3049 offsets[1] -= base_address;
3053 MPI_Type_contiguous(nnz,MPI_INT,&types[2]);
3054 MPI_Type_commit(&types[2]);
3055 MPI_Get_address(dist_column_index,&offsets[2]);
3056 offsets[2] -= base_address;
3060 MPI_Datatype send_type;
3061 MPI_Type_create_struct(3,len,offsets,types,&send_type);
3062 MPI_Type_commit(&send_type);
3063 MPI_Type_free(&types[0]);
3064 MPI_Type_free(&types[1]);
3065 MPI_Type_free(&types[2]);
3068 for (
int p = 0; p < nproc; p++)
3073 MPI_Isend(global_value,1,send_type,p,1,
3074 this->distribution_pt()->communicator_pt()->mpi_comm(),&req);
3075 send_req.push_back(req);
3078 MPI_Type_free(&send_type);
3082 for (
int p = 0; p < nproc; p++)
3088 if (dist_nrow_local[p] > 0)
3092 MPI_Datatype types[3];
3095 MPI_Aint offsets[3];
3101 MPI_Type_contiguous(dist_nrow_local[p],MPI_INT,&types[0]);
3102 MPI_Type_commit(&types[0]);
3103 MPI_Get_address(global_row_start+dist_first_row[p],&offsets[0]);
3104 offsets[0] -= base_address;
3108 MPI_Type_contiguous(dist_nnz_pt[p],MPI_DOUBLE,&types[1]);
3109 MPI_Type_commit(&types[1]);
3110 MPI_Get_address(global_value+nnz_offset[p],&offsets[1]);
3111 offsets[1] -= base_address;
3115 MPI_Type_contiguous(dist_nnz_pt[p],MPI_INT,&types[2]);
3116 MPI_Type_commit(&types[2]);
3117 MPI_Get_address(global_column_index+nnz_offset[p],&offsets[2]);
3118 offsets[2] -= base_address;
3122 MPI_Datatype recv_type;
3123 MPI_Type_create_struct(3,len,offsets,types,&recv_type);
3124 MPI_Type_commit(&recv_type);
3125 MPI_Type_free(&types[0]);
3126 MPI_Type_free(&types[1]);
3127 MPI_Type_free(&types[2]);
3131 MPI_Irecv(global_value,1,recv_type,p,1,
3132 this->distribution_pt()->communicator_pt()->mpi_comm(),&req);
3133 recv_req.push_back(req);
3134 MPI_Type_free(&recv_type);
3140 unsigned nrow_local = dist_nrow_local[my_rank];
3141 unsigned first_row = dist_first_row[my_rank];
3142 for (
unsigned i = 0;
i < nrow_local;
i++)
3144 global_row_start[first_row+
i]=dist_row_start[
i];
3146 unsigned offset = nnz_offset[my_rank];
3147 for (
int i = 0;
i <
nnz;
i++)
3149 global_value[offset+
i]=dist_value[
i];
3150 global_column_index[offset+
i]=dist_column_index[
i];
3156 unsigned n_recv_req = recv_req.size();
3160 MPI_Waitall(n_recv_req,&recv_req[0],&recv_status[0]);
3164 global_row_start[
nrow] = nnz_count;
3167 for (
int p = 0; p < nproc; p++)
3169 for (
int i = 0;
i < dist_nrow_local[p];
i++)
3171 unsigned j = dist_first_row[p] +
i;
3172 global_row_start[j]+=nnz_offset[p];
3177 unsigned n_send_req = send_req.size();
3181 MPI_Waitall(n_send_req,&send_req[0],&send_status[0]);
3188 this->
build(dist_pt);
3190 global_value,global_column_index,
3195 delete[] dist_first_row;
3196 delete[] dist_nrow_local;
3197 delete[] dist_nnz_pt;
3203 else if (!this->distributed() && dist_pt->
distributed())
3210 unsigned first_row = dist_pt->
first_row();
3213 int* global_row_start = this->row_start();
3214 int* global_column_index = this->column_index();
3215 double* global_value = this->
value();
3218 unsigned nnz = global_row_start[first_row+nrow_local] -
3219 global_row_start[first_row];
3222 int* dist_row_start =
new int[nrow_local+1];
3223 int* dist_column_index =
new int[
nnz];
3224 double* dist_value =
new double[
nnz];
3227 int offset = global_row_start[first_row];
3228 for (
unsigned i = 0;
i <= nrow_local;
i++)
3230 dist_row_start[
i] = global_row_start[first_row+
i]-offset;
3232 for (
unsigned i = 0;
i <
nnz;
i++)
3234 dist_column_index[
i] = global_column_index[offset+
i];
3235 dist_value[
i] = global_value[offset+
i];
3239 this->
build(dist_pt);
3241 dist_column_index,dist_row_start);
3253 unsigned long nnon_zeros=this->
nnz();
3259 unsigned long n_rows=this->
nrow();
3260 unsigned long n_rows_t=this->
ncol();
3262 #ifdef OOMPH_HAS_MPI 3264 if (this->distributed())
3267 std::ostringstream warning_message;
3270 warning_message <<
"This method currently works for serial but " 3271 <<
"has not been tested with MPI!\n";
3275 OOMPH_CURRENT_FUNCTION,
3276 OOMPH_EXCEPTION_LOCATION);
3282 communicator_pt(),n_rows_t,
false);
3286 const double* value_pt=this->
value();
3287 const int* row_start_pt=this->row_start();
3288 const int* column_index_pt=this->column_index();
3302 for (
unsigned i=0;
i<nnon_zeros;
i++)
3306 row_start_t[*(column_index_pt+
i)+1]++;
3311 for (
unsigned i=1;
i<n_rows_t+1;
i++)
3314 row_start_t[
i]+=row_start_t[
i-1];
3336 for (
unsigned i_row=0;i_row<n_rows;i_row++)
3343 i_row_s=*(row_start_pt+i_row);
3344 i_row_e=*(row_start_pt+i_row+1);
3348 for (
unsigned j=i_row_s;j<i_row_e;j++)
3355 a=*(column_index_pt+j);
3366 c=counter[*(column_index_pt+j)];
3370 column_index_t[b+c]=i_row;
3371 value_t[b+c]=*(value_pt+j);
3376 counter[*(column_index_pt+j)]++;
3384 result->
build(n_rows,value_t,column_index_t,row_start_t);
3396 if (!this->distribution_built())
3398 std::ostringstream error_message;
3399 error_message <<
"This matrix must be setup.";
3401 OOMPH_CURRENT_FUNCTION,
3402 OOMPH_EXCEPTION_LOCATION);
3407 unsigned nrow_local = this->nrow_local();
3409 const int* row_start = CR_matrix.row_start();
3410 const double*
value = CR_matrix.value();
3411 for (
unsigned i = 0;
i < nrow_local;
i++)
3414 for (
int j = row_start[
i]; j < row_start[
i+1]; j++)
3416 a += fabs(value[j]);
3422 #ifdef OOMPH_HAS_MPI 3424 if ( this->distributed() &&
3425 this->distribution_pt()->communicator_pt()->nproc() > 1)
3427 MPI_Allreduce(&n,&n2,1,MPI_DOUBLE,MPI_MAX,
3428 this->distribution_pt()->communicator_pt()->mpi_comm());
3449 std::ostringstream error_message;
3450 error_message <<
"The matrix has not been built.\n" 3451 <<
"Please build it...\n";
3453 OOMPH_CURRENT_FUNCTION,
3454 OOMPH_EXCEPTION_LOCATION);
3460 std::ostringstream error_message;
3461 error_message <<
"The matrix is not square. Can only get the diagonal\n" 3462 <<
"entries of a square matrix.\n";
3464 OOMPH_CURRENT_FUNCTION,
3465 OOMPH_EXCEPTION_LOCATION);
3470 unsigned nrow_local = this->nrow_local();
3474 result_vec.reserve(nrow_local);
3477 unsigned first_row = this->first_row();
3480 for (
unsigned i = 0;
i < nrow_local;
i++)
3483 unsigned diag_entry_col = first_row +
i;
3486 result_vec.push_back(CR_matrix.get_entry(i, diag_entry_col));
3502 std::ostringstream error_message;
3503 error_message <<
"The matrix is not built.\n" 3504 <<
"Please build the matrix!\n";
3506 OOMPH_CURRENT_FUNCTION,
3507 OOMPH_EXCEPTION_LOCATION);
3511 if(!matrix_in.
built())
3513 std::ostringstream error_message;
3514 error_message <<
"The matrix matrix_in is not built.\n" 3515 <<
"Please build the matrix!\n";
3517 OOMPH_CURRENT_FUNCTION,
3518 OOMPH_EXCEPTION_LOCATION);
3522 unsigned long this_nrow = this->
nrow();
3523 unsigned long matrix_in_nrow = matrix_in.
nrow();
3524 if(this_nrow != matrix_in_nrow)
3526 std::ostringstream error_message;
3527 error_message <<
"matrix_in has a different number of rows than\n" 3528 <<
"this matrix.\n";
3530 OOMPH_CURRENT_FUNCTION,
3531 OOMPH_EXCEPTION_LOCATION);
3534 unsigned long this_ncol = this->
ncol();
3535 unsigned long matrix_in_ncol = matrix_in.
ncol();
3536 if(this_ncol != matrix_in_ncol)
3538 std::ostringstream error_message;
3539 error_message <<
"matrix_in has a different number of columns than\n" 3540 <<
"this matrix.\n";
3542 OOMPH_CURRENT_FUNCTION,
3543 OOMPH_EXCEPTION_LOCATION);
3550 std::ostringstream error_message;
3551 error_message <<
"matrix_in must have the same distribution as\n" 3552 <<
"this matrix.\n";
3554 OOMPH_CURRENT_FUNCTION,
3555 OOMPH_EXCEPTION_LOCATION);
3561 if(result_matrix.
built() &&
3564 std::ostringstream error_message;
3565 error_message <<
"The result_matrix is built. " 3566 <<
"But has a different distribution from matrix_in \n" 3567 <<
"They need to be the same.\n";
3569 OOMPH_CURRENT_FUNCTION,
3570 OOMPH_EXCEPTION_LOCATION);
3580 unsigned nrow_local = this->nrow_local();
3584 res_row_start.reserve(nrow_local+1);
3587 const int* this_column_indices = this->column_index();
3588 const int* this_row_start = this->row_start();
3589 const int* in_column_indices = matrix_in.
column_index();
3590 const int* in_row_start = matrix_in.
row_start();
3593 const double* this_values = this->
value();
3594 const double* in_values = matrix_in.
value();
3598 res_row_start.push_back(0);
3602 for (
unsigned row_i = 0; row_i < nrow_local; row_i++)
3605 std::map<int,double> res_row_map;
3608 for (
int i = this_row_start[row_i];
i < this_row_start[row_i+1];
i++)
3610 res_row_map[this_column_indices[
i]] = this_values[
i];
3614 for (
int i = in_row_start[row_i];
i < in_row_start[row_i+1];
i++)
3616 res_row_map[in_column_indices[
i]] += in_values[
i];
3620 res_row_start.push_back(res_row_start.back() + res_row_map.size());
3623 for(std::map<int,double>::iterator it = res_row_map.begin();
3624 it != res_row_map.end(); ++it)
3626 res_column_indices.push_back(it->first);
3627 res_values.push_back(it->second);
3635 result_matrix.
build(this->
ncol(),res_values,
3636 res_column_indices,res_row_start);
3641 result_matrix.
build(this->distribution_pt(),this->
ncol(),res_values,
3642 res_column_indices,res_row_start);
3649 namespace CRDoubleMatrixHelpers
3659 const unsigned &
nrow,
const unsigned &
ncol,
3669 std::ostringstream error_message;
3670 error_message <<
"Please supply the communicator.\n";
3672 OOMPH_CURRENT_FUNCTION,
3673 OOMPH_EXCEPTION_LOCATION);
3676 if(matrix_out.
built())
3678 std::ostringstream error_message;
3679 error_message <<
"The result matrix has been built.\n" 3680 <<
"Please clear the matrix.\n";
3682 OOMPH_CURRENT_FUNCTION,
3683 OOMPH_EXCEPTION_LOCATION);
3688 bool distributed =
false;
3690 locally_replicated_distribution(comm_pt,nrow,distributed);
3693 matrix_out.
build(&locally_replicated_distribution,ncol,
3694 values,column_indices,row_start);
3699 distributed_distribution(comm_pt,nrow,distributed);
3712 const unsigned nblockrow = matrix_pt.
nrow();
3713 const unsigned nblockcol = matrix_pt.
ncol();
3717 if(matrix_pt.
nrow() == 0)
3719 std::ostringstream error_message;
3720 error_message <<
"There are no matrices... \n";
3722 OOMPH_CURRENT_FUNCTION,
3723 OOMPH_EXCEPTION_LOCATION);
3729 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3731 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
3733 if(matrix_pt(block_row_i,block_col_i) == 0)
3735 std::ostringstream error_message;
3736 error_message <<
"The pointer martrix_pt(" << block_row_i
3737 <<
"," << block_col_i <<
") is null.\n";
3739 OOMPH_CURRENT_FUNCTION,
3740 OOMPH_EXCEPTION_LOCATION);
3743 if(!matrix_pt(block_row_i,block_col_i)->built())
3745 std::ostringstream error_message;
3746 error_message <<
"The matrix at martrix_pt(" << block_row_i
3747 <<
"," << block_col_i <<
") is not built.\n";
3749 OOMPH_CURRENT_FUNCTION,
3750 OOMPH_EXCEPTION_LOCATION);
3756 #ifdef OOMPH_HAS_MPI 3760 = matrix_pt(0,0)->distribution_pt()->communicator_pt();
3766 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3768 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
3772 = *(matrix_pt(block_row_i,block_col_i)
3773 ->distribution_pt()->communicator_pt());
3774 if(*comm_pt != current_block_comm)
3776 std::ostringstream error_message;
3777 error_message <<
"The communicator of block martrix_pt("<< block_row_i
3778 <<
"," << block_col_i <<
") is not the same as block " 3779 <<
"matrix_pt(0,0).\n";
3781 OOMPH_CURRENT_FUNCTION,
3782 OOMPH_EXCEPTION_LOCATION);
3789 if(comm_pt->nproc() > 1)
3792 bool first_distributed = matrix_pt(0,0)->distributed();
3794 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3796 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
3799 bool current_distributed
3800 = matrix_pt(block_row_i,block_col_i)->distributed();
3802 if(first_distributed != current_distributed)
3804 std::ostringstream error_message;
3805 error_message <<
"Block matrix_pt(" << block_row_i
3806 <<
","<<block_col_i<<
") and block matrix_pt(0,0) " 3807 <<
"have a different distributed boolean.\n";
3809 OOMPH_CURRENT_FUNCTION,
3810 OOMPH_EXCEPTION_LOCATION);
3821 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3824 const unsigned first_block_nrow = matrix_pt(block_row_i,0)->
nrow();
3827 for (
unsigned block_col_i = 1; block_col_i < nblockcol; block_col_i++)
3831 const unsigned current_block_nrow
3832 = matrix_pt(block_row_i,block_col_i)->
nrow();
3834 if(first_block_nrow != current_block_nrow)
3836 std::ostringstream error_message;
3837 error_message <<
"First block has nrow = " << current_block_nrow
3838 <<
". But martrix_pt(" << block_row_i
3839 <<
"," << block_col_i <<
") has nrow = " 3840 << current_block_nrow <<
".\n";
3842 OOMPH_CURRENT_FUNCTION,
3843 OOMPH_EXCEPTION_LOCATION);
3850 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
3853 const unsigned first_block_ncol = matrix_pt(0,block_col_i)->
ncol();
3855 for (
unsigned block_row_i = 1; block_row_i < nblockrow; block_row_i++)
3858 const unsigned current_block_ncol
3859 = matrix_pt(block_row_i,block_col_i)->
ncol();
3861 if(first_block_ncol != current_block_ncol)
3863 std::ostringstream error_message;
3864 error_message <<
"First block has ncol = " << current_block_ncol
3865 <<
". But martrix_pt(" << block_row_i
3866 <<
"," << block_col_i <<
") has ncol = " 3867 << current_block_ncol <<
".\n";
3869 OOMPH_CURRENT_FUNCTION,
3870 OOMPH_EXCEPTION_LOCATION);
3876 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3880 = *(matrix_pt(block_row_i,0)->distribution_pt());
3883 for (
unsigned block_col_i = 1; block_col_i < nblockcol; block_col_i++)
3887 = matrix_pt(block_row_i,block_col_i)->distribution_pt();
3890 if(first_dist != current_dist)
3892 std::ostringstream error_message;
3893 error_message <<
"First distribution of block row " << block_row_i
3894 <<
" is different from the distribution from " 3895 <<
"martrix_pt(" << block_row_i
3896 <<
"," << block_col_i <<
").\n";
3898 OOMPH_CURRENT_FUNCTION,
3899 OOMPH_EXCEPTION_LOCATION);
3910 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3913 unsigned block_nrow_local = matrix_pt(block_row_i,0)->nrow_local();
3916 for (
unsigned local_row_i = 0; local_row_i < block_nrow_local;
3919 double abs_sum_of_row = 0;
3921 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
3926 const int* row_start = block_pt->
row_start();
3930 for (
int val_i = row_start[local_row_i];
3931 val_i < row_start[local_row_i+1]; val_i++)
3933 abs_sum_of_row += fabs(value[val_i]);
3937 inf_norm = std::max(inf_norm,abs_sum_of_row);
3942 #ifdef OOMPH_HAS_MPI 3944 if ( matrix_pt(0,0)->distributed() && comm_pt->nproc() > 1)
3946 MPI_Allreduce(&inf_norm,&inf_norm_local,1,MPI_DOUBLE,MPI_MAX,
3947 comm_pt->mpi_comm());
3949 inf_norm = inf_norm_local;
3980 const unsigned nblockrow = matrix_pt.
nrow();
3981 const unsigned nblockcol = matrix_pt.
ncol();
3985 if(matrix_pt.
nrow() == 0)
3987 std::ostringstream error_message;
3988 error_message <<
"There are no matrices... \n";
3990 OOMPH_CURRENT_FUNCTION,
3991 OOMPH_EXCEPTION_LOCATION);
3997 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
3999 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
4001 if(matrix_pt(block_row_i,block_col_i) == 0)
4003 std::ostringstream error_message;
4004 error_message <<
"The pointer martrix_pt(" << block_row_i
4005 <<
"," << block_col_i <<
") is null.\n";
4007 OOMPH_CURRENT_FUNCTION,
4008 OOMPH_EXCEPTION_LOCATION);
4011 if(!matrix_pt(block_row_i,block_col_i)->built())
4013 std::ostringstream error_message;
4014 error_message <<
"The matrix at martrix_pt(" << block_row_i
4015 <<
"," << block_col_i <<
") is not built.\n";
4017 OOMPH_CURRENT_FUNCTION,
4018 OOMPH_EXCEPTION_LOCATION);
4025 #ifdef OOMPH_HAS_MPI 4030 = matrix_pt(0,0)->distribution_pt()->communicator_pt();
4035 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4037 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
4041 = *(matrix_pt(block_row_i,block_col_i)
4042 ->distribution_pt()->communicator_pt());
4043 if(*comm_pt != current_block_comm)
4045 std::ostringstream error_message;
4046 error_message <<
"The communicator of block martrix_pt("<< block_row_i
4047 <<
"," << block_col_i <<
") is not the same as block " 4048 <<
"matrix_pt(0,0).\n";
4050 OOMPH_CURRENT_FUNCTION,
4051 OOMPH_EXCEPTION_LOCATION);
4058 if(comm_pt->nproc() > 1)
4061 bool first_distributed = matrix_pt(0,0)->distributed();
4063 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4065 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
4068 bool current_distributed
4069 = matrix_pt(block_row_i,block_col_i)->distributed();
4071 if(first_distributed != current_distributed)
4073 std::ostringstream error_message;
4074 error_message <<
"Block matrix_pt(" << block_row_i
4075 <<
","<<block_col_i<<
") and block matrix_pt(0,0) " 4076 <<
"have a different distributed boolean.\n";
4078 OOMPH_CURRENT_FUNCTION,
4079 OOMPH_EXCEPTION_LOCATION);
4090 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4093 const unsigned first_block_nrow = matrix_pt(block_row_i,0)->
nrow();
4096 for (
unsigned block_col_i = 1; block_col_i < nblockcol; block_col_i++)
4100 const unsigned current_block_nrow
4101 = matrix_pt(block_row_i,block_col_i)->
nrow();
4103 if(first_block_nrow != current_block_nrow)
4105 std::ostringstream error_message;
4106 error_message <<
"First block has nrow = " << current_block_nrow
4107 <<
". But martrix_pt(" << block_row_i
4108 <<
"," << block_col_i <<
") has nrow = " 4109 << current_block_nrow <<
".\n";
4111 OOMPH_CURRENT_FUNCTION,
4112 OOMPH_EXCEPTION_LOCATION);
4119 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
4122 const unsigned first_block_ncol = matrix_pt(0,block_col_i)->
ncol();
4124 for (
unsigned block_row_i = 1; block_row_i < nblockrow; block_row_i++)
4127 const unsigned current_block_ncol
4128 = matrix_pt(block_row_i,block_col_i)->
ncol();
4130 if(first_block_ncol != current_block_ncol)
4132 std::ostringstream error_message;
4133 error_message <<
"First block has ncol = " << current_block_ncol
4134 <<
". But martrix_pt(" << block_row_i
4135 <<
"," << block_col_i <<
") has ncol = " 4136 << current_block_ncol <<
".\n";
4138 OOMPH_CURRENT_FUNCTION,
4139 OOMPH_EXCEPTION_LOCATION);
4145 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4149 = *(matrix_pt(block_row_i,0)->distribution_pt());
4152 for (
unsigned block_col_i = 1; block_col_i < nblockcol; block_col_i++)
4156 = matrix_pt(block_row_i,block_col_i)->distribution_pt();
4159 if(first_dist != current_dist)
4161 std::ostringstream error_message;
4162 error_message <<
"First distribution of block row " << block_row_i
4163 <<
" is different from the distribution from " 4164 <<
"martrix_pt(" << block_row_i
4165 <<
"," << block_col_i <<
").\n";
4167 OOMPH_CURRENT_FUNCTION,
4168 OOMPH_EXCEPTION_LOCATION);
4178 double extreme_disc = 0;
4179 for (
unsigned block_row_i = 0; block_row_i < nblockrow; block_row_i++)
4182 unsigned block_nrow_local = matrix_pt(block_row_i,0)->nrow_local();
4185 for (
unsigned local_row_i = 0; local_row_i < block_nrow_local;
4188 double abs_sum_of_row = 0;
4190 for (
unsigned block_col_i = 0; block_col_i < nblockcol; block_col_i++)
4195 const int* row_start = block_pt->
row_start();
4199 for (
int val_i = row_start[local_row_i];
4200 val_i < row_start[local_row_i+1]; val_i++)
4202 abs_sum_of_row += fabs(value[val_i]);
4208 double* s_values = matrix_pt(block_row_i,block_row_i)->value();
4209 int* s_column_index = matrix_pt(block_row_i,block_row_i)->column_index();
4210 int* s_row_start = matrix_pt(block_row_i,block_row_i)->row_start();
4212 int s_first_row = matrix_pt(block_row_i,block_row_i)->first_row();
4215 double diagonal_value = 0;
4217 for (
int j = s_row_start[local_row_i];
4218 j < s_row_start[local_row_i+1] && !found; j++)
4220 if (s_column_index[j] ==
int(local_row_i + s_first_row))
4222 diagonal_value = s_values[j];
4230 std::ostringstream error_message;
4231 error_message <<
"The diagonal entry for the block(" 4232 << block_row_i<<
","<<block_row_i<<
")\n" 4233 <<
"on local row " << local_row_i <<
" does not exist." 4236 OOMPH_CURRENT_FUNCTION,
4237 OOMPH_EXCEPTION_LOCATION);
4241 abs_sum_of_row -= fabs(diagonal_value);
4245 if(diagonal_value > 0)
4247 double extreme_disc_local = diagonal_value + abs_sum_of_row;
4248 extreme_disc = std::max(extreme_disc_local,extreme_disc);
4252 double extreme_disc_local = diagonal_value - abs_sum_of_row;
4253 extreme_disc = std::min(extreme_disc_local,extreme_disc);
4259 #ifdef OOMPH_HAS_MPI 4260 double extreme_disc_local = extreme_disc;
4261 if ( matrix_pt(0,0)->distributed() && comm_pt->nproc() > 1)
4263 if(extreme_disc > 0)
4265 MPI_Allreduce(&extreme_disc,&extreme_disc_local,1,MPI_DOUBLE,MPI_MAX,
4266 comm_pt->mpi_comm());
4270 MPI_Allreduce(&extreme_disc,&extreme_disc_local,1,MPI_DOUBLE,MPI_MIN,
4271 comm_pt->mpi_comm());
4274 extreme_disc = extreme_disc_local;
4278 return extreme_disc;
4314 unsigned matrix_nrow = matrix_pt.
nrow();
4315 unsigned matrix_ncol = matrix_pt.
ncol();
4320 if(matrix_nrow == 0)
4322 std::ostringstream error_message;
4323 error_message <<
"There are no matrices to concatenate.\n";
4325 OOMPH_CURRENT_FUNCTION,
4326 OOMPH_EXCEPTION_LOCATION);
4330 if((matrix_nrow == 1) && (matrix_ncol == 1))
4332 std::ostringstream warning_message;
4333 warning_message <<
"There is only one matrix to concatenate...\n" 4334 <<
"This does not require concatenating...\n";
4336 OOMPH_CURRENT_FUNCTION,
4337 OOMPH_EXCEPTION_LOCATION);
4341 for(
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4343 for(
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
4345 if (!(matrix_pt(block_row_i,block_col_i)->built()))
4347 std::ostringstream error_message;
4349 <<
"The sub matrix (" << block_row_i <<
"," << block_col_i <<
")\n" 4350 <<
"is not built. \n";
4352 OOMPH_CURRENT_FUNCTION,
4353 OOMPH_EXCEPTION_LOCATION);
4360 for(
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4363 unsigned long current_block_nrow = matrix_pt(block_row_i,0)->
nrow();
4366 for(
unsigned block_col_i = 1; block_col_i < matrix_ncol; block_col_i++)
4369 unsigned long subblock_nrow
4370 = matrix_pt(block_row_i,block_col_i)->
nrow();
4372 if(current_block_nrow != subblock_nrow)
4374 std::ostringstream error_message;
4376 <<
"The sub matrix (" << block_row_i <<
"," << block_col_i <<
")\n" 4377 <<
"requires nrow = " << current_block_nrow
4378 <<
", but has nrow = " << subblock_nrow <<
".\n";
4380 OOMPH_CURRENT_FUNCTION,
4381 OOMPH_EXCEPTION_LOCATION);
4387 for(
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
4390 unsigned long current_block_ncol = matrix_pt(0,block_col_i)->
ncol();
4393 for(
unsigned block_row_i = 1; block_row_i < matrix_nrow; block_row_i++)
4396 unsigned long subblock_ncol
4397 = matrix_pt(block_row_i,block_col_i)->
ncol();
4399 if(current_block_ncol != subblock_ncol)
4401 std::ostringstream error_message;
4403 <<
"The sub matrix (" << block_row_i <<
"," << block_col_i <<
")\n" 4404 <<
"requires ncol = " << current_block_ncol
4405 <<
", but has ncol = " << subblock_ncol <<
".\n";
4407 OOMPH_CURRENT_FUNCTION,
4408 OOMPH_EXCEPTION_LOCATION);
4416 = matrix_pt(0,0)->distribution_pt()->communicator_pt();
4419 bool distributed = matrix_pt(0,0)->distributed();
4426 unsigned tmp_nrow = 0;
4427 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4429 tmp_nrow +=matrix_pt(block_row_i,0)->
nrow();
4434 result_matrix.
build(&tmp_distribution);
4444 unsigned tmp_nrow = 0;
4445 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4447 tmp_nrow +=matrix_pt(block_row_i,0)->
nrow();
4450 if(tmp_nrow != result_matrix.
nrow())
4452 std::ostringstream error_message;
4453 error_message <<
"The total number of rows from the matrices to\n" 4454 <<
"concatenate does not match the nrow from the\n" 4455 <<
"result matrix\n";
4457 OOMPH_CURRENT_FUNCTION,
4458 OOMPH_EXCEPTION_LOCATION);
4472 for(
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4474 for(
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
4477 = *(matrix_pt(block_row_i,block_col_i)
4478 ->distribution_pt()->communicator_pt());
4480 if(!(communicator == another_communicator))
4482 std::ostringstream error_message;
4484 <<
"The OomphCommunicator of the sub matrix (" 4485 << block_row_i <<
"," << block_col_i <<
")\n" 4486 <<
"does not have the same communicator as the result matrix. \n";
4488 OOMPH_CURRENT_FUNCTION,
4489 OOMPH_EXCEPTION_LOCATION);
4498 if(comm_pt->nproc() != 1)
4501 const bool res_distributed = result_matrix.
distributed();
4504 for(
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4506 for(
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
4508 const bool another_distributed
4509 = matrix_pt(block_row_i,block_col_i)->distributed();
4511 if(res_distributed != another_distributed)
4513 std::ostringstream error_message;
4515 <<
"The distributed boolean of the sub matrix (" 4516 << block_row_i <<
"," << block_col_i <<
")\n" 4517 <<
"is not the same as the result matrix. \n";
4519 OOMPH_CURRENT_FUNCTION,
4520 OOMPH_EXCEPTION_LOCATION);
4535 unsigned long res_ncol = 0;
4537 for(
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
4539 sum_of_ncol_up_to_block[block_col_i] = res_ncol;
4540 res_ncol += matrix_pt(0,block_col_i)->
ncol();
4545 if((comm_pt->nproc() == 1) || !distributed)
4550 unsigned long res_nnz = 0;
4551 for (
unsigned block_row_i = 0;
4552 block_row_i < matrix_nrow; block_row_i++)
4554 for (
unsigned block_col_i = 0;
4555 block_col_i < matrix_ncol; block_col_i++)
4557 res_nnz+=matrix_pt(block_row_i,block_col_i)->nnz();
4567 res_values.reserve(res_nnz);
4568 res_column_indices.reserve(res_nnz);
4569 res_row_start.reserve(result_matrix.
nrow()+1);
4574 int nnz_running_sum = 0;
4577 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4580 unsigned long block_row_nrow = matrix_pt(block_row_i,0)->
nrow();
4583 for (
unsigned row_i = 0; row_i < block_row_nrow; row_i++)
4586 res_row_start.push_back(nnz_running_sum);
4589 for (
unsigned block_col_i = 0;
4590 block_col_i < matrix_ncol; block_col_i++)
4594 = matrix_pt(block_row_i,block_col_i);
4597 double* current_block_values = current_block_pt->
value();
4598 int* current_block_column_indices
4600 int* current_block_row_start = current_block_pt->
row_start();
4602 for (
int val_i = current_block_row_start[row_i];
4603 val_i < current_block_row_start[row_i+1]; val_i++)
4605 res_values.push_back(current_block_values[val_i]);
4606 res_column_indices.push_back(current_block_column_indices[val_i]
4607 + sum_of_ncol_up_to_block[block_col_i]);
4611 nnz_running_sum += current_block_row_start[row_i+1]
4612 - current_block_row_start[row_i];
4618 res_row_start.push_back(res_nnz);
4621 result_matrix.
build(res_ncol,res_values,res_column_indices,res_row_start);
4626 #ifdef OOMPH_HAS_MPI 4630 bool enable_timing =
false;
4633 unsigned nproc = comm_pt->nproc();
4636 unsigned my_rank = comm_pt->my_rank();
4644 unsigned long sum_of_block_nrow = 0;
4646 double t_prep_data_start;
4658 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
4661 unsigned current_block_nrow_local = matrix_pt(block_row_i,0)
4665 unsigned current_block_row_first_row = matrix_pt(block_row_i,0)
4669 for(
unsigned sub_local_eqn = 0;
4670 sub_local_eqn < current_block_nrow_local; sub_local_eqn++)
4674 unsigned long res_global_eqn = sub_local_eqn
4675 + current_block_row_first_row + sum_of_block_nrow;
4682 unsigned res_p = res_distribution_pt
4687 unsigned res_first_row = res_distribution_pt->
first_row(res_p);
4688 unsigned res_local_eqn = res_global_eqn - res_first_row;
4692 unsigned long current_row_nnz = 0;
4693 for (
unsigned block_col_i = 0;
4694 block_col_i < matrix_ncol; block_col_i++)
4697 int* current_block_row_start = matrix_pt(block_row_i,block_col_i)
4701 current_row_nnz += current_block_row_start[sub_local_eqn+1]
4702 - current_block_row_start[sub_local_eqn];
4721 column_indices_to_send[res_p].push_back(res_local_eqn);
4722 column_indices_to_send[res_p].push_back(current_row_nnz);
4723 values_to_send[res_p].push_back(res_local_eqn);
4724 values_to_send[res_p].push_back(current_row_nnz);
4728 for (
unsigned block_col_i = 0;
4729 block_col_i < matrix_ncol; block_col_i++)
4733 = matrix_pt(block_row_i,block_col_i);
4736 double* current_block_values = current_block_pt->
value();
4737 int* current_block_column_indices
4739 int* current_block_row_start = current_block_pt->
row_start();
4742 for (
int val_i = current_block_row_start[sub_local_eqn];
4743 val_i < current_block_row_start[sub_local_eqn+1]; val_i++)
4746 values_to_send[res_p].push_back(current_block_values[val_i]);
4749 column_indices_to_send[res_p].push_back(
4750 current_block_column_indices[val_i]
4751 + sum_of_ncol_up_to_block[block_col_i]);
4757 sum_of_block_nrow += matrix_pt(block_row_i,0)->
nrow();
4764 double t_prep_data_time = t_prep_data_finish - t_prep_data_start;
4765 oomph_info <<
"Time for prep data: " << t_prep_data_time << std::endl;
4782 double t_total_ndata_start;
4788 unsigned total_ndata = 0;
4789 for (
unsigned rank = 0; rank < nproc; rank++)
4793 total_ndata += values_to_send[rank].size();
4800 double t_total_ndata_time= t_total_ndata_finish - t_total_ndata_start;
4801 oomph_info <<
"Time for total_ndata: " << t_total_ndata_time << std::endl;
4804 double t_flat_pack_start;
4811 send_values_data.reserve(total_ndata);
4812 send_column_indices_data.reserve(total_ndata);
4815 for (
unsigned rank = 0; rank < nproc; rank++)
4819 send_displacement[rank] = send_values_data.size();
4827 unsigned n_data = values_to_send[rank].size();
4828 for (
unsigned j = 0; j < n_data; j++)
4830 send_values_data.push_back(values_to_send[rank][j]);
4831 send_column_indices_data.push_back(
4832 column_indices_to_send[rank][j]);
4838 send_n[rank] = send_values_data.size() - send_displacement[rank];
4844 double t_flat_pack_time = t_flat_pack_finish - t_flat_pack_start;
4845 oomph_info <<
"t_flat_pack_time: " << t_flat_pack_time << std::endl;
4848 double t_sendn_start;
4855 MPI_Alltoall(&send_n[0],1,MPI_INT,&receive_n[0],1,MPI_INT,
4856 comm_pt->mpi_comm());
4861 double t_sendn_time = t_sendn_finish - t_sendn_start;
4862 oomph_info <<
"t_sendn_time: " << t_sendn_time << std::endl;
4870 int receive_data_count = 0;
4871 for (
unsigned rank = 0; rank < nproc; rank++)
4873 receive_displacement[rank] = receive_data_count;
4874 receive_data_count += receive_n[rank];
4879 if(receive_data_count == 0){receive_data_count++;}
4885 if(send_values_data.size()==0){send_values_data.resize(1);}
4887 double t_send_data_start;
4892 MPI_Alltoallv(&send_values_data[0],&send_n[0],&send_displacement[0],
4894 &receive_values_data[0],&receive_n[0],
4895 &receive_displacement[0],
4897 comm_pt->mpi_comm());
4900 MPI_Alltoallv(&send_column_indices_data[0],&send_n[0],
4901 &send_displacement[0],
4903 &receive_column_indices_data[0],&receive_n[0],
4904 &receive_displacement[0],
4906 comm_pt->mpi_comm());
4911 double t_send_data_time = t_send_data_finish - t_send_data_start;
4912 oomph_info <<
"t_send_data_time: " << t_send_data_time << std::endl;
4925 unsigned res_nrow_local = res_distribution_pt->
nrow_local();
4938 unsigned long res_nnz_local = 0;
4940 double t_locations_start;
4945 unsigned location_i = 0;
4946 unsigned my_column_indices_to_send_size
4947 = column_indices_to_send[my_rank].size();
4948 while(location_i < my_column_indices_to_send_size)
4950 unsigned current_local_eqn
4951 = column_indices_to_send[my_rank][location_i++];
4953 unsigned current_nnz
4954 = column_indices_to_send[my_rank][location_i++];
4959 value_column_locations[current_local_eqn][1] = current_nnz;
4962 res_nnz_local += current_nnz;
4965 value_column_locations[current_local_eqn][2] = location_i;
4968 location_i += current_nnz;
4974 bool data_has_been_received =
false;
4975 unsigned send_rank = 0;
4976 while(send_rank < nproc)
4978 if(receive_n[send_rank] > 0)
4980 data_has_been_received =
true;
4987 if(data_has_been_received)
4989 unsigned receive_column_indices_data_size
4990 = receive_column_indices_data.size();
4991 while(location_i < receive_column_indices_data_size)
4993 unsigned current_local_eqn
4994 = receive_column_indices_data[location_i++];
4995 unsigned current_nnz = receive_column_indices_data[location_i++];
4998 value_column_locations[current_local_eqn][0] = 1;
5001 value_column_locations[current_local_eqn][1] = current_nnz;
5004 res_nnz_local += current_nnz;
5007 value_column_locations[current_local_eqn][2] = location_i;
5010 location_i += current_nnz;
5017 double t_locations_time = t_locations_finish - t_locations_start;
5018 oomph_info <<
"t_locations_time: " << t_locations_time << std::endl;
5021 double t_fillvecs_start;
5031 res_column_indices.reserve(res_nnz_local);
5032 res_values.reserve(res_nnz_local);
5033 res_row_start.reserve(res_nrow_local+1);
5037 int nnz_running_sum = 0;
5040 for (
unsigned local_row_i = 0;
5041 local_row_i < res_nrow_local; local_row_i++)
5044 res_row_start.push_back(nnz_running_sum);
5046 bool data_is_from_other_proc
5047 = bool(value_column_locations[local_row_i][0]);
5049 unsigned row_i_nnz = value_column_locations[local_row_i][1];
5051 unsigned row_i_offset = value_column_locations[local_row_i][2];
5053 if(data_is_from_other_proc)
5058 res_column_indices.insert(res_column_indices.end(),
5059 receive_column_indices_data.begin()
5061 receive_column_indices_data.begin()
5062 +row_i_offset+row_i_nnz);
5064 res_values.insert(res_values.end(),
5065 receive_values_data.begin()+row_i_offset,
5066 receive_values_data.begin()+row_i_offset+row_i_nnz);
5070 res_column_indices.insert(res_column_indices.end(),
5071 column_indices_to_send[my_rank].begin()
5073 column_indices_to_send[my_rank].begin()
5074 +row_i_offset+row_i_nnz);
5076 res_values.insert(res_values.end(),
5077 values_to_send[my_rank].begin()+row_i_offset,
5078 values_to_send[my_rank].begin()+row_i_offset+row_i_nnz);
5082 nnz_running_sum += row_i_nnz;
5086 res_row_start.push_back(res_nnz_local);
5091 double t_fillvecs_time = t_fillvecs_finish - t_fillvecs_start;
5092 oomph_info <<
"t_fillvecs_time: " << t_fillvecs_time << std::endl;
5095 double t_buildres_start;
5100 result_matrix.
build(res_ncol,res_values,res_column_indices,res_row_start);
5105 double t_buildres_time = t_buildres_finish - t_buildres_start;
5106 oomph_info <<
"t_buildres_time: " << t_buildres_time << std::endl;
5171 unsigned matrix_nrow = matrix_pt.
nrow();
5172 unsigned matrix_ncol = matrix_pt.
ncol();
5181 if(matrix_nrow == 0 || matrix_ncol == 0)
5183 std::ostringstream error_message;
5184 error_message <<
"There are no matrices to concatenate.\n";
5186 OOMPH_CURRENT_FUNCTION,
5187 OOMPH_EXCEPTION_LOCATION);
5191 if((matrix_nrow == 1) && (matrix_ncol == 1))
5193 std::ostringstream warning_message;
5194 warning_message <<
"There is only one matrix to concatenate...\n" 5195 <<
"This does not require concatenating...\n";
5197 OOMPH_CURRENT_FUNCTION,
5198 OOMPH_EXCEPTION_LOCATION);
5206 if(matrix_nrow != row_distribution_pt.size())
5208 std::ostringstream error_message;
5209 error_message <<
"The number of row distributions must be the same as\n" 5210 <<
"the number of block rows.";
5212 OOMPH_CURRENT_FUNCTION,
5213 OOMPH_EXCEPTION_LOCATION);
5218 if(matrix_ncol != col_distribution_pt.size())
5220 std::ostringstream error_message;
5221 error_message <<
"The number of column distributions must be the same as\n" 5222 <<
"the number of block columns.";
5224 OOMPH_CURRENT_FUNCTION,
5225 OOMPH_EXCEPTION_LOCATION);
5229 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5231 if(row_distribution_pt[block_row_i] == 0)
5233 std::ostringstream error_message;
5234 error_message <<
"The row distribution pointer in position " 5235 << block_row_i <<
" is null.\n";
5237 OOMPH_CURRENT_FUNCTION,
5238 OOMPH_EXCEPTION_LOCATION);
5243 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5245 if(col_distribution_pt[block_col_i] == 0)
5247 std::ostringstream error_message;
5248 error_message <<
"The column distribution pointer in position " 5249 << block_col_i <<
" is null.\n";
5251 OOMPH_CURRENT_FUNCTION,
5252 OOMPH_EXCEPTION_LOCATION);
5258 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5260 if(!row_distribution_pt[block_row_i]->built())
5262 std::ostringstream error_message;
5263 error_message <<
"The distribution pointer in position " 5264 << block_row_i <<
" is not built.\n";
5266 OOMPH_CURRENT_FUNCTION,
5267 OOMPH_EXCEPTION_LOCATION);
5271 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5273 if(!col_distribution_pt[block_col_i]->built())
5275 std::ostringstream error_message;
5276 error_message <<
"The distribution pointer in position " 5277 << block_col_i <<
" is not built.\n";
5279 OOMPH_CURRENT_FUNCTION,
5280 OOMPH_EXCEPTION_LOCATION);
5286 = *(row_distribution_pt[0]->communicator_pt());
5288 for (
unsigned block_row_i = 1; block_row_i < matrix_nrow; block_row_i++)
5291 = *(row_distribution_pt[block_row_i]->communicator_pt());
5293 if(first_row_comm != current_comm)
5295 std::ostringstream error_message;
5296 error_message <<
"The communicator from the row distribution in position " 5297 << block_row_i <<
" is not the same as the first " 5298 <<
"communicator from row_distribution_pt";
5300 OOMPH_CURRENT_FUNCTION,
5301 OOMPH_EXCEPTION_LOCATION);
5307 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5310 = *(col_distribution_pt[block_col_i]->communicator_pt());
5312 if(first_row_comm != current_comm)
5314 std::ostringstream error_message;
5315 error_message <<
"The communicator from the col distribution in position " 5316 << block_col_i <<
" is not the same as the first " 5317 <<
"communicator from row_distribution_pt";
5319 OOMPH_CURRENT_FUNCTION,
5320 OOMPH_EXCEPTION_LOCATION);
5326 for(
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5328 for(
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5330 if (matrix_pt(block_row_i,block_col_i) != 0 &&
5331 !(matrix_pt(block_row_i,block_col_i)->built()))
5333 std::ostringstream error_message;
5335 <<
"The sub matrix_pt(" << block_row_i <<
"," << block_col_i <<
")\n" 5336 <<
"is not built.\n";
5338 OOMPH_CURRENT_FUNCTION,
5339 OOMPH_EXCEPTION_LOCATION);
5346 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5348 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5350 if(matrix_pt(block_row_i,block_col_i) != 0)
5353 = *(matrix_pt(block_row_i,block_col_i)
5355 ->communicator_pt());
5356 if(first_row_comm != current_comm)
5358 std::ostringstream error_message;
5360 <<
"The sub matrix_pt(" << block_row_i <<
","<<block_col_i<<
")\n" 5361 <<
"does not have the same communicator pointer as those in\n" 5362 <<
"(row|col)_distribution_pt.\n";
5364 OOMPH_CURRENT_FUNCTION,
5365 OOMPH_EXCEPTION_LOCATION);
5373 for(
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5376 unsigned long current_block_nrow = row_distribution_pt[block_row_i]
5380 for(
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5383 if(matrix_pt(block_row_i,block_col_i) != 0)
5386 unsigned long subblock_nrow
5387 = matrix_pt(block_row_i,block_col_i)->
nrow();
5389 if(current_block_nrow != subblock_nrow)
5391 std::ostringstream error_message;
5393 <<
"The sub matrix (" << block_row_i <<
"," << block_col_i <<
")\n" 5394 <<
"requires nrow = " << current_block_nrow
5395 <<
", but has nrow = " << subblock_nrow <<
".\n" 5396 <<
"Either the row_distribution_pt is incorrect or " 5397 <<
"the sub matrices are incorrect.\n";
5399 OOMPH_CURRENT_FUNCTION,
5400 OOMPH_EXCEPTION_LOCATION);
5407 for(
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5411 unsigned current_block_ncol = col_distribution_pt[block_col_i]
5414 for(
unsigned block_row_i = 0;
5415 block_row_i < matrix_nrow; block_row_i++)
5417 if(matrix_pt(block_row_i,block_col_i) != 0)
5420 unsigned subblock_ncol
5421 = matrix_pt(block_row_i,block_col_i)->
ncol();
5423 if(current_block_ncol != subblock_ncol)
5425 std::ostringstream error_message;
5427 <<
"The sub matrix (" << block_row_i <<
"," << block_col_i <<
")\n" 5428 <<
"requires ncol = " << current_block_ncol
5429 <<
", but has ncol = " << subblock_ncol <<
".\n" 5430 <<
"Either the col_distribution_pt is incorrect or " 5431 <<
"the sub matrices are incorrect.\n";
5433 OOMPH_CURRENT_FUNCTION,
5434 OOMPH_EXCEPTION_LOCATION);
5444 for (
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5448 = row_distribution_pt[block_row_i];
5451 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5453 if(matrix_pt(block_row_i,block_col_i) != 0)
5457 = matrix_pt(block_row_i,block_col_i)->distribution_pt();
5460 if((*block_row_distribution_pt) != (*current_block_distribution_pt))
5462 std::ostringstream error_message;
5463 error_message <<
"Sub block("<<block_row_i<<
","<<block_col_i<<
")" 5464 <<
"does not have the same distributoin as the first" 5465 <<
"block in this block row.\n" 5466 <<
"All distributions on a block row must be the same" 5467 <<
"for this function to concatenate matrices.\n";
5469 OOMPH_CURRENT_FUNCTION,
5470 OOMPH_EXCEPTION_LOCATION);
5479 = row_distribution_pt[0]->communicator_pt();
5482 unsigned nblock_row = matrix_nrow;
5493 result_matrix.
build(&tmp_distribution);
5505 wanted_distribution);
5509 std::ostringstream error_message;
5510 error_message <<
"The result distribution is not correct.\n" 5511 <<
"Please call the function without a result\n" 5512 <<
"distribution (clear the result matrix) or check the\n" 5513 <<
"distribution of the result matrix.\n" 5514 <<
"The result distribution must be the same as the one \n" 5516 <<
"LinearAlgebraDistributionHelpers::concatenate(...)";
5518 OOMPH_CURRENT_FUNCTION,
5519 OOMPH_EXCEPTION_LOCATION);
5540 = *(row_distribution_pt[0]->communicator_pt());
5542 if(res_comm != first_comm)
5544 std::ostringstream error_message;
5546 <<
"The OomphCommunicator of the result matrix is not the same as the " 5549 OOMPH_CURRENT_FUNCTION,
5550 OOMPH_EXCEPTION_LOCATION);
5557 if(comm_pt->nproc() != 1)
5560 const bool res_distributed = result_matrix.
distributed();
5563 for(
unsigned block_row_i = 0; block_row_i < matrix_nrow; block_row_i++)
5565 for(
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5567 if(matrix_pt(block_row_i,block_col_i) != 0)
5569 const bool another_distributed
5570 = matrix_pt(block_row_i,block_col_i)->distributed();
5572 if(res_distributed != another_distributed)
5574 std::ostringstream error_message;
5576 <<
"The distributed boolean of the sub matrix (" 5577 << block_row_i <<
"," << block_col_i <<
")\n" 5578 <<
"is not the same as the result matrix. \n";
5580 OOMPH_CURRENT_FUNCTION,
5581 OOMPH_EXCEPTION_LOCATION);
5588 const bool first_row_distribution_distributed
5589 = row_distribution_pt[0]->distributed();
5591 for (
unsigned block_row_i = 1; block_row_i < matrix_nrow; block_row_i++)
5593 const bool another_distributed
5594 = row_distribution_pt[block_row_i]->distributed();
5596 if(first_row_distribution_distributed != another_distributed)
5598 std::ostringstream error_message;
5600 <<
"The distributed boolean of row_distribution_pt[" 5601 << block_row_i <<
"]\n" 5602 <<
"is not the same as the one from row_distribution_pt[0]. \n";
5604 OOMPH_CURRENT_FUNCTION,
5605 OOMPH_EXCEPTION_LOCATION);
5610 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5612 const bool another_distributed
5613 = col_distribution_pt[block_col_i]->distributed();
5615 if(first_row_distribution_distributed != another_distributed)
5617 std::ostringstream error_message;
5619 <<
"The distributed boolean of col_distribution_pt[" 5620 << block_col_i <<
"]\n" 5621 <<
"is not the same as the one from row_distribution_pt[0]. \n";
5623 OOMPH_CURRENT_FUNCTION,
5624 OOMPH_EXCEPTION_LOCATION);
5633 unsigned nproc = comm_pt->nproc();
5640 unsigned res_nrow_local = res_distribution_pt->
nrow_local();
5643 unsigned nblock_col = matrix_ncol;
5647 std::vector<std::vector<unsigned> > col_offset(
5649 std::vector<unsigned>(nblock_col));
5651 for (
unsigned proc_i = 0; proc_i < nproc; proc_i++)
5653 for (
unsigned block_i = 0; block_i < nblock_col; block_i++)
5655 col_offset[proc_i][block_i] = off;
5656 off +=col_distribution_pt[block_i]->nrow_local(proc_i);
5665 std::vector<std::vector<unsigned> > p_for_rows(
5666 nblock_col,std::vector<unsigned>());
5668 for (
unsigned blocki = 0; blocki < nblock_col; blocki++)
5670 int blockinrow = col_distribution_pt[blocki]->nrow();
5671 p_for_rows[blocki].resize(blockinrow);
5673 for (
int rowi = 0; rowi < blockinrow; rowi++)
5676 int b_first_row = col_distribution_pt[blocki]->first_row(p);
5677 int b_nrow_local = col_distribution_pt[blocki]->nrow_local(p);
5679 while (rowi < b_first_row ||
5680 rowi >= b_nrow_local + b_first_row)
5683 b_first_row = col_distribution_pt[blocki]->first_row(p);
5684 b_nrow_local = col_distribution_pt[blocki]->nrow_local(p);
5686 p_for_rows[blocki][rowi] = p;
5692 unsigned long res_nnz = 0;
5693 for (
unsigned row_i = 0; row_i < nblock_row; row_i++)
5695 for (
unsigned col_i = 0; col_i < nblock_col; col_i++)
5697 if(matrix_pt(row_i,col_i) !=0)
5699 res_nnz += matrix_pt(row_i,col_i)->nnz();
5718 int* res_row_start =
new int[res_nrow_local+1];
5719 int* res_column_index =
new int[res_nnz];
5720 double* res_value =
new double[res_nnz];
5723 res_row_start[0] = 0;
5726 unsigned long res_i = 0;
5727 unsigned long res_row_i = 0;
5728 for (
unsigned i = 0;
i < nblock_row;
i++)
5731 unsigned block_nrow = row_distribution_pt[
i]->nrow_local();
5732 for (
unsigned k = 0; k < block_nrow; k++)
5735 res_row_start[res_row_i+1] = res_row_start[res_row_i];
5738 for (
unsigned j = 0; j < nblock_col; j++)
5741 if (matrix_pt(
i,j) != 0)
5744 int* b_row_start = matrix_pt(
i,j)->row_start();
5745 int* b_column_index = matrix_pt(
i,j)->column_index();
5746 double* b_value = matrix_pt(
i,j)->value();
5750 int numEleToCopy = b_row_start[k+1] - b_row_start[k];
5751 memcpy(res_value+res_i,b_value+b_row_start[k],numEleToCopy*
sizeof(
double));
5753 for (
int l = b_row_start[k]; l < b_row_start[k+1]; l++)
5759 unsigned p = p_for_rows[j][b_column_index[l]];
5761 int b_first_row = col_distribution_pt[j]->first_row(p);
5774 int eqn = b_column_index[l]-b_first_row;
5778 res_column_index[res_i] = col_offset[p][j]+eqn;
5779 res_row_start[res_row_i+1]++;
5795 unsigned res_ncol = 0;
5796 for (
unsigned block_col_i = 0; block_col_i < matrix_ncol; block_col_i++)
5798 res_ncol += col_distribution_pt[block_col_i]->nrow();
5824 unsigned matrix_nrow = matrix_pt.
nrow();
5825 unsigned matrix_ncol = matrix_pt.
ncol();
5828 if(matrix_nrow == 0)
5830 std::ostringstream error_message;
5831 error_message <<
"There are no matrices to concatenate.\n";
5833 OOMPH_CURRENT_FUNCTION,
5834 OOMPH_EXCEPTION_LOCATION);
5838 if(matrix_nrow != matrix_ncol)
5840 std::ostringstream error_message;
5841 error_message<<
"The number of block rows and block columns\n" 5842 <<
"must be the same. Otherwise, call the other\n" 5843 <<
"concatenate_without_communication function, passing in\n" 5844 <<
"a Vector of distributions describing how to permute the\n" 5847 OOMPH_CURRENT_FUNCTION,
5848 OOMPH_EXCEPTION_LOCATION);
5853 block_distribution_pt,block_distribution_pt,matrix_pt,result_matrix);
unsigned long N
Number of rows.
int * column_index()
Access to C-style column index array.
unsigned long nnz() const
Return the number of nonzero entries (the local nnz)
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...
Class of matrices containing doubles, and stored as a DenseMatrix<double>, but with solving functiona...
unsigned long ncol() const
Return the number of columns of the matrix.
unsigned long nrow() const
Return the number of rows of the matrix.
void concatenate_without_communication(const Vector< LinearAlgebraDistribution *> &block_distribution_pt, const DenseMatrix< CRDoubleMatrix *> &matrix_pt, CRDoubleMatrix &result_matrix)
Concatenate CRDoubleMatrix matrices. This calls the other concatenate_without_communication(...) function, passing block_distribution_pt as both the row_distribution_pt and col_distribution_pt. This should only be called for block square matrices.
double inf_norm() const
returns the inf-norm of this matrix
int * Column_start
Start index for column.
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
double inf_norm(const DenseMatrix< CRDoubleMatrix *> &matrix_pt)
Compute infinity (maximum) norm of sub blocks as if it was one matrix.
unsigned long ncol() const
Return the number of columns of the matrix.
LinearSolver * Default_linear_solver_pt
void redistribute(const LinearAlgebraDistribution *const &dist_pt)
virtual ~DenseDoubleMatrix()
Destructor.
bool built() const
access function to the Built flag - indicates whether the matrix has been build - i...
void add(const CRDoubleMatrix &matrix_in, CRDoubleMatrix &result_matrix) const
element-wise addition of this matrix with matrix_in.
double * values_pt()
access function to the underlying values
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...
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...
int * row_index()
Access to C-style row index array.
unsigned long N
Number of rows.
virtual void ludecompose()
LU decomposition using SuperLU if matrix is not distributed or distributed onto a single processor...
OomphCommunicator * communicator_pt() const
const access to the communicator pointer
virtual void lubksub(DoubleVector &rhs)
LU backsubstitution.
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
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 ...
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...
virtual void ludecompose()
LU decomposition using SuperLU.
void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Multiply the transposed matrix by the vector x: soln=A^T x.
virtual ~CRDoubleMatrix()
Destructor.
unsigned nrow() const
access function to the number of global rows.
unsigned first_row() const
access function for the first row on this processor. If not distributed then this is just zero...
bool distributed() const
access function to the distributed - indicates whether the distribution is serial or distributed ...
. SuperLU Project Solver class. This is a combined wrapper for both SuperLU and SuperLU Dist...
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...
DenseDoubleMatrix()
Constructor, set the default linear solver.
double * value()
Access to C-style value array.
LinearSolver * Linear_solver_pt
unsigned long nnz() const
Return the number of nonzero entries.
int * Row_index
Row index.
void solve(DoubleVector &rhs)
Complete LU solve (replaces matrix by its LU decomposition and overwrites RHS with solution)...
bool distribution_built() const
virtual void lubksub(DoubleVector &rhs)
LU back solve for given RHS.
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...
bool distributed() const
distribution is serial or distributed
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.
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
Dense LU decomposition-based solve of full assembled linear system. VERY inefficient but useful to il...
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
unsigned long ncol() const
Return the number of columns of the matrix.
CRDoubleMatrix * global_matrix() const
if this matrix is distributed then a the equivalent global matrix is built using new and returned...
A class for compressed column matrices: a sparse matrix format The class is passed as the MATRIX_TYPE...
void initialise(const double &v)
initialise the whole vector with value v
unsigned long M
Number of columns.
virtual void lubksub(DoubleVector &rhs)
LU back solve for given RHS.
unsigned nrow_local() const
access function for the num of local rows on this processor. If no MPI then Nrow is returned...
void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Multiply the transposed matrix by the vector x: soln=A^T x.
CRDoubleMatrix()
Default constructor.
Vector< double > diagonal_entries() const
returns a Vector of diagonal entries of this matrix. This only works with square matrices. This condition may be relaxed in the future if need be.
double timer()
returns the time in seconds after some point in past
void sort_entries()
Sorts the entries associated with each row of the matrix in the column index vector and the value vec...
unsigned rank_of_global_row(const unsigned i) const
return the processor rank of the global row number i
A class for compressed column matrices that store doubles.
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...
virtual void clean_up_memory()
Empty virtual function that can be overloaded in specific linear solvers to clean up any memory that ...
unsigned long nrow() const
Return the number of rows of the matrix.
unsigned nrow() const
access function to the number of global rows.
void multiply_transpose(const DoubleVector &x, DoubleVector &soln) const
Multiply the transposed matrix by the vector x: soln=A^T x.
unsigned long ncol() const
Return the number of columns of the matrix.
unsigned long M
Number of columns.
virtual void ludecompose()
LU decomposition using DenseLU (default linea solver)
void eigenvalues_by_jacobi(Vector< double > &eigen_val, DenseMatrix< double > &eigen_vect) const
Determine eigenvalues and eigenvectors, using Jacobi rotations. Only for symmetric matrices...
double * Value
Internal representation of the matrix values, a pointer.
unsigned nrow_local() const
access function for the num of local rows on this processor.
Class for dense matrices, storing all the values of the matrix as a pointer to a pointer with assorte...
int * column_start()
Access to C-style column_start array.
A vector in the mathematical sense, initially developed for linear algebra type applications. If MPI then this vector can be distributed - its distribution is described by the LinearAlgebraDistribution object at Distribution_pt. Data is stored in a C-style pointer vector (double*)
unsigned long nrow() const
Return the number of rows of the matrix.
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...
double * Matrixdata
Internal representation of matrix as a pointer to data.
CCDoubleMatrix()
Default constructor.
int * row_start()
Access to C-style row_start array.
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...
unsigned Matrix_matrix_multiply_method
Flag to determine which matrix-matrix multiplication method is used.
void concatenate(const DenseMatrix< CRDoubleMatrix *> &matrix_pt, CRDoubleMatrix &result_matrix)
Concatenate CRDoubleMatrix matrices. The in matrices are concatenated such that the block structure o...
A class for compressed row matrices. This is a distributable object.
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 ...
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
void get_matrix_transpose(CRDoubleMatrix *result) const
Returns the transpose of this matrix.
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 multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
double * value()
Access to C-style value array.
unsigned long nrow() const
Return the number of rows of the matrix.
unsigned long Nnz
Number of non-zero values (i.e. size of Value array)
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 ...
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
void resize(const unsigned long &n)