Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Numerics.hh
Go to the documentation of this file.
1#ifndef G_NUMERICS_H
2#define G_NUMERICS_H
3
4#include <array>
5#include <functional>
6#include <complex>
7#include <vector>
8
10
11namespace Garfield {
12
13/// Collection of numerical routines.
14namespace Numerics {
15
16constexpr std::array<double, 2> GaussLegendreNodes2() {
17 return {-0.577350269189625765, 0.577350269189625765};
18}
19constexpr std::array<double, 2> GaussLegendreWeights2() {
20 return {1., 1.};
21}
22constexpr std::array<double, 3> GaussLegendreNodes3() {
23 return {-0.774596669241483377, 0., 0.774596669241483377};
24}
25constexpr std::array<double, 3> GaussLegendreWeights3() {
26 return {5. / 9., 8. / 9., 5. / 9.};
27}
28constexpr std::array<double, 4> GaussLegendreNodes4() {
29 return {-0.861136311594052575, -0.339981043584856265,
30 0.339981043584856265, 0.861136311594052575};
31}
32constexpr std::array<double, 4> GaussLegendreWeights4() {
33 return {0.347854845137453857, 0.652145154862546143,
34 0.652145154862546143, 0.347854845137453857};
35}
36constexpr std::array<double, 5> GaussLegendreNodes5() {
37 return {-0.906179845938663993, -0.538469310105683091, 0.,
38 0.538469310105683091, 0.906179845938663993};
39}
40constexpr std::array<double, 5> GaussLegendreWeights5() {
41 return {0.236926885056189088, 0.478628670499366468, 128. / 225.,
42 0.478628670499366468, 0.236926885056189088};
43}
44constexpr std::array<double, 6> GaussLegendreNodes6() {
45 return {-0.932469514203152028, -0.661209386466264514,
46 -0.238619186083196909, 0.238619186083196909,
47 0.661209386466264514, 0.932469514203152028};
48}
49constexpr std::array<double, 6> GaussLegendreWeights6() {
50 return {0.171324492379170345, 0.360761573048138608,
51 0.467913934572691047, 0.467913934572691047,
52 0.360761573048138608, 0.171324492379170345};
53}
54
55/// Functions for performing numerical integration (quadrature).
56/// Reimplemented from %QUADPACK.
57///
58/// R. Piessens, E. de Doncker-Kapenger, C. Ueberhuber, D. Kahaner,
59/// %QUADPACK, a Subroutine Package for Automatic Integration,
60/// Springer, 1983
61namespace QUADPACK {
62
63/// Estimates an integral over a semi-infinite or infinite interval.
64/// Calculates an approximation to an integral
65/// \f[ I = \int_{a}^{\infty} f\left(x\right) dx, \f]
66/// or
67/// \f[ I = \int_{-\infty}^{a} f\left(x\right) dx, \f]
68/// or
69/// \f[ I = \int_{-\infty}^{\infty} f\left(x\right) dx \f]
70/// hopefully satisfying
71/// \f[
72/// \left| I - \mathrm{RESULT} \right| \leq
73/// \max(\varepsilon_{\mathrm{abs}}, \varepsilon_{\mathrm{rel}} \left|I\right|).
74/// \f]
75/// \param f function to be integrated.
76/// \param bound value of the finite endpoint of the integration range (if any).
77/// \param inf indicates the type of integration range.
78/// - 1: ( bound, +Infinity)
79/// - -1: (-Infinity, bound)
80/// - 2: (-Infinity, +Infinity)
81/// \param epsabs requested absolute accuracy
82/// \param epsrel requested relative accuracy
83/// \param result the estimated value of the integral
84/// \param abserr estimated error
85/// \param status error flag
86/// - 0: normal and reliable termination, requested accuracy
87/// has been achieved.
88/// - > 0: abnormal termination, estimates for result and error
89/// are less reliable.
90/// - 1: maximum number of subdivisions reached.
91/// - 2: occurance of roundoff error prevents the requested
92/// tolerance from being achieved. Error may be underestimated.
93/// - 3: extremely bad integrand behaviour at some points of the
94/// integration interval.
95/// - 4: algorithm does not converge, roundoff error is detected in
96/// the extrapolation table. It is assumed that the requested
97/// tolerance cannot be achieved and that the returned result
98/// is the best that can be obtained.
99/// - 5: integral is probably divergent, or slowly convergent.
100/// - 6: invalid input.
101void qagi(std::function<double(double)> f, double bound, const int inf,
102 const double epsabs, const double epsrel,
103 double& result, double& abserr, unsigned int& status);
104
105/// 15-point Gauss-Kronrod integration with (semi-)infinite integration range.
106/// \param f function to be integrated.
107/// \param bound finite bound of original integration range (0 if inf = 2).
108/// \param inf indicates the type of integration range.
109/// \param a lower limit for integration over subrange of (0, 1).
110/// \param b upper limit for integration over subrange of (0, 1).
111/// \param result approximation to the integral.
112/// \param abserr estimate of the modulus of the absolute error.
113/// \param resabs approximation to the integral over \f$\left|f\right|\f$.
114/// \param resasc approximation to the integral of
115/// \f$\left|f - I / (b-a)\right|\f$ over \f$(a,b)\f$.
116void qk15i(std::function<double(double)> f, double bound, const int inf,
117 const double a, const double b, double& result, double& abserr,
118 double& resabs, double& resasc);
119
120/// 15-point Gauss-Kronrod integration with finite integration range.
121void qk15(std::function<double(double)> f, const double a, const double b,
122 double& result, double& abserr, double& resabs, double& resasc);
123
124}
125
126/// Linear algebra routines from CERNLIB.
127namespace CERNLIB {
128
129/// Replaces b by the solution x of Ax = b, after which A is undefined.
130/// \param n order of the square matrix A.
131/// \param a n by n matrix.
132/// \param b right-hand side vector.
133/// \returns 0: normal exit, -1: singular matrix.
134int deqn(const int n, std::vector<std::vector<double> >& a,
135 std::vector<double>& b);
136/// Replaces b by the solution x of Ax = b, and replace A by its inverse.
137int deqinv(const int n, std::vector<std::vector<double> >& a,
138 std::vector<double>& b);
139
140void dfact(const int n, std::vector<std::vector<double> >& a,
141 std::vector<int>& ir, int& ifail, double& det, int& jfail);
142void dfeqn(const int n, std::vector<std::vector<double> >& a,
143 std::vector<int>& ir, std::vector<double>& b);
144void dfinv(const int n, std::vector<std::vector<double> >& a,
145 std::vector<int>& ir);
146/// Replace square matrix A by its inverse.
147int dinv(const int n, std::vector<std::vector<double> >& a);
148
149void cfact(const int n, std::vector<std::vector<std::complex<double> > >& a,
150 std::vector<int>& ir, int& ifail, std::complex<double>& det,
151 int& jfail);
152void cfinv(const int n, std::vector<std::vector<std::complex<double> > >& a,
153 std::vector<int>& ir);
154
155/// Replace square matrix A by its inverse.
156int cinv(const int n, std::vector<std::vector<std::complex<double> > >& a);
157
158void cfft(std::vector<std::complex<double> >& a, const int msign);
159}
160
161/// Legendre polynomials.
162inline double Legendre(const unsigned int n, const double x) {
163
164 if (std::abs(x) > 1.) return 0.;
165 double p0 = 1.;
166 double p1 = x;
167 if (n == 0) return p0;
168 if (n == 1) return p1;
169 for (unsigned int k = 1; k < n; ++k) {
170 p0 = ((2 * k + 1) * x * p1 - k * p0) / (k + 1);
171 std::swap(p0, p1);
172 }
173 return p1;
174}
175
176/// Modified Bessel functions.
177/// Series expansions from Abramowitz and Stegun.
178inline double BesselI0S(const double xx) {
179 const double y = xx / 3.75;
180 const double y2 = y * y;
181 return 1. + 3.5156229 * y2 + 3.0899424 * y2 * y2 +
182 1.2067492 * pow(y2, 3) + 0.2659732 * pow(y2, 4) +
183 0.0360768 * pow(y2, 5) + 0.0045813 * pow(y2, 6);
184}
185
186inline double BesselI1S(const double xx) {
187 const double y = xx / 3.75;
188 const double y2 = y * y;
189 return xx *
190 (0.5 + 0.87890594 * y2 + 0.51498869 * y2 * y2 +
191 0.15084934 * pow(y2, 3) + 0.02658733 * pow(y2, 4) +
192 0.00301532 * pow(y2, 5) + 0.00032411 * pow(y2, 6));
193}
194
195inline double BesselK0S(const double xx) {
196 const double y = xx / 2.;
197 const double y2 = y * y;
198 return -log(y) * BesselI0S(xx) - Gamma +
199 0.42278420 * y2 + 0.23069756 * y2 * y2 +
200 0.03488590 * pow(y2, 3) + 0.00262698 * pow(y2, 4) +
201 0.00010750 * pow(y2, 5) + 0.00000740 * pow(y2, 6);
202}
203
204inline double BesselK0L(const double xx) {
205 const double y = 2. / xx;
206 return (exp(-xx) / sqrt(xx)) *
207 (1.25331414 - 0.07832358 * y + 0.02189568 * y * y -
208 0.01062446 * pow(y, 3) + 0.00587872 * pow(y, 4) -
209 0.00251540 * pow(y, 5) + 0.00053208 * pow(y, 6));
210}
211
212inline double BesselK1S(const double xx) {
213 const double y = xx / 2.;
214 const double y2 = y * y;
215 return log(y) * BesselI1S(xx) +
216 (1. / xx) *
217 (1. + 0.15443144 * y2 - 0.67278579 * y2 * y2 -
218 0.18156897 * pow(y2, 3) - 0.01919402 * pow(y2, 4) -
219 0.00110404 * pow(y2, 5) - 0.00004686 * pow(y2, 6));
220}
221
222inline double BesselK1L(const double xx) {
223 const double y = 2. / xx;
224 return (exp(-xx) / sqrt(xx)) *
225 (1.25331414 + 0.23498619 * y - 0.03655620 * y * y +
226 0.01504268 * pow(y, 3) - 0.00780353 * pow(y, 4) +
227 0.00325614 * pow(y, 5) - 0.00068245 * pow(y, 6));
228}
229
230/// C++ version of DIVDIF (CERN program library E105) which performs
231/// tabular interpolation using symmetrically placed argument points.
232double Divdif(const std::vector<double>& f, const std::vector<double>& a,
233 int nn, double x, int mm);
234
235/// Interpolation of order 1 and 2 in an irregular rectangular
236/// two-dimensional grid.
237bool Boxin2(const std::vector<std::vector<double> >& value,
238 const std::vector<double>& xAxis, const std::vector<double>& yAxis,
239 const int nx, const int ny, const double xx, const double yy,
240 double& f, const int iOrder);
241/// Interpolation of order 1 and 2 in an irregular rectangular
242/// three-dimensional grid.
243bool Boxin3(const std::vector<std::vector<std::vector<double> > >& value,
244 const std::vector<double>& xAxis, const std::vector<double>& yAxis,
245 const std::vector<double>& zAxis, const int nx, const int ny,
246 const int nz, const double xx, const double yy, const double zz,
247 double& f, const int iOrder);
248
249/// Least-squares minimisation.
250bool LeastSquaresFit(
251 std::function<double(double, const std::vector<double>&)> f,
252 std::vector<double>& par, std::vector<double>& epar,
253 const std::vector<double>& x, const std::vector<double>& y,
254 const std::vector<double>& ey, const unsigned int nMaxIter,
255 const double diff, double& chi2, const double eps,
256 const bool debug, const bool verbose);
257
258}
259}
260
261#endif
Linear algebra routines from CERNLIB.
Definition Numerics.hh:127
void dfinv(const int n, std::vector< std::vector< double > > &a, std::vector< int > &ir)
Definition Numerics.cc:855
void cfact(const int n, std::vector< std::vector< std::complex< double > > > &a, std::vector< int > &ir, int &ifail, std::complex< double > &det, int &jfail)
Definition Numerics.cc:995
int deqn(const int n, std::vector< std::vector< double > > &a, std::vector< double > &b)
Definition Numerics.cc:594
void dfact(const int n, std::vector< std::vector< double > > &a, std::vector< int > &ir, int &ifail, double &det, int &jfail)
Definition Numerics.cc:669
void cfinv(const int n, std::vector< std::vector< std::complex< double > > > &a, std::vector< int > &ir)
Definition Numerics.cc:1080
int dinv(const int n, std::vector< std::vector< double > > &a)
Replace square matrix A by its inverse.
Definition Numerics.cc:788
void dfeqn(const int n, std::vector< std::vector< double > > &a, std::vector< int > &ir, std::vector< double > &b)
Definition Numerics.cc:754
int cinv(const int n, std::vector< std::vector< std::complex< double > > > &a)
Replace square matrix A by its inverse.
Definition Numerics.cc:1135
int deqinv(const int n, std::vector< std::vector< double > > &a, std::vector< double > &b)
Replaces b by the solution x of Ax = b, and replace A by its inverse.
Definition Numerics.cc:910
void cfft(std::vector< std::complex< double > > &a, const int msign)
Definition Numerics.cc:1205
void qk15(std::function< double(double)> f, const double a, const double b, double &result, double &abserr, double &resabs, double &resasc)
15-point Gauss-Kronrod integration with finite integration range.
Definition Numerics.cc:500
void qagi(std::function< double(double)> f, double bound, const int inf, const double epsabs, const double epsrel, double &result, double &abserr, unsigned int &status)
Definition Numerics.cc:145
void qk15i(std::function< double(double)> f, double bound, const int inf, const double a, const double b, double &result, double &abserr, double &resabs, double &resasc)
Definition Numerics.cc:409
Collection of numerical routines.
Definition Numerics.hh:14
constexpr std::array< double, 4 > GaussLegendreWeights4()
Definition Numerics.hh:32
constexpr std::array< double, 2 > GaussLegendreNodes2()
Definition Numerics.hh:16
bool Boxin3(const std::vector< std::vector< std::vector< double > > > &value, const std::vector< double > &xAxis, const std::vector< double > &yAxis, const std::vector< double > &zAxis, const int nx, const int ny, const int nz, const double xx, const double yy, const double zz, double &f, const int iOrder)
Definition Numerics.cc:1545
double BesselK0L(const double xx)
Definition Numerics.hh:204
double BesselI0S(const double xx)
Definition Numerics.hh:178
double BesselI1S(const double xx)
Definition Numerics.hh:186
constexpr std::array< double, 5 > GaussLegendreWeights5()
Definition Numerics.hh:40
double Legendre(const unsigned int n, const double x)
Legendre polynomials.
Definition Numerics.hh:162
constexpr std::array< double, 6 > GaussLegendreWeights6()
Definition Numerics.hh:49
double BesselK1S(const double xx)
Definition Numerics.hh:212
bool LeastSquaresFit(std::function< double(double, const std::vector< double > &)> f, std::vector< double > &par, std::vector< double > &epar, const std::vector< double > &x, const std::vector< double > &y, const std::vector< double > &ey, const unsigned int nMaxIter, const double diff, double &chi2, const double eps, const bool debug, const bool verbose)
Least-squares minimisation.
Definition Numerics.cc:1888
constexpr std::array< double, 2 > GaussLegendreWeights2()
Definition Numerics.hh:19
bool Boxin2(const std::vector< std::vector< double > > &value, const std::vector< double > &xAxis, const std::vector< double > &yAxis, const int nx, const int ny, const double xx, const double yy, double &f, const int iOrder)
Definition Numerics.cc:1354
constexpr std::array< double, 3 > GaussLegendreNodes3()
Definition Numerics.hh:22
constexpr std::array< double, 4 > GaussLegendreNodes4()
Definition Numerics.hh:28
double Divdif(const std::vector< double > &f, const std::vector< double > &a, int nn, double x, int mm)
Definition Numerics.cc:1255
constexpr std::array< double, 5 > GaussLegendreNodes5()
Definition Numerics.hh:36
constexpr std::array< double, 3 > GaussLegendreWeights3()
Definition Numerics.hh:25
double BesselK0S(const double xx)
Definition Numerics.hh:195
double BesselK1L(const double xx)
Definition Numerics.hh:222
constexpr std::array< double, 6 > GaussLegendreNodes6()
Definition Numerics.hh:44