FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
descent.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 - 2024 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7#ifndef KERNEL_SOLVER_DESCENT_HPP
8#define KERNEL_SOLVER_DESCENT_HPP 1
9
10// includes, FEAT
11#include <kernel/solver/iterative.hpp>
12
13namespace FEAT
14{
15 namespace Solver
16 {
17 enum class DescentVariant
18 {
20 fixed,
24 defect,
26 //min_res,
27 };
28
29 std::ostream& operator<<(std::ostream& os, DescentVariant dv)
30 {
31 switch(dv)
32 {
34 return os << "fixed";
35
37 return os << "steepest";
38
40 return os << "defect";
41
42 default:
43 return os << "???";
44 }
45 }
46
60 template<
61 typename Matrix_,
62 typename Filter_>
63 class Descent :
64 public PreconditionedIterativeSolver<typename Matrix_::VectorTypeR>
65 {
66 public:
67 typedef Matrix_ MatrixType;
68 typedef Filter_ FilterType;
69 typedef typename MatrixType::VectorTypeR VectorType;
70 typedef typename MatrixType::DataType DataType;
72
74
75 protected:
77 const MatrixType& _system_matrix;
79 const FilterType& _system_filter;
81 VectorType _vec_r, _vec_p, _vec_q;//, _vec_z;
84
85 public:
101 explicit Descent(const MatrixType& matrix, const FilterType& filter,
102 DescentVariant variant, std::shared_ptr<PrecondType> precond = nullptr) :
103 BaseClass("Descent", precond),
104 _system_matrix(matrix),
105 _system_filter(filter),
106 _variant(variant)
107 {
108 // set communicator by system matrix
109 this->_set_comm_by_matrix(matrix);
110 this->set_plot_name("Descent[" + stringify(this->_variant) + "]");
111 }
112
134 explicit Descent(const String& section_name, const PropertyMap* section,
135 const MatrixType& matrix, const FilterType& filter,
136 std::shared_ptr<PrecondType> precond = nullptr) :
137 BaseClass("Descent", section_name, section, precond),
138 _system_matrix(matrix),
139 _system_filter(filter)
140 {
141 // set communicator by system matrix
142 this->_set_comm_by_matrix(matrix);
143
144 // get our variant
145 auto variant_p = section->query("variant");
146 if(!variant_p.second)
147 throw ParseError("Descent: config section is missing the mandatory variant!");
148 if(variant_p.first.compare_no_case("steepest") == 0)
149 this->_variant = DescentVariant::steepest;
150 else if(variant_p.first.compare_no_case("defect") == 0)
151 this->_variant = DescentVariant::defect;
152 else
153 throw ParseError("Descent: invalid variant: " + variant_p.first);
154
155 this->set_plot_name("Descent[" + stringify(this->_variant) + "]");
156 }
157
158 virtual String name() const override
159 {
160 return "Descent";
161 }
162
163 virtual void init_symbolic() override
164 {
166
167 _vec_r = this->_system_matrix.create_vector_r();
168 _vec_p = this->_system_matrix.create_vector_r();
169 _vec_q = this->_system_matrix.create_vector_r();
170 //_vec_z = this->_system_matrix.create_vector_r();
171 }
172
173 virtual void done_symbolic() override
174 {
175 //this->_vec_z.clear();
176 this->_vec_q.clear();
177 this->_vec_p.clear();
178 this->_vec_r.clear();
180 }
181
182 virtual Status apply(VectorType& vec_cor, const VectorType& vec_def) override
183 {
184 // save defect
185 this->_vec_r.copy(vec_def);
186
187 // clear solution vector
188 vec_cor.format();
189
190 // apply solver
191 this->_status = _apply_intern(vec_cor);
192
193 // plot summary
194 this->plot_summary();
195
196 // return status
197 return this->_status;
198 }
199
200 virtual Status correct(VectorType& vec_sol, const VectorType& vec_rhs) override
201 {
202 // compute defect
203 this->_system_matrix.apply(this->_vec_r, vec_sol, vec_rhs, -DataType(1));
204 this->_system_filter.filter_def(this->_vec_r);
205
206 // apply solver
207 this->_status = _apply_intern(vec_sol);
208
209 // plot summary
210 this->plot_summary();
211
212 // return status
213 return this->_status;
214 }
215
216 protected:
217 virtual Status _apply_intern(VectorType& vec_sol)
218 {
219 IterationStats pre_iter(*this);
220 Statistics::add_solver_expression(std::make_shared<ExpressionStartSolve>(this->name()));
221
222 const MatrixType& matrix(this->_system_matrix);
223 const FilterType& filter(this->_system_filter);
224 VectorType& vec_r(this->_vec_r);
225 VectorType& vec_p(this->_vec_p);
226 VectorType& vec_q(this->_vec_q);
227 //VectorType& vec_z(this->_vec_z);
228
229 // set initial defect:
230 // r[0] := b - A*x[0]
231 Status status = this->_set_initial_defect(vec_r, vec_sol);
232 if(status != Status::progress)
233 {
234 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), status, this->get_num_iter()));
235 pre_iter.destroy();
236 return status;
237 }
238
239 // apply preconditioner to defect vector
240 // p[0] := M^{-1} * r[0]
241 if(!this->_apply_precond(vec_p, vec_r, filter))
242 {
243 pre_iter.destroy();
244 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::aborted, this->get_num_iter()));
245 return Status::aborted;
246 }
247
248 pre_iter.destroy();
249
250 // start iterating
251 while(status == Status::progress)
252 {
253 IterationStats stat(*this);
254
255 // q[k] := A*p[k]
256 matrix.apply(vec_q, vec_p);
257 filter.filter_def(vec_q);
258
259 // compute alpha
260 DataType gamma = DataType(1), omega = DataType(1);
261 switch(this->_variant)
262 {
264 gamma = omega = DataType(1);
265 break;
266
268 // alpha[k] := < r[k], p[k] > / < q[k], p[k] >
269 gamma = vec_r.dot(vec_p);
270 omega = vec_q.dot(vec_p);
271 break;
272
274 // alpha[k] := < r[k], q[k] > / < q[k], q[k] >
275 gamma = vec_r.dot(vec_q);
276 omega = vec_q.dot(vec_q);
277 break;
278 }
279
280 // compute alpha
281 DataType alpha = gamma / omega;
282
283 // update solution vector:
284 // x[k+1] := x[k] + alpha[k] * p[k]
285 vec_sol.axpy(vec_p, vec_sol, alpha);
286
287 // update defect vector:
288 // r[k+1] := r[k] - alpha[k] * q[k]
289 vec_r.axpy(vec_q, vec_r, -alpha);
290
291 // compute defect norm
292 status = this->_set_new_defect(vec_r, vec_sol);
293 if(status != Status::progress)
294 {
295 stat.destroy();
296 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), status, this->get_num_iter()));
297 return status;
298 }
299
300 // apply preconditioner
301 // p[k+1] := M^{-1} * r[k+1]
302 if(!this->_apply_precond(vec_p, vec_r, filter))
303 {
304 stat.destroy();
305 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::aborted, this->get_num_iter()));
306 return Status::aborted;
307 }
308 }
309
310 // we should never reach this point...
311 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::undefined, this->get_num_iter()));
312 return Status::undefined;
313 }
314 }; // class Descent<...>
315
334 template<typename Matrix_, typename Filter_>
335 inline std::shared_ptr<Descent<Matrix_, Filter_>> new_descent(
336 const Matrix_& matrix, const Filter_& filter, DescentVariant variant,
337 std::shared_ptr<SolverBase<typename Matrix_::VectorTypeL>> precond = nullptr)
338 {
339 return std::make_shared<Descent<Matrix_, Filter_>>(matrix, filter, variant, precond);
340 }
341
363 template<typename Matrix_, typename Filter_>
364 inline std::shared_ptr<Descent<Matrix_, Filter_>> new_pmr(
365 const String& section_name, const PropertyMap* section,
366 const Matrix_& matrix, const Filter_& filter,
367 std::shared_ptr<SolverBase<typename Matrix_::VectorTypeL>> precond = nullptr)
368 {
369 return std::make_shared<Descent<Matrix_, Filter_>>(section_name, section, matrix, filter, precond);
370 }
371 } // namespace Solver
372} // namespace FEAT
373
374#endif // KERNEL_SOLVER_DESCENT_HPP
Class for parser related errors.
Definition: exception.hpp:132
A class organizing a tree of key-value pairs.
std::pair< String, bool > query(String key_path) const
Queries a value by its key path.
(Preconditioned) Descent solver implementation
Definition: descent.hpp:65
Descent(const String &section_name, const PropertyMap *section, const MatrixType &matrix, const FilterType &filter, std::shared_ptr< PrecondType > precond=nullptr)
Constructor using a PropertyMap.
Definition: descent.hpp:134
virtual void init_symbolic() override
Symbolic initialization method.
Definition: descent.hpp:163
VectorType _vec_r
temporary vectors
Definition: descent.hpp:81
const MatrixType & _system_matrix
the matrix for the solver
Definition: descent.hpp:77
virtual void done_symbolic() override
Symbolic finalization method.
Definition: descent.hpp:173
DescentVariant _variant
the chosen descent type
Definition: descent.hpp:83
const FilterType & _system_filter
the filter for the solver
Definition: descent.hpp:79
virtual String name() const override
Returns a descriptive string.
Definition: descent.hpp:158
Descent(const MatrixType &matrix, const FilterType &filter, DescentVariant variant, std::shared_ptr< PrecondType > precond=nullptr)
Constructor.
Definition: descent.hpp:101
void set_plot_name(const String &plot_name)
Sets the plot name of the solver.
Definition: iterative.hpp:517
Index get_num_iter() const
Returns number of performed iterations.
Definition: iterative.hpp:462
Status _status
current status of the solver
Definition: iterative.hpp:213
void _set_comm_by_matrix(const Matrix_ &matrix)
Sets the communicator for the solver from a matrix.
Definition: iterative.hpp:680
virtual Status _set_new_defect(const VectorType &vec_def, const VectorType &vec_sol)
Internal function: sets the new (next) defect vector.
Definition: iterative.hpp:924
virtual void plot_summary() const
Plot a summary of the last solver run.
Definition: iterative.hpp:627
virtual Status _set_initial_defect(const VectorType &vec_def, const VectorType &vec_sol)
Internal function: sets the initial defect vector.
Definition: iterative.hpp:802
Abstract base-class for preconditioned iterative solvers.
Definition: iterative.hpp:1027
virtual void init_symbolic() override
Symbolic initialization method.
Definition: iterative.hpp:1086
bool _apply_precond(VectorType &vec_cor, const VectorType &vec_def, const Filter_ &filter)
Applies the preconditioner onto a defect vector.
Definition: iterative.hpp:1140
virtual void done_symbolic() override
Symbolic finalization method.
Definition: iterative.hpp:1110
Polymorphic solver interface.
Definition: base.hpp:183
String class implementation.
Definition: string.hpp:46
@ defect
left-preconditioned defect minimization
@ steepest
symmetrically preconditioned steepest descent
@ fixed
simple fixed Richardson iteration
std::shared_ptr< Descent< Matrix_, Filter_ > > new_descent(const Matrix_ &matrix, const Filter_ &filter, DescentVariant variant, std::shared_ptr< SolverBase< typename Matrix_::VectorTypeL > > precond=nullptr)
Creates a new Descent solver object.
Definition: descent.hpp:335
Status
Solver status return codes enumeration.
Definition: base.hpp:47
@ progress
continue iteration (internal use only)
@ undefined
undefined status
@ aborted
premature abort (solver aborted due to internal errors or preconditioner failure)
std::shared_ptr< Descent< Matrix_, Filter_ > > new_pmr(const String &section_name, const PropertyMap *section, const Matrix_ &matrix, const Filter_ &filter, std::shared_ptr< SolverBase< typename Matrix_::VectorTypeL > > precond=nullptr)
Creates a new Descent solver object using a PropertyMap.
Definition: descent.hpp:364
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944