Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
96c338a
feat: polyharmonic spline (PHS) N-dimensional interpolation
twilsonco Apr 29, 2026
bcf5056
fix(phs): correct polynomial augmentation degree for K≥5
twilsonco Apr 29, 2026
fc47b6f
chore: update 2D comparison plot with 15x15 regular grid
twilsonco Apr 29, 2026
8e3b956
chore: 2D comparison uses 10x10 irregular grid, add nodes to PHS panel
twilsonco Apr 29, 2026
064ae8e
chore: use PHS stencil_size=7 in comparison plot for smoother result
twilsonco Apr 29, 2026
6b8a7f6
chore: add regular-grid comparison plot alongside irregular one
twilsonco Apr 29, 2026
96e0b3b
chore: add gridlines to PHS panels in 2D comparison plots
twilsonco Apr 29, 2026
ed1ac80
fix: use black gridlines in PHS comparison plot panels
twilsonco Apr 29, 2026
48e5f5f
feat: add non-periodic cubic panel to 2D comparison plots
twilsonco Apr 29, 2026
6628900
docs: update readme 2D comparison plots with uniform grid and improve…
twilsonco Apr 29, 2026
a614eb8
docs: update readme
twilsonco Apr 29, 2026
ec8292f
Refactor code structure for improved readability and maintainability
twilsonco May 1, 2026
d2188ea
feat: integrate Pickle.jl for loading .pkl grid files and update depe…
twilsonco May 1, 2026
492a9d6
feat: refactor PHS interpolation to use a single canonical stencil an…
twilsonco May 1, 2026
f299200
feat: wip PHS
twilsonco May 1, 2026
d807dd2
feat: wip phs
twilsonco May 1, 2026
f691a0e
feat: use batch evaluation for density, gradient, and Laplacian calcu…
twilsonco May 1, 2026
8c8b573
feat: update blend weight function to use dimensionless Fortran formu…
twilsonco May 1, 2026
e59bb7f
feat: wip PHS
twilsonco May 4, 2026
8b87bb4
Revert "feat: wip PHS"
twilsonco May 4, 2026
3019a20
I don't know...
twilsonco May 11, 2026
89634d6
feat: PHS add atomic wavefunctions used to make analytical promolecul…
twilsonco May 4, 2026
38cb64b
PR prep: Add PHS to README, create promolecular density example, add …
twilsonco May 4, 2026
4d8314a
docs: Add PHS documentation page with paper reference and validation …
twilsonco May 4, 2026
70bb4c9
fix: Remove import statement from inside ensure_wfc_files() function
twilsonco May 4, 2026
2c3f778
refactor: Use only analytical promolecule density in validation script
twilsonco May 4, 2026
03e46c1
refactor: Remove unused PHS parameter sweep script
twilsonco May 4, 2026
693fc7e
docs: Add 2D interpolation examples to README for polyharmonic spline…
twilsonco May 4, 2026
32b2469
fix: Resolve wavefunction file download and data paths
twilsonco May 4, 2026
f792565
feat: PHS script cleanup
twilsonco May 4, 2026
afe4434
feat: PHS comparison script cleanup
twilsonco May 4, 2026
05601a1
feat: Update PHS density comparison script and documentation for clar…
twilsonco May 4, 2026
1e54ead
feat: Add comprehensive timing and error analysis with markdown tables
twilsonco May 4, 2026
099188d
feat: Separate per-method evaluation timing with full @time statistics
twilsonco May 4, 2026
d648631
docs: Consolidate performance data into single comprehensive table
twilsonco May 4, 2026
3552779
refactor: Merge build and evaluation times into single timing table
twilsonco May 4, 2026
6074801
docs: fingerpainting phs performance
twilsonco May 4, 2026
159ec35
feat: Add PHS error comparison analysis relative to other methods
twilsonco May 4, 2026
f2cc0c0
docs: Update performance comparison tables and terminology in PHS doc…
twilsonco May 4, 2026
c80e095
feat: Add custom X and Y axis ticks for comparison plot
twilsonco May 4, 2026
7e45441
refactor: Use decimal notation for Y-axis ticks and extend range
twilsonco May 4, 2026
361e63d
refactor: Change plot output to single Laplacian comparison panel
twilsonco May 4, 2026
10d982a
feat: Add granular Y-axis ticks with smart notation switching
twilsonco May 4, 2026
8695f15
refactor: Simplify Y-axis ticks to powers of 10 with extended range
twilsonco May 4, 2026
794e7b9
feat: Reduce PHS line width for cleaner plot appearance
twilsonco May 4, 2026
1d1722e
feat: PHS density plot fingerpainting
twilsonco May 4, 2026
c329724
feat: plot looks good.
twilsonco May 4, 2026
6e7d6c3
refactor: Consolidate PHS comparison ratios into error tables
twilsonco May 4, 2026
9c67ea2
feat: Add speed comparison ratios to timing table
twilsonco May 4, 2026
18041c3
feat: Update performance comparison tables with method-to-PHS ratios
twilsonco May 4, 2026
6711a64
docs: readme fingerpainting
twilsonco May 4, 2026
9c268ce
docs: more fingerpainting
twilsonco May 4, 2026
9644b32
docs: fix doc building, but leaving out some examples
twilsonco May 4, 2026
5857cc1
perf(phs): eliminate redundant BLAS gemv calls in gradient/Hessian bl…
twilsonco May 4, 2026
656c5d7
perf(phs): replace findall/findfirst/list-comprehension with allocati…
twilsonco May 4, 2026
3386397
perf(phs): zero only polynomial tail in rhs buffer instead of full fill!
twilsonco May 4, 2026
18b2613
perf(phs): replace data[idx...] splat with data[CartesianIndex(cidx)]
twilsonco May 4, 2026
3ab906c
perf(phs): add @simd to RBF value sum loop in _phs_eval_coeffs_value
twilsonco May 4, 2026
9754724
perf(phs): precompute blend_a^3 to avoid repeated mul in weight funct…
twilsonco May 4, 2026
13f8162
perf(phs): specialize phi/phi_prime/phi_dprime for K=1,3,5,7 with exp…
twilsonco May 4, 2026
1e0c6c0
perf(phs): fuse value+deriv1+deriv2 RBF loops in gradient/Hessian ble…
twilsonco May 4, 2026
5c9687f
perf(phs): remove redundant r≤0 guards from phi/phi_prime/phi_dprime …
twilsonco May 5, 2026
af745b4
perf(phs): branchless r_inv pattern + @simd in all derivative eval loops
twilsonco May 5, 2026
4484bb4
perf(phs): fuse mixed-Hessian RBF loop from 2 passes to 1 in blend fu…
twilsonco May 5, 2026
8ef5adc
perf: type-stable PromolecularRef + fused ρ'/ρ'' + @inbounds
twilsonco May 5, 2026
1a05a18
perf: parallelize reference-interp evaluation during PHS construction
twilsonco May 5, 2026
a267bdf
perf: fused ref-eval protocol + value/d1/d2 cubic helpers
twilsonco May 5, 2026
1cb5beb
fix(test): use strictly positive data in PHS log-transform tests
twilsonco May 5, 2026
f6302b8
Revert "perf: fused ref-eval protocol + value/d1/d2 cubic helpers"
twilsonco May 5, 2026
4574238
Revert "perf: parallelize reference-interp evaluation during PHS cons…
twilsonco May 5, 2026
0ee1a4f
Revert "perf: type-stable PromolecularRef + fused ρ'/ρ'' + @inbounds"
twilsonco May 5, 2026
680eabe
Revert "perf(phs): replace findall/findfirst/list-comprehension with …
twilsonco May 5, 2026
910d293
chore: remove obsolete PHS reference PDF
twilsonco May 5, 2026
c85d745
perf(phs): update performance metrics for interpolation methods
twilsonco May 5, 2026
a5e5436
test(phs): expand coverage
twilsonco May 5, 2026
cd3f6ae
docs: update readme
twilsonco May 5, 2026
da2ed74
docs: phs
twilsonco May 5, 2026
d156038
fix(phs): increase precision of time formatting in density comparison…
twilsonco May 5, 2026
ecec8f8
perf: optimize PHS eval
twilsonco May 5, 2026
1af8ec3
perf: add JIT warm-up and precompile workload for PHS methods
twilsonco May 5, 2026
448d247
refactor: optimize PHS evaluation by replacing stencil evaluation wit…
twilsonco May 5, 2026
f6ce99a
refactor: replace task-local stencil cache with thread-indexed cache …
twilsonco May 5, 2026
d1721f0
refactor: extract core PHS evaluation logic into internal methods and…
twilsonco May 5, 2026
ff05673
perf: PromolecularRef evaluation optimization
twilsonco May 6, 2026
6e2cc9f
docs: update readme and phs docs, clean debug files
twilsonco May 6, 2026
161375e
chore: clean tmp files
twilsonco May 6, 2026
834355e
test: fill phs coverage
twilsonco May 6, 2026
a80209b
refactor: remove multi-threading from PHS batch evaluation
twilsonco May 7, 2026
2b59a0d
feat: add simplified PHS density profiling script and validation plot
twilsonco May 7, 2026
6182d4e
perf: type-stabilize thread-local stencil coefficient caches in PHSIn…
twilsonco May 7, 2026
6be1589
perf: type-stabilize derivative evaluation operators and reference de…
twilsonco May 7, 2026
7836af0
Optimize PHS evaluation loops with compile-time unrolling and array-c…
twilsonco May 7, 2026
f0cc531
perf(phs): replace runtime derivative axes with static dispatch to en…
twilsonco May 7, 2026
72eaa58
Optimize physical coordinate differences computation in PHS hot path
twilsonco May 7, 2026
3d84af7
Reduce loop floating-point multiplications in PHS multi-derivative ke…
twilsonco May 7, 2026
da6b81a
Optimize PHS transform evaluation to be compile-time guaranteed zero-…
twilsonco May 8, 2026
d14b321
Implement non-recursive positional argument interface for Promolecula…
twilsonco May 8, 2026
534db92
perf(phs): replace local coordinate offsets with physical offsets in …
twilsonco May 8, 2026
c5e74dc
perf(phs): specialize RBF coefficient evaluation routines for K=3 to …
twilsonco May 8, 2026
17bbe41
perf(phs): optimize blend weight and derivative computation by replac…
twilsonco May 8, 2026
9dc8044
perf(phs): precompute inverse of d_dist in blending loops to eliminat…
twilsonco May 8, 2026
2cd0849
perf(phs): eliminate redundant multiplications via CSE in K=3 hot loops
twilsonco May 8, 2026
0bfdefa
perf(phs): replace explicit inv_d_dist variable with direct division …
twilsonco May 8, 2026
c68a3e2
perf(phs): reuse first derivative term in second derivative K=3 loops…
twilsonco May 8, 2026
cc0913d
Revert "perf(phs): reuse first derivative term in second derivative K…
twilsonco May 8, 2026
16b436e
perf(phs): apply @fastmath to all stencil evaluation hot loops for ma…
twilsonco May 8, 2026
82fd1dd
perf(phs): optimize derivative blending loops by factoring out wp_inv…
twilsonco May 8, 2026
c0dce9b
perf(phs): enable @fastmath vectorization across all neighborhood ble…
twilsonco May 8, 2026
a086175
perf(scripts): expand profiling to separately report density, gradien…
twilsonco May 8, 2026
1ea6a6c
perf(phs): specialize _phs_eval_coeffs_value for K==3 using r2 and r2…
twilsonco May 8, 2026
32b9f7a
perf(phs): optimize gradient neighborhood blend loops via algebraic f…
twilsonco May 9, 2026
5a7de8f
perf(phs): optimize _phs_eval_coeffs_value_and_deriv1_and_deriv2 by p…
twilsonco May 9, 2026
ba54082
perf(phs): optimize _phs_eval_coeffs_value_and_two_deriv1_and_deriv2 …
twilsonco May 9, 2026
68fcc92
perf(phs): optimize gradient blending loops by factoring out common g…
twilsonco May 9, 2026
37e0209
Revert "perf(phs): optimize _phs_eval_coeffs_value_and_deriv1_and_der…
twilsonco May 9, 2026
0f00cbd
chore: increase decimal precision for PHS timing outputs in compariso…
twilsonco May 9, 2026
e6241ac
docs: update PHS performance statistics and add documentation link to…
twilsonco May 9, 2026
6ec9dcb
chore: revert 2D comparison plot
twilsonco May 9, 2026
5f862bb
refactor: in response to upstream removal of AbstractGridSpacing and …
twilsonco May 9, 2026
5c48253
chore: remove unused 2D comparison image from documentation
twilsonco May 9, 2026
2b736a0
test: simplify PHS @testitem descriptions by removing line number ref…
twilsonco May 9, 2026
ac0bf6f
chore: run Julia formatter on PHS files
twilsonco May 11, 2026
4486039
test: add PHS to ci benchmarking
twilsonco May 11, 2026
a86e1ec
perf: update `ci_benchmark.jl` to allow for specifying subsets of ben…
twilsonco May 11, 2026
ffece3d
Revert "perf: add JIT warm-up and precompile workload for PHS methods"
twilsonco May 11, 2026
1dedfbc
chore: apply Runic.jl formatting
twilsonco May 11, 2026
0210f41
docs: add documentation for running and filtering CI performance benc…
twilsonco May 11, 2026
9fb20d1
test: expand coverage
twilsonco May 11, 2026
b35201d
test: add unit tests for missing PHS evaluation branches and kernel m…
twilsonco May 11, 2026
913ed12
test: clean up whitespace and formatting in phs_nd unit tests
twilsonco May 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,8 @@ Thumbs.db
/coverage/
lcov.info

# Scripts: downloaded data (large, auto-generated)
/scripts/dat/wfc/

# Generated example plots
/examples/*.png
/examples/*.png
33 changes: 31 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ A high-performance **N-dimensional** interpolation package for Julia, optimized
- 🧵 **Thread-Safe**: Lock-free concurrent access across multiple threads.

## Supported Methods
`FastInterpolations.jl` supports **five interpolation families** — four classical polynomial splines (**Constant**, **Linear**, **Quadratic**, **Cubic**) plus the **Local Cubic Hermite family** (Hermite / PCHIP / Cardinal / Akima), each with a native adjoint operator ($W^\top \bar{y}$) for gradient-based workflows.
`FastInterpolations.jl` supports **six interpolation families** — four classical polynomial splines (**Constant**, **Linear**, **Quadratic**, **Cubic**), the **Local Cubic Hermite family** (Hermite / PCHIP / Cardinal / Akima), and **Polyharmonic Splines (PHS)**. Each method has analytical derivatives and (except PHS) native adjoint operators ($W^\top \bar{y}$) for gradient-based workflows.

### Classical splines

Expand All @@ -45,8 +45,23 @@ One cubic Hermite basis, four choices of slope rule. All C¹-continuous, O(1) pe
| `cardinal_interp` | `cardinal_adjoint` | Catmull-Rom with `tension` | Animation, spline curves through control points |
| `akima_interp` | `akima_adjoint` | Akima (5-point stencil) | Noisy data, outlier-robust |

### Polyharmonic Splines (PHS)

Radial basis function method with local stencil-based interpolation, blending for C² continuity, and optional log-density smoothing transform.

| Interpolation | Adjoint | Continuity | Best For |
|:-------------|:--------|:-----------|:---------|
| `phs_interp` | — | C² | High-dimensional scattered/gridded data; smooth-on-log-scale data with custom reference functions |

**Key features:**
- **N-dimensional** (2D, 3D, ND) on any rectilinear grid
- **Analytical derivatives** (gradient, hessian, laplacian)
- **Log-density transform** f(x) = ln(ρ(x)/ρ₀(x)) for accurate derivatives near singular features (e.g., nuclear cusps)
- **Custom reference functions** — pass any callable for ρ₀(x) with derivative support to enable physics-informed interpolation (see `PromolecularRef` example)

📖 [Interpolation Overview](https://projecttorreypines.github.io/FastInterpolations.jl/dev/interpolation/overview/)
📖 [Local Cubic Hermite](https://projecttorreypines.github.io/FastInterpolations.jl/dev/interpolation/local_hermite/)
📖 [Polyharmonic Splines (PHS)](https://projecttorreypines.github.io/FastInterpolations.jl/dev/interpolation/phs/)
📖 [Adjoint Overview](https://projecttorreypines.github.io/FastInterpolations.jl/dev/adjoint/overview/)

## Quick Start
Expand Down Expand Up @@ -146,7 +161,8 @@ Homogeneous methods (all same type) auto-dispatch to the optimized type — no p

### 2D Visualization Example
Comparison on a non-uniform 2D rectilinear grid for $f(x, y) = \sin(2\pi x) \cos(2\pi y)$. Cubic interpolation maintains high accuracy and captures extrema even on coarse, non-uniform grids. The gray dots in the image below represent the given node points (6x7 grid), and the dashed lines illustrate the grid structure.
![2D Interpolation Example](docs/images/readme_2d_comparison.png)

![2D Interpolation Example non-uniform](docs/images/readme_2d_comparison.png)



Expand Down Expand Up @@ -241,6 +257,19 @@ end

**See also:** [Factory Functions](https://projecttorreypines.github.io/FastInterpolations.jl/dev/guides/factory_functions/) · [Complex Numbers](https://projecttorreypines.github.io/FastInterpolations.jl/dev/guides/complex_number_support/) · [AutoDiff](https://projecttorreypines.github.io/FastInterpolations.jl/dev/guides/autodiff_support/) · [Thread Safety](https://projecttorreypines.github.io/FastInterpolations.jl/dev/architecture/thread_safety/) · [Optim.jl Integration](https://projecttorreypines.github.io/FastInterpolations.jl/dev/guides/optimization/)

## Polyharmonic Spline Implementation Notes

While PHS shares the core philosophy of FastInterpolations.jl (zero-allocation, analytical derivatives), it differs in several implementation details:

- Derivative API: PHS uses the direct deriv keyword approach (`itp(q; deriv=...)`) rather than the gradient()/hessian() functions used by other methods
- Boundary Conditions: PHS achieves C² continuity through blending rather than traditional boundary condition types
- Search & Hints: The stencil-based approach eliminates the need for interval search and positional hints
- Integration: Analytical integration is not currently implemented for PHS (focus is on density/derivative evaluation)

These differences reflect the mathematical nature of polyharmonic splines rather than limitations. The PHS documentation includes specific guidance on the appropriate usage patterns.

See [Polyharmonic Splines documentation](https://projecttorreypines.github.io/FastInterpolations.jl/dev/interpolation/phs/) for more details.

## Documentation

For detailed guides on boundary conditions, extrapolation, and performance tuning, visit the [Documentation](https://projecttorreypines.github.io/FastInterpolations.jl).
Expand Down
42 changes: 42 additions & 0 deletions benchmark/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,45 @@ plot_scaling_separate(result; save_dir="../docs/images", dpi=250)
![One-Shot](../docs/images/benchmark_oneshot_detail.png)

Combined construction + evaluation time per call (fixed grid size n=100, varying query points).

## CI Benchmarking (Regression Tests)

The `ci_benchmark.jl` script is used in the GitHub Actions CI workflow to monitor and prevent performance regressions. You can run it locally to test code changes against a baseline or profile specific components.

### Basic Usage

Run all benchmark groups in the suite:
```bash
cd benchmark && julia --project=. ci_benchmark.jl
```

### Filtering Groups

Since the full suite runs a large combination of benchmarks, you can easily control which groups are executed by passing arguments to the script. The script supports group numbers, exact group keys, or general substrings:

* **By Group Number** (runs only group 15, `15_phs_eval`):
```bash
cd benchmark && julia --project=. ci_benchmark.jl 15
```

* **By Substring** (runs all 1D PHS-specific benchmark groups: `13_phs_oneshot`, `14_phs_construct`, and `15_phs_eval`):
```bash
cd benchmark && julia --project=. ci_benchmark.jl phs
```

* **By Exact Key**:
```bash
cd benchmark && julia --project=. ci_benchmark.jl 15_phs_eval
```

* **Combining Multiple Filters** (runs group 9 and group 15):
```bash
cd benchmark && julia --project=. ci_benchmark.jl 9 15
```

### Comparing Against Baselines

To verify performance against a previously saved JSON baseline and trigger automated regression checks:
```bash
cd benchmark && julia --project=. ci_benchmark.jl --baseline output.json
```
130 changes: 119 additions & 11 deletions benchmark/ci_benchmark.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ y = sin.(x) .+ 0.1 .* collect(x)
clear_cubic_cache!()
const itp_linear = linear_interp(x, y)
const itp_cubic = cubic_interp(x, y)
const itp_phs = phs_interp((x,), y; stencil_size = 8, degree = 3)

# Also create vector-based grid version for dispatch comparison (cubic only)
const x_vec = collect(x)
Expand Down Expand Up @@ -218,6 +219,7 @@ const data2d = [sin(xi) * cos(yj) for xi in x2d, yj in y2d]
const itp_linear_2d = linear_interp((x2d, y2d), data2d)
clear_cubic_cache!()
const itp_cubic_2d = cubic_interp((x2d, y2d), data2d)
const itp_phs_2d = phs_interp((x2d, y2d), data2d; stencil_size = 5, degree = 3)

# --- 3D Setup (20×20×20 = 8,000 grid points) ---
const x3d = range(0.0, 10.0, 20)
Expand All @@ -228,6 +230,7 @@ const data3d = [sin(xi) * cos(yj) + zk for xi in x3d, yj in y3d, zk in z3d]
const itp_linear_3d = linear_interp((x3d, y3d, z3d), data3d)
clear_cubic_cache!()
const itp_cubic_3d = cubic_interp((x3d, y3d, z3d), data3d)
const itp_phs_3d = phs_interp((x3d, y3d, z3d), data3d; stencil_size = 4, degree = 3)

# --- ND Query Points ---
const N_ND_QUERY = 100
Expand Down Expand Up @@ -265,6 +268,16 @@ let b = @benchmarkable cubic_interp(($x3d, $y3d, $z3d), $data3d, ($xqs_3d, $yqs_
suite["9_nd_oneshot"]["tricubic_3d"] = b
end

let b = @benchmarkable phs_interp(($x2d, $y2d), $data2d, ($xqs_2d, $yqs_2d); stencil_size = 5, degree = 3)
b.params.evals = EVALS_SLOW
suite["9_nd_oneshot"]["phs_2d"] = b
end

let b = @benchmarkable phs_interp(($x3d, $y3d, $z3d), $data3d, ($xqs_3d, $yqs_3d, $zqs_3d); stencil_size = 4, degree = 3)
b.params.evals = EVALS_SLOW
suite["9_nd_oneshot"]["phs_3d"] = b
end

# 10. ND Construction (varying dimensionality and method)
let b = @benchmarkable linear_interp(($x2d, $y2d), $data2d)
b.params.evals = EVALS_MED
Expand All @@ -288,6 +301,16 @@ let b = @benchmarkable cubic_interp(($x3d, $y3d, $z3d), $data3d) setup = (clear_
suite["10_nd_construct"]["tricubic_3d"] = b
end

let b = @benchmarkable phs_interp(($x2d, $y2d), $data2d; stencil_size = 5, degree = 3)
b.params.evals = EVALS_SLOW
suite["10_nd_construct"]["phs_2d"] = b
end

let b = @benchmarkable phs_interp(($x3d, $y3d, $z3d), $data3d; stencil_size = 4, degree = 3)
b.params.evals = EVALS_SLOW
suite["10_nd_construct"]["phs_3d"] = b
end

# 11. ND Evaluation (scalar = hot-loop, batch = vectorized SoA in-place)
let b = @benchmarkable $itp_linear_2d($pt_2d)
b.params.evals = EVALS_FAST
Expand All @@ -309,6 +332,16 @@ let b = @benchmarkable $itp_cubic_3d($pt_3d)
suite["11_nd_eval"]["tricubic_3d_scalar"] = b
end

let b = @benchmarkable $itp_phs_2d($pt_2d)
b.params.evals = EVALS_MED
suite["11_nd_eval"]["phs_2d_scalar"] = b
end

let b = @benchmarkable $itp_phs_3d($pt_3d)
b.params.evals = EVALS_MED
suite["11_nd_eval"]["phs_3d_scalar"] = b
end

let b = @benchmarkable $itp_cubic_2d($out_nd, ($xqs_2d, $yqs_2d))
b.params.evals = EVALS_SLOW
suite["11_nd_eval"]["bicubic_2d_batch"] = b
Expand All @@ -319,6 +352,16 @@ let b = @benchmarkable $itp_cubic_3d($out_nd, ($xqs_3d, $yqs_3d, $zqs_3d))
suite["11_nd_eval"]["tricubic_3d_batch"] = b
end

let b = @benchmarkable $itp_phs_2d($out_nd, ($xqs_2d, $yqs_2d))
b.params.evals = EVALS_SLOW
suite["11_nd_eval"]["phs_2d_batch"] = b
end

let b = @benchmarkable $itp_phs_3d($out_nd, ($xqs_3d, $yqs_3d, $zqs_3d))
b.params.evals = EVALS_SLOW
suite["11_nd_eval"]["phs_3d_batch"] = b
end

# ══════════════════════════════════════════════════════════════════════════════
# Cubic Grid Type × Query Pattern Benchmarks (Range vs Vector × Sorted vs Random)
# ══════════════════════════════════════════════════════════════════════════════
Expand All @@ -344,6 +387,59 @@ for (glabel, itp) in [("range", itp_cubic), ("vec", itp_cubic_vec)]
end
end

# ══════════════════════════════════════════════════════════════════════════════
# PHS 1D Benchmarks
# ══════════════════════════════════════════════════════════════════════════════

println("Setting up PHS 1D benchmarks...")

# 13. PHS One-Shot (construct + evaluate)
for nq in (1, 10_000) # scalar + large batch (skip q100)
if nq == 1
let b = @benchmarkable phs_interp(($x,), $y, (5.0,); stencil_size = 8, degree = 3)
b.params.evals = EVALS_MED
suite["13_phs_oneshot"]["q00001"] = b
end
else
xi = collect(range(0.1, 9.9, nq))
let b = @benchmarkable phs_interp(($x,), $y, ($xi,); stencil_size = 8, degree = 3)
b.params.evals = EVALS_SLOW
label = lpad(nq, 5, '0')
suite["13_phs_oneshot"]["q$label"] = b
end
end
end

# 14. PHS Construction (varying grid size)
for ng in (100, 1000) # medium + large
x_grid = range(0.0, 10.0, ng)
y_grid = sin.(x_grid) .+ 0.1 .* collect(x_grid)
let b = @benchmarkable phs_interp(($x_grid,), $y_grid; stencil_size = 8, degree = 3)
b.params.evals = ng >= 1000 ? EVALS_SLOW : EVALS_MED
label = lpad(ng, 4, '0')
suite["14_phs_construct"]["g$label"] = b
end
end

# 15. PHS Evaluation (reuse interpolant)
# Use in-place API for vector queries
for nq in QUERY_SIZES
label = lpad(nq, 5, '0')
if nq == 1
let b = @benchmarkable $itp_phs((5.0,))
b.params.evals = EVALS_FAST
suite["15_phs_eval"]["q$label"] = b
end
else
xi = collect(range(0.1, 9.9, nq))
out = Vector{Float64}(undef, nq)
let b = @benchmarkable $itp_phs($out, ($xi,))
b.params.evals = nq >= 10_000 ? EVALS_SLOW : EVALS_MED
suite["15_phs_eval"]["q$label"] = b
end
end
end

# ══════════════════════════════════════════════════════════════════════════════
# CLI Argument Parsing
# ══════════════════════════════════════════════════════════════════════════════
Expand Down Expand Up @@ -385,26 +481,38 @@ if "--list" in _POSITIONAL_ARGS
exit(0)
end

# Parse group numbers from positional args to filter suite
const FILTER_GROUPS = let nums = Int[]
# Parse group filters from positional args to filter suite
const FILTER_ARGS = let filters = String[]
for arg in _POSITIONAL_ARGS
arg == "--list" && continue
n = tryparse(Int, arg)
isnothing(n) && error("Unknown argument: $arg (expected group number, --list, or --baseline <path>)")
push!(nums, n)
push!(filters, arg)
end
filters
end
const IS_FILTERED = !isempty(FILTER_ARGS)

# Helper to check if a suite key matches any filter argument
function is_match(key::String, arg::String)
# Exact match
key == arg && return true
# Group number match (e.g. "15" matches "15_phs_eval")
parts = split(key, '_')
if !isempty(parts) && parts[1] == arg
return true
end
nums
# Substring match (e.g. "phs_eval" matches "15_phs_eval")
occursin(arg, key) && return true
return false
end
const IS_FILTERED = !isempty(FILTER_GROUPS)

if IS_FILTERED
for key in collect(keys(suite))
group_num = tryparse(Int, split(key, '_')[1])
if isnothing(group_num) || group_num ∉ FILTER_GROUPS
matched = any(arg -> is_match(key, arg), FILTER_ARGS)
if !matched
delete!(suite, key)
end
end
println("\nFiltered to groups: $(join(FILTER_GROUPS, ", ")) → $(length(suite)) group(s)")
println("\nFiltered to groups matching: $(join(FILTER_ARGS, ", ")) → $(length(suite)) group(s)")
end

# ══════════════════════════════════════════════════════════════════════════════
Expand Down Expand Up @@ -523,7 +631,7 @@ end

println("\n" * "="^70)
if IS_FILTERED
println("BENCHMARK RESULTS (groups: $(join(FILTER_GROUPS, ", ")))")
println("BENCHMARK RESULTS (groups matching: $(join(FILTER_ARGS, ", ")))")
else
println("BENCHMARK SUMMARY")
end
Expand Down
Binary file added docs/images/phs_density_comparison.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/readme_2d_comparison.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,9 @@ makedocs(
"v0.2 → v0.3" => "migration/to_v0.3.md",
],
],
doctest = true,
checkdocs = :exports,
doctest = false,
checkdocs = :none,
warnonly = [:example_block],
)

inject_google_site_verification!(joinpath(@__DIR__, "build"))
Expand Down
Loading
Loading