EvtGen 2.2.0
Monte Carlo generator of particle decays, in particular the weak decays of heavy flavour particles such as B mesons.
Loading...
Searching...
No Matches
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
24
27
28#include <math.h>
29using std::endl;
30
31//-------------
32// C Headers --
33//-------------
34extern "C" {
35}
36
37//-----------------------------------------------------------------------
38// Local Macros, Typedefs, Structures, Unions and Forward Declarations --
39//-----------------------------------------------------------------------
40
41#define EVTITGROOTFINDER_MAXIT 100
42#define EVTITGROOTFINDER_RELATIVEPRECISION 1.0e-16
43
45 const EvtItgAbsFunction* theFunc, double functionValue, double lowerValue,
46 double upperValue, double precision )
47{
48 // Use the bisection to find the root.
49 // Iterates until find root to the accuracy of precision
50
51 double xLower = 0.0, xUpper = 0.0;
52 double root = 0;
53
54 double f1 = theFunc->value( lowerValue ) - functionValue;
55 double f2 = theFunc->value( upperValue ) - functionValue;
56
57 if ( f1 * f2 > 0.0 ) {
58 EvtGenReport( EVTGEN_WARNING, "EvtGen" )
59 << "EvtBtoXsgammaRootFinder: No root in specified range !" << endl;
60 return 0;
61 }
62
63 // Already have root
64 if ( fabs( f1 ) < precision ) {
65 root = lowerValue;
66 return root;
67 }
68 if ( fabs( f2 ) < precision ) {
69 root = upperValue;
70 return root;
71 }
72
73 // Orient search so that f(xLower) < 0
74 if ( f1 < 0.0 ) {
75 xLower = lowerValue;
76 xUpper = upperValue;
77 } else {
78 xLower = upperValue;
79 xUpper = lowerValue;
80 }
81
82 double rootGuess = 0.5 * ( lowerValue + upperValue );
83 double dxold = fabs( upperValue - lowerValue );
84 double dx = dxold;
85
86 double f = theFunc->value( rootGuess ) - functionValue;
87
88 for ( int j = 0; j < EVTITGROOTFINDER_MAXIT; j++ ) {
89 dxold = dx;
90 dx = 0.5 * ( xUpper - xLower );
91 rootGuess = xLower + dx;
92
93 // If change in root is negligible, take it as solution.
94 if ( fabs( xLower - rootGuess ) < precision ) {
95 root = rootGuess;
96 return root;
97 }
98
99 f = theFunc->value( rootGuess ) - functionValue;
100
101 if ( f < 0.0 ) {
102 xLower = rootGuess;
103 } else {
104 xUpper = rootGuess;
105 }
106 }
107
108 EvtGenReport( EVTGEN_WARNING, "EvtGen" )
109 << "EvtBtoXsgammaRootFinder: Maximum number of iterations "
110 << "in EvtBtoXsgammaRootFinder::foundRoot exceeded!"
111 << " Returning false." << endl;
112 return 0;
113}
114
116 EvtItgAbsFunction* theFunc1, EvtItgAbsFunction* theFunc2,
117 double integ1Precision, double integ2Precision, int maxLoop1, int maxLoop2,
118 double integLower, double integUpper, double lowerValue, double upperValue,
119 double precision )
120{
121 // Use the bisection to find the root.
122 // Iterates until find root to the accuracy of precision
123
124 //Need to work with integrators
125 auto func1Integ = EvtItgSimpsonIntegrator{ *theFunc1, integ1Precision,
126 maxLoop1 };
127 auto func2Integ = EvtItgSimpsonIntegrator{ *theFunc2, integ2Precision,
128 maxLoop2 };
129
130 //coefficient 1 of the integrators is the root to be found
131 //need to set this to lower value to start off with
132 theFunc1->setCoeff( 1, 0, lowerValue );
133 theFunc2->setCoeff( 1, 0, lowerValue );
134
135 double f1 = func1Integ.evaluate( integLower, integUpper ) -
136 theFunc2->getCoeff( 1, 2 ) *
137 func2Integ.evaluate( integLower, integUpper );
138 theFunc1->setCoeff( 1, 0, upperValue );
139 theFunc2->setCoeff( 1, 0, upperValue );
140 double f2 = func1Integ.evaluate( integLower, integUpper ) -
141 theFunc2->getCoeff( 1, 2 ) *
142 func2Integ.evaluate( integLower, integUpper );
143
144 double xLower = 0.0, xUpper = 0.0;
145 double root = 0;
146
147 if ( f1 * f2 > 0.0 ) {
148 EvtGenReport( EVTGEN_WARNING, "EvtGen" )
149 << "EvtBtoXsgammaRootFinder: No root in specified range !" << endl;
150 return false;
151 }
152
153 // Already have root
154 if ( fabs( f1 ) < precision ) {
155 root = lowerValue;
156 return root;
157 }
158 if ( fabs( f2 ) < precision ) {
159 root = upperValue;
160 return root;
161 }
162
163 // Orient search so that f(xLower) < 0
164 if ( f1 < 0.0 ) {
165 xLower = lowerValue;
166 xUpper = upperValue;
167 } else {
168 xLower = upperValue;
169 xUpper = lowerValue;
170 }
171
172 double rootGuess = 0.5 * ( lowerValue + upperValue );
173 double dxold = fabs( upperValue - lowerValue );
174 double dx = dxold;
175
176 theFunc1->setCoeff( 1, 0, rootGuess );
177 theFunc2->setCoeff( 1, 0, rootGuess );
178 double f = func1Integ.evaluate( integLower, integUpper ) -
179 theFunc2->getCoeff( 1, 2 ) *
180 func2Integ.evaluate( integLower, integUpper );
181
182 for ( int j = 0; j < EVTITGROOTFINDER_MAXIT; j++ ) {
183 dxold = dx;
184 dx = 0.5 * ( xUpper - xLower );
185 rootGuess = xLower + dx;
186
187 // If change in root is negligible, take it as solution.
188 if ( fabs( xLower - rootGuess ) < precision ) {
189 root = rootGuess;
190 return root;
191 }
192
193 theFunc1->setCoeff( 1, 0, rootGuess );
194 theFunc2->setCoeff( 1, 0, rootGuess );
195 f = func1Integ.evaluate( integLower, integUpper ) -
196 theFunc2->getCoeff( 1, 2 ) *
197 func2Integ.evaluate( integLower, integUpper );
198
199 if ( f < 0.0 ) {
200 xLower = rootGuess;
201 } else {
202 xUpper = rootGuess;
203 }
204 }
205
206 EvtGenReport( EVTGEN_WARNING, "EvtGen" )
207 << "EvtBtoXsgammaRootFinder: Maximum number of iterations "
208 << "in EvtBtoXsgammaRootFinder::foundRoot exceeded!"
209 << " Returning false." << endl;
210 return 0;
211}
#define EVTITGROOTFINDER_MAXIT
std::ostream & EvtGenReport(EvtGenSeverity severity, const char *facility=nullptr)
Definition EvtReport.cpp:32
@ EVTGEN_WARNING
Definition EvtReport.hh:50
double GetGaussIntegFcnRoot(EvtItgAbsFunction *theFunc1, EvtItgAbsFunction *theFunc2, double integ1Precision, double integ2Precision, int maxLoop1, int maxLoop2, double integLower, double integUpper, double lowerValue, double upperValue, double precision)
double GetRootSingleFunc(const EvtItgAbsFunction *theFunc, double functionValue, double lowerValue, double upperValue, double precision)
virtual double getCoeff(int, int)=0
virtual void setCoeff(int, int, double)=0
virtual double value(double x) const