# Interpolate 2d function

**URL:** <https://discourse.julialang.org/t/interpolate-2d-function/96914>\
**Category:** Numerics\
**Tags:** question, interpolations, bsplinekit\
**Created:** [March 31, 2023, 8:26pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914 "2023-03-31T20:26:13Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [March 31, 2023, 8:26pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/1 "2023-03-31T20:26:13Z")

</div>

I want to interpolate 2d data. I have a function f(x, y) that is sampled as follows. For any y value in some array `y_arr`, I have the a set of points `x_arr`. Note that `x_arr` is different for any y, and even the boundaries of the x values are not the same.

I would like to perform interpolation of this 2d function.

For 1d interpolations, I am using `BSplineKit`, but from its documentation, I could not understand if it is possible to use it for 2d.

Would love to get any suggestions!

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [March 31, 2023, 9:32pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/2 "2023-03-31T21:32:31Z")

</div>

The README in Dierckx package seems to promise 2D interpolation on an irregular grid:  
[https://github.com/kbarbary/Dierckx.jl](https://github.com/kbarbary/Dierckx.jl)

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [March 31, 2023, 9:46pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/3 "2023-03-31T21:46:10Z")

</div>

True. Though I am having problems with this package.

Also, recently I saw that it is not actively maintained, so, therefore, I am looking for another solution.

---

<div class="post-metadata">

**Author:** ![JM\_Beckers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jm_beckers/32/22482_2.png) [@JM\_Beckers](https://discourse.julialang.org/u/JM_Beckers)\
**Post date:** [April 1, 2023, 3:39am UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/4 "2023-04-01T03:39:47Z")

</div>

You might try

> **[GitHub - gher-uliege/DIVAnd.jl: DIVAnd performs an n-dimensional variational...](https://github.com/gher-uliege/DIVAnd.jl)**
>
> DIVAnd performs an n-dimensional variational analysis of arbitrarily located observations - GitHub - gher-uliege/DIVAnd.jl: DIVAnd performs an n-dimensional variational analysis of arbitrarily loca...

in particular if you know beforehand the shape of the domain where you want to interpolate and which does not need to be a rectangle.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [April 1, 2023, 5:19am UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/5 "2023-04-01T05:19:10Z")

</div>

While Dierckx isn’t actively maintained, the existing features should work correctly, including 2D interpolation. New features may be slow to get added, that’s what the maintenance comment might have been about.

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [April 1, 2023, 2:46pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/6 "2023-04-01T14:46:41Z")

</div>

Thanks.

I tried to use Dierckx and I get this error:

```julia
No more knots can be added because the additional knot would
(quasi) coincide with an old one: s too small or too large a weight to
an inaccurate data point. The weighted least-squares spline
corresponds to the current set of knots.

```

I tried to play with `s`, and it did not help. Not sure what the problem is here.  
I am fine also with the simplest linear interpolation between points.

---

<div class="post-metadata">

**Author:** ![jipolanco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jipolanco/32/12129_2.png) [@jipolanco](https://discourse.julialang.org/u/jipolanco)\
**Post date:** [April 1, 2023, 2:49pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/7 "2023-04-01T14:49:39Z")

</div>

> [@roi.holtzman](#):
>
> For 1d interpolations, I am using `BSplineKit`, but from its documentation, I could not understand if it is possible to use it for 2d.

Multidimensional interpolations, using tensor product B-splines, have been in the plans for BSplineKit.jl for a while. There’s even a slighly outdated [open PR](https://github.com/jipolanco/BSplineKit.jl/pull/41) with a possible implementation, but I’m not very happy with the proposed interface and I haven’t had the time to do something better.

If it helps, here it’s a bit of code for manually doing 2D interpolations with BSplineKit.jl:

```julia
using BSplineKit
using LinearAlgebra

# Target function
f(x, y) = 2.0 + sinpi(x) * cospi(y)

xs = 0:0.1:1
ys = 0:0.1:2
fdata = f.(xs, ys')

ord = BSplineOrder(4) # cubic splines

# Create B-spline knots based on interpolation points (uses an internal function)
ts_x = SplineInterpolations.make_knots(xs, ord, nothing)
ts_y = SplineInterpolations.make_knots(ys, ord, nothing)

# Create B-spline bases
Bx = BSplineBasis(ord, ts_x; augment = Val(false))
By = BSplineBasis(ord, ts_y; augment = Val(false))

# Create and factorise interpolation matrices
Cx = lu!(collocation_matrix(Bx, xs))
Cy = lu!(collocation_matrix(By, ys))

# 2D B-spline coefficients (output)
coefs = similar(fdata)

# Solve linear systems
for j ∈ eachindex(ys)
    @views ldiv!(coefs[:, j], Cx, fdata[:, j])
end
for i ∈ eachindex(xs)
    @views ldiv!(Cy, coefs[i, :])
end

# Evaluate 2D (tensor product) spline at point (x, y).
function eval_spline2D(coefs::AbstractMatrix, (Bx, By), (x, y))
    i, bx = Bx(x) # evaluate B-spline basis at point x
    j, by = By(y)
    kx = order(Bx)
    ky = order(By)
    val = zero(eltype(coefs)) # spline evaluated at (x, y)
    for δj ∈ 1:ky, δi ∈ 1:kx
        coef = coefs[i - δi + 1, j - δj + 1]
        bi = bx[δi]
        bj = by[δj]
        val += coef * bi * bj
    end
    val
end

# Verification: evaluate 2D spline at data points
for m ∈ eachindex(ys), n ∈ eachindex(xs)
    x = xs[n]
    y = ys[m]
    val = eval_spline2D(coefs, (Bx, By), (x, y))
    fval = fdata[n, m]
    @assert val ≈ fval # check that the value is correct
end

```

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [April 1, 2023, 3:03pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/8 "2023-04-01T15:03:38Z")

</div>

Thanks @jipolanco !

This code seems like it is designed for an even grid, isn’t it?  
I have a large set of `x` and `y`, and the values `z(x,y)`. So this is an irregular grid. Is there a way to perform the 2d interpolation with the code you attached?

---

<div class="post-metadata">

**Author:** ![jipolanco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jipolanco/32/12129_2.png) [@jipolanco](https://discourse.julialang.org/u/jipolanco)\
**Post date:** [April 1, 2023, 3:04pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/9 "2023-04-01T15:04:58Z")

</div>

The example uses a regular grid, but it should work without a problem on irregular ones. (Just define `xs` and `ys` as vectors with sorted irregular values.)

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [April 1, 2023, 3:08pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/10 "2023-04-01T15:08:07Z")

</div>

> [@jipolanco](#):
>
> (Just define `xs` and `ys` as vectors with sorted irregular values.)

But how can it be sorted? I essentially have a set (x\_i, y\_i) and the values z\_i = z(x\_i, y\_i).

---

<div class="post-metadata">

**Author:** ![jipolanco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jipolanco/32/12129_2.png) [@jipolanco](https://discourse.julialang.org/u/jipolanco)\
**Post date:** [April 1, 2023, 3:16pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/11 "2023-04-01T15:16:06Z")

</div>

Maybe I misunderstood your initial post. If you have a curvilinear grid (your x\_i coordinates vary with y), then I’m not sure I can help…

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [April 1, 2023, 3:31pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/12 "2023-04-01T15:31:49Z")

</div>

Linking also [this other thread](https://discourse.julialang.org/t/plot-3d-data-in-a-2d-contour-plot/71251), which contains examples of GMT.jl and DIVAnd.jl solutions.

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [April 1, 2023, 3:47pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/13 "2023-04-01T15:47:29Z")

</div>

Thanks! I will try those!

---

<div class="post-metadata">

**Author:** ![PeterSimon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petersimon/32/25193_2.png) [@PeterSimon](https://discourse.julialang.org/u/PeterSimon)\
**Post date:** [April 1, 2023, 5:17pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/14 "2023-04-01T17:17:10Z")

</div>

Also, you should check out [ScatteredInterpolation.jl](https://github.com/eljungsk/ScatteredInterpolation.jl) which seems to be exactly what you’re looking for.

---

<div class="post-metadata">

**Author:** ![Sagar\_123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sagar_123/32/42788_2.png) [@Sagar\_123](https://discourse.julialang.org/u/Sagar_123)\
**Post date:** [March 4, 2025, 4:29pm UTC](https://discourse.julialang.org/t/interpolate-2d-function/96914/15 "2025-03-04T16:29:32Z")

</div>

If I were to approximate (say using least squares) a 2D function using BSpline basis defined on a poloidal grid, what’s the best way to go about it? End goal is to solve a differential equation (poisson) using Galerkin method with BSplines on this 2D grid.
