FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
qpenalty.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 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
7namespace FEAT
8{
9 namespace Solver
10 {
46 template<typename Functional_>
47 class QPenalty : public IterativeSolver<typename Functional_::VectorTypeR>
48 {
49 public:
51 typedef Functional_ FunctionalType;
53 typedef typename Functional_::VectorTypeR VectorType;
55 typedef typename VectorType::DataType DataType;
58
59 private:
63 std::shared_ptr<IterativeSolver<VectorType>> _inner_solver;
68
69 public:
82 explicit QPenalty(FunctionalType& functional, std::shared_ptr<IterativeSolver<VectorType>> inner_solver,
83 DataType initial_penalty_param = DataType(1)) :
84 BaseClass("QPenalty"),
85 _functional(functional),
86 _inner_solver(inner_solver),
87 _initial_penalty_param(initial_penalty_param),
88 _tol_penalty(Math::pow(Math::huge<DataType>(), DataType(0.25)))
89 {
90 // set communicator by functional (same interface as matrix)
91 this->_set_comm_by_matrix(functional);
92 }
93
112 explicit QPenalty(const String& section_name, const PropertyMap* section,
113 FunctionalType& functional, std::shared_ptr<IterativeSolver<VectorType>> inner_solver) :
114 BaseClass("QPenalty", section_name, section),
115 _functional(functional),
116 _inner_solver(inner_solver),
118 _tol_penalty(Math::pow(Math::huge<DataType>(), DataType(0.25)))
119 {
120 // set communicator by functional (same interface as matrix)
121 this->_set_comm_by_matrix(functional);
122
123 auto initial_penalty_param_p = section->query("initial_penalty_param");
124 if(initial_penalty_param_p.second)
125 {
126 set_initial_penalty_param(DataType(std::stod(initial_penalty_param_p.first)));
127 }
128
129 auto tol_penalty_p = section->query("tol_penalty");
130 if(tol_penalty_p.second)
131 {
132 set_tol_penalty(DataType(std::stod(tol_penalty_p.first)));
133 }
134 }
135
137 QPenalty(const QPenalty&) = delete;
138
142 virtual ~QPenalty()
143 {
144 _inner_solver = nullptr;
145 }
146
148 virtual String name() const override
149 {
150 return "QPenalty";
151 }
152
154 virtual void init_symbolic() override
155 {
157 _inner_solver->init_symbolic();
158 }
159
161 virtual void done_symbolic() override
162 {
163 _inner_solver->done_symbolic();
165 }
166
170 void set_initial_penalty_param(DataType initial_penalty_param)
171 {
172 XASSERT(initial_penalty_param > DataType(0));
173
174 _initial_penalty_param = initial_penalty_param;
175 }
176
180 void set_tol_penalty(DataType tol_penalty)
181 {
182 XASSERT(tol_penalty > DataType(0));
183
184 _tol_penalty = tol_penalty;
185 }
186
188 virtual Status apply(VectorType& vec_cor, const VectorType& vec_def) override
189 {
190 _functional.set_penalty_param(_initial_penalty_param);
191
192 // clear solution vector
193 vec_cor.format();
194
195 // apply
196 this->_status = _apply_intern(vec_cor, vec_def);
197 this->plot_summary();
198 return this->_status;
199 }
200
202 virtual Status correct(VectorType& vec_sol, const VectorType& vec_rhs) override
203 {
204 _functional.set_penalty_param(_initial_penalty_param);
205
206 // apply
207 this->_status = _apply_intern(vec_sol, vec_rhs);
208 this->plot_summary();
209 return this->_status;
210 }
211
212 protected:
226 virtual Status _apply_intern(VectorType& vec_sol, const VectorType& vec_rhs)
227 {
228 Statistics::add_solver_expression(std::make_shared<ExpressionStartSolve>(this->name()));
229
230 const Index inner_iter_digits(Math::ilog10(_inner_solver->get_max_iter()));
231
232 Status st(_set_initial_defect(_functional.get_constraint()));
233
234 IterationStats stat(*this);
235
236 // The Penalty Iteration(TM)
237 while(st == Status::progress)
238 {
239 ++(this->_num_iter);
240
241 DataType def_old(this->_def_cur);
242 //DataType penalty_param_old(penalty_param);
243
244 Status inner_st(_inner_solver->correct(vec_sol, vec_rhs));
245 if(inner_st == Status::aborted)
246 {
247 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::aborted, this->get_num_iter()));
248 return Status::aborted;
249 }
250
251 // After the inner solver was called, the constraint is already there so we can just get() it
252 this->_def_cur = _functional.get_constraint();
253 DataType penalty_param(_functional.get_penalty_param());
254
255 if(this->_plot_iter())
256 {
257 String msg = this->_plot_name
258 + ": " + stringify(this->_num_iter).pad_front(this->_iter_digits)
259 + " (" + stringify(this->_inner_solver->get_num_iter()).pad_front(inner_iter_digits)
260 + ":" + stringify(inner_st) + ")"
261 + " : " + stringify_fp_sci(this->_def_cur)
262 + " / " + stringify_fp_sci(this->_def_cur / this->_def_init)
263 + " / " + stringify_fp_sci(DataType(0.5)*Math::sqr(this->_def_cur))
264 + " : " + stringify_fp_sci(penalty_param);
265
266 this->_print_line(msg);
267 }
268
269 // ensure that the defect is neither NaN nor infinity
270 if(!Math::isfinite(this->_def_cur))
271 {
272 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::aborted, this->get_num_iter()));
273 return Status::aborted;
274 }
275
276 // is diverged?
277 if(this->is_diverged())
278 {
279 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::diverged, this->get_num_iter()));
280 return Status::diverged;
281 }
282
283 // minimum number of iterations performed?
284 if(this->_num_iter < this->_min_iter)
285 {
286 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::progress, this->get_num_iter()));
287 return Status::progress;
288 }
289
290 // maximum number of iterations performed?
291 if(this->_num_iter >= this->_max_iter)
292 {
293 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::max_iter, this->get_num_iter()));
294 return Status::max_iter;
295 }
296
297 // Check for convergence
298 if(this->is_converged())
299 {
300 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::success, this->get_num_iter()));
301 return Status::success;
302 }
303
304 // Increment for the penalty factor by at least factor 5, very arbitrary
305 penalty_param = DataType(5)*Math::sqr(penalty_param)
306 *Math::max(Math::sqr( def_old/this->_def_cur),DataType(1));
307
308 if(penalty_param >= _tol_penalty)
309 {
310 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::stagnated, this->get_num_iter()));
311 return Status::stagnated;
312 }
313
314 _functional.set_penalty_param(penalty_param);
315 }
316
317 // We should never come to this point
318 Statistics::add_solver_expression(std::make_shared<ExpressionEndSolve>(this->name(), Status::undefined, this->get_num_iter()));
319 return Status::undefined;
320 }
321
332 {
333 // store new defect
334 this->_def_init = this->_def_cur = def_init_;
335 // insert special toe to signal new start of solver
336 //Statistics::add_solver_toe(this->_branch, double(-1));
337 //Statistics::add_solver_mpi_execute(this->_branch, double(-1));
338 //Statistics::add_solver_mpi_wait(this->_branch, double(-1));
339 //insert -1 as first defect, to signalize a new starting solver iteration run
340 //Statistics::add_solver_defect(this->_branch, double(-1));
341 //Statistics::add_solver_defect(this->_branch, double(this->_def_init));
342 this->_num_iter = Index(0);
343 this->_num_stag_iter = Index(0);
344 Statistics::add_solver_expression(std::make_shared<ExpressionDefect>(this->name(), this->_def_init, this->get_num_iter()));
345
346 // Plot?
347 if(this->_plot_iter())
348 {
349 String msg = this->_plot_name
350 + ": " + stringify(0).pad_front(this->_iter_digits)
351 + " : " + stringify_fp_sci(this->_def_init);
352
353 this->_print_line(msg);
354 }
355
356 // Ensure that the defect is neither NaN nor infinity
357 if(!Math::isfinite(this->_def_init))
358 {
359 return Status::aborted;
360 }
361
362 // Check if the initial defect lower than the absolute tolerance
363 if(this->_def_init <= this->_tol_abs)
364 {
365 return Status::success;
366 }
367
368 // continue iterating
369 return Status::progress;
370 }
371
374
375 };
376
391 template<typename Functional_>
392 inline std::shared_ptr<QPenalty<Functional_>> new_qpenalty( Functional_& functional,
393 std::shared_ptr<IterativeSolver<typename Functional_::VectorTypeR>> inner_solver,
394 typename Functional_::VectorTypeR::DataType initial_penalty_param =
395 typename Functional_::VectorTypeR::DataType(1))
396 {
397 return std::make_shared<QPenalty<Functional_>>(functional, inner_solver, initial_penalty_param);
398 }
399
420 template<typename Functional_>
421 inline std::shared_ptr<QPenalty<Functional_>> new_qpenalty(
422 const String& section_name, const PropertyMap* section,
423 Functional_& functional, std::shared_ptr<IterativeSolver<typename Functional_::VectorTypeR>> inner_solver)
424 {
425 return std::make_shared<QPenalty<Functional_>>(section_name, section, functional, inner_solver);
426 }
427
428 }
429} // namespace FEAT
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
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.
Helper class for iteration statistics collection.
Definition: base.hpp:392
Abstract base-class for iterative solvers.
Definition: iterative.hpp:198
Index _iter_digits
iteration count digits for plotting
Definition: iterative.hpp:243
Index get_num_iter() const
Returns number of performed iterations.
Definition: iterative.hpp:462
void _set_comm_by_matrix(const Matrix_ &matrix)
Sets the communicator for the solver from a matrix.
Definition: iterative.hpp:680
void _print_line(const String &line) const
Prints a line.
Definition: iterative.hpp:752
Index _num_iter
number of performed iterations
Definition: iterative.hpp:231
bool _plot_iter(Status st=Status::progress) const
Plot the current iteration?
Definition: iterative.hpp:720
Index _num_stag_iter
number of consecutive stagnated iterations
Definition: iterative.hpp:235
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
bool is_converged() const
checks for convergence
Definition: iterative.hpp:533
DataType _tol_abs
absolute tolerance parameter
Definition: iterative.hpp:217
Quadratic penalty iteration.
Definition: qpenalty.hpp:48
VectorType::DataType DataType
Underlying floating point type.
Definition: qpenalty.hpp:55
virtual Status apply(VectorType &vec_cor, const VectorType &vec_def) override
Solver application method.
Definition: qpenalty.hpp:188
Functional_ FunctionalType
The functional type.
Definition: qpenalty.hpp:51
FunctionalType & _functional
The functional that takes the penalty parameters and is assembled in the inner solver.
Definition: qpenalty.hpp:61
virtual ~QPenalty()
Virtual destructor.
Definition: qpenalty.hpp:142
IterativeSolver< VectorType > BaseClass
Our base class.
Definition: qpenalty.hpp:57
QPenalty(const String &section_name, const PropertyMap *section, FunctionalType &functional, std::shared_ptr< IterativeSolver< VectorType > > inner_solver)
Constructor using a PropertyMap.
Definition: qpenalty.hpp:112
DataType _tol_penalty
Maximum value the penalty parameter is allowed to take.
Definition: qpenalty.hpp:67
virtual void done_symbolic() override
Symbolic initialization method.
Definition: qpenalty.hpp:161
void set_initial_penalty_param(DataType initial_penalty_param)
Sets the initial penalty parameter.
Definition: qpenalty.hpp:170
virtual String name() const override
Returns a descriptive string.
Definition: qpenalty.hpp:148
virtual Status _apply_intern(VectorType &vec_sol, const VectorType &vec_rhs)
Internal function, applies the solver.
Definition: qpenalty.hpp:226
Status _set_initial_defect(const DataType def_init_)
Internal function: sets the initial defect.
Definition: qpenalty.hpp:331
QPenalty(FunctionalType &functional, std::shared_ptr< IterativeSolver< VectorType > > inner_solver, DataType initial_penalty_param=DataType(1))
Constructor.
Definition: qpenalty.hpp:82
virtual void init_symbolic() override
Symbolic initialization method.
Definition: qpenalty.hpp:154
virtual Status correct(VectorType &vec_sol, const VectorType &vec_rhs) override
Solver correction method.
Definition: qpenalty.hpp:202
void set_tol_penalty(DataType tol_penalty)
Sets the initial penalty parameter.
Definition: qpenalty.hpp:180
Functional_::VectorTypeR VectorType
The input vector type.
Definition: qpenalty.hpp:53
std::shared_ptr< IterativeSolver< VectorType > > _inner_solver
The inner solver for the penalized, unconstrained optimization problem.
Definition: qpenalty.hpp:63
QPenalty(const QPenalty &)=delete
Explicitly delete the copy constructor.
DataType _initial_penalty_param
We start with this initial penalty parameter.
Definition: qpenalty.hpp:65
virtual void init_symbolic()
Symbolic initialization method.
Definition: base.hpp:227
virtual void done_symbolic()
Symbolic finalization method.
Definition: base.hpp:255
String class implementation.
Definition: string.hpp:46
String pad_front(size_type len, char c=' ') const
Pads the front of the string up to a desired length.
Definition: string.hpp:392
T_ sqr(T_ x)
Returns the square of a value.
Definition: math.hpp:95
T_ ilog10(T_ x)
Computes the integral base-10 logarithm of an integer, i.e. its number of non-zero decimal digits.
Definition: math.hpp:231
bool isfinite(T_ x)
Checks whether a value is finite.
T_ max(T_ a, T_ b)
Returns the maximum of two values.
Definition: math.hpp:137
std::shared_ptr< QPenalty< Functional_ > > new_qpenalty(Functional_ &functional, std::shared_ptr< IterativeSolver< typename Functional_::VectorTypeR > > inner_solver, typename Functional_::VectorTypeR::DataType initial_penalty_param=typename Functional_::VectorTypeR::DataType(1))
Creates a new QPenalty object.
Definition: qpenalty.hpp:392
Status
Solver status return codes enumeration.
Definition: base.hpp:47
@ success
solving successful (convergence criterion fulfilled)
@ progress
continue iteration (internal use only)
@ undefined
undefined status
@ stagnated
solver stagnated (stagnation criterion fulfilled)
@ max_iter
solver reached maximum iterations
@ diverged
solver diverged (divergence criterion fulfilled)
@ aborted
premature abort (solver aborted due to internal errors or preconditioner failure)
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944
String stringify_fp_sci(DataType_ value, int precision=0, int width=0, bool sign=false)
Prints a floating point value to a string in scientific notation.
Definition: string.hpp:1088
std::uint64_t Index
Index data type.