ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4INCLRootFinder.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4INCLRootFinder.cc
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 
53 namespace G4INCL {
54 
55  namespace RootFinder {
56 
57  namespace {
58 
60  const G4double toleranceY = 1.e-4;
61 
63  const G4int maxIterations=50;
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 }