-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSphericalBesselGenerator.cpp
267 lines (214 loc) · 5.55 KB
/
SphericalBesselGenerator.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#include <cassert>
#include "compat.h"
#ifndef NO_BESSEL_TABLE
#include <greens_functions/SphericalBesselTable.hpp>
#endif
#include "SphericalBesselGenerator.hpp"
namespace greens_functions
{
#ifndef NO_BESSEL_TABLE
static inline double hermite_interp(double x,
double x0, double dx,
double const* y_array)
#else
static inline double hermite_interp(double x,
double x0, double dx,
std::vector<double> const& y_array)
#endif
{
const double hinv = 1.0 / dx;
const size_t i = static_cast<size_t>((x - x0 ) * hinv);
const size_t index = i * 2;
const double x_lo = (x - x0) * hinv - i;
const double x_hi = 1.0 - x_lo;
const double y_lo = y_array[index];
const double ydot_lo = y_array[index + 1] * dx;
const double y_hi = y_array[index + 2];
const double ydot_hi = y_array[index + 3] * dx;
return x_hi * x_hi * (y_lo + x_lo * (2 * y_lo + ydot_lo))
+ x_lo * x_lo * (y_hi + x_hi * (2 * y_hi - ydot_hi));
}
#ifndef NO_BESSEL_TABLE
inline static Real interp(Real x_start, Real delta_x,
Real const* yTable, Real x)
#else
inline static Real interp(Real x_start, Real delta_x,
std::vector<double> const& yTable, Real x)
#endif
{
return hermite_interp(x, x_start, delta_x, yTable);
}
static Real _j(UnsignedInteger n, Real z)
{
return gsl_sf_bessel_jl(n, z);
}
static Real _y(UnsignedInteger n, Real z)
{
return gsl_sf_bessel_yl(n, z);
}
SphericalBesselGenerator const& SphericalBesselGenerator::instance()
{
static const SphericalBesselGenerator sphericalBesselGenerator;
return sphericalBesselGenerator;
}
UnsignedInteger SphericalBesselGenerator::getMinNJ()
{
return sb_table::sj_table_min;
}
UnsignedInteger SphericalBesselGenerator::getMinNY()
{
return sb_table::sy_table_min;
}
UnsignedInteger SphericalBesselGenerator::getMaxNJ()
{
return sb_table::sj_table_max;
}
UnsignedInteger SphericalBesselGenerator::getMaxNY()
{
return sb_table::sy_table_max;
}
#ifndef NO_BESSEL_TABLE
static sb_table::Table const* getSJTable(UnsignedInteger n)
{
return sb_table::sj_table[n];
}
static sb_table::Table const* getSYTable(UnsignedInteger n)
{
return sb_table::sy_table[n];
}
static inline Real _j_table(UnsignedInteger n, Real z)
{
sb_table::Table const* tablen(getSJTable(n));
return interp(tablen->x_start, tablen->delta_x, tablen->y, z);
}
static inline Real _y_table(UnsignedInteger n, Real z)
{
sb_table::Table const* tablen(getSYTable(n));
return interp(tablen->x_start, tablen->delta_x, tablen->y, z);
}
#else
sb_table::Table const* SphericalBesselGenerator::getSJTable(UnsignedInteger n) const
{
return &sj_table_[n];
}
sb_table::Table const* SphericalBesselGenerator::getSYTable(UnsignedInteger n) const
{
return &sy_table_[n];
}
Real SphericalBesselGenerator::_j_table(UnsignedInteger n, Real z) const
{
sb_table::Table const* tablen(getSJTable(n));
return interp(tablen->x_start, tablen->delta_x, tablen->y, z);
}
Real SphericalBesselGenerator::_y_table(UnsignedInteger n, Real z) const
{
sb_table::Table const* tablen(getSYTable(n));
return interp(tablen->x_start, tablen->delta_x, tablen->y, z);
}
#endif
static inline Real _j_smalln(UnsignedInteger n, Real z)
{
assert(n <= 3 && n >= 0);
if(n == 0)
{
if(z != 0)
{
return std::sin(z) / z;
}
else
{
return 1.0;
}
}
if(z == 0.0)
{
return 0.0;
}
Real sin_z;
Real cos_z;
sincos(z, &sin_z, &cos_z);
const Real z_r(1. / z);
if(n == 1)
{
return (sin_z * z_r - cos_z) * z_r;
}
else if(n == 2)
{
const Real _3_zsq(3. * z_r * z_r);
return (_3_zsq - 1) * sin_z * z_r - _3_zsq * cos_z;
}
else //if(n == 3)
{
const Real _15_zsq(15. * z_r * z_r);
return ((_15_zsq - 6.) * sin_z * z_r -
(_15_zsq - 1) * cos_z) * z_r;
}
}
static inline Real _y_smalln(UnsignedInteger n, Real z)
{
assert(n <= 2 && n >= 0);
if(n == 0)
{
return - std::cos(z) / z;
}
Real sin_z;
Real cos_z;
sincos(z, &sin_z, &cos_z);
const Real z_r(1. / z);
if(n == 1)
{
return - (cos_z * z_r + sin_z) * z_r;
}
else //if(n == 2)
{
const Real _3_zsq(3. * z_r * z_r);
return (1 - _3_zsq) * cos_z * z_r - _3_zsq * sin_z;
}
}
Real SphericalBesselGenerator::j(UnsignedInteger n, Real z) const
{
if(n <= 3)
{
return _j_smalln(n, z);
}
if(n > getMaxNJ())
{
return _j(n, z);
}
const sb_table::Table* table(getSJTable(n));
assert(table != 0);
const Real minz(table->x_start + table->delta_x * 3);
const Real maxz(table->x_start + table->delta_x * (table->N-3));
if(z >= minz && z < maxz)
{
return _j_table(n, z);
}
else
{
return _j(n, z);
}
}
Real SphericalBesselGenerator::y(const UnsignedInteger n, const Real z) const
{
if(n <= 2)
{
return _y_smalln(n, z);
}
if(n > getMaxNY())
{
return _y(n, z);
}
const sb_table::Table* table(getSYTable(n));
assert(table != 0);
const Real minz(table->x_start + table->delta_x * 3);
const Real maxz(table->x_start + table->delta_x * (table->N-3));
if(z >= minz && z < maxz)
{
return _y_table(n, z);
}
else
{
return _y(n, z);
}
}
}