15#ifndef dealii_precondition_h
16#define dealii_precondition_h
40template <
typename number>
42template <
typename number>
48 template <
typename,
typename>
127 template <
typename PreconditionerType>
248 template <
typename MatrixType>
256 template <
typename VectorType>
258 vmult(VectorType &,
const VectorType &)
const;
264 template <
typename VectorType>
266 Tvmult(VectorType &,
const VectorType &)
const;
271 template <
typename VectorType>
279 template <
typename VectorType>
377 template <
typename MatrixType>
384 template <
typename VectorType>
386 vmult(VectorType &,
const VectorType &)
const;
392 template <
typename VectorType>
394 Tvmult(VectorType &,
const VectorType &)
const;
398 template <
typename VectorType>
406 template <
typename VectorType>
496template <
typename MatrixType = SparseMatrix<
double>,
497 typename VectorType = Vector<
double>>
505 const VectorType &) const;
519 vmult(VectorType &dst,
const VectorType &src)
const;
564template <
typename MatrixType = SparseMatrix<
double>,
565 typename PreconditionerType = IdentityMatrix>
593 EigenvalueAlgorithm::lanczos);
639 template <
typename VectorType>
641 vmult(VectorType &,
const VectorType &)
const;
647 template <
typename VectorType>
649 Tvmult(VectorType &,
const VectorType &)
const;
654 template <
typename VectorType>
656 step(VectorType &x,
const VectorType &rhs)
const;
661 template <
typename VectorType>
663 Tstep(VectorType &x,
const VectorType &rhs)
const;
670 template <
typename VectorType>
715 template <
typename MatrixType,
typename VectorType>
716 using vmult_functions_t =
decltype(std::declval<const MatrixType>().vmult(
717 std::declval<VectorType &>(),
718 std::declval<const VectorType &>(),
720 const std::function<
void(
const unsigned int,
const unsigned int)> &>(),
722 const std::function<
void(
const unsigned int,
const unsigned int)> &>()));
724 template <
typename MatrixType,
726 typename PreconditionerType>
727 constexpr bool has_vmult_with_std_functions =
729 std::is_same_v<PreconditionerType, ::DiagonalMatrix<VectorType>> &&
730 (std::is_same_v<VectorType,
738 template <
typename MatrixType,
typename VectorType>
739 constexpr bool has_vmult_with_std_functions_for_precondition =
744 template <
typename T,
typename VectorType>
745 using Tvmult_t =
decltype(std::declval<const T>().Tvmult(
746 std::declval<VectorType &>(),
747 std::declval<const VectorType &>()));
749 template <
typename T,
typename VectorType>
750 constexpr bool has_Tvmult = is_supported_operation<Tvmult_t, T, VectorType>;
752 template <
typename T,
typename VectorType>
753 using step_t =
decltype(std::declval<const T>().step(
754 std::declval<VectorType &>(),
755 std::declval<const VectorType &>()));
757 template <
typename T,
typename VectorType>
758 constexpr bool has_step = is_supported_operation<step_t, T, VectorType>;
760 template <
typename T,
typename VectorType>
762 decltype(std::declval<const T>().step(std::declval<VectorType &>(),
763 std::declval<const VectorType &>(),
764 std::declval<const double>()));
766 template <
typename T,
typename VectorType>
767 constexpr bool has_step_omega =
768 is_supported_operation<step_omega_t, T, VectorType>;
770 template <
typename T,
typename VectorType>
771 using Tstep_t =
decltype(std::declval<const T>().Tstep(
772 std::declval<VectorType &>(),
773 std::declval<const VectorType &>()));
775 template <
typename T,
typename VectorType>
776 constexpr bool has_Tstep = is_supported_operation<Tstep_t, T, VectorType>;
778 template <
typename T,
typename VectorType>
779 using Tstep_omega_t =
780 decltype(std::declval<const T>().Tstep(std::declval<VectorType &>(),
781 std::declval<const VectorType &>(),
782 std::declval<const double>()));
784 template <
typename T,
typename VectorType>
785 constexpr bool has_Tstep_omega =
786 is_supported_operation<Tstep_omega_t, T, VectorType>;
788 template <
typename T,
typename VectorType>
789 using jacobi_step_t =
decltype(std::declval<const T>().Jacobi_step(
790 std::declval<VectorType &>(),
791 std::declval<const VectorType &>(),
792 std::declval<const double>()));
794 template <
typename T,
typename VectorType>
795 constexpr bool has_jacobi_step =
796 is_supported_operation<jacobi_step_t, T, VectorType>;
798 template <
typename T,
typename VectorType>
799 using SOR_step_t =
decltype(std::declval<const T>().SOR_step(
800 std::declval<VectorType &>(),
801 std::declval<const VectorType &>(),
802 std::declval<const double>()));
804 template <
typename T,
typename VectorType>
805 constexpr bool has_SOR_step =
806 is_supported_operation<SOR_step_t, T, VectorType>;
808 template <
typename T,
typename VectorType>
809 using SSOR_step_t =
decltype(std::declval<const T>().SSOR_step(
810 std::declval<VectorType &>(),
811 std::declval<const VectorType &>(),
812 std::declval<const double>()));
814 template <
typename T,
typename VectorType>
815 constexpr bool has_SSOR_step =
816 is_supported_operation<SSOR_step_t, T, VectorType>;
818 template <
typename MatrixType>
819 class PreconditionJacobiImpl
822 PreconditionJacobiImpl(
const MatrixType &A,
const double relaxation)
824 , relaxation(relaxation)
827 template <
typename VectorType>
829 vmult(VectorType &dst,
const VectorType &src)
const
831 this->A->precondition_Jacobi(dst, src, this->relaxation);
834 template <
typename VectorType>
836 Tvmult(VectorType &dst,
const VectorType &src)
const
839 this->vmult(dst, src);
842 template <
typename VectorType,
843 std::enable_if_t<has_jacobi_step<MatrixType, VectorType>,
844 MatrixType> * =
nullptr>
846 step(VectorType &dst,
const VectorType &src)
const
848 this->A->Jacobi_step(dst, src, this->relaxation);
851 template <
typename VectorType,
852 std::enable_if_t<!has_jacobi_step<MatrixType, VectorType>,
853 MatrixType> * =
nullptr>
855 step(VectorType &,
const VectorType &)
const
859 "Matrix A does not provide a Jacobi_step() function!"));
862 template <
typename VectorType>
864 Tstep(VectorType &dst,
const VectorType &src)
const
867 this->step(dst, src);
872 const double relaxation;
875 template <
typename MatrixType>
876 class PreconditionSORImpl
879 PreconditionSORImpl(
const MatrixType &A,
const double relaxation)
881 , relaxation(relaxation)
884 template <
typename VectorType>
886 vmult(VectorType &dst,
const VectorType &src)
const
888 this->A->precondition_SOR(dst, src, this->relaxation);
891 template <
typename VectorType>
893 Tvmult(VectorType &dst,
const VectorType &src)
const
895 this->A->precondition_TSOR(dst, src, this->relaxation);
898 template <
typename VectorType,
899 std::enable_if_t<has_SOR_step<MatrixType, VectorType>,
900 MatrixType> * =
nullptr>
902 step(VectorType &dst,
const VectorType &src)
const
904 this->A->SOR_step(dst, src, this->relaxation);
907 template <
typename VectorType,
908 std::enable_if_t<!has_SOR_step<MatrixType, VectorType>,
909 MatrixType> * =
nullptr>
911 step(VectorType &,
const VectorType &)
const
915 "Matrix A does not provide a SOR_step() function!"));
918 template <
typename VectorType,
919 std::enable_if_t<has_SOR_step<MatrixType, VectorType>,
920 MatrixType> * =
nullptr>
922 Tstep(VectorType &dst,
const VectorType &src)
const
924 this->A->TSOR_step(dst, src, this->relaxation);
927 template <
typename VectorType,
928 std::enable_if_t<!has_SOR_step<MatrixType, VectorType>,
929 MatrixType> * =
nullptr>
931 Tstep(VectorType &,
const VectorType &)
const
935 "Matrix A does not provide a TSOR_step() function!"));
940 const double relaxation;
943 template <
typename MatrixType>
944 class PreconditionSSORImpl
947 using size_type =
typename MatrixType::size_type;
949 PreconditionSSORImpl(
const MatrixType &A,
const double relaxation)
951 , relaxation(relaxation)
962 const size_type n = this->A->n();
963 pos_right_of_diagonal.resize(n,
static_cast<std::size_t
>(-1));
964 for (size_type row = 0; row < n; ++row)
971 typename MatrixType::value_type>::const_iterator it =
973 for (; it < mat->
end(row); ++it)
974 if (it->column() > row)
976 pos_right_of_diagonal[row] = it - mat->
begin();
981 template <
typename VectorType>
983 vmult(VectorType &dst,
const VectorType &src)
const
985 this->A->precondition_SSOR(dst,
988 pos_right_of_diagonal);
991 template <
typename VectorType>
993 Tvmult(VectorType &dst,
const VectorType &src)
const
995 this->A->precondition_SSOR(dst,
998 pos_right_of_diagonal);
1001 template <
typename VectorType,
1002 std::enable_if_t<has_SSOR_step<MatrixType, VectorType>,
1003 MatrixType> * =
nullptr>
1005 step(VectorType &dst,
const VectorType &src)
const
1007 this->A->SSOR_step(dst, src, this->relaxation);
1010 template <
typename VectorType,
1011 std::enable_if_t<!has_SSOR_step<MatrixType, VectorType>,
1012 MatrixType> * =
nullptr>
1014 step(VectorType &,
const VectorType &)
const
1018 "Matrix A does not provide a SSOR_step() function!"));
1021 template <
typename VectorType>
1023 Tstep(VectorType &dst,
const VectorType &src)
const
1026 this->step(dst, src);
1031 const double relaxation;
1037 std::vector<std::size_t> pos_right_of_diagonal;
1040 template <
typename MatrixType>
1041 class PreconditionPSORImpl
1044 using size_type =
typename MatrixType::size_type;
1046 PreconditionPSORImpl(
const MatrixType &A,
1047 const double relaxation,
1048 const std::vector<size_type> &permutation,
1049 const std::vector<size_type> &inverse_permutation)
1051 , relaxation(relaxation)
1052 , permutation(permutation)
1053 , inverse_permutation(inverse_permutation)
1056 template <
typename VectorType>
1058 vmult(VectorType &dst,
const VectorType &src)
const
1061 this->A->PSOR(dst, permutation, inverse_permutation, this->relaxation);
1064 template <
typename VectorType>
1066 Tvmult(VectorType &dst,
const VectorType &src)
const
1069 this->A->TPSOR(dst, permutation, inverse_permutation, this->relaxation);
1074 const double relaxation;
1076 const std::vector<size_type> &permutation;
1077 const std::vector<size_type> &inverse_permutation;
1080 template <
typename MatrixType,
1081 typename PreconditionerType,
1082 typename VectorType,
1083 std::enable_if_t<has_step_omega<PreconditionerType, VectorType>,
1084 PreconditionerType> * =
nullptr>
1086 step(
const MatrixType &,
1087 const PreconditionerType &preconditioner,
1089 const VectorType &src,
1090 const double relaxation,
1094 preconditioner.step(dst, src, relaxation);
1098 typename MatrixType,
1099 typename PreconditionerType,
1100 typename VectorType,
1101 std::enable_if_t<!has_step_omega<PreconditionerType, VectorType> &&
1102 has_step<PreconditionerType, VectorType>,
1103 PreconditionerType> * =
nullptr>
1105 step(
const MatrixType &,
1106 const PreconditionerType &preconditioner,
1108 const VectorType &src,
1109 const double relaxation,
1117 preconditioner.step(dst, src);
1121 typename MatrixType,
1122 typename PreconditionerType,
1123 typename VectorType,
1124 std::enable_if_t<!has_step_omega<PreconditionerType, VectorType> &&
1125 !has_step<PreconditionerType, VectorType>,
1126 PreconditionerType> * =
nullptr>
1128 step(
const MatrixType &A,
1129 const PreconditionerType &preconditioner,
1131 const VectorType &src,
1132 const double relaxation,
1133 VectorType &residual,
1136 residual.reinit(dst,
true);
1137 tmp.reinit(dst,
true);
1139 A.vmult(residual, dst);
1140 residual.sadd(-1.0, 1.0, src);
1142 preconditioner.vmult(tmp, residual);
1143 dst.add(relaxation, tmp);
1146 template <
typename MatrixType,
1147 typename PreconditionerType,
1148 typename VectorType,
1149 std::enable_if_t<has_Tstep_omega<PreconditionerType, VectorType>,
1150 PreconditionerType> * =
nullptr>
1152 Tstep(
const MatrixType &,
1153 const PreconditionerType &preconditioner,
1155 const VectorType &src,
1156 const double relaxation,
1160 preconditioner.Tstep(dst, src, relaxation);
1164 typename MatrixType,
1165 typename PreconditionerType,
1166 typename VectorType,
1167 std::enable_if_t<!has_Tstep_omega<PreconditionerType, VectorType> &&
1168 has_Tstep<PreconditionerType, VectorType>,
1169 PreconditionerType> * =
nullptr>
1171 Tstep(
const MatrixType &,
1172 const PreconditionerType &preconditioner,
1174 const VectorType &src,
1175 const double relaxation,
1183 preconditioner.Tstep(dst, src);
1186 template <
typename MatrixType,
1187 typename VectorType,
1188 std::enable_if_t<has_Tvmult<MatrixType, VectorType>, MatrixType>
1191 Tvmult(
const MatrixType &A, VectorType &dst,
const VectorType &src)
1196 template <
typename MatrixType,
1197 typename VectorType,
1198 std::enable_if_t<!has_Tvmult<MatrixType, VectorType>, MatrixType>
1201 Tvmult(
const MatrixType &, VectorType &,
const VectorType &)
1204 ExcMessage(
"Matrix A does not provide a Tvmult() function!"));
1208 typename MatrixType,
1209 typename PreconditionerType,
1210 typename VectorType,
1211 std::enable_if_t<!has_Tstep_omega<PreconditionerType, VectorType> &&
1212 !has_Tstep<PreconditionerType, VectorType>,
1213 PreconditionerType> * =
nullptr>
1215 Tstep(
const MatrixType &A,
1216 const PreconditionerType &preconditioner,
1218 const VectorType &src,
1219 const double relaxation,
1220 VectorType &residual,
1223 residual.reinit(dst,
true);
1224 tmp.reinit(dst,
true);
1226 Tvmult(A, residual, dst);
1227 residual.sadd(-1.0, 1.0, src);
1229 Tvmult(preconditioner, tmp, residual);
1230 dst.add(relaxation, tmp);
1234 template <
typename MatrixType,
1235 typename PreconditionerType,
1236 typename VectorType,
1237 std::enable_if_t<!has_vmult_with_std_functions_for_precondition<
1242 step_operations(
const MatrixType &A,
1243 const PreconditionerType &preconditioner,
1245 const VectorType &src,
1246 const double relaxation,
1249 const unsigned int i,
1250 const bool transposed)
1255 Tvmult(preconditioner, dst, src);
1257 preconditioner.vmult(dst, src);
1259 if (relaxation != 1.0)
1265 Tstep(A, preconditioner, dst, src, relaxation, tmp1, tmp2);
1267 step(A, preconditioner, dst, src, relaxation, tmp1, tmp2);
1274 typename MatrixType,
1275 typename PreconditionerType,
1276 typename VectorType,
1278 has_vmult_with_std_functions_for_precondition<PreconditionerType,
1280 !has_vmult_with_std_functions_for_precondition<MatrixType,
1284 step_operations(
const MatrixType &A,
1285 const PreconditionerType &preconditioner,
1287 const VectorType &src,
1288 const double relaxation,
1291 const unsigned int i,
1292 const bool transposed)
1295 using Number =
typename VectorType::value_type;
1299 Number *dst_ptr = dst.begin();
1300 const Number *src_ptr = src.begin();
1302 preconditioner.vmult(
1305 [&](
const unsigned int start_range,
const unsigned int end_range) {
1307 if (end_range > start_range)
1308 std::memset(dst.begin() + start_range,
1310 sizeof(Number) * (end_range - start_range));
1312 [&](
const unsigned int start_range,
const unsigned int end_range) {
1313 if (relaxation == 1.0)
1316 const auto src_ptr = src.begin();
1317 const auto dst_ptr = dst.begin();
1320 for (std::size_t i = start_range; i < end_range; ++i)
1321 dst_ptr[i] *= relaxation;
1326 tmp.reinit(src,
true);
1332 preconditioner.vmult(
1335 [&](
const unsigned int start_range,
const unsigned int end_range) {
1336 const auto src_ptr = src.begin();
1337 const auto tmp_ptr = tmp.begin();
1339 if (relaxation == 1.0)
1342 for (std::size_t i = start_range; i < end_range; ++i)
1343 tmp_ptr[i] = src_ptr[i] - tmp_ptr[i];
1351 for (std::size_t i = start_range; i < end_range; ++i)
1352 tmp_ptr[i] = relaxation * (src_ptr[i] - tmp_ptr[i]);
1355 [&](
const unsigned int,
const unsigned int) {
1365 typename MatrixType,
1366 typename PreconditionerType,
1367 typename VectorType,
1369 has_vmult_with_std_functions_for_precondition<PreconditionerType,
1371 has_vmult_with_std_functions_for_precondition<MatrixType, VectorType>,
1374 step_operations(
const MatrixType &A,
1375 const PreconditionerType &preconditioner,
1377 const VectorType &src,
1378 const double relaxation,
1381 const unsigned int i,
1382 const bool transposed)
1385 using Number =
typename VectorType::value_type;
1389 Number *dst_ptr = dst.begin();
1390 const Number *src_ptr = src.begin();
1392 preconditioner.vmult(
1395 [&](
const unsigned int start_range,
const unsigned int end_range) {
1397 if (end_range > start_range)
1398 std::memset(dst.begin() + start_range,
1400 sizeof(Number) * (end_range - start_range));
1402 [&](
const unsigned int start_range,
const unsigned int end_range) {
1403 if (relaxation == 1.0)
1406 const auto src_ptr = src.begin();
1407 const auto dst_ptr = dst.begin();
1410 for (std::size_t i = start_range; i < end_range; ++i)
1411 dst_ptr[i] *= relaxation;
1416 tmp.reinit(src,
true);
1423 [&](
const unsigned int start_range,
const unsigned int end_range) {
1426 if (end_range > start_range)
1427 std::memset(tmp.begin() + start_range,
1429 sizeof(Number) * (end_range - start_range));
1431 [&](
const unsigned int start_range,
const unsigned int end_range) {
1432 const auto src_ptr = src.begin();
1433 const auto tmp_ptr = tmp.begin();
1435 if (relaxation == 1.0)
1438 for (std::size_t i = start_range; i < end_range; ++i)
1439 tmp_ptr[i] = src_ptr[i] - tmp_ptr[i];
1447 for (std::size_t i = start_range; i < end_range; ++i)
1448 tmp_ptr[i] = relaxation * (src_ptr[i] - tmp_ptr[i]);
1452 preconditioner.vmult(dst, tmp, [](
const auto,
const auto) {
1460 template <
typename MatrixType,
1461 typename VectorType,
1462 std::enable_if_t<!IsBlockVector<VectorType>::value &&
1463 !has_vmult_with_std_functions<
1467 VectorType> * =
nullptr>
1469 step_operations(
const MatrixType &A,
1470 const ::DiagonalMatrix<VectorType> &preconditioner,
1472 const VectorType &src,
1473 const double relaxation,
1476 const unsigned int i,
1477 const bool transposed)
1479 using Number =
typename VectorType::value_type;
1483 Number *dst_ptr = dst.begin();
1484 const Number *src_ptr = src.begin();
1485 const Number *diag_ptr = preconditioner.get_vector().begin();
1487 if (relaxation == 1.0)
1490 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1491 dst_ptr[i] = src_ptr[i] * diag_ptr[i];
1496 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1497 dst_ptr[i] = relaxation * src_ptr[i] * diag_ptr[i];
1502 tmp.reinit(src,
true);
1504 Number *dst_ptr = dst.begin();
1505 const Number *src_ptr = src.begin();
1506 const Number *tmp_ptr = tmp.begin();
1507 const Number *diag_ptr = preconditioner.get_vector().begin();
1510 Tvmult(A, tmp, dst);
1514 if (relaxation == 1.0)
1517 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1518 dst_ptr[i] += (src_ptr[i] - tmp_ptr[i]) * diag_ptr[i];
1523 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1525 relaxation * (src_ptr[i] - tmp_ptr[i]) * diag_ptr[i];
1532 template <
typename MatrixType,
1533 typename VectorType,
1534 std::enable_if_t<!IsBlockVector<VectorType>::value &&
1535 has_vmult_with_std_functions<
1539 VectorType> * =
nullptr>
1541 step_operations(
const MatrixType &A,
1542 const ::DiagonalMatrix<VectorType> &preconditioner,
1544 const VectorType &src,
1545 const double relaxation,
1548 const unsigned int i,
1549 const bool transposed)
1552 using Number =
typename VectorType::value_type;
1556 Number *dst_ptr = dst.begin();
1557 const Number *src_ptr = src.begin();
1558 const Number *diag_ptr = preconditioner.get_vector().begin();
1560 if (relaxation == 1.0)
1563 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1564 dst_ptr[i] = src_ptr[i] * diag_ptr[i];
1569 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1570 dst_ptr[i] = relaxation * src_ptr[i] * diag_ptr[i];
1575 tmp.reinit(src,
true);
1582 [&](
const unsigned int start_range,
const unsigned int end_range) {
1584 if (end_range > start_range)
1585 std::memset(tmp.begin() + start_range,
1587 sizeof(Number) * (end_range - start_range));
1589 [&](
const unsigned int begin,
const unsigned int end) {
1590 const Number *dst_ptr = dst.begin();
1591 const Number *src_ptr = src.begin();
1592 Number *tmp_ptr = tmp.begin();
1593 const Number *diag_ptr = preconditioner.get_vector().begin();
1597 if (relaxation == 1.0)
1600 for (std::size_t i = begin; i < end; ++i)
1602 dst_ptr[i] + (src_ptr[i] - tmp_ptr[i]) * diag_ptr[i];
1607 for (std::size_t i = begin; i < end; ++i)
1608 tmp_ptr[i] = dst_ptr[i] + relaxation *
1609 (src_ptr[i] - tmp_ptr[i]) *
1651template <
typename MatrixType = SparseMatrix<
double>>
1655 internal::PreconditionRelaxation::PreconditionJacobiImpl<MatrixType>>
1658 internal::PreconditionRelaxation::PreconditionJacobiImpl<MatrixType>;
1721template <
typename MatrixType = SparseMatrix<
double>>
1725 internal::PreconditionRelaxation::PreconditionSORImpl<MatrixType>>
1728 internal::PreconditionRelaxation::PreconditionSORImpl<MatrixType>;
1773template <
typename MatrixType = SparseMatrix<
double>>
1777 internal::PreconditionRelaxation::PreconditionSSORImpl<MatrixType>>
1780 internal::PreconditionRelaxation::PreconditionSSORImpl<MatrixType>;
1829template <
typename MatrixType = SparseMatrix<
double>>
1833 internal::PreconditionRelaxation::PreconditionPSORImpl<MatrixType>>
1836 internal::PreconditionRelaxation::PreconditionPSORImpl<MatrixType>;
1893 const std::vector<size_type> &permutation,
1894 const std::vector<size_type> &inverse_permutation,
2101template <
typename MatrixType = SparseMatrix<
double>,
2102 typename VectorType = Vector<
double>,
2103 typename PreconditionerType = DiagonalMatrix<VectorType>>
2141 const unsigned int degree = 1,
2147 EigenvalueAlgorithm::lanczos,
2196 vmult(VectorType &dst,
const VectorType &src)
const;
2203 Tvmult(VectorType &dst,
const VectorType &src)
const;
2209 step(VectorType &dst,
const VectorType &src)
const;
2215 Tstep(VectorType &dst,
const VectorType &src)
const;
2318 template <
typename VectorType>
2320 set_initial_guess(VectorType &vector)
2322 vector = 1. /
std::sqrt(
static_cast<double>(vector.size()));
2323 if (vector.locally_owned_elements().is_element(0))
2327 template <
typename Number>
2335 for (
unsigned int i = 0; i < vector.
size(); ++i)
2338 const Number mean_value = vector.
mean_value();
2339 vector.
add(-mean_value);
2342 template <
typename Number>
2347 for (
unsigned int block = 0; block < vector.
n_blocks(); ++block)
2348 set_initial_guess(vector.
block(block));
2351 template <
typename Number,
typename MemorySpace>
2368 Kokkos::RangePolicy<
typename MemorySpace::kokkos_space::execution_space,
2369 Kokkos::IndexType<types::global_dof_index>>
2370 policy(0, n_local_elements);
2371 Kokkos::parallel_for(
2372 "::PreconditionChebyshev::set_initial_guess",
2375 values_ptr[i] = (i + first_local_range) % 11;
2377 const Number mean_value = vector.
mean_value();
2378 vector.
add(-mean_value);
2381 struct EigenvalueTracker
2390 std::vector<double> values;
2395 template <
typename MatrixType,
2396 typename VectorType,
2397 typename PreconditionerType>
2400 VectorType &eigenvector,
2401 const PreconditionerType &preconditioner,
2402 const unsigned int n_iterations)
2404 typename VectorType::value_type eigenvalue_estimate = 0.;
2405 eigenvector /= eigenvector.l2_norm();
2406 VectorType vector1, vector2;
2407 vector1.reinit(eigenvector,
true);
2408 if (!std::is_same_v<PreconditionerType, PreconditionIdentity>)
2409 vector2.reinit(eigenvector,
true);
2410 for (
unsigned int i = 0; i < n_iterations; ++i)
2412 if (!std::is_same_v<PreconditionerType, PreconditionIdentity>)
2414 matrix.vmult(vector2, eigenvector);
2415 preconditioner.vmult(vector1, vector2);
2418 matrix.vmult(vector1, eigenvector);
2420 eigenvalue_estimate = eigenvector * vector1;
2422 vector1 /= vector1.l2_norm();
2423 eigenvector.swap(vector1);
2425 return std::abs(eigenvalue_estimate);
2430 template <
typename MatrixType,
2431 typename VectorType,
2432 typename PreconditionerType>
2433 EigenvalueInformation
2434 estimate_eigenvalues(
2435 const EigenvalueAlgorithmAdditionalData<PreconditionerType> &data,
2436 const MatrixType *matrix_ptr,
2437 VectorType &solution_old,
2438 VectorType &temp_vector1,
2439 const unsigned int degree)
2443 EigenvalueInformation info{};
2445 if (data.eig_cg_n_iterations > 0)
2447 Assert(data.eig_cg_n_iterations > 2,
2449 "Need to set at least two iterations to find eigenvalues."));
2451 internal::EigenvalueTracker eigenvalue_tracker;
2456 internal::set_initial_guess(temp_vector1);
2457 data.constraints.set_zero(temp_vector1);
2468 solver.connect_eigenvalues_slot(
2469 [&eigenvalue_tracker](
const std::vector<double> &
eigenvalues) {
2473 solver.solve(*matrix_ptr,
2476 *data.preconditioner);
2478 info.cg_iterations = control.last_step();
2480 else if (data.eigenvalue_algorithm ==
2486 ExcMessage(
"Cannot estimate the minimal eigenvalue with the "
2487 "power iteration"));
2489 eigenvalue_tracker.values.push_back(
2492 *data.preconditioner,
2493 data.eig_cg_n_iterations));
2499 if (eigenvalue_tracker.values.empty())
2500 info.min_eigenvalue_estimate = info.max_eigenvalue_estimate = 1.;
2503 info.min_eigenvalue_estimate = eigenvalue_tracker.values.front();
2507 info.max_eigenvalue_estimate =
2508 1.2 * eigenvalue_tracker.values.back();
2513 info.max_eigenvalue_estimate = data.max_eigenvalue;
2514 info.min_eigenvalue_estimate =
2515 data.max_eigenvalue / data.smoothing_range;
2529template <
typename MatrixType>
2539template <
typename VectorType>
2548template <
typename VectorType>
2555template <
typename VectorType>
2564template <
typename VectorType>
2596 const double relaxation)
2597 : relaxation(relaxation)
2606 AdditionalData add_data;
2607 relaxation = add_data.relaxation;
2621template <
typename MatrixType>
2624 const MatrixType &matrix,
2634template <
typename VectorType>
2639 std::is_same_v<size_type, typename VectorType::size_type>,
2640 "PreconditionRichardson and VectorType must have the same size_type.");
2647template <
typename VectorType>
2652 std::is_same_v<size_type, typename VectorType::size_type>,
2653 "PreconditionRichardson and VectorType must have the same size_type.");
2658template <
typename VectorType>
2663 std::is_same_v<size_type, typename VectorType::size_type>,
2664 "PreconditionRichardson and VectorType must have the same size_type.");
2671template <
typename VectorType>
2676 std::is_same_v<size_type, typename VectorType::size_type>,
2677 "PreconditionRichardson and VectorType must have the same size_type.");
2698template <
typename MatrixType,
typename PreconditionerType>
2701 const MatrixType &rA,
2702 const AdditionalData ¶meters)
2705 eigenvalues_are_initialized =
false;
2709 this->data = parameters;
2713template <
typename MatrixType,
typename PreconditionerType>
2717 eigenvalues_are_initialized =
false;
2719 data.relaxation = 1.0;
2720 data.preconditioner =
nullptr;
2723template <
typename MatrixType,
typename PreconditionerType>
2732template <
typename MatrixType,
typename PreconditionerType>
2741template <
typename MatrixType,
typename PreconditionerType>
2742template <
typename VectorType>
2746 const VectorType &src)
const
2751 if (eigenvalues_are_initialized ==
false)
2752 estimate_eigenvalues(src);
2754 VectorType tmp1, tmp2;
2756 for (
unsigned int i = 0; i < data.n_iterations; ++i)
2757 internal::PreconditionRelaxation::step_operations(*A,
2758 *data.preconditioner,
2768template <
typename MatrixType,
typename PreconditionerType>
2769template <
typename VectorType>
2773 const VectorType &src)
const
2778 if (eigenvalues_are_initialized ==
false)
2779 estimate_eigenvalues(src);
2781 VectorType tmp1, tmp2;
2783 for (
unsigned int i = 0; i < data.n_iterations; ++i)
2784 internal::PreconditionRelaxation::step_operations(
2785 *A, *data.preconditioner, dst, src, data.relaxation, tmp1, tmp2, i,
true);
2788template <
typename MatrixType,
typename PreconditionerType>
2789template <
typename VectorType>
2793 const VectorType &src)
const
2798 if (eigenvalues_are_initialized ==
false)
2799 estimate_eigenvalues(src);
2801 VectorType tmp1, tmp2;
2803 for (
unsigned int i = 1; i <= data.n_iterations; ++i)
2804 internal::PreconditionRelaxation::step_operations(*A,
2805 *data.preconditioner,
2815template <
typename MatrixType,
typename PreconditionerType>
2816template <
typename VectorType>
2820 const VectorType &src)
const
2825 if (eigenvalues_are_initialized ==
false)
2826 estimate_eigenvalues(src);
2828 VectorType tmp1, tmp2;
2830 for (
unsigned int i = 1; i <= data.n_iterations; ++i)
2831 internal::PreconditionRelaxation::step_operations(
2832 *A, *data.preconditioner, dst, src, data.relaxation, tmp1, tmp2, i,
true);
2835template <
typename MatrixType,
typename PreconditionerType>
2836template <
typename VectorType>
2839 const VectorType &src)
const
2843 EigenvalueInformation info;
2845 if (data.relaxation == 0.0)
2847 VectorType solution_old, temp_vector1;
2849 solution_old.reinit(src);
2850 temp_vector1.reinit(src,
true);
2852 info = internal::estimate_eigenvalues<MatrixType>(
2853 data, A, solution_old, temp_vector1, data.n_iterations);
2855 const double alpha =
2856 (data.smoothing_range > 1. ?
2857 info.max_eigenvalue_estimate / data.smoothing_range :
2858 std::min(0.9 * info.max_eigenvalue_estimate,
2859 info.min_eigenvalue_estimate));
2862 ->data.relaxation = 2.0 / (alpha + info.max_eigenvalue_estimate);
2866 ->eigenvalues_are_initialized =
true;
2871template <
typename MatrixType,
typename PreconditionerType>
2875 return data.relaxation;
2881template <
typename MatrixType>
2884 const AdditionalData ¶meters_in)
2888 parameters_in.relaxation != 0.0,
2890 "Relaxation cannot automatically be determined by PreconditionJacobi."));
2892 AdditionalData parameters;
2893 parameters.relaxation = 1.0;
2894 parameters.n_iterations = parameters_in.n_iterations;
2895 parameters.preconditioner =
2896 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
2898 this->BaseClass::initialize(A, parameters);
2903template <
typename MatrixType>
2906 const AdditionalData ¶meters_in)
2910 parameters_in.relaxation != 0.0,
2912 "Relaxation cannot automatically be determined by PreconditionSOR."));
2914 AdditionalData parameters;
2915 parameters.relaxation = 1.0;
2916 parameters.n_iterations = parameters_in.n_iterations;
2917 parameters.preconditioner =
2918 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
2920 this->BaseClass::initialize(A, parameters);
2925template <
typename MatrixType>
2928 const AdditionalData ¶meters_in)
2932 parameters_in.relaxation != 0.0,
2934 "Relaxation cannot automatically be determined by PreconditionSSOR."));
2936 AdditionalData parameters;
2937 parameters.relaxation = 1.0;
2938 parameters.n_iterations = parameters_in.n_iterations;
2939 parameters.preconditioner =
2940 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
2942 this->BaseClass::initialize(A, parameters);
2949template <
typename MatrixType>
2952 const MatrixType &A,
2953 const std::vector<size_type> &p,
2954 const std::vector<size_type> &ip,
2955 const typename BaseClass::AdditionalData ¶meters_in)
2959 parameters_in.relaxation != 0.0,
2961 "Relaxation cannot automatically be determined by PreconditionPSOR."));
2963 typename BaseClass::AdditionalData parameters;
2964 parameters.relaxation = 1.0;
2965 parameters.n_iterations = parameters_in.n_iterations;
2966 parameters.preconditioner =
2967 std::make_shared<PreconditionerType>(A, parameters_in.relaxation, p, ip);
2969 this->BaseClass::initialize(A, parameters);
2973template <
typename MatrixType>
2976 const AdditionalData &additional_data)
2979 additional_data.permutation,
2980 additional_data.inverse_permutation,
2981 additional_data.parameters);
2984template <
typename MatrixType>
2986 const std::vector<size_type> &permutation,
2987 const std::vector<size_type> &inverse_permutation,
2990 : permutation(permutation)
2991 , inverse_permutation(inverse_permutation)
2992 , parameters(parameters)
2999template <
typename MatrixType,
typename VectorType>
3001 const MatrixType &M,
3002 const function_ptr method)
3004 , precondition(method)
3009template <
typename MatrixType,
typename VectorType>
3013 const VectorType &src)
const
3015 (
matrix.*precondition)(dst, src);
3023 template <
typename PreconditionerType>
3026 const double smoothing_range,
3027 const unsigned int eig_cg_n_iterations,
3028 const double eig_cg_residual,
3029 const double max_eigenvalue,
3030 const EigenvalueAlgorithm eigenvalue_algorithm)
3031 : smoothing_range(smoothing_range)
3032 , eig_cg_n_iterations(eig_cg_n_iterations)
3033 , eig_cg_residual(eig_cg_residual)
3034 , max_eigenvalue(max_eigenvalue)
3035 , eigenvalue_algorithm(eigenvalue_algorithm)
3040 template <
typename PreconditionerType>
3041 inline EigenvalueAlgorithmAdditionalData<PreconditionerType> &
3042 EigenvalueAlgorithmAdditionalData<PreconditionerType>::operator=(
3043 const EigenvalueAlgorithmAdditionalData &other_data)
3045 smoothing_range = other_data.smoothing_range;
3046 eig_cg_n_iterations = other_data.eig_cg_n_iterations;
3047 eig_cg_residual = other_data.eig_cg_residual;
3048 max_eigenvalue = other_data.max_eigenvalue;
3049 preconditioner = other_data.preconditioner;
3050 eigenvalue_algorithm = other_data.eigenvalue_algorithm;
3051 constraints.copy_from(other_data.constraints);
3057template <
typename MatrixType,
typename PreconditionerType>
3060 const unsigned int n_iterations,
3061 const double smoothing_range,
3062 const unsigned int eig_cg_n_iterations,
3063 const double eig_cg_residual,
3064 const double max_eigenvalue,
3065 const EigenvalueAlgorithm eigenvalue_algorithm)
3066 :
internal::EigenvalueAlgorithmAdditionalData<PreconditionerType>(
3068 eig_cg_n_iterations,
3071 eigenvalue_algorithm)
3072 , relaxation(relaxation)
3073 , n_iterations(n_iterations)
3082 namespace PreconditionChebyshevImplementation
3090 template <
typename VectorType,
typename PreconditionerType>
3092 vector_updates(
const VectorType &rhs,
3093 const PreconditionerType &preconditioner,
3094 const unsigned int iteration_index,
3095 const double factor1,
3096 const double factor2,
3097 VectorType &solution_old,
3098 VectorType &temp_vector1,
3099 VectorType &temp_vector2,
3100 VectorType &solution)
3102 if (iteration_index == 0)
3104 solution.equ(factor2, rhs);
3105 preconditioner.vmult(solution_old, solution);
3107 else if (iteration_index == 1)
3110 temp_vector1.sadd(-1.0, 1.0, rhs);
3111 preconditioner.vmult(solution_old, temp_vector1);
3114 solution_old.sadd(factor2, 1 + factor1, solution);
3119 temp_vector1.sadd(-1.0, 1.0, rhs);
3120 preconditioner.vmult(temp_vector2, temp_vector1);
3123 solution_old.sadd(-factor1, factor2, temp_vector2);
3124 solution_old.add(1 + factor1, solution);
3127 solution.swap(solution_old);
3133 typename PreconditionerType,
3135 !has_vmult_with_std_functions_for_precondition<
3142 const PreconditionerType &preconditioner,
3143 const unsigned int iteration_index,
3144 const double factor1_,
3145 const double factor2_,
3154 const Number factor1 = factor1_;
3155 const Number factor1_plus_1 = 1. + factor1_;
3156 const Number factor2 = factor2_;
3158 if (iteration_index == 0)
3160 const auto solution_old_ptr = solution_old.
begin();
3163 preconditioner.vmult(solution_old, rhs);
3168 solution_old_ptr[i] = solution_old_ptr[i] * factor2;
3170 else if (iteration_index == 1)
3172 const auto solution_ptr = solution.
begin();
3173 const auto solution_old_ptr = solution_old.
begin();
3176 temp_vector1.
sadd(-1.0, 1.0, rhs);
3178 preconditioner.vmult(solution_old, temp_vector1);
3183 solution_old_ptr[i] =
3184 factor1_plus_1 * solution_ptr[i] + solution_old_ptr[i] * factor2;
3188 const auto solution_ptr = solution.
begin();
3189 const auto solution_old_ptr = solution_old.
begin();
3190 const auto temp_vector2_ptr = temp_vector2.
begin();
3193 temp_vector1.
sadd(-1.0, 1.0, rhs);
3195 preconditioner.vmult(temp_vector2, temp_vector1);
3200 solution_old_ptr[i] = factor1_plus_1 * solution_ptr[i] -
3201 factor1 * solution_old_ptr[i] +
3202 temp_vector2_ptr[i] * factor2;
3205 solution.
swap(solution_old);
3210 typename PreconditionerType,
3212 has_vmult_with_std_functions_for_precondition<
3219 const PreconditionerType &preconditioner,
3220 const unsigned int iteration_index,
3221 const double factor1_,
3222 const double factor2_,
3231 const Number factor1 = factor1_;
3232 const Number factor1_plus_1 = 1. + factor1_;
3233 const Number factor2 = factor2_;
3235 const auto rhs_ptr = rhs.
begin();
3236 const auto temp_vector1_ptr = temp_vector1.
begin();
3237 const auto temp_vector2_ptr = temp_vector2.
begin();
3238 const auto solution_ptr = solution.
begin();
3239 const auto solution_old_ptr = solution_old.
begin();
3241 if (iteration_index == 0)
3243 preconditioner.vmult(
3246 [&](
const auto start_range,
const auto end_range) {
3247 if (end_range > start_range)
3248 std::memset(solution.
begin() + start_range,
3250 sizeof(Number) * (end_range - start_range));
3252 [&](
const auto begin,
const auto end) {
3254 for (std::size_t i = begin; i <
end; ++i)
3255 solution_ptr[i] *= factor2;
3260 preconditioner.vmult(
3263 [&](
const auto begin,
const auto end) {
3265 std::memset(temp_vector2.
begin() + begin,
3267 sizeof(Number) * (end - begin));
3270 for (std::size_t i = begin; i <
end; ++i)
3271 temp_vector1_ptr[i] = rhs_ptr[i] - temp_vector1_ptr[i];
3273 [&](
const auto begin,
const auto end) {
3274 if (iteration_index == 1)
3277 for (std::size_t i = begin; i <
end; ++i)
3278 temp_vector2_ptr[i] = factor1_plus_1 * solution_ptr[i] +
3279 factor2 * temp_vector2_ptr[i];
3284 for (std::size_t i = begin; i <
end; ++i)
3285 temp_vector2_ptr[i] = factor1_plus_1 * solution_ptr[i] -
3286 factor1 * solution_old_ptr[i] +
3287 factor2 * temp_vector2_ptr[i];
3292 if (iteration_index > 0)
3294 solution_old.
swap(temp_vector2);
3295 solution_old.
swap(solution);
3302 template <
typename Number>
3303 struct VectorUpdater
3305 VectorUpdater(
const Number *rhs,
3306 const Number *matrix_diagonal_inverse,
3307 const unsigned int iteration_index,
3308 const Number factor1,
3309 const Number factor2,
3310 Number *solution_old,
3314 , matrix_diagonal_inverse(matrix_diagonal_inverse)
3315 , iteration_index(iteration_index)
3318 , solution_old(solution_old)
3319 , tmp_vector(tmp_vector)
3320 , solution(solution)
3324 apply_to_subrange(
const std::size_t begin,
const std::size_t end)
const
3330 const Number factor1 = this->factor1;
3331 const Number factor1_plus_1 = 1. + this->factor1;
3332 const Number factor2 = this->factor2;
3333 if (iteration_index == 0)
3336 for (std::size_t i = begin; i <
end; ++i)
3337 solution[i] = factor2 * matrix_diagonal_inverse[i] * rhs[i];
3339 else if (iteration_index == 1)
3343 for (std::size_t i = begin; i <
end; ++i)
3347 factor1_plus_1 * solution[i] +
3348 factor2 * matrix_diagonal_inverse[i] * (rhs[i] - tmp_vector[i]);
3355 for (std::size_t i = begin; i <
end; ++i)
3362 factor1_plus_1 * solution[i] - factor1 * solution_old[i] +
3363 factor2 * matrix_diagonal_inverse[i] * (rhs[i] - tmp_vector[i]);
3368 const Number *matrix_diagonal_inverse;
3369 const unsigned int iteration_index;
3370 const Number factor1;
3371 const Number factor2;
3372 mutable Number *solution_old;
3373 mutable Number *tmp_vector;
3374 mutable Number *solution;
3377 template <
typename Number>
3380 VectorUpdatesRange(
const VectorUpdater<Number> &updater,
3381 const std::size_t size)
3385 VectorUpdatesRange::apply_to_subrange(0, size);
3393 ~VectorUpdatesRange()
override =
default;
3396 apply_to_subrange(
const std::size_t begin,
3397 const std::size_t end)
const override
3399 updater.apply_to_subrange(begin, end);
3402 const VectorUpdater<Number> &updater;
3406 template <
typename Number>
3409 const ::Vector<Number> &rhs,
3411 const unsigned int iteration_index,
3412 const double factor1,
3413 const double factor2,
3419 VectorUpdater<Number> upd(rhs.begin(),
3420 jacobi.get_vector().begin(),
3424 solution_old.
begin(),
3425 temp_vector1.
begin(),
3427 VectorUpdatesRange<Number>(upd, rhs.size());
3430 if (iteration_index == 0)
3437 solution.
swap(temp_vector1);
3438 solution_old.
swap(temp_vector1);
3443 template <
typename Number>
3447 const ::DiagonalMatrix<
3449 const unsigned int iteration_index,
3450 const double factor1,
3451 const double factor2,
3459 VectorUpdater<Number> upd(rhs.
begin(),
3460 jacobi.get_vector().begin(),
3464 solution_old.
begin(),
3465 temp_vector1.
begin(),
3470 if (iteration_index == 0)
3477 solution.
swap(temp_vector1);
3478 solution_old.
swap(temp_vector1);
3487 typename MatrixType,
3488 typename VectorType,
3489 typename PreconditionerType,
3491 !has_vmult_with_std_functions<MatrixType,
3493 PreconditionerType> &&
3494 !(has_vmult_with_std_functions_for_precondition<PreconditionerType,
3496 has_vmult_with_std_functions_for_precondition<MatrixType,
3500 vmult_and_update(
const MatrixType &matrix,
3501 const PreconditionerType &preconditioner,
3502 const VectorType &rhs,
3503 const unsigned int iteration_index,
3504 const double factor1,
3505 const double factor2,
3506 VectorType &solution,
3507 VectorType &solution_old,
3508 VectorType &temp_vector1,
3509 VectorType &temp_vector2)
3511 if (iteration_index > 0)
3512 matrix.vmult(temp_vector1, solution);
3527 typename MatrixType,
3528 typename VectorType,
3529 typename PreconditionerType,
3531 !has_vmult_with_std_functions<MatrixType,
3533 PreconditionerType> &&
3534 (has_vmult_with_std_functions_for_precondition<PreconditionerType,
3536 has_vmult_with_std_functions_for_precondition<MatrixType,
3540 vmult_and_update(
const MatrixType &matrix,
3541 const PreconditionerType &preconditioner,
3542 const VectorType &rhs,
3543 const unsigned int iteration_index,
3544 const double factor1_,
3545 const double factor2_,
3546 VectorType &solution,
3547 VectorType &solution_old,
3548 VectorType &temp_vector1,
3549 VectorType &temp_vector2)
3551 using Number =
typename VectorType::value_type;
3553 const Number factor1 = factor1_;
3554 const Number factor1_plus_1 = 1. + factor1_;
3555 const Number factor2 = factor2_;
3557 if (iteration_index == 0)
3559 preconditioner.vmult(
3562 [&](
const unsigned int start_range,
const unsigned int end_range) {
3564 if (end_range > start_range)
3565 std::memset(solution.begin() + start_range,
3567 sizeof(Number) * (end_range - start_range));
3569 [&](
const unsigned int start_range,
const unsigned int end_range) {
3570 const auto solution_ptr = solution.begin();
3573 for (std::size_t i = start_range; i < end_range; ++i)
3574 solution_ptr[i] *= factor2;
3579 temp_vector1.reinit(rhs,
true);
3580 temp_vector2.reinit(rhs,
true);
3586 [&](
const unsigned int start_range,
const unsigned int end_range) {
3589 if (end_range > start_range)
3590 std::memset(temp_vector1.begin() + start_range,
3592 sizeof(Number) * (end_range - start_range));
3594 [&](
const unsigned int start_range,
const unsigned int end_range) {
3595 const auto rhs_ptr = rhs.begin();
3596 const auto tmp_ptr = temp_vector1.begin();
3599 for (std::size_t i = start_range; i < end_range; ++i)
3600 tmp_ptr[i] = rhs_ptr[i] - tmp_ptr[i];
3604 preconditioner.vmult(
3607 [&](
const unsigned int start_range,
const unsigned int end_range) {
3610 if (end_range > start_range)
3611 std::memset(temp_vector2.begin() + start_range,
3613 sizeof(Number) * (end_range - start_range));
3615 [&](
const unsigned int start_range,
const unsigned int end_range) {
3616 const auto solution_ptr = solution.begin();
3617 const auto solution_old_ptr = solution_old.begin();
3618 const auto tmp_ptr = temp_vector2.begin();
3620 if (iteration_index == 1)
3623 for (std::size_t i = start_range; i < end_range; ++i)
3625 factor1_plus_1 * solution_ptr[i] + factor2 * tmp_ptr[i];
3630 for (std::size_t i = start_range; i < end_range; ++i)
3631 tmp_ptr[i] = factor1_plus_1 * solution_ptr[i] -
3632 factor1 * solution_old_ptr[i] +
3633 factor2 * tmp_ptr[i];
3637 solution.swap(temp_vector2);
3638 solution_old.swap(temp_vector2);
3644 template <
typename MatrixType,
3645 typename VectorType,
3646 typename PreconditionerType,
3647 std::enable_if_t<has_vmult_with_std_functions<MatrixType,
3649 PreconditionerType>,
3652 vmult_and_update(
const MatrixType &matrix,
3653 const PreconditionerType &preconditioner,
3654 const VectorType &rhs,
3655 const unsigned int iteration_index,
3656 const double factor1,
3657 const double factor2,
3658 VectorType &solution,
3659 VectorType &solution_old,
3660 VectorType &temp_vector1,
3663 using Number =
typename VectorType::value_type;
3664 VectorUpdater<Number> updater(rhs.begin(),
3665 preconditioner.get_vector().begin(),
3669 solution_old.begin(),
3670 temp_vector1.begin(),
3672 if (iteration_index > 0)
3676 [&](
const unsigned int start_range,
const unsigned int end_range) {
3679 if (end_range > start_range)
3680 std::memset(temp_vector1.begin() + start_range,
3682 sizeof(Number) * (end_range - start_range));
3684 [&](
const unsigned int start_range,
const unsigned int end_range) {
3685 if (end_range > start_range)
3686 updater.apply_to_subrange(start_range, end_range);
3689 updater.apply_to_subrange(0U, solution.locally_owned_size());
3692 if (iteration_index == 0)
3699 solution.swap(temp_vector1);
3700 solution_old.swap(temp_vector1);
3704 template <
typename MatrixType,
typename PreconditionerType>
3706 initialize_preconditioner(
3707 const MatrixType &matrix,
3708 std::shared_ptr<PreconditionerType> &preconditioner)
3711 (void)preconditioner;
3715 template <
typename MatrixType,
typename VectorType>
3717 initialize_preconditioner(
3718 const MatrixType &matrix,
3721 if (preconditioner.get() ==
nullptr || preconditioner->m() !=
matrix.m())
3723 if (preconditioner.get() ==
nullptr)
3725 std::make_shared<::DiagonalMatrix<VectorType>>();
3728 preconditioner->m() == 0,
3730 "Preconditioner appears to be initialized but not sized correctly"));
3733 if (preconditioner->m() !=
matrix.m())
3735 preconditioner->get_vector().reinit(
matrix.m());
3736 for (
typename VectorType::size_type i = 0; i <
matrix.m(); ++i)
3737 preconditioner->get_vector()(i) = 1. /
matrix.el(i, i);
3746template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3749 const double smoothing_range,
3750 const unsigned int eig_cg_n_iterations,
3751 const double eig_cg_residual,
3752 const double max_eigenvalue,
3753 const EigenvalueAlgorithm eigenvalue_algorithm,
3754 const PolynomialType polynomial_type)
3755 :
internal::EigenvalueAlgorithmAdditionalData<PreconditionerType>(
3757 eig_cg_n_iterations,
3760 eigenvalue_algorithm)
3762 , polynomial_type(polynomial_type)
3767template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3772 , eigenvalues_are_initialized(false)
3775 std::is_same_v<size_type, typename VectorType::size_type>,
3776 "PreconditionChebyshev and VectorType must have the same size_type.");
3781template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3784 const MatrixType &matrix,
3785 const AdditionalData &additional_data)
3788 data = additional_data;
3790 ExcMessage(
"The degree of the Chebyshev method must be positive."));
3791 internal::PreconditionChebyshevImplementation::initialize_preconditioner(
3792 matrix, data.preconditioner);
3793 eigenvalues_are_initialized =
false;
3798template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3802 eigenvalues_are_initialized =
false;
3803 theta = delta = 1.0;
3804 matrix_ptr =
nullptr;
3806 VectorType empty_vector;
3807 solution_old.reinit(empty_vector);
3808 temp_vector1.reinit(empty_vector);
3809 temp_vector2.reinit(empty_vector);
3811 data.preconditioner.reset();
3816template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3823 solution_old.reinit(src);
3824 temp_vector1.reinit(src,
true);
3826 auto info = internal::estimate_eigenvalues<MatrixType>(
3827 data, matrix_ptr, solution_old, temp_vector1, data.degree);
3829 const double alpha = (data.smoothing_range > 1. ?
3830 info.max_eigenvalue_estimate / data.smoothing_range :
3831 std::min(0.9 * info.max_eigenvalue_estimate,
3832 info.min_eigenvalue_estimate));
3841 const double actual_range = info.max_eigenvalue_estimate / alpha;
3842 const double sigma = (1. -
std::sqrt(1. / actual_range)) /
3844 const double eps = data.smoothing_range;
3849 1 +
static_cast<unsigned int>(
3854 info.degree = data.degree;
3859 (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
3860 (info.max_eigenvalue_estimate) :
3861 ((info.max_eigenvalue_estimate - alpha) * 0.5);
3864 ->theta = (info.max_eigenvalue_estimate + alpha) * 0.5;
3868 using NumberType =
typename VectorType::value_type;
3876 (std::is_same_v<VectorType,
3879 temp_vector2.
reinit(src, true);
3882 VectorType empty_vector;
3883 temp_vector2.reinit(empty_vector);
3888 ->eigenvalues_are_initialized =
true;
3895template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3898 VectorType &solution,
3899 const VectorType &rhs)
const
3901 std::lock_guard<std::mutex> lock(mutex);
3902 if (eigenvalues_are_initialized ==
false)
3903 estimate_eigenvalues(rhs);
3905 internal::PreconditionChebyshevImplementation::vmult_and_update(
3907 *data.preconditioner,
3911 (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
3912 (4. / (3. * delta)) :
3921 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
3924 double rhok = delta / theta, sigma = theta / delta;
3925 for (
unsigned int k = 0; k < data.degree - 1; ++k)
3927 double factor1 = 0.0;
3928 double factor2 = 0.0;
3930 if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
3932 factor1 = (2 * k + 1.) / (2 * k + 5.);
3933 factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
3937 const double rhokp = 1. / (2. * sigma - rhok);
3938 factor1 = rhokp * rhok;
3939 factor2 = 2. * rhokp / delta;
3943 internal::PreconditionChebyshevImplementation::vmult_and_update(
3945 *data.preconditioner,
3959template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3962 VectorType &solution,
3963 const VectorType &rhs)
const
3965 std::lock_guard<std::mutex> lock(mutex);
3966 if (eigenvalues_are_initialized ==
false)
3967 estimate_eigenvalues(rhs);
3969 internal::PreconditionChebyshevImplementation::vector_updates(
3971 *data.preconditioner,
3974 (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
3975 (4. / (3. * delta)) :
3982 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
3985 double rhok = delta / theta, sigma = theta / delta;
3986 for (
unsigned int k = 0; k < data.degree - 1; ++k)
3988 double factor1 = 0.0;
3989 double factor2 = 0.0;
3991 if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
3993 factor1 = (2 * k + 1.) / (2 * k + 5.);
3994 factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
3998 const double rhokp = 1. / (2. * sigma - rhok);
3999 factor1 = rhokp * rhok;
4000 factor2 = 2. * rhokp / delta;
4004 matrix_ptr->Tvmult(temp_vector1, solution);
4005 internal::PreconditionChebyshevImplementation::vector_updates(
4007 *data.preconditioner,
4020template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4023 VectorType &solution,
4024 const VectorType &rhs)
const
4026 std::lock_guard<std::mutex> lock(mutex);
4027 if (eigenvalues_are_initialized ==
false)
4028 estimate_eigenvalues(rhs);
4030 internal::PreconditionChebyshevImplementation::vmult_and_update(
4032 *data.preconditioner,
4036 (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
4037 (4. / (3. * delta)) :
4044 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
4047 double rhok = delta / theta, sigma = theta / delta;
4048 for (
unsigned int k = 0; k < data.degree - 1; ++k)
4050 double factor1 = 0.0;
4051 double factor2 = 0.0;
4053 if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
4055 factor1 = (2 * k + 1.) / (2 * k + 5.);
4056 factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
4060 const double rhokp = 1. / (2. * sigma - rhok);
4061 factor1 = rhokp * rhok;
4062 factor2 = 2. * rhokp / delta;
4066 internal::PreconditionChebyshevImplementation::vmult_and_update(
4068 *data.preconditioner,
4082template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4085 VectorType &solution,
4086 const VectorType &rhs)
const
4088 std::lock_guard<std::mutex> lock(mutex);
4089 if (eigenvalues_are_initialized ==
false)
4090 estimate_eigenvalues(rhs);
4092 matrix_ptr->Tvmult(temp_vector1, solution);
4093 internal::PreconditionChebyshevImplementation::vector_updates(
4095 *data.preconditioner,
4098 (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
4099 (4. / (3. * delta)) :
4106 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
4109 double rhok = delta / theta, sigma = theta / delta;
4110 for (
unsigned int k = 0; k < data.degree - 1; ++k)
4112 double factor1 = 0.0;
4113 double factor2 = 0.0;
4115 if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
4117 factor1 = (2 * k + 1.) / (2 * k + 5.);
4118 factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
4122 const double rhokp = 1. / (2. * sigma - rhok);
4123 factor1 = rhokp * rhok;
4124 factor2 = 2. * rhokp / delta;
4128 matrix_ptr->Tvmult(temp_vector1, solution);
4129 internal::PreconditionChebyshevImplementation::vector_updates(
4131 *data.preconditioner,
4144template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4147 PreconditionerType>::size_type
4151 return matrix_ptr->m();
4156template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4159 PreconditionerType>::size_type
4163 return matrix_ptr->n();
unsigned int n_blocks() const
BlockType & block(const unsigned int i)
size_type nth_index_in_set(const size_type local_index) const
void sadd(const Number s, const Number a, const Vector< Number, MemorySpace > &V)
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
void Tvmult(VectorType &dst, const VectorType &src) const
void step(VectorType &dst, const VectorType &src) const
EigenvalueInformation estimate_eigenvalues(const VectorType &src) const
void Tstep(VectorType &dst, const VectorType &src) const
SmartPointer< const MatrixType, PreconditionChebyshev< MatrixType, VectorType, PreconditionerType > > matrix_ptr
void vmult(VectorType &dst, const VectorType &src) const
void initialize(const MatrixType &matrix, const AdditionalData &additional_data=AdditionalData())
bool eigenvalues_are_initialized
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
internal::PreconditionRelaxation::PreconditionPSORImpl< MatrixType > PreconditionerType
typename BaseClass::size_type size_type
void initialize(const MatrixType &A, const AdditionalData &additional_data)
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)
double get_relaxation() const
SmartPointer< const MatrixType, PreconditionRelaxation< MatrixType > > A
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
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.)
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
const function_ptr precondition
const MatrixType & matrix
void vmult(VectorType &dst, const VectorType &src) const
void(MatrixType::*)(VectorType &, const VectorType &) const function_ptr
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
virtual size_type size() const override
virtual void swap(Vector< Number > &v) noexcept
#define DEAL_II_OPENMP_SIMD_PRAGMA
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
#define DEAL_II_NOT_IMPLEMENTED()
@ matrix
Contents is actually a matrix.
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
unsigned int minimum_parallel_grain_size
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
constexpr bool is_supported_operation
static const 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
PolynomialType polynomial_type
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)
std::shared_ptr< PreconditionerType > preconditioner
EigenvalueAlgorithmAdditionalData< PreconditionerType > & operator=(const EigenvalueAlgorithmAdditionalData< PreconditionerType > &other_data)
::AffineConstraints< double > constraints
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)
unsigned int eig_cg_n_iterations
EigenvalueAlgorithm eigenvalue_algorithm
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)