Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d37c715
gneralise interpolate to allow mixed dimensions
rafaqz Oct 16, 2025
b36c2d9
cleanup
rafaqz Oct 16, 2025
ad6bdaa
simpler type, single _interpolat! method
rafaqz Oct 16, 2025
3b6aa64
bugfix
rafaqz Oct 16, 2025
2e8b635
handle empty dimensions with NoInterpolationDimension
rafaqz Oct 16, 2025
c4595d2
more fixes for mixed dimensions
rafaqz Oct 21, 2025
b384f41
more mixed dims
rafaqz Oct 21, 2025
d6d652d
cleanup
rafaqz Oct 21, 2025
87dd1ab
tweaks
rafaqz Oct 22, 2025
107dd45
working besides Constant nans
rafaqz Oct 23, 2025
9061c83
fix ConstantInterpolationDimension nans
rafaqz Oct 23, 2025
0bfe73c
remove constant
rafaqz Oct 23, 2025
42e6d68
fix eval grid checks
rafaqz Oct 23, 2025
60c36a2
simplify and minimise changes
rafaqz Oct 23, 2025
cb2864d
rename scale to weight
rafaqz Oct 24, 2025
c010f30
cleanup grid_size
rafaqz Oct 24, 2025
5a87b17
explicity multi_point_index
rafaqz Oct 24, 2025
31fe7ea
bugfix and test nointerp itp()
rafaqz Oct 31, 2025
471b1e5
cleanup
rafaqz Oct 31, 2025
09e20e2
run JuliaFormatter
rafaqz Oct 31, 2025
05f2c4c
use JuliaFormatter v2
rafaqz Oct 31, 2025
a27ae40
bugfix eval_unstructured
rafaqz Nov 4, 2025
0222ba0
review suggestions
rafaqz Nov 4, 2025
00704e4
use NURBS
rafaqz Nov 4, 2025
b37af8c
dim checks
rafaqz Nov 4, 2025
45fbe9b
bugfix constructor changes
rafaqz Nov 4, 2025
3537e53
comments and format
rafaqz Nov 4, 2025
79acff4
fix NoInterpolationDimension docstring
rafaqz Nov 4, 2025
14263fd
Merge remote-tracking branch 'upstream/main' into generalis_interpolate
SouthEndMusic Feb 15, 2026
9d87744
Fixes
SouthEndMusic Feb 15, 2026
f7e25bd
Mix interpolation types in examples
SouthEndMusic Feb 15, 2026
1d07fce
Update NDInterpolation docstring
SouthEndMusic Feb 15, 2026
a10aabf
Remove redundant comment
SouthEndMusic Feb 15, 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
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ DataInterpolationsNDSymbolicsExt = ["SymbolicUtils", "Symbolics"]

[compat]
Adapt = "4.3.0"
Aqua = "0.8"
DataInterpolations = "8"
EllipsisNotation = "1.8.0"
ForwardDiff = "0"
Expand All @@ -32,6 +33,7 @@ Test = "1"
julia = "1"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
DataInterpolations = "82cc6244-b520-54b8-b5a6-8a565e85f1d0"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Expand All @@ -42,4 +44,4 @@ Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["DataInterpolations", "ForwardDiff", "Pkg", "Random", "SafeTestsets", "Symbolics", "Test", "SymbolicUtils"]
test = ["Aqua", "DataInterpolations", "ForwardDiff", "Pkg", "Random", "SafeTestsets", "Symbolics", "Test", "SymbolicUtils"]
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ DataInterpolationsND.jl is a library for interpolating arbitrarily high dimensio

For one dimensional interpolation see also [DataInterpolations.jl](https://github.com/SciML/DataInterpolations.jl).

DataInterpolationsND.jl is similar in functionality to [Interpolations.jl](https://github.com/JuliaMath/Interpolations.jl), a well established interpolation package that is currently much more feature rich than DataInterpolationsND.jl. We hope to justify the existence of DataInterpolationsND.jl through its use of the KernelAbstractions and its planned integration with the SciML ecosystem.
DataInterpolationsND.jl is similar in functionality to [Interpolations.jl](https://github.com/JuliaMath/Interpolations.jl), a well established interpolation package that is currently much more feature rich than DataInterpolationsND.jl. We hope to justify the existence of DataInterpolationsND.jl through its use of KernelAbstractions and its planned integration with the SciML ecosystem.

## API

Expand All @@ -28,7 +28,7 @@ t2 = cumsum(rand(7))

interpolation_dimensions = (
LinearInterpolationDimension(t1),
LinearInterpolationDimension(t2)
ConstantInterpolationDimension(t2)
)

# The outputs will be vectors of length 2
Expand All @@ -51,7 +51,7 @@ If we provide `t_eval` for the interpolation dimensions, we can evaluate at thes
```julia
interpolation_dimensions = (
LinearInterpolationDimension(t1; t_eval = range(first(t1), last(t1); length = 100)),
LinearInterpolationDimension(t2; t_eval = range(first(t2), last(t2); length = 100))
ConstantInterpolationDimension(t2; t_eval = range(first(t2), last(t2); length = 100))
)

interp = NDInterpolation(u, interpolation_dimensions)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ t2 = cumsum(rand(7))

interpolation_dimensions = (
LinearInterpolationDimension(t1),
LinearInterpolationDimension(t2)
ConstantInterpolationDimension(t2)
)

# The outputs will be vectors of length 2
Expand All @@ -39,7 +39,7 @@ If we provide `t_eval` for the interpolation dimensions, we can evaluate at thes
```julia
interpolation_dimensions = (
LinearInterpolationDimension(t1; t_eval = range(first(t1), last(t1); length = 100)),
LinearInterpolationDimension(t2; t_eval = range(first(t2), last(t2); length = 100))
ConstantInterpolationDimension(t2; t_eval = range(first(t2), last(t2); length = 100))
)

interp = NDInterpolation(u, interpolation_dimensions)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Random.seed!(1)

interp_dims = (
LinearInterpolationDimension(cumsum(0.5 .+ rand(5))),
LinearInterpolationDimension(cumsum(0.5 .+ rand(10)))
ConstantInterpolationDimension(cumsum(0.5 .+ rand(10)))
)

t_eval_1 = range(
Expand Down Expand Up @@ -85,7 +85,7 @@ using LinearAlgebra

interp_dims = (
LinearInterpolationDimension(interp_dims[1].t; t_eval = t_eval_1),
LinearInterpolationDimension(interp_dims[2].t; t_eval = t_eval_2)
ConstantInterpolationDimension(interp_dims[2].t; t_eval = t_eval_2)
)
itp = NDInterpolation(u, interp_dims)

Expand Down
64 changes: 39 additions & 25 deletions src/DataInterpolationsND.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,57 @@ struct EmptyCache <: AbstractInterpolationCache end
"""
NDInterpolation(u, interp_dims; cache = EmptyCache())

The interpolation object containing the interpolation dimensions and the data to interpolate `u`.
Given the number of interpolation dimensions `N_in`, for first `N_in` dimensions of `u`
the size of `u` along that dimension must match the length of `t` of the corresponding interpolation dimension.
The interpolation object containing the interpolation dimensions and the data to be interpolated `u`.
For non-trivial interpolation dimensions (i.e. not `NoInterpolationDimension`) the length of its `t` must match
the size of `u` along the corresponding dimension.

## Arguments

- `interp_dims`: A tuple of identically typed interpolation dimensions.
- `interp_dims`: A tuple of interpolation dimensions of length `≤ ndims(u)`.
- `u`: The array to be interpolated.

## Keyword Arguments

- `cache`: Optional global cache
"""
struct NDInterpolation{
N_in, N_out,
ID <: AbstractInterpolationDimension,
N,
N_in,
N_out,
gType <: AbstractInterpolationCache,
D <: Tuple{Vararg{<:AbstractInterpolationDimension}},
uType <: AbstractArray,
}
u::uType
interp_dims::NTuple{N_in, ID}
interp_dims::D
cache::gType
function NDInterpolation(u, interp_dims, cache)
function NDInterpolation(u::AbstractArray{<:Any, N}, interp_dims, cache) where {N}
if interp_dims isa AbstractInterpolationDimension
interp_dims = (interp_dims,)
end
N_in = length(interp_dims)
N_out = ndims(u) - N_in
@assert N_out ≥ 0 "The number of dimensions of u must be at least the number of interpolation dimensions."
@assert length(interp_dims) <= N "The number of interpolation dimensions must be no more than the dimensions of u. got $(length(interp_dims)) and $N"
interp_dims = _add_trailing_no_interp_dims(interp_dims, Val{N}())
N_in = length(remove(NoInterpolationDimension, interp_dims))
N_out = length(keep(NoInterpolationDimension, interp_dims))
validate_size_u(interp_dims, u)
validate_cache(cache, interp_dims, u)
return new{N_in, N_out, eltype(interp_dims), typeof(cache), typeof(u)}(
return new{N, N_in, N_out, typeof(cache), typeof(interp_dims), typeof(u)}(
u, interp_dims, cache
)
end
end

# Constructor with optional global cache
function NDInterpolation(u, interp_dims; cache = EmptyCache())
return NDInterpolation(u, interp_dims, cache)
end

function _add_trailing_no_interp_dims(dim::AbstractInterpolationDimension, n)
return _add_trailing_interp_dims((dim,), n)
end
function _add_trailing_no_interp_dims(dims::Tuple, ::Val{N}) where {N}
return (dims..., ntuple(_ -> NoInterpolationDimension(), Val{N - length(dims)}())...)
end

@adapt_structure NDInterpolation

include("interpolation_dimensions.jl")
Expand All @@ -76,15 +85,22 @@ function (interp::NDInterpolation)(
end

# In place single input evaluation
function (interp::NDInterpolation{N_in})(
out::Union{Number, AbstractArray{<:Number}},
t::Tuple{Vararg{Number, N_in}};
derivative_orders::NTuple{N_in, <:Integer} = ntuple(_ -> 0, N_in)
) where {N_in}
validate_derivative_orders(derivative_orders, interp)
idx = get_idx(interp.interp_dims, t)
@assert size(out) == size(interp.u)[(N_in + 1):end] "The size of out must match the size of the last N_out dimensions of u."
return _interpolate!(out, interp, t, idx, derivative_orders, nothing)
function (interp::NDInterpolation{N, N_in, N_out})(
out::Union{Number, AbstractArray{<:Number, N_out}},
t::Tuple{Vararg{Any, N_in}};
derivative_orders::Tuple{Vararg{Integer, N_in}} = ntuple(_ -> 0, N_in)
) where {N, N_in, N_out}
(; interp_dims, u) = interp
# We need to add the NoInterpolationDimensions for all arguments to _interpolate.
# Currently interp() accepts only the interpolating dimensions.
# We could switch this so it needs indices for NoInterpolationDimension, but thats a breaking change.
Comment on lines +94 to +96

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vaguely remember the discussion on this. I think avoiding the breaking change would be nicest. When indexing for the NoInterpolationDimension we should support integers and slices. We could overload getindex for this, or is that too much outside the scope of that pattern/syntax?

d_o_all = insertat(NoInterpolationDimension, 0, derivative_orders, interp_dims)
validate_derivative_order(d_o_all, interp)
t_all = insertat(NoInterpolationDimension, Colon(), t, interp.interp_dims)
idx_all = get_idx(interp_dims, t_all)
@assert size(out) == keepat(NoInterpolationDimension, size(u), interp_dims) "The size of out must match the size of the NoInterpolationDimensions of u."
multi_point_index = nothing
return _interpolate!(out, interp, t_all, idx_all, d_o_all, multi_point_index)
end

# Out of place single input evaluation
Expand All @@ -94,9 +110,7 @@ function (interp::NDInterpolation)(t::Tuple{Vararg{Number}}; kwargs...)
end

export NDInterpolation, LinearInterpolationDimension, ConstantInterpolationDimension,
BSplineInterpolationDimension, NURBSWeights,
BSplineInterpolationDimension, NURBSWeights, NoInterpolationDimension,
eval_unstructured, eval_unstructured!, eval_grid, eval_grid!

include("precompilation.jl")

end # module DataInterpolationsND
19 changes: 10 additions & 9 deletions src/interpolation_dimensions.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
"""
NoInterpolationDimension()

A dimension that does not perform interpolation.
"""
struct NoInterpolationDimension <: AbstractInterpolationDimension end
Comment thread
SouthEndMusic marked this conversation as resolved.

"""
LinearInterpolationDimension(t; t_eval = similar(t, 0))

Expand Down Expand Up @@ -161,15 +168,9 @@ function BSplineInterpolationDimension(
synchronize(backend)

idx_eval = similar(t_eval, Int)
basis_function_eval = similar(
t_eval,
typeof(inv(one(eltype(t))) * inv(one(eltype(t_eval)))),
(
length(t_eval),
degree + 1,
max_derivative_order_eval + 1,
)
)
T = typeof(inv(one(eltype(t))) * inv(one(eltype(t_eval))))
s = (length(t_eval), degree + 1, max_derivative_order_eval + 1)
basis_function_eval = similar(t_eval, T, s)
itp_dim = BSplineInterpolationDimension(
t, knots_all, t_eval, idx_eval, degree, max_derivative_order_eval,
basis_function_eval, multiplicities
Expand Down
Loading
Loading