74template <
typename T,
typename U =
double>
85 int solve(T* dl, T* d, T* du, T* b,
int n)
87 for (
int i = 0; i < n - 1; i++) {
88 if (std::abs(dl[i]) == 0) {
89 if (std::abs(d[i]) == 0) {
92 }
else if (std::abs(d[i]) >= std::abs(dl[i])) {
93 T mult = dl[i] / d[i];
94 d[i + 1] -= mult *
du[i];
95 b[i + 1] -= mult * b[i];
100 T mult = d[i] / dl[i];
103 d[i + 1] =
du[i] - mult * tmp;
106 du[i + 1] = -mult * dl[i];
111 b[i + 1] = tmp - mult * b[i + 1];
114 if (std::abs(d[n - 1]) == 0) {
117 b[n - 1] /= d[n - 1];
119 b[n - 2] = (b[n - 2] -
du[n - 2] * b[n - 1]) / d[n - 2];
121 for (
int i = n - 3; i >= 0; i--) {
122 b[i] = (b[i] -
du[i] * b[i + 1] - dl[i] * b[i + 2]) / d[i];
152 for (
int i = 0; i < this->
num_points(); i++) {
161 assert(
static_cast<int>(y__.size()) <= this->num_points());
177 for (
int ir = 0; ir < this->
num_points(); ir++) {
178 coeffs_(ir, 0) = f__(this->x(ir));
183 Spline<T, U>& operator=(std::vector<T>
const& y__)
185 assert(
static_cast<int>(y__.size()) <= this->num_points());
218 int j = this->index_of(x);
221 s <<
"spline::at_point() index of point is not found\n"
222 <<
" x : " << x <<
"\n"
223 <<
" first point : " << this->
first() <<
"\n"
224 <<
" last point : " << this->
last();
225 throw std::runtime_error(s.str());
227 U
dx = x - (*this)[j];
228 return (*
this)(j, dx);
231 inline T deriv(
const int dm,
const int i,
const U dx)
const
256 throw std::runtime_error(
"wrong order of derivative");
263 inline T deriv(
int dm,
int i)
const
269 return deriv(dm, i - 1, this->dx(i - 1));
271 return deriv(dm, i, 0);
282 T* dl =
coeffs_.at(sddk::memory_t::host, 0, 1);
284 T* d =
coeffs_.at(sddk::memory_t::host, 0, 2);
286 T*
du =
coeffs_.at(sddk::memory_t::host, 0, 3);
288 std::vector<T> m(ns);
290 std::vector<T> dy(ns - 1);
291 for (
int i = 0; i < ns - 1; i++) {
295 for (
int i = 0; i < ns - 2; i++) {
296 m[i + 1] = (dy[i + 1] - dy[i]) * 6.0;
300 m[ns - 1] = m[ns - 2];
303 for (
int i = 0; i < ns - 2; i++) {
304 d[i + 1] =
static_cast<T
>(this->
x(i + 2) - this->
x(i)) * 2.0;
307 for (
int i = 0; i < ns - 1; i++) {
315 d[0] = h0 - (h1 / h0) * h1;
316 du[0] = h1 * ((h1 / h0) + 1) + 2 * (h0 + h1);
318 h0 = this->dx(ns - 2);
319 h1 = this->dx(ns - 3);
320 d[ns - 1] = h0 - (h1 / h0) * h1;
321 dl[ns - 2] = h1 * ((h1 / h0) + 1) + 2 * (h0 + h1);
331 int info =
solve(dl, d,
du, &m[0], ns);
335 s <<
"[sirius::Spline::interpolate] error in tridiagonal solver: " << info;
336 throw std::runtime_error(s.str());
339 for (
int i = 0; i < ns - 1; i++) {
343 T t = (m[i + 1] - m[i]) / 6.0;
347 coeffs_(i, 3) = t / this->dx(i);
430 for (
int i = 0; i < this->
num_points() - 1; i++) {
437 for (
int i = 0; i < this->
num_points() - 1; i++) {
445 T val = dx * (dx * (dx * (dx * (dx * (dx * a3 / 6.0 + (a2 + 2.0 * a3 * x0) / 5.0) +
446 (a1 + x0 * (2.0 * a2 + a3 * x0)) / 4.0) + (a0 + x0 * (2.0 * a1 + a2 * x0)) / 3.0) +
447 x0 * (2.0 * a0 + a1 * x0) / 2.0) + a0 * x0 * x0);
449 g__[i + 1] = g__[i] + val;
454 for (
int i = 0; i < this->
num_points() - 1; i++) {
456 U x1 = this->
x(i + 1);
466 g__[i + 1] = g__[i] + (dx / 6.0) * (6.0 * a1 + x0 * (-9.0 * a2 + 11.0 * a3 * x0) + x1 * (3.0 * a2 - 7.0 * a3 * x0 + 2.0 * a3 * x1)) +
467 (-a0 + x0 * (a1 + x0 * (-a2 + a3 * x0))) * std::log(x0 / x1);
472 for (
int i = 0; i < this->
num_points() - 1; i++) {
474 U x1 = this->
x(i + 1);
490 (a2 * dx - 5.0 * a3 * x0 * dx / 2.0 - a1 * (dx / x1) + a0 * (dx / x0 / x1) + (x0 / x1) * dx * (a2 - a3 * x0) + a3 * x1 * dx / 2.0) +
491 (a1 + x0 * (-2.0 * a2 + 3.0 * a3 * x0)) * std::log(x1 / x0);
496 for (
int i = 0; i < this->
num_points() - 1; i++) {
498 U x1 = this->
x(i + 1);
516 x0 * (a1 * dx + x0 * (a2 * x0 - a3 * std::pow(x0, 2) - 3.0 * a2 * x1 + 5.0 * a3 * x0 * x1 + 2.0 * a3 * std::pow(x1, 2)))) /
517 std::pow(x0 * x1, 2) / 2.0 +
518 (-a2 + 3.0 * a3 * x0) * std::log(x0 / x1);
523 for (
int i = 0; i < this->
num_points() - 1; i++) {
525 U x1 = this->
x(i + 1);
540 g__[i + 1] = g__[i] +
541 (2.0 * a0 * (-std::pow(x0, 3) + std::pow(x1, 3)) -
543 (-a1 * dx * (2.0 * x0 + x1) +
544 x0 * (-2.0 * a2 * std::pow(dx, 2) + a3 * x0 * (2.0 * std::pow(x0, 2) - 7.0 * x0 * x1 + 11.0 * std::pow(x1, 2))))) /
545 std::pow(x0 * x1, 3) / 6.0 +
546 a3 * std::log(x1 / x0);
551 for (
int i = 0; i < this->
num_points() - 1; i++) {
553 U x1 = this->
x(i + 1);
564 (std::pow(x0, 1 + m__) * (-(a0 * double((2 + m__) * (3 + m__) * (4 + m__))) +
565 x0 * (a1 *
double((3 + m__) * (4 + m__)) - 2.0 * a2 * double(4 + m__) * x0 + 6.0 * a3 * std::pow(x0, 2)))) /
566 double((1 + m__) * (2 + m__) * (3 + m__) * (4 + m__)) +
567 std::pow(x1, 1 + m__) *
568 ((a0 - x0 * (a1 + x0 * (-a2 + a3 * x0))) /
double(1 + m__) + ((a1 + x0 * (-2.0 * a2 + 3.0 * a3 * x0)) * x1) /
double(2 + m__) +
569 ((a2 - 3.0 * a3 * x0) * std::pow(x1, 2)) /
double(3 + m__) + (a3 * std::pow(x1, 3)) /
double(4 + m__));
585 inline void scale(
double a__)
587 for (
int i = 0; i < this->
num_points(); i++) {
595 inline std::array<T, 4> coeffs(
int i__)
const
600 inline sddk::mdarray<T, 2>
const& coeffs()
const
612 std::vector<T> values()
const
615 for (
int ir = 0; ir < this->
num_points(); ir++) {
622template <
typename T,
typename U =
double>
623inline Spline<T, U>
operator*(Spline<T, U>
const& a__, Spline<T, U>
const& b__)
625 Spline<T> s12(
reinterpret_cast<Radial_grid<U> const&
>(a__));
627 auto& coeffs_a = a__.coeffs();
628 auto& coeffs_b = b__.coeffs();
629 auto& coeffs =
const_cast<sddk::mdarray<T, 2>&
>(s12.coeffs());
631 for (
int ir = 0; ir < a__.num_points(); ir++) {
632 coeffs(ir, 0) = coeffs_a(ir, 0) * coeffs_b(ir, 0);
633 coeffs(ir, 1) = coeffs_a(ir, 1) * coeffs_b(ir, 0) + coeffs_a(ir, 0) * coeffs_b(ir, 1);
634 coeffs(ir, 2) = coeffs_a(ir, 2) * coeffs_b(ir, 0) + coeffs_a(ir, 1) * coeffs_b(ir, 1) + coeffs_a(ir, 0) * coeffs_b(ir, 2);
636 coeffs_a(ir, 3) * coeffs_b(ir, 0) + coeffs_a(ir, 2) * coeffs_b(ir, 1) + coeffs_a(ir, 1) * coeffs_b(ir, 2) + coeffs_a(ir, 0) * coeffs_b(ir, 3);
652extern "C" void spline_inner_product_gpu_v3(
int const* idx_ri__,
int num_ri__,
int num_points__,
double const* x__,
double const* dx__,
double const* f__,
653 double const* g__,
double* result__);
657T
inner(Spline<T>
const& f__, Spline<T>
const& g__,
int m__,
int num_points__)
663 for (
int i = 0; i < num_points__ - 1; i++) {
664 double dx = f__.dx(i);
666 auto f = f__.coeffs(i);
667 auto g = g__.coeffs(i);
669 T faga = f[0] * g[0];
670 T fdgd = f[3] * g[3];
672 T k1 = f[0] * g[1] + f[1] * g[0];
673 T k2 = f[2] * g[0] + f[1] * g[1] + f[0] * g[2];
674 T k3 = f[0] * g[3] + f[1] * g[2] + f[2] * g[1] + f[3] * g[0];
675 T k4 = f[1] * g[3] + f[2] * g[2] + f[3] * g[1];
676 T k5 = f[2] * g[3] + f[3] * g[2];
678 result += dx * (faga + dx * (k1 / 2.0 + dx * (k2 / 3.0 + dx * (k3 / 4.0 + dx * (k4 / 5.0 + dx * (k5 / 6.0 + dx * fdgd / 7.0))))));
683 for (
int i = 0; i < num_points__ - 1; i++) {
685 double dx = f__.dx(i);
687 auto f = f__.coeffs(i);
688 auto g = g__.coeffs(i);
690 T faga = f[0] * g[0];
691 T fdgd = f[3] * g[3];
693 T k1 = f[0] * g[1] + f[1] * g[0];
694 T k2 = f[2] * g[0] + f[1] * g[1] + f[0] * g[2];
695 T k3 = f[0] * g[3] + f[1] * g[2] + f[2] * g[1] + f[3] * g[0];
696 T k4 = f[1] * g[3] + f[2] * g[2] + f[3] * g[1];
697 T k5 = f[2] * g[3] + f[3] * g[2];
701 dx * ((faga + k1 * x0) / 2.0 +
702 dx * ((k1 + k2 * x0) / 3.0 +
703 dx * ((k2 + k3 * x0) / 4.0 +
704 dx * ((k3 + k4 * x0) / 5.0 + dx * ((k4 + k5 * x0) / 6.0 + dx * ((k5 + fdgd * x0) / 7.0 + dx * fdgd / 8.0)))))));
709 for (
int i = 0; i < num_points__ - 1; i++) {
711 double dx = f__.dx(i);
713 auto f = f__.coeffs(i);
714 auto g = g__.coeffs(i);
717 T k1 = f[3] * g[1] + f[2] * g[2] + f[1] * g[3];
718 T k2 = f[3] * g[0] + f[2] * g[1] + f[1] * g[2] + f[0] * g[3];
719 T k3 = f[2] * g[0] + f[1] * g[1] + f[0] * g[2];
720 T k4 = f[3] * g[2] + f[2] * g[3];
721 T k5 = f[1] * g[0] + f[0] * g[1];
724 T r1 = k4 * 0.125 + k6 * x0 * 0.25;
725 T r2 = (k1 + x0 * (2.0 * k4 + k6 * x0)) * 0.14285714285714285714;
726 T r3 = (k2 + x0 * (2.0 * k1 + k4 * x0)) * 0.16666666666666666667;
727 T r4 = (k3 + x0 * (2.0 * k2 + k1 * x0)) * 0.2;
728 T r5 = (k5 + x0 * (2.0 * k3 + k2 * x0)) * 0.25;
729 T r6 = (k0 + x0 * (2.0 * k5 + k3 * x0)) * 0.33333333333333333333;
730 T r7 = (x0 * (2.0 * k0 + x0 * k5)) * 0.5;
732 T v = dx * k6 * 0.11111111111111111111;
741 result += dx * (k0 * x0 * x0 + v);
779 throw std::runtime_error(
"wrong r^m prefactor");
786T
inner(Spline<T>
const& f__, Spline<T>
const& g__,
int m__)
788 return inner(f__, g__, m__, f__.num_points());
Base class for radial grids.
double last() const
Last point of the grid.
sddk::mdarray< double, 1 > x_
Radial grid points.
double dx(const int i) const
Return .
double first() const
First point of the grid.
void init()
Initialize the grid.
T x(const int i) const
Return .
int num_points() const
Number of grid points.
Cubic spline with a not-a-knot boundary conditions.
Spline(Radial_grid< U > const &radial_grid__)
Constructor of a new empty spline.
Spline(Radial_grid< U > const &radial_grid__, std::vector< T > const &y__)
Constructor of a spline from a list of values.
T operator()(const int i, U dx) const
Get value at the point x[i] + dx.
T integrate(std::vector< T > &g__, int m__) const
Integrate spline with r^m prefactor.
Spline()
Default constructor.
sddk::mdarray< T, 2 > coeffs_
Array of spline coefficients.
int solve(T *dl, T *d, T *du, T *b, int n)
Solver tridiagonal system of linear equaitons.
T & operator()(const int i)
Get the reference to a value at the point x[i].
T const & operator()(const int i) const
Get value at the point x[i].
Spline< T, U > & interpolate()
void init_grid(Radial_grid< U > const &radial_grid__)
Init the underlying radial grid.
Spline(Radial_grid< U > const &radial_grid__, std::function< T(U)> f__)
Constructor of a spline from a function.
T at_point(U x) const
Compute value at any point.
T integrate(int m__) const
Integrate spline with r^m prefactor.
void zero(memory_t mem__, size_t idx0__, size_t n__)
Zero n elements starting from idx0.
void copy(T *target__, T const *source__, size_t n__)
Copy memory inside a device.
std::enable_if_t< std::is_same< T, real_type< F > >::value, void > inner(::spla::Context &spla_ctx__, sddk::memory_t mem__, spin_range spins__, W const &wf_i__, band_range br_i__, Wave_functions< T > const &wf_j__, band_range br_j__, la::dmatrix< F > &result__, int irow0__, int jcol0__)
Compute inner product between the two sets of wave-functions.
Namespace of the SIRIUS library.
auto operator*(Spheric_function< function_domain_t::spatial, T > const &a__, Spheric_function< function_domain_t::spatial, T > const &b__)
Multiplication of two functions in spatial domain.
Contains declaraion and partial implementation of sirius::Radial_grid class.