2#include "LinAlg/Matrix.hpp"
3#include "qip/Maths.hpp"
4#include "qip/Vector.hpp"
6#include <gsl/gsl_sf_bessel.h>
9#include <gsl/gsl_errno.h>
22T
JL(
const int L,
const T x) {
25 if (std::abs(x) < 0.1) {
29 return 1.0 - 0.166666666666667 * x2 + 0.0083333333333333 * x4;
34 return 0.333333333333 * x - 0.0333333333333 * x3 + 0.001190476190 * x5;
39 return 0.06666666667 * x2 - 0.004761904762 * x4 + 0.0001322751323 * x6;
45 return 0.009523809524 * x3 - 0.0005291005291 * x5 + 0.00001202501203 * x7;
50 return 0.001058201058 * x4 - 0.00004810004810 * x6;
56 return 0.00009620009620 * x5 - 3.700003700e-6 * x7;
59 const T x6 = x2 * x2 * x2;
60 return 7.400007400e-6 * x6;
63 const T x7 = x2 * x2 * x2 * x;
64 return 4.933338267e-7 * x7;
69 return (T)gsl_sf_bessel_jl(L, (
double)x);
74T exactGSL_JL(
int L, T x) {
75 return (T)gsl_sf_bessel_jl(L, (
double)x);
82 std::vector<T> Jl_vec;
83 Jl_vec.reserve(xvec.size());
84 for (
const auto &x : xvec) {
86 Jl_vec.push_back(
JL(l, x));
92std::vector<T> fillBesselVec_kr(
const int l,
const double k,
93 const std::vector<T> &rvec) {
94 std::vector<T> Jl_vec;
95 Jl_vec.reserve(rvec.size());
96 for (
const auto &r : rvec) {
97 Jl_vec.push_back(
JL(l, k * r));
103void fillBesselVec_kr(
int l,
double k,
const std::vector<T> &r,
104 std::vector<T> *jl) {
105 jl->resize(r.size());
106#pragma omp parallel for
107 for (std::size_t i = 0; i < r.size(); ++i) {
108 (*jl)[i] =
JL(l, k * r[i]);
123 JL_table(
int max_L,
const std::vector<double> &q,
124 const std::vector<double> &r) {
129 void fill(
int max_L,
const std::vector<double> &q,
130 const std::vector<double> &r) {
132 m_J_L_q.
resize(std::size_t(max_L + 1), q.size());
133 m_J_L_q_on_qr.
resize(std::size_t(max_L + 1), q.size());
135#pragma omp parallel for collapse(2)
136 for (
auto L = 0ul; L <= std::size_t(max_L); ++L) {
137 for (
auto iq = 0ul; iq < m_J_L_q.
cols(); ++iq) {
138 const auto tq = q[iq];
140 m_J_L_q[L][iq] = fillBesselVec_kr(
int(L), tq, r);
142 m_J_L_q_on_qr[L][iq] = m_J_L_q[L][iq] / (tq * r);
149 const std::vector<double> &
at(std::size_t L, std::size_t iq)
const {
150 return m_J_L_q.
atc(L, iq);
155 const std::vector<double> &
jL(
int L,
double q)
const {
157 const auto it = std::lower_bound(m_q.begin(), m_q.end() - 1, q);
158 const auto iq = std::size_t(std::distance(m_q.begin(), it));
159 return m_J_L_q.
atc(std::size_t(L), iq);
164 const std::vector<double> &
jL_nearest(
int L,
double q)
const {
167 if (q <= m_q.front())
168 return m_J_L_q.
atc(std::size_t(L), 0);
170 return m_J_L_q.
atc(std::size_t(L), m_q.size() - 1);
173 const auto it = std::lower_bound(m_q.begin() + 1, m_q.end() - 1, q);
174 const auto i = std::size_t(std::distance(m_q.begin(), it)) - 1;
177 const auto iq = (q - m_q[i] < m_q[i + 1] - q) ? i : i + 1;
179 return m_J_L_q.
atc(std::size_t(L), iq);
187 if (q <= m_q.front())
188 return m_J_L_q_on_qr.
atc(std::size_t(L), 0);
190 return m_J_L_q_on_qr.
atc(std::size_t(L), m_q.size() - 1);
193 const auto it = std::lower_bound(m_q.begin() + 1, m_q.end() - 1, q);
194 const auto i = std::size_t(std::distance(m_q.begin(), it)) - 1;
197 const auto iq = (q - m_q[i] < m_q[i + 1] - q) ? i : i + 1;
199 return m_J_L_q_on_qr.
atc(std::size_t(L), iq);
208 if (q <= m_q.front())
209 return m_J_L_q.
atc(std::size_t(L), 0);
211 return m_J_L_q.
atc(std::size_t(L), m_q.size() - 1);
214 const auto it = std::lower_bound(m_q.begin() + 1, m_q.end() - 1, q);
215 const auto i = std::size_t(std::distance(m_q.begin(), it)) - 1;
220 const double logq = std::log10(q);
221 const double logq0 = std::log10(m_q[i]);
222 const double logq1 = std::log10(m_q[i + 1]);
223 const double t = (logq - logq0) / (logq1 - logq0);
225 const auto &v0 = m_J_L_q.
atc(std::size_t(L), i);
226 const auto &v1 = m_J_L_q.
atc(std::size_t(L), i + 1);
229 return (1.0 - t) * v0 + t * v1;
236 std::vector<double> m_q{};
Matrix class; row-major.
Definition Matrix.hpp:35
const T & atc(std::size_t row_i, std::size_t col_j) const
const ref () index access (with range checking). (i,j) ith row, jth col
Definition Matrix.hpp:139
std::size_t cols() const
Return columns [minor index size].
Definition Matrix.hpp:110
void resize(std::size_t rows, std::size_t cols)
Resizes matrix to new dimension; all values reset to default.
Definition Matrix.hpp:92
Spherical Bessel Lookup table; in the form j_L(qr) = J[L][q][r].
Definition SphericalBessel.hpp:120
const std::vector< double > & jL_nearest(int L, double q) const
Returns jL(q_i*r) for the grid point q_i nearest to the requested q.
Definition SphericalBessel.hpp:164
const std::vector< double > & at(std::size_t L, std::size_t iq) const
Direct access to jL(q*r) for specific q grid index.
Definition SphericalBessel.hpp:149
const std::vector< double > & jL_on_qr_nearest(int L, double q) const
Returns jL(q_i*r)/(q_i*r) for the grid point q_i nearest to the requested q.
Definition SphericalBessel.hpp:184
const std::vector< double > & jL(int L, double q) const
Returns jL(q_i*r) for the first grid point q_i such that q_i >= q.
Definition SphericalBessel.hpp:155
std::vector< double > jL_interp(int L, double q) const
Returns jL(q*r) interpolated linearly between grid points. nb: assumes q grid dense enough that linea...
Definition SphericalBessel.hpp:205
void fill(int max_L, const std::vector< double > &q, const std::vector< double > &r)
If derivatives required for degree L, max_L = L+1.
Definition SphericalBessel.hpp:129
Wrappers for returning Spherical Bessel functions.
Definition SphericalBessel.hpp:16
T JL(const int L, const T x)
Spherical Bessel function. For x<0.1 and K<=7, uses expansion accurate to delta~1e-15,...
Definition SphericalBessel.hpp:22
std::vector< T > fillBesselVec(const int l, const std::vector< T > &xvec)
Creates a vector of Jl(r) for given r.
Definition SphericalBessel.hpp:81
namespace qip::overloads provides operator overloads for std::vector
Definition Vector.hpp:451