power_iteration
};
+ /**
+ * An enum to define the available types of polynomial types.
+ */
+ enum class PolynomialType
+ {
+ /**
+ * First-kind Chebyshev polynomials.
+ */
+ first_kind,
+ /**
+ * Fourth-kind Chebyshev polynomials according to @cite lottes2022optimal
+ * and @cite phillips2022optimal.
+ */
+ fourth_kind
+ };
+
/**
* Constructor.
*/
- 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);
+ 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);
/**
* Copy assignment operator.
* Specifies the underlying eigenvalue estimation algorithm.
*/
EigenvalueAlgorithm eigenvalue_algorithm;
+
+ /**
+ * Specifies the polynomial type to be used.
+ */
+ PolynomialType polynomial_type;
};
const unsigned int eig_cg_n_iterations,
const double eig_cg_residual,
const double max_eigenvalue,
- const EigenvalueAlgorithm eigenvalue_algorithm)
+ const EigenvalueAlgorithm eigenvalue_algorithm,
+ const PolynomialType polynomial_type)
: degree(degree)
, smoothing_range(smoothing_range)
, eig_cg_n_iterations(eig_cg_n_iterations)
, eig_cg_residual(eig_cg_residual)
, max_eigenvalue(max_eigenvalue)
, eigenvalue_algorithm(eigenvalue_algorithm)
+ , polynomial_type(polynomial_type)
{}
max_eigenvalue = other_data.max_eigenvalue;
preconditioner = other_data.preconditioner;
eigenvalue_algorithm = other_data.eigenvalue_algorithm;
+ polynomial_type = other_data.polynomial_type;
constraints.copy_from(other_data.constraints);
return *this;
const_cast<
PreconditionChebyshev<MatrixType, VectorType, PreconditionerType> *>(this)
- ->delta = (info.max_eigenvalue_estimate - alpha) * 0.5;
+ ->delta =
+ (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
+ (info.max_eigenvalue_estimate) :
+ ((info.max_eigenvalue_estimate - alpha) * 0.5);
const_cast<
PreconditionChebyshev<MatrixType, VectorType, PreconditionerType> *>(this)
->theta = (info.max_eigenvalue_estimate + alpha) * 0.5;
rhs,
0,
0.,
- 1. / theta,
+ (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
+ (4. / (3. * delta)) :
+ (1. / theta),
solution,
solution_old,
temp_vector1,
double rhok = delta / theta, sigma = theta / delta;
for (unsigned int k = 0; k < data.degree - 1; ++k)
{
- const double rhokp = 1. / (2. * sigma - rhok);
- const double factor1 = rhokp * rhok, factor2 = 2. * rhokp / delta;
- rhok = rhokp;
+ double factor1 = 0.0;
+ double factor2 = 0.0;
+
+ if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
+ {
+ factor1 = (2 * k + 1.) / (2 * k + 5.);
+ factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
+ }
+ else
+ {
+ const double rhokp = 1. / (2. * sigma - rhok);
+ factor1 = rhokp * rhok;
+ factor2 = 2. * rhokp / delta;
+ rhok = rhokp;
+ }
+
internal::PreconditionChebyshevImplementation::vmult_and_update(
*matrix_ptr,
*data.preconditioner,
*data.preconditioner,
0,
0.,
- 1. / theta,
+ (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
+ (4. / (3. * delta)) :
+ (1. / theta),
solution_old,
temp_vector1,
temp_vector2,
double rhok = delta / theta, sigma = theta / delta;
for (unsigned int k = 0; k < data.degree - 1; ++k)
{
- const double rhokp = 1. / (2. * sigma - rhok);
- const double factor1 = rhokp * rhok, factor2 = 2. * rhokp / delta;
- rhok = rhokp;
+ double factor1 = 0.0;
+ double factor2 = 0.0;
+
+ if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
+ {
+ factor1 = (2 * k + 1.) / (2 * k + 5.);
+ factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
+ }
+ else
+ {
+ const double rhokp = 1. / (2. * sigma - rhok);
+ factor1 = rhokp * rhok;
+ factor2 = 2. * rhokp / delta;
+ rhok = rhokp;
+ }
+
matrix_ptr->Tvmult(temp_vector1, solution);
internal::PreconditionChebyshevImplementation::vector_updates(
rhs,
rhs,
1,
0.,
- 1. / theta,
+ (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
+ (4. / (3. * delta)) :
+ (1. / theta),
solution,
solution_old,
temp_vector1,
double rhok = delta / theta, sigma = theta / delta;
for (unsigned int k = 0; k < data.degree - 1; ++k)
{
- const double rhokp = 1. / (2. * sigma - rhok);
- const double factor1 = rhokp * rhok, factor2 = 2. * rhokp / delta;
- rhok = rhokp;
+ double factor1 = 0.0;
+ double factor2 = 0.0;
+
+ if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
+ {
+ factor1 = (2 * k + 1.) / (2 * k + 5.);
+ factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
+ }
+ else
+ {
+ const double rhokp = 1. / (2. * sigma - rhok);
+ factor1 = rhokp * rhok;
+ factor2 = 2. * rhokp / delta;
+ rhok = rhokp;
+ }
+
internal::PreconditionChebyshevImplementation::vmult_and_update(
*matrix_ptr,
*data.preconditioner,
*data.preconditioner,
1,
0.,
- 1. / theta,
+ (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind) ?
+ (4. / (3. * delta)) :
+ (1. / theta),
solution_old,
temp_vector1,
temp_vector2,
double rhok = delta / theta, sigma = theta / delta;
for (unsigned int k = 0; k < data.degree - 1; ++k)
{
- const double rhokp = 1. / (2. * sigma - rhok);
- const double factor1 = rhokp * rhok, factor2 = 2. * rhokp / delta;
- rhok = rhokp;
+ double factor1 = 0.0;
+ double factor2 = 0.0;
+
+ if (data.polynomial_type == AdditionalData::PolynomialType::fourth_kind)
+ {
+ factor1 = (2 * k + 1.) / (2 * k + 5.);
+ factor2 = (8 * k + 12.) / (delta * (2 * k + 5.));
+ }
+ else
+ {
+ const double rhokp = 1. / (2. * sigma - rhok);
+ factor1 = rhokp * rhok;
+ factor2 = 2. * rhokp / delta;
+ rhok = rhokp;
+ }
+
matrix_ptr->Tvmult(temp_vector1, solution);
internal::PreconditionChebyshevImplementation::vector_updates(
rhs,
DEAL::Size 4 Unknowns 9
-DEAL::Residual step i=0: ilu=0.3321067622, cheby=0.05099432420
-DEAL::Residual step i=1: ilu=0.3592209788, cheby=0.04600439733
-DEAL::Residual step i=2: ilu=0.1716913688, cheby=0.02710123523
+DEAL::Residual step i=0: ilu=0.3321067622, cheby=0.05099432420, 4th-kind cheby=0.03534224422
+DEAL::Residual step i=1: ilu=0.3592209788, cheby=0.04600439733, 4th-kind cheby=0.03663547728
+DEAL::Residual step i=2: ilu=0.1716913688, cheby=0.02710123523, 4th-kind cheby=0.01763749678
DEAL::Size 8 Unknowns 49
-DEAL::Residual step i=0: ilu=1.943632434, cheby=0.1724610774
-DEAL::Residual step i=1: ilu=2.148727169, cheby=0.1731956717
-DEAL::Residual step i=2: ilu=1.756318039, cheby=0.1687993258
+DEAL::Residual step i=0: ilu=1.943632434, cheby=0.1724610774, 4th-kind cheby=0.09757580669
+DEAL::Residual step i=1: ilu=2.148727169, cheby=0.1731956717, 4th-kind cheby=0.1005156479
+DEAL::Residual step i=2: ilu=1.756318039, cheby=0.1687993258, 4th-kind cheby=0.1079517431
DEAL::Size 16 Unknowns 225
-DEAL::Residual step i=0: ilu=6.146258348, cheby=0.4251547823
-DEAL::Residual step i=1: ilu=6.252364591, cheby=0.4316860132
-DEAL::Residual step i=2: ilu=5.653977586, cheby=0.4063348761
+DEAL::Residual step i=0: ilu=6.146258348, cheby=0.4251547823, 4th-kind cheby=0.6729443511
+DEAL::Residual step i=1: ilu=6.252364591, cheby=0.4316860132, 4th-kind cheby=0.6896778102
+DEAL::Residual step i=2: ilu=5.653977586, cheby=0.4063348761, 4th-kind cheby=0.6284682272