16#ifndef dealii_precondition_h
17#define dealii_precondition_h
40template <
typename number>
42template <
typename number>
48 template <
typename,
typename>
110 template <
typename MatrixType>
118 template <
class VectorType>
120 vmult(VectorType &,
const VectorType &)
const;
126 template <
class VectorType>
128 Tvmult(VectorType &,
const VectorType &)
const;
133 template <
class VectorType>
141 template <
class VectorType>
239 template <
typename MatrixType>
246 template <
class VectorType>
248 vmult(VectorType &,
const VectorType &)
const;
254 template <
class VectorType>
256 Tvmult(VectorType &,
const VectorType &)
const;
260 template <
class VectorType>
268 template <
class VectorType>
358template <
typename MatrixType = SparseMatrix<
double>,
359 class VectorType = Vector<
double>>
367 const VectorType &)
const;
381 vmult(VectorType &dst,
const VectorType &src)
const;
402template <
typename MatrixType = SparseMatrix<
double>,
403 typename PreconditionerType = IdentityMatrix>
473 template <
class VectorType>
475 vmult(VectorType &,
const VectorType &)
const;
481 template <
class VectorType>
483 Tvmult(VectorType &,
const VectorType &)
const;
488 template <
class VectorType>
490 step(VectorType &x,
const VectorType &rhs)
const;
495 template <
class VectorType>
497 Tstep(VectorType &x,
const VectorType &rhs)
const;
529 template <
typename T,
typename VectorType>
530 using Tvmult_t =
decltype(
531 std::declval<T const>().Tvmult(std::declval<VectorType &>(),
532 std::declval<const VectorType &>()));
534 template <
typename T,
typename VectorType>
535 constexpr bool has_Tvmult = is_supported_operation<Tvmult_t, T, VectorType>;
537 template <
typename T,
typename VectorType>
538 using step_t =
decltype(
539 std::declval<T const>().step(std::declval<VectorType &>(),
540 std::declval<const VectorType &>()));
542 template <
typename T,
typename VectorType>
543 constexpr bool has_step = is_supported_operation<step_t, T, VectorType>;
545 template <
typename T,
typename VectorType>
547 decltype(std::declval<T const>().step(std::declval<VectorType &>(),
548 std::declval<const VectorType &>(),
549 std::declval<const double>()));
551 template <
typename T,
typename VectorType>
552 constexpr bool has_step_omega =
553 is_supported_operation<step_omega_t, T, VectorType>;
555 template <
typename T,
typename VectorType>
556 using Tstep_t =
decltype(
557 std::declval<T const>().Tstep(std::declval<VectorType &>(),
558 std::declval<const VectorType &>()));
560 template <
typename T,
typename VectorType>
561 constexpr bool has_Tstep = is_supported_operation<Tstep_t, T, VectorType>;
563 template <
typename T,
typename VectorType>
564 using Tstep_omega_t =
565 decltype(std::declval<T const>().Tstep(std::declval<VectorType &>(),
566 std::declval<const VectorType &>(),
567 std::declval<const double>()));
569 template <
typename T,
typename VectorType>
570 constexpr bool has_Tstep_omega =
571 is_supported_operation<Tstep_omega_t, T, VectorType>;
573 template <
typename T,
typename VectorType>
574 using jacobi_step_t =
decltype(
575 std::declval<T const>().Jacobi_step(std::declval<VectorType &>(),
576 std::declval<const VectorType &>(),
577 std::declval<const double>()));
579 template <
typename T,
typename VectorType>
580 constexpr bool has_jacobi_step =
581 is_supported_operation<jacobi_step_t, T, VectorType>;
583 template <
typename T,
typename VectorType>
584 using SOR_step_t =
decltype(
585 std::declval<T const>().SOR_step(std::declval<VectorType &>(),
586 std::declval<const VectorType &>(),
587 std::declval<const double>()));
589 template <
typename T,
typename VectorType>
590 constexpr bool has_SOR_step =
591 is_supported_operation<SOR_step_t, T, VectorType>;
593 template <
typename T,
typename VectorType>
594 using SSOR_step_t =
decltype(
595 std::declval<T const>().SSOR_step(std::declval<VectorType &>(),
596 std::declval<const VectorType &>(),
597 std::declval<const double>()));
599 template <
typename T,
typename VectorType>
600 constexpr bool has_SSOR_step =
601 is_supported_operation<SSOR_step_t, T, VectorType>;
603 template <
typename MatrixType>
604 class PreconditionJacobiImpl
607 PreconditionJacobiImpl(
const MatrixType &A,
const double relaxation)
609 , relaxation(relaxation)
612 template <
typename VectorType>
614 vmult(VectorType &dst,
const VectorType &src)
const
616 this->A->precondition_Jacobi(dst, src, this->relaxation);
619 template <
typename VectorType>
621 Tvmult(VectorType &dst,
const VectorType &src)
const
624 this->vmult(dst, src);
627 template <
typename VectorType,
628 typename std::enable_if<has_jacobi_step<MatrixType, VectorType>,
629 MatrixType>::type * =
nullptr>
631 step(VectorType &dst,
const VectorType &src)
const
633 this->A->Jacobi_step(dst, src, this->relaxation);
638 typename std::enable_if<!has_jacobi_step<MatrixType, VectorType>,
639 MatrixType>::type * =
nullptr>
641 step(VectorType &,
const VectorType &)
const
645 "Matrix A does not provide a Jacobi_step() function!"));
648 template <
typename VectorType>
650 Tstep(VectorType &dst,
const VectorType &src)
const
653 this->step(dst, src);
658 const double relaxation;
661 template <
typename MatrixType>
662 class PreconditionSORImpl
665 PreconditionSORImpl(
const MatrixType &A,
const double relaxation)
667 , relaxation(relaxation)
670 template <
typename VectorType>
672 vmult(VectorType &dst,
const VectorType &src)
const
674 this->A->precondition_SOR(dst, src, this->relaxation);
677 template <
typename VectorType>
679 Tvmult(VectorType &dst,
const VectorType &src)
const
681 this->A->precondition_TSOR(dst, src, this->relaxation);
684 template <
typename VectorType,
685 typename std::enable_if<has_SOR_step<MatrixType, VectorType>,
686 MatrixType>::type * =
nullptr>
688 step(VectorType &dst,
const VectorType &src)
const
690 this->A->SOR_step(dst, src, this->relaxation);
693 template <
typename VectorType,
694 typename std::enable_if<!has_SOR_step<MatrixType, VectorType>,
695 MatrixType>::type * =
nullptr>
697 step(VectorType &,
const VectorType &)
const
701 "Matrix A does not provide a SOR_step() function!"));
704 template <
typename VectorType,
705 typename std::enable_if<has_SOR_step<MatrixType, VectorType>,
706 MatrixType>::type * =
nullptr>
708 Tstep(VectorType &dst,
const VectorType &src)
const
710 this->A->TSOR_step(dst, src, this->relaxation);
713 template <
typename VectorType,
714 typename std::enable_if<!has_SOR_step<MatrixType, VectorType>,
715 MatrixType>::type * =
nullptr>
717 Tstep(VectorType &,
const VectorType &)
const
721 "Matrix A does not provide a TSOR_step() function!"));
726 const double relaxation;
729 template <
typename MatrixType>
730 class PreconditionSSORImpl
733 using size_type =
typename MatrixType::size_type;
735 PreconditionSSORImpl(
const MatrixType &A,
const double relaxation)
737 , relaxation(relaxation)
748 const size_type n = this->A->n();
749 pos_right_of_diagonal.resize(n,
static_cast<std::size_t
>(-1));
750 for (size_type row = 0; row < n; ++row)
757 typename MatrixType::value_type>::const_iterator it =
759 for (; it < mat->
end(row); ++it)
760 if (it->column() > row)
762 pos_right_of_diagonal[row] = it - mat->
begin();
767 template <
typename VectorType>
769 vmult(VectorType &dst,
const VectorType &src)
const
771 this->A->precondition_SSOR(dst,
774 pos_right_of_diagonal);
777 template <
typename VectorType>
779 Tvmult(VectorType &dst,
const VectorType &src)
const
781 this->A->precondition_SSOR(dst,
784 pos_right_of_diagonal);
787 template <
typename VectorType,
788 typename std::enable_if<has_SSOR_step<MatrixType, VectorType>,
789 MatrixType>::type * =
nullptr>
791 step(VectorType &dst,
const VectorType &src)
const
793 this->A->SSOR_step(dst, src, this->relaxation);
796 template <
typename VectorType,
797 typename std::enable_if<!has_SSOR_step<MatrixType, VectorType>,
798 MatrixType>::type * =
nullptr>
800 step(VectorType &,
const VectorType &)
const
804 "Matrix A does not provide a SSOR_step() function!"));
807 template <
typename VectorType>
809 Tstep(VectorType &dst,
const VectorType &src)
const
812 this->step(dst, src);
817 const double relaxation;
823 std::vector<std::size_t> pos_right_of_diagonal;
826 template <
typename MatrixType>
827 class PreconditionPSORImpl
830 using size_type =
typename MatrixType::size_type;
832 PreconditionPSORImpl(
const MatrixType & A,
833 const double relaxation,
834 const std::vector<size_type> &permutation,
835 const std::vector<size_type> &inverse_permutation)
837 , relaxation(relaxation)
838 , permutation(permutation)
839 , inverse_permutation(inverse_permutation)
842 template <
typename VectorType>
844 vmult(VectorType &dst,
const VectorType &src)
const
847 this->A->PSOR(dst, permutation, inverse_permutation, this->relaxation);
850 template <
typename VectorType>
852 Tvmult(VectorType &dst,
const VectorType &src)
const
855 this->A->TPSOR(dst, permutation, inverse_permutation, this->relaxation);
860 const double relaxation;
862 const std::vector<size_type> &permutation;
863 const std::vector<size_type> &inverse_permutation;
868 typename PreconditionerType,
870 typename std::enable_if<has_step_omega<PreconditionerType, VectorType>,
871 PreconditionerType>::type * =
nullptr>
873 step(
const MatrixType &,
874 const PreconditionerType &preconditioner,
876 const VectorType & src,
877 const double relaxation,
881 preconditioner.step(dst, src, relaxation);
886 typename PreconditionerType,
888 typename std::enable_if<!has_step_omega<PreconditionerType, VectorType> &&
889 has_step<PreconditionerType, VectorType>,
890 PreconditionerType>::type * =
nullptr>
892 step(
const MatrixType &,
893 const PreconditionerType &preconditioner,
895 const VectorType & src,
896 const double relaxation,
904 preconditioner.step(dst, src);
909 typename PreconditionerType,
911 typename std::enable_if<!has_step_omega<PreconditionerType, VectorType> &&
912 !has_step<PreconditionerType, VectorType>,
913 PreconditionerType>::type * =
nullptr>
915 step(
const MatrixType & A,
916 const PreconditionerType &preconditioner,
918 const VectorType & src,
919 const double relaxation,
920 VectorType & residual,
923 residual.reinit(dst,
true);
924 tmp.reinit(dst,
true);
926 A.vmult(residual, dst);
927 residual.sadd(-1.0, 1.0, src);
929 preconditioner.vmult(tmp, residual);
930 dst.add(relaxation, tmp);
935 typename PreconditionerType,
937 typename std::enable_if<has_Tstep_omega<PreconditionerType, VectorType>,
938 PreconditionerType>::type * =
nullptr>
940 Tstep(
const MatrixType &,
941 const PreconditionerType &preconditioner,
943 const VectorType & src,
944 const double relaxation,
948 preconditioner.Tstep(dst, src, relaxation);
951 template <
typename MatrixType,
952 typename PreconditionerType,
954 typename std::enable_if<
955 !has_Tstep_omega<PreconditionerType, VectorType> &&
956 has_Tstep<PreconditionerType, VectorType>,
957 PreconditionerType>::type * =
nullptr>
959 Tstep(
const MatrixType &,
960 const PreconditionerType &preconditioner,
962 const VectorType & src,
963 const double relaxation,
971 preconditioner.Tstep(dst, src);
974 template <
typename MatrixType,
976 typename std::enable_if<has_Tvmult<MatrixType, VectorType>,
977 MatrixType>::type * =
nullptr>
979 Tvmult(
const MatrixType &A, VectorType &dst,
const VectorType &src)
984 template <
typename MatrixType,
986 typename std::enable_if<!has_Tvmult<MatrixType, VectorType>,
987 MatrixType>::type * =
nullptr>
989 Tvmult(
const MatrixType &, VectorType &,
const VectorType &)
992 ExcMessage(
"Matrix A does not provide a Tvmult() function!"));
995 template <
typename MatrixType,
996 typename PreconditionerType,
998 typename std::enable_if<
999 !has_Tstep_omega<PreconditionerType, VectorType> &&
1000 !has_Tstep<PreconditionerType, VectorType>,
1001 PreconditionerType>::type * =
nullptr>
1003 Tstep(
const MatrixType & A,
1004 const PreconditionerType &preconditioner,
1006 const VectorType & src,
1007 const double relaxation,
1008 VectorType & residual,
1011 residual.reinit(dst,
true);
1012 tmp.reinit(dst,
true);
1014 Tvmult(A, residual, dst);
1015 residual.sadd(-1.0, 1.0, src);
1017 Tvmult(preconditioner, tmp, residual);
1018 dst.add(relaxation, tmp);
1021 template <
typename MatrixType,
1022 typename PreconditionerType,
1023 typename VectorType>
1025 step_operations(
const MatrixType & A,
1026 const PreconditionerType &preconditioner,
1028 const VectorType & src,
1029 const double relaxation,
1032 const unsigned int i,
1033 const bool transposed)
1038 Tvmult(preconditioner, dst, src);
1040 preconditioner.vmult(dst, src);
1042 if (relaxation != 1.0)
1048 Tstep(A, preconditioner, dst, src, relaxation, tmp1, tmp2);
1050 step(A, preconditioner, dst, src, relaxation, tmp1, tmp2);
1054 template <
typename MatrixType,
1055 typename VectorType,
1056 typename std::enable_if<!IsBlockVector<VectorType>::value,
1057 VectorType>::type * =
nullptr>
1059 step_operations(
const MatrixType & A,
1062 const VectorType & src,
1063 const double relaxation,
1064 VectorType & residual,
1066 const unsigned int i,
1067 const bool transposed)
1071 const auto dst_ptr = dst.begin();
1072 const auto src_ptr = src.begin();
1073 const auto diag_ptr = preconditioner.get_vector().begin();
1075 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1076 dst_ptr[i] = relaxation * src_ptr[i] * diag_ptr[i];
1080 residual.reinit(src,
true);
1082 const auto dst_ptr = dst.begin();
1083 const auto src_ptr = src.begin();
1084 const auto residual_ptr = residual.begin();
1085 const auto diag_ptr = preconditioner.get_vector().begin();
1088 A.Tvmult(residual, dst);
1090 A.vmult(residual, dst);
1092 for (
unsigned int i = 0; i < dst.locally_owned_size(); ++i)
1094 relaxation * (src_ptr[i] - residual_ptr[i]) * diag_ptr[i];
1131template <
typename MatrixType = SparseMatrix<
double>>
1135 internal::PreconditionRelaxation::PreconditionJacobiImpl<MatrixType>>
1138 internal::PreconditionRelaxation::PreconditionJacobiImpl<MatrixType>;
1201template <
typename MatrixType = SparseMatrix<
double>>
1205 internal::PreconditionRelaxation::PreconditionSORImpl<MatrixType>>
1208 internal::PreconditionRelaxation::PreconditionSORImpl<MatrixType>;
1253template <
typename MatrixType = SparseMatrix<
double>>
1257 internal::PreconditionRelaxation::PreconditionSSORImpl<MatrixType>>
1260 internal::PreconditionRelaxation::PreconditionSSORImpl<MatrixType>;
1309template <
typename MatrixType = SparseMatrix<
double>>
1313 internal::PreconditionRelaxation::PreconditionPSORImpl<MatrixType>>
1316 internal::PreconditionRelaxation::PreconditionPSORImpl<MatrixType>;
1373 const std::vector<size_type> & permutation,
1374 const std::vector<size_type> & inverse_permutation,
1591template <
typename MatrixType = SparseMatrix<
double>,
1592 typename VectorType = Vector<
double>,
1593 typename PreconditionerType = DiagonalMatrix<VectorType>>
1739 vmult(VectorType &dst,
const VectorType &src)
const;
1746 Tvmult(VectorType &dst,
const VectorType &src)
const;
1752 step(VectorType &dst,
const VectorType &src)
const;
1758 Tstep(VectorType &dst,
const VectorType &src)
const;
1826 EigenvalueInformation
1895template <
typename MatrixType>
1905template <
class VectorType>
1914template <
class VectorType>
1921template <
class VectorType>
1930template <
class VectorType>
1962 const double relaxation)
1963 : relaxation(relaxation)
1972 AdditionalData add_data;
1973 relaxation = add_data.relaxation;
1987template <
typename MatrixType>
1990 const MatrixType & matrix,
2000template <
class VectorType>
2005 std::is_same<size_type, typename VectorType::size_type>::value,
2006 "PreconditionRichardson and VectorType must have the same size_type.");
2013template <
class VectorType>
2018 std::is_same<size_type, typename VectorType::size_type>::value,
2019 "PreconditionRichardson and VectorType must have the same size_type.");
2024template <
class VectorType>
2029 std::is_same<size_type, typename VectorType::size_type>::value,
2030 "PreconditionRichardson and VectorType must have the same size_type.");
2037template <
class VectorType>
2042 std::is_same<size_type, typename VectorType::size_type>::value,
2043 "PreconditionRichardson and VectorType must have the same size_type.");
2064template <
typename MatrixType,
typename PreconditionerType>
2067 const MatrixType & rA,
2068 const AdditionalData ¶meters)
2071 relaxation = parameters.relaxation;
2075 preconditioner = parameters.preconditioner;
2076 n_iterations = parameters.n_iterations;
2080template <
typename MatrixType,
typename PreconditionerType>
2085 preconditioner =
nullptr;
2088template <
typename MatrixType,
typename PreconditionerType>
2097template <
typename MatrixType,
typename PreconditionerType>
2106template <
typename MatrixType,
typename PreconditionerType>
2107template <
class VectorType>
2111 const VectorType &src)
const
2116 VectorType tmp1, tmp2;
2118 for (
unsigned int i = 0; i < n_iterations; ++i)
2119 internal::PreconditionRelaxation::step_operations(
2120 *A, *preconditioner, dst, src, relaxation, tmp1, tmp2, i,
false);
2123template <
typename MatrixType,
typename PreconditionerType>
2124template <
class VectorType>
2128 const VectorType &src)
const
2133 VectorType tmp1, tmp2;
2135 for (
unsigned int i = 0; i < n_iterations; ++i)
2136 internal::PreconditionRelaxation::step_operations(
2137 *A, *preconditioner, dst, src, relaxation, tmp1, tmp2, i,
true);
2140template <
typename MatrixType,
typename PreconditionerType>
2141template <
class VectorType>
2145 const VectorType &src)
const
2150 VectorType tmp1, tmp2;
2152 for (
unsigned int i = 1; i <= n_iterations; ++i)
2153 internal::PreconditionRelaxation::step_operations(
2154 *A, *preconditioner, dst, src, relaxation, tmp1, tmp2, i,
false);
2157template <
typename MatrixType,
typename PreconditionerType>
2158template <
class VectorType>
2162 const VectorType &src)
const
2167 VectorType tmp1, tmp2;
2169 for (
unsigned int i = 1; i <= n_iterations; ++i)
2170 internal::PreconditionRelaxation::step_operations(
2171 *A, *preconditioner, dst, src, relaxation, tmp1, tmp2, i,
true);
2176template <
typename MatrixType>
2179 const AdditionalData ¶meters_in)
2183 AdditionalData parameters;
2184 parameters.relaxation = 1.0;
2185 parameters.n_iterations = parameters_in.n_iterations;
2186 parameters.preconditioner =
2187 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
2189 this->BaseClass::initialize(A, parameters);
2194template <
typename MatrixType>
2197 const AdditionalData ¶meters_in)
2201 AdditionalData parameters;
2202 parameters.relaxation = 1.0;
2203 parameters.n_iterations = parameters_in.n_iterations;
2204 parameters.preconditioner =
2205 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
2207 this->BaseClass::initialize(A, parameters);
2212template <
typename MatrixType>
2215 const AdditionalData ¶meters_in)
2219 AdditionalData parameters;
2220 parameters.relaxation = 1.0;
2221 parameters.n_iterations = parameters_in.n_iterations;
2222 parameters.preconditioner =
2223 std::make_shared<PreconditionerType>(A, parameters_in.relaxation);
2225 this->BaseClass::initialize(A, parameters);
2232template <
typename MatrixType>
2235 const MatrixType & A,
2236 const std::vector<size_type> & p,
2237 const std::vector<size_type> & ip,
2238 const typename BaseClass::AdditionalData ¶meters_in)
2242 typename BaseClass::AdditionalData parameters;
2243 parameters.relaxation = 1.0;
2244 parameters.n_iterations = parameters_in.n_iterations;
2245 parameters.preconditioner =
2246 std::make_shared<PreconditionerType>(A, parameters_in.relaxation, p, ip);
2248 this->BaseClass::initialize(A, parameters);
2252template <
typename MatrixType>
2255 const AdditionalData &additional_data)
2258 additional_data.permutation,
2259 additional_data.inverse_permutation,
2260 additional_data.parameters);
2263template <
typename MatrixType>
2265 const std::vector<size_type> &permutation,
2266 const std::vector<size_type> &inverse_permutation,
2269 : permutation(permutation)
2270 , inverse_permutation(inverse_permutation)
2271 , parameters(parameters)
2278template <
typename MatrixType,
class VectorType>
2280 const MatrixType & M,
2281 const function_ptr method)
2283 , precondition(method)
2288template <
typename MatrixType,
class VectorType>
2292 const VectorType &src)
const
2294 (
matrix.*precondition)(dst, src);
2299template <
typename MatrixType,
typename PreconditionerType>
2301 AdditionalData(
const double relaxation,
const unsigned int n_iterations)
2302 : relaxation(relaxation)
2303 , n_iterations(n_iterations)
2312 namespace PreconditionChebyshevImplementation
2320 template <
typename VectorType,
typename PreconditionerType>
2322 vector_updates(
const VectorType & rhs,
2323 const PreconditionerType &preconditioner,
2324 const unsigned int iteration_index,
2325 const double factor1,
2326 const double factor2,
2327 VectorType & solution_old,
2328 VectorType & temp_vector1,
2329 VectorType & temp_vector2,
2330 VectorType & solution)
2332 if (iteration_index == 0)
2334 solution.equ(factor2, rhs);
2335 preconditioner.vmult(solution_old, solution);
2337 else if (iteration_index == 1)
2340 temp_vector1.sadd(-1.0, 1.0, rhs);
2341 preconditioner.vmult(solution_old, temp_vector1);
2344 solution_old.sadd(factor2, 1 + factor1, solution);
2349 temp_vector1.sadd(-1.0, 1.0, rhs);
2350 preconditioner.vmult(temp_vector2, temp_vector1);
2353 solution_old.sadd(-factor1, factor2, temp_vector2);
2354 solution_old.add(1 + factor1, solution);
2357 solution.swap(solution_old);
2363 template <
typename Number>
2364 struct VectorUpdater
2366 VectorUpdater(
const Number * rhs,
2367 const Number * matrix_diagonal_inverse,
2368 const unsigned int iteration_index,
2369 const Number factor1,
2370 const Number factor2,
2371 Number * solution_old,
2372 Number * tmp_vector,
2375 , matrix_diagonal_inverse(matrix_diagonal_inverse)
2376 , iteration_index(iteration_index)
2379 , solution_old(solution_old)
2380 , tmp_vector(tmp_vector)
2381 , solution(solution)
2385 apply_to_subrange(
const std::size_t begin,
const std::size_t end)
const
2391 const Number factor1 = this->factor1;
2392 const Number factor1_plus_1 = 1. + this->factor1;
2393 const Number factor2 = this->factor2;
2394 if (iteration_index == 0)
2397 for (std::size_t i = begin; i <
end; ++i)
2398 solution[i] = factor2 * matrix_diagonal_inverse[i] * rhs[i];
2400 else if (iteration_index == 1)
2404 for (std::size_t i = begin; i <
end; ++i)
2408 factor1_plus_1 * solution[i] +
2409 factor2 * matrix_diagonal_inverse[i] * (rhs[i] - tmp_vector[i]);
2416 for (std::size_t i = begin; i <
end; ++i)
2418 factor1_plus_1 * solution[i] - factor1 * solution_old[i] +
2419 factor2 * matrix_diagonal_inverse[i] * (rhs[i] - tmp_vector[i]);
2424 const Number * matrix_diagonal_inverse;
2425 const unsigned int iteration_index;
2426 const Number factor1;
2427 const Number factor2;
2428 mutable Number * solution_old;
2429 mutable Number * tmp_vector;
2430 mutable Number * solution;
2433 template <
typename Number>
2436 VectorUpdatesRange(
const VectorUpdater<Number> &updater,
2437 const std::size_t size)
2441 VectorUpdatesRange::apply_to_subrange(0, size);
2449 ~VectorUpdatesRange()
override =
default;
2452 apply_to_subrange(
const std::size_t begin,
2453 const std::size_t end)
const override
2455 updater.apply_to_subrange(begin, end);
2458 const VectorUpdater<Number> &updater;
2462 template <
typename Number>
2464 vector_updates(const ::Vector<Number> & rhs,
2466 const unsigned int iteration_index,
2467 const double factor1,
2468 const double factor2,
2474 VectorUpdater<Number> upd(rhs.begin(),
2475 jacobi.get_vector().begin(),
2479 solution_old.
begin(),
2480 temp_vector1.
begin(),
2482 VectorUpdatesRange<Number>(upd, rhs.size());
2485 if (iteration_index == 0)
2490 else if (iteration_index == 1)
2492 solution.
swap(temp_vector1);
2493 solution_old.
swap(temp_vector1);
2496 solution.
swap(solution_old);
2500 template <
typename Number>
2506 const unsigned int iteration_index,
2507 const double factor1,
2508 const double factor2,
2516 VectorUpdater<Number> upd(rhs.
begin(),
2517 jacobi.get_vector().begin(),
2521 solution_old.
begin(),
2522 temp_vector1.
begin(),
2527 if (iteration_index == 0)
2532 else if (iteration_index == 1)
2534 solution.
swap(temp_vector1);
2535 solution_old.
swap(temp_vector1);
2538 solution.
swap(solution_old);
2544 template <
typename MatrixType,
typename VectorType>
2545 using vmult_functions_t =
decltype(std::declval<MatrixType const>().vmult(
2546 std::declval<VectorType &>(),
2547 std::declval<const VectorType &>(),
2549 const std::function<
void(
const unsigned int,
const unsigned int)> &>(),
2550 std::declval<
const std::function<
void(
const unsigned int,
2551 const unsigned int)> &>()));
2553 template <
typename MatrixType,
2554 typename VectorType,
2555 typename PreconditionerType>
2556 constexpr bool has_vmult_with_std_functions =
2557 is_supported_operation<vmult_functions_t, MatrixType, VectorType>
2558 && std::is_same<PreconditionerType, DiagonalMatrix<VectorType>>::value
2567 typename MatrixType,
2568 typename VectorType,
2569 typename PreconditionerType,
2570 typename std::enable_if<!has_vmult_with_std_functions<MatrixType,
2572 PreconditionerType>,
2573 int>::type * =
nullptr>
2575 vmult_and_update(
const MatrixType & matrix,
2576 const PreconditionerType &preconditioner,
2577 const VectorType & rhs,
2578 const unsigned int iteration_index,
2579 const double factor1,
2580 const double factor2,
2581 VectorType & solution,
2582 VectorType & solution_old,
2583 VectorType & temp_vector1,
2584 VectorType & temp_vector2)
2586 if (iteration_index > 0)
2587 matrix.vmult(temp_vector1, solution);
2600 typename MatrixType,
2601 typename VectorType,
2602 typename PreconditionerType,
2603 typename std::enable_if<has_vmult_with_std_functions<MatrixType,
2605 PreconditionerType>,
2606 int>::type * =
nullptr>
2608 vmult_and_update(
const MatrixType & matrix,
2609 const PreconditionerType &preconditioner,
2610 const VectorType & rhs,
2611 const unsigned int iteration_index,
2612 const double factor1,
2613 const double factor2,
2614 VectorType & solution,
2615 VectorType & solution_old,
2616 VectorType & temp_vector1,
2619 using Number =
typename VectorType::value_type;
2620 VectorUpdater<Number> updater(rhs.begin(),
2621 preconditioner.get_vector().begin(),
2625 solution_old.begin(),
2626 temp_vector1.begin(),
2628 if (iteration_index > 0)
2632 [&](
const unsigned int start_range,
const unsigned int end_range) {
2635 if (end_range > start_range)
2636 std::memset(temp_vector1.begin() + start_range,
2638 sizeof(Number) * (end_range - start_range));
2640 [&](
const unsigned int start_range,
const unsigned int end_range) {
2641 if (end_range > start_range)
2642 updater.apply_to_subrange(start_range, end_range);
2645 updater.apply_to_subrange(0U, solution.locally_owned_size());
2648 if (iteration_index == 0)
2653 else if (iteration_index == 1)
2655 solution.swap(temp_vector1);
2656 solution_old.swap(temp_vector1);
2659 solution.swap(solution_old);
2662 template <
typename MatrixType,
typename PreconditionerType>
2664 initialize_preconditioner(
2665 const MatrixType & matrix,
2666 std::shared_ptr<PreconditionerType> &preconditioner)
2669 (void)preconditioner;
2673 template <
typename MatrixType,
typename VectorType>
2675 initialize_preconditioner(
2676 const MatrixType & matrix,
2679 if (preconditioner.get() ==
nullptr || preconditioner->m() !=
matrix.m())
2681 if (preconditioner.get() ==
nullptr)
2682 preconditioner = std::make_shared<DiagonalMatrix<VectorType>>();
2685 preconditioner->m() == 0,
2687 "Preconditioner appears to be initialized but not sized correctly"));
2690 if (preconditioner->m() !=
matrix.m())
2692 preconditioner->get_vector().reinit(
matrix.m());
2693 for (
typename VectorType::size_type i = 0; i <
matrix.m(); ++i)
2694 preconditioner->get_vector()(i) = 1. /
matrix.el(i, i);
2699 template <
typename VectorType>
2701 set_initial_guess(VectorType &vector)
2703 vector = 1. /
std::sqrt(
static_cast<double>(vector.size()));
2704 if (vector.locally_owned_elements().is_element(0))
2708 template <
typename Number>
2716 for (
unsigned int i = 0; i < vector.
size(); ++i)
2719 const Number mean_value = vector.
mean_value();
2720 vector.
add(-mean_value);
2723 template <
typename Number>
2741 const Number mean_value = vector.
mean_value();
2742 vector.
add(-mean_value);
2745 template <
typename Number>
2750 for (
unsigned int block = 0; block < vector.
n_blocks(); ++block)
2751 set_initial_guess(vector.
block(block));
2755# ifdef DEAL_II_COMPILER_CUDA_AWARE
2756 template <
typename Number>
2759 const unsigned int locally_owned_size,
2763 const unsigned int index = threadIdx.x + blockDim.x * blockIdx.x;
2764 if (index < locally_owned_size)
2768 template <
typename Number>
2787 set_initial_guess_kernel<<<n_blocks, CUDAWrappers::block_size>>>(
2788 first_local_range, n_local_elements, vector.
get_values());
2791 const Number mean_value = vector.
mean_value();
2792 vector.
add(-mean_value);
2796 struct EigenvalueTracker
2805 std::vector<double>
values;
2810 template <
typename MatrixType,
2811 typename VectorType,
2812 typename PreconditionerType>
2814 power_iteration(
const MatrixType & matrix,
2815 VectorType & eigenvector,
2816 const PreconditionerType &preconditioner,
2817 const unsigned int n_iterations)
2819 double eigenvalue_estimate = 0.;
2820 eigenvector /= eigenvector.l2_norm();
2821 VectorType vector1, vector2;
2822 vector1.reinit(eigenvector,
true);
2823 if (!std::is_same<PreconditionerType, PreconditionIdentity>::value)
2824 vector2.reinit(eigenvector,
true);
2825 for (
unsigned int i = 0; i < n_iterations; ++i)
2827 if (!std::is_same<PreconditionerType, PreconditionIdentity>::value)
2829 matrix.vmult(vector2, eigenvector);
2830 preconditioner.vmult(vector1, vector2);
2833 matrix.vmult(vector1, eigenvector);
2835 eigenvalue_estimate = eigenvector * vector1;
2837 vector1 /= vector1.l2_norm();
2838 eigenvector.swap(vector1);
2840 return eigenvalue_estimate;
2847template <
typename MatrixType,
class VectorType,
typename PreconditionerType>
2850 const double smoothing_range,
2851 const unsigned int eig_cg_n_iterations,
2852 const double eig_cg_residual,
2853 const double max_eigenvalue,
2854 const EigenvalueAlgorithm eigenvalue_algorithm)
2856 , smoothing_range(smoothing_range)
2857 , eig_cg_n_iterations(eig_cg_n_iterations)
2858 , eig_cg_residual(eig_cg_residual)
2859 , max_eigenvalue(max_eigenvalue)
2860 , eigenvalue_algorithm(eigenvalue_algorithm)
2865template <
typename MatrixType,
class VectorType,
typename PreconditionerType>
2868 PreconditionerType>::AdditionalData &
2872 degree = other_data.
degree;
2873 smoothing_range = other_data.smoothing_range;
2874 eig_cg_n_iterations = other_data.eig_cg_n_iterations;
2875 eig_cg_residual = other_data.eig_cg_residual;
2876 max_eigenvalue = other_data.max_eigenvalue;
2877 preconditioner = other_data.preconditioner;
2878 eigenvalue_algorithm = other_data.eigenvalue_algorithm;
2879 constraints.copy_from(other_data.constraints);
2886template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
2891 , eigenvalues_are_initialized(false)
2894 std::is_same<size_type, typename VectorType::size_type>::value,
2895 "PreconditionChebyshev and VectorType must have the same size_type.");
2900template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
2903 const MatrixType & matrix,
2904 const AdditionalData &additional_data)
2907 data = additional_data;
2909 ExcMessage(
"The degree of the Chebyshev method must be positive."));
2910 internal::PreconditionChebyshevImplementation::initialize_preconditioner(
2911 matrix, data.preconditioner);
2912 eigenvalues_are_initialized =
false;
2917template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
2921 eigenvalues_are_initialized =
false;
2922 theta = delta = 1.0;
2923 matrix_ptr =
nullptr;
2925 VectorType empty_vector;
2926 solution_old.reinit(empty_vector);
2927 temp_vector1.reinit(empty_vector);
2928 temp_vector2.reinit(empty_vector);
2930 data.preconditioner.reset();
2935template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
2938 PreconditionerType>::EigenvalueInformation
2946 EigenvalueInformation info{};
2948 solution_old.reinit(src);
2949 temp_vector1.reinit(src,
true);
2951 if (data.eig_cg_n_iterations > 0)
2953 Assert(data.eig_cg_n_iterations > 2,
2955 "Need to set at least two iterations to find eigenvalues."));
2957 internal::PreconditionChebyshevImplementation::EigenvalueTracker
2963 internal::PreconditionChebyshevImplementation::set_initial_guess(
2965 data.constraints.set_zero(temp_vector1);
2967 if (data.eigenvalue_algorithm ==
2968 AdditionalData::EigenvalueAlgorithm::lanczos)
2977 solver.connect_eigenvalues_slot(
2978 [&eigenvalue_tracker](
const std::vector<double> &
eigenvalues) {
2982 solver.solve(*matrix_ptr,
2985 *data.preconditioner);
2987 info.cg_iterations = control.last_step();
2989 else if (data.eigenvalue_algorithm ==
2990 AdditionalData::EigenvalueAlgorithm::power_iteration)
2993 ExcMessage(
"Cannot estimate the minimal eigenvalue with the "
2994 "power iteration"));
2996 eigenvalue_tracker.values.push_back(
2997 internal::PreconditionChebyshevImplementation::power_iteration(
3000 *data.preconditioner,
3001 data.eig_cg_n_iterations));
3007 if (eigenvalue_tracker.values.empty())
3008 info.min_eigenvalue_estimate = info.max_eigenvalue_estimate = 1.;
3011 info.min_eigenvalue_estimate = eigenvalue_tracker.values.front();
3015 info.max_eigenvalue_estimate = 1.2 * eigenvalue_tracker.values.back();
3020 info.max_eigenvalue_estimate = data.max_eigenvalue;
3021 info.min_eigenvalue_estimate = data.max_eigenvalue / data.smoothing_range;
3024 const double alpha = (data.smoothing_range > 1. ?
3025 info.max_eigenvalue_estimate / data.smoothing_range :
3026 std::min(0.9 * info.max_eigenvalue_estimate,
3027 info.min_eigenvalue_estimate));
3036 const double actual_range = info.max_eigenvalue_estimate / alpha;
3037 const double sigma = (1. -
std::sqrt(1. / actual_range)) /
3039 const double eps = data.smoothing_range;
3044 1 +
static_cast<unsigned int>(
3049 info.degree = data.degree;
3053 ->delta = (info.max_eigenvalue_estimate - alpha) * 0.5;
3056 ->theta = (info.max_eigenvalue_estimate + alpha) * 0.5;
3060 using NumberType =
typename VectorType::value_type;
3064 ((std::is_same<VectorType,
3068 (std::is_same<VectorType,
3069 LinearAlgebra::distributed::
3070 Vector<NumberType, MemorySpace::CUDA>>::value ==
3072 temp_vector2.reinit(src,
true);
3075 VectorType empty_vector;
3076 temp_vector2.reinit(empty_vector);
3081 ->eigenvalues_are_initialized =
true;
3088template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3091 VectorType & solution,
3092 const VectorType &rhs)
const
3094 std::lock_guard<std::mutex> lock(mutex);
3095 if (eigenvalues_are_initialized ==
false)
3096 estimate_eigenvalues(rhs);
3098 internal::PreconditionChebyshevImplementation::vmult_and_update(
3100 *data.preconditioner,
3112 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
3115 double rhok = delta / theta, sigma = theta / delta;
3116 for (
unsigned int k = 0; k < data.degree - 1; ++k)
3118 const double rhokp = 1. / (2. * sigma - rhok);
3119 const double factor1 = rhokp * rhok, factor2 = 2. * rhokp / delta;
3121 internal::PreconditionChebyshevImplementation::vmult_and_update(
3123 *data.preconditioner,
3137template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3140 VectorType & solution,
3141 const VectorType &rhs)
const
3143 std::lock_guard<std::mutex> lock(mutex);
3144 if (eigenvalues_are_initialized ==
false)
3145 estimate_eigenvalues(rhs);
3147 internal::PreconditionChebyshevImplementation::vector_updates(
3149 *data.preconditioner,
3158 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
3161 double rhok = delta / theta, sigma = theta / delta;
3162 for (
unsigned int k = 0; k < data.degree - 1; ++k)
3164 const double rhokp = 1. / (2. * sigma - rhok);
3165 const double factor1 = rhokp * rhok, factor2 = 2. * rhokp / delta;
3167 matrix_ptr->Tvmult(temp_vector1, solution);
3168 internal::PreconditionChebyshevImplementation::vector_updates(
3170 *data.preconditioner,
3183template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3186 VectorType & solution,
3187 const VectorType &rhs)
const
3189 std::lock_guard<std::mutex> lock(mutex);
3190 if (eigenvalues_are_initialized ==
false)
3191 estimate_eigenvalues(rhs);
3193 internal::PreconditionChebyshevImplementation::vmult_and_update(
3195 *data.preconditioner,
3205 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
3208 double rhok = delta / theta, sigma = theta / delta;
3209 for (
unsigned int k = 0; k < data.degree - 1; ++k)
3211 const double rhokp = 1. / (2. * sigma - rhok);
3212 const double factor1 = rhokp * rhok, factor2 = 2. * rhokp / delta;
3214 internal::PreconditionChebyshevImplementation::vmult_and_update(
3216 *data.preconditioner,
3230template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3233 VectorType & solution,
3234 const VectorType &rhs)
const
3236 std::lock_guard<std::mutex> lock(mutex);
3237 if (eigenvalues_are_initialized ==
false)
3238 estimate_eigenvalues(rhs);
3240 matrix_ptr->Tvmult(temp_vector1, solution);
3241 internal::PreconditionChebyshevImplementation::vector_updates(
3243 *data.preconditioner,
3252 if (data.degree < 2 ||
std::abs(delta) < 1e-40)
3255 double rhok = delta / theta, sigma = theta / delta;
3256 for (
unsigned int k = 0; k < data.degree - 1; ++k)
3258 const double rhokp = 1. / (2. * sigma - rhok);
3259 const double factor1 = rhokp * rhok, factor2 = 2. * rhokp / delta;
3261 matrix_ptr->Tvmult(temp_vector1, solution);
3262 internal::PreconditionChebyshevImplementation::vector_updates(
3264 *data.preconditioner,
3277template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3280 PreconditionerType>::size_type
3284 return matrix_ptr->m();
3289template <
typename MatrixType,
typename VectorType,
typename PreconditionerType>
3292 PreconditionerType>::size_type
3296 return matrix_ptr->n();
size_type nth_index_in_set(const size_type local_index) const
const_iterator end() const
const_iterator begin() const
#define DEAL_II_OPENMP_SIMD_PRAGMA
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define AssertCudaKernel()
unsigned int n_blocks() const
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
BlockType & block(const unsigned int i)
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
types::global_dof_index size_type
void vmult_add(VectorType &, const VectorType &) const
internal::PreconditionRelaxation::PreconditionSORImpl< MatrixType > PreconditionerType
typename BaseClass::AdditionalData AdditionalData
SmartPointer< const MatrixType, PreconditionRelaxation< MatrixType > > A
void Tvmult(VectorType &dst, const VectorType &src) const
AdditionalData(const std::vector< size_type > &permutation, const std::vector< size_type > &inverse_permutation, const typename BaseClass::AdditionalData ¶meters=typename BaseClass::AdditionalData())
typename BaseClass::size_type size_type
void Tvmult(VectorType &, const VectorType &) const
std::shared_ptr< PreconditionerType > preconditioner
unsigned int n_iterations
std::shared_ptr< PreconditionerType > preconditioner
void(MatrixType::*)(VectorType &, const VectorType &) const function_ptr
void vmult_add(VectorType &, const VectorType &) const
const function_ptr precondition
void step(VectorType &dst, const VectorType &src) const
double min_eigenvalue_estimate
double max_eigenvalue_estimate
void initialize(const MatrixType &A, const AdditionalData ¶meters=AdditionalData())
BaseClass::AdditionalData parameters
void initialize(const AdditionalData ¶meters)
void vmult(VectorType &, const VectorType &) const
AdditionalData & operator=(const AdditionalData &other_data)
void initialize(const MatrixType &A, const AdditionalData &additional_data)
EigenvalueInformation estimate_eigenvalues(const VectorType &src) const
AffineConstraints< double > constraints
void Tstep(VectorType &dst, const VectorType &src) const
std::shared_ptr< PreconditionerType > preconditioner
const std::vector< size_type > & inverse_permutation
const MatrixType & matrix
typename BaseClass::AdditionalData AdditionalData
void initialize(const MatrixType &matrix, const AdditionalData &additional_data=AdditionalData())
void initialize(const MatrixType &matrix, const AdditionalData ¶meters)
SmartPointer< const MatrixType, PreconditionChebyshev< MatrixType, VectorType, PreconditionerType > > matrix_ptr
unsigned int eig_cg_n_iterations
void initialize(const MatrixType &A, const AdditionalData ¶meters=AdditionalData())
unsigned int cg_iterations
AdditionalData(const double relaxation=1.)
internal::PreconditionRelaxation::PreconditionJacobiImpl< MatrixType > PreconditionerType
void initialize(const MatrixType &A, const AdditionalData ¶meters=AdditionalData())
void step(VectorType &x, const VectorType &rhs) const
AdditionalData(const double relaxation=1., const unsigned int n_iterations=1)
unsigned int n_iterations
const std::vector< size_type > & permutation
void vmult(VectorType &, const VectorType &) const
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)
void Tvmult(VectorType &, const VectorType &) const
void Tvmult_add(VectorType &, const VectorType &) const
void initialize(const MatrixType &A, const AdditionalData ¶meters=AdditionalData())
void vmult(VectorType &dst, const VectorType &src) const
internal::PreconditionRelaxation::PreconditionPSORImpl< MatrixType > PreconditionerType
typename BaseClass::AdditionalData AdditionalData
internal::PreconditionRelaxation::PreconditionSSORImpl< MatrixType > PreconditionerType
void vmult(VectorType &dst, const VectorType &src) const
void Tstep(VectorType &x, const VectorType &rhs) const
void vmult(VectorType &, const VectorType &) const
void initialize(const MatrixType &matrix, const AdditionalData &additional_data=AdditionalData())
PreconditionUseMatrix(const MatrixType &M, const function_ptr method)
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())
bool eigenvalues_are_initialized
void Tvmult(VectorType &, const VectorType &) const
EigenvalueAlgorithm eigenvalue_algorithm
void Tvmult_add(VectorType &, const VectorType &) const
types::global_dof_index size_type
void add(const std::vector< size_type > &indices, const std::vector< OtherNumber > &values)
Number local_element(const size_type local_index) const
Number * get_values() const
void swap(Vector< Number, MemorySpace > &v)
Number mean_value() const
size_type locally_owned_size() const
virtual Number mean_value() const override
virtual void swap(Vector< Number > &v)
virtual void add(const Number a) override
virtual ::IndexSet locally_owned_elements() const override
@ matrix
Contents is actually a matrix.
std::enable_if< IsBlockVector< VectorType >::value, unsignedint >::type n_blocks(const VectorType &vector)
VectorType::value_type * end(VectorType &V)
unsigned int minimum_parallel_grain_size
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
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)