13#ifndef dealii_precondition_h
14#define dealii_precondition_h
31#include <Kokkos_Core.hpp>
39template <
typename number>
41template <
typename number>
47 template <
typename,
typename>
49 template <
typename,
typename>
126 template <
typename PreconditionerType>
256 template <
typename MatrixType>
264 template <
typename VectorType>
266 vmult(VectorType &,
const VectorType &)
const;
272 template <
typename VectorType>
274 Tvmult(VectorType &,
const VectorType &)
const;
279 template <
typename VectorType>
287 template <
typename VectorType>
385 template <
typename MatrixType>
392 template <
typename VectorType>
394 vmult(VectorType &,
const VectorType &)
const;
400 template <
typename VectorType>
402 Tvmult(VectorType &,
const VectorType &)
const;
406 template <
typename VectorType>
414 template <
typename VectorType>
504template <
typename MatrixType = SparseMatrix<
double>,
505 typename VectorType = Vector<
double>>
513 const VectorType &) const;
527 vmult(VectorType &dst,
const VectorType &src)
const;
572template <
typename MatrixType = SparseMatrix<
double>,
573 typename PreconditionerType = IdentityMatrix>
601 EigenvalueAlgorithm::lanczos,
648 template <
typename VectorType>
650 vmult(VectorType &,
const VectorType &)
const;
656 template <
typename VectorType>
658 Tvmult(VectorType &,
const VectorType &)
const;
663 template <
typename VectorType>
665 step(VectorType &x,
const VectorType &rhs)
const;
670 template <
typename VectorType>
672 Tstep(VectorType &x,
const VectorType &rhs)
const;
679 template <
typename VectorType>
724 template <
typename MatrixType,
typename VectorType>
725 using vmult_functions_t =
decltype(std::declval<const MatrixType>().vmult(
726 std::declval<VectorType &>(),
727 std::declval<const VectorType &>(),
729 const std::function<
void(
const unsigned int,
const unsigned int)> &>(),
731 const std::function<
void(
const unsigned int,
const unsigned int)> &>()));
733 template <
typename MatrixType,
735 typename PreconditionerType>
736 constexpr bool has_vmult_with_std_functions =
737 is_supported_operation<vmult_functions_t, MatrixType, VectorType> &&
738 std::is_same_v<PreconditionerType, ::DiagonalMatrix<VectorType>> &&
739 (std::is_same_v<VectorType,
747 template <
typename MatrixType,
typename VectorType>
748 constexpr bool has_vmult_with_std_functions_for_precondition =
749 is_supported_operation<vmult_functions_t, MatrixType, VectorType>;
753 template <
typename T,
typename VectorType>
754 using Tvmult_t =
decltype(std::declval<const T>().Tvmult(
755 std::declval<VectorType &>(),
756 std::declval<const VectorType &>()));
758 template <
typename T,
typename VectorType>
759 constexpr bool has_Tvmult = is_supported_operation<Tvmult_t, T, VectorType>;
761 template <
typename T,
typename VectorType>
762 using step_t =
decltype(std::declval<const T>().step(
763 std::declval<VectorType &>(),
764 std::declval<const VectorType &>()));
766 template <
typename T,
typename VectorType>
767 constexpr bool has_step = is_supported_operation<step_t, T, VectorType>;
769 template <
typename T,
typename VectorType>
771 decltype(std::declval<const T>().step(std::declval<VectorType &>(),
772 std::declval<const VectorType &>(),
773 std::declval<const double>()));
775 template <
typename T,
typename VectorType>
776 constexpr bool has_step_omega =
777 is_supported_operation<step_omega_t, T, VectorType>;
779 template <
typename T,
typename VectorType>
780 using Tstep_t =
decltype(std::declval<const T>().Tstep(
781 std::declval<VectorType &>(),
782 std::declval<const VectorType &>()));
784 template <
typename T,
typename VectorType>
785 constexpr bool has_Tstep = is_supported_operation<Tstep_t, T, VectorType>;
787 template <
typename T,
typename VectorType>
788 using Tstep_omega_t =
789 decltype(std::declval<const T>().Tstep(std::declval<VectorType &>(),
790 std::declval<const VectorType &>(),
791 std::declval<const double>()));
793 template <
typename T,
typename VectorType>
794 constexpr bool has_Tstep_omega =
795 is_supported_operation<Tstep_omega_t, T, VectorType>;
797 template <
typename T,
typename VectorType>
798 using jacobi_step_t =
decltype(std::declval<const T>().Jacobi_step(
799 std::declval<VectorType &>(),
800 std::declval<const VectorType &>(),
801 std::declval<const double>()));
803 template <
typename T,
typename VectorType>
804 constexpr bool has_jacobi_step =
805 is_supported_operation<jacobi_step_t, T, VectorType>;
807 template <
typename T,
typename VectorType>
808 using SOR_step_t =
decltype(std::declval<const T>().SOR_step(
809 std::declval<VectorType &>(),
810 std::declval<const VectorType &>(),
811 std::declval<const double>()));
813 template <
typename T,
typename VectorType>
814 constexpr bool has_SOR_step =
815 is_supported_operation<SOR_step_t, T, VectorType>;
817 template <
typename T,
typename VectorType>
818 using SSOR_step_t =
decltype(std::declval<const T>().SSOR_step(
819 std::declval<VectorType &>(),
820 std::declval<const VectorType &>(),
821 std::declval<const double>()));
823 template <
typename T,
typename VectorType>
824 constexpr bool has_SSOR_step =
825 is_supported_operation<SSOR_step_t, T, VectorType>;
827 template <
typename MatrixType>
828 class PreconditionJacobiImpl
831 PreconditionJacobiImpl(
const MatrixType &A,
const double relaxation)
833 , relaxation(relaxation)
836 template <
typename VectorType>
838 vmult(VectorType &dst,
const VectorType &src)
const
840 this->A->precondition_Jacobi(dst, src, this->relaxation);
843 template <
typename VectorType>
845 Tvmult(VectorType &dst,
const VectorType &src)
const
848 this->vmult(dst, src);
851 template <
typename VectorType,
852 std::enable_if_t<has_jacobi_step<MatrixType, VectorType>,
853 MatrixType> * =
nullptr>
855 step(VectorType &dst,
const VectorType &src)
const
857 this->A->Jacobi_step(dst, src, this->relaxation);
860 template <
typename VectorType,
861 std::enable_if_t<!has_jacobi_step<MatrixType, VectorType>,
862 MatrixType> * =
nullptr>
864 step(VectorType &,
const VectorType &)
const
868 "Matrix A does not provide a Jacobi_step() function!"));
871 template <
typename VectorType>
873 Tstep(VectorType &dst,
const VectorType &src)
const
876 this->step(dst, src);
881 const double relaxation;
884 template <
typename MatrixType>
885 class PreconditionSORImpl
888 PreconditionSORImpl(
const MatrixType &A,
const double relaxation)
890 , relaxation(relaxation)
893 template <
typename VectorType>
895 vmult(VectorType &dst,
const VectorType &src)
const
897 this->A->precondition_SOR(dst, src, this->relaxation);
900 template <
typename VectorType>
902 Tvmult(VectorType &dst,
const VectorType &src)
const
904 this->A->precondition_TSOR(dst, src, this->relaxation);
907 template <
typename VectorType,
908 std::enable_if_t<has_SOR_step<MatrixType, VectorType>,
909 MatrixType> * =
nullptr>
911 step(VectorType &dst,
const VectorType &src)
const
913 this->A->SOR_step(dst, src, this->relaxation);
916 template <
typename VectorType,
917 std::enable_if_t<!has_SOR_step<MatrixType, VectorType>,
918 MatrixType> * =
nullptr>
920 step(VectorType &,
const VectorType &)
const
924 "Matrix A does not provide a SOR_step() function!"));
927 template <
typename VectorType,
928 std::enable_if_t<has_SOR_step<MatrixType, VectorType>,
929 MatrixType> * =
nullptr>
931 Tstep(VectorType &dst,
const VectorType &src)
const
933 this->A->TSOR_step(dst, src, this->relaxation);
936 template <
typename VectorType,
937 std::enable_if_t<!has_SOR_step<MatrixType, VectorType>,
938 MatrixType> * =
nullptr>
940 Tstep(VectorType &,
const VectorType &)
const
944 "Matrix A does not provide a TSOR_step() function!"));
949 const double relaxation;
952 template <
typename MatrixType>
953 class PreconditionSSORImpl
956 using size_type =
typename MatrixType::size_type;
958 PreconditionSSORImpl(
const MatrixType &A,
const double relaxation)
960 , relaxation(relaxation)
971 const size_type n = this->A->n();
972 pos_right_of_diagonal.resize(n,
static_cast<std::size_t
>(-1));
973 for (size_type row = 0; row < n; ++row)
982 for (; it < mat->
end(row); ++it)
983 if (it->column() > row)
985 pos_right_of_diagonal[row] = it - mat->
begin();
990 template <
typename VectorType>
992 vmult(VectorType &dst,
const VectorType &src)
const
994 this->A->precondition_SSOR(dst,
997 pos_right_of_diagonal);
1000 template <
typename VectorType>
1002 Tvmult(VectorType &dst,
const VectorType &src)
const
1004 this->A->precondition_SSOR(dst,
1007 pos_right_of_diagonal);
1010 template <
typename VectorType,
1011 std::enable_if_t<has_SSOR_step<MatrixType, VectorType>,
1012 MatrixType> * =
nullptr>
1014 step(VectorType &dst,
const VectorType &src)
const
1016 this->A->SSOR_step(dst, src, this->relaxation);
1019 template <
typename VectorType,
1020 std::enable_if_t<!has_SSOR_step<MatrixType, VectorType>,
1021 MatrixType> * =
nullptr>
1023 step(VectorType &,
const VectorType &)
const
1027 "Matrix A does not provide a SSOR_step() function!"));
1030 template <
typename VectorType>
1032 Tstep(VectorType &dst,
const VectorType &src)
const
1035 this->step(dst, src);
1040 const double relaxation;
1046 std::vector<std::size_t> pos_right_of_diagonal;
1049 template <
typename MatrixType>
1050 class PreconditionPSORImpl
1053 using size_type =
typename MatrixType::size_type;
1055 PreconditionPSORImpl(
const MatrixType &A,
1056 const double relaxation,
1057 const std::vector<size_type> &permutation,
1058 const std::vector<size_type> &inverse_permutation)
1060 , relaxation(relaxation)
1061 , permutation(permutation)
1062 , inverse_permutation(inverse_permutation)
1065 template <
typename VectorType>
1067 vmult(VectorType &dst,
const VectorType &src)
const
1070 this->A->PSOR(dst, permutation, inverse_permutation, this->relaxation);
1073 template <
typename VectorType>
1075 Tvmult(VectorType &dst,
const VectorType &src)
const
1078 this->A->TPSOR(dst, permutation, inverse_permutation, this->relaxation);
1083 const double relaxation;
1085 const std::vector<size_type> &permutation;
1086 const std::vector<size_type> &inverse_permutation;
1089 template <
typename MatrixType,
1090 typename PreconditionerType,
1091 typename VectorType,
1092 std::enable_if_t<has_step_omega<PreconditionerType, VectorType>,
1093 PreconditionerType> * =
nullptr>
1095 step(
const MatrixType &,
1096 const PreconditionerType &preconditioner,
1098 const VectorType &src,
1099 const double relaxation,
1103 preconditioner.step(dst, src, relaxation);
1107 typename MatrixType,
1108 typename PreconditionerType,
1109 typename VectorType,
1110 std::enable_if_t<!has_step_omega<PreconditionerType, VectorType> &&
1111 has_step<PreconditionerType, VectorType>,
1112 PreconditionerType> * =
nullptr>
1114 step(
const MatrixType &,
1115 const PreconditionerType &preconditioner,
1117 const VectorType &src,
1118 const double relaxation,
1126 preconditioner.step(dst, src);
1130 typename MatrixType,
1131 typename PreconditionerType,
1132 typename VectorType,
1133 std::enable_if_t<!has_step_omega<PreconditionerType, VectorType> &&
1134 !has_step<PreconditionerType, VectorType>,
1135 PreconditionerType> * =
nullptr>
1137 step(
const MatrixType &A,
1138 const PreconditionerType &preconditioner,
1140 const VectorType &src,
1141 const double relaxation,
1142 VectorType &residual,
1145 residual.reinit(dst,
true);
1146 tmp.reinit(dst,
true);
1148 A.vmult(residual, dst);
1149 residual.sadd(-1.0, 1.0, src);
1151 preconditioner.vmult(tmp, residual);
1152 dst.add(relaxation, tmp);
1155 template <
typename MatrixType,
1156 typename PreconditionerType,
1157 typename VectorType,
1158 std::enable_if_t<has_Tstep_omega<PreconditionerType, VectorType>,
1159 PreconditionerType> * =
nullptr>
1161 Tstep(
const MatrixType &,
1162 const PreconditionerType &preconditioner,
1164 const VectorType &src,
1165 const double relaxation,
1169 preconditioner.Tstep(dst, src, relaxation);
1173 typename MatrixType,
1174 typename PreconditionerType,
1175 typename VectorType,
1176 std::enable_if_t<!has_Tstep_omega<PreconditionerType, VectorType> &&
1177 has_Tstep<PreconditionerType, VectorType>,
1178 PreconditionerType> * =
nullptr>
1180 Tstep(
const MatrixType &,
1181 const PreconditionerType &preconditioner,
1183 const VectorType &src,
1184 const double relaxation,
1192 preconditioner.Tstep(dst, src);
1195 template <
typename MatrixType,
1196 typename VectorType,
1197 std::enable_if_t<has_Tvmult<MatrixType, VectorType>, MatrixType>
1200 Tvmult(
const MatrixType &A, VectorType &dst,
const VectorType &src)
1205 template <
typename MatrixType,
1206 typename VectorType,
1207 std::enable_if_t<!has_Tvmult<MatrixType, VectorType>, MatrixType>
1210 Tvmult(
const MatrixType &, VectorType &,
const VectorType &)
1213 ExcMessage(
"Matrix A does not provide a Tvmult() function!"));
1217 typename MatrixType,
1218 typename PreconditionerType,
1219 typename VectorType,
1220 std::enable_if_t<!has_Tstep_omega<PreconditionerType, VectorType> &&
1221 !has_Tstep<PreconditionerType, VectorType>,
1222 PreconditionerType> * =
nullptr>
1224 Tstep(
const MatrixType &A,
1225 const PreconditionerType &preconditioner,
1227 const VectorType &src,
1228 const double relaxation,
1229 VectorType &residual,
1232 residual.reinit(dst,
true);
1233 tmp.reinit(dst,
true);
1235 Tvmult(A, residual, dst);
1236 residual.sadd(-1.0, 1.0, src);
1238 Tvmult(preconditioner, tmp, residual);
1239 dst.add(relaxation, tmp);
1243 template <
typename MatrixType,
1244 typename PreconditionerType,
1245 typename VectorType,
1246 std::enable_if_t<!has_vmult_with_std_functions_for_precondition<
1251 step_operations(
const MatrixType &A,
1252 const PreconditionerType &preconditioner,
1254 const VectorType &src,
1255 const double relaxation,
1258 const unsigned int i,
1259 const bool transposed)
1264 Tvmult(preconditioner, dst, src);
1266 preconditioner.vmult(dst, src);
1268 if (relaxation != 1.0)
1274 Tstep(A, preconditioner, dst, src, relaxation, tmp1, tmp2);
1276 step(A, preconditioner, dst, src, relaxation, tmp1, tmp2);
1283 typename MatrixType,
1284 typename PreconditionerType,
1285 typename VectorType,
1287 has_vmult_with_std_functions_for_precondition<PreconditionerType,
1289 !has_vmult_with_std_functions_for_precondition<MatrixType,
1293 step_operations(
const MatrixType &A,
1294 const PreconditionerType &preconditioner,
1296 const VectorType &src,
1297 const double relaxation,
1300 const unsigned int i,
1301 const bool transposed)
1304 using Number =
typename VectorType::value_type;
1305 Number *dst_ptr = dst.begin();
1306 const Number *src_ptr = src.begin();
1310 preconditioner.vmult(
1313 [&](
const unsigned int start_range,
const unsigned int end_range) {
1315 if (end_range > start_range)
1316 std::memset(dst_ptr + start_range,
1318 sizeof(Number) * (end_range - start_range));
1320 [&](
const unsigned int start_range,
const unsigned int end_range) {
1321 if (relaxation == 1.0)
1325 for (std::size_t i = start_range; i < end_range; ++i)
1326 dst_ptr[i] *= relaxation;
1331 tmp.reinit(src,
true);
1337 preconditioner.vmult(
1340 [&](
const unsigned int start_range,
const unsigned int end_range) {
1341 const auto tmp_ptr = tmp.begin();
1343 if (relaxation == 1.0)
1346 for (std::size_t i = start_range; i < end_range; ++i)
1347 tmp_ptr[i] = src_ptr[i] - tmp_ptr[i];
1355 for (std::size_t i = start_range; i < end_range; ++i)
1356 tmp_ptr[i] = relaxation * (src_ptr[i] - tmp_ptr[i]);
1359 [&](
const unsigned int,
const unsigned int) {
1369 typename MatrixType,
1370 typename PreconditionerType,
1371 typename VectorType,
1373 has_vmult_with_std_functions_for_precondition<PreconditionerType,
1375 has_vmult_with_std_functions_for_precondition<MatrixType, VectorType>,
1378 step_operations(
const MatrixType &A,
1379 const PreconditionerType &preconditioner,
1381 const VectorType &src,
1382 const double relaxation,
1385 const unsigned int i,
1386 const bool transposed)
1389 using Number =
typename VectorType::value_type;
1391 Number *dst_ptr = dst.begin();
1392 const Number *src_ptr = src.begin();
1396 preconditioner.vmult(
1399 [&](
const unsigned int start_range,
const unsigned int end_range) {
1401 if (end_range > start_range)
1402 std::memset(dst_ptr + start_range,
1404 sizeof(Number) * (end_range - start_range));
1406 [&](
const unsigned int start_range,
const unsigned int end_range) {
1407 if (relaxation == 1.0)
1411 for (std::size_t i = start_range; i < end_range; ++i)
1412 dst_ptr[i] *= relaxation;
1417 tmp.reinit(src,
true);
1418 const auto tmp_ptr = tmp.begin();
1425 [&](
const unsigned int start_range,
const unsigned int end_range) {
1428 if (end_range > start_range)
1429 std::memset(tmp_ptr + start_range,
1431 sizeof(Number) * (end_range - start_range));
1433 [&](
const unsigned int start_range,
const unsigned int end_range) {
1434 if (relaxation == 1.0)
1437 for (std::size_t i = start_range; i < end_range; ++i)
1438 tmp_ptr[i] = src_ptr[i] - tmp_ptr[i];
1446 for (std::size_t i = start_range; i < end_range; ++i)
1447 tmp_ptr[i] = relaxation * (src_ptr[i] - tmp_ptr[i]);
1451 preconditioner.vmult(dst, tmp, [](
const auto,
const auto) {
1460 typename MatrixType,
1461 typename VectorType,
1468 !has_vmult_with_std_functions<MatrixType,
1471 VectorType> * =
nullptr>
1473 step_operations(
const MatrixType &A,
1474 const ::DiagonalMatrix<VectorType> &preconditioner,
1476 const VectorType &src,
1477 const double relaxation,
1480 const unsigned int i,
1481 const bool transposed)
1483 using Number =
typename VectorType::value_type;
1487 Number *dst_ptr = dst.begin();
1488 const Number *src_ptr = src.begin();
1489 const Number *diag_ptr = preconditioner.get_vector().begin();
1491 if (relaxation == 1.0)
1494 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1495 dst_ptr[i] = src_ptr[i] * diag_ptr[i];
1500 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1501 dst_ptr[i] = relaxation * src_ptr[i] * diag_ptr[i];
1506 tmp.reinit(src,
true);
1509 Tvmult(A, tmp, dst);
1513 Number *dst_ptr = dst.begin();
1514 const Number *src_ptr = src.begin();
1515 const Number *tmp_ptr = tmp.begin();
1516 const Number *diag_ptr = preconditioner.get_vector().begin();
1518 if (relaxation == 1.0)
1521 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1522 dst_ptr[i] += (src_ptr[i] - tmp_ptr[i]) * diag_ptr[i];
1527 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1529 relaxation * (src_ptr[i] - tmp_ptr[i]) * diag_ptr[i];
1536 template <
typename MatrixType,
1537 typename VectorType,
1538 std::enable_if_t<!IsBlockVector<VectorType>::value &&
1539 has_vmult_with_std_functions<
1543 VectorType> * =
nullptr>
1545 step_operations(
const MatrixType &A,
1546 const ::DiagonalMatrix<VectorType> &preconditioner,
1548 const VectorType &src,
1549 const double relaxation,
1552 const unsigned int i,
1553 const bool transposed)
1556 using Number =
typename VectorType::value_type;
1560 Number *dst_ptr = dst.begin();
1561 const Number *src_ptr = src.begin();
1562 const Number *diag_ptr = preconditioner.get_vector().begin();
1564 if (relaxation == 1.0)
1567 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1568 dst_ptr[i] = src_ptr[i] * diag_ptr[i];
1573 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1574 dst_ptr[i] = relaxation * src_ptr[i] * diag_ptr[i];
1579 tmp.reinit(src,
true);
1586 [&](
const unsigned int start_range,
const unsigned int end_range) {
1588 if (end_range > start_range)
1589 std::memset(tmp.begin() + start_range,
1591 sizeof(Number) * (end_range - start_range));
1593 [&](
const unsigned int begin,
const unsigned int end) {
1594 const Number *dst_ptr = dst.begin();
1595 const Number *src_ptr = src.begin();
1596 Number *tmp_ptr = tmp.begin();
1597 const Number *diag_ptr = preconditioner.get_vector().begin();
1601 if (relaxation == 1.0)
1604 for (std::size_t i =
begin; i <
end; ++i)
1606 dst_ptr[i] + (src_ptr[i] - tmp_ptr[i]) * diag_ptr[i];
1611 for (std::size_t i =
begin; i <
end; ++i)
1612 tmp_ptr[i] = dst_ptr[i] + relaxation *
1613 (src_ptr[i] - tmp_ptr[i]) *
1655template <
typename MatrixType = SparseMatrix<
double>>
1659 internal::PreconditionRelaxation::PreconditionJacobiImpl<MatrixType>>
1662 internal::PreconditionRelaxation::PreconditionJacobiImpl<MatrixType>;
1725template <
typename MatrixType = SparseMatrix<
double>>
1729 internal::PreconditionRelaxation::PreconditionSORImpl<MatrixType>>
1732 internal::PreconditionRelaxation::PreconditionSORImpl<MatrixType>;
1777template <
typename MatrixType = SparseMatrix<
double>>
1781 internal::PreconditionRelaxation::PreconditionSSORImpl<MatrixType>>
1784 internal::PreconditionRelaxation::PreconditionSSORImpl<MatrixType>;
1833template <
typename MatrixType = SparseMatrix<
double>>
1837 internal::PreconditionRelaxation::PreconditionPSORImpl<MatrixType>>
1840 internal::PreconditionRelaxation::PreconditionPSORImpl<MatrixType>;
1897 const std::vector<size_type> &permutation,
1898 const std::vector<size_type> &inverse_permutation,
2106template <
typename MatrixType = SparseMatrix<
double>,
2107 typename VectorType = Vector<
double>,
2108 typename PreconditionerType = DiagonalMatrix<VectorType>>
2146 const unsigned int degree = 1,
2152 EigenvalueAlgorithm::lanczos,
2202 vmult(VectorType &dst,
const VectorType &src)
const;
2219 Tvmult(VectorType &dst,
const VectorType &src)
const;
2225 step(VectorType &dst,
const VectorType &src)
const;
2241 Tstep(VectorType &dst,
const VectorType &src)
const;
2295 template <
bool use_transpose>
2298 const VectorType &src,
2300 const bool compute_final_norm =
false)
const;
2365 template <
typename VectorType>
2367 set_initial_guess(VectorType &vector)
2369 vector = 1. /
std::sqrt(
static_cast<double>(vector.size()));
2370 if (vector.locally_owned_elements().is_element(0))
2376 template <
typename Number>
2384 for (
unsigned int i = 0; i < vector.
size(); ++i)
2389 vector.
add(-mean_value);
2394 template <
typename Number,
typename MemorySpace>
2400 for (
unsigned int block = 0; block < vector.
n_blocks(); ++block)
2401 set_initial_guess(vector.
block(block));
2406 template <
typename Number,
typename MemorySpace>
2423 typename MemorySpace::kokkos_space::execution_space exec;
2424 Kokkos::RangePolicy<
typename MemorySpace::kokkos_space::execution_space,
2425 Kokkos::IndexType<types::global_dof_index>>
2426 policy(exec, 0, n_local_elements);
2428 Kokkos::parallel_for(
2429 "::PreconditionChebyshev::set_initial_guess",
2432 values_ptr[i] = (i + first_local_range) % 11;
2438 vector.
add(-mean_value);
2443 struct EigenvalueTracker
2452 std::vector<double>
values;
2459 typename PreconditionerType>
2462 VectorType &eigenvector,
2463 const PreconditionerType &preconditioner,
2464 const unsigned int n_iterations)
2466 typename VectorType::value_type eigenvalue_estimate = 0.;
2467 eigenvector /= eigenvector.l2_norm();
2469 vector1.reinit(eigenvector,
true);
2470 if (!std::is_same_v<PreconditionerType, PreconditionIdentity>)
2471 vector2.reinit(eigenvector,
true);
2472 for (
unsigned int i = 0; i < n_iterations; ++i)
2474 if (!std::is_same_v<PreconditionerType, PreconditionIdentity>)
2476 matrix.vmult(vector2, eigenvector);
2477 preconditioner.vmult(vector1, vector2);
2480 matrix.vmult(vector1, eigenvector);
2482 eigenvalue_estimate = eigenvector * vector1;
2484 vector1 /= vector1.l2_norm();
2485 eigenvector.swap(vector1);
2487 return std::abs(eigenvalue_estimate);
2494 typename PreconditionerType>
2495 EigenvalueInformation
2496 estimate_eigenvalues(
2497 const EigenvalueAlgorithmAdditionalData<PreconditionerType> &
data,
2498 const MatrixType *matrix_ptr,
2499 VectorType &solution_old,
2500 VectorType &temp_vector1,
2501 const unsigned int degree,
2502 const double safety_factor)
2507 safety_factor >= 1.,
2509 "The safety factor must be at least 1.0 to ensure the maximum eigenvalue is "
2510 "not underestimated. Please set safety_factor >= 1.0 in your AdditionalData."));
2512 EigenvalueInformation info{};
2514 if (
data.eig_cg_n_iterations > 0)
2518 "Need to set at least two iterations to find eigenvalues."));
2520 internal::EigenvalueTracker eigenvalue_tracker;
2525 internal::set_initial_guess(temp_vector1);
2526 data.constraints.set_zero(temp_vector1);
2537 if (temp_vector1.all_zero() ==
false)
2539 if (
data.eigenvalue_algorithm ==
2549 solver.connect_eigenvalues_slot(
2550 [&eigenvalue_tracker](
2555 solver.solve(*matrix_ptr,
2558 *
data.preconditioner);
2560 info.cg_iterations = control.last_step();
2562 else if (
data.eigenvalue_algorithm ==
2569 "Cannot estimate the minimal eigenvalue with the "
2570 "power iteration"));
2572 eigenvalue_tracker.values.push_back(
2575 *
data.preconditioner,
2576 data.eig_cg_n_iterations));
2583 if (eigenvalue_tracker.values.empty())
2584 info.min_eigenvalue_estimate = info.max_eigenvalue_estimate = 1.;
2587 info.min_eigenvalue_estimate = eigenvalue_tracker.values.front();
2591 info.max_eigenvalue_estimate =
2592 safety_factor * eigenvalue_tracker.values.back();
2597 info.max_eigenvalue_estimate =
data.max_eigenvalue;
2598 info.min_eigenvalue_estimate =
2599 data.max_eigenvalue /
data.smoothing_range;
2613template <
typename MatrixType>
2623template <
typename VectorType>
2632template <
typename VectorType>
2639template <
typename VectorType>
2648template <
typename VectorType>
2680 const double relaxation)
2681 : relaxation(relaxation)
2690 AdditionalData add_data;
2691 relaxation = add_data.relaxation;
2705template <
typename MatrixType>
2708 const MatrixType &matrix,
2718template <
typename VectorType>
2723 std::is_same_v<size_type, typename VectorType::size_type>,
2724 "PreconditionRichardson and VectorType must have the same size_type.");
2731template <
typename VectorType>
2736 std::is_same_v<size_type, typename VectorType::size_type>,
2737 "PreconditionRichardson and VectorType must have the same size_type.");
2742template <
typename VectorType>
2747 std::is_same_v<size_type, typename VectorType::size_type>,
2748 "PreconditionRichardson and VectorType must have the same size_type.");
2755template <
typename VectorType>
2760 std::is_same_v<size_type, typename VectorType::size_type>,
2761 "PreconditionRichardson and VectorType must have the same size_type.");
2782template <
typename MatrixType,
typename PreconditionerType>
2785 const MatrixType &rA,
2786 const AdditionalData ¶meters)
2789 eigenvalues_are_initialized =
false;
2793 this->data = parameters;
2797template <
typename MatrixType,
typename PreconditionerType>
2801 eigenvalues_are_initialized =
false;
2803 data.relaxation = 1.0;
2804 data.preconditioner =
nullptr;
2807template <
typename MatrixType,
typename PreconditionerType>
2816template <
typename MatrixType,
typename PreconditionerType>
2825template <
typename MatrixType,
typename PreconditionerType>
2826template <
typename VectorType>
2830 const VectorType &src)
const
2835 if (eigenvalues_are_initialized ==
false)
2836 estimate_eigenvalues(src);
2840 for (
unsigned int i = 0; i <
data.n_iterations; ++i)
2841 internal::PreconditionRelaxation::step_operations(*A,
2842 *
data.preconditioner,
2852template <
typename MatrixType,
typename PreconditionerType>
2853template <
typename VectorType>
2857 const VectorType &src)
const
2862 if (eigenvalues_are_initialized ==
false)
2863 estimate_eigenvalues(src);
2867 for (
unsigned int i = 0; i <
data.n_iterations; ++i)
2868 internal::PreconditionRelaxation::step_operations(
2869 *A, *
data.preconditioner, dst, src,
data.relaxation, tmp1, tmp2, i,
true);
2872template <
typename MatrixType,
typename PreconditionerType>
2873template <
typename VectorType>
2877 const VectorType &src)
const
2882 if (eigenvalues_are_initialized ==
false)
2883 estimate_eigenvalues(src);
2887 for (
unsigned int i = 1; i <=
data.n_iterations; ++i)
2888 internal::PreconditionRelaxation::step_operations(*A,
2889 *
data.preconditioner,
2899template <
typename MatrixType,
typename PreconditionerType>
2900template <
typename VectorType>
2904 const VectorType &src)
const
2909 if (eigenvalues_are_initialized ==
false)
2910 estimate_eigenvalues(src);
2914 for (
unsigned int i = 1; i <=
data.n_iterations; ++i)
2915 internal::PreconditionRelaxation::step_operations(
2916 *A, *
data.preconditioner, dst, src,
data.relaxation, tmp1, tmp2, i,
true);
2919template <
typename MatrixType,
typename PreconditionerType>
2920template <
typename VectorType>
2923 const VectorType &src)
const
2927 EigenvalueInformation info;
2929 if (
data.relaxation == 0.0)
2933 solution_old.reinit(src);
2934 temp_vector1.reinit(src,
true);
2936 info = internal::estimate_eigenvalues<MatrixType>(
data,
2941 data.safety_factor);
2943 const double alpha =
2944 (
data.smoothing_range > 1. ?
2945 info.max_eigenvalue_estimate /
data.smoothing_range :
2946 std::min(0.9 * info.max_eigenvalue_estimate,
2947 info.min_eigenvalue_estimate));
2950 ->
data.relaxation = 2.0 / (alpha + info.max_eigenvalue_estimate);
2954 ->eigenvalues_are_initialized =
true;
2959template <
typename MatrixType,
typename PreconditionerType>
2963 return data.relaxation;
2969template <
typename MatrixType>
2972 const AdditionalData ¶meters_in)
2976 parameters_in.relaxation != 0.0,
2978 "Relaxation cannot automatically be determined by PreconditionJacobi."));
2980 AdditionalData parameters;
2981 parameters.relaxation = 1.0;
2982 parameters.n_iterations = parameters_in.n_iterations;
2983 parameters.preconditioner =
2984 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
2986 this->BaseClass::initialize(A, parameters);
2991template <
typename MatrixType>
2994 const AdditionalData ¶meters_in)
2998 parameters_in.relaxation != 0.0,
3000 "Relaxation cannot automatically be determined by PreconditionSOR."));
3002 AdditionalData parameters;
3003 parameters.relaxation = 1.0;
3004 parameters.n_iterations = parameters_in.n_iterations;
3005 parameters.preconditioner =
3006 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
3008 this->BaseClass::initialize(A, parameters);
3013template <
typename MatrixType>
3016 const AdditionalData ¶meters_in)
3020 parameters_in.relaxation != 0.0,
3022 "Relaxation cannot automatically be determined by PreconditionSSOR."));
3024 AdditionalData parameters;
3025 parameters.relaxation = 1.0;
3026 parameters.n_iterations = parameters_in.n_iterations;
3027 parameters.preconditioner =
3028 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
3030 this->BaseClass::initialize(A, parameters);
3037template <
typename MatrixType>
3040 const MatrixType &A,
3041 const std::vector<size_type> &p,
3042 const std::vector<size_type> &ip,
3043 const typename BaseClass::AdditionalData ¶meters_in)
3047 parameters_in.relaxation != 0.0,
3049 "Relaxation cannot automatically be determined by PreconditionPSOR."));
3051 typename BaseClass::AdditionalData parameters;
3052 parameters.relaxation = 1.0;
3053 parameters.n_iterations = parameters_in.n_iterations;
3054 parameters.preconditioner =
3055 std::make_shared<PreconditionerType>(A, parameters_in.relaxation, p, ip);
3057 this->BaseClass::initialize(A, parameters);
3061template <
typename MatrixType>
3064 const AdditionalData &additional_data)
3067 additional_data.permutation,
3068 additional_data.inverse_permutation,
3069 additional_data.parameters);
3072template <
typename MatrixType>
3074 const std::vector<size_type> &permutation,
3075 const std::vector<size_type> &inverse_permutation,
3078 : permutation(permutation)
3079 , inverse_permutation(inverse_permutation)
3080 , parameters(parameters)
3087template <
typename MatrixType,
typename VectorType>
3089 const MatrixType &M,
3090 const function_ptr method)
3092 , precondition(method)
3097template <
typename MatrixType,
typename VectorType>
3101 const VectorType &src)
const
3103 (
matrix.*precondition)(dst, src);
3111 template <
typename PreconditionerType>
3114 const double smoothing_range,
3115 const unsigned int eig_cg_n_iterations,
3116 const double eig_cg_residual,
3117 const double max_eigenvalue,
3119 const double safety_factor)
3120 : smoothing_range(smoothing_range)
3121 , eig_cg_n_iterations(eig_cg_n_iterations)
3122 , eig_cg_residual(eig_cg_residual)
3123 , max_eigenvalue(max_eigenvalue)
3124 , eigenvalue_algorithm(eigenvalue_algorithm)
3125 , safety_factor(safety_factor)
3130 template <
typename PreconditionerType>
3131 inline EigenvalueAlgorithmAdditionalData<PreconditionerType> &
3132 EigenvalueAlgorithmAdditionalData<PreconditionerType>::operator=(
3133 const EigenvalueAlgorithmAdditionalData &other_data)
3135 smoothing_range = other_data.smoothing_range;
3136 eig_cg_n_iterations = other_data.eig_cg_n_iterations;
3137 eig_cg_residual = other_data.eig_cg_residual;
3138 max_eigenvalue = other_data.max_eigenvalue;
3139 preconditioner = other_data.preconditioner;
3140 eigenvalue_algorithm = other_data.eigenvalue_algorithm;
3141 safety_factor = other_data.safety_factor;
3142 constraints.copy_from(other_data.constraints);
3148template <
typename MatrixType,
typename PreconditionerType>
3151 const unsigned int n_iterations,
3152 const double smoothing_range,
3153 const unsigned int eig_cg_n_iterations,
3154 const double eig_cg_residual,
3155 const double max_eigenvalue,
3156 const EigenvalueAlgorithm eigenvalue_algorithm,
3157 const double safety_factor)
3158 :
internal::EigenvalueAlgorithmAdditionalData<PreconditionerType>(
3160 eig_cg_n_iterations,
3163 eigenvalue_algorithm,
3165 , relaxation(relaxation)
3166 , n_iterations(n_iterations)
3175 namespace PreconditionChebyshevImplementation
3183 template <
typename VectorType,
typename PreconditionerType>
3185 vector_updates(
const VectorType &rhs,
3186 const PreconditionerType &preconditioner,
3187 const unsigned int iteration_index,
3188 const double factor1,
3189 const double factor2,
3190 VectorType &solution_old,
3191 VectorType &temp_vector1,
3192 VectorType &temp_vector2,
3193 VectorType &solution,
3194 const bool compute_residual_norm)
3196 double residual_norm = 0;
3197 if (iteration_index == 0)
3199 if (compute_residual_norm)
3200 residual_norm = rhs.l2_norm();
3201 solution.equ(factor2, rhs);
3202 preconditioner.vmult(solution_old, solution);
3204 else if (iteration_index == 1)
3207 if (compute_residual_norm)
3209 std::sqrt(temp_vector1.add_and_dot(-1.0, rhs, temp_vector1));
3211 temp_vector1.add(-1.0, rhs);
3212 preconditioner.vmult(solution_old, temp_vector1);
3215 solution_old.sadd(-factor2, 1 + factor1, solution);
3220 if (compute_residual_norm)
3222 std::sqrt(temp_vector1.add_and_dot(-1.0, rhs, temp_vector1));
3224 temp_vector1.add(-1.0, rhs);
3226 preconditioner.vmult(temp_vector2, temp_vector1);
3229 solution_old.sadd(-factor1, -factor2, temp_vector2);
3230 solution_old.add(1 + factor1, solution);
3233 solution.swap(solution_old);
3234 return residual_norm;
3240 typename PreconditionerType,
3242 !has_vmult_with_std_functions_for_precondition<
3249 const PreconditionerType &preconditioner,
3250 const unsigned int iteration_index,
3251 const double factor1_,
3252 const double factor2_,
3260 const bool compute_residual_norm)
3262 const Number factor1 = factor1_;
3263 const Number factor1_plus_1 = 1. + factor1_;
3264 const Number factor2 = factor2_;
3265 double residual_norm = 0;
3267 if (iteration_index == 0)
3269 if (compute_residual_norm)
3270 residual_norm = rhs.
l2_norm();
3273 preconditioner.vmult(solution_old, rhs);
3276 const auto solution_old_ptr = solution_old.
begin();
3279 solution_old_ptr[i] = solution_old_ptr[i] * factor2;
3281 else if (iteration_index == 1)
3284 if (compute_residual_norm)
3288 temp_vector1.
add(-1.0, rhs);
3290 preconditioner.vmult(solution_old, temp_vector1);
3293 const auto solution_ptr = solution.
begin();
3294 const auto solution_old_ptr = solution_old.
begin();
3297 solution_old_ptr[i] =
3298 factor1_plus_1 * solution_ptr[i] - solution_old_ptr[i] * factor2;
3303 if (compute_residual_norm)
3307 temp_vector1.
add(-1.0, rhs);
3309 preconditioner.vmult(temp_vector2, temp_vector1);
3312 const auto solution_ptr = solution.
begin();
3313 const auto solution_old_ptr = solution_old.
begin();
3314 const auto temp_vector2_ptr = temp_vector2.
begin();
3317 solution_old_ptr[i] = factor1_plus_1 * solution_ptr[i] -
3318 factor1 * solution_old_ptr[i] -
3319 temp_vector2_ptr[i] * factor2;
3322 solution.
swap(solution_old);
3324 return residual_norm;
3329 typename PreconditionerType,
3331 has_vmult_with_std_functions_for_precondition<
3338 const PreconditionerType &preconditioner,
3339 const unsigned int iteration_index,
3340 const double factor1_,
3341 const double factor2_,
3349 const bool compute_residual_norm)
3351 const Number factor1 = factor1_;
3352 const Number factor1_plus_1 = 1. + factor1_;
3353 const Number factor2 = factor2_;
3354 double residual_norm = 0;
3356 const auto rhs_ptr = rhs.
begin();
3357 const auto temp_vector1_ptr = temp_vector1.
begin();
3358 const auto temp_vector2_ptr = temp_vector2.
begin();
3359 const auto solution_ptr = solution.
begin();
3360 const auto solution_old_ptr = solution_old.
begin();
3362 if (iteration_index == 0)
3364 if (compute_residual_norm)
3365 residual_norm = rhs.
l2_norm();
3366 preconditioner.vmult(
3369 [&](
const auto start_range,
const auto end_range) {
3370 if (end_range > start_range)
3371 std::memset(temp_vector2_ptr + start_range,
3373 sizeof(Number) * (end_range - start_range));
3375 [&](
const auto begin,
const auto end) {
3377 for (std::size_t i =
begin; i <
end; ++i)
3378 temp_vector2_ptr[i] *= factor2;
3384 const auto post_update = [&](
const unsigned int begin,
3385 const unsigned int end) {
3386 if (iteration_index == 1)
3389 for (std::size_t i =
begin; i <
end; ++i)
3390 temp_vector2_ptr[i] = factor1_plus_1 * solution_ptr[i] +
3391 factor2 * temp_vector2_ptr[i];
3396 for (std::size_t i =
begin; i <
end; ++i)
3397 temp_vector2_ptr[i] = factor1_plus_1 * solution_ptr[i] -
3398 factor1 * solution_old_ptr[i] +
3399 factor2 * temp_vector2_ptr[i];
3402 if (compute_residual_norm)
3404 preconditioner.vmult(
3407 [&](
const auto begin,
const auto end) {
3409 std::memset(temp_vector2_ptr +
begin,
3414 constexpr unsigned int n_lanes =
3416 const unsigned int end_regular =
end / n_lanes * n_lanes;
3417 for (
unsigned int i =
begin; i < end_regular; i += n_lanes)
3420 rhs_i.
load(rhs_ptr + i);
3421 tmp_i.
load(temp_vector1_ptr + i);
3423 residual_i.
store(temp_vector1_ptr + i);
3424 local_sum += residual_i * residual_i;
3426 for (
unsigned int i = end_regular; i <
end; ++i)
3428 temp_vector1_ptr[i] = rhs_ptr[i] - temp_vector1_ptr[i];
3429 local_sum[i - end_regular] +=
3430 temp_vector1_ptr[i] * temp_vector1_ptr[i];
3440 preconditioner.vmult(
3443 [&](
const auto begin,
const auto end) {
3445 std::memset(temp_vector2_ptr +
begin,
3449 for (std::size_t i =
begin; i <
end; ++i)
3450 temp_vector1_ptr[i] = rhs_ptr[i] - temp_vector1_ptr[i];
3455 solution_old.
swap(temp_vector2);
3456 solution_old.
swap(solution);
3458 return residual_norm;
3462 template <
typename Number>
3467 const ::DiagonalMatrix<
3470 const unsigned int iteration_index,
3471 const double factor1_,
3472 const double factor2_,
3480 const bool compute_residual_norm)
3482 const Number factor1 = factor1_;
3483 const Number factor1_plus_1 = 1. + factor1_;
3484 const Number factor2 = factor2_;
3485 double residual_norm = 0;
3487 auto exec = typename ::MemorySpace::Default::kokkos_space::
3491 const Number *prec_data = preconditioner.get_vector().begin();
3494 using size_type =
typename LinearAlgebra::distributed::
3495 Vector<Number, MemorySpace::Default>::size_type;
3497 if (iteration_index == 0)
3499 Kokkos::parallel_for(
3501 Kokkos::RangePolicy<
3502 ::MemorySpace::Default::kokkos_space::execution_space>(
3504 KOKKOS_LAMBDA(size_type i) {
3505 sol_old_data[i] = prec_data[i] * factor2 * rhs_data[i];
3507 if (compute_residual_norm)
3508 residual_norm = rhs.
l2_norm();
3510 else if (iteration_index == 1)
3512 Kokkos::parallel_for(
3514 Kokkos::RangePolicy<
3515 ::MemorySpace::Default::kokkos_space::execution_space>(
3517 KOKKOS_LAMBDA(size_type i) {
3518 const Number residual = rhs_data[i] - tmp_data[i];
3519 sol_old_data[i] = factor2 * prec_data[i] * residual +
3520 factor1_plus_1 * sol_data[i];
3522 if (compute_residual_norm)
3528 Kokkos::parallel_for(
3530 Kokkos::RangePolicy<
3531 ::MemorySpace::Default::kokkos_space::execution_space>(
3533 KOKKOS_LAMBDA(size_type i) {
3534 const Number residual = rhs_data[i] - tmp_data[i];
3535 sol_old_data[i] = factor2 * prec_data[i] * residual -
3536 factor1 * sol_old_data[i] +
3537 factor1_plus_1 * sol_data[i];
3539 if (compute_residual_norm)
3545 solution.
swap(solution_old);
3546 return residual_norm;
3552 template <
typename Number>
3553 struct VectorUpdater
3555 VectorUpdater(
const Number *rhs,
3556 const Number *matrix_diagonal_inverse,
3557 const unsigned int iteration_index,
3558 const Number factor1,
3559 const Number factor2,
3560 Number *solution_old,
3563 const bool compute_residual_norm)
3565 , matrix_diagonal_inverse(matrix_diagonal_inverse)
3566 , iteration_index(iteration_index)
3569 , solution_old(solution_old)
3570 , tmp_vector(tmp_vector)
3571 , solution(solution)
3572 , compute_residual_norm(compute_residual_norm)
3573 , sum_accumulator(0.0)
3577 apply_to_subrange(
const std::size_t
begin,
const std::size_t
end)
const
3580 const Number factor1 = this->factor1;
3581 const Number factor1_plus_1 = 1. + this->factor1;
3582 const Number factor2 = this->factor2;
3583 if (compute_residual_norm)
3587 const unsigned int end_regular =
end / n_lanes * n_lanes;
3588 if (iteration_index == 0)
3590 for (
unsigned int i =
begin; i < end_regular; i += n_lanes)
3593 rhs_i.
load(rhs + i);
3594 diag_i.
load(matrix_diagonal_inverse + i);
3596 factor2 * diag_i * rhs_i;
3597 res_i.
store(tmp_vector + i);
3598 local_sum += rhs_i * rhs_i;
3600 for (
unsigned int i = end_regular; i <
end; ++i)
3603 factor2 * matrix_diagonal_inverse[i] * rhs[i];
3604 local_sum[i - end_regular] += rhs[i] * rhs[i];
3607 else if (iteration_index == 1)
3610 for (
unsigned int i =
begin; i < end_regular; i += n_lanes)
3613 rhs_i.
load(rhs + i);
3614 diag_i.
load(matrix_diagonal_inverse + i);
3615 sol_i.
load(solution + i);
3616 tmp_i.
load(tmp_vector + i);
3618 local_sum += residual_i * residual_i;
3620 factor1_plus_1 * sol_i + factor2 * diag_i * residual_i;
3621 res_i.
store(tmp_vector + i);
3623 for (
unsigned int i = end_regular; i <
end; ++i)
3625 const Number residual_i = rhs[i] - tmp_vector[i];
3626 local_sum[i - end_regular] += residual_i * residual_i;
3628 factor1_plus_1 * solution[i] +
3629 factor2 * matrix_diagonal_inverse[i] * residual_i;
3636 for (
unsigned int i =
begin; i < end_regular; i += n_lanes)
3640 rhs_i.
load(rhs + i);
3641 diag_i.
load(matrix_diagonal_inverse + i);
3642 sol_i.
load(solution + i);
3643 sol_old_i.
load(solution_old + i);
3644 tmp_i.
load(tmp_vector + i);
3646 local_sum += residual_i * residual_i;
3648 factor1_plus_1 * sol_i - factor1 * sol_old_i +
3649 factor2 * diag_i * residual_i;
3650 res_i.
store(tmp_vector + i);
3652 for (
unsigned int i = end_regular; i <
end; ++i)
3654 const Number residual_i = rhs[i] - tmp_vector[i];
3655 local_sum[i - end_regular] += residual_i * residual_i;
3657 factor1_plus_1 * solution[i] - factor1 * solution_old[i] +
3658 factor2 * matrix_diagonal_inverse[i] * residual_i;
3661 sum_accumulator += local_sum;
3665 if (iteration_index == 0)
3668 for (std::size_t i =
begin; i <
end; ++i)
3669 tmp_vector[i] = factor2 * matrix_diagonal_inverse[i] * rhs[i];
3671 else if (iteration_index == 1)
3675 for (std::size_t i =
begin; i <
end; ++i)
3678 tmp_vector[i] = factor1_plus_1 * solution[i] +
3679 factor2 * matrix_diagonal_inverse[i] *
3680 (rhs[i] - tmp_vector[i]);
3687 for (std::size_t i =
begin; i <
end; ++i)
3693 tmp_vector[i] = factor1_plus_1 * solution[i] -
3694 factor1 * solution_old[i] +
3695 factor2 * matrix_diagonal_inverse[i] *
3696 (rhs[i] - tmp_vector[i]);
3702 const Number *matrix_diagonal_inverse;
3703 const unsigned int iteration_index;
3706 mutable Number *solution_old;
3707 mutable Number *tmp_vector;
3708 mutable Number *solution;
3709 bool compute_residual_norm;
3713 template <
typename Number>
3716 VectorUpdatesRange(
const VectorUpdater<Number> &updater,
3717 const std::size_t
size)
3720 Assert(updater.compute_residual_norm ==
false ||
3723 "Currently, we cannot compute residual in parallel"));
3727 VectorUpdatesRange::apply_to_subrange(0,
size);
3735 ~VectorUpdatesRange()
override =
default;
3738 apply_to_subrange(
const std::size_t
begin,
3739 const std::size_t
end)
const override
3741 updater.apply_to_subrange(
begin,
end);
3744 const VectorUpdater<Number> &updater;
3748 template <
typename Number>
3751 const ::Vector<Number> &rhs,
3753 const unsigned int iteration_index,
3754 const double factor1,
3755 const double factor2,
3760 const bool compute_residual_norm)
3762 VectorUpdater<Number> upd(rhs.begin(),
3763 jacobi.get_vector().begin(),
3767 solution_old.
begin(),
3768 temp_vector1.
begin(),
3770 compute_residual_norm);
3772 VectorUpdatesRange<Number>(upd, rhs.size());
3775 solution.
swap(temp_vector1);
3776 solution_old.
swap(temp_vector1);
3778 if (compute_residual_norm)
3787 template <
typename Number>
3791 const ::DiagonalMatrix<
3793 const unsigned int iteration_index,
3794 const double factor1,
3795 const double factor2,
3802 const bool compute_residual_norm)
3804 VectorUpdater<Number> upd(rhs.
begin(),
3805 jacobi.get_vector().begin(),
3809 solution_old.
begin(),
3810 temp_vector1.
begin(),
3812 compute_residual_norm);
3817 solution.
swap(temp_vector1);
3818 solution_old.
swap(temp_vector1);
3820 if (compute_residual_norm)
3835 typename PreconditionerType,
3839 PreconditionerType> &&
3840 !(has_vmult_with_std_functions_for_precondition<PreconditionerType,
3842 has_vmult_with_std_functions_for_precondition<
MatrixType,
3846 vmult_and_update(
const MatrixType &matrix,
3847 const PreconditionerType &preconditioner,
3848 const VectorType &rhs,
3849 const unsigned int iteration_index,
3850 const double factor1,
3851 const double factor2,
3852 VectorType &solution,
3853 VectorType &solution_old,
3854 VectorType &temp_vector1,
3855 VectorType &temp_vector2,
3856 const bool compute_residual_norm)
3858 if (iteration_index > 0)
3859 matrix.vmult(temp_vector1, solution);
3860 return vector_updates(rhs,
3869 compute_residual_norm);
3877 typename PreconditionerType,
3881 PreconditionerType> &&
3882 (has_vmult_with_std_functions_for_precondition<PreconditionerType,
3884 has_vmult_with_std_functions_for_precondition<
MatrixType,
3888 vmult_and_update(
const MatrixType &matrix,
3889 const PreconditionerType &preconditioner,
3890 const VectorType &rhs,
3891 const unsigned int iteration_index,
3892 const double factor1_,
3893 const double factor2_,
3894 VectorType &solution,
3895 VectorType &solution_old,
3896 VectorType &temp_vector1,
3897 VectorType &temp_vector2,
3898 const bool compute_residual_norm)
3900 using Number =
typename VectorType::value_type;
3902 const Number factor1 = factor1_;
3903 const Number factor1_plus_1 = 1. + factor1_;
3904 const Number factor2 = factor2_;
3905 double residual_norm = 0;
3907 if (iteration_index == 0)
3909 if (compute_residual_norm)
3910 residual_norm = rhs.l2_norm();
3912 preconditioner.vmult(
3915 [&](
const unsigned int start_range,
const unsigned int end_range) {
3917 if (end_range > start_range)
3918 std::memset(temp_vector2.begin() + start_range,
3920 sizeof(Number) * (end_range - start_range));
3922 [&](
const unsigned int start_range,
const unsigned int end_range) {
3923 const auto tmp_ptr = temp_vector2.begin();
3926 for (std::size_t i = start_range; i < end_range; ++i)
3927 tmp_ptr[i] *= factor2;
3932 temp_vector1.reinit(rhs,
true);
3933 temp_vector2.reinit(rhs,
true);
3936 const auto post_operation = [&](
const unsigned int start_range,
3937 const unsigned int end_range) {
3938 const auto rhs_ptr = rhs.begin();
3939 const auto tmp_ptr = temp_vector1.begin();
3942 for (std::size_t i = start_range; i < end_range; ++i)
3943 tmp_ptr[i] = rhs_ptr[i] - tmp_ptr[i];
3946 if (compute_residual_norm)
3950 [&](
const unsigned int begin,
const unsigned int end) {
3951 const auto rhs_ptr = rhs.begin();
3952 const auto tmp_ptr = temp_vector1.begin();
3954 constexpr unsigned int n_lanes =
3956 const unsigned int end_regular =
end / n_lanes * n_lanes;
3957 for (
unsigned int i =
begin; i < end_regular; i += n_lanes)
3960 rhs_i.
load(rhs_ptr + i);
3961 tmp_i.
load(tmp_ptr + i);
3963 residual_i.
store(tmp_ptr + i);
3964 local_sum += residual_i * residual_i;
3966 for (
unsigned int i = end_regular; i <
end; ++i)
3968 tmp_ptr[i] = rhs_ptr[i] - tmp_ptr[i];
3969 local_sum[i - end_regular] += tmp_ptr[i] * tmp_ptr[i];
3980 [&](
const unsigned int start_range,
3981 const unsigned int end_range) {
3982 const auto rhs_ptr = rhs.begin();
3983 const auto tmp_ptr = temp_vector1.begin();
3986 for (std::size_t i = start_range; i < end_range; ++i)
3987 tmp_ptr[i] = rhs_ptr[i] - tmp_ptr[i];
3994 preconditioner.vmult(
3997 [&](
const unsigned int start_range,
const unsigned int end_range) {
4000 if (end_range > start_range)
4001 std::memset(temp_vector2.begin() + start_range,
4003 sizeof(Number) * (end_range - start_range));
4005 [&](
const unsigned int start_range,
const unsigned int end_range) {
4006 const auto solution_ptr = solution.begin();
4007 const auto solution_old_ptr = solution_old.begin();
4008 const auto tmp_ptr = temp_vector2.begin();
4010 if (iteration_index == 1)
4013 for (std::size_t i = start_range; i < end_range; ++i)
4015 factor1_plus_1 * solution_ptr[i] + factor2 * tmp_ptr[i];
4020 for (std::size_t i = start_range; i < end_range; ++i)
4021 tmp_ptr[i] = factor1_plus_1 * solution_ptr[i] -
4022 factor1 * solution_old_ptr[i] +
4023 factor2 * tmp_ptr[i];
4027 if (compute_residual_norm)
4031 solution.swap(temp_vector2);
4032 solution_old.swap(temp_vector2);
4033 return residual_norm;
4040 typename PreconditionerType,
4041 std::enable_if_t<has_vmult_with_std_functions<
MatrixType,
4043 PreconditionerType>,
4046 vmult_and_update(
const MatrixType &matrix,
4047 const PreconditionerType &preconditioner,
4048 const VectorType &rhs,
4049 const unsigned int iteration_index,
4050 const double factor1,
4051 const double factor2,
4052 VectorType &solution,
4053 VectorType &solution_old,
4054 VectorType &temp_vector1,
4056 const bool compute_residual_norm)
4058 using Number =
typename VectorType::value_type;
4059 VectorUpdater<Number> updater(rhs.begin(),
4060 preconditioner.get_vector().begin(),
4064 solution_old.begin(),
4065 temp_vector1.begin(),
4067 compute_residual_norm);
4068 if (iteration_index > 0)
4072 [&](
const unsigned int start_range,
const unsigned int end_range) {
4075 if (end_range > start_range)
4076 std::memset(temp_vector1.begin() + start_range,
4078 sizeof(Number) * (end_range - start_range));
4080 [&](
const unsigned int start_range,
const unsigned int end_range) {
4081 if (end_range > start_range)
4082 updater.apply_to_subrange(start_range, end_range);
4085 updater.apply_to_subrange(0U, solution.locally_owned_size());
4088 solution.swap(temp_vector1);
4089 solution_old.swap(temp_vector1);
4091 if (compute_residual_norm)
4093 solution.get_mpi_communicator()));
4098 template <
typename MatrixType,
typename PreconditionerType>
4100 initialize_preconditioner(
4101 const MatrixType & ,
4102 std::shared_ptr<PreconditionerType> &preconditioner)
4104 (void)preconditioner;
4108 template <
typename MatrixType,
typename VectorType>
4110 initialize_preconditioner(
4111 const MatrixType &matrix,
4114 if (preconditioner.get() ==
nullptr || preconditioner->m() !=
matrix.m())
4116 if (preconditioner.get() ==
nullptr)
4118 std::make_shared<::DiagonalMatrix<VectorType>>();
4121 preconditioner->m() == 0,
4123 "Preconditioner appears to be initialized but not sized correctly"));
4126 if (preconditioner->m() !=
matrix.m())
4128 preconditioner->get_vector().reinit(
matrix.m());
4129 for (
typename VectorType::size_type i = 0; i <
matrix.m(); ++i)
4130 preconditioner->get_vector()(i) = 1. /
matrix.el(i, i);
4139template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4142 const double smoothing_range,
4143 const unsigned int eig_cg_n_iterations,
4144 const double eig_cg_residual,
4145 const double max_eigenvalue,
4146 const EigenvalueAlgorithm eigenvalue_algorithm,
4147 const PolynomialType polynomial_type,
4148 const double safety_factor)
4149 :
internal::EigenvalueAlgorithmAdditionalData<PreconditionerType>(
4151 eig_cg_n_iterations,
4154 eigenvalue_algorithm,
4157 , polynomial_type(polynomial_type)
4162template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4167 , eigenvalues_are_initialized(false)
4170 std::is_same_v<size_type, typename VectorType::size_type>,
4171 "PreconditionChebyshev and VectorType must have the same size_type.");
4176template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4179 const MatrixType &matrix,
4180 const AdditionalData &additional_data)
4183 data = additional_data;
4185 ExcMessage(
"The degree of the Chebyshev method must be positive."));
4186 internal::PreconditionChebyshevImplementation::initialize_preconditioner(
4187 matrix,
data.preconditioner);
4188 eigenvalues_are_initialized =
false;
4193template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4197 eigenvalues_are_initialized =
false;
4198 theta = delta = 1.0;
4199 matrix_ptr =
nullptr;
4202 solution_old.reinit(empty_vector);
4203 temp_vector1.reinit(empty_vector);
4204 temp_vector2.reinit(empty_vector);
4206 data.preconditioner.reset();
4211template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4218 solution_old.reinit(src);
4219 temp_vector1.reinit(src,
true);
4221 auto info = internal::estimate_eigenvalues<MatrixType>(
data,
4226 data.safety_factor);
4228 const double alpha = (
data.smoothing_range > 1. ?
4229 info.max_eigenvalue_estimate /
data.smoothing_range :
4230 std::min(0.9 * info.max_eigenvalue_estimate,
4231 info.min_eigenvalue_estimate));
4249 "When using PreconditionChebyshev as a solver (i.e., when "
4250 "AdditionalData::degree == numbers::invalid_unsigned_int), "
4251 "AdditionalData::smoothing_range must be strictly less than "
4252 "one because it is interpreted as the relative target "
4253 "tolerance of the Chebyshev iteration. A value >= 1 is only "
4254 "meaningful when PreconditionChebyshev is used as a smoother "
4255 "with a fixed polynomial degree."));
4257 const double actual_range = info.max_eigenvalue_estimate / alpha;
4258 const double sigma = (1. -
std::sqrt(1. / actual_range)) /
4260 const double eps =
data.smoothing_range;
4265 1 +
static_cast<unsigned int>(
4270 info.degree =
data.degree;
4275 (
data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
4276 (info.max_eigenvalue_estimate) :
4277 ((info.max_eigenvalue_estimate - alpha) * 0.5);
4280 ->theta = (info.max_eigenvalue_estimate + alpha) * 0.5;
4284 using NumberType =
typename VectorType::value_type;
4292 (std::is_same_v<VectorType,
4295 temp_vector2.
reinit(src, true);
4299 temp_vector2.reinit(empty_vector);
4304 ->eigenvalues_are_initialized =
true;
4311template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4312template <
bool do_transpose>
4316 const VectorType &rhs,
4317 VectorType &solution,
4318 const bool compute_final_norm)
const
4320 std::scoped_lock lock(mutex);
4321 if (eigenvalues_are_initialized ==
false)
4322 estimate_eigenvalues(rhs);
4324 double residual_norm = 0;
4325 if constexpr (do_transpose)
4327 matrix_ptr->Tvmult(temp_vector1, solution);
4329 internal::PreconditionChebyshevImplementation::vector_updates(
4331 *
data.preconditioner,
4332 zero_out_dst ? 0 : 1,
4334 (
data.polynomial_type ==
4335 AdditionalData::PolynomialType::fourth_kind) ?
4336 (4. / (3. * delta)) :
4342 compute_final_norm &&
data.degree < 2);
4346 internal::PreconditionChebyshevImplementation::vmult_and_update(
4348 *
data.preconditioner,
4350 zero_out_dst ? 0 : 1,
4352 (
data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
4353 (4. / (3. * delta)) :
4359 compute_final_norm &&
data.degree < 2);
4364 return residual_norm;
4366 double rhok = delta /
theta, sigma =
theta / delta;
4367 for (
unsigned int k = 0; k <
data.degree - 1; ++k)
4369 double factor1 = 0.0;
4370 double factor2 = 0.0;
4372 if (
data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
4374 factor1 = (2 * k + 1.) / (2 * k + 5.);
4375 factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
4379 const double rhokp = 1. / (2. * sigma - rhok);
4380 factor1 = rhokp * rhok;
4381 factor2 = 2. * rhokp / delta;
4385 if constexpr (do_transpose)
4387 matrix_ptr->Tvmult(temp_vector1, solution);
4389 internal::PreconditionChebyshevImplementation::vector_updates(
4391 *
data.preconditioner,
4392 k + (zero_out_dst ? 1 : 2),
4399 compute_final_norm && k ==
data.degree - 2);
4404 internal::PreconditionChebyshevImplementation::vmult_and_update(
4406 *
data.preconditioner,
4408 k + (zero_out_dst ? 1 : 2),
4415 compute_final_norm && k ==
data.degree - 2);
4419 return residual_norm;
4424template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4427 VectorType &solution,
4428 const VectorType &rhs)
const
4430 apply_internal<false>(
true, rhs, solution);
4435template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4438 VectorType &solution,
4439 const VectorType &rhs)
const
4441 apply_internal<true>(
true, rhs, solution);
4446template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4449 VectorType &solution,
4450 const VectorType &rhs)
const
4452 apply_internal<false>(
false, rhs, solution);
4457template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4460 VectorType &solution,
4461 const VectorType &rhs)
const
4463 apply_internal<true>(
false, rhs, solution);
4468template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4472 const VectorType &rhs)
const
4474 return apply_internal<false>(
true,
4482template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4486 const VectorType &rhs)
const
4488 return apply_internal<false>(
false,
4496template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4499 PreconditionerType>::size_type
4503 return matrix_ptr->m();
4508template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4511 PreconditionerType>::size_type
4515 return matrix_ptr->n();
4520template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4523 const unsigned int degree)
4526 ExcMessage(
"The degree of the Chebyshev method must be positive."));
4527 data.degree = degree;
* * const_iterator()=default
unsigned int n_blocks() const
BlockType & block(const unsigned int i)
size_type nth_index_in_set(const size_type local_index) const
Number mean_value() const
Number * get_values() const
size_type locally_owned_size() const
void swap(Vector< Number, MemorySpace > &v) noexcept
::IndexSet locally_owned_elements() const
real_type l2_norm() const
Number add_and_dot(const Number a, const Vector< Number, MemorySpace > &V, const Vector< Number, MemorySpace > &W)
MPI_Comm get_mpi_communicator() const
static unsigned int n_threads()
void Tvmult(VectorType &dst, const VectorType &src) const
void step(VectorType &dst, const VectorType &src) const
double step_with_last_residual_norm(VectorType &dst, const VectorType &src) const
EigenvalueInformation estimate_eigenvalues(const VectorType &src) const
void Tstep(VectorType &dst, const VectorType &src) const
double apply_internal(const bool zero_out_dst, const VectorType &src, VectorType &dst, const bool compute_final_norm=false) const
double vmult_with_last_residual_norm(VectorType &dst, const VectorType &src) const
void set_degree(const unsigned int degree)
void vmult(VectorType &dst, const VectorType &src) const
void initialize(const MatrixType &matrix, const AdditionalData &additional_data=AdditionalData())
bool eigenvalues_are_initialized
ObserverPointer< const MatrixType, PreconditionChebyshev< MatrixType, VectorType, PreconditionerType > > matrix_ptr
void vmult_add(VectorType &, const VectorType &) const
void vmult(VectorType &, const VectorType &) const
void initialize(const MatrixType &matrix, const AdditionalData &additional_data=AdditionalData())
void Tvmult(VectorType &, const VectorType &) const
void Tvmult_add(VectorType &, const VectorType &) const
typename BaseClass::AdditionalData AdditionalData
internal::PreconditionRelaxation::PreconditionJacobiImpl< MatrixType > PreconditionerType
void initialize(const MatrixType &A, const AdditionalData ¶meters=AdditionalData())
AdditionalData(const std::vector< size_type > &permutation, const std::vector< size_type > &inverse_permutation, const typename BaseClass::AdditionalData ¶meters=typename BaseClass::AdditionalData())
BaseClass::AdditionalData parameters
const std::vector< size_type > & inverse_permutation
const std::vector< size_type > & permutation
typename BaseClass::size_type size_type
void initialize(const MatrixType &A, const AdditionalData &additional_data)
internal::PreconditionRelaxation::PreconditionPSORImpl< MatrixType > PreconditionerType
void initialize(const MatrixType &A, const std::vector< size_type > &permutation, const std::vector< size_type > &inverse_permutation, const typename BaseClass::AdditionalData ¶meters=typename BaseClass::AdditionalData())
unsigned int n_iterations
AdditionalData(const double relaxation=1., const unsigned int n_iterations=1, const double smoothing_range=0., const unsigned int eig_cg_n_iterations=8, const double eig_cg_residual=1e-2, const double max_eigenvalue=1, const EigenvalueAlgorithm eigenvalue_algorithm=EigenvalueAlgorithm::lanczos, const double safety_factor=1.2)
double get_relaxation() const
void Tvmult(VectorType &, const VectorType &) const
std::shared_ptr< PreconditionerType > preconditioner
EigenvalueInformation estimate_eigenvalues(const VectorType &src) const
void step(VectorType &x, const VectorType &rhs) const
ObserverPointer< const MatrixType, PreconditionRelaxation< MatrixType > > A
void initialize(const MatrixType &A, const AdditionalData ¶meters=AdditionalData())
bool eigenvalues_are_initialized
void Tstep(VectorType &x, const VectorType &rhs) const
void vmult(VectorType &, const VectorType &) const
types::global_dof_index size_type
AdditionalData(const double relaxation=1.)
types::global_dof_index size_type
void vmult_add(VectorType &, const VectorType &) const
void initialize(const AdditionalData ¶meters)
void initialize(const MatrixType &matrix, const AdditionalData ¶meters)
void vmult(VectorType &, const VectorType &) const
void Tvmult(VectorType &, const VectorType &) const
void Tvmult_add(VectorType &, const VectorType &) const
internal::PreconditionRelaxation::PreconditionSORImpl< MatrixType > PreconditionerType
typename BaseClass::AdditionalData AdditionalData
void initialize(const MatrixType &A, const AdditionalData ¶meters=AdditionalData())
void initialize(const MatrixType &A, const AdditionalData ¶meters=AdditionalData())
typename BaseClass::AdditionalData AdditionalData
internal::PreconditionRelaxation::PreconditionSSORImpl< MatrixType > PreconditionerType
void(MatrixType::*)(VectorType &, const VectorType &) const function_ptr
const function_ptr precondition
const MatrixType & matrix
void vmult(VectorType &dst, const VectorType &src) const
PreconditionUseMatrix(const MatrixType &M, const function_ptr method)
const_iterator end() const
const_iterator begin() const
void add(const std::vector< size_type > &indices, const std::vector< OtherNumber > &values)
Number mean_value() const
MPI_Comm get_mpi_communicator() const
virtual size_type size() const override
virtual void swap(Vector< Number > &v) noexcept
static constexpr std::size_t size()
void store(OtherNumber *ptr) const
void load(const OtherNumber *ptr)
#define DEAL_II_OPENMP_SIMD_PRAGMA
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::vector< index_type > data
types::global_dof_index size_type
@ matrix
Contents is actually a matrix.
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
Tpetra::CrsMatrix< Number, LO, GO, NodeType< MemorySpace > > MatrixType
* * * RotationFunction< dim, Number >::RotationFunction Number(dim)
T sum(const T &t, const MPI_Comm mpi_communicator)
unsigned int minimum_parallel_grain_size
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
constexpr unsigned int invalid_unsigned_int
::VectorizedArray< Number, width > log(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int global_dof_index
AdditionalData(const unsigned int degree=1, const double smoothing_range=0., const unsigned int eig_cg_n_iterations=8, const double eig_cg_residual=1e-2, const double max_eigenvalue=1, const EigenvalueAlgorithm eigenvalue_algorithm=EigenvalueAlgorithm::lanczos, const PolynomialType polynomial_type=PolynomialType::first_kind, const double safety_factor=1.2)
PolynomialType polynomial_type
std::shared_ptr< PreconditionerType > preconditioner
EigenvalueAlgorithmAdditionalData(const double smoothing_range, const unsigned int eig_cg_n_iterations, const double eig_cg_residual, const double max_eigenvalue, const EigenvalueAlgorithm eigenvalue_algorithm, const double safety_factor=1.2)
EigenvalueAlgorithmAdditionalData< PreconditionerType > & operator=(const EigenvalueAlgorithmAdditionalData< PreconditionerType > &other_data)
::AffineConstraints< double > constraints
unsigned int eig_cg_n_iterations
EigenvalueAlgorithm eigenvalue_algorithm
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)