Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4INCLRootFinder.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// INCL++ intra-nuclear cascade model
27// Alain Boudard, CEA-Saclay, France
28// Joseph Cugnon, University of Liege, Belgium
29// Jean-Christophe David, CEA-Saclay, France
30// Pekka Kaitaniemi, CEA-Saclay, France, and Helsinki Institute of Physics, Finland
31// Sylvie Leray, CEA-Saclay, France
32// Davide Mancusi, CEA-Saclay, France
33//
34#define INCLXX_IN_GEANT4_MODE 1
35
36#include "globals.hh"
37
38/** \file G4INCLRootFinder.hh
39 * \brief Static root-finder algorithm.
40 *
41 * Provides a stateless root-finder algorithm.
42 *
43 * \date 2nd March 2011
44 * \author Davide Mancusi
45 */
46
47#include "G4INCLRootFinder.hh"
48#include "G4INCLGlobals.hh"
49#include "G4INCLLogger.hh"
50#include <utility>
51#include <cmath>
52
53namespace G4INCL {
54
55 namespace RootFinder {
56
57 namespace {
58
59 /// \brief Tolerance on the y value
60 const G4double toleranceY = 1.e-4;
61
62 /// \brief Maximum number of iterations for convergence
63 const G4int maxIterations=50;
64
65 /** \brief Bracket the root of the function f.
66 *
67 * Tries to find a bracketing value for the function root.
68 *
69 * \param f pointer to a RootFunctor
70 * \param x0 starting value
71 * \return if the root could be bracketed, returns two values of x
72 * bracketing the root, as a pair. If the bracketing failed, returns a
73 * pair with first > second.
74 */
75 std::pair<G4double,G4double> bracketRoot(RootFunctor const * const f, G4double x0) {
76 G4double y0 = (*f)(x0);
77
78 const G4double scaleFactor = 1.5;
79
80 G4double x1;
81 if(x0!=0.)
82 x1=scaleFactor*x0;
83 else
84 x1=1.;
85 G4double y1 = (*f)(x1);
86
87 if(Math::sign(y0)!=Math::sign(y1))
88 return std::make_pair(x0,x1);
89
90 const G4double scaleFactorMinus1 = 1./scaleFactor;
91 G4double oldx0, oldx1, oldy1;
92 G4int iterations=0;
93 do {
94 if(iterations > maxIterations) {
95 INCL_DEBUG("Could not bracket the root." << '\n');
96 return std::make_pair((G4double) 1.,(G4double) -1.);
97 }
98
99 oldx0=x0;
100 oldx1=x1;
101 oldy1=y1;
102
103 x0 *= scaleFactorMinus1;
104 x1 *= scaleFactor;
105 y0 = (*f)(x0);
106 y1 = (*f)(x1);
107 iterations++;
108 } while(Math::sign(y0)==Math::sign(y1)); /* Loop checking, 10.07.2015, D.Mancusi */
109
110 if(Math::sign(y1)==Math::sign(oldy1))
111 return std::make_pair(x0,oldx0);
112 else
113 return std::make_pair(oldx1,x1);
114 }
115
116 }
117
118 Solution solve(RootFunctor const * const f, const G4double x0) {
119 // If we already have the solution, do nothing
120 const G4double y0 = (*f)(x0);
121 if( std::abs(y0) < toleranceY ) {
122 return Solution(x0,y0);
123 }
124
125 // Bracket the root and set the initial values
126 std::pair<G4double,G4double> bracket = bracketRoot(f,x0);
127 G4double x1 = bracket.first;
128 G4double x2 = bracket.second;
129 // If x1>x2, it means that we could not bracket the root. Return false.
130 if(x1>x2) {
131 // Maybe zero is a good solution?
132 G4double y_at_zero = (*f)(0.);
133 if(std::abs(y_at_zero)<=toleranceY) {
134 f->cleanUp(true);
135 return Solution(0.,y_at_zero);
136 } else {
137 INCL_DEBUG("Root-finding algorithm could not bracket the root." << '\n');
138 f->cleanUp(false);
139 return Solution();
140 }
141 }
142
143 G4double y1 = (*f)(x1);
144 G4double y2 = (*f)(x2);
145 G4double x = x1;
146 G4double y = y1;
147
148 /* ********************************
149 * Start of the false-position loop
150 * ********************************/
151
152 // Keep track of the last updated interval end (-1=left, 1=right)
153 G4int lastUpdated = 0;
154
155 for(G4int iterations=0; std::abs(y) > toleranceY; iterations++) {
156
157 if(iterations > maxIterations) {
158 INCL_DEBUG("Root-finding algorithm did not converge." << '\n');
159 f->cleanUp(false);
160 return Solution();
161 }
162
163 // Estimate the root position by linear interpolation
164 x = (y1*x2-y2*x1)/(y1-y2);
165
166 // Update the value of the function
167 y = (*f)(x);
168
169 // Update the bracketing interval
170 if(Math::sign(y) == Math::sign(y1)) {
171 x1=x;
172 y1=y;
173 if(lastUpdated==-1) y2 *= 0.5;
174 lastUpdated = -1;
175 } else {
176 x2=x;
177 y2=y;
178 if(lastUpdated==1) y1 *= 0.5;
179 lastUpdated = 1;
180 }
181 }
182
183 /* ******************************
184 * End of the false-position loop
185 * ******************************/
186
187 f->cleanUp(true);
188 return Solution(x,y);
189 }
190
191 } // namespace RootFinder
192}
#define INCL_DEBUG(x)
Static root-finder algorithm.
double G4double
Definition: G4Types.hh:83
int G4int
Definition: G4Types.hh:85
virtual void cleanUp(const G4bool success) const =0
G4int sign(const T t)
Solution solve(RootFunctor const *const f, const G4double x0)
Numerically solve a one-dimensional equation.