48 SolverBase() : l2_0(1.0), l2_n(1.0), n(0), rho(0.0), n10(0)
50 timer_tree = std::make_shared<TimerTree>();
61 update_preconditioner(
bool const update_preconditioner)
const = 0;
63 template<
typename Control>
65 do_compute_performance_metrics(Control
const & solver_control)
const
68 this->l2_0 = solver_control.initial_value();
69 this->l2_n = solver_control.last_value();
70 this->n = solver_control.last_step();
75 this->rho = std::pow(l2_n / l2_0, 1.0 / n);
76 this->n10 = -10.0 * std::log(10.0) / std::log(rho);
80 virtual std::shared_ptr<TimerTree>
89 mutable unsigned int n;
94 std::shared_ptr<TimerTree> timer_tree;
101class KrylovSolver :
public SolverBase<VectorType>
104 KrylovSolver(Operator
const & underlying_operator_in,
105 Preconditioner & preconditioner_in,
107 bool const use_preconditioner_in,
108 bool const compute_performance_metrics_in =
false,
109 bool const compute_eigenvalues_in =
false)
110 : underlying_operator(underlying_operator_in),
111 preconditioner(preconditioner_in),
112 solver_data(solver_data_in),
113 solver_name(linear_solver_to_string(solver_data.linear_solver)),
114 use_preconditioner(use_preconditioner_in),
115 compute_performance_metrics(compute_performance_metrics_in),
116 compute_eigenvalues(compute_eigenvalues_in)
120 virtual ~KrylovSolver()
125 update_preconditioner(
bool const update_preconditioner)
const override
127 if(use_preconditioner)
129 if(preconditioner.needs_update() or update_preconditioner)
131 preconditioner.update();
141 dealii::ReductionControl solver_control(solver_data.max_iter,
143 solver_data.rel_tol);
145 dealii::SolverSelector<VectorType> solver(solver_name, solver_control);
148 if(solver_name ==
"gmres")
150 typename dealii::SolverGMRES<VectorType>::AdditionalData additional_data;
151 additional_data.max_n_tmp_vectors = solver_data.max_krylov_size;
152 additional_data.right_preconditioning =
true;
154 solver.set_data(additional_data);
156 else if(solver_name ==
"fgmres")
158 typename dealii::SolverFGMRES<VectorType>::AdditionalData additional_data;
159 additional_data.max_basis_size = solver_data.max_krylov_size;
162 solver.set_data(additional_data);
167 if(compute_eigenvalues ==
true)
169 initial_guess.reinit(dst,
true );
170 initial_guess.copy_locally_owned_data_from(dst);
175 if(dealii::PointerComparison::equal(&dst, &rhs) ==
true)
179 tmp_dst.reinit(dst,
false );
180 if(use_preconditioner ==
false)
182 solver.solve(underlying_operator, tmp_dst, rhs, dealii::PreconditionIdentity());
186 solver.solve(underlying_operator, tmp_dst, rhs, preconditioner);
188 dst.copy_locally_owned_data_from(tmp_dst);
192 if(use_preconditioner ==
false)
194 solver.solve(underlying_operator, dst, rhs, dealii::PreconditionIdentity());
198 solver.solve(underlying_operator, dst, rhs, preconditioner);
204 if(compute_eigenvalues ==
true)
206 estimate_eigenvalues_gmres(
207 underlying_operator, preconditioner, initial_guess, rhs, solver_data,
true );
210 AssertThrow(std::isfinite(solver_control.last_value()),
211 dealii::ExcMessage(
"Last iteration step contained NaN or Inf values."));
213 if(compute_performance_metrics)
215 this->do_compute_performance_metrics(solver_control);
218 this->timer_tree->insert({
"Solver (" + solver_name +
")"}, timer.wall_time());
220 return solver_control.last_step();
223 std::shared_ptr<TimerTree>
224 get_timings()
const override
226 if(use_preconditioner)
228 this->timer_tree->insert({
"Solver (" + solver_name +
")"}, preconditioner.get_timings());
231 return this->timer_tree;
235 Operator
const & underlying_operator;
236 Preconditioner & preconditioner;
241 std::string
const solver_name;
243 bool use_preconditioner;
244 bool compute_performance_metrics;
245 bool compute_eigenvalues;