HermesCommon  3.0
nonlinear_matrix_solver.cpp
1 // This file is part of HermesCommon
2 //
3 // Copyright (c) 2009 hp-FEM group at the University of Nevada, Reno (UNR).
4 // Email: hpfem-group@unr.edu, home page: http://www.hpfem.org/.
5 //
6 // Hermes2D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published
8 // by the Free Software Foundation; either version 2 of the License,
9 // or (at your option) any later version.
10 //
11 // Hermes2D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with Hermes2D; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "common.h"
24 #include "util/memory_handling.h"
25 
26 using namespace Hermes::Algebra;
27 
28 namespace Hermes
29 {
30  namespace Solvers
31  {
32  template<typename Scalar>
34  {
35  this->init_nonlinear();
36  }
37 
38  template<typename Scalar>
40  {
41  this->handleMultipleTolerancesAnd = false;
42  this->max_allowed_iterations = 20;
43  this->max_allowed_residual_norm = 1E9;
44  this->num_iters = 0;
45  this->previous_sln_vector = nullptr;
46  this->use_initial_guess_for_iterative_solvers = false;
47  this->clear_tolerances();
48  }
49 
50  template<typename Scalar>
52  {
53  this->free();
54  }
55 
56  template<typename Scalar>
58  {
59  free_with_check(this->sln_vector, true);
60  }
61 
62  template<typename Scalar>
64  {
65  bool toleranceSet = false;
66  for (int i = 0; i < NonlinearConvergenceMeasurementTypeCount; i++)
67  if (this->tolerance_set[i])
68  toleranceSet = true;
69  if (!toleranceSet)
70  {
71  throw Exceptions::Exception("No tolerance set in NonlinearMatrixSolver.");
72  return false;
73  }
74  return true;
75  }
76 
77  template<typename Scalar>
79  {
80  if (max_allowed_iterations_ < 1)
81  throw Exceptions::ValueException("max_allowed_iterations", max_allowed_iterations_, 1);
82  this->max_allowed_iterations = max_allowed_iterations_;
83  }
84 
85  template<typename Scalar>
87  {
88  return get_l2_norm(this->get_residual());
89  }
90 
91  template<typename Scalar>
93  {
94  this->check();
95  this->tick();
96 
97  // Number of DOFs.
98  assert(this->problem_size > 0);
99 
100  free_with_check(this->sln_vector, true);
101  this->sln_vector = malloc_with_check<NonlinearMatrixSolver<Scalar>, Scalar>(this->problem_size, this, true);
102 
103  if (coeff_vec == nullptr)
104  memset(this->sln_vector, 0, this->problem_size*sizeof(Scalar));
105  else
106  memcpy(this->sln_vector, coeff_vec, this->problem_size*sizeof(Scalar));
107 
108  // previous_sln_vector
109  this->previous_sln_vector = calloc_with_check<NonlinearMatrixSolver<Scalar>, Scalar>(this->problem_size, this, true);
110 
111  // Backup vector for unsuccessful reuse of Jacobian.
112  residual_back = create_vector<Scalar>();
113  residual_back->alloc(this->problem_size);
114 
115  this->previous_jacobian = nullptr;
116  this->previous_residual = nullptr;
117 
118  this->on_initialization();
119  }
120 
121  template<typename Scalar>
122  void NonlinearMatrixSolver<Scalar>::set_tolerance(double tolerance_, NonlinearConvergenceMeasurementType toleranceType, bool handleMultipleTolerancesAnd)
123  {
124  this->handleMultipleTolerancesAnd = handleMultipleTolerancesAnd;
125 
126  if (tolerance_ < 0.0)
127  throw Exceptions::ValueException("tolerance", tolerance_, 0.0);
128 
129  switch (toleranceType)
130  {
131  case ResidualNormRelativeToPrevious:
132  {
133  this->tolerance[0] = tolerance_;
134  this->tolerance_set[0] = true;
135  }
136  break;
137  case ResidualNormRatioToInitial:
138  {
139  this->tolerance[1] = tolerance_;
140  this->tolerance_set[1] = true;
141  }
142  break;
143  case ResidualNormRatioToPrevious:
144  {
145  this->tolerance[2] = tolerance_;
146  this->tolerance_set[2] = true;
147  }
148  break;
149  case ResidualNormAbsolute:
150  {
151  this->tolerance[3] = tolerance_;
152  this->tolerance_set[3] = true;
153  }
154  break;
155  case SolutionChangeAbsolute:
156  {
157  this->tolerance[4] = tolerance_;
158  this->tolerance_set[4] = true;
159  }
160  break;
161  case SolutionChangeRelative:
162  {
163  this->tolerance[5] = tolerance_;
164  this->tolerance_set[5] = true;
165  }
166  break;
167  default:
168  throw Exceptions::Exception("Unknown NonlinearConvergenceMeasurementType in NonlinearMatrixSolver::set_tolerance.");
169  }
170  }
171 
172  template<typename Scalar>
173  void NonlinearMatrixSolver<Scalar>::set_max_allowed_residual_norm(double max_allowed_residual_norm_to_set)
174  {
175  if (max_allowed_residual_norm_to_set < 0.0)
176  throw Exceptions::ValueException("max_allowed_residual_norm_to_set", max_allowed_residual_norm_to_set, 0.0);
177  this->max_allowed_residual_norm = max_allowed_residual_norm_to_set;
178  }
179 
180  template<typename Scalar>
182  {
183  return this->num_iters;
184  }
185 
186  template<typename Scalar>
188  {
189  if (this->get_current_iteration_number() >= this->max_allowed_iterations)
190  return AboveMaxIterations;
191 
193  return Converged;
194  else
195  return NotConverged;
196 
197  return Error;
198  }
199 
200  template<typename Scalar>
202  {
203  for (int i = 0; i < NonlinearConvergenceMeasurementTypeCount; i++)
204  this->tolerance[i] = std::numeric_limits<double>::max();
205  memset(this->tolerance_set, 0, sizeof(bool)*NonlinearConvergenceMeasurementTypeCount);
206  }
207 
208  template<typename Scalar>
210  {
211  if (ratio < 0.0)
212  throw Exceptions::ValueException("sufficient_improvement_factor_jacobian", sufficient_improvement_factor_jacobian, 0.0);
213  this->sufficient_improvement_factor_jacobian = ratio;
214  }
215 
216  template<typename Scalar>
218  {
219  this->max_steps_with_reused_jacobian = steps;
220  }
221 
222  template<typename Scalar>
223  void NonlinearMatrixSolver<Scalar>::set_min_allowed_damping_coeff(double min_allowed_damping_coeff_to_set)
224  {
225  if (min_allowed_damping_coeff_to_set < 0.0)
226  throw Exceptions::ValueException("min_allowed_damping_coeff_to_set", min_allowed_damping_coeff_to_set, 0.0);
227  this->min_allowed_damping_coeff = min_allowed_damping_coeff_to_set;
228  }
229 
230  template<typename Scalar>
232  {
233  if (coeff <= 0.0 || coeff > 1.0)
234  throw Exceptions::ValueException("coeff", coeff, 0.0, 1.0);
235  if (onOff)
236  {
237  this->manual_damping = true;
238  this->manual_damping_factor = coeff;
239  }
240  else
241  this->manual_damping = false;
242  }
243 
244  template<typename Scalar>
246  {
247  if (coeff <= 0.0 || coeff > 1.0)
248  throw Exceptions::ValueException("coeff", coeff, 0.0, 1.0);
249  if (this->manual_damping)
250  this->warn("Manual damping is turned on and you called set_initial_auto_damping_coeff(), turn off manual damping first by set_manual_damping_coeff(false);");
251  else
252  this->initial_auto_damping_factor = coeff;
253  }
254 
255  template<typename Scalar>
257  {
258  if (ratio <= 1.0)
259  throw Exceptions::ValueException("ratio", ratio, 1.0);
260  if (this->manual_damping)
261  this->warn("Manual damping is turned on and you called set_initial_auto_damping_coeff(), turn off manual damping first by set_manual_damping_coeff(false);");
262  this->auto_damping_ratio = ratio;
263  }
264 
265  template<typename Scalar>
267  {
268  if (ratio <= 0.0)
269  throw Exceptions::ValueException("ratio", ratio, 0.0);
270  if (this->manual_damping)
271  this->warn("Manual damping is turned on and you called set_initial_auto_damping_coeff(), turn off manual damping first by set_manual_damping_coeff(false);");
272  this->sufficient_improvement_factor = ratio;
273  }
274 
275  template<typename Scalar>
277  {
278  if (steps < 1)
279  throw Exceptions::ValueException("necessary_successful_steps_to_increase", steps, 0.0);
280  if (this->manual_damping)
281  this->warn("Manual damping is turned on and you called set_initial_auto_damping_coeff(), turn off manual damping first by set_manual_damping_coeff(false);");
282  this->necessary_successful_steps_to_increase = steps;
283  }
284 
285  template<typename Scalar>
287  {
288  // If we have not converged and everything else is ok, we finish.
289  if (state == NotConverged)
290  return false;
291 
292  // Act upon the state.
293  switch (state)
294  {
295  case Converged:
296  this->info("\tNonlinearSolver: done.\n");
297  break;
298  case AboveMaxIterations:
299  throw Exceptions::NonlinearException(AboveMaxIterations);
300  break;
301  case BelowMinDampingCoeff:
302  throw Exceptions::NonlinearException(BelowMinDampingCoeff);
303  break;
304  case AboveMaxAllowedResidualNorm:
305  throw Exceptions::NonlinearException(AboveMaxAllowedResidualNorm);
306  break;
307  case Error:
308  throw Exceptions::Exception("Unknown exception in NonlinearMatrixSolver.");
309  break;
310  default:
311  throw Exceptions::Exception("Unknown ConvergenceState in NonlinearMatrixSolver.");
312  break;
313  }
314 
315  // And now the finishing states (both good and bad).
316  this->finalize_solving();
317 
318  // Return that we should finish.
319  return true;
320  }
321 
322  template<typename Scalar>
323  bool NonlinearMatrixSolver<Scalar>::calculate_damping_factor(unsigned int& successful_steps)
324  {
325  std::vector<double>& damping_factors_vector = this->get_parameter_value(p_damping_factors);
326 
327  if (this->manual_damping)
328  {
329  damping_factors_vector.push_back(this->manual_damping_factor);
330  return true;
331  }
332 
333  if (this->damping_factor_condition())
334  {
335  if (++successful_steps >= this->necessary_successful_steps_to_increase)
336  {
337  double new_damping_factor = std::min(this->initial_auto_damping_factor, this->auto_damping_ratio * damping_factors_vector.back());
338  this->info("\t\tstep successful, new damping factor: %g.", new_damping_factor);
339  damping_factors_vector.push_back(new_damping_factor);
340  }
341  else
342  {
343  this->info("\t\tstep successful, keep damping factor: %g.", damping_factors_vector.back());
344  damping_factors_vector.push_back(damping_factors_vector.back());
345  }
346 
347  return true;
348  }
349  else
350  {
351  double current_damping_factor = damping_factors_vector.back();
352  damping_factors_vector.pop_back();
353  successful_steps = 0;
354  if (current_damping_factor <= this->min_allowed_damping_coeff)
355  {
356  this->warn("\t\tNOT successful, damping factor at minimum level: %g.", min_allowed_damping_coeff);
357  this->info("\t\tto decrease the minimum level, use set_min_allowed_damping_coeff()");
358  throw Exceptions::NonlinearException(BelowMinDampingCoeff);
359  }
360  else
361  {
362  double new_damping_factor = (1. / this->auto_damping_ratio) * current_damping_factor;
363  this->warn("\t\tNOT successful, step restarted with factor: %g.", new_damping_factor);
364  damping_factors_vector.push_back(new_damping_factor);
365  }
366 
367  return false;
368  }
369  }
370 
371  template<typename Scalar>
373  {
374  free_with_check(this->previous_sln_vector, true);
375  delete residual_back;
376  this->problem_size = -1;
377  if (this->previous_jacobian)
378  delete this->previous_jacobian;
379  if (this->previous_residual)
380  delete this->previous_residual;
381  }
382 
383  template<typename Scalar>
385  {
386  this->tick();
387  this->num_iters = this->get_current_iteration_number();
388  this->info("\tNonlinearSolver: solution duration: %f s.\n", this->last());
389  this->on_finish();
390  this->deinit_solving();
391  }
392 
393  template<typename Scalar>
394  bool NonlinearMatrixSolver<Scalar>::force_reuse_jacobian_values(unsigned int& successful_steps_with_reused_jacobian)
395  {
396  if (successful_steps_with_reused_jacobian >= this->max_steps_with_reused_jacobian)
397  {
398  successful_steps_with_reused_jacobian = 0;
399  return false;
400  }
401  successful_steps_with_reused_jacobian++;
402  return true;
403  }
404 
405  template<typename Scalar>
407  {
408  // Store the initial norm.
409  this->get_parameter_value(this->p_solution_norms).push_back(get_l2_norm(this->sln_vector, this->problem_size));
410 
411  // Assemble the system.
412  if (this->jacobian_reusable && this->constant_jacobian)
413  {
414  this->linear_matrix_solver->set_reuse_scheme(HERMES_REUSE_MATRIX_STRUCTURE_COMPLETELY);
415  this->assemble_residual(false);
416  this->get_parameter_value(this->p_iterations_with_recalculated_jacobian).push_back(false);
417  }
418  else
419  {
420  this->linear_matrix_solver->set_reuse_scheme(HERMES_CREATE_STRUCTURE_FROM_SCRATCH);
421  this->assemble(false, false);
422  this->jacobian_reusable = true;
423  this->get_parameter_value(this->p_iterations_with_recalculated_jacobian).push_back(true);
424  }
425 
426  // Get the residual norm and act upon it.
427  double residual_norm = this->calculate_residual_norm();
428  this->info("\n\tNonlinearSolver: initial residual norm: %g", residual_norm);
429  this->get_parameter_value(this->p_residual_norms).push_back(residual_norm);
430 
431  this->solve_linear_system();
432 
433  if (this->handle_convergence_state_return_finished(this->get_convergence_state()))
434  return true;
435 
436  if (this->on_initial_step_end() == false)
437  {
438  this->info("\tNonlinearSolver: aborted.");
439  this->finalize_solving();
440  return true;
441  }
442 
443  return false;
444  }
445 
446  template<typename Scalar>
448  {
449  // store the previous solution to previous_sln_vector.
450  memcpy(this->previous_sln_vector, this->sln_vector, sizeof(Scalar)*this->problem_size);
451 
452  // Solve, if the solver is iterative, give him the initial guess.
453  this->linear_matrix_solver->solve(this->use_initial_guess_for_iterative_solvers ? this->sln_vector : nullptr);
454 
455  // 1. store the solution.
456  double solution_change_norm = this->update_solution_return_change_norm(this->linear_matrix_solver->get_sln_vector());
457 
458  // 2. store the solution change.
459  this->get_parameter_value(this->p_solution_change_norms).push_back(solution_change_norm);
460 
461  // 3. store the solution norm.
462  this->get_parameter_value(this->p_solution_norms).push_back(get_l2_norm(this->sln_vector, this->problem_size));
463  }
464 
465  template<typename Scalar>
467  {
468  // Output.
469  this->info("\n\tNonlinearSolver: iteration %d,", this->get_current_iteration_number());
470  this->info("\t\tresidual norm: %g,", this->get_parameter_value(this->p_residual_norms).back());
471 
472  double solution_norm = this->get_parameter_value(this->p_solution_norms).back();
473  double previous_solution_norm = this->get_parameter_value(this->p_solution_norms)[this->get_parameter_value(this->p_solution_norms).size() - 2];
474  double solution_change_norm = this->get_parameter_value(this->p_solution_change_norms).back();
475  this->info("\t\tsolution norm: %g,", solution_norm);
476  this->info("\t\tsolution change norm: %g.", solution_change_norm);
477  this->info("\t\trelative solution change: %g.", solution_change_norm / previous_solution_norm);
478  }
479 
480  template<typename Scalar>
481  void NonlinearMatrixSolver<Scalar>::solve(Scalar* coeff_vec)
482  {
483  // Initialization.
484  this->init_solving(coeff_vec);
485 
486 #pragma region parameter_setup
487  // Initialize parameters.
488  unsigned int successful_steps_damping = 0;
489  unsigned int successful_steps_jacobian = 0;
490  std::vector<bool> iterations_with_recalculated_jacobian;
491  std::vector<double> residual_norms;
492  std::vector<double> solution_norms;
493  std::vector<double> solution_change_norms;
494  std::vector<double> damping_factors;
495  bool residual_norm_drop;
496  unsigned int iteration = 1;
497 
498  // Initial damping factor.
499  damping_factors.push_back(this->manual_damping ? manual_damping_factor : initial_auto_damping_factor);
500 
501  // Link parameters.
502  this->set_parameter_value(this->p_residual_norms, &residual_norms);
503  this->set_parameter_value(this->p_solution_norms, &solution_norms);
504  this->set_parameter_value(this->p_solution_change_norms, &solution_change_norms);
505  this->set_parameter_value(this->p_successful_steps_damping, &successful_steps_damping);
506  this->set_parameter_value(this->p_successful_steps_jacobian, &successful_steps_jacobian);
507  this->set_parameter_value(this->p_residual_norm_drop, &residual_norm_drop);
508  this->set_parameter_value(this->p_damping_factors, &damping_factors);
509  this->set_parameter_value(this->p_iterations_with_recalculated_jacobian, &iterations_with_recalculated_jacobian);
510  this->set_parameter_value(this->p_iteration, &iteration);
511 #pragma endregion
512 
513  // Does the initial step & checks the convergence & deallocates.
514  if (this->do_initial_step_return_finished())
515  return;
516 
517  // Main Nonlinear loop
518  while (true)
519  {
520  // Handle the event of step beginning.
521  if (!this->on_step_begin())
522  {
523  this->info("\tNonlinearSolver: aborted.");
524  this->finalize_solving();
525  return;
526  }
527 
528 #pragma region damping_factor_loop
529  this->info("\n\tNonlinearSolver: Damping factor handling:");
530  // Loop searching for the damping factor.
531  do
532  {
533  // Assemble just the residual.
534  this->assemble_residual(false);
535  // Current residual norm.
536  this->get_parameter_value(this->p_residual_norms).push_back(this->calculate_residual_norm());
537 
538  // Test convergence - if in this loop we found a solution.
539  this->info("\tNonlinearSolver: Convergence test...");
540  if (this->handle_convergence_state_return_finished(this->get_convergence_state()))
541  return;
542 
543  // Inspect the damping factor.
544  this->info("\tNonlinearSolver: Probing the damping factor...");
545  try
546  {
547  // Calculate damping factor, and return whether or not was this a successful step.
548  residual_norm_drop = this->calculate_damping_factor(successful_steps_damping);
549  }
551  {
552  this->finalize_solving();
553  throw e;
554  return;
555  }
556 
557  if (!residual_norm_drop)
558  {
559  // Delete the previous residual and solution norm.
560  residual_norms.pop_back();
561  solution_norms.pop_back();
562 
563  // Adjust the previous solution change norm.
564  solution_change_norms.back() /= this->auto_damping_ratio;
565 
566  // Try with the different damping factor.
567  // Important thing here is the factor used that must be calculated from the current one and the previous one.
568  // This results in the following relation (since the damping factor is only updated one way).
569  for (int i = 0; i < this->problem_size; i++)
570  this->sln_vector[i] = this->previous_sln_vector[i] + (this->sln_vector[i] - this->previous_sln_vector[i]) / this->auto_damping_ratio;
571 
572  // Add new_ solution norm.
573  solution_norms.push_back(get_l2_norm(this->sln_vector, this->problem_size));
574  }
575  } while (!residual_norm_drop);
576 #pragma endregion
577 
578  // Damping factor was updated, handle the event.
579  this->on_damping_factor_updated();
580 
581 #pragma region jacobian_reusage_loop
582  this->info("\n\tNonlinearSolver: Jacobian handling:");
583  // Loop until jacobian is not reusable anymore.
584  // The whole loop is skipped if the jacobian is not suitable for being reused at all.
585  while (this->jacobian_reusable && (this->constant_jacobian || force_reuse_jacobian_values(successful_steps_jacobian)))
586  {
587  this->residual_back->set_vector(this->get_residual());
588 
589  // Info & handle the situation as necessary.
590  this->info("\tNonlinearSolver: Reusing Jacobian.");
591  this->on_reused_jacobian_step_begin();
592 
593  // Solve the system.
594  this->linear_matrix_solver->set_reuse_scheme(HERMES_REUSE_MATRIX_STRUCTURE_COMPLETELY);
595  this->solve_linear_system();
596 
597  // Assemble next residual for both reusage and convergence test.
598  this->assemble_residual(false);
599  // Current residual norm.
600  this->get_parameter_value(this->p_residual_norms).push_back(this->calculate_residual_norm());
601 
602  // Test whether it was okay to reuse the jacobian.
603  if (!this->jacobian_reused_okay(successful_steps_jacobian))
604  {
605  this->warn("\tNonlinearSolver: Reused Jacobian disapproved.");
606  this->get_parameter_value(this->p_residual_norms).pop_back();
607  this->get_parameter_value(this->p_solution_norms).pop_back();
608  this->get_parameter_value(this->p_solution_change_norms).pop_back();
609  memcpy(this->sln_vector, this->previous_sln_vector, sizeof(Scalar)*this->problem_size);
610  this->get_residual()->set_vector(residual_back);
611  break;
612  }
613 
614  // Increase the iteration count.
615  this->get_parameter_value(this->p_iterations_with_recalculated_jacobian).push_back(false);
616  this->get_parameter_value(this->p_iteration)++;
617 
618  // Output successful reuse info.
619  this->step_info();
620 
621  // Handle the event of end of a step.
622  this->on_reused_jacobian_step_end();
623  if (!this->on_step_end())
624  {
625  this->info("\tNonlinearSolver: aborted.");
626  this->finalize_solving();
627  return;
628  }
629 
630  // Test convergence - if in this iteration we found a solution.
631  if (this->handle_convergence_state_return_finished(this->get_convergence_state()))
632  return;
633  }
634 #pragma endregion
635 
636  // Reassemble the jacobian once not reusable anymore.
637  this->info("\tNonlinearSolver: Re-calculating Jacobian.");
638 
639  // Set factorization scheme.
640  this->assemble_jacobian(true);
641  this->linear_matrix_solver->set_reuse_scheme(HERMES_CREATE_STRUCTURE_FROM_SCRATCH);
642 
643  // Solve the system, state that the jacobian is reusable should it be desirable.
644  this->solve_linear_system();
645  this->jacobian_reusable = true;
646 
647  // Increase the iteration count.
648  this->get_parameter_value(this->p_iterations_with_recalculated_jacobian).push_back(true);
649  this->get_parameter_value(this->p_iteration)++;
650 
651  // Output info.
652  this->step_info();
653 
654  // Handle the event of end of a step.
655  if (!this->on_step_end())
656  {
657  this->info("\tNonlinearSolver: aborted.");
658  this->finalize_solving();
659  return;
660  }
661 
662  // Test convergence - if in this iteration we found a solution.
663  if (this->handle_convergence_state_return_finished(this->get_convergence_state()))
664  return;
665  }
666  }
667 
668  template<typename Scalar>
670  {
671  double residual_norm = *(this->get_parameter_value(this->residual_norms()).end() - 1);
672  double previous_residual_norm = *(this->get_parameter_value(this->residual_norms()).end() - 2);
673 
674  return (residual_norm < previous_residual_norm * this->sufficient_improvement_factor);
675  }
676 
677  template<typename Scalar>
679  {
680  return this->get_parameter_value(this->p_iteration);
681  }
682 
683  template<typename Scalar>
684  bool NonlinearMatrixSolver<Scalar>::jacobian_reused_okay(unsigned int& successful_steps_with_reused_jacobian)
685  {
686  double residual_norm = *(this->get_parameter_value(this->p_residual_norms).end() - 1);
687  double previous_residual_norm = *(this->get_parameter_value(this->p_residual_norms).end() - 2);
688 
689  if ((residual_norm / previous_residual_norm) > this->sufficient_improvement_factor_jacobian)
690  {
691  successful_steps_with_reused_jacobian = 0;
692  return false;
693  }
694  else
695  return true;
696  }
697 
698  template<typename Scalar>
700  {
701  }
702 
703  template<typename Scalar>
705  {
706  }
707 
708  template<typename Scalar>
710  {
711  }
712 
713  template class HERMES_API NonlinearMatrixSolver < double > ;
714  template class HERMES_API NonlinearMatrixSolver < std::complex<double> > ;
715  }
716 
717  namespace Exceptions
718  {
719  NonlinearException::NonlinearException(Solvers::NonlinearConvergenceState convergenceState) : Exception("NonlinearException"), convergenceState(convergenceState)
720  {
721  }
722 
723  Solvers::NonlinearConvergenceState NonlinearException::get_exception_state()
724  {
725  return this->convergenceState;
726  }
727  }
728 }
General namespace for the Hermes library.
void set_max_allowed_residual_norm(double max_allowed_residual_norm_to_set)
virtual bool isOkay() const
State querying helpers.
Exception interface Basically a std::exception, but with a constructor with string and with print_msg...
Definition: exceptions.h:49
NonlinearConvergenceMeasurementType
This specifies the quantity that is compared to newton_tolerance (settable by set_tolerance()).
bool force_reuse_jacobian_values(unsigned int &successful_steps_with_reused_jacobian)
For deciding if the jacobian is reused at this point.
int get_current_iteration_number()
Shortcut method for getting the current iteration.
void set_manual_damping_coeff(bool onOff, double coeff)
Namespace containing classes for vector / matrix operations.
File containing common definitions, and basic global enums etc. for HermesCommon. ...
virtual void free()
Frees the instances.
void set_min_allowed_damping_coeff(double min_allowed_damping_coeff_to_set)
Base class for defining interface for nonlinear solvers.
int get_num_iters() const
Get the number of iterations.
virtual double calculate_residual_norm()
Norm for convergence.
virtual bool handle_convergence_state_return_finished(NonlinearConvergenceState state)
NonlinearConvergenceState
Nonlinear Convergence state.
interface for both linear and nonlinear algebraic solvers.
Definition: matrix_solver.h:35
bool calculate_damping_factor(unsigned int &successful_steps)
Calculates the new_ damping coefficient.
void set_max_allowed_iterations(int max_allowed_iterations)
Set the maximum number of iterations, thus co-determine when to stop iterations.
void step_info()
Output info about the step.
virtual void init_solving(Scalar *coeff_vec)
virtual bool damping_factor_condition()
Returns iff the damping factor condition is fulfilled.
virtual NonlinearConvergenceState get_convergence_state()
Find out the convergence state.
File containing common definitions, and basic global enums etc. for HermesCommon. ...
bool jacobian_reused_okay(unsigned int &successful_steps_with_reused_jacobian)
For deciding if the reused jacobian did not bring residual increase at this point.
const int NonlinearConvergenceMeasurementTypeCount
Numeric value is out of allowed range.
Definition: exceptions.h:174
void init_nonlinear()
Shared code for constructors.
void set_necessary_successful_steps_to_increase(unsigned int steps)
virtual void clear_tolerances()
Clear (reset) all tolerances.
void set_tolerance(double newton_tol, NonlinearConvergenceMeasurementType toleranceType, bool handleMultipleTolerancesAnd=false)
General nonlinear solver functionality.
void set_max_steps_with_reused_jacobian(unsigned int steps)
virtual void solve_linear_system()
Solve the step's linear system.