Skip to content

Getting Started

First, let's load the package along with the StaticArrays.jl package which we use for each data point

julia
using RadialBasisFunctions
using StaticArrays

Interpolation

Suppose we have a set of data x where xiR2, and we want to interpolate a function f:R2R

julia
f(x) = 2*x[1]^2 + 3*x[2]
x = [SVector{2}(rand(2)) for _ in 1:1000]
y = f.(x)
1000-element Vector{Float64}:
 1.949796847880153
 4.365061678419328
 1.8158333679762508
 2.267235653010953
 4.042788431918299
 1.1956520477904393
 4.293499502418451
 2.6777890821347614
 4.081472737805298
 3.2680161257913403

 1.4565518147980479
 0.9665517937060841
 3.322712514866616
 1.3071021580501934
 0.9459402248264434
 2.222283725466295
 2.8582327183378577
 0.6317916226972882
 3.0964137053484753

and now we can build the interpolator

julia
interp = Interpolator(x, y)
Interpolator
├─Input type: StaticArraysCore.SVector{2, Float64}
├─Output type: Float64
├─Number of points: 1000
└─Basis: Polyharmonic spline (r³) with degree 2 Monomial

and evaluate it at a new point

julia
x_new = [rand(2) for _ in 1:5]
y_new = interp(x_new)
y_true = f.(x_new)
5-element Vector{Float64}:
 2.997965072031075
 2.3752525214951463
 2.2063140726135146
 1.6940147548787858
 2.734893955704455

and compare the error

julia
abs.(y_true .- y_new)
5-element Vector{Float64}:
 8.881784197001252e-16
 4.440892098500626e-16
 1.7763568394002505e-15
 4.440892098500626e-16
 4.440892098500626e-16

Wow! The error is numerically zero! Well... we set ourselves up for success here. Interpolator (along with RadialBasisOperator) has an optional argument to provide the type of radial basis including the degree of polynomial augmentation. The default basis is a cubic polyharmonic spline with 2nd degree polynomial augmentation (which the constructor is PHS(3, poly_deg=2)) and given the underlying function we are interpolating is a 2nd order polynomial itself, we are able to represent it exactly (up to machine precision). Let's see what happens when we only use 1st order polynomial augmentation

julia
interp = Interpolator(x, y, PHS(3, poly_deg=1))
y_new = interp(x_new)
abs.(y_true .- y_new)
5-element Vector{Float64}:
 2.303845914042313e-8
 4.062415648320439e-8
 5.486017276012944e-7
 9.914695731083611e-10
 1.6515037001063604e-5

Operators

This package also provides an API for operators. There is support for several built-in operators along with support for user-defined operators. Currently, we have implementations for

  • partial derivative (1st and 2nd order)

  • laplacian

  • gradient

but we plan to add more in the future. Please make and issue or pull request for additional operators.

Partial Derivative

We can take the same data as above and build a partial derivative operator with a similar construction as the interpolator. For the partial we need to specify the order of differentiation we want along with the dimension for which to take the partial. We can also supply some optional arguments such as the basis and number of points in the stencil. The function inputs order is partial(x, order, dim, basis; k=5)

julia
df_x_rbf = partial(x, 1, 1)

# define exact
df_x(x) = 4*x[1]

# error
all(abs.(df_x.(x) .- df_x_rbf(y)) .< 1e-10)
true

Laplacian

Building a laplacian operator is as easy as

julia
lap_rbf = laplacian(x)

# define exact
lap(x) = 4

# error
all(abs.(lap.(x) .- lap_rbf(y)) .< 1e-8)
true

Gradient

We can also retrieve the gradient. This is really just a convenience wrapper around Partial.

julia
grad = gradient(x)

# define exacts
df_x(x) = 4*x[1]
df_y(x) = 3

# error
all(df_x.(x) .≈ grad(y)[1])
true
julia
all(df_y.(x) .≈ grad(y)[2])
true