* for Sparse Linear Systems", section 6.7. Called once per iteration
*/
boost::signals2::connection
- connect_coefficients_slot(const std::function<void(double, double)> &slot);
+ connect_coefficients_slot(
+ const std::function<void(typename VectorType::value_type,
+ typename VectorType::value_type)> &slot);
/**
* Connect a slot to retrieve the estimated condition number. Called on each
*/
static void
compute_eigs_and_cond(
- const std::vector<double> &diagonal,
- const std::vector<double> &offdiagonal,
+ const std::vector<typename VectorType::value_type> &diagonal,
+ const std::vector<typename VectorType::value_type> &offdiagonal,
const boost::signals2::signal<void(const std::vector<double> &)>
& eigenvalues_signal,
const boost::signals2::signal<void(double)> &cond_signal);
/**
* Signal used to retrieve the CG coefficients. Called on each iteration.
*/
- boost::signals2::signal<void(double, double)> coefficients_signal;
+ boost::signals2::signal<void(typename VectorType::value_type,
+ typename VectorType::value_type)>
+ coefficients_signal;
/**
* Signal used to retrieve the estimated condition number. Called once when
template <typename VectorType>
inline void
SolverCG<VectorType>::compute_eigs_and_cond(
- const std::vector<double> &diagonal,
- const std::vector<double> &offdiagonal,
+ const std::vector<typename VectorType::value_type> &diagonal,
+ const std::vector<typename VectorType::value_type> &offdiagonal,
const boost::signals2::signal<void(const std::vector<double> &)>
& eigenvalues_signal,
const boost::signals2::signal<void(double)> &cond_signal)
// Avoid computing eigenvalues unless they are needed.
if (!cond_signal.empty() || !eigenvalues_signal.empty())
{
- TridiagonalMatrix<double> T(diagonal.size(), true);
+ TridiagonalMatrix<typename VectorType::value_type> T(diagonal.size(),
+ true);
for (size_type i = 0; i < diagonal.size(); ++i)
{
T(i, i) = diagonal[i];
// Need two eigenvalues to estimate the condition number.
if (diagonal.size() > 1)
{
- double condition_number = T.eigenvalue(T.n() - 1) / T.eigenvalue(0);
- cond_signal(condition_number);
+ auto condition_number = T.eigenvalue(T.n() - 1) / T.eigenvalue(0);
+ // Condition number is real valued and nonnegative; simply take
+ // the absolute value:
+ cond_signal(std::abs(condition_number));
}
// Avoid copying the eigenvalues of T to a vector unless a signal is
// connected.
std::vector<double> eigenvalues(T.n());
for (unsigned int j = 0; j < T.n(); ++j)
{
- eigenvalues.at(j) = T.eigenvalue(j);
+ // for a hermitian matrix, all eigenvalues are real-valued
+ // and non-negative, simply return the absolute value:
+ eigenvalues[j] = std::abs(T.eigenvalue(j));
}
eigenvalues_signal(eigenvalues);
}
const VectorType & b,
const PreconditionerType &preconditioner)
{
+ using number = typename VectorType::value_type;
+
SolverControl::State conv = SolverControl::iterate;
LogStream::Prefix prefix("cg");
// vectors used for eigenvalue
// computations
- std::vector<double> diagonal;
- std::vector<double> offdiagonal;
+ std::vector<typename VectorType::value_type> diagonal;
+ std::vector<typename VectorType::value_type> offdiagonal;
int it = 0;
double res = -std::numeric_limits<double>::max();
- double eigen_beta_alpha = 0;
+ typename VectorType::value_type eigen_beta_alpha = 0;
// resize the vectors, but do not set
// the values since they'd be overwritten
d.reinit(x, true);
h.reinit(x, true);
- double gh, beta;
+ number gh, beta;
// compute residual. if vector is
// zero, then short-circuit the
it++;
A.vmult(h, d);
- double alpha = d * h;
- Assert(alpha != 0., ExcDivideByZero());
+ number alpha = d * h;
+ Assert(std::abs(alpha) != 0., ExcDivideByZero());
alpha = gh / alpha;
x.add(alpha, d);
- res = std::sqrt(g.add_and_dot(alpha, h, g));
+ res = std::sqrt(std::abs(g.add_and_dot(alpha, h, g)));
print_vectors(it, x, g, d);
preconditioner.vmult(h, g);
beta = gh;
- Assert(beta != 0., ExcDivideByZero());
+ Assert(std::abs(beta) != 0., ExcDivideByZero());
gh = g * h;
beta = gh / beta;
d.sadd(beta, -1., h);
// the projected matrix.
if (do_eigenvalues)
{
- diagonal.push_back(1. / alpha + eigen_beta_alpha);
+ diagonal.push_back(number(1.) / alpha + eigen_beta_alpha);
eigen_beta_alpha = beta / alpha;
offdiagonal.push_back(std::sqrt(beta) / alpha);
}
template <typename VectorType>
boost::signals2::connection
SolverCG<VectorType>::connect_coefficients_slot(
- const std::function<void(double, double)> &slot)
+ const std::function<void(typename VectorType::value_type,
+ typename VectorType::value_type)> &slot)
{
return coefficients_signal.connect(slot);
}