17 #include <deal.II/lac/scalapack.h> 19 #ifdef DEAL_II_WITH_SCALAPACK 21 # include <deal.II/base/array_view.h> 22 # include <deal.II/base/mpi.h> 23 # include <deal.II/base/mpi.templates.h> 24 # include <deal.II/base/std_cxx14/memory.h> 26 # include <deal.II/lac/scalapack.templates.h> 28 # ifdef DEAL_II_WITH_HDF5 32 DEAL_II_NAMESPACE_OPEN
34 # ifdef DEAL_II_WITH_HDF5 36 template <
typename number>
38 hdf5_type_id(
const number *)
46 hdf5_type_id(
const double *)
48 return H5T_NATIVE_DOUBLE;
52 hdf5_type_id(
const float *)
54 return H5T_NATIVE_FLOAT;
58 hdf5_type_id(
const int *)
60 return H5T_NATIVE_INT;
64 hdf5_type_id(
const unsigned int *)
66 return H5T_NATIVE_UINT;
70 hdf5_type_id(
const char *)
72 return H5T_NATIVE_CHAR;
74 # endif // DEAL_II_WITH_HDF5 78 template <
typename NumberType>
82 const std::shared_ptr<const Utilities::MPI::ProcessGrid> &process_grid,
89 , first_process_column(0)
103 template <
typename NumberType>
106 const std::shared_ptr<const Utilities::MPI::ProcessGrid> process_grid,
119 template <
typename NumberType>
124 const std::shared_ptr<const Utilities::MPI::ProcessGrid> &process_grid,
129 Assert(row_block_size_ > 0,
ExcMessage(
"Row block size has to be positive."));
130 Assert(column_block_size_ > 0,
131 ExcMessage(
"Column block size has to be positive."));
133 row_block_size_ <= n_rows_,
135 "Row block size can not be greater than the number of rows of the matrix"));
137 column_block_size_ <= n_columns_,
139 "Column block size can not be greater than the number of columns of the matrix"));
141 state = LAPACKSupport::State::matrix;
142 property = property_;
149 if (
grid->mpi_process_is_active)
154 &(
grid->this_process_row),
156 &(
grid->n_process_rows));
159 &(
grid->this_process_column),
161 &(
grid->n_process_columns));
175 &(
grid->blacs_context),
187 for (
unsigned int i = 0; i < 9; ++i)
194 template <
typename NumberType>
198 const std::shared_ptr<const Utilities::MPI::ProcessGrid> process_grid,
202 reinit(size, size, process_grid, block_size, block_size, property);
207 template <
typename NumberType>
212 property = property_;
217 template <
typename NumberType>
226 template <
typename NumberType>
235 template <
typename NumberType>
248 if (
grid->mpi_process_is_active)
256 local_el(i, j) = matrix(glob_i, glob_j);
266 template <
typename NumberType>
272 const int i = loc_row + 1;
275 &(
grid->this_process_row),
277 &(
grid->n_process_rows)) -
283 template <
typename NumberType>
290 const int j = loc_column + 1;
293 &(
grid->this_process_column),
295 &(
grid->n_process_columns)) -
301 template <
typename NumberType>
314 if (
grid->mpi_process_is_active)
322 matrix(glob_i, glob_j) =
local_el(i, j);
334 for (
unsigned int i = 0; i < matrix.
n(); ++i)
335 for (
unsigned int j = i + 1; j < matrix.
m(); ++j)
338 for (
unsigned int i = 0; i < matrix.
n(); ++i)
339 for (
unsigned int j = 0; j < i; ++j)
346 for (
unsigned int i = 0; i < matrix.
n(); ++i)
347 for (
unsigned int j = i + 1; j < matrix.
m(); ++j)
348 matrix(i, j) = matrix(j, i);
349 else if (
uplo ==
'U')
350 for (
unsigned int i = 0; i < matrix.
n(); ++i)
351 for (
unsigned int j = 0; j < i; ++j)
352 matrix(i, j) = matrix(j, i);
358 template <
typename NumberType>
362 const std::pair<unsigned int, unsigned int> &offset_A,
363 const std::pair<unsigned int, unsigned int> &offset_B,
364 const std::pair<unsigned int, unsigned int> &submatrix_size)
const 367 if (submatrix_size.first == 0 || submatrix_size.second == 0)
371 Assert(offset_A.first < (
unsigned int)(
n_rows - submatrix_size.first + 1),
374 offset_A.second < (
unsigned int)(
n_columns - submatrix_size.second + 1),
378 Assert(offset_B.first < (
unsigned int)(B.
n_rows - submatrix_size.first + 1),
381 offset_B.second < (
unsigned int)(B.
n_columns - submatrix_size.second + 1),
386 int ierr, comparison;
387 ierr = MPI_Comm_compare(
grid->mpi_communicator,
388 B.
grid->mpi_communicator,
391 Assert(comparison == MPI_IDENT,
392 ExcMessage(
"Matrix A and B must have a common MPI Communicator"));
400 int union_blacs_context = Csys2blacs_handle(this->
grid->mpi_communicator);
401 const char *order =
"Col";
402 int union_n_process_rows =
404 int union_n_process_columns = 1;
405 Cblacs_gridinit(&union_blacs_context,
407 union_n_process_rows,
408 union_n_process_columns);
410 int n_grid_rows_A, n_grid_columns_A, my_row_A, my_column_A;
411 Cblacs_gridinfo(this->
grid->blacs_context,
418 const bool in_context_A =
419 (my_row_A >= 0 && my_row_A < n_grid_rows_A) &&
420 (my_column_A >= 0 && my_column_A < n_grid_columns_A);
423 int n_grid_rows_B, n_grid_columns_B, my_row_B, my_column_B;
424 Cblacs_gridinfo(B.
grid->blacs_context,
431 const bool in_context_B =
432 (my_row_B >= 0 && my_row_B < n_grid_rows_B) &&
433 (my_column_B >= 0 && my_column_B < n_grid_columns_B);
435 const int n_rows_submatrix = submatrix_size.first;
436 const int n_columns_submatrix = submatrix_size.second;
439 int ia = offset_A.first + 1, ja = offset_A.second + 1;
440 int ib = offset_B.first + 1, jb = offset_B.second + 1;
442 std::array<int, 9> desc_A, desc_B;
444 const NumberType *loc_vals_A =
nullptr;
445 NumberType * loc_vals_B =
nullptr;
455 loc_vals_A = &this->
values[0];
457 for (
unsigned int i = 0; i < desc_A.size(); ++i)
466 loc_vals_B = &B.
values[0];
468 for (
unsigned int i = 0; i < desc_B.size(); ++i)
474 pgemr2d(&n_rows_submatrix,
475 &n_columns_submatrix,
484 &union_blacs_context);
489 Cblacs_gridexit(union_blacs_context);
494 template <
typename NumberType>
502 if (this->
grid->mpi_process_is_active)
506 "Copying of ScaLAPACK matrices only implemented for dense matrices"));
507 if (dest.
grid->mpi_process_is_active)
511 "Copying of ScaLAPACK matrices only implemented for dense matrices"));
527 MPI_Group group_source, group_dest, group_union;
528 ierr = MPI_Comm_group(this->
grid->mpi_communicator, &group_source);
530 ierr = MPI_Comm_group(dest.
grid->mpi_communicator, &group_dest);
532 ierr = MPI_Group_union(group_source, group_dest, &group_union);
534 MPI_Comm mpi_communicator_union;
550 &mpi_communicator_union);
558 int union_blacs_context = Csys2blacs_handle(mpi_communicator_union);
559 const char *order =
"Col";
560 int union_n_process_rows =
562 int union_n_process_columns = 1;
563 Cblacs_gridinit(&union_blacs_context,
565 union_n_process_rows,
566 union_n_process_columns);
568 const NumberType *loc_vals_source =
nullptr;
569 NumberType * loc_vals_dest =
nullptr;
571 if (this->
grid->mpi_process_is_active && (this->values.size() > 0))
575 "source: process is active but local matrix empty"));
576 loc_vals_source = &this->
values[0];
583 "destination: process is active but local matrix empty"));
584 loc_vals_dest = &dest.
values[0];
596 &union_blacs_context);
598 Cblacs_gridexit(union_blacs_context);
600 if (mpi_communicator_union != MPI_COMM_NULL)
602 ierr = MPI_Comm_free(&mpi_communicator_union);
605 ierr = MPI_Group_free(&group_source);
607 ierr = MPI_Group_free(&group_dest);
609 ierr = MPI_Group_free(&group_union);
614 if (this->
grid->mpi_process_is_active)
623 template <
typename NumberType>
633 template <
typename NumberType>
636 const NumberType alpha,
637 const NumberType beta,
638 const bool transpose_B)
660 ExcMessage(
"The matrices A and B need to have the same process grid"));
662 if (this->
grid->mpi_process_is_active)
664 char trans_b = transpose_B ?
'T' :
'N';
688 template <
typename NumberType>
698 template <
typename NumberType>
708 template <
typename NumberType>
714 const bool transpose_A,
715 const bool transpose_B)
const 718 ExcMessage(
"The matrices A and B need to have the same process grid"));
720 ExcMessage(
"The matrices B and C need to have the same process grid"));
724 if (!transpose_A && !transpose_B)
739 else if (transpose_A && !transpose_B)
754 else if (!transpose_A && transpose_B)
786 if (this->
grid->mpi_process_is_active)
788 char trans_a = transpose_A ?
'T' :
'N';
789 char trans_b = transpose_B ?
'T' :
'N';
791 const NumberType *A_loc =
793 const NumberType *B_loc =
825 template <
typename NumberType>
829 const bool adding)
const 832 mult(1., B, 1., C,
false,
false);
834 mult(1., B, 0, C,
false,
false);
839 template <
typename NumberType>
843 const bool adding)
const 846 mult(1., B, 1., C,
true,
false);
848 mult(1., B, 0, C,
true,
false);
853 template <
typename NumberType>
857 const bool adding)
const 860 mult(1., B, 1., C,
false,
true);
862 mult(1., B, 0, C,
false,
true);
867 template <
typename NumberType>
871 const bool adding)
const 874 mult(1., B, 1., C,
true,
true);
876 mult(1., B, 0, C,
true,
true);
881 template <
typename NumberType>
888 "Cholesky factorization can be applied to symmetric matrices only."));
891 "Matrix has to be in Matrix state before calling this function."));
893 if (
grid->mpi_process_is_active)
896 NumberType *A_loc = &this->
values[0];
914 template <
typename NumberType>
920 "Matrix has to be in Matrix state before calling this function."));
922 if (
grid->mpi_process_is_active)
925 NumberType *A_loc = &this->
values[0];
929 &(
grid->this_process_row),
931 &(
grid->n_process_rows));
932 const int mp = numroc_(&
n_rows,
934 &(
grid->this_process_row),
936 &(
grid->n_process_rows));
949 state = LAPACKSupport::State::lu;
955 template <
typename NumberType>
963 state == LAPACKSupport::State::cholesky);
968 (
state == LAPACKSupport::State::matrix ||
969 state == LAPACKSupport::State::inverse_matrix);
973 if (
grid->mpi_process_is_active)
975 const char uploTriangular =
977 const char diag =
'N';
979 NumberType *A_loc = &this->
values[0];
980 ptrtri(&uploTriangular,
998 if (!(
state == LAPACKSupport::State::lu ||
999 state == LAPACKSupport::State::cholesky))
1006 if (
grid->mpi_process_is_active)
1009 NumberType *A_loc = &this->
values[0];
1022 property = LAPACKSupport::Property::symmetric;
1026 int lwork = -1, liwork = -1;
1047 iwork.resize(liwork);
1066 state = LAPACKSupport::State::inverse_matrix;
1071 template <
typename NumberType>
1072 std::vector<NumberType>
1074 const std::pair<unsigned int, unsigned int> &index_limits,
1075 const bool compute_eigenvectors)
1080 Assert(index_limits.second < (
unsigned int)n_rows,
1083 std::pair<unsigned int, unsigned int> idx =
1084 std::make_pair(std::min(index_limits.first, index_limits.second),
1085 std::max(index_limits.first, index_limits.second));
1088 if (idx.first == 0 && idx.second == (
unsigned int)n_rows - 1)
1096 template <
typename NumberType>
1097 std::vector<NumberType>
1099 const std::pair<NumberType, NumberType> &value_limits,
1100 const bool compute_eigenvectors)
1102 Assert(!std::isnan(value_limits.first),
1104 Assert(!std::isnan(value_limits.second),
1107 std::pair<unsigned int, unsigned int> indices =
1116 template <
typename NumberType>
1117 std::vector<NumberType>
1119 const bool compute_eigenvectors,
1120 const std::pair<unsigned int, unsigned int> &eigenvalue_idx,
1121 const std::pair<NumberType, NumberType> & eigenvalue_limits)
1125 "Matrix has to be in Matrix state before calling this function."));
1127 ExcMessage(
"Matrix has to be symmetric for this operation."));
1131 const bool use_values = (std::isnan(eigenvalue_limits.first) ||
1132 std::isnan(eigenvalue_limits.second)) ?
1135 const bool use_indices =
1142 !(use_values && use_indices),
1144 "Prescribing both the index and value range for the eigenvalues is ambiguous"));
1148 std::unique_ptr<ScaLAPACKMatrix<NumberType>>
eigenvectors =
1149 compute_eigenvectors ?
1150 std_cxx14::make_unique<ScaLAPACKMatrix<NumberType>>(
n_rows,
1154 grid->n_process_rows, grid->n_process_columns, grid, 1, 1);
1161 std::vector<NumberType> ev(n_rows);
1163 if (grid->mpi_process_is_active)
1170 char jobz = compute_eigenvectors ?
'V' :
'N';
1173 bool all_eigenpairs =
true;
1174 NumberType vl = NumberType(), vu = NumberType();
1180 NumberType abstol = NumberType();
1187 NumberType orfac = 0;
1189 std::vector<int> ifail;
1196 std::vector<int> iclustr;
1212 all_eigenpairs =
true;
1217 all_eigenpairs =
false;
1218 vl = std::min(eigenvalue_limits.first, eigenvalue_limits.second);
1219 vu = std::max(eigenvalue_limits.first, eigenvalue_limits.second);
1225 all_eigenpairs =
false;
1228 il = std::min(eigenvalue_idx.first, eigenvalue_idx.second) + 1;
1229 iu = std::max(eigenvalue_idx.first, eigenvalue_idx.second) + 1;
1231 NumberType *A_loc = &this->
values[0];
1238 NumberType *eigenvectors_loc =
1239 (compute_eigenvectors ? &eigenvectors->values[0] :
nullptr);
1254 &eigenvectors->submatrix_row,
1255 &eigenvectors->submatrix_column,
1256 eigenvectors->descriptor,
1264 char cmach = compute_eigenvectors ?
'U' :
'S';
1265 plamch(&(this->grid->blacs_context), &cmach, abstol);
1267 ifail.resize(n_rows);
1268 iclustr.resize(2 * grid->n_process_rows * grid->n_process_columns);
1269 gap.resize(grid->n_process_rows * grid->n_process_columns);
1289 &eigenvectors->submatrix_row,
1290 &eigenvectors->submatrix_column,
1291 eigenvectors->descriptor,
1316 &eigenvectors->submatrix_row,
1317 &eigenvectors->submatrix_column,
1318 eigenvectors->descriptor,
1329 iwork.resize(liwork);
1349 &eigenvectors->submatrix_row,
1350 &eigenvectors->submatrix_column,
1351 eigenvectors->descriptor,
1366 if (compute_eigenvectors)
1370 while ((
int)ev.size() >
m)
1376 grid->send_to_inactive(&m, 1);
1381 if (!grid->mpi_process_is_active)
1386 grid->send_to_inactive(ev.data(), ev.size());
1393 if (compute_eigenvectors)
1406 template <
typename NumberType>
1407 std::vector<NumberType>
1409 const std::pair<unsigned int, unsigned int> &index_limits,
1410 const bool compute_eigenvectors)
1416 const std::pair<unsigned int, unsigned int> idx =
1417 std::make_pair(std::min(index_limits.first, index_limits.second),
1418 std::max(index_limits.first, index_limits.second));
1421 if (idx.first == 0 && idx.second == static_cast<unsigned int>(
n_rows - 1))
1429 template <
typename NumberType>
1430 std::vector<NumberType>
1432 const std::pair<NumberType, NumberType> &value_limits,
1433 const bool compute_eigenvectors)
1438 const std::pair<unsigned int, unsigned int> indices =
1447 template <
typename NumberType>
1448 std::vector<NumberType>
1450 const bool compute_eigenvectors,
1451 const std::pair<unsigned int, unsigned int> &eigenvalue_idx,
1452 const std::pair<NumberType, NumberType> & eigenvalue_limits)
1456 "Matrix has to be in Matrix state before calling this function."));
1458 ExcMessage(
"Matrix has to be symmetric for this operation."));
1462 const bool use_values = (std::isnan(eigenvalue_limits.first) ||
1463 std::isnan(eigenvalue_limits.second)) ?
1466 const bool use_indices =
1473 !(use_values && use_indices),
1475 "Prescribing both the index and value range for the eigenvalues is ambiguous"));
1479 std::unique_ptr<ScaLAPACKMatrix<NumberType>>
eigenvectors =
1480 compute_eigenvectors ?
1481 std_cxx14::make_unique<ScaLAPACKMatrix<NumberType>>(
n_rows,
1485 grid->n_process_rows, grid->n_process_columns, grid, 1, 1);
1491 std::vector<NumberType> ev(n_rows);
1498 if (grid->mpi_process_is_active)
1505 char jobz = compute_eigenvectors ?
'V' :
'N';
1509 NumberType vl = NumberType(), vu = NumberType();
1524 vl = std::min(eigenvalue_limits.first, eigenvalue_limits.second);
1525 vu = std::max(eigenvalue_limits.first, eigenvalue_limits.second);
1533 il = std::min(eigenvalue_idx.first, eigenvalue_idx.second) + 1;
1534 iu = std::max(eigenvalue_idx.first, eigenvalue_idx.second) + 1;
1536 NumberType *A_loc = &this->
values[0];
1544 NumberType *eigenvectors_loc =
1545 (compute_eigenvectors ? &eigenvectors->values[0] :
nullptr);
1565 &eigenvectors->submatrix_row,
1566 &eigenvectors->submatrix_column,
1567 eigenvectors->descriptor,
1579 iwork.resize(liwork);
1597 &eigenvectors->submatrix_row,
1598 &eigenvectors->submatrix_column,
1599 eigenvectors->descriptor,
1608 if (compute_eigenvectors)
1612 "psyevr failed to compute all eigenvectors for the selected eigenvalues"));
1617 if (compute_eigenvectors)
1621 while ((
int)ev.size() >
m)
1627 grid->send_to_inactive(&m, 1);
1632 if (!grid->mpi_process_is_active)
1637 grid->send_to_inactive(ev.data(), ev.size());
1644 if (compute_eigenvectors)
1657 template <
typename NumberType>
1658 std::vector<NumberType>
1664 "Matrix has to be in Matrix state before calling this function."));
1668 const bool left_singluar_vectors = (U !=
nullptr) ?
true :
false;
1669 const bool right_singluar_vectors = (VT !=
nullptr) ?
true :
false;
1671 if (left_singluar_vectors)
1683 if (right_singluar_vectors)
1695 VT->
grid->blacs_context));
1701 if (
grid->mpi_process_is_active)
1703 char jobu = left_singluar_vectors ?
'V' :
'N';
1704 char jobvt = right_singluar_vectors ?
'V' :
'N';
1705 NumberType *A_loc = &this->
values[0];
1706 NumberType *U_loc = left_singluar_vectors ? &(U->
values[0]) :
nullptr;
1707 NumberType *VT_loc = right_singluar_vectors ? &(VT->
values[0]) :
nullptr;
1767 grid->send_to_inactive(sv.data(), sv.size());
1770 state = LAPACKSupport::State::unusable;
1777 template <
typename NumberType>
1783 ExcMessage(
"The matrices A and B need to have the same process grid"));
1786 "Matrix has to be in Matrix state before calling this function."));
1789 "Matrix B has to be in Matrix state before calling this function."));
1804 "Use identical block sizes for rows and columns of matrix A"));
1807 "Use identical block sizes for rows and columns of matrix B"));
1810 "Use identical block-cyclic distribution for matrices A and B"));
1814 if (
grid->mpi_process_is_active)
1816 char trans = transpose ?
'T' :
'N';
1817 NumberType *A_loc = &this->
values[0];
1818 NumberType *B_loc = &B.
values[0];
1864 state = LAPACKSupport::State::unusable;
1869 template <
typename NumberType>
1875 "Matrix has to be in Matrix state before calling this function."));
1878 "Use identical block sizes for rows and columns of matrix A"));
1880 ratio > 0. && ratio < 1.,
1882 "input parameter ratio has to be larger than zero and smaller than 1"));
1896 std::vector<NumberType> sv = this->
compute_SVD(&U, &VT);
1897 AssertThrow(sv[0] > std::numeric_limits<NumberType>::min(),
1904 unsigned int n_sv = 1;
1905 std::vector<NumberType> inv_sigma;
1906 inv_sigma.push_back(1 / sv[0]);
1908 for (
unsigned int i = 1; i < sv.size(); ++i)
1909 if (sv[i] > sv[0] * ratio)
1912 inv_sigma.push_back(1 / sv[i]);
1934 std::make_pair(0, 0),
1935 std::make_pair(0, 0),
1936 std::make_pair(
n_rows, n_sv));
1938 std::make_pair(0, 0),
1939 std::make_pair(0, 0),
1949 VT_R.
mult(1, U_R, 0, *
this,
true,
true);
1950 state = LAPACKSupport::State::inverse_matrix;
1956 template <
typename NumberType>
1959 const NumberType a_norm)
const 1963 "Matrix has to be in Cholesky state before calling this function."));
1965 NumberType rcond = 0.;
1967 if (
grid->mpi_process_is_active)
1970 iwork.resize(liwork);
1973 const NumberType *A_loc = &this->
values[0];
1993 lwork = std::ceil(
work[0]);
2012 grid->send_to_inactive(&rcond);
2018 template <
typename NumberType>
2022 const char type(
'O');
2032 template <
typename NumberType>
2036 const char type(
'I');
2046 template <
typename NumberType>
2050 const char type(
'F');
2060 template <
typename NumberType>
2066 ExcMessage(
"norms can be called in matrix state only."));
2068 NumberType res = 0.;
2070 if (
grid->mpi_process_is_active)
2074 &(
grid->this_process_row),
2076 &(
grid->n_process_rows));
2079 &(
grid->this_process_column),
2081 &(
grid->n_process_columns));
2082 const int mp0 = numroc_(&
n_rows,
2084 &(
grid->this_process_row),
2086 &(
grid->n_process_rows));
2089 &(
grid->this_process_column),
2091 &(
grid->n_process_columns));
2097 if (type ==
'O' || type ==
'1')
2099 else if (type ==
'I')
2113 grid->send_to_inactive(&res);
2119 template <
typename NumberType>
2125 ExcMessage(
"norms can be called in matrix state only."));
2127 ExcMessage(
"Matrix has to be symmetric for this operation."));
2129 NumberType res = 0.;
2131 if (
grid->mpi_process_is_active)
2136 ilcm_(&(
grid->n_process_rows), &(
grid->n_process_columns));
2137 const int v2 = lcm / (
grid->n_process_rows);
2141 &(
grid->this_process_row),
2143 &(
grid->n_process_rows));
2146 &(
grid->this_process_column),
2148 &(
grid->n_process_columns));
2151 &(
grid->this_process_row),
2153 &(
grid->n_process_rows));
2156 &(
grid->this_process_column),
2158 &(
grid->n_process_columns));
2166 (type ==
'M' || type ==
'F' || type ==
'E') ? 0 : 2 * Nq0 + Np0 + ldw;
2178 grid->send_to_inactive(&res);
2184 # ifdef DEAL_II_WITH_HDF5 2190 create_HDF5_state_enum_id(hid_t &state_enum_id)
2195 val = LAPACKSupport::State::cholesky;
2196 herr_t status = H5Tenum_insert(state_enum_id,
"cholesky", (
int *)&val);
2199 status = H5Tenum_insert(state_enum_id,
"eigenvalues", (
int *)&val);
2201 val = LAPACKSupport::State::inverse_matrix;
2202 status = H5Tenum_insert(state_enum_id,
"inverse_matrix", (
int *)&val);
2204 val = LAPACKSupport::State::inverse_svd;
2205 status = H5Tenum_insert(state_enum_id,
"inverse_svd", (
int *)&val);
2207 val = LAPACKSupport::State::lu;
2208 status = H5Tenum_insert(state_enum_id,
"lu", (
int *)&val);
2210 val = LAPACKSupport::State::matrix;
2211 status = H5Tenum_insert(state_enum_id,
"matrix", (
int *)&val);
2213 val = LAPACKSupport::State::svd;
2214 status = H5Tenum_insert(state_enum_id,
"svd", (
int *)&val);
2216 val = LAPACKSupport::State::unusable;
2217 status = H5Tenum_insert(state_enum_id,
"unusable", (
int *)&val);
2222 create_HDF5_property_enum_id(hid_t &property_enum_id)
2228 H5Tenum_insert(property_enum_id,
"diagonal", (
int *)&prop);
2231 status = H5Tenum_insert(property_enum_id,
"general", (
int *)&prop);
2233 prop = LAPACKSupport::Property::hessenberg;
2234 status = H5Tenum_insert(property_enum_id,
"hessenberg", (
int *)&prop);
2236 prop = LAPACKSupport::Property::lower_triangular;
2238 H5Tenum_insert(property_enum_id,
"lower_triangular", (
int *)&prop);
2240 prop = LAPACKSupport::Property::symmetric;
2241 status = H5Tenum_insert(property_enum_id,
"symmetric", (
int *)&prop);
2243 prop = LAPACKSupport::Property::upper_triangular;
2245 H5Tenum_insert(property_enum_id,
"upper_triangular", (
int *)&prop);
2254 template <
typename NumberType>
2257 const char * filename,
2258 const std::pair<unsigned int, unsigned int> &chunk_size)
const 2260 # ifndef DEAL_II_WITH_HDF5 2266 std::pair<unsigned int, unsigned int> chunks_size_ = chunk_size;
2272 chunks_size_.first =
n_rows;
2273 chunks_size_.second = 1;
2276 (chunks_size_.first > 0),
2279 (chunks_size_.second > 0),
2282 # ifdef H5_HAVE_PARALLEL 2284 save_parallel(filename, chunks_size_);
2288 save_serial(filename, chunks_size_);
2296 template <
typename NumberType>
2299 const char * filename,
2300 const std::pair<unsigned int, unsigned int> &chunk_size)
const 2302 # ifndef DEAL_II_WITH_HDF5 2317 const auto column_grid =
2318 std::make_shared<Utilities::MPI::ProcessGrid>(this->
grid->mpi_communicator,
2328 if (tmp.
grid->mpi_process_is_active)
2334 H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
2337 hsize_t chunk_dims[2];
2340 chunk_dims[0] = chunk_size.second;
2341 chunk_dims[1] = chunk_size.first;
2342 hid_t data_property = H5Pcreate(H5P_DATASET_CREATE);
2343 status = H5Pset_chunk(data_property, 2, chunk_dims);
2352 hid_t dataspace_id = H5Screate_simple(2, dims,
nullptr);
2355 hid_t type_id = hdf5_type_id(&tmp.
values[0]);
2356 hid_t dataset_id = H5Dcreate2(file_id,
2366 dataset_id, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, &tmp.
values[0]);
2371 hid_t state_enum_id, property_enum_id;
2372 internal::create_HDF5_state_enum_id(state_enum_id);
2373 internal::create_HDF5_property_enum_id(property_enum_id);
2376 hsize_t dims_state[1];
2378 hid_t state_enum_dataspace = H5Screate_simple(1, dims_state,
nullptr);
2380 hid_t state_enum_dataset = H5Dcreate2(file_id,
2383 state_enum_dataspace,
2388 status = H5Dwrite(state_enum_dataset,
2397 hsize_t dims_property[1];
2398 dims_property[0] = 1;
2399 hid_t property_enum_dataspace =
2400 H5Screate_simple(1, dims_property,
nullptr);
2402 hid_t property_enum_dataset = H5Dcreate2(file_id,
2405 property_enum_dataspace,
2410 status = H5Dwrite(property_enum_dataset,
2419 status = H5Dclose(dataset_id);
2421 status = H5Dclose(state_enum_dataset);
2423 status = H5Dclose(property_enum_dataset);
2427 status = H5Sclose(dataspace_id);
2429 status = H5Sclose(state_enum_dataspace);
2431 status = H5Sclose(property_enum_dataspace);
2435 status = H5Tclose(state_enum_id);
2437 status = H5Tclose(property_enum_id);
2441 status = H5Pclose(data_property);
2445 status = H5Fclose(file_id);
2453 template <
typename NumberType>
2456 const char * filename,
2457 const std::pair<unsigned int, unsigned int> &chunk_size)
const 2459 # ifndef DEAL_II_WITH_HDF5 2465 const unsigned int n_mpi_processes(
2467 MPI_Info info = MPI_INFO_NULL;
2475 const auto column_grid =
2476 std::make_shared<Utilities::MPI::ProcessGrid>(this->
grid->mpi_communicator,
2492 hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS);
2493 status = H5Pset_fapl_mpio(plist_id, tmp.
grid->mpi_communicator, info);
2497 hid_t file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id);
2498 status = H5Pclose(plist_id);
2507 hid_t filespace = H5Screate_simple(2, dims,
nullptr);
2510 hsize_t chunk_dims[2];
2512 chunk_dims[0] = chunk_size.second;
2513 chunk_dims[1] = chunk_size.first;
2514 plist_id = H5Pcreate(H5P_DATASET_CREATE);
2515 H5Pset_chunk(plist_id, 2, chunk_dims);
2516 hid_t type_id = hdf5_type_id(data);
2517 hid_t dset_id = H5Dcreate2(
2518 file_id,
"/matrix", type_id, filespace, H5P_DEFAULT, plist_id, H5P_DEFAULT);
2520 status = H5Sclose(filespace);
2523 status = H5Pclose(plist_id);
2527 std::vector<int> proc_n_local_rows(n_mpi_processes),
2528 proc_n_local_columns(n_mpi_processes);
2532 proc_n_local_rows.data(),
2535 tmp.
grid->mpi_communicator);
2540 proc_n_local_columns.data(),
2543 tmp.
grid->mpi_communicator);
2546 const unsigned int my_rank(
2555 hid_t memspace = H5Screate_simple(2, count,
nullptr);
2557 hsize_t offset[2] = {0};
2558 for (
unsigned int i = 0; i < my_rank; ++i)
2559 offset[0] += proc_n_local_columns[i];
2562 filespace = H5Dget_space(dset_id);
2563 status = H5Sselect_hyperslab(
2564 filespace, H5S_SELECT_SET, offset,
nullptr, count,
nullptr);
2568 plist_id = H5Pcreate(H5P_DATASET_XFER);
2569 status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT);
2575 status = H5Dwrite(dset_id, type_id, memspace, filespace, plist_id, data);
2579 status = H5Dclose(dset_id);
2581 status = H5Sclose(filespace);
2583 status = H5Sclose(memspace);
2585 status = H5Pclose(plist_id);
2587 status = H5Fclose(file_id);
2592 ierr = MPI_Barrier(tmp.
grid->mpi_communicator);
2596 if (tmp.
grid->this_mpi_process == 0)
2599 hid_t file_id_reopen = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT);
2603 hid_t state_enum_id, property_enum_id;
2604 internal::create_HDF5_state_enum_id(state_enum_id);
2605 internal::create_HDF5_property_enum_id(property_enum_id);
2608 hsize_t dims_state[1];
2610 hid_t state_enum_dataspace = H5Screate_simple(1, dims_state,
nullptr);
2612 hid_t state_enum_dataset = H5Dcreate2(file_id_reopen,
2615 state_enum_dataspace,
2620 status = H5Dwrite(state_enum_dataset,
2629 hsize_t dims_property[1];
2630 dims_property[0] = 1;
2631 hid_t property_enum_dataspace =
2632 H5Screate_simple(1, dims_property,
nullptr);
2634 hid_t property_enum_dataset = H5Dcreate2(file_id_reopen,
2637 property_enum_dataspace,
2642 status = H5Dwrite(property_enum_dataset,
2650 status = H5Dclose(state_enum_dataset);
2652 status = H5Dclose(property_enum_dataset);
2654 status = H5Sclose(state_enum_dataspace);
2656 status = H5Sclose(property_enum_dataspace);
2658 status = H5Tclose(state_enum_id);
2660 status = H5Tclose(property_enum_id);
2662 status = H5Fclose(file_id_reopen);
2671 template <
typename NumberType>
2675 # ifndef DEAL_II_WITH_HDF5 2679 # ifdef H5_HAVE_PARALLEL 2681 load_parallel(filename);
2685 load_serial(filename);
2692 template <
typename NumberType>
2696 # ifndef DEAL_II_WITH_HDF5 2707 const auto one_grid =
2708 std::make_shared<Utilities::MPI::ProcessGrid>(this->
grid->mpi_communicator,
2716 int property_int = -1;
2720 if (tmp.
grid->mpi_process_is_active)
2725 hid_t file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
2728 hid_t dataset_id = H5Dopen2(file_id,
"/matrix", H5P_DEFAULT);
2734 hid_t datatype = H5Dget_type(dataset_id);
2735 H5T_class_t t_class_in = H5Tget_class(datatype);
2736 H5T_class_t t_class = H5Tget_class(hdf5_type_id(&tmp.
values[0]));
2738 t_class_in == t_class,
2740 "The data type of the matrix to be read does not match the archive"));
2743 hid_t dataspace_id = H5Dget_space(dataset_id);
2745 const int ndims = H5Sget_simple_extent_ndims(dataspace_id);
2749 H5Sget_simple_extent_dims(dataspace_id, dims,
nullptr);
2753 "The number of columns of the matrix does not match the content of the archive"));
2757 "The number of rows of the matrix does not match the content of the archive"));
2760 status = H5Dread(dataset_id,
2761 hdf5_type_id(&tmp.
values[0]),
2770 hid_t state_enum_id, property_enum_id;
2771 internal::create_HDF5_state_enum_id(state_enum_id);
2772 internal::create_HDF5_property_enum_id(property_enum_id);
2775 hid_t dataset_state_id = H5Dopen2(file_id,
"/state", H5P_DEFAULT);
2776 hid_t datatype_state = H5Dget_type(dataset_state_id);
2777 H5T_class_t t_class_state = H5Tget_class(datatype_state);
2780 hid_t dataset_property_id = H5Dopen2(file_id,
"/property", H5P_DEFAULT);
2781 hid_t datatype_property = H5Dget_type(dataset_property_id);
2782 H5T_class_t t_class_property = H5Tget_class(datatype_property);
2786 hid_t dataspace_state = H5Dget_space(dataset_state_id);
2787 hid_t dataspace_property = H5Dget_space(dataset_property_id);
2789 const int ndims_state = H5Sget_simple_extent_ndims(dataspace_state);
2791 const int ndims_property = H5Sget_simple_extent_ndims(dataspace_property);
2794 hsize_t dims_state[1];
2795 H5Sget_simple_extent_dims(dataspace_state, dims_state,
nullptr);
2797 hsize_t dims_property[1];
2798 H5Sget_simple_extent_dims(dataspace_property, dims_property,
nullptr);
2802 status = H5Dread(dataset_state_id,
2812 state_int =
static_cast<int>(tmp.
state);
2814 status = H5Dread(dataset_property_id,
2824 property_int =
static_cast<int>(tmp.
property);
2827 status = H5Sclose(dataspace_id);
2829 status = H5Sclose(dataspace_state);
2831 status = H5Sclose(dataspace_property);
2835 status = H5Tclose(datatype);
2837 status = H5Tclose(state_enum_id);
2839 status = H5Tclose(property_enum_id);
2843 status = H5Dclose(dataset_state_id);
2845 status = H5Dclose(dataset_id);
2847 status = H5Dclose(dataset_property_id);
2851 status = H5Fclose(file_id);
2855 tmp.
grid->send_to_inactive(&state_int, 1);
2858 tmp.
grid->send_to_inactive(&property_int, 1);
2865 # endif // DEAL_II_WITH_HDF5 2870 template <
typename NumberType>
2874 # ifndef DEAL_II_WITH_HDF5 2878 # ifndef H5_HAVE_PARALLEL 2882 const unsigned int n_mpi_processes(
2884 MPI_Info info = MPI_INFO_NULL;
2891 const auto column_grid =
2892 std::make_shared<Utilities::MPI::ProcessGrid>(this->
grid->mpi_communicator,
2905 hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS);
2906 status = H5Pset_fapl_mpio(plist_id, tmp.
grid->mpi_communicator, info);
2911 hid_t file_id = H5Fopen(filename, H5F_ACC_RDONLY, plist_id);
2912 status = H5Pclose(plist_id);
2916 hid_t dataset_id = H5Dopen2(file_id,
"/matrix", H5P_DEFAULT);
2922 hid_t datatype = hdf5_type_id(data);
2923 hid_t datatype_inp = H5Dget_type(dataset_id);
2924 H5T_class_t t_class_inp = H5Tget_class(datatype_inp);
2925 H5T_class_t t_class = H5Tget_class(datatype);
2927 t_class_inp == t_class,
2929 "The data type of the matrix to be read does not match the archive"));
2933 hid_t dataspace_id = H5Dget_space(dataset_id);
2935 const int ndims = H5Sget_simple_extent_ndims(dataspace_id);
2939 status = H5Sget_simple_extent_dims(dataspace_id, dims,
nullptr);
2944 "The number of columns of the matrix does not match the content of the archive"));
2948 "The number of rows of the matrix does not match the content of the archive"));
2951 std::vector<int> proc_n_local_rows(n_mpi_processes),
2952 proc_n_local_columns(n_mpi_processes);
2956 proc_n_local_rows.data(),
2959 tmp.
grid->mpi_communicator);
2964 proc_n_local_columns.data(),
2967 tmp.
grid->mpi_communicator);
2970 const unsigned int my_rank(
2980 hsize_t offset[2] = {0};
2981 for (
unsigned int i = 0; i < my_rank; ++i)
2982 offset[0] += proc_n_local_columns[i];
2985 status = H5Sselect_hyperslab(
2986 dataspace_id, H5S_SELECT_SET, offset,
nullptr, count,
nullptr);
2990 hid_t memspace = H5Screate_simple(2, count,
nullptr);
2994 H5Dread(dataset_id, datatype, memspace, dataspace_id, H5P_DEFAULT, data);
2998 hid_t state_enum_id, property_enum_id;
2999 internal::create_HDF5_state_enum_id(state_enum_id);
3000 internal::create_HDF5_property_enum_id(property_enum_id);
3003 hid_t dataset_state_id = H5Dopen2(file_id,
"/state", H5P_DEFAULT);
3004 hid_t datatype_state = H5Dget_type(dataset_state_id);
3005 H5T_class_t t_class_state = H5Tget_class(datatype_state);
3008 hid_t dataset_property_id = H5Dopen2(file_id,
"/property", H5P_DEFAULT);
3009 hid_t datatype_property = H5Dget_type(dataset_property_id);
3010 H5T_class_t t_class_property = H5Tget_class(datatype_property);
3014 hid_t dataspace_state = H5Dget_space(dataset_state_id);
3015 hid_t dataspace_property = H5Dget_space(dataset_property_id);
3017 const int ndims_state = H5Sget_simple_extent_ndims(dataspace_state);
3019 const int ndims_property = H5Sget_simple_extent_ndims(dataspace_property);
3022 hsize_t dims_state[1];
3023 H5Sget_simple_extent_dims(dataspace_state, dims_state,
nullptr);
3025 hsize_t dims_property[1];
3026 H5Sget_simple_extent_dims(dataspace_property, dims_property,
nullptr);
3031 dataset_state_id, state_enum_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, &tmp.
state);
3034 status = H5Dread(dataset_property_id,
3043 status = H5Sclose(memspace);
3045 status = H5Dclose(dataset_id);
3047 status = H5Dclose(dataset_state_id);
3049 status = H5Dclose(dataset_property_id);
3051 status = H5Sclose(dataspace_id);
3053 status = H5Sclose(dataspace_state);
3055 status = H5Sclose(dataspace_property);
3059 status = H5Tclose(state_enum_id);
3061 status = H5Tclose(property_enum_id);
3063 status = H5Fclose(file_id);
3069 # endif // H5_HAVE_PARALLEL 3070 # endif // DEAL_II_WITH_HDF5 3079 template <
typename NumberType>
3087 for (
unsigned int i = 0; i < matrix.
local_n(); ++i)
3091 for (
unsigned int j = 0; j < matrix.
local_m(); ++j)
3096 template <
typename NumberType>
3104 for (
unsigned int i = 0; i < matrix.
local_m(); ++i)
3106 const NumberType s = factors[matrix.
global_row(i)];
3108 for (
unsigned int j = 0; j < matrix.
local_n(); ++j)
3118 template <
typename NumberType>
3119 template <
class InputVector>
3123 if (this->
grid->mpi_process_is_active)
3124 internal::scale_columns(*
this, make_array_view(factors));
3129 template <
typename NumberType>
3130 template <
class InputVector>
3134 if (this->
grid->mpi_process_is_active)
3135 internal::scale_rows(*
this, make_array_view(factors));
3141 # include "scalapack.inst" 3144 DEAL_II_NAMESPACE_CLOSE
3146 #endif // DEAL_II_WITH_SCALAPACK std::vector< NumberType > eigenpairs_symmetric_by_index_MRRR(const std::pair< unsigned int, unsigned int > &index_limits, const bool compute_eigenvectors)
void copy_transposed(const ScaLAPACKMatrix< NumberType > &B)
ScaLAPACKMatrix(const size_type n_rows, const size_type n_columns, const std::shared_ptr< const Utilities::MPI::ProcessGrid > &process_grid, const size_type row_block_size=32, const size_type column_block_size=32, const LAPACKSupport::Property property=LAPACKSupport::Property::general)
std::vector< NumberType > eigenpairs_symmetric_by_value_MRRR(const std::pair< NumberType, NumberType > &value_limits, const bool compute_eigenvectors)
NumberType reciprocal_condition_number(const NumberType a_norm) const
static const unsigned int invalid_unsigned_int
LAPACKSupport::State state
unsigned int global_column(const unsigned int loc_column) const
void copy_to(FullMatrix< NumberType > &matrix) const
void save(const char *filename, const std::pair< unsigned int, unsigned int > &chunk_size=std::make_pair(numbers::invalid_unsigned_int, numbers::invalid_unsigned_int)) const
Contents is actually a matrix.
std::array< std::pair< Number, Tensor< 1, dim, Number > >, std::integral_constant< int, dim >::value > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)
NumberType norm_general(const char type) const
ScaLAPACKMatrix< NumberType > & operator=(const FullMatrix< NumberType > &)
static::ExceptionBase & ExcIO()
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
unsigned int pseudoinverse(const NumberType ratio)
void load(const char *filename)
Matrix is upper triangular.
unsigned int local_m() const
void mTmult(ScaLAPACKMatrix< NumberType > &C, const ScaLAPACKMatrix< NumberType > &B, const bool adding=false) const
std::vector< NumberType > eigenpairs_symmetric(const bool compute_eigenvectors, const std::pair< unsigned int, unsigned int > &index_limits=std::make_pair(numbers::invalid_unsigned_int, numbers::invalid_unsigned_int), const std::pair< NumberType, NumberType > &value_limits=std::make_pair(std::numeric_limits< NumberType >::quiet_NaN(), std::numeric_limits< NumberType >::quiet_NaN()))
Contents is the inverse of a matrix.
std::vector< NumberType > eigenpairs_symmetric_by_index(const std::pair< unsigned int, unsigned int > &index_limits, const bool compute_eigenvectors)
#define AssertIndexRange(index, range)
void mult(const NumberType b, const ScaLAPACKMatrix< NumberType > &B, const NumberType c, ScaLAPACKMatrix< NumberType > &C, const bool transpose_A=false, const bool transpose_B=false) const
void scale_columns(const InputVector &factors)
std::shared_ptr< const Utilities::MPI::ProcessGrid > grid
#define AssertThrow(cond, exc)
static::ExceptionBase & ExcErrorCode(std::string arg1, types::blas_int arg2)
static::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
const int submatrix_column
void reinit(const size_type n_rows, const size_type n_columns, const std::shared_ptr< const Utilities::MPI::ProcessGrid > &process_grid, const size_type row_block_size=32, const size_type column_block_size=32, const LAPACKSupport::Property property=LAPACKSupport::Property::general)
const TableIndices< N > & size() const
LAPACKSupport::Property get_property() const
void least_squares(ScaLAPACKMatrix< NumberType > &B, const bool transpose=false)
NumberType norm_symmetric(const char type) const
static::ExceptionBase & ExcMessage(std::string arg1)
Contents is a Cholesky decomposition.
void scale_rows(const InputVector &factors)
T sum(const T &t, const MPI_Comm &mpi_communicator)
void set_property(const LAPACKSupport::Property property)
#define Assert(cond, exc)
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
const int first_process_row
void reinit(const size_type size1, const size_type size2, const bool omit_default_initialization=false)
int create_group(const MPI_Comm &comm, const MPI_Group &group, const int tag, MPI_Comm *new_comm)
void add(const ScaLAPACKMatrix< NumberType > &B, const NumberType a=0., const NumberType b=1., const bool transpose_B=false)
Contents is something useless.
std::vector< NumberType > eigenpairs_symmetric_by_value(const std::pair< NumberType, NumberType > &value_limits, const bool compute_eigenvectors)
SymmetricTensor< rank_, dim, Number > transpose(const SymmetricTensor< rank_, dim, Number > &t)
NumberType l1_norm() const
void TmTmult(ScaLAPACKMatrix< NumberType > &C, const ScaLAPACKMatrix< NumberType > &B, const bool adding=false) const
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
void mmult(ScaLAPACKMatrix< NumberType > &C, const ScaLAPACKMatrix< NumberType > &B, const bool adding=false) const
NumberType local_el(const unsigned int loc_row, const unsigned int loc_column) const
void swap(AlignedVector< T > &vec)
#define AssertThrowMPI(error_code)
NumberType frobenius_norm() const
std::vector< NumberType > eigenpairs_symmetric_MRRR(const bool compute_eigenvectors, const std::pair< unsigned int, unsigned int > &index_limits=std::make_pair(numbers::invalid_unsigned_int, numbers::invalid_unsigned_int), const std::pair< NumberType, NumberType > &value_limits=std::make_pair(std::numeric_limits< NumberType >::quiet_NaN(), std::numeric_limits< NumberType >::quiet_NaN()))
std::vector< NumberType > compute_SVD(ScaLAPACKMatrix< NumberType > *U=nullptr, ScaLAPACKMatrix< NumberType > *VT=nullptr)
unsigned int local_n() const
std::vector< NumberType > work
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
static::ExceptionBase & ExcNotImplemented()
const int first_process_column
LAPACKSupport::Property property
void Tadd(const NumberType b, const ScaLAPACKMatrix< NumberType > &B)
unsigned int global_row(const unsigned int loc_row) const
Eigenvalue vector is filled.
AlignedVector< NumberType > values
void Tmmult(ScaLAPACKMatrix< NumberType > &C, const ScaLAPACKMatrix< NumberType > &B, const bool adding=false) const
void compute_cholesky_factorization()
NumberType linfty_norm() const
Matrix is lower triangular.
#define AssertIsFinite(number)
static::ExceptionBase & ExcInternalError()
LAPACKSupport::State get_state() const
void compute_lu_factorization()