feat: polyharmonic spline (PHS) N-dimensional interpolation#136
feat: polyharmonic spline (PHS) N-dimensional interpolation#136twilsonco wants to merge 130 commits into
Conversation
FastInterpolations.jl BenchmarksAll benchmarks (57 total, click to expand)
This comment was automatically generated by Benchmark workflow. |
|
@twilsonco This is a fairly large change, so I’ll need some time to digest it and review it properly. I’m also in the middle of major refactoring for the next minor release, so I’ll probably finish that first, and then review and merge this separately for a following version. I likely won’t be able to review this properly over the next few days, but I’ll get back to it as soon as I can. Sorry for the delay, and thanks again for the contribution! A couple of quick notes for now:
|
|
Hi. Great project here. I'm happy to contribute.
Yes. Fortunately, all the changes are self-contained (except for the addition of PrecompileTools).
That's fine. Once you're done with the refactor, comment hear and I'll make any necessary changes to the PR.
I'll make sure it's applied.
Yes. It looks like it's the formatting that's the failing step.
Once the PR is ready again after you finish the refactor, I'll resubmit. At that point, of course you're welcome to make edits. |
Implements C2-continuous blended PHS interpolation via local RBF stencils with polynomial augmentation. Zero-allocation hot path via AdaptiveArrayPools, multithreaded batch evaluation, full first+second derivative support. New files in src/phs/: - phs_kernels.jl: radial kernel phi(r)=r^K, blend weight w(d,a) with derivs - phs_stencil.jl: stencil selection + Phi-inv precomputation (boundary-safe) - phs_types.jl: PHSInterpolantND struct + PHSLogTransform - phs_eval.jl: 3-layer evaluation engine (value/deriv1/deriv2, quotient rule) - phs_interpolant.jl: constructor + callable protocol - phs_oneshot.jl: one-shot scalar and batch forms - phs.jl: aggregator include New test file: test/test_phs_nd.jl (115 tests, all passing) Exports added: phs_interp, phs_interp!, PHSInterpolantND, PHSLogTransform
For r^K PHS the augmentation must have degree ≥ (K-1)÷2: - K=3 → linear (N+1 terms) — was already correct - K=5 → quadratic C(N+2,2) terms — was WRONG (only used N+1) - K=7 → cubic C(N+3,3) terms — was WRONG Changes: - phs_kernels.jl: add _phs_n_poly, _phs_all_exponents, @generated _phs_poly_exps_tuple, _phs_eval_poly, _phs_eval_poly_deriv1, _phs_eval_poly_deriv2 - phs_stencil.jl: _phs_build_phi_inv now computes poly_deg=(degree-1)÷2, uses _phs_all_exponents for C block; M = ns + binomial(N+poly_deg,poly_deg) - phs_eval.jl: all three _phs_eval_coeffs_* use _phs_poly_exps_tuple for correct compile-time polynomial evaluation; buffer size M taken from actual phi_inv matrix size instead of hardcoded ns+N+1 - scripts/update_readme_2d_comparison.jl: drop PeriodicBC from cubic for fairer comparison; use PHS degree=3 All 115 PHS tests pass.
Use 15x15 regular spacing so PHS (0.3% error) and cubic with PeriodicBC (0.0% error) both show near-perfect results, while constant (18%) and linear (3.5%) illustrate the progression.
…d PHS interpolation title Co-authored-by: Copilot <copilot@github.com>
…d boundary shift cache
…lations in density comparison Co-authored-by: Copilot <copilot@github.com>
…la and improve derivative calculations
This reverts commit 348e7b3.
…ConstantRef tests
…plot example - Create docs/src/interpolation/phs.md with mathematical foundation, usage, and quantum chemistry example - Link to paper (https://doi.org/10.1063/5.0090232) - Add auto-download for critic2 wavefunction files in phs_density_comparison.jl - Add scripts/dat/wfc/ to .gitignore to avoid committing large downloaded files - Remove redundant examples/promolecular_density.jl (consolidate with validation script) - Update README link to point to full PHS documentation
The ensure_wfc_files() function had an invalid 'import JSON' statement inside it, which causes a syntax error in Julia. Fixed by switching to regex-based URL parsing instead of JSON parsing. This removes the JSON.jl dependency while maintaining full functionality for downloading wavefunction files.
… to eliminate multiplications
…=3 loops to eliminate multiplications" This reverts commit 4aedaf2. Reapply "perf(phs): reuse first derivative term in second derivative K=3 loops to eliminate multiplications" This reverts commit 1c0a969ccf4f87e05cd25de4fb1979d4a1f6d4d9. Revert "Reapply "perf(phs): reuse first derivative term in second derivative K=3 loops to eliminate multiplications"" This reverts commit 181682b1d93de3bc3847085dd33e247fddcb7697.
…ssive SIMD and instruction reassociation benefits
… and simplifying wxixi math
…t, and laplacian flat profiles
…actorization of wp_dir
…recomputing ci_3r_xh
…by precomputing ci_3r_xh1
…iv2 by precomputing ci_3r_xh" This reverts commit 6451f0e.
…chmarks to run e.g. `julia --project=benchmark benchmark/ci_benchmark.jl 15` will only run benchmark group `15_phs_eval`
This reverts commit 1af8ec3.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #136 +/- ##
==========================================
+ Coverage 96.19% 96.42% +0.23%
==========================================
Files 142 148 +6
Lines 11755 13023 +1268
==========================================
+ Hits 11308 12558 +1250
- Misses 447 465 +18
🚀 New features to boost your workflow:
|
|
Note that the missing lines in test coverage CodeCov is reporting are false-positives. The PR has 100% coverage. |
Add N-Dimensional Polyharmonic Spline (PHS) Interpolation
This Pull Request introduces a high-performance, general-dimension Polyharmonic Spline (PHS) Radial Basis Function (RBF) interpolant to
FastInterpolations.jl, based on the implementation described here.Excerpt from Otero-de-la-Roza - 2022 - Finding critical points and reconstruction of electron densities on grids
PHS is particularly effective for smooth interpolation of multidimensional gridded physical data (e.g., electron densities, potential energy surfaces), especially when combined with log-density transforms and custom reference functions (physics-informed interpolation).
Key Features
N-Dimensional PHS Interpolation (
PHSInterpolantND)Float32,Float64) and value type (retaining duck-typed scalar support).Log-Density Smoothing Transform & Custom References
PHSLogTransformto interpolate smooth log-transformed functions of the formConstantRef(val)(for standard log-space interpolation) or other existing interpolants.Weighted Blending for$C^2$ Continuity
blend_factorconstructor argument.Robust Precompilation & JIT Warmup
PrecompileToolsinsidesrc/phs/phs.jlto precompile the most commonFloat64/3D patterns. This completely eliminates first-call latency (JIT compilation overhead) for standard value and derivative queries.Zero-Allocation Hot Path & Performance Optimizations
Achieving competitive evaluation speeds for stencil-based RBFs required eliminating all sources of heap allocations on the hot path. Through rigorous profiling and micro-optimizations, the query hot path is 100% allocation-free for both values and derivatives.
Key Optimizations:
shift_cache.coeff_cacheswithinPHSInterpolantNDandAdaptiveArrayPoolsfor thread workspaces), ensuring thread-safety without dynamic memory allocations under parallel batch queries.r^Kexponentiation with explicit, compiler-friendly multiplications.r_invpatterns and@simdloops in radial evaluation. Redundant divisions in blending functions were fused into a single reciprocal division followed by multiplications.@generatedfunction dispatch, allowing the compiler to fully unroll evaluation loops.Real-World Validation: Phenol Dimer (Electron Density)
To validate correctness and showcase the interpolation accuracy, we included a real-world quantum chemistry benchmark in$75 \times 113 \times 70$ grid).
scripts/phs_density_comparison.jl(phenol dimer, DFT-computed electron density on aThe benchmark compares PHS (using a log-density transform and a promolecular density reference constructed analytically from critic2 wavefunctions) against standard interpolation methods (Nearest, Linear, Cubic, Cardinal).
Accuracy Comparison (Relative Error Statistics)
1. Charge Density ($\rho$ )
2. Gradient Magnitude ($|\nabla \rho|$ )
3. Laplacian Magnitude ($|\nabla^2 \rho|$ )
Note: Relative error ratios in parentheses indicate how many times larger the error of the given method is compared to PHS.
Here's a set of plots that better captures the comparison (this plot is generated using the new script with the PR, and is included in the PHS docs):
Evaluation Timings & Allocation Verification
Evaluation times are measured for 1000 query points along a phenol-dimer hydrogen-bond path (runs executed twice to isolate JIT and stencil caches):
Extensive optimization was performed after the original implementation, reducing the runtime for this from approx.
30sdown to0.042son a M3 Ultra Mac Studio, a ~715X speedup.While PHS has a higher baseline computational cost due to localized blending and radial evaluations, it provides multiple orders of magnitude better accuracy, particularly in derivative fields (gradient & Hessian/Laplacian), with completely stable memory usage.
Codebase Modifications & Added Files
The main addition of the PHS feature-set lives in the
src/phs/directory:src/phs/phs.jl: Features aggregator and compile workload definition.src/phs/phs_kernels.jl: Core radial basis functions and their specialized first/second-order derivatives (src/phs/phs_stencil.jl: Matrix formulation, canonical stencil offset solver, and boundary shift cached variants.src/phs/phs_types.jl: Type definitions (PHSInterpolantND,PHSLogTransform,ConstantRef).src/phs/phs_eval.jl: Thread-safe coefficient evaluations, blend function kernels, and evaluation pipelines (including value, gradient, Hessian, and log-transform chain-rule solvers).src/phs/phs_interpolant.jl: Public constructorphs_interpand user-facing callable entrypoints.src/phs/phs_oneshot.jl: Non-allocating batch evaluation methods.New Documentation & Testing:
docs/src/interpolation/phs.md: Mathematical foundations, full API specifications, parameters tuning, and performance guides.test/test_phs_nd.jl: Exhaustive unit tests checking multidimensional interpolation correctness, degree scaling, log-transform safety, allocations, and type stability.scripts/phs_density_comparison.jl: Full-scale validation and timing comparison script for phenol-dimer electron density.scripts/update_readme_2d_comparison.jl: Scripts to plot multi-panel 2D validation results on regular and irregular grids.Future Improvements
As I integrate this PHS implementation into my other project (the chemistry density-analysis tool for which PHS was originally implemented), further changes, potential API polish, or performance-related improvements may be PR'd back to this repository.
Thank you for the reviews! Let me know if you would like any specific changes or further tests.