Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evaluate a splined radial basis #287

Open
sirmarcel opened this issue Mar 4, 2024 · 1 comment
Open

Evaluate a splined radial basis #287

sirmarcel opened this issue Mar 4, 2024 · 1 comment
Labels
Python Issues related to the Python API

Comments

@sirmarcel
Copy link

Hello, as discussed on Slack, here's a feature request: It'd be nice to be able to evaluate a (splined) radial basis at arbitrary points for testing purposes. This would allow fine-grained testing of alternative implementations, as opposed to end-to-end testing via the SphericalExpansion calculators.

@Luthaf Luthaf added the Python Issues related to the Python API label Mar 4, 2024
@Luthaf
Copy link
Owner

Luthaf commented Mar 4, 2024

This would mainly require copying the code from here to a Python function:

// notation in this function follows
// https://en.wikipedia.org/wiki/Cubic_Hermite_spline
let mut k = match self.points.binary_search_by(
|v| v.position.partial_cmp(&x).expect("got NaN")
) {
Ok(k) => k,
Err(k) => k - 1,
};
// If we are evaluating at exactly the last spline point, use the
// previous point as a basis, and t will be 1 below.
if k == self.points.len() - 1 {
k -= 1;
}
let point_k = &self.points[k];
let point_k_1 = &self.points[k + 1];
let x_k = point_k.position;
let x_k_1 = point_k_1.position;
debug_assert!(x_k <= x && x <= x_k_1);
let delta = x_k_1 - x_k;
let t = (x - x_k) / delta;
let t_2 = t * t;
let t_3 = t_2 * t;
// Hermit base polynomials
let h00 = 2.0 * t_3 - 3.0 * t_2 + 1.0;
let h10 = t_3 - 2.0 * t_2 + t;
let h01 = -2.0 * t_3 + 3.0 * t_2;
let h11 = t_3 - t_2;
let p_k = &point_k.values;
let p_k_1 = &point_k_1.values;
let m_k = &point_k.derivatives;
let m_k_1 = &point_k_1.derivatives;
azip!((v in values, p_k in p_k, p_k_1 in p_k_1, m_k in m_k, m_k_1 in m_k_1) {
*v = h00 * p_k + h10 * delta * m_k + h01 * p_k_1 + h11 * delta * m_k_1;
});
if let Some(gradients) = gradients {
let d_h00_dt = 6.0 * (t_2 - t);
let d_h10_dt = 3.0 * t_2 - 4.0 * t + 1.0;
let d_h01_dt = -d_h00_dt;
let d_h11_dt = 3.0 * t_2 - 2.0 * t;
let dx_dt = 1.0 / delta;
azip!((g in gradients, p_k in p_k, p_k_1 in p_k_1, m_k in m_k, m_k_1 in m_k_1) {
*g = d_h00_dt * p_k * dx_dt + d_h10_dt * m_k + d_h01_dt * p_k_1 * dx_dt + d_h11_dt * m_k_1;
});
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Python Issues related to the Python API
Projects
None yet
Development

No branches or pull requests

2 participants