Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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)