15#ifndef dealii_solver_gmres_h
16#define dealii_solver_gmres_h
48 template <
typename,
typename>
64 namespace SolverGMRESImplementation
73 template <
typename VectorType>
121 std::vector<typename VectorMemory<VectorType>::Pointer>
data;
134 template <
typename Number>
145 const unsigned int max_basis_size,
146 const bool force_reorthogonalization);
170 template <
typename VectorType>
173 const unsigned int n,
175 const unsigned int accumulated_iterations = 0,
176 const boost::signals2::signal<
void(
int)> &reorthogonalize_signal =
177 boost::signals2::signal<
void(
int)>());
282 std::vector<std::pair<double, double>> &rotations,
355template <
typename VectorType = Vector<
double>>
376 const bool right_preconditioning =
false,
377 const bool use_default_residual =
true,
378 const bool force_re_orthogonalization =
false,
379 const bool batched_mode =
false,
381 orthogonalization_strategy =
383 delayed_classical_gram_schmidt);
464 template <
typename MatrixType,
typename PreconditionerType>
468 void solve(const MatrixType &A,
471 const PreconditionerType &preconditioner);
479 boost::signals2::connection
480 connect_condition_number_slot(const
std::function<
void(
double)> &slot,
481 const
bool every_iteration = false);
489 boost::signals2::connection
490 connect_eigenvalues_slot(
491 const
std::function<
void(const
std::vector<
std::complex<
double>> &)> &slot,
492 const
bool every_iteration = false);
501 boost::signals2::connection
502 connect_hessenberg_slot(
504 const
bool every_iteration = true);
512 boost::signals2::connection
513 connect_krylov_space_slot(
515 void(const
internal::SolverGMRESImplementation::TmpVectors<VectorType> &)>
523 boost::signals2::connection
524 connect_re_orthogonalization_slot(const
std::function<
void(
int)> &slot);
529 << "The number of temporary vectors you gave (" << arg1
530 << ") is too small. It should be at least 10 for "
531 << "any results, and much more for reasonable ones.");
543 boost::signals2::signal<
void(
double)> condition_number_signal;
549 boost::signals2::signal<
void(
double)> all_condition_numbers_signal;
555 boost::signals2::signal<
void(const
std::vector<
std::complex<
double>> &)>
562 boost::signals2::signal<
void(const
std::vector<
std::complex<
double>> &)>
563 all_eigenvalues_signal;
576 all_hessenberg_signal;
582 boost::signals2::signal<
void(
583 const
internal::SolverGMRESImplementation::TmpVectors<VectorType> &)>
590 boost::signals2::signal<
void(
int)> re_orthogonalize_signal;
612 compute_eigs_and_cond(
614 const
unsigned int n,
615 const
boost::signals2::signal<
616 void(const
std::vector<
std::complex<
double>> &)> &eigenvalues_signal,
619 const
boost::signals2::signal<
void(
double)> &cond_signal);
625 internal::SolverGMRESImplementation::ArnoldiProcess<
626 typename VectorType::value_type>
652template <typename VectorType =
Vector<
double>>
667 orthogonalization_strategy =
669 delayed_classical_gram_schmidt)
670 : max_basis_size(max_basis_size)
671 , orthogonalization_strategy(orthogonalization_strategy)
702 template <
typename MatrixType,
typename PreconditionerType>
706 void solve(const MatrixType &A,
709 const PreconditionerType &preconditioner);
721 internal::SolverGMRESImplementation::ArnoldiProcess<
722 typename VectorType::value_type>
732template <
typename VectorType>
735 const unsigned int max_basis_size,
736 const bool right_preconditioning,
737 const bool use_default_residual,
738 const bool force_re_orthogonalization,
739 const bool batched_mode,
741 : max_n_tmp_vectors(0)
742 , max_basis_size(max_basis_size)
743 , right_preconditioning(right_preconditioning)
744 , use_default_residual(use_default_residual)
745 , force_re_orthogonalization(force_re_orthogonalization)
746 , batched_mode(batched_mode)
747 , orthogonalization_strategy(orthogonalization_strategy)
749 Assert(max_basis_size >= 1,
750 ExcMessage(
"SolverGMRES needs at least one vector in the "
756template <
typename VectorType>
760 const AdditionalData &
data)
762 , additional_data(
data)
768template <
typename VectorType>
771 const AdditionalData &
data)
773 , additional_data(
data)
781 namespace SolverGMRESImplementation
783 template <
typename VectorType>
792 template <
typename VectorType>
794 TmpVectors<VectorType>::operator[](
const unsigned int i)
const
804 template <
typename VectorType>
806 TmpVectors<VectorType>::operator()(
const unsigned int i,
807 const VectorType &temp)
810 if (
data[i] ==
nullptr)
813 data[i]->reinit(temp,
true);
820 template <
typename VectorType>
822 TmpVectors<VectorType>::size()
const
824 return (
data.size() > 0 ?
data.size() - 1 : 0);
829 template <
typename VectorType,
typename Enable =
void>
830 struct is_dealii_compatible_vector;
832 template <
typename VectorType>
833 struct is_dealii_compatible_vector<
835 std::enable_if_t<!internal::is_block_vector<VectorType>>>
837 static constexpr bool value =
842 std::is_same_v<VectorType, Vector<typename VectorType::value_type>>;
847 template <
typename VectorType>
848 struct is_dealii_compatible_vector<
850 std::enable_if_t<internal::is_block_vector<VectorType>>>
852 static constexpr bool value =
854 typename VectorType::BlockType,
857 std::is_same_v<VectorType, Vector<typename VectorType::value_type>>;
863 std::enable_if_t<!IsBlockVector<VectorType>::value,
VectorType>
874 std::enable_if_t<IsBlockVector<VectorType>::value,
VectorType> * =
879 return vector.n_blocks();
885 std::enable_if_t<!IsBlockVector<VectorType>::value,
VectorType>
888 block(VectorType &vector,
const unsigned int b)
898 std::enable_if_t<!IsBlockVector<VectorType>::value,
VectorType>
901 block(
const VectorType &vector,
const unsigned int b)
911 std::enable_if_t<IsBlockVector<VectorType>::value,
VectorType> * =
913 typename VectorType::BlockType &
914 block(VectorType &vector,
const unsigned int b)
916 return vector.block(b);
922 std::enable_if_t<IsBlockVector<VectorType>::value,
VectorType> * =
924 const typename VectorType::BlockType &
925 block(
const VectorType &vector,
const unsigned int b)
927 return vector.block(b);
932 template <
bool delayed_reorthogonalization,
934 std::enable_if_t<!is_dealii_compatible_vector<VectorType>::value,
937 Tvmult_add(
const unsigned int n,
938 const VectorType &vv,
939 const TmpVectors<VectorType> &orthogonal_vectors,
941 std::vector<const typename VectorType::value_type *> &)
943 for (
unsigned int i = 0; i < n; ++i)
945 h(i) += vv * orthogonal_vectors[i];
946 if (delayed_reorthogonalization)
947 h(n + i) += orthogonal_vectors[i] * orthogonal_vectors[n - 1];
949 if (delayed_reorthogonalization)
956 template <
bool delayed_reorthogonalization,
typename Number>
960 const Number *current_vector,
961 const std::vector<const Number *> &orthogonal_vectors,
966 template <
bool delayed_reorthogonalization,
968 std::enable_if_t<is_dealii_compatible_vector<VectorType>::value,
972 const unsigned int n,
973 const VectorType &vv,
974 const TmpVectors<VectorType> &orthogonal_vectors,
976 std::vector<const typename VectorType::value_type *> &vector_ptrs)
978 for (
unsigned int b = 0;
b <
n_blocks(vv); ++
b)
980 vector_ptrs.resize(n);
981 for (
unsigned int i = 0; i < n; ++i)
982 vector_ptrs[i] = block(orthogonal_vectors[i], b).begin();
984 do_Tvmult_add<delayed_reorthogonalization>(n,
986 block(vv, b).
begin(),
987 block(vv, b).
begin(),
997 template <
bool delayed_reorthogonalization,
999 std::enable_if_t<!is_dealii_compatible_vector<VectorType>::value,
1002 subtract_and_norm(
const unsigned int n,
1003 const TmpVectors<VectorType> &orthogonal_vectors,
1006 std::vector<const typename VectorType::value_type *> &)
1011 const_cast<VectorType &
>(orthogonal_vectors[n - 1]);
1012 for (
unsigned int i = 0; i < n - 1; ++i)
1014 if (delayed_reorthogonalization && i + 2 < n)
1015 last_vector.add(-h(n + i), orthogonal_vectors[i]);
1016 vv.add(-h(i), orthogonal_vectors[i]);
1019 if (delayed_reorthogonalization)
1022 last_vector.sadd(1. / h(n + n - 1),
1023 -h(n + n - 2) / h(n + n - 1),
1024 orthogonal_vectors[n - 2]);
1027 const double scaling_factor_vv = h(n + n) > 0.0 ?
1028 1. / (h(n + n - 1) * h(n + n)) :
1029 1. / (h(n + n - 1) * h(n + n - 1));
1030 vv.sadd(scaling_factor_vv,
1031 -h(n - 1) * scaling_factor_vv,
1036 return std::numeric_limits<double>::signaling_NaN();
1040 vv.add_and_dot(-h(n - 1), orthogonal_vectors[n - 1], vv));
1046 template <
bool delayed_reorthogonalization,
typename Number>
1050 const std::vector<const Number *> &orthogonal_vectors,
1052 Number *current_vector);
1056 template <
bool delayed_reorthogonalization,
1058 std::enable_if_t<is_dealii_compatible_vector<VectorType>::value,
1062 const unsigned int n,
1063 const TmpVectors<VectorType> &orthogonal_vectors,
1066 std::vector<const typename VectorType::value_type *> &vector_ptrs)
1068 double norm_vv_temp = 0.0;
1070 for (
unsigned int b = 0;
b <
n_blocks(vv); ++
b)
1072 vector_ptrs.resize(n);
1073 for (
unsigned int i = 0; i < n; ++i)
1074 vector_ptrs[i] = block(orthogonal_vectors[i], b).begin();
1076 norm_vv_temp += do_subtract_and_norm<delayed_reorthogonalization>(
1078 block(vv, b).
end() - block(vv, b).
begin(),
1081 block(vv, b).
begin());
1091 std::enable_if_t<!is_dealii_compatible_vector<VectorType>::value,
1095 const unsigned int n,
1097 const TmpVectors<VectorType> &tmp_vectors,
1098 const bool zero_out,
1099 std::vector<const typename VectorType::value_type *> &)
1102 p.equ(h(0), tmp_vectors[0]);
1104 p.add(h(0), tmp_vectors[0]);
1106 for (
unsigned int i = 1; i < n; ++i)
1107 p.add(h(i), tmp_vectors[i]);
1113 template <
typename Number>
1115 do_add(
const unsigned int n_vectors,
1117 const std::vector<const Number *> &tmp_vectors,
1119 const bool zero_out,
1125 std::enable_if_t<is_dealii_compatible_vector<VectorType>::value,
1129 const unsigned int n,
1131 const TmpVectors<VectorType> &tmp_vectors,
1132 const bool zero_out,
1133 std::vector<const typename VectorType::value_type *> &vector_ptrs)
1135 for (
unsigned int b = 0;
b <
n_blocks(p); ++
b)
1137 vector_ptrs.resize(n);
1138 for (
unsigned int i = 0; i < n; ++i)
1139 vector_ptrs[i] = block(tmp_vectors[i], b).begin();
1141 block(p, b).
end() - block(p, b).
begin(),
1145 block(p, b).
begin());
1151 template <
typename Number>
1153 ArnoldiProcess<Number>::initialize(
1155 const unsigned int basis_size,
1156 const bool force_reorthogonalization)
1158 this->orthogonalization_strategy = orthogonalization_strategy;
1159 this->do_reorthogonalization = force_reorthogonalization;
1161 hessenberg_matrix.reinit(basis_size + 1, basis_size);
1162 triangular_matrix.reinit(basis_size + 1, basis_size,
true);
1165 projected_rhs.reinit(basis_size + 1,
true);
1166 givens_rotations.reserve(basis_size);
1168 if (orthogonalization_strategy ==
1171 h.
reinit(2 * basis_size + 3);
1173 h.
reinit(basis_size + 1);
1178 template <
typename Number>
1179 template <
typename VectorType>
1181 ArnoldiProcess<Number>::orthonormalize_nth_vector(
1182 const unsigned int n,
1183 TmpVectors<VectorType> &orthogonal_vectors,
1184 const unsigned int accumulated_iterations,
1185 const boost::signals2::signal<
void(
int)> &reorthogonalize_signal)
1192 double residual_estimate = std::numeric_limits<double>::signaling_NaN();
1195 givens_rotations.clear();
1196 residual_estimate = vv.l2_norm();
1197 if (residual_estimate != 0.)
1198 vv /= residual_estimate;
1199 projected_rhs(0) = residual_estimate;
1201 else if (orthogonalization_strategy ==
1211 const double previous_scaling = n > 0 ? h(n + n - 2) : 1.;
1214 h.reinit(n + n + 1);
1217 Tvmult_add<true>(n, vv, orthogonal_vectors, h, vector_ptrs);
1221 for (
unsigned int i = 0; i < n - 1; ++i)
1222 tmp += h(n + i) * h(n + i);
1223 const double alpha_j = h(n + n - 1) > tmp ?
1226 h(n + n - 1) = alpha_j;
1229 for (
unsigned int i = 0; i < n - 1; ++i)
1230 tmp += h(i) * h(n + i);
1231 h(n - 1) = (h(n - 1) - tmp) / alpha_j;
1236 for (
unsigned int i = 0; i < n - 1; ++i)
1237 hessenberg_matrix(i, n - 2) += h(n + i) * previous_scaling;
1238 hessenberg_matrix(n - 1, n - 2) = alpha_j * previous_scaling;
1240 for (
unsigned int i = 0; i < n; ++i)
1243 for (
unsigned int j = (i == 0 ? 0 : i - 1); j < n - 1; ++j)
1244 sum += hessenberg_matrix(i, j) * h(n + j);
1245 hessenberg_matrix(i, n - 1) = (h(i) -
sum) / alpha_j;
1251 for (
unsigned int i = 0; i < n - 1; ++i)
1253 sum += (2. - 1.) * h(n - 1) * h(n - 1);
1254 hessenberg_matrix(n, n - 1) =
1261 h(n + n) = hessenberg_matrix(n, n - 1);
1262 subtract_and_norm<true>(n, orthogonal_vectors, h, vv, vector_ptrs);
1266 residual_estimate = do_givens_rotation(
1267 true, n - 2, triangular_matrix, givens_rotations, projected_rhs);
1272 double norm_vv = 0.0;
1273 double norm_vv_start = 0;
1274 const bool consider_reorthogonalize =
1275 (do_reorthogonalization ==
false) && (n % 5 == 0);
1276 if (consider_reorthogonalize)
1277 norm_vv_start = vv.l2_norm();
1283 for (
unsigned int c = 0; c < 2; ++c)
1286 if (orthogonalization_strategy ==
1290 double htmp = vv * orthogonal_vectors[0];
1292 for (
unsigned int i = 1; i < n; ++i)
1294 htmp = vv.add_and_dot(-htmp,
1295 orthogonal_vectors[i - 1],
1296 orthogonal_vectors[i]);
1301 vv.add_and_dot(-htmp, orthogonal_vectors[n - 1], vv));
1303 else if (orthogonalization_strategy ==
1307 Tvmult_add<false>(n, vv, orthogonal_vectors, h, vector_ptrs);
1308 norm_vv = subtract_and_norm<false>(
1309 n, orthogonal_vectors, h, vv, vector_ptrs);
1327 if (consider_reorthogonalize)
1330 10. * norm_vv_start *
1332 typename VectorType::value_type>::epsilon()))
1337 do_reorthogonalization =
true;
1338 if (!reorthogonalize_signal.empty())
1339 reorthogonalize_signal(accumulated_iterations);
1343 if (do_reorthogonalization ==
false)
1347 for (
unsigned int i = 0; i < n; ++i)
1348 hessenberg_matrix(i, n - 1) = h(i);
1349 hessenberg_matrix(n, n - 1) = norm_vv;
1356 residual_estimate = do_givens_rotation(
1357 false, n - 1, triangular_matrix, givens_rotations, projected_rhs);
1360 return residual_estimate;
1365 template <
typename Number>
1367 ArnoldiProcess<Number>::do_givens_rotation(
1368 const bool delayed_reorthogonalization,
1371 std::vector<std::pair<double, double>> &rotations,
1379 if (delayed_reorthogonalization)
1384 matrix(0, col) = hessenberg_matrix(0, col);
1386 double H_next = hessenberg_matrix(0, col + 1);
1387 for (
int i = 0; i < col; ++i)
1389 const double c = rotations[i].first;
1390 const double s = rotations[i].second;
1391 const double Hi =
matrix(i, col);
1392 const double Hi1 = hessenberg_matrix(i + 1, col);
1393 H_next = -s * H_next + c * hessenberg_matrix(i + 1, col + 1);
1394 matrix(i, col) = c * Hi + s * Hi1;
1395 matrix(i + 1, col) = -s * Hi + c * Hi1;
1400 const double H_col1 = hessenberg_matrix(col + 1, col);
1401 const double H_col =
matrix(col, col);
1402 const double r = 1. /
std::sqrt(H_col * H_col + H_col1 * H_col1);
1403 rotations.emplace_back(H_col * r, H_col1 * r);
1405 rotations[col].first * H_col + rotations[col].second * H_col1;
1407 rhs(col + 1) = -rotations[col].second * rhs(col);
1408 rhs(col) *= rotations[col].first;
1411 -rotations[col].second * H_next +
1412 rotations[col].first * hessenberg_matrix(col + 1, col + 1);
1415 const double H_last = hessenberg_matrix(col + 2, col + 1);
1416 const double r = 1. /
std::sqrt(H_next * H_next + H_last * H_last);
1417 return std::abs(H_last * r * rhs(col + 1));
1423 matrix(0, col) = hessenberg_matrix(0, col);
1424 for (
int i = 0; i < col; ++i)
1426 const double c = rotations[i].first;
1427 const double s = rotations[i].second;
1428 const double Hi =
matrix(i, col);
1429 const double Hi1 = hessenberg_matrix(i + 1, col);
1430 matrix(i, col) = c * Hi + s * Hi1;
1431 matrix(i + 1, col) = -s * Hi + c * Hi1;
1434 const double Hi =
matrix(col, col);
1435 const double Hi1 = hessenberg_matrix(col + 1, col);
1436 const double r = 1. /
std::sqrt(Hi * Hi + Hi1 * Hi1);
1437 rotations.emplace_back(Hi * r, Hi1 * r);
1439 rotations[col].first * Hi + rotations[col].second * Hi1;
1441 rhs(col + 1) = -rotations[col].second * rhs(col);
1442 rhs(col) *= rotations[col].first;
1450 template <
typename Number>
1452 ArnoldiProcess<Number>::solve_projected_system(
1453 const bool orthogonalization_finished)
1459 unsigned int n = givens_rotations.
size();
1469 if (orthogonalization_strategy ==
1474 if (!orthogonalization_finished)
1476 tmp_triangular_matrix = triangular_matrix;
1477 tmp_rhs = projected_rhs;
1478 std::vector<std::pair<double, double>> tmp_givens_rotations(
1480 do_givens_rotation(
false,
1481 givens_rotations.size(),
1482 tmp_triangular_matrix,
1483 tmp_givens_rotations,
1485 matrix = &tmp_triangular_matrix;
1489 do_givens_rotation(
false,
1490 givens_rotations.size(),
1497 projected_solution.reinit(n);
1498 for (
int i = n - 1; i >= 0; --i)
1500 double s = (*rhs)(i);
1501 for (
unsigned int j = i + 1; j < n; ++j)
1502 s -= projected_solution(j) * (*matrix)(i, j);
1503 projected_solution(i) = s / (*matrix)(i, i);
1507 return projected_solution;
1512 template <
typename Number>
1514 ArnoldiProcess<Number>::get_hessenberg_matrix()
const
1516 return hessenberg_matrix;
1523 complex_less_pred(
const std::complex<double> &x,
1524 const std::complex<double> &y)
1526 return x.real() < y.real() ||
1527 (x.real() == y.real() && x.imag() < y.imag());
1534template <
typename VectorType>
1538 const unsigned int n,
1539 const boost::signals2::signal<
void(
const std::vector<std::complex<double>> &)>
1540 &eigenvalues_signal,
1543 const boost::signals2::signal<
void(
double)> &cond_signal)
1546 if ((!eigenvalues_signal.empty() || !hessenberg_signal.empty() ||
1547 !cond_signal.empty()) &&
1551 for (
unsigned int i = 0; i < n; ++i)
1552 for (
unsigned int j = 0; j < n; ++j)
1553 mat(i, j) = H_orig(i, j);
1554 hessenberg_signal(H_orig);
1556 if (!eigenvalues_signal.empty())
1562 mat_eig.compute_eigenvalues();
1564 for (
unsigned int i = 0; i < mat_eig.n(); ++i)
1569 internal::SolverGMRESImplementation::complex_less_pred);
1574 if (!cond_signal.empty() && (mat.n() > 1))
1577 double condition_number =
1578 mat.singular_value(0) / mat.singular_value(mat.n() - 1);
1579 cond_signal(condition_number);
1586template <
typename VectorType>
1588template <
typename MatrixType,
typename PreconditionerType>
1594 const VectorType &b,
1595 const PreconditionerType &preconditioner)
1597 std::unique_ptr<LogStream::Prefix> prefix;
1598 if (!additional_data.batched_mode)
1599 prefix = std::make_unique<LogStream::Prefix>(
"GMRES");
1603 const unsigned int basis_size =
1606 std::max(additional_data.max_n_tmp_vectors, 3u) - 2);
1610 basis_size + 2, this->memory);
1614 unsigned int accumulated_iterations = 0;
1616 const bool do_eigenvalues =
1617 !additional_data.batched_mode &&
1618 (!condition_number_signal.empty() ||
1619 !all_condition_numbers_signal.empty() || !eigenvalues_signal.empty() ||
1620 !all_eigenvalues_signal.empty() || !hessenberg_signal.empty() ||
1621 !all_hessenberg_signal.empty());
1624 double res = std::numeric_limits<double>::lowest();
1628 const bool left_precondition = !additional_data.right_preconditioning;
1633 const bool use_default_residual = additional_data.use_default_residual;
1636 VectorType &p = basis_vectors(basis_size + 1, x);
1642 if (!use_default_residual)
1652 additional_data.force_re_orthogonalization);
1669 if (left_precondition)
1671 if (accumulated_iterations == 0 && x.all_zero())
1672 preconditioner.vmult(v, b);
1677 preconditioner.vmult(v, p);
1682 if (accumulated_iterations == 0 && x.all_zero())
1691 const double norm_v = arnoldi_process.orthonormalize_nth_vector(
1692 0, basis_vectors, accumulated_iterations, re_orthogonalize_signal);
1697 if (use_default_residual)
1700 if (additional_data.batched_mode)
1701 iteration_state = solver_control.
check(accumulated_iterations, res);
1704 this->iteration_status(accumulated_iterations, res, x);
1711 deallog <<
"default_res=" << norm_v << std::endl;
1713 if (left_precondition)
1716 r->sadd(-1., 1., b);
1719 preconditioner.vmult(*r, v);
1722 if (additional_data.batched_mode)
1723 iteration_state = solver_control.
check(accumulated_iterations, res);
1726 this->iteration_status(accumulated_iterations, res, x);
1734 unsigned int inner_iteration = 0;
1735 for (; (inner_iteration < basis_size &&
1739 ++accumulated_iterations;
1741 VectorType &vv = basis_vectors(inner_iteration + 1, x);
1743 if (left_precondition)
1745 A.vmult(p, basis_vectors[inner_iteration]);
1746 preconditioner.vmult(vv, p);
1750 preconditioner.vmult(p, basis_vectors[inner_iteration]);
1755 arnoldi_process.orthonormalize_nth_vector(inner_iteration + 1,
1757 accumulated_iterations,
1758 re_orthogonalize_signal);
1760 if (use_default_residual)
1762 if (additional_data.batched_mode)
1764 solver_control.
check(accumulated_iterations, res);
1767 this->iteration_status(accumulated_iterations, res, x);
1771 if (!additional_data.batched_mode)
1772 deallog <<
"default_res=" << res << std::endl;
1776 arnoldi_process.solve_projected_system(
false);
1778 if (left_precondition)
1779 for (
unsigned int i = 0; i < inner_iteration + 1; ++i)
1780 x_->add(projected_solution(i), basis_vectors[i]);
1784 for (
unsigned int i = 0; i < inner_iteration + 1; ++i)
1785 p.add(projected_solution(i), basis_vectors[i]);
1786 preconditioner.vmult(*r, p);
1790 r->sadd(-1., 1., b);
1793 if (left_precondition)
1797 this->iteration_status(accumulated_iterations, res, x);
1801 preconditioner.vmult(*x_, *r);
1802 res = x_->l2_norm();
1804 if (additional_data.batched_mode)
1806 solver_control.
check(accumulated_iterations, res);
1809 this->iteration_status(accumulated_iterations, res, x);
1817 arnoldi_process.solve_projected_system(
true);
1820 compute_eigs_and_cond(arnoldi_process.get_hessenberg_matrix(),
1822 all_eigenvalues_signal,
1823 all_hessenberg_signal,
1824 condition_number_signal);
1826 if (left_precondition)
1827 ::internal::SolverGMRESImplementation::add(
1833 arnoldi_process.vector_ptrs);
1836 ::internal::SolverGMRESImplementation::add(
1842 arnoldi_process.vector_ptrs);
1843 preconditioner.vmult(v, p);
1851 compute_eigs_and_cond(arnoldi_process.get_hessenberg_matrix(),
1855 condition_number_signal);
1857 if (!additional_data.batched_mode && !krylov_space_signal.empty())
1858 krylov_space_signal(basis_vectors);
1873template <
typename VectorType>
1875boost::signals2::connection
1877 const std::function<
void(
double)> &slot,
1878 const bool every_iteration)
1880 if (every_iteration)
1882 return all_condition_numbers_signal.connect(slot);
1886 return condition_number_signal.connect(slot);
1892template <
typename VectorType>
1895 const std::function<
void(
const std::vector<std::complex<double>> &)> &slot,
1896 const bool every_iteration)
1898 if (every_iteration)
1900 return all_eigenvalues_signal.connect(slot);
1904 return eigenvalues_signal.connect(slot);
1910template <
typename VectorType>
1914 const bool every_iteration)
1916 if (every_iteration)
1918 return all_hessenberg_signal.connect(slot);
1922 return hessenberg_signal.connect(slot);
1928template <
typename VectorType>
1931 const std::function<
void(
1934 return krylov_space_signal.connect(slot);
1939template <
typename VectorType>
1941boost::signals2::connection
1943 const std::function<
void(
int)> &slot)
1945 return re_orthogonalize_signal.connect(slot);
1950template <
typename VectorType>
1964template <
typename VectorType>
1968 const AdditionalData &
data)
1970 , additional_data(
data)
1975template <
typename VectorType>
1978 const AdditionalData &
data)
1980 , additional_data(
data)
1985template <
typename VectorType>
1987template <
typename MatrixType,
typename PreconditionerType>
1993 const VectorType &b,
1994 const PreconditionerType &preconditioner)
2004 basis_size + 1, this->memory);
2006 basis_size, this->memory);
2010 unsigned int accumulated_iterations = 0;
2018 double res = std::numeric_limits<double>::lowest();
2028 if (accumulated_iterations == 0 && x.all_zero())
2032 A.vmult(v(0, x), x);
2033 v[0].sadd(-1., 1., b);
2036 res = arnoldi_process.orthonormalize_nth_vector(0, v);
2037 iteration_state = this->iteration_status(accumulated_iterations, res, x);
2041 unsigned int inner_iteration = 0;
2042 for (; (inner_iteration < basis_size &&
2046 preconditioner.vmult(z(inner_iteration, x), v[inner_iteration]);
2047 A.vmult(v(inner_iteration + 1, x), z[inner_iteration]);
2050 arnoldi_process.orthonormalize_nth_vector(inner_iteration + 1, v);
2057 this->iteration_status(++accumulated_iterations, res, x);
2063 arnoldi_process.solve_projected_system(
true);
2064 ::internal::SolverGMRESImplementation::add(
2070 arnoldi_process.vector_ptrs);
virtual State check(const unsigned int step, const double check_value)
@ iterate
Continue iteration.
@ success
Stop iteration, goal reached.
SolverFGMRES(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
SolverFGMRES(SolverControl &cn, const AdditionalData &data=AdditionalData())
SolverGMRES(const SolverGMRES< VectorType > &)=delete
boost::signals2::connection connect_condition_number_slot(const std::function< void(double)> &slot, const bool every_iteration=false)
boost::signals2::connection connect_krylov_space_slot(const std::function< void(const internal::SolverGMRESImplementation::TmpVectors< VectorType > &)> &slot)
boost::signals2::connection connect_re_orthogonalization_slot(const std::function< void(int)> &slot)
static void compute_eigs_and_cond(const FullMatrix< double > &H_orig, const unsigned int n, const boost::signals2::signal< void(const std::vector< std::complex< double > > &)> &eigenvalues_signal, const boost::signals2::signal< void(const FullMatrix< double > &)> &hessenberg_signal, const boost::signals2::signal< void(double)> &cond_signal)
SolverGMRES(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
boost::signals2::connection connect_hessenberg_slot(const std::function< void(const FullMatrix< double > &)> &slot, const bool every_iteration=true)
SolverGMRES(SolverControl &cn, const AdditionalData &data=AdditionalData())
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
virtual double criterion()
boost::signals2::connection connect_eigenvalues_slot(const std::function< void(const std::vector< std::complex< double > > &)> &slot, const bool every_iteration=false)
virtual size_type size() const override
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
const FullMatrix< double > & get_hessenberg_matrix() const
Vector< double > projected_rhs
bool do_reorthogonalization
LinearAlgebra::OrthogonalizationStrategy orthogonalization_strategy
double orthonormalize_nth_vector(const unsigned int n, TmpVectors< VectorType > &orthogonal_vectors, const unsigned int accumulated_iterations=0, const boost::signals2::signal< void(int)> &reorthogonalize_signal=boost::signals2::signal< void(int)>())
const Vector< double > & solve_projected_system(const bool orthogonalization_finished)
void initialize(const LinearAlgebra::OrthogonalizationStrategy orthogonalization_strategy, const unsigned int max_basis_size, const bool force_reorthogonalization)
Vector< double > projected_solution
FullMatrix< double > hessenberg_matrix
std::vector< const Number * > vector_ptrs
FullMatrix< double > triangular_matrix
std::vector< std::pair< double, double > > givens_rotations
double do_givens_rotation(const bool delayed_reorthogonalization, const int col, FullMatrix< double > &matrix, std::vector< std::pair< double, double > > &rotations, Vector< double > &rhs)
VectorMemory< VectorType > & mem
std::vector< typename VectorMemory< VectorType >::Pointer > data
TmpVectors(const unsigned int max_size, VectorMemory< VectorType > &vmem)
unsigned int size() const
VectorType & operator[](const unsigned int i) const
VectorType & operator()(const unsigned int i, const VectorType &temp)
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_CXX20_REQUIRES(condition)
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertIsFinite(number)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcNotInitialized()
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
#define DEAL_II_ASSERT_UNREACHABLE()
std::vector< index_type > data
types::global_dof_index locally_owned_size
@ matrix
Contents is actually a matrix.
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
OrthogonalizationStrategy
@ delayed_classical_gram_schmidt
std::enable_if_t< IsBlockVector< VectorType >::value, unsigned int > n_blocks(const VectorType &vector)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
T sum(const T &t, const MPI_Comm mpi_communicator)
void do_Tvmult_add(const unsigned int n_vectors, const std::size_t locally_owned_size, const Number *current_vector, const std::vector< const Number * > &orthogonal_vectors, Vector< double > &h)
double do_subtract_and_norm(const unsigned int n_vectors, const std::size_t locally_owned_size, const std::vector< const Number * > &orthogonal_vectors, const Vector< double > &h, Number *current_vector)
void do_add(const unsigned int n_vectors, const std::size_t locally_owned_size, const std::vector< const Number * > &tmp_vectors, const Vector< double > &h, const bool zero_out, Number *output)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
AdditionalData(const unsigned int max_basis_size=30, const LinearAlgebra::OrthogonalizationStrategy orthogonalization_strategy=LinearAlgebra::OrthogonalizationStrategy::delayed_classical_gram_schmidt)
unsigned int max_basis_size
LinearAlgebra::OrthogonalizationStrategy orthogonalization_strategy
AdditionalData(const unsigned int max_basis_size=30, const bool right_preconditioning=false, const bool use_default_residual=true, const bool force_re_orthogonalization=false, const bool batched_mode=false, const LinearAlgebra::OrthogonalizationStrategy orthogonalization_strategy=LinearAlgebra::OrthogonalizationStrategy::delayed_classical_gram_schmidt)
bool right_preconditioning
bool force_re_orthogonalization
LinearAlgebra::OrthogonalizationStrategy orthogonalization_strategy
bool use_default_residual
unsigned int max_basis_size
unsigned int max_n_tmp_vectors
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)