DUNE PDELab (2.8)

linearproblem.hh
1// -*- tab-width: 2; indent-tabs-mode: nil -*-
2// vi: set et ts=2 sw=2 sts=2:
3
4#ifndef DUNE_PDELAB_STATIONARY_LINEARPROBLEM_HH
5#define DUNE_PDELAB_STATIONARY_LINEARPROBLEM_HH
6
7#include <iostream>
8
11
12#include <dune/pdelab/backend/interface.hh>
13#include <dune/pdelab/constraints/common/constraints.hh>
14#include <dune/pdelab/backend/solver.hh>
15
16namespace Dune {
17 namespace PDELab {
18
19 //===============================================================
20 // A class for solving linear stationary problems.
21 // It assembles the matrix, computes the right hand side and
22 // solves the problem.
23 // This is only a first vanilla implementation which has to be improved.
24 //===============================================================
25
26 // Status information of linear problem solver
27 template<class RFType>
28 struct StationaryLinearProblemSolverResult : LinearSolverResult<RFType>
29 {
30 RFType first_defect; // the first defect
31 RFType defect; // the final defect
32 double assembler_time; // Cumulative time for matrix assembly
33 double linear_solver_time; // Cumulative time for linear solver
34 int linear_solver_iterations; // Total number of linear iterations
35
36 StationaryLinearProblemSolverResult()
37 : first_defect(0.0)
38 , defect(0.0)
39 , assembler_time(0.0)
40 , linear_solver_time(0.0)
41 , linear_solver_iterations(0)
42 {}
43
44 };
45
46
47
59 template<typename GO, typename LS, typename V>
61 {
62 typedef typename Dune::template FieldTraits<typename V::ElementType >::real_type Real;
63 typedef typename GO::Traits::Jacobian M;
64 typedef typename GO::Traits::TrialGridFunctionSpace TrialGridFunctionSpace;
65 using W = Dune::PDELab::Backend::Vector<TrialGridFunctionSpace,typename V::ElementType>;
66 typedef GO GridOperator;
67
68 public:
69 typedef StationaryLinearProblemSolverResult<double> Result;
70
71 StationaryLinearProblemSolver(const GO& go, LS& ls, V& x, Real reduction, Real min_defect = 1e-99, int verbose=1)
72 : _go(go)
73 , _ls(ls)
74 , _x(&x)
75 , _reduction(reduction)
76 , _min_defect(min_defect)
77 , _hanging_node_modifications(false)
78 , _keep_matrix(true)
79 , _verbose(verbose)
80 {}
81
82 StationaryLinearProblemSolver (const GO& go, LS& ls, Real reduction, Real min_defect = 1e-99, int verbose=1)
83 : _go(go)
84 , _ls(ls)
85 , _x()
86 , _reduction(reduction)
87 , _min_defect(min_defect)
88 , _hanging_node_modifications(false)
89 , _keep_matrix(true)
90 , _verbose(verbose)
91 {}
92
94
111 StationaryLinearProblemSolver(const GO& go, LS& ls, V& x, const ParameterTree& params)
112 : _go(go)
113 , _ls(ls)
114 , _x(&x)
115 , _reduction(params.get<Real>("reduction"))
116 , _min_defect(params.get<Real>("min_defect",1e-99))
117 , _hanging_node_modifications(params.get<bool>("hanging_node_modifications",false))
118 , _keep_matrix(params.get<bool>("keep_matrix",true))
119 , _verbose(params.get<int>("verbosity",1))
120 {}
121
123
140 StationaryLinearProblemSolver(const GO& go, LS& ls, const ParameterTree& params)
141 : _go(go)
142 , _ls(ls)
143 , _x()
144 , _reduction(params.get<Real>("reduction"))
145 , _min_defect(params.get<Real>("min_defect",1e-99))
146 , _hanging_node_modifications(params.get<bool>("hanging_node_modifications",false))
147 , _keep_matrix(params.get<bool>("keep_matrix",true))
148 , _verbose(params.get<int>("verbosity",1))
149 {}
150
153 {
154 _hanging_node_modifications=b;
155 }
156
159 {
160 return _hanging_node_modifications;
161 }
162
164 void setKeepMatrix(bool b)
165 {
166 _keep_matrix = b;
167 }
168
170 bool keepMatrix() const
171 {
172 return _keep_matrix;
173 }
174
176 const Result& result() const
177 {
178 return _res;
179 }
180
182 void apply(V& x, bool reuse_matrix = false) {
183 _x = &x;
184 apply(reuse_matrix);
185 }
186
188 void apply (bool reuse_matrix = false)
189 {
190 Dune::Timer watch;
191 double timing,assembler_time=0;
192
193 // assemble matrix; optional: assemble only on demand!
194 watch.reset();
195
196 if constexpr (linearSolverIsMatrixFree<LS>()){
197 if (_go.trialGridFunctionSpace().gridView().comm().rank()==0 && _verbose>=1)
198 std::cout << "=== matrix setup not required for matrix free solvers" << std::endl;
199 }
200 else{
201 if (!_jacobian)
202 {
203 _jacobian = std::make_shared<M>(_go);
204 timing = watch.elapsed();
205 if (_go.trialGridFunctionSpace().gridView().comm().rank()==0 && _verbose>=1)
206 std::cout << "=== matrix setup (max) " << timing << " s" << std::endl;
207 watch.reset();
208 assembler_time += timing;
209 }
210 else if (_go.trialGridFunctionSpace().gridView().comm().rank()==0 && _verbose>=1)
211 std::cout << "=== matrix setup skipped (matrix already allocated)" << std::endl;
212 }
213
214 if (_hanging_node_modifications)
215 {
216 Dune::PDELab::set_shifted_dofs(_go.localAssembler().trialConstraints(),0.0,*_x); // set hanging node DOFs to zero
217 _go.localAssembler().backtransform(*_x); // interpolate hanging nodes adjacent to Dirichlet nodes
218 }
219
220 // Assemble Jacobian if necessary
221 if constexpr (!linearSolverIsMatrixFree<LS>()){
222 if (!reuse_matrix)
223 {
224 (*_jacobian) = Real(0.0);
225 _go.jacobian(*_x,*_jacobian);
226 }
227 }
228 timing = watch.elapsed();
229
230 if constexpr (!linearSolverIsMatrixFree<LS>()){
231 if (_go.trialGridFunctionSpace().gridView().comm().rank()==0 && _verbose>=1)
232 {
233 if (reuse_matrix)
234 std::cout << "=== matrix assembly SKIPPED" << std::endl;
235 else
236 std::cout << "=== matrix assembly (max) " << timing << " s" << std::endl;
237 }
238 }
239
240 assembler_time += timing;
241
242 // assemble residual
243 watch.reset();
244
245 W r(_go.testGridFunctionSpace(),0.0);
246 _go.residual(*_x,r); // residual is additive
247
248 timing = watch.elapsed();
249 // timing = gos.trialGridFunctionSpace().gridView().comm().max(timing);
250 if (_go.trialGridFunctionSpace().gridView().comm().rank()==0 && _verbose>=1)
251 std::cout << "=== residual assembly (max) " << timing << " s" << std::endl;
252 assembler_time += timing;
253 _res.assembler_time = assembler_time;
254
255 auto defect = _ls.norm(r);
256
257 // compute correction
258 watch.reset();
259 V z(_go.trialGridFunctionSpace(),0.0);
260 auto red = std::max(_reduction,_min_defect/defect);
261 if (_go.trialGridFunctionSpace().gridView().comm().rank()==0 && _verbose>=1)
262 {
263 std::cout << "=== solving (reduction: " << red << ") ";
264 if (_verbose>=1)
265 std::cout << std::flush;
266 else
267 std::cout << std::endl;
268 }
269 if constexpr (linearSolverIsMatrixFree<LS>()){
270 _ls.apply(z, r, red);
271 }
272 if constexpr (!linearSolverIsMatrixFree<LS>()){
273 _ls.apply(*_jacobian,z,r,red); // solver makes right hand side consistent
274 }
275 _linear_solver_result = _ls.result();
276 timing = watch.elapsed();
277 // timing = gos.trialGridFunctionSpace().gridView().comm().max(timing);
278 if (_go.trialGridFunctionSpace().gridView().comm().rank()==0 && _verbose>=1)
279 std::cout << timing << " s" << std::endl;
280 _res.linear_solver_time = timing;
281
282 _res.converged = _linear_solver_result.converged;
283 _res.iterations = _linear_solver_result.iterations;
284 _res.elapsed = _linear_solver_result.elapsed;
285 _res.reduction = _linear_solver_result.reduction;
286 _res.conv_rate = _linear_solver_result.conv_rate;
287 _res.first_defect = static_cast<double>(defect);
288 _res.defect = static_cast<double>(defect)*_linear_solver_result.reduction;
289 _res.linear_solver_iterations = _linear_solver_result.iterations;
290
291 // and update
292 if (_hanging_node_modifications)
293 Dune::PDELab::set_shifted_dofs(_go.localAssembler().trialConstraints(),0.0,*_x); // set hanging node DOFs to zero
294 *_x -= z;
295 if (_hanging_node_modifications)
296 _go.localAssembler().backtransform(*_x); // interpolate hanging nodes adjacent to Dirichlet nodes
297
298 if constexpr (!linearSolverIsMatrixFree<LS>()){
299 if (!_keep_matrix)
300 _jacobian.reset();
301 }
302 }
303
306 {
307 if(_jacobian)
308 _jacobian.reset();
309 }
310
311 const Dune::PDELab::LinearSolverResult<double>& ls_result() const{
312 return _linear_solver_result;
313 }
314
315 Real reduction() const
316 {
317 return _reduction;
318 }
319
320 void setReduction(Real reduction)
321 {
322 _reduction = reduction;
323 }
324
325
326 private:
327 const GO& _go;
328 LS& _ls;
329 V* _x;
330 std::shared_ptr<M> _jacobian;
331 Real _reduction;
332 Real _min_defect;
333 Dune::PDELab::LinearSolverResult<double> _linear_solver_result;
334 Result _res;
335 bool _hanging_node_modifications;
336 bool _keep_matrix;
337 int _verbose;
338 };
339
340 } // namespace PDELab
341} // namespace Dune
342
343#endif // DUNE_PDELAB_STATIONARY_LINEARPROBLEM_HH
Solve linear problems using a residual formulation.
Definition: linearproblem.hh:61
const Result & result() const
Return result object.
Definition: linearproblem.hh:176
void setKeepMatrix(bool b)
Set whether the jacobian matrix should be kept across calls to apply().
Definition: linearproblem.hh:164
void apply(bool reuse_matrix=false)
Solve linear problem (use initial guess that was passed at construction)
Definition: linearproblem.hh:188
void setHangingNodeModifications(bool b)
Set whether the solver should apply the necessary transformations for calculations on hanging nodes.
Definition: linearproblem.hh:152
bool hangingNodeModifications() const
Return whether the solver performs the necessary transformations for calculations on hanging nodes.
Definition: linearproblem.hh:158
StationaryLinearProblemSolver(const GO &go, LS &ls, V &x, const ParameterTree &params)
Construct a StationaryLinearProblemSolver for the given objects and read parameters from a ParameterT...
Definition: linearproblem.hh:111
void apply(V &x, bool reuse_matrix=false)
Solve linear problem with the provided initial guess.
Definition: linearproblem.hh:182
void discardMatrix()
Discard the stored Jacobian matrix.
Definition: linearproblem.hh:305
bool keepMatrix() const
Return whether the jacobian matrix is kept across calls to apply().
Definition: linearproblem.hh:170
StationaryLinearProblemSolver(const GO &go, LS &ls, const ParameterTree &params)
Construct a StationaryLinearProblemSolver for the given objects and read parameters from a ParameterT...
Definition: linearproblem.hh:140
Hierarchical structure of string parameters.
Definition: parametertree.hh:35
A simple stop watch.
Definition: timer.hh:41
void reset() noexcept
Reset timer while keeping the running/stopped state.
Definition: timer.hh:55
double elapsed() const noexcept
Get elapsed user-time from last reset until now/last stop in seconds.
Definition: timer.hh:75
void set_shifted_dofs(const CG &cg, typename XG::ElementType x, XG &xg)
Definition: constraints.hh:1014
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:79
Dune namespace.
Definition: alignedallocator.hh:11
A hierarchical structure of string parameters.
A simple timing class.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)