Geant4-11
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
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
60 const G4double toleranceY = 1.e-4;
61
64
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)
std::pair< G4double, G4double > bracketRoot(RootFunctor const *const f, G4double x0)
Bracket the root of the function f.
const G4int maxIterations
Maximum number of iterations for convergence.
Solution solve(RootFunctor const *const f, const G4double x0)
Numerically solve a one-dimensional equation.