Skip to content

Generalise _interpolate! to allow mixed dimensions#33

Open
rafaqz wants to merge 33 commits into
SciML:mainfrom
rafaqz:generalis_interpolate
Open

Generalise _interpolate! to allow mixed dimensions#33
rafaqz wants to merge 33 commits into
SciML:mainfrom
rafaqz:generalis_interpolate

Conversation

@rafaqz

@rafaqz rafaqz commented Oct 16, 2025

Copy link
Copy Markdown
Collaborator

This PR is an exploration of #31 and #32 to see whats possible.

Probably quite slow in current form but this largely works already for the current tests.

The idea is to break each dimension into a preparation step, a definition of the iteration space, and then scaling and index generation functions for the inner loop, then call all of these function from the same shared _interpolate! method.

Will need to add some tests for mixed dimension types.

Closes #31 and closes #32

@rafaqz rafaqz marked this pull request as draft October 16, 2025 06:18
@rafaqz rafaqz changed the title Gneralise _interpolate! to allow mixed dimensions Generalise _interpolate! to allow mixed dimensions Oct 16, 2025
@rafaqz rafaqz marked this pull request as ready for review October 19, 2025 23:53

@SouthEndMusic SouthEndMusic left a comment

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 don't fully onderstand everything yet, but overall it looks good. I added some comments.

Comment thread src/DataInterpolationsND.jl Outdated
Comment thread src/interpolation_dimensions.jl
Comment thread src/interpolation_methods.jl Outdated
Comment thread src/interpolation_methods.jl Outdated
Comment thread src/interpolation_methods.jl Outdated
Comment thread src/interpolation_methods.jl Outdated
Comment thread src/interpolation_methods.jl Outdated
Comment thread src/interpolation_methods.jl Outdated
@rafaqz

rafaqz commented Oct 21, 2025

Copy link
Copy Markdown
Collaborator Author

FYI there is a lot left to do, the tests that pass are because there are no missing dimensions but this will break if there are any.

Comment thread src/DataInterpolationsND.jl Outdated
Comment thread src/interpolation_parallel.jl
Comment thread src/interpolation_methods.jl Outdated
@rafaqz

rafaqz commented Oct 23, 2025

Copy link
Copy Markdown
Collaborator Author

This should be working now.

@rafaqz

rafaqz commented Oct 24, 2025

Copy link
Copy Markdown
Collaborator Author

There are a few outstanding questions not - like #38 on what dimensions the weights matrix should have now.

But more importantly, what should ts in itp(ts) be ? For NoInterpolationDimension should it require an Int, Colon or AbstractArray{Int} ? To me that would be the most powerful approach, but others may disagree. The alternative would be as now with the trailing dimensions, non interpolated dims are just not included.

Currently Colons are inserted into ts internall to represent the non-interpolating dimensions. But it would be much more flexible if the colon could be an Int or AbstractArray so that _interpolate could be the core function for e.g. a DimensionalData.jl wrapper that allowed arbitrary mixed indexing.

Please chime in here this should be finalised and tested in this PR.

Comment thread src/DataInterpolationsND.jl Outdated
Comment thread src/DataInterpolationsND.jl Outdated
Comment thread src/interpolation_utils.jl Outdated
Comment thread src/interpolation_methods.jl Outdated
for (t₁, t₂) in zip(tᵢ, tᵢ₊₁)
t_vol *= t₂ - t₁
out, valid_derivative_orders = check_derivative_order(interp_dims, derivative_orders, ts, out)
valid_derivative_orders || return out

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.

It should be more clear that !valid_derivative_orders does not mean that the input is invalid but that it is certain that the output is 0.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

What do you suggest

Comment thread src/interpolation_methods.jl Outdated
out::Union{Number, AbstractArray{<:Any, N_out}},
A::NDInterpolation{N, N_in, N_out},
ts::Tuple{Vararg{Any, N}},
idx::Tuple{Vararg{Any ,N}},

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.

Why allow the index to be any type?

@rafaqz rafaqz Oct 31, 2025

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It can be Colon() etc for NoInterpolationDimension.

Although this could all be cleaned up a bit.

Comment thread src/interpolation_methods.jl Outdated
Comment thread src/interpolation_methods.jl Outdated
Comment thread src/interpolation_methods.jl Outdated
Comment thread src/interpolation_utils.jl
@SouthEndMusic

SouthEndMusic commented Oct 29, 2025

Copy link
Copy Markdown
Member

But more importantly, what should ts in itp(ts) be ? For NoInterpolationDimension should it require an Int, Colon or AbstractArray{Int} ? To me that would be the most powerful approach, but others may disagree. The alternative would be as now with the trailing dimensions, non interpolated dims are just not included.

Why not support multiple approaches? Have one method which calls _interpolate! with arguments that are most convenient for the internals, and several wrapper methods that convert other input formats to the internal one. We can dispatch on the number of arguments matching to N and N_in (The ambiguity for N = N_in can probably easily be dealt with), and a fallback method which gives an error that it doesn't match either.

@rafaqz

rafaqz commented Oct 29, 2025

Copy link
Copy Markdown
Collaborator Author

Maybe, I was leaning to choosing one or the other because mixed tuple lengths both accepted in the same function may invite some user error and confusion.

@SouthEndMusic

Copy link
Copy Markdown
Member

I am still in favor of supporting multiple options if reasonably possible. We could make the difference more explicit by using different functions or pass an optional Boolean flag. Then we still have to decide what the default behavior is. From a mathematical perspective I would prefer the current approach on main, but if passing some trivial object for the non-interpolated dimensions makes more sense from a code perspective, that's fine too.

@rafaqz

rafaqz commented Oct 31, 2025

Copy link
Copy Markdown
Collaborator Author

A bool keyword on a tuple length isn't necessarily type stable unless it reliably constant props, and I would prefer simplicity over options, so making a choice either way seems better to me.

Given this difference of perspective its probably better discussed in a new PR and not hold up this one, so I kept the behavior as it was on main.

@rafaqz

rafaqz commented Nov 5, 2025

Copy link
Copy Markdown
Collaborator Author

This seems good to go to me. I don't think its even a breaking change? I have some performance improvements too but will PR those when this lands.

(Please use squash if/when this is merged, there are a lot of small commits not intended for the history)

@SouthEndMusic

Copy link
Copy Markdown
Member

@rafaqz sorry for the long time until my response. Do you still want to merge this? It looks like some conflicts have accumulated.

SouthEndMusic
SouthEndMusic previously approved these changes Feb 14, 2026

@SouthEndMusic SouthEndMusic left a comment

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 left a few small comments, and there are some TODO's left. It looks like you know what you are doing. Please go over the docstrings and the README/documentation before merging.

## Arguments

- `interp_dims`: A tuple of identically typed interpolation dimensions.
- `u`: The array to be interpolated.

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.

The NDinterpolation docstring needs an update

Comment on lines +88 to +90
# 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.

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?

Comment thread src/interpolation_methods.jl Outdated
stencil(::NoInterpolationDimension) = 1
stencil(d::BSplineInterpolationDimension) = 1:(d.degree + 1)

# Precalculate coefficient/s

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.

Suggested change
# Precalculate coefficient/s
# Precalculate coefficients

t::Tuple{Vararg{Number, N_in}},
idx::NTuple{N_in, <:Integer},
derivative_orders::NTuple{N_in, <:Integer},
Base.@propagate_inbounds function _interpolate!(

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 feel like this main function belongs either in a separate file or in DataInterpolationsND.jl

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Intentions for mixed mode dimensions Add explicit NonInterpolatedDimension ?

2 participants