DOpE
instat_step_newtonsolver.h
Go to the documentation of this file.
1 
24 #ifndef INSTAT_STEP_NEWTON_SOLVER_H_
25 #define INSTAT_STEP_NEWTON_SOLVER_H_
26 
27 #include <deal.II/lac/vector.h>
28 #include <deal.II/lac/block_sparsity_pattern.h>
29 #include <deal.II/lac/block_sparse_matrix.h>
30 #include <deal.II/numerics/vector_tools.h>
31 
32 #include <vector>
33 #include <iostream>
34 #include <fstream>
35 #include <iomanip>
36 
37 #include "parameterreader.h"
38 
39 
40 
41 
42 namespace DOpE
43 {
54  template <typename INTEGRATOR, typename LINEARSOLVER, typename VECTOR>
55  class InstatStepNewtonSolver : public LINEARSOLVER
56  {
57  public:
65  InstatStepNewtonSolver(INTEGRATOR &integrator, ParameterReader &param_reader);
67 
68  static void declare_params(ParameterReader &param_reader);
69 
70  /******************************************************/
71 
76  template<typename PROBLEM>
77  void ReInit(PROBLEM& pde);
78 
79  /******************************************************/
80 
110  template<typename PROBLEM>
111  bool NonlinearSolve(PROBLEM& pde, const VECTOR &last_time_solution, VECTOR &solution,
112  bool apply_boundary_values=true,
113  bool force_matrix_build=false, int priority = 5, std::string algo_level = "\t\t ");
114  /******************************************************/
115 
145  template<typename PROBLEM>
146  bool NonlinearSolve_Initial(PROBLEM& pde, VECTOR &solution, bool apply_boundary_values=true,
147  bool force_matrix_build=false, int priority = 5, std::string algo_level = "\t\t ");
148 
149  /******************************************************/
150 
161  template<typename PROBLEM>
162  void NonlinearLastTimeEvals(PROBLEM& pde, const VECTOR &last_time_solution, VECTOR &residual);
163 
164  protected:
165 
166  inline INTEGRATOR& GetIntegrator();
167 
168  private:
169  INTEGRATOR &integrator_;
170 
171  bool build_matrix_;
172 
173  double nonlinear_global_tol_, nonlinear_tol_, nonlinear_rho_;
174  double linesearch_rho_;
175  int nonlinear_maxiter_, line_maxiter_;
176  };
177 
178  /**********************************Implementation*******************************************/
179 
180 template <typename INTEGRATOR, typename LINEARSOLVER, typename VECTOR>
183  {
184  param_reader.SetSubsection("newtonsolver parameters");
185  param_reader.declare_entry("nonlinear_global_tol", "1.e-12",Patterns::Double(0),"global tolerance for the newton iteration");
186  param_reader.declare_entry("nonlinear_tol", "1.e-10",Patterns::Double(0),"relative tolerance for the newton iteration");
187  param_reader.declare_entry("nonlinear_maxiter", "10",Patterns::Integer(0),"maximal number of newton iterations");
188  param_reader.declare_entry("nonlinear_rho", "0.1",Patterns::Double(0),"minimal newton reduction, if actual reduction is less, matrix is rebuild ");
189 
190  param_reader.declare_entry("line_maxiter", "4",Patterns::Integer(0),"maximal number of linesearch steps");
191  param_reader.declare_entry("linesearch_rho", "0.9",Patterns::Double(0),"reduction rate for the linesearch damping paramete");
192 
193  LINEARSOLVER::declare_params(param_reader);
194  }
195 
196  /*******************************************************************************************/
197 
198  template <typename INTEGRATOR, typename LINEARSOLVER, typename VECTOR>
200  ::InstatStepNewtonSolver(INTEGRATOR &integrator, ParameterReader &param_reader)
201  : LINEARSOLVER(param_reader), integrator_(integrator)
202  {
203  param_reader.SetSubsection("newtonsolver parameters");
204  nonlinear_global_tol_ = param_reader.get_double ("nonlinear_global_tol");
205  nonlinear_tol_ = param_reader.get_double ("nonlinear_tol");
206  nonlinear_maxiter_ = param_reader.get_integer ("nonlinear_maxiter");
207  nonlinear_rho_ = param_reader.get_double ("nonlinear_rho");
208 
209  line_maxiter_ = param_reader.get_integer ("line_maxiter");
210  linesearch_rho_ = param_reader.get_double ("linesearch_rho");
211 
212  }
213 
214  /*******************************************************************************************/
215 
216  template <typename INTEGRATOR, typename LINEARSOLVER, typename VECTOR>
219  {
220  }
221 
222  /*******************************************************************************************/
223  template <typename INTEGRATOR, typename LINEARSOLVER, typename VECTOR>
224  template<typename PROBLEM>
226  ::ReInit(PROBLEM& pde)
227  {
228  LINEARSOLVER::ReInit(pde);
229  }
230 
231  /*******************************************************************************************/
232  template <typename INTEGRATOR, typename LINEARSOLVER, typename VECTOR>
233  template<typename PROBLEM>
235  ::NonlinearLastTimeEvals(PROBLEM& pde, const VECTOR &last_time_solution, VECTOR &residual)
236  {
237  VECTOR tmp_residual;
238  tmp_residual.reinit(residual);
239  residual =0.;
240  GetIntegrator().AddDomainData("last_newton_solution",&last_time_solution);
241  GetIntegrator().AddDomainData("last_time_solution",&last_time_solution);
242  pde.SetStepPart("Old");
243  GetIntegrator().ComputeNonlinearLhs(pde,residual);
244  GetIntegrator().ComputeNonlinearRhs(pde,tmp_residual);
245  tmp_residual *= -1;
246  residual += tmp_residual;
247 
248  GetIntegrator().DeleteDomainData("last_newton_solution");
249  GetIntegrator().DeleteDomainData("last_time_solution");
250 
251  }
252  /*******************************************************************************************/
253 
254  template <typename INTEGRATOR, typename LINEARSOLVER, typename VECTOR>
255  template<typename PROBLEM>
257  ::NonlinearSolve_Initial(PROBLEM& pde, VECTOR &solution, bool apply_boundary_values,
258  bool force_matrix_build, int priority, std::string algo_level)
259  {
260  bool build_matrix = force_matrix_build;
261  VECTOR residual;
262  VECTOR du;
263  std::stringstream out;
264  pde.GetOutputHandler()->InitNewtonOut(out);
265 
266  du.reinit(solution);
267  residual.reinit(solution);
268 
269  if(apply_boundary_values)
270  {
271  GetIntegrator().ApplyInitialBoundaryValues(pde,solution);
272  }
273  pde.GetDoFConstraints().distribute(solution);
274 
275  GetIntegrator().AddDomainData("last_newton_solution",&solution);
276 
277  GetIntegrator().ComputeNonlinearResidual(pde,residual);
278  residual *= -1.;
279 
280  pde.GetOutputHandler()->SetIterationNumber(0,"PDENewton");
281  pde.GetOutputHandler()->Write(residual,"Residual"+pde.GetType(),pde.GetDoFType());
282 
283  double res = residual.linfty_norm();
284  double firstres = res;
285  double lastres = res;
286 
287 
288  out<< algo_level << "Newton step: " <<0<<"\t Residual (abs.): "
289  <<pde.GetOutputHandler()->ZeroTolerance(res, 1.0)
290  <<"\n";
291 
292  out<< algo_level << "Newton step: " <<0<<"\t Residual (rel.): " << std::scientific << pde.GetOutputHandler()->ZeroTolerance(firstres/firstres,1.0);
293 
294 
295  pde.GetOutputHandler()->Write(out,priority);
296 
297  int iter=0;
298  while(res > nonlinear_global_tol_ && res > firstres * nonlinear_tol_)
299  {
300  iter++;
301 
302  if(iter > nonlinear_maxiter_)
303  {
304  GetIntegrator().DeleteDomainData("last_newton_solution");
305  throw DOpEIterationException("Iteration count exceeded bounds!","InstatStepNewtonSolver::NonlinearSolve_Initial");
306  }
307 
308  pde.GetOutputHandler()->SetIterationNumber(iter,"PDENewton");
309 
310  LINEARSOLVER::Solve(pde,GetIntegrator(),residual,du,build_matrix);
311  build_matrix = false;
312 
313  //Linesearch
314  {
315  solution += du;
316  GetIntegrator().ComputeNonlinearResidual(pde,residual);
317  residual *= -1.;
318 
319  pde.GetOutputHandler()->Write(residual,"Residual"+pde.GetType(),pde.GetDoFType());
320  pde.GetOutputHandler()->Write(du,"Update"+pde.GetType(),pde.GetDoFType());
321 
322  double newres = residual.linfty_norm();
323  int lineiter=0;
324  double rho = linesearch_rho_;
325  double alpha=1;
326 
327  while(newres > res)
328  {
329  out<< algo_level << "Newton step: " <<iter<<"\t Residual (rel.): "
330  <<pde.GetOutputHandler()->ZeroTolerance(newres/firstres, 1.0)
331  << "\t LineSearch {"<<lineiter<<"} ";
332 
333  pde.GetOutputHandler()->Write(out,priority+1);
334 
335  lineiter++;
336  if(lineiter > line_maxiter_)
337  {
338  GetIntegrator().DeleteDomainData("last_newton_solution");
339  throw DOpEIterationException("Line-Iteration count exceeded bounds!","InstatStepNewtonSolver::NonlinearSolve_Initial");
340  }
341  solution.add(alpha*(rho-1.),du);
342  alpha*= rho;
343 
344  GetIntegrator().ComputeNonlinearResidual(pde,residual);
345  residual *= -1.;
346  pde.GetOutputHandler()->Write(residual,"Residual"+pde.GetType(),pde.GetDoFType());
347 
348  newres = residual.linfty_norm();
349 
350  }
351  if(res/lastres > nonlinear_rho_)
352  {
353  build_matrix=true;
354  }
355  lastres=res;
356  res=newres;
357 
358  out << algo_level
359  << "Newton step: "
360  <<iter
361  <<"\t Residual (rel.): "
362  << pde.GetOutputHandler()->ZeroTolerance(res/firstres, 1.0)
363  << "\t LineSearch {"
364  <<lineiter
365  <<"} ";
366 
367 
368  pde.GetOutputHandler()->Write(out,priority);
369 
370  }//End of Linesearch
371  }
372  GetIntegrator().DeleteDomainData("last_newton_solution");
373 
374  return build_matrix;
375  }
376 
377  /*******************************************************************************************/
378  template <typename INTEGRATOR, typename LINEARSOLVER, typename VECTOR>
379  template<typename PROBLEM>
381  ::NonlinearSolve(PROBLEM& pde,
382  const VECTOR &last_time_solution,
383  VECTOR &solution,
384  bool apply_boundary_values,
385  bool force_matrix_build,
386  int priority,
387  std::string /*algo_level*/)
388  {
389 
390  bool build_matrix = force_matrix_build;
391  VECTOR residual, time_residual, tmp_residual;
392  VECTOR du;
393  std::stringstream out;
394  pde.GetOutputHandler()->InitNewtonOut(out);
395 
396  double res = 0.0;
397  double firstres = 0.0;
398  double lastres = 0.0;
399 
400  du.reinit(solution);
401  residual.reinit(solution);
402  time_residual.reinit(solution);
403  tmp_residual.reinit(solution);
404 
405  //Transfer from previous timestep
406  residual +=solution;
407  // last_time_solution is very good starting value?
408  solution = last_time_solution;
409 
410  if(apply_boundary_values)
411  {
412  GetIntegrator().ApplyInitialBoundaryValues(pde,solution);
413  }
414 
415  // Righthandside for the current timestep f^{n+1}
416  GetIntegrator().AddDomainData("last_time_solution",&last_time_solution);
417  GetIntegrator().AddDomainData("last_newton_solution",&solution);
418  pde.SetStepPart("New");
419  GetIntegrator().ComputeNonlinearRhs(pde,tmp_residual);
420  tmp_residual *= -1;
421  residual += tmp_residual;
422 
423  // Save the part of the residual which is independent of u^{n+1}
424  time_residual = residual;
425  time_residual *=-1;
426 
427  // Calculate the "real" residual in the current timestep
428  GetIntegrator().ComputeNonlinearLhs(pde,tmp_residual); // modi, new
429  residual += tmp_residual;
430 
431  residual *=-1.; // due to A(U)(\psi) = - A(U)(du,\psi)
432 
433  pde.GetOutputHandler()->SetIterationNumber(0,"PDENewton");
434  pde.GetOutputHandler()->Write(residual,"Residual"+pde.GetType(),pde.GetDoFType());
435 
436  res = residual.linfty_norm();
437  firstres = res;
438  lastres = res;
439  int iter=0;
440 
441  out<<"\t\t Newton step: " <<0<<"\t Residual (abs.): "
442  <<pde.GetOutputHandler()->ZeroTolerance(res, 1.0)
443  <<"\n";
444 
445  out<<"\t\t Newton step: " <<0<<"\t Residual (rel.): "<< std::scientific << pde.GetOutputHandler()->ZeroTolerance(firstres/firstres,1.0);
446 
447 
448 
449  pde.GetOutputHandler()->Write(out,priority);
450  while(res > nonlinear_global_tol_ && res > firstres * nonlinear_tol_)
451  {
452  iter++;
453  if(iter > nonlinear_maxiter_)
454  {
455  throw DOpEIterationException("Iteration count exceeded bounds!","StatSolver::NonlinearSolve");
456  }
457 
458  pde.GetOutputHandler()->SetIterationNumber(iter,"PDENewton");
459  LINEARSOLVER::Solve(pde,GetIntegrator(),residual,du,build_matrix);
460  build_matrix = false;
461  //Linesearch
462  {
463  solution += du;
464  GetIntegrator().ComputeNonlinearLhs(pde,residual);
465  residual -= time_residual;
466  residual *= -1.;
467  pde.GetOutputHandler()->Write(residual,"Residual"+pde.GetType(),pde.GetDoFType());
468 
469  double newres = residual.linfty_norm();
470  int lineiter=0;
471  double rho = linesearch_rho_;
472  double alpha=1;
473 
474  while(newres > res)
475  {
476  out<<"\t\t\t Linesearch step: " <<lineiter<<"\t Residual (rel.): "
477  <<pde.GetOutputHandler()->ZeroTolerance(newres/firstres, 1.0);
478  pde.GetOutputHandler()->Write(out,priority+1);
479  lineiter++;
480  if(lineiter > line_maxiter_)
481  {
482  throw DOpEIterationException("Line-Iteration count exceeded bounds!","StatSolver::NonlinearSolve");
483  }
484  solution.add(alpha*(rho-1.),du);
485  alpha*= rho;
486 
487  GetIntegrator().ComputeNonlinearLhs(pde,residual);
488  residual -= time_residual;
489  residual *= -1.;
490  pde.GetOutputHandler()->Write(residual,"Residual"+pde.GetType(),pde.GetDoFType());
491 
492  newres = residual.linfty_norm();
493 
494  }
495  if(res/lastres > nonlinear_rho_)
496  {
497  build_matrix=true;
498  }
499  lastres=res;
500  res=newres;
501 
502  out<<"\t\t Newton step: " <<iter<<"\t Residual (rel.): "
503  << pde.GetOutputHandler()->ZeroTolerance(res/firstres, 1.0)
504  << "\t LineSearch {"<<lineiter<<"} ";
505  pde.GetOutputHandler()->Write(out,priority);
506 
507  }//End of Linesearch
508  }
509  GetIntegrator().DeleteDomainData("last_time_solution");
510  GetIntegrator().DeleteDomainData("last_newton_solution");
511 
512 
513  return build_matrix;
514  }
515 
516 /*******************************************************************************************/
517  template <typename INTEGRATOR, typename LINEARSOLVER, typename VECTOR>
520  {
521  return integrator_;
522  }
523 
524  /*******************************************************************************************/
525 
526 }
527 #endif
bool NonlinearSolve_Initial(PROBLEM &pde, VECTOR &solution, bool apply_boundary_values=true, bool force_matrix_build=false, int priority=5, std::string algo_level="\t\t ")
Definition: instat_step_newtonsolver.h:257
Definition: dopeexception.h:76
void NonlinearLastTimeEvals(PROBLEM &pde, const VECTOR &last_time_solution, VECTOR &residual)
Definition: instat_step_newtonsolver.h:235
double get_double(const std::string &entry_name)
Definition: parameterreader.h:115
static void declare_params(ParameterReader &param_reader)
Definition: instat_step_newtonsolver.h:182
Definition: parameterreader.h:36
bool NonlinearSolve(PROBLEM &pde, const VECTOR &last_time_solution, VECTOR &solution, bool apply_boundary_values=true, bool force_matrix_build=false, int priority=5, std::string algo_level="\t\t ")
Definition: instat_step_newtonsolver.h:381
~InstatStepNewtonSolver()
Definition: instat_step_newtonsolver.h:218
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation=std::string())
Definition: parameterreader.h:98
InstatStepNewtonSolver(INTEGRATOR &integrator, ParameterReader &param_reader)
Definition: instat_step_newtonsolver.h:200
INTEGRATOR & GetIntegrator()
Definition: instat_step_newtonsolver.h:519
void ReInit(PROBLEM &pde)
Definition: instat_step_newtonsolver.h:226
Definition: instat_step_newtonsolver.h:55
int get_integer(const std::string &entry_name)
Definition: parameterreader.h:126
void SetSubsection(const std::string subsection)
Definition: parameterreader.h:93