Geant4.10
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Data Structures | Functions
G4INCL::RootFinder Namespace Reference

Data Structures

class  Solution
 

Functions

Solution solve (RootFunctor const *const f, const G4double x0)
 Numerically solve a one-dimensional equation. More...
 

Function Documentation

Solution G4INCL::RootFinder::solve ( RootFunctor const *const  f,
const G4double  x0 
)

Numerically solve a one-dimensional equation.

Numerically solves the equation f(x)==0. This implementation uses the false-position method.

If a root is found, it can be retrieved using the getSolution() method,

Parameters
fpointer to a RootFunctor
x0initial value of the function argument
Returns
a Solution object describing the root, if it was found

Definition at line 117 of file G4INCLRootFinder.cc.

References G4INCL::RootFunctor::cleanUp(), INCL_DEBUG, G4INCL::Math::sign(), and test::x.

Referenced by G4INCL::InteractionAvatar::enforceEnergyConservation().

117  {
118  // If we already have the solution, do nothing
119  const G4double y0 = (*f)(x0);
120  if( std::abs(y0) < toleranceY ) {
121  return Solution(x0,y0);
122  }
123 
124  // Bracket the root and set the initial values
125  std::pair<G4double,G4double> bracket = bracketRoot(f,x0);
126  G4double x1 = bracket.first;
127  G4double x2 = bracket.second;
128  // If x1>x2, it means that we could not bracket the root. Return false.
129  if(x1>x2) {
130  // Maybe zero is a good solution?
131  G4double y_at_zero = (*f)(0.);
132  if(std::abs(y_at_zero)<=toleranceY) {
133  f->cleanUp(true);
134  return Solution(0.,y_at_zero);
135  } else {
136  INCL_DEBUG("Root-finding algorithm could not bracket the root." << std::endl);
137  f->cleanUp(false);
138  return Solution();
139  }
140  }
141 
142  G4double y1 = (*f)(x1);
143  G4double y2 = (*f)(x2);
144  G4double x = x1;
145  G4double y = y1;
146 
147  /* ********************************
148  * Start of the false-position loop
149  * ********************************/
150 
151  // Keep track of the last updated interval end (-1=left, 1=right)
152  G4int lastUpdated = 0;
153 
154  for(G4int iterations=0; std::abs(y) > toleranceY; iterations++) {
155 
156  if(iterations > maxIterations) {
157  INCL_DEBUG("Root-finding algorithm did not converge." << std::endl);
158  f->cleanUp(false);
159  return Solution();
160  }
161 
162  // Estimate the root position by linear interpolation
163  x = (y1*x2-y2*x1)/(y1-y2);
164 
165  // Update the value of the function
166  y = (*f)(x);
167 
168  // Update the bracketing interval
169  if(Math::sign(y) == Math::sign(y1)) {
170  x1=x;
171  y1=y;
172  if(lastUpdated==-1) y2 *= 0.5;
173  lastUpdated = -1;
174  } else {
175  x2=x;
176  y2=y;
177  if(lastUpdated==1) y1 *= 0.5;
178  lastUpdated = 1;
179  }
180  }
181 
182  /* ******************************
183  * End of the false-position loop
184  * ******************************/
185 
186  f->cleanUp(true);
187  return Solution(x,y);
188  }
int G4int
Definition: G4Types.hh:78
double G4double
Definition: G4Types.hh:76
#define INCL_DEBUG(x)
G4int sign(const T t)