Loading...
Searching...
No Matches
lagrange.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * 4-point Lagrange interpolation on a uniform grid.
5 *
6 * Provides a reusable utility for interpolating tabulated functions
7 * (beta functions, atomic charge density, core charge, Q-functions, etc.)
8 * that are stored on a uniform q-grid with spacing dq.
9 *
10 * This replaces the repeated inline interpolation pattern:
11 * px = q/dq - int(q/dq)
12 * ux = 1-px; vx = 2-px; wx = 3-px
13 * f(q) ≈ f[i0]*ux*vx*wx/6 + f[i0+1]*px*vx*wx/2 - f[i0+2]*px*ux*wx/2 + f[i0+3]*px*ux*vx/6
14 */
15
16#include <vector>
17
19
20namespace q3 {
21
22/**
23 * Interpolate a function tabulated on a uniform grid using 4-point Lagrange interpolation.
24 *
25 * @param table Tabulated function values at uniform q-grid points.
26 * @param q_value The q-point at which to interpolate.
27 * @param q_spacing The uniform grid spacing.
28 * @param table_size Number of points in the table.
29 * @return Interpolated value, or 0 if out of range.
30 */
31inline Real lagrange_interpolation_4point(const std::vector<Real>& table,
32 Real q_value,
33 Real q_spacing,
34 int table_size) {
35 Real fractional_index = q_value / q_spacing;
36 int base_index = static_cast<int>(fractional_index);
37 Real fractional_part = fractional_index - base_index;
38 if (base_index + 3 >= table_size)
39 return 0.0;
40 Real weight_1 = 1.0 - fractional_part;
41 Real weight_2 = 2.0 - fractional_part;
42 Real weight_3 = 3.0 - fractional_part;
43 return table[base_index] * weight_1 * weight_2 * weight_3 / 6.0 +
44 table[base_index + 1] * fractional_part * weight_2 * weight_3 / 2.0 -
45 table[base_index + 2] * fractional_part * weight_1 * weight_3 / 2.0 +
46 table[base_index + 3] * fractional_part * weight_1 * weight_2 / 6.0;
47}
48
49/**
50 * Compute the derivative of a 4-point Lagrange interpolant on a uniform grid.
51 *
52 * This is the analytical derivative of lagrange_interpolation_4point with respect to q_value.
53 *
54 * @param table Tabulated function values at uniform q-grid points.
55 * @param q_value The q-point at which to evaluate the derivative.
56 * @param q_spacing The uniform grid spacing.
57 * @param table_size Number of points in the table.
58 * @return Derivative value df/dq, or 0 if out of range.
59 */
60inline Real lagrange_interpolation_4point_derivative(const std::vector<Real>& table,
61 Real q_value,
62 Real q_spacing,
63 int table_size) {
64 Real fractional_index = q_value / q_spacing;
65 int base_index = static_cast<int>(fractional_index);
66 Real fractional_part = fractional_index - base_index;
67 if (base_index + 3 >= table_size)
68 return 0.0;
69 Real weight_1 = 1.0 - fractional_part;
70 Real weight_2 = 2.0 - fractional_part;
71 Real weight_3 = 3.0 - fractional_part;
72 // d/dq of the 4-point Lagrange interpolant, divided by q_spacing for chain rule
73 return (table[base_index] * (-weight_2 * weight_3 - weight_1 * weight_3 - weight_1 * weight_2) /
74 6.0 +
75 table[base_index + 1] *
76 (+weight_2 * weight_3 - fractional_part * weight_3 - fractional_part * weight_2) /
77 2.0 -
78 table[base_index + 2] *
79 (+weight_1 * weight_3 - fractional_part * weight_3 - fractional_part * weight_1) /
80 2.0 +
81 table[base_index + 3] *
82 (+weight_1 * weight_2 - fractional_part * weight_2 - fractional_part * weight_1) /
83 6.0) /
84 q_spacing;
85}
86
87} // namespace q3
double Real
Real lagrange_interpolation_4point_derivative(const std::vector< Real > &table, Real q_value, Real q_spacing, int table_size)
Definition lagrange.hpp:60
Real lagrange_interpolation_4point(const std::vector< Real > &table, Real q_value, Real q_spacing, int table_size)
Definition lagrange.hpp:31