KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
brent_iteration.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ \.
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Michael Andre
11 //
12 // Contributors: Jordi Cotela Dalmau
13 //
14 
15 #pragma once
16 
17 #include <cmath>
18 #include <algorithm>
19 #include "includes/define.h"
20 
21 namespace Kratos
22 {
23 
30 {
31 
32 public:
33 
40  template< typename func_t >
41  static double FindRoot(
42  func_t Function,
43  double Guess1,
44  double Guess2,
45  double Tolerance,
46  int MaximumIterations)
47  {
48  double a = Guess1;
49  double b = Guess2;
50  double fa = Function(a);
51  double fb = Function(b);
52 
53  if (fa*fb > 0.0)
54  {
55  KRATOS_THROW_ERROR(std::runtime_error,"Error in BrentIteration::FindRoot: The images of both initial guesses have the same sign.","");
56  }
57 
58  double c = b;
59  double fc = fb;
60  double p,q,r,s,tol1,xm;
61  // Explicit initialization to silence a gcc compilation warning
62  double d = 0.0, e = 0.0;
63  double eps = (Tolerance < 1e-8) ? Tolerance : 1e-8; // Small value, was machine precision in the original algorithm
64 
65  for( int iter = 0; iter < MaximumIterations; iter++ )
66  {
67  // Reorder values and update interval length
68  if ( fb*fc > 0.0 )
69  {
70  c = a;
71  fc = fa;
72  d = b-a;
73  e = d;
74  }
75 
76  if ( std::fabs(fc) < std::fabs(fb) )
77  {
78  a = b;
79  b = c;
80  c = a;
81  fa = fb;
82  fb = fc;
83  fc = fa;
84  }
85 
86  // Convergence check
87  tol1 = 2.*eps*std::fabs(b) + 0.5*Tolerance;
88  xm = 0.5*(c-b);
89 
90  if (std::fabs(xm) < tol1 || std::fabs(fb) < eps)
91  return b;
92 
93  if (std::fabs(e) > tol1 && std::fabs(fa) > std::fabs(fb) )
94  {
95  // Try to use inverse quadratic interpolation
96  s = fb/fa;
97  if ( std::fabs(a-c) < eps )
98  {
99  p = 2.0*xm*s;
100  q = 1.0-s;
101  }
102  else
103  {
104  q = fa/fc;
105  r = fb/fc;
106  p = s*( 2.0*xm*q*(q-r) - (b-a)*(r-1.0) );
107  q = (q-1.0)*(r-1.0)*(s-1.0);
108  }
109 
110  // Change sign of update if necessary
111  if ( p > 0.0 )
112  q = -q;
113  p = std::fabs(p);
114 
115  double bound1 = 3.0*xm*q - std::fabs(tol1*q);
116  double bound2 = std::fabs(e*q);
117  if ( 2.0*p < std::min( bound1 , bound2 ) )
118  {
119  // Accept inverse quadratic interpolation guess
120  e = d;
121  d = p/q;
122  }
123  else
124  {
125  // Fall back to bisection
126  d = xm;
127  e = d;
128  }
129  }
130  else
131  {
132  // Bounds decreasing too slowly, switch to bisection
133  d = xm;
134  e = d;
135  }
136 
137  // Move last best guess to a
138  a = b;
139  fa = fb;
140 
141  // Evaluate new guess
142  if (std::abs(d) > tol1)
143  {
144  b += d;
145  }
146  else
147  {
148  b += (xm > 0.0) ? std::fabs(tol1) : -std::fabs(tol1);
149  }
150  fb = Function(b);
151  }
152 
153 
154  return b;
155  }
156 
157 };
158 
159 }
Definition: brent_iteration.h:30
static double FindRoot(func_t Function, double Guess1, double Guess2, double Tolerance, int MaximumIterations)
Definition: brent_iteration.h:41
#define KRATOS_THROW_ERROR(ExceptionType, ErrorMessage, MoreInfo)
Definition: define.h:77
static double min(double a, double b)
Definition: GeometryFunctions.h:71
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
q
Definition: generate_convection_diffusion_explicit_element.py:109
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
c
Definition: generate_weakly_compressible_navier_stokes_element.py:108
int d
Definition: ode_solve.py:397
p
Definition: sensitivityMatrix.py:52
e
Definition: run_cpp_mpi_tests.py:31