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 
9 #include <dune/common/timer.hh>
11 
12 #include <dune/pdelab/backend/interface.hh>
13 #include <dune/pdelab/constraints/common/constraints.hh>
14 #include <dune/pdelab/backend/solver.hh>
15 
16 namespace 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
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
const Result & result() const
Return result object.
Definition: linearproblem.hh:176
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.80.0 (May 16, 22:29, 2024)