evtgen is hosted by Hepforge, IPPP Durham
EvtGen  2.0.0
Monte Carlo generator of particle decays, in particular the weak decays of heavy flavour particles such as B mesons.
EvtBtoXsgammaRootFinder.cpp
Go to the documentation of this file.
1 
2 /***********************************************************************
3 * Copyright 1998-2020 CERN for the benefit of the EvtGen authors *
4 * *
5 * This file is part of EvtGen. *
6 * *
7 * EvtGen is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * EvtGen is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with EvtGen. If not, see <https://www.gnu.org/licenses/>. *
19 ***********************************************************************/
20 
22 
23 #include "EvtGenBase/EvtPatches.hh"
24 #include "EvtGenBase/EvtReport.hh"
25 
28 
29 #include <math.h>
30 using std::endl;
31 
32 //-------------
33 // C Headers --
34 //-------------
35 extern "C" {
36 }
37 
38 //-----------------------------------------------------------------------
39 // Local Macros, Typedefs, Structures, Unions and Forward Declarations --
40 //-----------------------------------------------------------------------
41 
42 #define EVTITGROOTFINDER_MAXIT 100
43 #define EVTITGROOTFINDER_RELATIVEPRECISION 1.0e-16
44 
46  const EvtItgAbsFunction* theFunc, double functionValue, double lowerValue,
47  double upperValue, double precision )
48 {
49  // Use the bisection to find the root.
50  // Iterates until find root to the accuracy of precision
51 
52  double xLower = 0.0, xUpper = 0.0;
53  double root = 0;
54 
55  double f1 = theFunc->value( lowerValue ) - functionValue;
56  double f2 = theFunc->value( upperValue ) - functionValue;
57 
58  if ( f1 * f2 > 0.0 ) {
59  EvtGenReport( EVTGEN_WARNING, "EvtGen" )
60  << "EvtBtoXsgammaRootFinder: No root in specified range !" << endl;
61  return 0;
62  }
63 
64  // Already have root
65  if ( fabs( f1 ) < precision ) {
66  root = lowerValue;
67  return root;
68  }
69  if ( fabs( f2 ) < precision ) {
70  root = upperValue;
71  return root;
72  }
73 
74  // Orient search so that f(xLower) < 0
75  if ( f1 < 0.0 ) {
76  xLower = lowerValue;
77  xUpper = upperValue;
78  } else {
79  xLower = upperValue;
80  xUpper = lowerValue;
81  }
82 
83  double rootGuess = 0.5 * ( lowerValue + upperValue );
84  double dxold = fabs( upperValue - lowerValue );
85  double dx = dxold;
86 
87  double f = theFunc->value( rootGuess ) - functionValue;
88 
89  for ( int j = 0; j < EVTITGROOTFINDER_MAXIT; j++ ) {
90  dxold = dx;
91  dx = 0.5 * ( xUpper - xLower );
92  rootGuess = xLower + dx;
93 
94  // If change in root is negligible, take it as solution.
95  if ( fabs( xLower - rootGuess ) < precision ) {
96  root = rootGuess;
97  return root;
98  }
99 
100  f = theFunc->value( rootGuess ) - functionValue;
101 
102  if ( f < 0.0 ) {
103  xLower = rootGuess;
104  } else {
105  xUpper = rootGuess;
106  }
107  }
108 
109  EvtGenReport( EVTGEN_WARNING, "EvtGen" )
110  << "EvtBtoXsgammaRootFinder: Maximum number of iterations "
111  << "in EvtBtoXsgammaRootFinder::foundRoot exceeded!"
112  << " Returning false." << endl;
113  return 0;
114 }
115 
117  EvtItgAbsFunction* theFunc1, EvtItgAbsFunction* theFunc2,
118  double integ1Precision, double integ2Precision, int maxLoop1, int maxLoop2,
119  double integLower, double integUpper, double lowerValue, double upperValue,
120  double precision )
121 {
122  // Use the bisection to find the root.
123  // Iterates until find root to the accuracy of precision
124 
125  //Need to work with integrators
126  auto func1Integ = EvtItgSimpsonIntegrator{*theFunc1, integ1Precision,
127  maxLoop1};
128  auto func2Integ = EvtItgSimpsonIntegrator{*theFunc2, integ2Precision,
129  maxLoop2};
130 
131  //coefficient 1 of the integrators is the root to be found
132  //need to set this to lower value to start off with
133  theFunc1->setCoeff( 1, 0, lowerValue );
134  theFunc2->setCoeff( 1, 0, lowerValue );
135 
136  double f1 = func1Integ.evaluate( integLower, integUpper ) -
137  theFunc2->getCoeff( 1, 2 ) *
138  func2Integ.evaluate( integLower, integUpper );
139  theFunc1->setCoeff( 1, 0, upperValue );
140  theFunc2->setCoeff( 1, 0, upperValue );
141  double f2 = func1Integ.evaluate( integLower, integUpper ) -
142  theFunc2->getCoeff( 1, 2 ) *
143  func2Integ.evaluate( integLower, integUpper );
144 
145  double xLower = 0.0, xUpper = 0.0;
146  double root = 0;
147 
148  if ( f1 * f2 > 0.0 ) {
149  EvtGenReport( EVTGEN_WARNING, "EvtGen" )
150  << "EvtBtoXsgammaRootFinder: No root in specified range !" << endl;
151  return false;
152  }
153 
154  // Already have root
155  if ( fabs( f1 ) < precision ) {
156  root = lowerValue;
157  return root;
158  }
159  if ( fabs( f2 ) < precision ) {
160  root = upperValue;
161  return root;
162  }
163 
164  // Orient search so that f(xLower) < 0
165  if ( f1 < 0.0 ) {
166  xLower = lowerValue;
167  xUpper = upperValue;
168  } else {
169  xLower = upperValue;
170  xUpper = lowerValue;
171  }
172 
173  double rootGuess = 0.5 * ( lowerValue + upperValue );
174  double dxold = fabs( upperValue - lowerValue );
175  double dx = dxold;
176 
177  theFunc1->setCoeff( 1, 0, rootGuess );
178  theFunc2->setCoeff( 1, 0, rootGuess );
179  double f = func1Integ.evaluate( integLower, integUpper ) -
180  theFunc2->getCoeff( 1, 2 ) *
181  func2Integ.evaluate( integLower, integUpper );
182 
183  for ( int j = 0; j < EVTITGROOTFINDER_MAXIT; j++ ) {
184  dxold = dx;
185  dx = 0.5 * ( xUpper - xLower );
186  rootGuess = xLower + dx;
187 
188  // If change in root is negligible, take it as solution.
189  if ( fabs( xLower - rootGuess ) < precision ) {
190  root = rootGuess;
191  return root;
192  }
193 
194  theFunc1->setCoeff( 1, 0, rootGuess );
195  theFunc2->setCoeff( 1, 0, rootGuess );
196  f = func1Integ.evaluate( integLower, integUpper ) -
197  theFunc2->getCoeff( 1, 2 ) *
198  func2Integ.evaluate( integLower, integUpper );
199 
200  if ( f < 0.0 ) {
201  xLower = rootGuess;
202  } else {
203  xUpper = rootGuess;
204  }
205  }
206 
207  EvtGenReport( EVTGEN_WARNING, "EvtGen" )
208  << "EvtBtoXsgammaRootFinder: Maximum number of iterations "
209  << "in EvtBtoXsgammaRootFinder::foundRoot exceeded!"
210  << " Returning false." << endl;
211  return 0;
212 }
std::ostream & EvtGenReport(EvtGenSeverity severity, const char *facility=0)
Definition: EvtReport.cpp:33
#define EVTITGROOTFINDER_MAXIT
virtual void setCoeff(int, int, double)=0
double GetGaussIntegFcnRoot(EvtItgAbsFunction *theFunc1, EvtItgAbsFunction *theFunc2, double integ1Precision, double integ2Precision, int maxLoop1, int maxLoop2, double integLower, double integUpper, double lowerValue, double upperValue, double precision)
virtual double value(double x) const
double GetRootSingleFunc(const EvtItgAbsFunction *theFunc, double functionValue, double lowerValue, double upperValue, double precision)
virtual double getCoeff(int, int)=0