16#include <deal.II/base/mpi.templates.h>
19#include <deal.II/lac/scalapack.templates.h>
21#ifdef DEAL_II_WITH_HDF5
30#ifdef DEAL_II_WITH_HDF5
34 template <
typename number>
36 hdf5_type_id(
const number *)
44 hdf5_type_id(
const double *)
46 return H5T_NATIVE_DOUBLE;
50 hdf5_type_id(
const float *)
52 return H5T_NATIVE_FLOAT;
59template <
typename NumberType>
63 const std::shared_ptr<const Utilities::MPI::ProcessGrid> &process_grid,
70 , first_process_column(0)
84template <
typename NumberType>
87 const std::shared_ptr<const Utilities::MPI::ProcessGrid> &process_grid,
100template <
typename NumberType>
102 const std::string &filename,
103 const std::shared_ptr<const Utilities::MPI::ProcessGrid> &process_grid,
109 , first_process_column(0)
111 , submatrix_column(1)
113#ifndef DEAL_II_WITH_HDF5
121 "This function is only available when deal.II is configured with HDF5"));
124 const unsigned int this_mpi_process(
130 if (this_mpi_process == 0)
135 hid_t file = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
139 hid_t dataset = H5Dopen2(file,
"/matrix", H5P_DEFAULT);
143 hid_t filespace = H5Dget_space(dataset);
146 int rank = H5Sget_simple_extent_ndims(filespace);
149 status = H5Sget_simple_extent_dims(filespace, dims,
nullptr);
158 status = H5Sclose(filespace);
160 status = H5Dclose(dataset);
162 status = H5Fclose(file);
165 int ierr = MPI_Bcast(&
n_rows,
169 process_grid->mpi_communicator);
176 process_grid->mpi_communicator);
187 load(filename.c_str());
194template <
typename NumberType>
199 const std::shared_ptr<const Utilities::MPI::ProcessGrid> &process_grid,
204 Assert(row_block_size_ > 0,
ExcMessage(
"Row block size has to be positive."));
205 Assert(column_block_size_ > 0,
206 ExcMessage(
"Column block size has to be positive."));
208 row_block_size_ <= n_rows_,
210 "Row block size can not be greater than the number of rows of the matrix"));
212 column_block_size_ <= n_columns_,
214 "Column block size can not be greater than the number of columns of the matrix"));
217 property = property_;
220 n_columns = n_columns_;
221 row_block_size = row_block_size_;
222 column_block_size = column_block_size_;
224 if (grid->mpi_process_is_active)
227 n_local_rows = numroc_(&n_rows,
229 &(grid->this_process_row),
231 &(grid->n_process_rows));
232 n_local_columns = numroc_(&n_columns,
234 &(grid->this_process_column),
235 &first_process_column,
236 &(grid->n_process_columns));
240 int lda =
std::max(1, n_local_rows);
243 descinit_(descriptor,
249 &first_process_column,
250 &(grid->blacs_context),
261 n_local_columns = -1;
262 std::fill(std::begin(descriptor), std::end(descriptor), -1);
268template <
typename NumberType>
272 const std::shared_ptr<const Utilities::MPI::ProcessGrid> &process_grid,
276 reinit(
size,
size, process_grid, block_size, block_size, property);
281template <
typename NumberType>
286 property = property_;
291template <
typename NumberType>
300template <
typename NumberType>
309template <
typename NumberType>
319 Assert(n_columns ==
int(matrix.n()),
322 if (grid->mpi_process_is_active)
324 for (
int i = 0; i < n_local_rows; ++i)
326 const int glob_i = global_row(i);
327 for (
int j = 0; j < n_local_columns; ++j)
329 const int glob_j = global_column(j);
330 local_el(i, j) = matrix(glob_i, glob_j);
340template <
typename NumberType>
343 const unsigned int rank)
345 if (n_rows * n_columns == 0)
348 const unsigned int this_mpi_process(
355 "All processes have to call routine with identical rank"));
358 "All processes have to call routine with identical rank"));
362 if (this_mpi_process == rank)
373 MPI_Comm_group(this->grid->mpi_communicator, &group_A);
375 const std::vector<int> ranks(n, rank);
377 MPI_Group_incl(group_A, n, ranks.data(), &group_B);
381 const int ierr = MPI_Comm_create_group(this->grid->mpi_communicator,
386 int n_proc_rows_B = 1, n_proc_cols_B = 1;
387 int this_process_row_B = -1, this_process_column_B = -1;
388 int blacs_context_B = -1;
389 if (MPI_COMM_NULL != communicator_B)
392 blacs_context_B = Csys2blacs_handle(communicator_B);
393 const char *order =
"Col";
394 Cblacs_gridinit(&blacs_context_B, order, n_proc_rows_B, n_proc_cols_B);
395 Cblacs_gridinfo(blacs_context_B,
399 &this_process_column_B);
405 const bool mpi_process_is_active_B =
406 (this_process_row_B >= 0 && this_process_column_B >= 0);
409 std::vector<int> descriptor_B(9, -1);
410 const int first_process_row_B = 0, first_process_col_B = 0;
412 if (mpi_process_is_active_B)
415 int n_local_rows_B = numroc_(&n_rows,
418 &first_process_row_B,
420 int n_local_cols_B = numroc_(&n_columns,
422 &this_process_column_B,
423 &first_process_col_B,
428 int lda =
std::max(1, n_local_rows_B);
430 descinit_(descriptor_B.data(),
435 &first_process_row_B,
436 &first_process_col_B,
442 if (this->grid->mpi_process_is_active)
445 NumberType *loc_vals_A =
446 this->values.size() > 0 ? this->values.data() :
nullptr;
447 const NumberType *loc_vals_B =
448 mpi_process_is_active_B ? &(B(0, 0)) :
nullptr;
462 &(this->grid->blacs_context));
464 if (mpi_process_is_active_B)
465 Cblacs_gridexit(blacs_context_B);
467 MPI_Group_free(&group_A);
468 MPI_Group_free(&group_B);
469 if (MPI_COMM_NULL != communicator_B)
477template <
typename NumberType>
481 Assert(n_local_rows >= 0 && loc_row <
static_cast<unsigned int>(n_local_rows),
483 const int i = loc_row + 1;
486 &(grid->this_process_row),
488 &(grid->n_process_rows)) -
494template <
typename NumberType>
498 Assert(n_local_columns >= 0 &&
499 loc_column <
static_cast<unsigned int>(n_local_columns),
501 const int j = loc_column + 1;
504 &(grid->this_process_column),
505 &first_process_column,
506 &(grid->n_process_columns)) -
512template <
typename NumberType>
515 const unsigned int rank)
const
517 if (n_rows * n_columns == 0)
520 const unsigned int this_mpi_process(
527 "All processes have to call routine with identical rank"));
530 "All processes have to call routine with identical rank"));
533 if (this_mpi_process == rank)
546 MPI_Comm_group(this->grid->mpi_communicator, &group_A);
548 const std::vector<int> ranks(n, rank);
550 MPI_Group_incl(group_A, n, ranks.data(), &group_B);
554 const int ierr = MPI_Comm_create_group(this->grid->mpi_communicator,
559 int n_proc_rows_B = 1, n_proc_cols_B = 1;
560 int this_process_row_B = -1, this_process_column_B = -1;
561 int blacs_context_B = -1;
562 if (MPI_COMM_NULL != communicator_B)
565 blacs_context_B = Csys2blacs_handle(communicator_B);
566 const char *order =
"Col";
567 Cblacs_gridinit(&blacs_context_B, order, n_proc_rows_B, n_proc_cols_B);
568 Cblacs_gridinfo(blacs_context_B,
572 &this_process_column_B);
578 const bool mpi_process_is_active_B =
579 (this_process_row_B >= 0 && this_process_column_B >= 0);
582 std::vector<int> descriptor_B(9, -1);
583 const int first_process_row_B = 0, first_process_col_B = 0;
585 if (mpi_process_is_active_B)
588 int n_local_rows_B = numroc_(&n_rows,
591 &first_process_row_B,
593 int n_local_cols_B = numroc_(&n_columns,
595 &this_process_column_B,
596 &first_process_col_B,
601 int lda =
std::max(1, n_local_rows_B);
604 descinit_(descriptor_B.data(),
609 &first_process_row_B,
610 &first_process_col_B,
618 if (this->grid->mpi_process_is_active)
621 const NumberType *loc_vals_A =
622 this->values.size() > 0 ? this->values.data() :
nullptr;
623 NumberType *loc_vals_B = mpi_process_is_active_B ? &(B(0, 0)) :
nullptr;
635 &(this->grid->blacs_context));
637 if (mpi_process_is_active_B)
638 Cblacs_gridexit(blacs_context_B);
640 MPI_Group_free(&group_A);
641 MPI_Group_free(&group_B);
642 if (MPI_COMM_NULL != communicator_B)
648template <
typename NumberType>
657 Assert(n_columns ==
int(matrix.n()),
661 if (grid->mpi_process_is_active)
663 for (
int i = 0; i < n_local_rows; ++i)
665 const int glob_i = global_row(i);
666 for (
int j = 0; j < n_local_columns; ++j)
668 const int glob_j = global_column(j);
669 matrix(glob_i, glob_j) = local_el(i, j);
681 for (
unsigned int i = 0; i < matrix.n(); ++i)
682 for (
unsigned int j = i + 1; j < matrix.m(); ++j)
685 for (
unsigned int i = 0; i < matrix.n(); ++i)
686 for (
unsigned int j = 0; j < i; ++j)
693 for (
unsigned int i = 0; i < matrix.n(); ++i)
694 for (
unsigned int j = i + 1; j < matrix.m(); ++j)
695 matrix(i, j) = matrix(j, i);
696 else if (uplo ==
'U')
697 for (
unsigned int i = 0; i < matrix.n(); ++i)
698 for (
unsigned int j = 0; j < i; ++j)
699 matrix(i, j) = matrix(j, i);
705template <
typename NumberType>
709 const std::pair<unsigned int, unsigned int> &offset_A,
710 const std::pair<unsigned int, unsigned int> &offset_B,
711 const std::pair<unsigned int, unsigned int> &submatrix_size)
const
714 if (submatrix_size.first == 0 || submatrix_size.second == 0)
727 int ierr, comparison;
728 ierr = MPI_Comm_compare(grid->mpi_communicator,
729 B.
grid->mpi_communicator,
732 Assert(comparison == MPI_IDENT,
733 ExcMessage(
"Matrix A and B must have a common MPI Communicator"));
741 int union_blacs_context = Csys2blacs_handle(this->grid->mpi_communicator);
742 const char *order =
"Col";
743 int union_n_process_rows =
745 int union_n_process_columns = 1;
746 Cblacs_gridinit(&union_blacs_context,
748 union_n_process_rows,
749 union_n_process_columns);
751 int n_grid_rows_A, n_grid_columns_A, my_row_A, my_column_A;
752 Cblacs_gridinfo(this->grid->blacs_context,
759 const bool in_context_A =
760 (my_row_A >= 0 && my_row_A < n_grid_rows_A) &&
761 (my_column_A >= 0 && my_column_A < n_grid_columns_A);
763 int n_grid_rows_B, n_grid_columns_B, my_row_B, my_column_B;
764 Cblacs_gridinfo(B.
grid->blacs_context,
771 const bool in_context_B =
772 (my_row_B >= 0 && my_row_B < n_grid_rows_B) &&
773 (my_column_B >= 0 && my_column_B < n_grid_columns_B);
775 const int n_rows_submatrix = submatrix_size.first;
776 const int n_columns_submatrix = submatrix_size.second;
779 int ia = offset_A.first + 1, ja = offset_A.second + 1;
780 int ib = offset_B.first + 1, jb = offset_B.second + 1;
782 std::array<int, 9> desc_A, desc_B;
784 const NumberType *loc_vals_A =
nullptr;
785 NumberType *loc_vals_B =
nullptr;
794 if (this->values.size() != 0)
795 loc_vals_A = this->values.data();
797 for (
unsigned int i = 0; i < desc_A.size(); ++i)
798 desc_A[i] = this->descriptor[i];
806 loc_vals_B = B.
values.data();
808 for (
unsigned int i = 0; i < desc_B.size(); ++i)
814 pgemr2d(&n_rows_submatrix,
815 &n_columns_submatrix,
824 &union_blacs_context);
829 Cblacs_gridexit(union_blacs_context);
834template <
typename NumberType>
842 if (this->grid->mpi_process_is_active)
844 this->descriptor[0] == 1,
846 "Copying of ScaLAPACK matrices only implemented for dense matrices"));
847 if (dest.
grid->mpi_process_is_active)
851 "Copying of ScaLAPACK matrices only implemented for dense matrices"));
867 MPI_Group group_source, group_dest, group_union;
868 ierr = MPI_Comm_group(this->grid->mpi_communicator, &group_source);
870 ierr = MPI_Comm_group(dest.
grid->mpi_communicator, &group_dest);
872 ierr = MPI_Group_union(group_source, group_dest, &group_union);
889 ierr = MPI_Comm_create_group(MPI_COMM_WORLD,
892 &mpi_communicator_union);
900 int union_blacs_context = Csys2blacs_handle(mpi_communicator_union);
901 const char *order =
"Col";
902 int union_n_process_rows =
904 int union_n_process_columns = 1;
905 Cblacs_gridinit(&union_blacs_context,
907 union_n_process_rows,
908 union_n_process_columns);
910 const NumberType *loc_vals_source =
nullptr;
911 NumberType *loc_vals_dest =
nullptr;
913 if (this->grid->mpi_process_is_active && (this->values.size() > 0))
917 "source: process is active but local matrix empty"));
918 loc_vals_source = this->values.data();
920 if (dest.
grid->mpi_process_is_active && (dest.
values.size() > 0))
925 "destination: process is active but local matrix empty"));
926 loc_vals_dest = dest.
values.data();
938 &union_blacs_context);
940 Cblacs_gridexit(union_blacs_context);
942 if (mpi_communicator_union != MPI_COMM_NULL)
944 ierr = MPI_Group_free(&group_source);
946 ierr = MPI_Group_free(&group_dest);
948 ierr = MPI_Group_free(&group_union);
953 if (this->grid->mpi_process_is_active)
954 dest.
values = this->values;
962template <
typename NumberType>
972template <
typename NumberType>
975 const NumberType alpha,
976 const NumberType beta,
977 const bool transpose_B)
999 ExcMessage(
"The matrices A and B need to have the same process grid"));
1001 if (this->grid->mpi_process_is_active)
1003 char trans_b = transpose_B ?
'T' :
'N';
1005 (this->values.size() > 0) ? this->values.data() :
nullptr;
1006 const NumberType *B_loc =
1028template <
typename NumberType>
1033 add(B, 1, a,
false);
1038template <
typename NumberType>
1048template <
typename NumberType>
1054 const bool transpose_A,
1055 const bool transpose_B)
const
1058 ExcMessage(
"The matrices A and B need to have the same process grid"));
1060 ExcMessage(
"The matrices B and C need to have the same process grid"));
1064 if (!transpose_A && !transpose_B)
1068 Assert(this->n_rows == C.n_rows,
1072 Assert(this->row_block_size == C.row_block_size,
1079 else if (transpose_A && !transpose_B)
1083 Assert(this->n_columns == C.n_rows,
1087 Assert(this->column_block_size == C.row_block_size,
1094 else if (!transpose_A && transpose_B)
1098 Assert(this->n_rows == C.n_rows,
1102 Assert(this->row_block_size == C.row_block_size,
1114 Assert(this->n_columns == C.n_rows,
1118 Assert(this->column_block_size == C.row_block_size,
1126 if (this->grid->mpi_process_is_active)
1128 char trans_a = transpose_A ?
'T' :
'N';
1129 char trans_b = transpose_B ?
'T' :
'N';
1131 const NumberType *A_loc =
1132 (this->values.size() > 0) ? this->values.data() :
nullptr;
1133 const NumberType *B_loc =
1135 NumberType *C_loc = (C.values.size() > 0) ? C.values.data() :
nullptr;
1137 int n = C.n_columns;
1138 int k = transpose_A ? this->n_rows : this->n_columns;
1147 &(this->submatrix_row),
1148 &(this->submatrix_column),
1157 &C.submatrix_column,
1165template <
typename NumberType>
1169 const bool adding)
const
1172 mult(1., B, 1., C,
false,
false);
1174 mult(1., B, 0, C,
false,
false);
1179template <
typename NumberType>
1183 const bool adding)
const
1186 mult(1., B, 1., C,
true,
false);
1188 mult(1., B, 0, C,
true,
false);
1193template <
typename NumberType>
1197 const bool adding)
const
1200 mult(1., B, 1., C,
false,
true);
1202 mult(1., B, 0, C,
false,
true);
1207template <
typename NumberType>
1211 const bool adding)
const
1214 mult(1., B, 1., C,
true,
true);
1216 mult(1., B, 0, C,
true,
true);
1221template <
typename NumberType>
1228 "Cholesky factorization can be applied to symmetric matrices only."));
1231 "Matrix has to be in Matrix state before calling this function."));
1233 if (grid->mpi_process_is_active)
1236 NumberType *A_loc = this->values.data();
1254template <
typename NumberType>
1260 "Matrix has to be in Matrix state before calling this function."));
1262 if (grid->mpi_process_is_active)
1265 NumberType *A_loc = this->values.data();
1267 const int iarow = indxg2p_(&submatrix_row,
1269 &(grid->this_process_row),
1271 &(grid->n_process_rows));
1272 const int mp = numroc_(&n_rows,
1274 &(grid->this_process_row),
1276 &(grid->n_process_rows));
1277 ipiv.resize(mp + row_block_size);
1295template <
typename NumberType>
1313 if (grid->mpi_process_is_active)
1315 const char uploTriangular =
1317 const char diag =
'N';
1319 NumberType *A_loc = this->values.data();
1320 ptrtri(&uploTriangular,
1342 compute_cholesky_factorization();
1344 compute_lu_factorization();
1346 if (grid->mpi_process_is_active)
1349 NumberType *A_loc = this->values.data();
1366 int lwork = -1, liwork = -1;
1384 lwork =
static_cast<int>(work[0]);
1387 iwork.resize(liwork);
1411template <
typename NumberType>
1412std::vector<NumberType>
1414 const std::pair<unsigned int, unsigned int> &index_limits,
1415 const bool compute_eigenvectors)
1421 std::pair<unsigned int, unsigned int> idx =
1422 std::make_pair(
std::min(index_limits.first, index_limits.second),
1423 std::max(index_limits.first, index_limits.second));
1426 if (idx.first == 0 && idx.second ==
static_cast<unsigned int>(n_rows - 1))
1427 return eigenpairs_symmetric(compute_eigenvectors);
1429 return eigenpairs_symmetric(compute_eigenvectors, idx);
1434template <
typename NumberType>
1435std::vector<NumberType>
1437 const std::pair<NumberType, NumberType> &value_limits,
1438 const bool compute_eigenvectors)
1440 Assert(!std::isnan(value_limits.first),
1442 Assert(!std::isnan(value_limits.second),
1445 std::pair<unsigned int, unsigned int> indices =
1449 return eigenpairs_symmetric(compute_eigenvectors, indices, value_limits);
1454template <
typename NumberType>
1455std::vector<NumberType>
1457 const bool compute_eigenvectors,
1458 const std::pair<unsigned int, unsigned int> &eigenvalue_idx,
1459 const std::pair<NumberType, NumberType> &eigenvalue_limits)
1463 "Matrix has to be in Matrix state before calling this function."));
1465 ExcMessage(
"Matrix has to be symmetric for this operation."));
1467 std::scoped_lock lock(mutex);
1469 const bool use_values = (std::isnan(eigenvalue_limits.first) ||
1470 std::isnan(eigenvalue_limits.second)) ?
1473 const bool use_indices =
1480 !(use_values && use_indices),
1482 "Prescribing both the index and value range for the eigenvalues is ambiguous"));
1486 std::unique_ptr<ScaLAPACKMatrix<NumberType>>
eigenvectors =
1487 compute_eigenvectors ?
1488 std::make_unique<ScaLAPACKMatrix<NumberType>>(n_rows,
1491 std::make_unique<ScaLAPACKMatrix<NumberType>>(
1492 grid->n_process_rows, grid->n_process_columns, grid, 1, 1);
1499 std::vector<NumberType> ev(n_rows);
1501 if (grid->mpi_process_is_active)
1508 char jobz = compute_eigenvectors ?
'V' :
'N';
1511 bool all_eigenpairs =
true;
1512 NumberType vl = NumberType(), vu = NumberType();
1518 NumberType abstol = NumberType();
1525 NumberType orfac = 0;
1527 std::vector<int> ifail;
1534 std::vector<int> iclustr;
1540 std::vector<NumberType> gap(n_local_rows * n_local_columns);
1550 all_eigenpairs =
true;
1555 all_eigenpairs =
false;
1556 vl =
std::min(eigenvalue_limits.first, eigenvalue_limits.second);
1557 vu =
std::max(eigenvalue_limits.first, eigenvalue_limits.second);
1563 all_eigenpairs =
false;
1566 il =
std::min(eigenvalue_idx.first, eigenvalue_idx.second) + 1;
1567 iu =
std::max(eigenvalue_idx.first, eigenvalue_idx.second) + 1;
1569 NumberType *A_loc = this->values.data();
1576 NumberType *eigenvectors_loc =
1577 (compute_eigenvectors ?
eigenvectors->values.data() :
nullptr);
1612 char cmach = compute_eigenvectors ?
'U' :
'S';
1613 plamch(&(this->grid->blacs_context), &cmach, abstol);
1615 ifail.resize(n_rows);
1616 iclustr.resize(2 * grid->n_process_rows * grid->n_process_columns);
1617 gap.resize(grid->n_process_rows * grid->n_process_columns);
1650 lwork =
static_cast<int>(work[0]);
1677 iwork.resize(liwork);
1714 if (compute_eigenvectors)
1718 while (ev.size() >
static_cast<size_type>(m))
1724 grid->send_to_inactive(&m, 1);
1729 if (!grid->mpi_process_is_active)
1734 grid->send_to_inactive(ev.data(), ev.size());
1741 if (compute_eigenvectors)
1754template <
typename NumberType>
1755std::vector<NumberType>
1757 const std::pair<unsigned int, unsigned int> &index_limits,
1758 const bool compute_eigenvectors)
1764 const std::pair<unsigned int, unsigned int> idx =
1765 std::make_pair(
std::min(index_limits.first, index_limits.second),
1766 std::max(index_limits.first, index_limits.second));
1769 if (idx.first == 0 && idx.second ==
static_cast<unsigned int>(n_rows - 1))
1770 return eigenpairs_symmetric_MRRR(compute_eigenvectors);
1772 return eigenpairs_symmetric_MRRR(compute_eigenvectors, idx);
1777template <
typename NumberType>
1778std::vector<NumberType>
1780 const std::pair<NumberType, NumberType> &value_limits,
1781 const bool compute_eigenvectors)
1786 const std::pair<unsigned int, unsigned int> indices =
1790 return eigenpairs_symmetric_MRRR(compute_eigenvectors, indices, value_limits);
1795template <
typename NumberType>
1796std::vector<NumberType>
1798 const bool compute_eigenvectors,
1799 const std::pair<unsigned int, unsigned int> &eigenvalue_idx,
1800 const std::pair<NumberType, NumberType> &eigenvalue_limits)
1804 "Matrix has to be in Matrix state before calling this function."));
1806 ExcMessage(
"Matrix has to be symmetric for this operation."));
1808 std::scoped_lock lock(mutex);
1810 const bool use_values = (std::isnan(eigenvalue_limits.first) ||
1811 std::isnan(eigenvalue_limits.second)) ?
1814 const bool use_indices =
1821 !(use_values && use_indices),
1823 "Prescribing both the index and value range for the eigenvalues is ambiguous"));
1827 std::unique_ptr<ScaLAPACKMatrix<NumberType>>
eigenvectors =
1828 compute_eigenvectors ?
1829 std::make_unique<ScaLAPACKMatrix<NumberType>>(n_rows,
1832 std::make_unique<ScaLAPACKMatrix<NumberType>>(
1833 grid->n_process_rows, grid->n_process_columns, grid, 1, 1);
1839 std::vector<NumberType> ev(n_rows);
1846 if (grid->mpi_process_is_active)
1853 char jobz = compute_eigenvectors ?
'V' :
'N';
1857 NumberType vl = NumberType(), vu = NumberType();
1872 vl =
std::min(eigenvalue_limits.first, eigenvalue_limits.second);
1873 vu =
std::max(eigenvalue_limits.first, eigenvalue_limits.second);
1881 il =
std::min(eigenvalue_idx.first, eigenvalue_idx.second) + 1;
1882 iu =
std::max(eigenvalue_idx.first, eigenvalue_idx.second) + 1;
1884 NumberType *A_loc = this->values.data();
1892 NumberType *eigenvectors_loc =
1893 (compute_eigenvectors ?
eigenvectors->values.data() :
nullptr);
1924 lwork =
static_cast<int>(work[0]);
1927 iwork.resize(liwork);
1956 if (compute_eigenvectors)
1960 "psyevr failed to compute all eigenvectors for the selected eigenvalues"));
1965 if (compute_eigenvectors)
1969 while (ev.size() >
static_cast<size_type>(m))
1975 grid->send_to_inactive(&m, 1);
1980 if (!grid->mpi_process_is_active)
1985 grid->send_to_inactive(ev.data(), ev.size());
1992 if (compute_eigenvectors)
2005template <
typename NumberType>
2006std::vector<NumberType>
2012 "Matrix has to be in Matrix state before calling this function."));
2013 Assert(row_block_size == column_block_size,
2016 const bool left_singular_vectors = (U !=
nullptr) ?
true :
false;
2017 const bool right_singular_vectors = (VT !=
nullptr) ?
true :
false;
2019 if (left_singular_vectors)
2022 Assert(U->n_rows == U->n_columns,
2024 Assert(row_block_size == U->row_block_size,
2026 Assert(column_block_size == U->column_block_size,
2028 Assert(grid->blacs_context == U->grid->blacs_context,
2031 if (right_singular_vectors)
2041 Assert(grid->blacs_context == VT->
grid->blacs_context,
2043 VT->
grid->blacs_context));
2045 std::scoped_lock lock(mutex);
2047 std::vector<NumberType> sv(
std::min(n_rows, n_columns));
2049 if (grid->mpi_process_is_active)
2051 char jobu = left_singular_vectors ?
'V' :
'N';
2052 char jobvt = right_singular_vectors ?
'V' :
'N';
2053 NumberType *A_loc = this->values.data();
2054 NumberType *U_loc = left_singular_vectors ? U->values.data() :
nullptr;
2055 NumberType *VT_loc = right_singular_vectors ? VT->
values.data() :
nullptr;
2075 &U->submatrix_column,
2086 lwork =
static_cast<int>(work[0]);
2100 &U->submatrix_column,
2115 grid->send_to_inactive(sv.data(), sv.size());
2125template <
typename NumberType>
2131 ExcMessage(
"The matrices A and B need to have the same process grid"));
2134 "Matrix has to be in Matrix state before calling this function."));
2137 "Matrix B has to be in Matrix state before calling this function."));
2150 Assert(row_block_size == column_block_size,
2152 "Use identical block sizes for rows and columns of matrix A"));
2155 "Use identical block sizes for rows and columns of matrix B"));
2158 "Use identical block-cyclic distribution for matrices A and B"));
2160 std::scoped_lock lock(mutex);
2162 if (grid->mpi_process_is_active)
2165 NumberType *A_loc = this->values.data();
2166 NumberType *B_loc = B.
values.data();
2192 lwork =
static_cast<int>(work[0]);
2217template <
typename NumberType>
2223 "Matrix has to be in Matrix state before calling this function."));
2224 Assert(row_block_size == column_block_size,
2226 "Use identical block sizes for rows and columns of matrix A"));
2228 ratio > 0. && ratio < 1.,
2230 "input parameter ratio has to be larger than zero and smaller than 1"));
2244 std::vector<NumberType> sv = this->compute_SVD(&U, &VT);
2245 AssertThrow(sv[0] > std::numeric_limits<NumberType>::min(),
2252 unsigned int n_sv = 1;
2253 std::vector<NumberType> inv_sigma;
2254 inv_sigma.push_back(1 / sv[0]);
2256 for (
unsigned int i = 1; i < sv.size(); ++i)
2257 if (sv[i] > sv[0] * ratio)
2260 inv_sigma.push_back(1 / sv[i]);
2282 std::make_pair(0, 0),
2283 std::make_pair(0, 0),
2284 std::make_pair(n_rows, n_sv));
2286 std::make_pair(0, 0),
2287 std::make_pair(0, 0),
2288 std::make_pair(n_sv, n_columns));
2291 this->reinit(n_columns,
2297 VT_R.
mult(1, U_R, 0, *
this,
true,
true);
2304template <
typename NumberType>
2307 const NumberType a_norm)
const
2311 "Matrix has to be in Cholesky state before calling this function."));
2312 std::scoped_lock lock(mutex);
2313 NumberType rcond = 0.;
2315 if (grid->mpi_process_is_active)
2317 int liwork = n_local_rows;
2318 iwork.resize(liwork);
2321 const NumberType *A_loc = this->values.data();
2341 lwork =
static_cast<int>(std::ceil(work[0]));
2360 grid->send_to_inactive(&rcond);
2366template <
typename NumberType>
2370 const char type(
'O');
2373 return norm_symmetric(type);
2375 return norm_general(type);
2380template <
typename NumberType>
2384 const char type(
'I');
2387 return norm_symmetric(type);
2389 return norm_general(type);
2394template <
typename NumberType>
2398 const char type(
'F');
2401 return norm_symmetric(type);
2403 return norm_general(type);
2408template <
typename NumberType>
2414 ExcMessage(
"norms can be called in matrix state only."));
2415 std::scoped_lock lock(mutex);
2416 NumberType res = 0.;
2418 if (grid->mpi_process_is_active)
2420 const int iarow = indxg2p_(&submatrix_row,
2422 &(grid->this_process_row),
2424 &(grid->n_process_rows));
2425 const int iacol = indxg2p_(&submatrix_column,
2427 &(grid->this_process_column),
2428 &first_process_column,
2429 &(grid->n_process_columns));
2430 const int mp0 = numroc_(&n_rows,
2432 &(grid->this_process_row),
2434 &(grid->n_process_rows));
2435 const int nq0 = numroc_(&n_columns,
2437 &(grid->this_process_column),
2439 &(grid->n_process_columns));
2445 if (type ==
'O' || type ==
'1')
2447 else if (type ==
'I')
2451 const NumberType *A_loc = this->values.begin();
2461 grid->send_to_inactive(&res);
2467template <
typename NumberType>
2473 ExcMessage(
"norms can be called in matrix state only."));
2475 ExcMessage(
"Matrix has to be symmetric for this operation."));
2476 std::scoped_lock lock(mutex);
2477 NumberType res = 0.;
2479 if (grid->mpi_process_is_active)
2484 ilcm_(&(grid->n_process_rows), &(grid->n_process_columns));
2485 const int v2 = lcm / (grid->n_process_rows);
2487 const int IAROW = indxg2p_(&submatrix_row,
2489 &(grid->this_process_row),
2491 &(grid->n_process_rows));
2492 const int IACOL = indxg2p_(&submatrix_column,
2494 &(grid->this_process_column),
2495 &first_process_column,
2496 &(grid->n_process_columns));
2497 const int Np0 = numroc_(&n_columns ,
2499 &(grid->this_process_row),
2501 &(grid->n_process_rows));
2502 const int Nq0 = numroc_(&n_columns ,
2504 &(grid->this_process_column),
2506 &(grid->n_process_columns));
2508 const int v1 = iceil_(&Np0, &row_block_size);
2509 const int ldw = (n_local_rows == n_local_columns) ?
2511 row_block_size * iceil_(&
v1, &v2);
2514 (type ==
'M' || type ==
'F' || type ==
'E') ? 0 : 2 * Nq0 + Np0 + ldw;
2516 const NumberType *A_loc = this->values.begin();
2526 grid->send_to_inactive(&res);
2532#ifdef DEAL_II_WITH_HDF5
2538 create_HDF5_state_enum_id(hid_t &state_enum_id)
2544 herr_t status = H5Tenum_insert(state_enum_id,
"cholesky", &val);
2547 status = H5Tenum_insert(state_enum_id,
"eigenvalues", &val);
2550 status = H5Tenum_insert(state_enum_id,
"inverse_matrix", &val);
2553 status = H5Tenum_insert(state_enum_id,
"inverse_svd", &val);
2556 status = H5Tenum_insert(state_enum_id,
"lu", &val);
2559 status = H5Tenum_insert(state_enum_id,
"matrix", &val);
2562 status = H5Tenum_insert(state_enum_id,
"svd", &val);
2565 status = H5Tenum_insert(state_enum_id,
"unusable", &val);
2570 create_HDF5_property_enum_id(hid_t &property_enum_id)
2575 herr_t status = H5Tenum_insert(property_enum_id,
"diagonal", &prop);
2578 status = H5Tenum_insert(property_enum_id,
"general", &prop);
2581 status = H5Tenum_insert(property_enum_id,
"hessenberg", &prop);
2584 status = H5Tenum_insert(property_enum_id,
"lower_triangular", &prop);
2587 status = H5Tenum_insert(property_enum_id,
"symmetric", &prop);
2590 status = H5Tenum_insert(property_enum_id,
"upper_triangular", &prop);
2599template <
typename NumberType>
2602 const std::string &filename,
2603 const std::pair<unsigned int, unsigned int> &chunk_size)
const
2605#ifndef DEAL_II_WITH_HDF5
2611 std::pair<unsigned int, unsigned int> chunks_size_ = chunk_size;
2617 chunks_size_.first = n_rows;
2618 chunks_size_.second = 1;
2620 Assert(chunks_size_.first > 0,
2621 ExcMessage(
"The row chunk size must be larger than 0."));
2623 Assert(chunks_size_.second > 0,
2624 ExcMessage(
"The column chunk size must be larger than 0."));
2627# ifdef H5_HAVE_PARALLEL
2629 save_parallel(filename, chunks_size_);
2633 save_serial(filename, chunks_size_);
2641template <
typename NumberType>
2644 const std::string &filename,
2645 const std::pair<unsigned int, unsigned int> &chunk_size)
const
2647#ifndef DEAL_II_WITH_HDF5
2662 const auto column_grid =
2663 std::make_shared<Utilities::MPI::ProcessGrid>(this->grid->mpi_communicator,
2667 const int MB = n_rows, NB = n_columns;
2673 if (tmp.
grid->mpi_process_is_active)
2679 H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
2682 hsize_t chunk_dims[2];
2685 chunk_dims[0] = chunk_size.second;
2686 chunk_dims[1] = chunk_size.first;
2687 hid_t data_property = H5Pcreate(H5P_DATASET_CREATE);
2688 status = H5Pset_chunk(data_property, 2, chunk_dims);
2695 dims[0] = n_columns;
2697 hid_t dataspace_id = H5Screate_simple(2, dims,
nullptr);
2700 hid_t type_id = hdf5_type_id(tmp.
values.data());
2701 hid_t dataset_id = H5Dcreate2(file_id,
2711 dataset_id, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, tmp.
values.data());
2716 hid_t state_enum_id, property_enum_id;
2717 internal::create_HDF5_state_enum_id(state_enum_id);
2718 internal::create_HDF5_property_enum_id(property_enum_id);
2721 hsize_t dims_state[1];
2723 hid_t state_enum_dataspace = H5Screate_simple(1, dims_state,
nullptr);
2725 hid_t state_enum_dataset = H5Dcreate2(file_id,
2728 state_enum_dataspace,
2733 status = H5Dwrite(state_enum_dataset,
2742 hsize_t dims_property[1];
2743 dims_property[0] = 1;
2744 hid_t property_enum_dataspace =
2745 H5Screate_simple(1, dims_property,
nullptr);
2747 hid_t property_enum_dataset = H5Dcreate2(file_id,
2750 property_enum_dataspace,
2755 status = H5Dwrite(property_enum_dataset,
2764 status = H5Dclose(dataset_id);
2766 status = H5Dclose(state_enum_dataset);
2768 status = H5Dclose(property_enum_dataset);
2772 status = H5Sclose(dataspace_id);
2774 status = H5Sclose(state_enum_dataspace);
2776 status = H5Sclose(property_enum_dataspace);
2780 status = H5Tclose(state_enum_id);
2782 status = H5Tclose(property_enum_id);
2786 status = H5Pclose(data_property);
2790 status = H5Fclose(file_id);
2798template <
typename NumberType>
2801 const std::string &filename,
2802 const std::pair<unsigned int, unsigned int> &chunk_size)
const
2804#ifndef DEAL_II_WITH_HDF5
2810 const unsigned int n_mpi_processes(
2812 MPI_Info info = MPI_INFO_NULL;
2820 const auto column_grid =
2821 std::make_shared<Utilities::MPI::ProcessGrid>(this->grid->mpi_communicator,
2825 const int MB = n_rows;
2838 const int NB =
std::max(
static_cast<int>(std::ceil(
2839 static_cast<double>(n_columns) / n_mpi_processes)),
2853 hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS);
2854 status = H5Pset_fapl_mpio(plist_id, tmp.
grid->mpi_communicator, info);
2859 H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, plist_id);
2860 status = H5Pclose(plist_id);
2869 hid_t filespace = H5Screate_simple(2, dims,
nullptr);
2872 hsize_t chunk_dims[2];
2874 chunk_dims[0] = chunk_size.second;
2875 chunk_dims[1] = chunk_size.first;
2876 plist_id = H5Pcreate(H5P_DATASET_CREATE);
2877 H5Pset_chunk(plist_id, 2, chunk_dims);
2878 hid_t type_id = hdf5_type_id(
data);
2879 hid_t dset_id = H5Dcreate2(
2880 file_id,
"/matrix", type_id, filespace, H5P_DEFAULT, plist_id, H5P_DEFAULT);
2882 status = H5Sclose(filespace);
2885 status = H5Pclose(plist_id);
2889 std::vector<int> proc_n_local_rows(n_mpi_processes),
2890 proc_n_local_columns(n_mpi_processes);
2894 proc_n_local_rows.data(),
2897 tmp.
grid->mpi_communicator);
2902 proc_n_local_columns.data(),
2905 tmp.
grid->mpi_communicator);
2917 hid_t memspace = H5Screate_simple(2, count,
nullptr);
2919 hsize_t offset[2] = {0};
2920 for (
unsigned int i = 0; i <
my_rank; ++i)
2921 offset[0] += proc_n_local_columns[i];
2924 filespace = H5Dget_space(dset_id);
2925 status = H5Sselect_hyperslab(
2926 filespace, H5S_SELECT_SET, offset,
nullptr, count,
nullptr);
2930 plist_id = H5Pcreate(H5P_DATASET_XFER);
2931 status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT);
2935 if (tmp.
values.size() > 0)
2937 status = H5Dwrite(dset_id, type_id, memspace, filespace, plist_id,
data);
2941 status = H5Dclose(dset_id);
2943 status = H5Sclose(filespace);
2945 status = H5Sclose(memspace);
2947 status = H5Pclose(plist_id);
2949 status = H5Fclose(file_id);
2954 ierr = MPI_Barrier(tmp.
grid->mpi_communicator);
2958 if (tmp.
grid->this_mpi_process == 0)
2961 hid_t file_id_reopen =
2962 H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
2966 hid_t state_enum_id, property_enum_id;
2967 internal::create_HDF5_state_enum_id(state_enum_id);
2968 internal::create_HDF5_property_enum_id(property_enum_id);
2971 hsize_t dims_state[1];
2973 hid_t state_enum_dataspace = H5Screate_simple(1, dims_state,
nullptr);
2975 hid_t state_enum_dataset = H5Dcreate2(file_id_reopen,
2978 state_enum_dataspace,
2983 status = H5Dwrite(state_enum_dataset,
2992 hsize_t dims_property[1];
2993 dims_property[0] = 1;
2994 hid_t property_enum_dataspace =
2995 H5Screate_simple(1, dims_property,
nullptr);
2997 hid_t property_enum_dataset = H5Dcreate2(file_id_reopen,
3000 property_enum_dataspace,
3005 status = H5Dwrite(property_enum_dataset,
3013 status = H5Dclose(state_enum_dataset);
3015 status = H5Dclose(property_enum_dataset);
3017 status = H5Sclose(state_enum_dataspace);
3019 status = H5Sclose(property_enum_dataspace);
3021 status = H5Tclose(state_enum_id);
3023 status = H5Tclose(property_enum_id);
3025 status = H5Fclose(file_id_reopen);
3034template <
typename NumberType>
3038#ifndef DEAL_II_WITH_HDF5
3042# ifdef H5_HAVE_PARALLEL
3044 load_parallel(filename);
3048 load_serial(filename);
3055template <
typename NumberType>
3059#ifndef DEAL_II_WITH_HDF5
3070 const auto one_grid =
3071 std::make_shared<Utilities::MPI::ProcessGrid>(this->grid->mpi_communicator,
3075 const int MB = n_rows, NB = n_columns;
3079 int property_int = -1;
3083 if (tmp.
grid->mpi_process_is_active)
3088 hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
3091 hid_t dataset_id = H5Dopen2(file_id,
"/matrix", H5P_DEFAULT);
3097 hid_t datatype = H5Dget_type(dataset_id);
3098 H5T_class_t t_class_in = H5Tget_class(datatype);
3099 H5T_class_t t_class = H5Tget_class(hdf5_type_id(tmp.
values.data()));
3101 t_class_in == t_class,
3103 "The data type of the matrix to be read does not match the archive"));
3106 hid_t dataspace_id = H5Dget_space(dataset_id);
3108 const int ndims = H5Sget_simple_extent_ndims(dataspace_id);
3112 H5Sget_simple_extent_dims(dataspace_id, dims,
nullptr);
3114 static_cast<int>(dims[0]) == n_columns,
3116 "The number of columns of the matrix does not match the content of the archive"));
3118 static_cast<int>(dims[1]) == n_rows,
3120 "The number of rows of the matrix does not match the content of the archive"));
3123 status = H5Dread(dataset_id,
3124 hdf5_type_id(tmp.
values.data()),
3133 hid_t state_enum_id, property_enum_id;
3134 internal::create_HDF5_state_enum_id(state_enum_id);
3135 internal::create_HDF5_property_enum_id(property_enum_id);
3138 hid_t dataset_state_id = H5Dopen2(file_id,
"/state", H5P_DEFAULT);
3139 hid_t datatype_state = H5Dget_type(dataset_state_id);
3140 H5T_class_t t_class_state = H5Tget_class(datatype_state);
3143 hid_t dataset_property_id = H5Dopen2(file_id,
"/property", H5P_DEFAULT);
3144 hid_t datatype_property = H5Dget_type(dataset_property_id);
3145 H5T_class_t t_class_property = H5Tget_class(datatype_property);
3149 hid_t dataspace_state = H5Dget_space(dataset_state_id);
3150 hid_t dataspace_property = H5Dget_space(dataset_property_id);
3152 const int ndims_state = H5Sget_simple_extent_ndims(dataspace_state);
3154 const int ndims_property = H5Sget_simple_extent_ndims(dataspace_property);
3157 hsize_t dims_state[1];
3158 H5Sget_simple_extent_dims(dataspace_state, dims_state,
nullptr);
3160 hsize_t dims_property[1];
3161 H5Sget_simple_extent_dims(dataspace_property, dims_property,
nullptr);
3165 status = H5Dread(dataset_state_id,
3175 state_int =
static_cast<int>(tmp.
state);
3177 status = H5Dread(dataset_property_id,
3187 property_int =
static_cast<int>(tmp.
property);
3190 status = H5Sclose(dataspace_id);
3192 status = H5Sclose(dataspace_state);
3194 status = H5Sclose(dataspace_property);
3198 status = H5Tclose(datatype);
3200 status = H5Tclose(state_enum_id);
3202 status = H5Tclose(property_enum_id);
3206 status = H5Dclose(dataset_state_id);
3208 status = H5Dclose(dataset_id);
3210 status = H5Dclose(dataset_property_id);
3214 status = H5Fclose(file_id);
3218 tmp.
grid->send_to_inactive(&state_int, 1);
3221 tmp.
grid->send_to_inactive(&property_int, 1);
3233template <
typename NumberType>
3237#ifndef DEAL_II_WITH_HDF5
3241# ifndef H5_HAVE_PARALLEL
3246 const unsigned int n_mpi_processes(
3248 MPI_Info info = MPI_INFO_NULL;
3255 const auto column_grid =
3256 std::make_shared<Utilities::MPI::ProcessGrid>(this->grid->mpi_communicator,
3260 const int MB = n_rows;
3262 const int NB =
std::max(
static_cast<int>(std::ceil(
3263 static_cast<double>(n_columns) / n_mpi_processes)),
3274 hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS);
3275 status = H5Pset_fapl_mpio(plist_id, tmp.
grid->mpi_communicator, info);
3280 hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, plist_id);
3281 status = H5Pclose(plist_id);
3285 hid_t dataset_id = H5Dopen2(file_id,
"/matrix", H5P_DEFAULT);
3291 hid_t datatype = hdf5_type_id(
data);
3292 hid_t datatype_inp = H5Dget_type(dataset_id);
3293 H5T_class_t t_class_inp = H5Tget_class(datatype_inp);
3294 H5T_class_t t_class = H5Tget_class(datatype);
3296 t_class_inp == t_class,
3298 "The data type of the matrix to be read does not match the archive"));
3302 hid_t dataspace_id = H5Dget_space(dataset_id);
3304 const int ndims = H5Sget_simple_extent_ndims(dataspace_id);
3308 status = H5Sget_simple_extent_dims(dataspace_id, dims,
nullptr);
3311 static_cast<int>(dims[0]) == n_columns,
3313 "The number of columns of the matrix does not match the content of the archive"));
3315 static_cast<int>(dims[1]) == n_rows,
3317 "The number of rows of the matrix does not match the content of the archive"));
3320 std::vector<int> proc_n_local_rows(n_mpi_processes),
3321 proc_n_local_columns(n_mpi_processes);
3325 proc_n_local_rows.data(),
3328 tmp.
grid->mpi_communicator);
3333 proc_n_local_columns.data(),
3336 tmp.
grid->mpi_communicator);
3349 hsize_t offset[2] = {0};
3350 for (
unsigned int i = 0; i <
my_rank; ++i)
3351 offset[0] += proc_n_local_columns[i];
3354 status = H5Sselect_hyperslab(
3355 dataspace_id, H5S_SELECT_SET, offset,
nullptr, count,
nullptr);
3359 hid_t memspace = H5Screate_simple(2, count,
nullptr);
3363 H5Dread(dataset_id, datatype, memspace, dataspace_id, H5P_DEFAULT,
data);
3367 hid_t state_enum_id, property_enum_id;
3368 internal::create_HDF5_state_enum_id(state_enum_id);
3369 internal::create_HDF5_property_enum_id(property_enum_id);
3372 hid_t dataset_state_id = H5Dopen2(file_id,
"/state", H5P_DEFAULT);
3373 hid_t datatype_state = H5Dget_type(dataset_state_id);
3374 H5T_class_t t_class_state = H5Tget_class(datatype_state);
3377 hid_t dataset_property_id = H5Dopen2(file_id,
"/property", H5P_DEFAULT);
3378 hid_t datatype_property = H5Dget_type(dataset_property_id);
3379 H5T_class_t t_class_property = H5Tget_class(datatype_property);
3383 hid_t dataspace_state = H5Dget_space(dataset_state_id);
3384 hid_t dataspace_property = H5Dget_space(dataset_property_id);
3386 const int ndims_state = H5Sget_simple_extent_ndims(dataspace_state);
3388 const int ndims_property = H5Sget_simple_extent_ndims(dataspace_property);
3391 hsize_t dims_state[1];
3392 H5Sget_simple_extent_dims(dataspace_state, dims_state,
nullptr);
3394 hsize_t dims_property[1];
3395 H5Sget_simple_extent_dims(dataspace_property, dims_property,
nullptr);
3400 dataset_state_id, state_enum_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, &tmp.
state);
3403 status = H5Dread(dataset_property_id,
3412 status = H5Sclose(memspace);
3414 status = H5Dclose(dataset_id);
3416 status = H5Dclose(dataset_state_id);
3418 status = H5Dclose(dataset_property_id);
3420 status = H5Sclose(dataspace_id);
3422 status = H5Sclose(dataspace_state);
3424 status = H5Sclose(dataspace_property);
3428 status = H5Tclose(state_enum_id);
3430 status = H5Tclose(property_enum_id);
3432 status = H5Fclose(file_id);
3448 template <
typename NumberType>
3456 for (
unsigned int i = 0; i < matrix.local_n(); ++i)
3458 const NumberType s = factors[matrix.global_column(i)];
3460 for (
unsigned int j = 0; j < matrix.local_m(); ++j)
3461 matrix.local_el(j, i) *= s;
3465 template <
typename NumberType>
3473 for (
unsigned int i = 0; i <
matrix.local_m(); ++i)
3475 const NumberType s = factors[
matrix.global_row(i)];
3477 for (
unsigned int j = 0; j <
matrix.local_n(); ++j)
3478 matrix.local_el(i, j) *= s;
3487template <
typename NumberType>
3488template <
class InputVector>
3492 if (this->grid->mpi_process_is_active)
3498template <
typename NumberType>
3499template <
class InputVector>
3503 if (this->grid->mpi_process_is_active)
3510#include "lac/scalapack.inst"
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
std::vector< NumberType > compute_SVD(ScaLAPACKMatrix< NumberType > *U=nullptr, ScaLAPACKMatrix< NumberType > *VT=nullptr)
std::vector< NumberType > eigenpairs_symmetric_by_value(const std::pair< NumberType, NumberType > &value_limits, const bool compute_eigenvectors)
NumberType frobenius_norm() const
unsigned int pseudoinverse(const NumberType ratio)
std::vector< NumberType > eigenpairs_symmetric_by_value_MRRR(const std::pair< NumberType, NumberType > &value_limits, const bool compute_eigenvectors)
void copy_from(const LAPACKFullMatrix< NumberType > &matrix, const unsigned int rank)
void save_parallel(const std::string &filename, const std::pair< unsigned int, unsigned int > &chunk_size) const
void least_squares(ScaLAPACKMatrix< NumberType > &B, const bool transpose=false)
ScaLAPACKMatrix< NumberType > & operator=(const FullMatrix< NumberType > &)
void Tadd(const NumberType b, const ScaLAPACKMatrix< NumberType > &B)
void mTmult(ScaLAPACKMatrix< NumberType > &C, const ScaLAPACKMatrix< NumberType > &B, const bool adding=false) const
void add(const ScaLAPACKMatrix< NumberType > &B, const NumberType a=0., const NumberType b=1., const bool transpose_B=false)
LAPACKSupport::State get_state() const
LAPACKSupport::Property get_property() const
void Tmmult(ScaLAPACKMatrix< NumberType > &C, const ScaLAPACKMatrix< NumberType > &B, const bool adding=false) 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()))
void scale_rows(const InputVector &factors)
std::shared_ptr< const Utilities::MPI::ProcessGrid > grid
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)
void load(const std::string &filename)
const int submatrix_column
void mmult(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()))
void save_serial(const std::string &filename, const std::pair< unsigned int, unsigned int > &chunk_size) const
NumberType norm_general(const char type) const
void save(const std::string &filename, const std::pair< unsigned int, unsigned int > &chunk_size=std::make_pair(numbers::invalid_unsigned_int, numbers::invalid_unsigned_int)) const
void load_parallel(const std::string &filename)
NumberType l1_norm() const
void compute_lu_factorization()
NumberType norm_symmetric(const char type) const
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
LAPACKSupport::Property property
void set_property(const LAPACKSupport::Property property)
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)
void load_serial(const std::string &filename)
std::vector< NumberType > eigenpairs_symmetric_by_index_MRRR(const std::pair< unsigned int, unsigned int > &index_limits, const bool compute_eigenvectors)
NumberType reciprocal_condition_number(const NumberType a_norm) const
LAPACKSupport::State state
void TmTmult(ScaLAPACKMatrix< NumberType > &C, const ScaLAPACKMatrix< NumberType > &B, const bool adding=false) const
std::vector< NumberType > eigenpairs_symmetric_by_index(const std::pair< unsigned int, unsigned int > &index_limits, const bool compute_eigenvectors)
unsigned int global_column(const unsigned int loc_column) const
void copy_to(FullMatrix< NumberType > &matrix) const
unsigned int global_row(const unsigned int loc_row) const
void compute_cholesky_factorization()
void copy_transposed(const ScaLAPACKMatrix< NumberType > &B)
NumberType linfty_norm() const
void scale_columns(const InputVector &factors)
AlignedVector< T > values
void reinit(const size_type size1, const size_type size2, const bool omit_default_initialization=false)
#define DEAL_II_NAMESPACE_OPEN
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcErrorCode(std::string arg1, types::blas_int arg2)
#define Assert(cond, exc)
#define AssertIsFinite(number)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcNeedsHDF5()
static ::ExceptionBase & ExcIndexRange(std::size_t arg1, std::size_t arg2, std::size_t arg3)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
const unsigned int my_rank
std::vector< index_type > data
@ cholesky
Contents is a Cholesky decomposition.
@ lu
Contents is an LU decomposition.
@ matrix
Contents is actually a matrix.
@ unusable
Contents is something useless.
@ inverse_matrix
Contents is the inverse of a matrix.
@ svd
Matrix contains singular value decomposition,.
@ inverse_svd
Matrix is the inverse of a singular value decomposition.
@ eigenvalues
Eigenvalue vector is filled.
@ symmetric
Matrix is symmetric.
@ hessenberg
Matrix is in upper Hessenberg form.
@ diagonal
Matrix is diagonal.
@ upper_triangular
Matrix is upper triangular.
@ lower_triangular
Matrix is lower triangular.
@ general
No special properties.
T sum(const T &t, const MPI_Comm mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
T max(const T &t, const MPI_Comm mpi_communicator)
T min(const T &t, const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
const MPI_Datatype mpi_type_id_for_type
void free_communicator(MPI_Comm mpi_communicator)
constexpr unsigned int invalid_unsigned_int
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)