15#ifndef dealii_precondition_h
16#define dealii_precondition_h
39template <
typename number>
41template <
typename number>
47 template <
typename,
typename>
126 template <
typename PreconditionerType>
247 template <
typename MatrixType>
255 template <
typename VectorType>
257 vmult(VectorType &,
const VectorType &)
const;
263 template <
typename VectorType>
265 Tvmult(VectorType &,
const VectorType &)
const;
270 template <
typename VectorType>
278 template <
typename VectorType>
376 template <
typename MatrixType>
383 template <
typename VectorType>
385 vmult(VectorType &,
const VectorType &)
const;
391 template <
typename VectorType>
393 Tvmult(VectorType &,
const VectorType &)
const;
397 template <
typename VectorType>
405 template <
typename VectorType>
495template <
typename MatrixType = SparseMatrix<
double>,
496 typename VectorType = Vector<
double>>
504 const VectorType &) const;
518 vmult(VectorType &dst,
const VectorType &src)
const;
563template <
typename MatrixType = SparseMatrix<
double>,
564 typename PreconditionerType = IdentityMatrix>
592 EigenvalueAlgorithm::lanczos);
638 template <
typename VectorType>
640 vmult(VectorType &,
const VectorType &)
const;
646 template <
typename VectorType>
648 Tvmult(VectorType &,
const VectorType &)
const;
653 template <
typename VectorType>
655 step(VectorType &x,
const VectorType &rhs)
const;
660 template <
typename VectorType>
662 Tstep(VectorType &x,
const VectorType &rhs)
const;
669 template <
typename VectorType>
714 template <
typename MatrixType,
typename VectorType>
715 using vmult_functions_t =
decltype(std::declval<const MatrixType>().vmult(
716 std::declval<VectorType &>(),
717 std::declval<const VectorType &>(),
719 const std::function<
void(
const unsigned int,
const unsigned int)> &>(),
721 const std::function<
void(
const unsigned int,
const unsigned int)> &>()));
723 template <
typename MatrixType,
725 typename PreconditionerType>
726 constexpr bool has_vmult_with_std_functions =
727 is_supported_operation<vmult_functions_t, MatrixType, VectorType> &&
728 std::is_same_v<PreconditionerType, ::DiagonalMatrix<VectorType>> &&
729 (std::is_same_v<VectorType,
737 template <
typename MatrixType,
typename VectorType>
738 constexpr bool has_vmult_with_std_functions_for_precondition =
739 is_supported_operation<vmult_functions_t, MatrixType, VectorType>;
743 template <
typename T,
typename VectorType>
744 using Tvmult_t =
decltype(std::declval<const T>().Tvmult(
745 std::declval<VectorType &>(),
746 std::declval<const VectorType &>()));
748 template <
typename T,
typename VectorType>
749 constexpr bool has_Tvmult = is_supported_operation<Tvmult_t, T, VectorType>;
751 template <
typename T,
typename VectorType>
752 using step_t =
decltype(std::declval<const T>().step(
753 std::declval<VectorType &>(),
754 std::declval<const VectorType &>()));
756 template <
typename T,
typename VectorType>
757 constexpr bool has_step = is_supported_operation<step_t, T, VectorType>;
759 template <
typename T,
typename VectorType>
761 decltype(std::declval<const T>().step(std::declval<VectorType &>(),
762 std::declval<const VectorType &>(),
763 std::declval<const double>()));
765 template <
typename T,
typename VectorType>
766 constexpr bool has_step_omega =
767 is_supported_operation<step_omega_t, T, VectorType>;
769 template <
typename T,
typename VectorType>
770 using Tstep_t =
decltype(std::declval<const T>().Tstep(
771 std::declval<VectorType &>(),
772 std::declval<const VectorType &>()));
774 template <
typename T,
typename VectorType>
775 constexpr bool has_Tstep = is_supported_operation<Tstep_t, T, VectorType>;
777 template <
typename T,
typename VectorType>
778 using Tstep_omega_t =
779 decltype(std::declval<const T>().Tstep(std::declval<VectorType &>(),
780 std::declval<const VectorType &>(),
781 std::declval<const double>()));
783 template <
typename T,
typename VectorType>
784 constexpr bool has_Tstep_omega =
785 is_supported_operation<Tstep_omega_t, T, VectorType>;
787 template <
typename T,
typename VectorType>
788 using jacobi_step_t =
decltype(std::declval<const T>().Jacobi_step(
789 std::declval<VectorType &>(),
790 std::declval<const VectorType &>(),
791 std::declval<const double>()));
793 template <
typename T,
typename VectorType>
794 constexpr bool has_jacobi_step =
795 is_supported_operation<jacobi_step_t, T, VectorType>;
797 template <
typename T,
typename VectorType>
798 using SOR_step_t =
decltype(std::declval<const T>().SOR_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_SOR_step =
805 is_supported_operation<SOR_step_t, T, VectorType>;
807 template <
typename T,
typename VectorType>
808 using SSOR_step_t =
decltype(std::declval<const T>().SSOR_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_SSOR_step =
815 is_supported_operation<SSOR_step_t, T, VectorType>;
817 template <
typename MatrixType>
818 class PreconditionJacobiImpl
821 PreconditionJacobiImpl(
const MatrixType &A,
const double relaxation)
823 , relaxation(relaxation)
826 template <
typename VectorType>
828 vmult(VectorType &dst,
const VectorType &src)
const
830 this->A->precondition_Jacobi(dst, src, this->relaxation);
833 template <
typename VectorType>
835 Tvmult(VectorType &dst,
const VectorType &src)
const
838 this->vmult(dst, src);
841 template <
typename VectorType,
842 std::enable_if_t<has_jacobi_step<MatrixType, VectorType>,
843 MatrixType> * =
nullptr>
845 step(VectorType &dst,
const VectorType &src)
const
847 this->A->Jacobi_step(dst, src, this->relaxation);
850 template <
typename VectorType,
851 std::enable_if_t<!has_jacobi_step<MatrixType, VectorType>,
852 MatrixType> * =
nullptr>
854 step(VectorType &,
const VectorType &)
const
858 "Matrix A does not provide a Jacobi_step() function!"));
861 template <
typename VectorType>
863 Tstep(VectorType &dst,
const VectorType &src)
const
866 this->step(dst, src);
871 const double relaxation;
874 template <
typename MatrixType>
875 class PreconditionSORImpl
878 PreconditionSORImpl(
const MatrixType &A,
const double relaxation)
880 , relaxation(relaxation)
883 template <
typename VectorType>
885 vmult(VectorType &dst,
const VectorType &src)
const
887 this->A->precondition_SOR(dst, src, this->relaxation);
890 template <
typename VectorType>
892 Tvmult(VectorType &dst,
const VectorType &src)
const
894 this->A->precondition_TSOR(dst, src, this->relaxation);
897 template <
typename VectorType,
898 std::enable_if_t<has_SOR_step<MatrixType, VectorType>,
899 MatrixType> * =
nullptr>
901 step(VectorType &dst,
const VectorType &src)
const
903 this->A->SOR_step(dst, src, this->relaxation);
906 template <
typename VectorType,
907 std::enable_if_t<!has_SOR_step<MatrixType, VectorType>,
908 MatrixType> * =
nullptr>
910 step(VectorType &,
const VectorType &)
const
914 "Matrix A does not provide a SOR_step() function!"));
917 template <
typename VectorType,
918 std::enable_if_t<has_SOR_step<MatrixType, VectorType>,
919 MatrixType> * =
nullptr>
921 Tstep(VectorType &dst,
const VectorType &src)
const
923 this->A->TSOR_step(dst, src, this->relaxation);
926 template <
typename VectorType,
927 std::enable_if_t<!has_SOR_step<MatrixType, VectorType>,
928 MatrixType> * =
nullptr>
930 Tstep(VectorType &,
const VectorType &)
const
934 "Matrix A does not provide a TSOR_step() function!"));
939 const double relaxation;
942 template <
typename MatrixType>
943 class PreconditionSSORImpl
946 using size_type =
typename MatrixType::size_type;
948 PreconditionSSORImpl(
const MatrixType &A,
const double relaxation)
950 , relaxation(relaxation)
961 const size_type n = this->A->n();
962 pos_right_of_diagonal.resize(n,
static_cast<std::size_t
>(-1));
963 for (size_type row = 0; row < n; ++row)
970 typename MatrixType::value_type>::const_iterator it =
972 for (; it < mat->
end(row); ++it)
973 if (it->column() > row)
975 pos_right_of_diagonal[row] = it - mat->
begin();
980 template <
typename VectorType>
982 vmult(VectorType &dst,
const VectorType &src)
const
984 this->A->precondition_SSOR(dst,
987 pos_right_of_diagonal);
990 template <
typename VectorType>
992 Tvmult(VectorType &dst,
const VectorType &src)
const
994 this->A->precondition_SSOR(dst,
997 pos_right_of_diagonal);
1000 template <
typename VectorType,
1001 std::enable_if_t<has_SSOR_step<MatrixType, VectorType>,
1002 MatrixType> * =
nullptr>
1004 step(VectorType &dst,
const VectorType &src)
const
1006 this->A->SSOR_step(dst, src, this->relaxation);
1009 template <
typename VectorType,
1010 std::enable_if_t<!has_SSOR_step<MatrixType, VectorType>,
1011 MatrixType> * =
nullptr>
1013 step(VectorType &,
const VectorType &)
const
1017 "Matrix A does not provide a SSOR_step() function!"));
1020 template <
typename VectorType>
1022 Tstep(VectorType &dst,
const VectorType &src)
const
1025 this->step(dst, src);
1030 const double relaxation;
1036 std::vector<std::size_t> pos_right_of_diagonal;
1039 template <
typename MatrixType>
1040 class PreconditionPSORImpl
1043 using size_type =
typename MatrixType::size_type;
1045 PreconditionPSORImpl(
const MatrixType &A,
1046 const double relaxation,
1047 const std::vector<size_type> &permutation,
1048 const std::vector<size_type> &inverse_permutation)
1050 , relaxation(relaxation)
1051 , permutation(permutation)
1052 , inverse_permutation(inverse_permutation)
1055 template <
typename VectorType>
1057 vmult(VectorType &dst,
const VectorType &src)
const
1060 this->A->PSOR(dst, permutation, inverse_permutation, this->relaxation);
1063 template <
typename VectorType>
1065 Tvmult(VectorType &dst,
const VectorType &src)
const
1068 this->A->TPSOR(dst, permutation, inverse_permutation, this->relaxation);
1073 const double relaxation;
1075 const std::vector<size_type> &permutation;
1076 const std::vector<size_type> &inverse_permutation;
1079 template <
typename MatrixType,
1080 typename PreconditionerType,
1081 typename VectorType,
1082 std::enable_if_t<has_step_omega<PreconditionerType, VectorType>,
1083 PreconditionerType> * =
nullptr>
1085 step(
const MatrixType &,
1086 const PreconditionerType &preconditioner,
1088 const VectorType &src,
1089 const double relaxation,
1093 preconditioner.step(dst, src, relaxation);
1097 typename MatrixType,
1098 typename PreconditionerType,
1099 typename VectorType,
1100 std::enable_if_t<!has_step_omega<PreconditionerType, VectorType> &&
1101 has_step<PreconditionerType, VectorType>,
1102 PreconditionerType> * =
nullptr>
1104 step(
const MatrixType &,
1105 const PreconditionerType &preconditioner,
1107 const VectorType &src,
1108 const double relaxation,
1116 preconditioner.step(dst, src);
1120 typename MatrixType,
1121 typename PreconditionerType,
1122 typename VectorType,
1123 std::enable_if_t<!has_step_omega<PreconditionerType, VectorType> &&
1124 !has_step<PreconditionerType, VectorType>,
1125 PreconditionerType> * =
nullptr>
1127 step(
const MatrixType &A,
1128 const PreconditionerType &preconditioner,
1130 const VectorType &src,
1131 const double relaxation,
1132 VectorType &residual,
1135 residual.reinit(dst,
true);
1136 tmp.reinit(dst,
true);
1138 A.vmult(residual, dst);
1139 residual.sadd(-1.0, 1.0, src);
1141 preconditioner.vmult(tmp, residual);
1142 dst.add(relaxation, tmp);
1145 template <
typename MatrixType,
1146 typename PreconditionerType,
1147 typename VectorType,
1148 std::enable_if_t<has_Tstep_omega<PreconditionerType, VectorType>,
1149 PreconditionerType> * =
nullptr>
1151 Tstep(
const MatrixType &,
1152 const PreconditionerType &preconditioner,
1154 const VectorType &src,
1155 const double relaxation,
1159 preconditioner.Tstep(dst, src, relaxation);
1163 typename MatrixType,
1164 typename PreconditionerType,
1165 typename VectorType,
1166 std::enable_if_t<!has_Tstep_omega<PreconditionerType, VectorType> &&
1167 has_Tstep<PreconditionerType, VectorType>,
1168 PreconditionerType> * =
nullptr>
1170 Tstep(
const MatrixType &,
1171 const PreconditionerType &preconditioner,
1173 const VectorType &src,
1174 const double relaxation,
1182 preconditioner.Tstep(dst, src);
1185 template <
typename MatrixType,
1186 typename VectorType,
1187 std::enable_if_t<has_Tvmult<MatrixType, VectorType>, MatrixType>
1190 Tvmult(
const MatrixType &A, VectorType &dst,
const VectorType &src)
1195 template <
typename MatrixType,
1196 typename VectorType,
1197 std::enable_if_t<!has_Tvmult<MatrixType, VectorType>, MatrixType>
1200 Tvmult(
const MatrixType &, VectorType &,
const VectorType &)
1203 ExcMessage(
"Matrix A does not provide a Tvmult() function!"));
1207 typename MatrixType,
1208 typename PreconditionerType,
1209 typename VectorType,
1210 std::enable_if_t<!has_Tstep_omega<PreconditionerType, VectorType> &&
1211 !has_Tstep<PreconditionerType, VectorType>,
1212 PreconditionerType> * =
nullptr>
1214 Tstep(
const MatrixType &A,
1215 const PreconditionerType &preconditioner,
1217 const VectorType &src,
1218 const double relaxation,
1219 VectorType &residual,
1222 residual.reinit(dst,
true);
1223 tmp.reinit(dst,
true);
1225 Tvmult(A, residual, dst);
1226 residual.sadd(-1.0, 1.0, src);
1228 Tvmult(preconditioner, tmp, residual);
1229 dst.add(relaxation, tmp);
1233 template <
typename MatrixType,
1234 typename PreconditionerType,
1235 typename VectorType,
1236 std::enable_if_t<!has_vmult_with_std_functions_for_precondition<
1241 step_operations(
const MatrixType &A,
1242 const PreconditionerType &preconditioner,
1244 const VectorType &src,
1245 const double relaxation,
1248 const unsigned int i,
1249 const bool transposed)
1254 Tvmult(preconditioner, dst, src);
1256 preconditioner.vmult(dst, src);
1258 if (relaxation != 1.0)
1264 Tstep(A, preconditioner, dst, src, relaxation, tmp1, tmp2);
1266 step(A, preconditioner, dst, src, relaxation, tmp1, tmp2);
1273 typename MatrixType,
1274 typename PreconditionerType,
1275 typename VectorType,
1277 has_vmult_with_std_functions_for_precondition<PreconditionerType,
1279 !has_vmult_with_std_functions_for_precondition<MatrixType,
1283 step_operations(
const MatrixType &A,
1284 const PreconditionerType &preconditioner,
1286 const VectorType &src,
1287 const double relaxation,
1290 const unsigned int i,
1291 const bool transposed)
1294 using Number =
typename VectorType::value_type;
1298 Number *dst_ptr = dst.begin();
1299 const Number *src_ptr = src.begin();
1301 preconditioner.vmult(
1304 [&](
const unsigned int start_range,
const unsigned int end_range) {
1306 if (end_range > start_range)
1307 std::memset(dst.begin() + start_range,
1309 sizeof(Number) * (end_range - start_range));
1311 [&](
const unsigned int start_range,
const unsigned int end_range) {
1312 if (relaxation == 1.0)
1315 const auto src_ptr = src.begin();
1316 const auto dst_ptr = dst.begin();
1319 for (std::size_t i = start_range; i < end_range; ++i)
1320 dst_ptr[i] *= relaxation;
1325 tmp.reinit(src,
true);
1331 preconditioner.vmult(
1334 [&](
const unsigned int start_range,
const unsigned int end_range) {
1335 const auto src_ptr = src.begin();
1336 const auto tmp_ptr = tmp.begin();
1338 if (relaxation == 1.0)
1341 for (std::size_t i = start_range; i < end_range; ++i)
1342 tmp_ptr[i] = src_ptr[i] - tmp_ptr[i];
1350 for (std::size_t i = start_range; i < end_range; ++i)
1351 tmp_ptr[i] = relaxation * (src_ptr[i] - tmp_ptr[i]);
1354 [&](
const unsigned int,
const unsigned int) {
1364 typename MatrixType,
1365 typename PreconditionerType,
1366 typename VectorType,
1368 has_vmult_with_std_functions_for_precondition<PreconditionerType,
1370 has_vmult_with_std_functions_for_precondition<MatrixType, VectorType>,
1373 step_operations(
const MatrixType &A,
1374 const PreconditionerType &preconditioner,
1376 const VectorType &src,
1377 const double relaxation,
1380 const unsigned int i,
1381 const bool transposed)
1384 using Number =
typename VectorType::value_type;
1388 Number *dst_ptr = dst.begin();
1389 const Number *src_ptr = src.begin();
1391 preconditioner.vmult(
1394 [&](
const unsigned int start_range,
const unsigned int end_range) {
1396 if (end_range > start_range)
1397 std::memset(dst.begin() + start_range,
1399 sizeof(Number) * (end_range - start_range));
1401 [&](
const unsigned int start_range,
const unsigned int end_range) {
1402 if (relaxation == 1.0)
1405 const auto src_ptr = src.begin();
1406 const auto dst_ptr = dst.begin();
1409 for (std::size_t i = start_range; i < end_range; ++i)
1410 dst_ptr[i] *= relaxation;
1415 tmp.reinit(src,
true);
1422 [&](
const unsigned int start_range,
const unsigned int end_range) {
1425 if (end_range > start_range)
1426 std::memset(tmp.begin() + start_range,
1428 sizeof(Number) * (end_range - start_range));
1430 [&](
const unsigned int start_range,
const unsigned int end_range) {
1431 const auto src_ptr = src.begin();
1432 const auto tmp_ptr = tmp.begin();
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) {
1459 template <
typename MatrixType,
1460 typename VectorType,
1461 std::enable_if_t<!IsBlockVector<VectorType>::value &&
1462 !has_vmult_with_std_functions<
1466 VectorType> * =
nullptr>
1468 step_operations(
const MatrixType &A,
1469 const ::DiagonalMatrix<VectorType> &preconditioner,
1471 const VectorType &src,
1472 const double relaxation,
1475 const unsigned int i,
1476 const bool transposed)
1478 using Number =
typename VectorType::value_type;
1482 Number *dst_ptr = dst.begin();
1483 const Number *src_ptr = src.begin();
1484 const Number *diag_ptr = preconditioner.get_vector().begin();
1486 if (relaxation == 1.0)
1489 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1490 dst_ptr[i] = src_ptr[i] * diag_ptr[i];
1495 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1496 dst_ptr[i] = relaxation * src_ptr[i] * diag_ptr[i];
1501 tmp.reinit(src,
true);
1503 Number *dst_ptr = dst.begin();
1504 const Number *src_ptr = src.begin();
1505 const Number *tmp_ptr = tmp.begin();
1506 const Number *diag_ptr = preconditioner.get_vector().begin();
1509 Tvmult(A, tmp, dst);
1513 if (relaxation == 1.0)
1516 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1517 dst_ptr[i] += (src_ptr[i] - tmp_ptr[i]) * diag_ptr[i];
1522 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1524 relaxation * (src_ptr[i] - tmp_ptr[i]) * diag_ptr[i];
1531 template <
typename MatrixType,
1532 typename VectorType,
1533 std::enable_if_t<!IsBlockVector<VectorType>::value &&
1534 has_vmult_with_std_functions<
1538 VectorType> * =
nullptr>
1540 step_operations(
const MatrixType &A,
1541 const ::DiagonalMatrix<VectorType> &preconditioner,
1543 const VectorType &src,
1544 const double relaxation,
1547 const unsigned int i,
1548 const bool transposed)
1551 using Number =
typename VectorType::value_type;
1555 Number *dst_ptr = dst.begin();
1556 const Number *src_ptr = src.begin();
1557 const Number *diag_ptr = preconditioner.get_vector().begin();
1559 if (relaxation == 1.0)
1562 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1563 dst_ptr[i] = src_ptr[i] * diag_ptr[i];
1568 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1569 dst_ptr[i] = relaxation * src_ptr[i] * diag_ptr[i];
1574 tmp.reinit(src,
true);
1581 [&](
const unsigned int start_range,
const unsigned int end_range) {
1583 if (end_range > start_range)
1584 std::memset(tmp.begin() + start_range,
1586 sizeof(Number) * (end_range - start_range));
1588 [&](
const unsigned int begin,
const unsigned int end) {
1589 const Number *dst_ptr = dst.begin();
1590 const Number *src_ptr = src.begin();
1591 Number *tmp_ptr = tmp.begin();
1592 const Number *diag_ptr = preconditioner.get_vector().begin();
1596 if (relaxation == 1.0)
1599 for (std::size_t i = begin; i < end; ++i)
1601 dst_ptr[i] + (src_ptr[i] - tmp_ptr[i]) * diag_ptr[i];
1606 for (std::size_t i = begin; i < end; ++i)
1607 tmp_ptr[i] = dst_ptr[i] + relaxation *
1608 (src_ptr[i] - tmp_ptr[i]) *
1650template <
typename MatrixType = SparseMatrix<
double>>
1654 internal::PreconditionRelaxation::PreconditionJacobiImpl<MatrixType>>
1657 internal::PreconditionRelaxation::PreconditionJacobiImpl<MatrixType>;
1720template <
typename MatrixType = SparseMatrix<
double>>
1724 internal::PreconditionRelaxation::PreconditionSORImpl<MatrixType>>
1727 internal::PreconditionRelaxation::PreconditionSORImpl<MatrixType>;
1772template <
typename MatrixType = SparseMatrix<
double>>
1776 internal::PreconditionRelaxation::PreconditionSSORImpl<MatrixType>>
1779 internal::PreconditionRelaxation::PreconditionSSORImpl<MatrixType>;
1828template <
typename MatrixType = SparseMatrix<
double>>
1832 internal::PreconditionRelaxation::PreconditionPSORImpl<MatrixType>>
1835 internal::PreconditionRelaxation::PreconditionPSORImpl<MatrixType>;
1892 const std::vector<size_type> &permutation,
1893 const std::vector<size_type> &inverse_permutation,
2100template <
typename MatrixType = SparseMatrix<
double>,
2101 typename VectorType = Vector<
double>,
2102 typename PreconditionerType = DiagonalMatrix<VectorType>>
2140 const unsigned int degree = 1,
2146 EigenvalueAlgorithm::lanczos,
2195 vmult(VectorType &dst,
const VectorType &src)
const;
2202 Tvmult(VectorType &dst,
const VectorType &src)
const;
2208 step(VectorType &dst,
const VectorType &src)
const;
2214 Tstep(VectorType &dst,
const VectorType &src)
const;
2317 template <
typename VectorType>
2319 set_initial_guess(VectorType &vector)
2321 vector = 1. /
std::sqrt(
static_cast<double>(vector.size()));
2322 if (vector.locally_owned_elements().is_element(0))
2326 template <
typename Number>
2334 for (
unsigned int i = 0; i < vector.
size(); ++i)
2337 const Number mean_value = vector.
mean_value();
2338 vector.
add(-mean_value);
2341 template <
typename Number>
2346 for (
unsigned int block = 0; block < vector.
n_blocks(); ++block)
2347 set_initial_guess(vector.
block(block));
2350 template <
typename Number,
typename MemorySpace>
2367 Kokkos::RangePolicy<
typename MemorySpace::kokkos_space::execution_space,
2368 Kokkos::IndexType<types::global_dof_index>>
2369 policy(0, n_local_elements);
2370 Kokkos::parallel_for(
2371 "::PreconditionChebyshev::set_initial_guess",
2374 values_ptr[i] = (i + first_local_range) % 11;
2376 const Number mean_value = vector.
mean_value();
2377 vector.
add(-mean_value);
2380 struct EigenvalueTracker
2389 std::vector<double>
values;
2396 typename PreconditionerType>
2399 VectorType &eigenvector,
2400 const PreconditionerType &preconditioner,
2401 const unsigned int n_iterations)
2403 typename VectorType::value_type eigenvalue_estimate = 0.;
2404 eigenvector /= eigenvector.l2_norm();
2406 vector1.reinit(eigenvector,
true);
2407 if (!std::is_same_v<PreconditionerType, PreconditionIdentity>)
2408 vector2.reinit(eigenvector,
true);
2409 for (
unsigned int i = 0; i < n_iterations; ++i)
2411 if (!std::is_same_v<PreconditionerType, PreconditionIdentity>)
2413 matrix.vmult(vector2, eigenvector);
2414 preconditioner.vmult(vector1, vector2);
2417 matrix.vmult(vector1, eigenvector);
2419 eigenvalue_estimate = eigenvector * vector1;
2421 vector1 /= vector1.l2_norm();
2422 eigenvector.swap(vector1);
2424 return std::abs(eigenvalue_estimate);
2431 typename PreconditionerType>
2432 EigenvalueInformation
2433 estimate_eigenvalues(
2434 const EigenvalueAlgorithmAdditionalData<PreconditionerType> &data,
2435 const MatrixType *matrix_ptr,
2436 VectorType &solution_old,
2437 VectorType &temp_vector1,
2438 const unsigned int degree)
2442 EigenvalueInformation info{};
2444 if (data.eig_cg_n_iterations > 0)
2446 Assert(data.eig_cg_n_iterations > 2,
2448 "Need to set at least two iterations to find eigenvalues."));
2450 internal::EigenvalueTracker eigenvalue_tracker;
2455 internal::set_initial_guess(temp_vector1);
2456 data.constraints.set_zero(temp_vector1);
2467 solver.connect_eigenvalues_slot(
2468 [&eigenvalue_tracker](
const std::vector<double> &
eigenvalues) {
2472 solver.solve(*matrix_ptr,
2475 *data.preconditioner);
2477 info.cg_iterations = control.last_step();
2479 else if (data.eigenvalue_algorithm ==
2485 ExcMessage(
"Cannot estimate the minimal eigenvalue with the "
2486 "power iteration"));
2488 eigenvalue_tracker.values.push_back(
2491 *data.preconditioner,
2492 data.eig_cg_n_iterations));
2498 if (eigenvalue_tracker.values.empty())
2499 info.min_eigenvalue_estimate = info.max_eigenvalue_estimate = 1.;
2502 info.min_eigenvalue_estimate = eigenvalue_tracker.values.front();
2506 info.max_eigenvalue_estimate =
2507 1.2 * eigenvalue_tracker.values.back();
2512 info.max_eigenvalue_estimate = data.max_eigenvalue;
2513 info.min_eigenvalue_estimate =
2514 data.max_eigenvalue / data.smoothing_range;
2528template <
typename MatrixType>
2538template <
typename VectorType>
2547template <
typename VectorType>
2554template <
typename VectorType>
2563template <
typename VectorType>
2595 const double relaxation)
2596 : relaxation(relaxation)
2605 AdditionalData add_data;
2606 relaxation = add_data.relaxation;
2620template <
typename MatrixType>
2623 const MatrixType &matrix,
2633template <
typename VectorType>
2638 std::is_same_v<size_type, typename VectorType::size_type>,
2639 "PreconditionRichardson and VectorType must have the same size_type.");
2646template <
typename VectorType>
2651 std::is_same_v<size_type, typename VectorType::size_type>,
2652 "PreconditionRichardson and VectorType must have the same size_type.");
2657template <
typename VectorType>
2662 std::is_same_v<size_type, typename VectorType::size_type>,
2663 "PreconditionRichardson and VectorType must have the same size_type.");
2670template <
typename VectorType>
2675 std::is_same_v<size_type, typename VectorType::size_type>,
2676 "PreconditionRichardson and VectorType must have the same size_type.");
2697template <
typename MatrixType,
typename PreconditionerType>
2700 const MatrixType &rA,
2701 const AdditionalData ¶meters)
2704 eigenvalues_are_initialized =
false;
2708 this->data = parameters;
2712template <
typename MatrixType,
typename PreconditionerType>
2716 eigenvalues_are_initialized =
false;
2718 data.relaxation = 1.0;
2719 data.preconditioner =
nullptr;
2722template <
typename MatrixType,
typename PreconditionerType>
2731template <
typename MatrixType,
typename PreconditionerType>
2740template <
typename MatrixType,
typename PreconditionerType>
2741template <
typename VectorType>
2745 const VectorType &src)
const
2750 if (eigenvalues_are_initialized ==
false)
2751 estimate_eigenvalues(src);
2755 for (
unsigned int i = 0; i < data.n_iterations; ++i)
2756 internal::PreconditionRelaxation::step_operations(*A,
2757 *data.preconditioner,
2767template <
typename MatrixType,
typename PreconditionerType>
2768template <
typename VectorType>
2772 const VectorType &src)
const
2777 if (eigenvalues_are_initialized ==
false)
2778 estimate_eigenvalues(src);
2782 for (
unsigned int i = 0; i < data.n_iterations; ++i)
2783 internal::PreconditionRelaxation::step_operations(
2784 *A, *data.preconditioner, dst, src, data.relaxation, tmp1, tmp2, i,
true);
2787template <
typename MatrixType,
typename PreconditionerType>
2788template <
typename VectorType>
2792 const VectorType &src)
const
2797 if (eigenvalues_are_initialized ==
false)
2798 estimate_eigenvalues(src);
2802 for (
unsigned int i = 1; i <= data.n_iterations; ++i)
2803 internal::PreconditionRelaxation::step_operations(*A,
2804 *data.preconditioner,
2814template <
typename MatrixType,
typename PreconditionerType>
2815template <
typename VectorType>
2819 const VectorType &src)
const
2824 if (eigenvalues_are_initialized ==
false)
2825 estimate_eigenvalues(src);
2829 for (
unsigned int i = 1; i <= data.n_iterations; ++i)
2830 internal::PreconditionRelaxation::step_operations(
2831 *A, *data.preconditioner, dst, src, data.relaxation, tmp1, tmp2, i,
true);
2834template <
typename MatrixType,
typename PreconditionerType>
2835template <
typename VectorType>
2838 const VectorType &src)
const
2842 EigenvalueInformation info;
2844 if (data.relaxation == 0.0)
2848 solution_old.reinit(src);
2849 temp_vector1.reinit(src,
true);
2851 info = internal::estimate_eigenvalues<MatrixType>(
2852 data, A, solution_old, temp_vector1, data.n_iterations);
2854 const double alpha =
2855 (data.smoothing_range > 1. ?
2856 info.max_eigenvalue_estimate / data.smoothing_range :
2857 std::min(0.9 * info.max_eigenvalue_estimate,
2858 info.min_eigenvalue_estimate));
2861 ->data.relaxation = 2.0 / (alpha + info.max_eigenvalue_estimate);
2865 ->eigenvalues_are_initialized =
true;
2870template <
typename MatrixType,
typename PreconditionerType>
2874 return data.relaxation;
2880template <
typename MatrixType>
2883 const AdditionalData ¶meters_in)
2887 parameters_in.relaxation != 0.0,
2889 "Relaxation cannot automatically be determined by PreconditionJacobi."));
2891 AdditionalData parameters;
2892 parameters.relaxation = 1.0;
2893 parameters.n_iterations = parameters_in.n_iterations;
2894 parameters.preconditioner =
2895 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
2897 this->BaseClass::initialize(A, parameters);
2902template <
typename MatrixType>
2905 const AdditionalData ¶meters_in)
2909 parameters_in.relaxation != 0.0,
2911 "Relaxation cannot automatically be determined by PreconditionSOR."));
2913 AdditionalData parameters;
2914 parameters.relaxation = 1.0;
2915 parameters.n_iterations = parameters_in.n_iterations;
2916 parameters.preconditioner =
2917 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
2919 this->BaseClass::initialize(A, parameters);
2924template <
typename MatrixType>
2927 const AdditionalData ¶meters_in)
2931 parameters_in.relaxation != 0.0,
2933 "Relaxation cannot automatically be determined by PreconditionSSOR."));
2935 AdditionalData parameters;
2936 parameters.relaxation = 1.0;
2937 parameters.n_iterations = parameters_in.n_iterations;
2938 parameters.preconditioner =
2939 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
2941 this->BaseClass::initialize(A, parameters);
2948template <
typename MatrixType>
2951 const MatrixType &A,
2952 const std::vector<size_type> &p,
2953 const std::vector<size_type> &ip,
2954 const typename BaseClass::AdditionalData ¶meters_in)
2958 parameters_in.relaxation != 0.0,
2960 "Relaxation cannot automatically be determined by PreconditionPSOR."));
2962 typename BaseClass::AdditionalData parameters;
2963 parameters.relaxation = 1.0;
2964 parameters.n_iterations = parameters_in.n_iterations;
2965 parameters.preconditioner =
2966 std::make_shared<PreconditionerType>(A, parameters_in.relaxation, p, ip);
2968 this->BaseClass::initialize(A, parameters);
2972template <
typename MatrixType>
2975 const AdditionalData &additional_data)
2978 additional_data.permutation,
2979 additional_data.inverse_permutation,
2980 additional_data.parameters);
2983template <
typename MatrixType>
2985 const std::vector<size_type> &permutation,
2986 const std::vector<size_type> &inverse_permutation,
2989 : permutation(permutation)
2990 , inverse_permutation(inverse_permutation)
2991 , parameters(parameters)
2998template <
typename MatrixType,
typename VectorType>
3000 const MatrixType &M,
3001 const function_ptr method)
3003 , precondition(method)
3008template <
typename MatrixType,
typename VectorType>
3012 const VectorType &src)
const
3014 (
matrix.*precondition)(dst, src);
3022 template <
typename PreconditionerType>
3025 const double smoothing_range,
3026 const unsigned int eig_cg_n_iterations,
3027 const double eig_cg_residual,
3028 const double max_eigenvalue,
3030 : smoothing_range(smoothing_range)
3031 , eig_cg_n_iterations(eig_cg_n_iterations)
3032 , eig_cg_residual(eig_cg_residual)
3033 , max_eigenvalue(max_eigenvalue)
3034 , eigenvalue_algorithm(eigenvalue_algorithm)
3039 template <
typename PreconditionerType>
3040 inline EigenvalueAlgorithmAdditionalData<PreconditionerType> &
3041 EigenvalueAlgorithmAdditionalData<PreconditionerType>::operator=(
3042 const EigenvalueAlgorithmAdditionalData &other_data)
3044 smoothing_range = other_data.smoothing_range;
3045 eig_cg_n_iterations = other_data.eig_cg_n_iterations;
3046 eig_cg_residual = other_data.eig_cg_residual;
3047 max_eigenvalue = other_data.max_eigenvalue;
3048 preconditioner = other_data.preconditioner;
3049 eigenvalue_algorithm = other_data.eigenvalue_algorithm;
3050 constraints.copy_from(other_data.constraints);
3056template <
typename MatrixType,
typename PreconditionerType>
3059 const unsigned int n_iterations,
3060 const double smoothing_range,
3061 const unsigned int eig_cg_n_iterations,
3062 const double eig_cg_residual,
3063 const double max_eigenvalue,
3064 const EigenvalueAlgorithm eigenvalue_algorithm)
3065 :
internal::EigenvalueAlgorithmAdditionalData<PreconditionerType>(
3067 eig_cg_n_iterations,
3070 eigenvalue_algorithm)
3071 , relaxation(relaxation)
3072 , n_iterations(n_iterations)
3081 namespace PreconditionChebyshevImplementation
3089 template <
typename VectorType,
typename PreconditionerType>
3091 vector_updates(
const VectorType &rhs,
3092 const PreconditionerType &preconditioner,
3093 const unsigned int iteration_index,
3094 const double factor1,
3095 const double factor2,
3096 VectorType &solution_old,
3097 VectorType &temp_vector1,
3098 VectorType &temp_vector2,
3099 VectorType &solution)
3101 if (iteration_index == 0)
3103 solution.equ(factor2, rhs);
3104 preconditioner.vmult(solution_old, solution);
3106 else if (iteration_index == 1)
3109 temp_vector1.sadd(-1.0, 1.0, rhs);
3110 preconditioner.vmult(solution_old, temp_vector1);
3113 solution_old.sadd(factor2, 1 + factor1, solution);
3118 temp_vector1.sadd(-1.0, 1.0, rhs);
3119 preconditioner.vmult(temp_vector2, temp_vector1);
3122 solution_old.sadd(-factor1, factor2, temp_vector2);
3123 solution_old.add(1 + factor1, solution);
3126 solution.swap(solution_old);
3132 typename PreconditionerType,
3134 !has_vmult_with_std_functions_for_precondition<
3141 const PreconditionerType &preconditioner,
3142 const unsigned int iteration_index,
3143 const double factor1_,
3144 const double factor2_,
3153 const Number factor1 = factor1_;
3154 const Number factor1_plus_1 = 1. + factor1_;
3155 const Number factor2 = factor2_;
3157 if (iteration_index == 0)
3159 const auto solution_old_ptr = solution_old.
begin();
3162 preconditioner.vmult(solution_old, rhs);
3167 solution_old_ptr[i] = solution_old_ptr[i] * factor2;
3169 else if (iteration_index == 1)
3171 const auto solution_ptr = solution.
begin();
3172 const auto solution_old_ptr = solution_old.
begin();
3175 temp_vector1.
sadd(-1.0, 1.0, rhs);
3177 preconditioner.vmult(solution_old, temp_vector1);
3182 solution_old_ptr[i] =
3183 factor1_plus_1 * solution_ptr[i] + solution_old_ptr[i] * factor2;
3187 const auto solution_ptr = solution.
begin();
3188 const auto solution_old_ptr = solution_old.
begin();
3189 const auto temp_vector2_ptr = temp_vector2.
begin();
3192 temp_vector1.
sadd(-1.0, 1.0, rhs);
3194 preconditioner.vmult(temp_vector2, temp_vector1);
3199 solution_old_ptr[i] = factor1_plus_1 * solution_ptr[i] -
3200 factor1 * solution_old_ptr[i] +
3201 temp_vector2_ptr[i] * factor2;
3204 solution.
swap(solution_old);
3209 typename PreconditionerType,
3211 has_vmult_with_std_functions_for_precondition<
3218 const PreconditionerType &preconditioner,
3219 const unsigned int iteration_index,
3220 const double factor1_,
3221 const double factor2_,
3230 const Number factor1 = factor1_;
3231 const Number factor1_plus_1 = 1. + factor1_;
3232 const Number factor2 = factor2_;
3234 const auto rhs_ptr = rhs.
begin();
3235 const auto temp_vector1_ptr = temp_vector1.
begin();
3236 const auto temp_vector2_ptr = temp_vector2.
begin();
3237 const auto solution_ptr = solution.
begin();
3238 const auto solution_old_ptr = solution_old.
begin();
3240 if (iteration_index == 0)
3242 preconditioner.vmult(
3245 [&](
const auto start_range,
const auto end_range) {
3246 if (end_range > start_range)
3247 std::memset(solution.
begin() + start_range,
3249 sizeof(Number) * (end_range - start_range));
3251 [&](
const auto begin,
const auto end) {
3253 for (std::size_t i = begin; i <
end; ++i)
3254 solution_ptr[i] *= factor2;
3259 preconditioner.vmult(
3262 [&](
const auto begin,
const auto end) {
3264 std::memset(temp_vector2.
begin() + begin,
3266 sizeof(Number) * (end - begin));
3269 for (std::size_t i = begin; i <
end; ++i)
3270 temp_vector1_ptr[i] = rhs_ptr[i] - temp_vector1_ptr[i];
3272 [&](
const auto begin,
const auto end) {
3273 if (iteration_index == 1)
3276 for (std::size_t i = begin; i <
end; ++i)
3277 temp_vector2_ptr[i] = factor1_plus_1 * solution_ptr[i] +
3278 factor2 * temp_vector2_ptr[i];
3283 for (std::size_t i = begin; i <
end; ++i)
3284 temp_vector2_ptr[i] = factor1_plus_1 * solution_ptr[i] -
3285 factor1 * solution_old_ptr[i] +
3286 factor2 * temp_vector2_ptr[i];
3291 if (iteration_index > 0)
3293 solution_old.
swap(temp_vector2);
3294 solution_old.
swap(solution);
3301 template <
typename Number>
3302 struct VectorUpdater
3304 VectorUpdater(
const Number *rhs,
3305 const Number *matrix_diagonal_inverse,
3306 const unsigned int iteration_index,
3307 const Number factor1,
3308 const Number factor2,
3309 Number *solution_old,
3313 , matrix_diagonal_inverse(matrix_diagonal_inverse)
3314 , iteration_index(iteration_index)
3317 , solution_old(solution_old)
3318 , tmp_vector(tmp_vector)
3319 , solution(solution)
3323 apply_to_subrange(
const std::size_t begin,
const std::size_t end)
const
3329 const Number factor1 = this->factor1;
3330 const Number factor1_plus_1 = 1. + this->factor1;
3331 const Number factor2 = this->factor2;
3332 if (iteration_index == 0)
3335 for (std::size_t i = begin; i <
end; ++i)
3336 solution[i] = factor2 * matrix_diagonal_inverse[i] * rhs[i];
3338 else if (iteration_index == 1)
3342 for (std::size_t i = begin; i <
end; ++i)
3346 factor1_plus_1 * solution[i] +
3347 factor2 * matrix_diagonal_inverse[i] * (rhs[i] - tmp_vector[i]);
3354 for (std::size_t i = begin; i <
end; ++i)
3361 factor1_plus_1 * solution[i] - factor1 * solution_old[i] +
3362 factor2 * matrix_diagonal_inverse[i] * (rhs[i] - tmp_vector[i]);
3367 const Number *matrix_diagonal_inverse;
3368 const unsigned int iteration_index;
3369 const Number factor1;
3370 const Number factor2;
3371 mutable Number *solution_old;
3372 mutable Number *tmp_vector;
3373 mutable Number *solution;
3376 template <
typename Number>
3379 VectorUpdatesRange(
const VectorUpdater<Number> &updater,
3380 const std::size_t size)
3384 VectorUpdatesRange::apply_to_subrange(0, size);
3392 ~VectorUpdatesRange()
override =
default;
3395 apply_to_subrange(
const std::size_t begin,
3396 const std::size_t end)
const override
3398 updater.apply_to_subrange(begin, end);
3401 const VectorUpdater<Number> &updater;
3405 template <
typename Number>
3408 const ::Vector<Number> &rhs,
3410 const unsigned int iteration_index,
3411 const double factor1,
3412 const double factor2,
3418 VectorUpdater<Number> upd(rhs.begin(),
3419 jacobi.get_vector().begin(),
3423 solution_old.
begin(),
3424 temp_vector1.
begin(),
3426 VectorUpdatesRange<Number>(upd, rhs.size());
3429 if (iteration_index == 0)
3436 solution.
swap(temp_vector1);
3437 solution_old.
swap(temp_vector1);
3442 template <
typename Number>
3446 const ::DiagonalMatrix<
3448 const unsigned int iteration_index,
3449 const double factor1,
3450 const double factor2,
3458 VectorUpdater<Number> upd(rhs.
begin(),
3459 jacobi.get_vector().begin(),
3463 solution_old.
begin(),
3464 temp_vector1.
begin(),
3469 if (iteration_index == 0)
3476 solution.
swap(temp_vector1);
3477 solution_old.
swap(temp_vector1);
3488 typename PreconditionerType,
3492 PreconditionerType> &&
3493 !(has_vmult_with_std_functions_for_precondition<PreconditionerType,
3495 has_vmult_with_std_functions_for_precondition<
MatrixType,
3499 vmult_and_update(
const MatrixType &matrix,
3500 const PreconditionerType &preconditioner,
3501 const VectorType &rhs,
3502 const unsigned int iteration_index,
3503 const double factor1,
3504 const double factor2,
3505 VectorType &solution,
3506 VectorType &solution_old,
3507 VectorType &temp_vector1,
3508 VectorType &temp_vector2)
3510 if (iteration_index > 0)
3511 matrix.vmult(temp_vector1, solution);
3528 typename PreconditionerType,
3532 PreconditionerType> &&
3533 (has_vmult_with_std_functions_for_precondition<PreconditionerType,
3535 has_vmult_with_std_functions_for_precondition<
MatrixType,
3539 vmult_and_update(
const MatrixType &matrix,
3540 const PreconditionerType &preconditioner,
3541 const VectorType &rhs,
3542 const unsigned int iteration_index,
3543 const double factor1_,
3544 const double factor2_,
3545 VectorType &solution,
3546 VectorType &solution_old,
3547 VectorType &temp_vector1,
3548 VectorType &temp_vector2)
3550 using Number =
typename VectorType::value_type;
3552 const Number factor1 = factor1_;
3553 const Number factor1_plus_1 = 1. + factor1_;
3554 const Number factor2 = factor2_;
3556 if (iteration_index == 0)
3558 preconditioner.vmult(
3561 [&](
const unsigned int start_range,
const unsigned int end_range) {
3563 if (end_range > start_range)
3564 std::memset(solution.begin() + start_range,
3566 sizeof(Number) * (end_range - start_range));
3568 [&](
const unsigned int start_range,
const unsigned int end_range) {
3569 const auto solution_ptr = solution.begin();
3572 for (std::size_t i = start_range; i < end_range; ++i)
3573 solution_ptr[i] *= factor2;
3578 temp_vector1.reinit(rhs,
true);
3579 temp_vector2.reinit(rhs,
true);
3585 [&](
const unsigned int start_range,
const unsigned int end_range) {
3588 if (end_range > start_range)
3589 std::memset(temp_vector1.begin() + start_range,
3591 sizeof(Number) * (end_range - start_range));
3593 [&](
const unsigned int start_range,
const unsigned int end_range) {
3594 const auto rhs_ptr = rhs.begin();
3595 const auto tmp_ptr = temp_vector1.begin();
3598 for (std::size_t i = start_range; i < end_range; ++i)
3599 tmp_ptr[i] = rhs_ptr[i] - tmp_ptr[i];
3603 preconditioner.vmult(
3606 [&](
const unsigned int start_range,
const unsigned int end_range) {
3609 if (end_range > start_range)
3610 std::memset(temp_vector2.begin() + start_range,
3612 sizeof(Number) * (end_range - start_range));
3614 [&](
const unsigned int start_range,
const unsigned int end_range) {
3615 const auto solution_ptr = solution.begin();
3616 const auto solution_old_ptr = solution_old.begin();
3617 const auto tmp_ptr = temp_vector2.begin();
3619 if (iteration_index == 1)
3622 for (std::size_t i = start_range; i < end_range; ++i)
3624 factor1_plus_1 * solution_ptr[i] + factor2 * tmp_ptr[i];
3629 for (std::size_t i = start_range; i < end_range; ++i)
3630 tmp_ptr[i] = factor1_plus_1 * solution_ptr[i] -
3631 factor1 * solution_old_ptr[i] +
3632 factor2 * tmp_ptr[i];
3636 solution.swap(temp_vector2);
3637 solution_old.swap(temp_vector2);
3645 typename PreconditionerType,
3646 std::enable_if_t<has_vmult_with_std_functions<
MatrixType,
3648 PreconditionerType>,
3651 vmult_and_update(
const MatrixType &matrix,
3652 const PreconditionerType &preconditioner,
3653 const VectorType &rhs,
3654 const unsigned int iteration_index,
3655 const double factor1,
3656 const double factor2,
3657 VectorType &solution,
3658 VectorType &solution_old,
3659 VectorType &temp_vector1,
3662 using Number =
typename VectorType::value_type;
3663 VectorUpdater<Number> updater(rhs.begin(),
3664 preconditioner.get_vector().begin(),
3668 solution_old.begin(),
3669 temp_vector1.begin(),
3671 if (iteration_index > 0)
3675 [&](
const unsigned int start_range,
const unsigned int end_range) {
3678 if (end_range > start_range)
3679 std::memset(temp_vector1.begin() + start_range,
3681 sizeof(Number) * (end_range - start_range));
3683 [&](
const unsigned int start_range,
const unsigned int end_range) {
3684 if (end_range > start_range)
3685 updater.apply_to_subrange(start_range, end_range);
3688 updater.apply_to_subrange(0U, solution.locally_owned_size());
3691 if (iteration_index == 0)
3698 solution.swap(temp_vector1);
3699 solution_old.swap(temp_vector1);
3703 template <
typename MatrixType,
typename PreconditionerType>
3705 initialize_preconditioner(
3706 const MatrixType &matrix,
3707 std::shared_ptr<PreconditionerType> &preconditioner)
3710 (void)preconditioner;
3714 template <
typename MatrixType,
typename VectorType>
3716 initialize_preconditioner(
3717 const MatrixType &matrix,
3720 if (preconditioner.get() ==
nullptr || preconditioner->m() !=
matrix.m())
3722 if (preconditioner.get() ==
nullptr)
3724 std::make_shared<::DiagonalMatrix<VectorType>>();
3727 preconditioner->m() == 0,
3729 "Preconditioner appears to be initialized but not sized correctly"));
3732 if (preconditioner->m() !=
matrix.m())
3734 preconditioner->get_vector().reinit(
matrix.m());
3735 for (
typename VectorType::size_type i = 0; i <
matrix.m(); ++i)
3736 preconditioner->get_vector()(i) = 1. /
matrix.el(i, i);
3745template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3748 const double smoothing_range,
3749 const unsigned int eig_cg_n_iterations,
3750 const double eig_cg_residual,
3751 const double max_eigenvalue,
3752 const EigenvalueAlgorithm eigenvalue_algorithm,
3753 const PolynomialType polynomial_type)
3754 :
internal::EigenvalueAlgorithmAdditionalData<PreconditionerType>(
3756 eig_cg_n_iterations,
3759 eigenvalue_algorithm)
3761 , polynomial_type(polynomial_type)
3766template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3771 , eigenvalues_are_initialized(false)
3774 std::is_same_v<size_type, typename VectorType::size_type>,
3775 "PreconditionChebyshev and VectorType must have the same size_type.");
3780template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3783 const MatrixType &matrix,
3784 const AdditionalData &additional_data)
3787 data = additional_data;
3789 ExcMessage(
"The degree of the Chebyshev method must be positive."));
3790 internal::PreconditionChebyshevImplementation::initialize_preconditioner(
3791 matrix, data.preconditioner);
3792 eigenvalues_are_initialized =
false;
3797template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3801 eigenvalues_are_initialized =
false;
3802 theta = delta = 1.0;
3803 matrix_ptr =
nullptr;
3806 solution_old.reinit(empty_vector);
3807 temp_vector1.reinit(empty_vector);
3808 temp_vector2.reinit(empty_vector);
3810 data.preconditioner.reset();
3815template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3822 solution_old.reinit(src);
3823 temp_vector1.reinit(src,
true);
3825 auto info = internal::estimate_eigenvalues<MatrixType>(
3826 data, matrix_ptr, solution_old, temp_vector1, data.degree);
3828 const double alpha = (data.smoothing_range > 1. ?
3829 info.max_eigenvalue_estimate / data.smoothing_range :
3830 std::min(0.9 * info.max_eigenvalue_estimate,
3831 info.min_eigenvalue_estimate));
3840 const double actual_range = info.max_eigenvalue_estimate / alpha;
3841 const double sigma = (1. -
std::sqrt(1. / actual_range)) /
3843 const double eps = data.smoothing_range;
3848 1 +
static_cast<unsigned int>(
3853 info.degree = data.degree;
3858 (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
3859 (info.max_eigenvalue_estimate) :
3860 ((info.max_eigenvalue_estimate - alpha) * 0.5);
3863 ->theta = (info.max_eigenvalue_estimate + alpha) * 0.5;
3867 using NumberType =
typename VectorType::value_type;
3875 (std::is_same_v<VectorType,
3878 temp_vector2.
reinit(src, true);
3882 temp_vector2.reinit(empty_vector);
3887 ->eigenvalues_are_initialized =
true;
3894template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3897 VectorType &solution,
3898 const VectorType &rhs)
const
3900 std::lock_guard<std::mutex> lock(mutex);
3901 if (eigenvalues_are_initialized ==
false)
3902 estimate_eigenvalues(rhs);
3904 internal::PreconditionChebyshevImplementation::vmult_and_update(
3906 *data.preconditioner,
3910 (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
3911 (4. / (3. * delta)) :
3920 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
3923 double rhok = delta / theta, sigma = theta / delta;
3924 for (
unsigned int k = 0; k < data.degree - 1; ++k)
3926 double factor1 = 0.0;
3927 double factor2 = 0.0;
3929 if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
3931 factor1 = (2 * k + 1.) / (2 * k + 5.);
3932 factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
3936 const double rhokp = 1. / (2. * sigma - rhok);
3937 factor1 = rhokp * rhok;
3938 factor2 = 2. * rhokp / delta;
3942 internal::PreconditionChebyshevImplementation::vmult_and_update(
3944 *data.preconditioner,
3958template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3961 VectorType &solution,
3962 const VectorType &rhs)
const
3964 std::lock_guard<std::mutex> lock(mutex);
3965 if (eigenvalues_are_initialized ==
false)
3966 estimate_eigenvalues(rhs);
3968 internal::PreconditionChebyshevImplementation::vector_updates(
3970 *data.preconditioner,
3973 (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
3974 (4. / (3. * delta)) :
3981 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
3984 double rhok = delta / theta, sigma = theta / delta;
3985 for (
unsigned int k = 0; k < data.degree - 1; ++k)
3987 double factor1 = 0.0;
3988 double factor2 = 0.0;
3990 if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
3992 factor1 = (2 * k + 1.) / (2 * k + 5.);
3993 factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
3997 const double rhokp = 1. / (2. * sigma - rhok);
3998 factor1 = rhokp * rhok;
3999 factor2 = 2. * rhokp / delta;
4003 matrix_ptr->Tvmult(temp_vector1, solution);
4004 internal::PreconditionChebyshevImplementation::vector_updates(
4006 *data.preconditioner,
4019template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4022 VectorType &solution,
4023 const VectorType &rhs)
const
4025 std::lock_guard<std::mutex> lock(mutex);
4026 if (eigenvalues_are_initialized ==
false)
4027 estimate_eigenvalues(rhs);
4029 internal::PreconditionChebyshevImplementation::vmult_and_update(
4031 *data.preconditioner,
4035 (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
4036 (4. / (3. * delta)) :
4043 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
4046 double rhok = delta / theta, sigma = theta / delta;
4047 for (
unsigned int k = 0; k < data.degree - 1; ++k)
4049 double factor1 = 0.0;
4050 double factor2 = 0.0;
4052 if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
4054 factor1 = (2 * k + 1.) / (2 * k + 5.);
4055 factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
4059 const double rhokp = 1. / (2. * sigma - rhok);
4060 factor1 = rhokp * rhok;
4061 factor2 = 2. * rhokp / delta;
4065 internal::PreconditionChebyshevImplementation::vmult_and_update(
4067 *data.preconditioner,
4081template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4084 VectorType &solution,
4085 const VectorType &rhs)
const
4087 std::lock_guard<std::mutex> lock(mutex);
4088 if (eigenvalues_are_initialized ==
false)
4089 estimate_eigenvalues(rhs);
4091 matrix_ptr->Tvmult(temp_vector1, solution);
4092 internal::PreconditionChebyshevImplementation::vector_updates(
4094 *data.preconditioner,
4097 (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
4098 (4. / (3. * delta)) :
4105 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
4108 double rhok = delta / theta, sigma = theta / delta;
4109 for (
unsigned int k = 0; k < data.degree - 1; ++k)
4111 double factor1 = 0.0;
4112 double factor2 = 0.0;
4114 if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
4116 factor1 = (2 * k + 1.) / (2 * k + 5.);
4117 factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
4121 const double rhokp = 1. / (2. * sigma - rhok);
4122 factor1 = rhokp * rhok;
4123 factor2 = 2. * rhokp / delta;
4127 matrix_ptr->Tvmult(temp_vector1, solution);
4128 internal::PreconditionChebyshevImplementation::vector_updates(
4130 *data.preconditioner,
4143template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4146 PreconditionerType>::size_type
4150 return matrix_ptr->m();
4155template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
4158 PreconditionerType>::size_type
4162 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
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)
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
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.
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
Tpetra::CrsMatrix< Number, LO, GO, NodeType< MemorySpace > > MatrixType
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)
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)