Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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// Pekka Kaitaniemi, CEA and Helsinki Institute of Physics
28// Davide Mancusi, CEA
29// Alain Boudard, CEA
30// Sylvie Leray, CEA
31// Joseph Cugnon, University of Liege
32//
33// INCL++ revision: v5.1.8
34//
35#define INCLXX_IN_GEANT4_MODE 1
36
37#include "globals.hh"
38
39/** \file G4INCLRootFinder.hh
40 * \brief Static root-finder algorithm.
41 *
42 * Provides a stateless root-finder algorithm.
43 *
44 * \date 2nd March 2011
45 * \author Davide Mancusi
46 */
47
48#include "G4INCLRootFinder.hh"
49#include "G4INCLGlobals.hh"
50#include "G4INCLLogger.hh"
51#include <utility>
52#include <cmath>
53
54namespace G4INCL {
55
56 std::pair<G4double,G4double> RootFinder::solution;
57
58 const G4double RootFinder::toleranceY = 1.e-4;
59
60 G4bool RootFinder::solve(RootFunctor const * const f, const G4double x0) {
61 // If we already have the solution, do nothing
62 const G4double y0 = (*f)(x0);
63 if( std::abs(y0) < toleranceY ) {
64 solution = std::make_pair(x0,y0);
65 return true;
66 }
67
68 // Bracket the root and set the initial values
69 std::pair<G4double,G4double> bracket = bracketRoot(f,x0);
70 G4double x1 = bracket.first;
71 G4double x2 = bracket.second;
72 // If x1>x2, it means that we could not bracket the root. Return false.
73 if(x1>x2) {
74 // Maybe zero is a good solution?
75 G4double y_at_zero = (*f)(0.);
76 if(std::abs(y_at_zero)<=toleranceY) {
77 f->cleanUp(true);
78 solution = std::make_pair(0.,y_at_zero);
79 return true;
80 } else {
81 WARN("Root-finding algorithm could not bracket the root." << std::endl);
82 f->cleanUp(false);
83 return false;
84 }
85 }
86
87 G4double y1 = (*f)(x1);
88 G4double y2 = (*f)(x2);
89 G4double x = x1;
90 G4double y = y1;
91
92 /* ********************************
93 * Start of the false-position loop
94 * ********************************/
95
96 // Keep track of the last updated interval end (-1=left, 1=right)
97 G4int lastUpdated = 0;
98
99 for(G4int iterations=0; std::abs(y) > toleranceY; iterations++) {
100
101 if(iterations > maxIterations) {
102 WARN("Root-finding algorithm did not converge." << std::endl);
103 f->cleanUp(false);
104 return false;
105 }
106
107 // Estimate the root position by linear interpolation
108 x = (y1*x2-y2*x1)/(y1-y2);
109
110 // Update the value of the function
111 y = (*f)(x);
112
113 // Update the bracketing interval
114 if(Math::sign(y) == Math::sign(y1)) {
115 x1=x;
116 y1=y;
117 if(lastUpdated==-1) y2 *= 0.5;
118 lastUpdated = -1;
119 } else {
120 x2=x;
121 y2=y;
122 if(lastUpdated==1) y1 *= 0.5;
123 lastUpdated = 1;
124 }
125 }
126
127 /* ******************************
128 * End of the false-position loop
129 * ******************************/
130
131 solution = std::make_pair(x,y);
132 f->cleanUp(true);
133 return true;
134 }
135
136 std::pair<G4double,G4double> RootFinder::bracketRoot(RootFunctor const * const f, G4double x0) {
137 G4double y0 = (*f)(x0);
138
139 const G4double scaleFactor = 1.5;
140
141 G4double x1;
142 if(x0!=0.)
143 x1=scaleFactor*x0;
144 else
145 x1=1.;
146 G4double y1 = (*f)(x1);
147
148 if(Math::sign(y0)!=Math::sign(y1))
149 return std::make_pair(x0,x1);
150
151 const G4double scaleFactorMinus1 = 1./scaleFactor;
152 G4double oldx0, oldx1, oldy1;
153 G4int iterations=0;
154 do {
155 if(iterations > maxIterations) {
156 DEBUG("Could not bracket the root." << std::endl);
157 return std::make_pair((G4double) 1.,(G4double) -1.);
158 }
159
160 oldx0=x0;
161 oldx1=x1;
162 oldy1=y1;
163
164 x0 *= scaleFactorMinus1;
165 x1 *= scaleFactor;
166 y0 = (*f)(x0);
167 y1 = (*f)(x1);
168 iterations++;
169 } while(Math::sign(y0)==Math::sign(y1));
170
171 if(Math::sign(y1)==Math::sign(oldy1))
172 return std::make_pair(x0,oldx0);
173 else
174 return std::make_pair(oldx1,x1);
175 }
176
177}
#define WARN(x)
#define DEBUG(x)
Static root-finder algorithm.
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
static G4bool solve(RootFunctor const *const f, const G4double x0)
Numerically solve a one-dimensional equation.
virtual void cleanUp(const G4bool success) const =0
G4int sign(T t)