Kindfield
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Friends Pages
boysfunctionintermediate.cpp
Go to the documentation of this file.
2 
3 #include <math/boysfunction.h>
4 #include <string>
5 
6 using namespace std;
7 
13 BoysFunctionIntermediate::BoysFunctionIntermediate(int levelMax, int nValues, double limitMin, double limitMax, int nIntegralValues) :
14  m_nValues(nValues),
15  m_levelMax(levelMax),
16  m_neededLevelMax(m_levelMax + m_taylorExpansionOrder + 1),
17  m_limitMin(limitMin),
18  m_limitMax(limitMax),
19  m_nIntegralValues(nIntegralValues)
20 {
21  factorialInverseTable[0] = 1.0;
22  factorialInverseTable[1] = 1.0;
23  factorialInverseTable[2] = 0.5;
24  factorialInverseTable[3] = 0.166666666667;
25  factorialInverseTable[4] = 0.0416666666667;
26  factorialInverseTable[5] = 0.00833333333333;
27  factorialInverseTable[6] = 0.00138888888889;
28  factorialInverseTable[7] = 0.000198412698413;
29  factorialInverseTable[8] = 2.48015873016e-05;
30  factorialInverseTable[9] = 2.7557319224e-06;
31  factorialInverseTable[10] = 2.7557319224e-07;
32  factorialInverseTable[11] = 2.50521083854e-08;
33  factorialInverseTable[12] = 2.08767569879e-09;
34  factorialInverseTable[13] = 1.60590438368e-10;
35  factorialInverseTable[14] = 1.14707455977e-11;
36  factorialInverseTable[15] = 7.64716373182e-13;
37  factorialInverseTable[16] = 4.77947733239e-14;
38  factorialInverseTable[17] = 2.81145725435e-15;
39  factorialInverseTable[18] = 1.56192069686e-16;
40  factorialInverseTable[19] = 8.22063524662e-18;
41  factorialInverseTable[20] = 4.11031762331e-19;
42  factorialInverseTable[21] = 1.95729410634e-20;
43  factorialInverseTable[22] = 8.89679139245e-22;
44  factorialInverseTable[23] = 3.86817017063e-23;
45  factorialInverseTable[24] = 1.6117375711e-24;
46  factorialInverseTable[25] = 6.44695028438e-26;
47  factorialInverseTable[26] = 2.47959626322e-27;
48  factorialInverseTable[27] = 9.1836898638e-29;
49  factorialInverseTable[28] = 3.27988923707e-30;
50  factorialInverseTable[29] = 1.13099628864e-31;
51  factorialInverseTable[30] = 3.76998762882e-33;
52  factorialInverseTable[31] = 1.21612504155e-34;
53  factorialInverseTable[32] = 3.80039075485e-36;
54  factorialInverseTable[33] = 1.15163356208e-37;
55  factorialInverseTable[34] = 3.38715753552e-39;
56  factorialInverseTable[35] = 9.67759295863e-41;
57  factorialInverseTable[36] = 2.68822026629e-42;
58  factorialInverseTable[37] = 7.26546017915e-44;
59  factorialInverseTable[38] = 1.91196320504e-45;
60  factorialInverseTable[39] = 4.90246975651e-47;
61 
62  m_dx = (limitMax - limitMin) / (nValues - 1);
63  m_dxInverse = 1.0 / m_dx;
64  updateResults();
65 }
66 
68  // Try to load results from file
69  stringstream fileNameStream;
70  fileNameStream << "boys_function_data"
71 // << "_lmax_" << m_levelMax
72  << "_nx" << m_nValues
73  << "_limmin_" << m_limitMin
74  << "_limmax_" << m_limitMax
75  << "_nt" << m_nIntegralValues
76  << ".arma";
77  bool allGood = m_results.load("boys_tabulated.dat");
78  if(!allGood) {
79  cout << "BoysFunctionIntermediate::updateResults(): Boys function data file not found. Generating now." << endl;
80  }
81  if(allGood) {
82  if(m_results.n_cols < uint(m_neededLevelMax)) {
83  cout << "BoysFunctionIntermediate::updateResults(): Boys function file has " << m_results.n_cols << " cols, "
84  << "but we need " << m_neededLevelMax << endl;
85  allGood = false;
86  }
87  }
88  if(!allGood) {
89  cout << "BoysFunctionIntermediate::updateResults(): Filename: " << fileNameStream.str() << endl;
90  cout << "BoysFunctionIntermediate::updateResults(): Max level: " << m_levelMax << endl;
91  m_results = zeros(m_nValues, m_neededLevelMax); // + 6 for the Taylor expansions
92  // Could not load results from file. Generate results and write file instead.
93  for(uint i = 0; i < m_nValues; i++) {
94  double x = i * m_dx;
95  cout << "x = " << x << endl;
96  for(uint n = 0; n < uint(m_neededLevelMax); n++) {
97  m_results(i,n) = directIntegral(x, n);
98  }
99  }
100  cout << "BoysFunctionIntermediate::updateResults(): Generating results done. Writing to file " << fileNameStream.str() << endl;
101  m_results.save(fileNameStream.str());
102  }
103 }
104 
105 double BoysFunctionIntermediate::result(double arg, int n) const {
106  // Linear interpolation
107  double dx = m_dx;
108  double dxI = m_dxInverse;
109  int closestIndex = (arg - m_limitMin + dx * 0.5) * dxI; // + dx / 2.0 always gives the closest index
110  double closestArg = closestIndex * dx;
111  double difference = arg - closestArg;
112  double sumResult = m_results(closestIndex, n);
113  double powResult = 1;
114  for(int k = 1; k < m_taylorExpansionOrder + 1; k++) {
115  double F_n_k_x = m_results(closestIndex, n + k);
116  powResult *= -difference;
117  sumResult += F_n_k_x * powResult * factorialInverseTable[k];
118  }
119  return sumResult;
120 }
121 
122 double BoysFunctionIntermediate::directIntegral(double x, double n) const {
123  double t0 = 0.0;
124  double t1 = 1.0;
125  double nt = m_nIntegralValues;
126  double dt = (t1 - t0) / nt;
127  double integralResult = 0;
128  for(int i = 0; i < nt; i++) {
129  double t = t0 + dt * i;
130  integralResult += 2 * integrand(x, t + dt, n);
131  }
132  integralResult -= integrand(x, 0, n);
133  integralResult -= integrand(x, (nt - 1)*dt, n);
134  integralResult *= dt / 2.0;
135  return integralResult;
136 }
137 
138 double BoysFunctionIntermediate::fastPow(double x, int a) const {
139  double powResult = 1;
140  for(int i = 0; i < a; i++) {
141  powResult *= x;
142  }
143  return powResult;
144 }
145 
146 double BoysFunctionIntermediate::integrand(double x, double t, double n) const {
147  return exp(-x*t*t) * fastPow(t, 2*n);
148 }