NaturalNeighbours
Documentation for NaturalNeighbours.
This is a package for working with natural neighbours of planar point sets, enabling scattered data (or spatial) interpolation via natural neighbour interpolation, as well as derivative generation. We use DelaunayTriangulation.jl to define the spatial information. Much of the work in this package is based on this great thesis.
Please see the sections in the sidebar for some more discussion. The relevant docstrings for this package are shown below.
NaturalNeighbours.interpolate — Functioninterpolate(tri::Triangulation, z; gradient=nothing, hessian=nothing, derivatives=false, kwargs...)
interpolate(points, z; gradient=nothing, hessian=nothing, derivatives=false, kwargs...)
interpolate(x::AbstractVector, y::AbstractVector, z; gradient=nothing, hessian=nothing, derivatives=false, kwargs...)Construct an interpolant over the data z at the sites defined by the triangulation tri (or points, or (x, y)). See the Output  section for a description of how to use the interpolant itp.
When the underlying triangulation, tri, has points in get_points(tri) that are not  vertices of the triangulation itself, the associated derivatives (relevant only if derivatives=true) at these points will be set to zero.
Keyword Arguments
gradient=nothing: The gradients at the corresponding data sites ofz. Will be generated ifisnothing(gradient)andderivatives==true.hessian=nothing: The hessians at the corresponding data sites ofz. Will be generated ifisnothing(hessian)andderivatives==true.derivatives=false: Whether to generate derivatives at the data sites ofz. See alsogenerate_derivatives.kwargs...: Keyword arguments passed togenerate_derivatives.
Output
The returned value is a NaturalNeighboursInterpolant struct. This struct is callable, with the following methods defined:
(itp::NaturalNeighboursInterpolant)(x, y, id::Integer=1; parallel=false, method=Sibson(), project = true, kwargs...)
(itp::NaturalNeighboursInterpolant)(vals::AbstractVector, x::AbstractVector, y::AbstractVector; parallel=true, method=Sibson(), project = true, kwargs...)
(itp::NaturalNeighboursInterpolant)(x::AbstractVector, y::AbstractVector; parallel=true, method=Sibson(), project = true, kwargs...)- The first method is for scalars, with 
idreferring to a thread id. - This method is an in-place method for vectors, storing 
itp(x[i], y[i])intovals[i]. - This method is similar to (2), but 
valsis constructed and returned. 
In each method, method defines the method used for evaluating the interpolant, which is some AbstractInterpolator. For the first  method, parallel is ignored, but for the latter two methods it defines whether to use multithreading or not for evaluating the interpolant at  all the points. The kwargs... argument is passed into add_point! from DelaunayTriangulation.jl, e.g. you could pass some rng. Lastly,  the project argument determines whether extrapolation is performed by projecting any exterior points onto the boundary of the convex hull  of the data sites and performing two-point interpolation, or to simply replace any extrapolated values with Inf.
For the best performance when evaluating the interpolant at many points, either of the second or third methods are preferred over repeatedly calling the first.
Until we implement ghost point extrapolation, behaviour near the convex hull of your data sites may in some cases be undesirable, despite the extrapolation method we describe above, even for points that are inside the convex hull. If you want to control this  behaviour so that you discard any points that are very close to the convex hull, see identify_exterior_points and the tol  keyword argument.
NaturalNeighbours.differentiate — Functiondifferentiate(itp::NaturalNeighboursInterpolant, order)Differentiate a given interpolant itp up to degree order (1 or 2). The returned object is a  NaturalNeighboursDifferentiator struct, which is callable. 
When the underlying triangulation, tri, has points in get_points(tri) that are not  vertices of the triangulation itself, the associated derivatives at these points will be set to zero.
For calling the resulting struct, we define the following methods:
(∂::NaturalNeighboursDifferentiator)(x, y, zᵢ, nc, id::Integer=1; parallel=false, method=default_diff_method(∂), kwargs...)
(∂::NaturalNeighboursDifferentiator)(x, y, id::Integer=1; parallel=false, method=default_diff_method(∂), interpolant_method=Sibson(), rng=Random.default_rng(), project = true, kwargs...)
(∂::NaturalNeighboursDifferentiator)(vals::AbstractVector, x::AbstractVector, y::AbstractVector; parallel=true, method=default_diff_method(∂), interpolant_method=Sibson(), kwargs...)
(∂::NaturalNeighboursDifferentiator{I, O})(x::AbstractVector, y::AbstractVector; parallel=true, method=default_diff_method(∂), interpolant_method=Sibson(), kwargs...) where {I, O}- This method is useful if you already have an estimate for the function value, 
zᵢ, at the data site,(x, y), provided you also provide theNaturalCoordinatesnc.idis the thread id. - This method is for scalars, with 
idreferring to a thread id. - This method is an in-place method for vectors, storing 
∂(x[i], y[i], 1)intovals[i]. - This method is similar to (3), but 
valsis constructed and returned. 
The available keyword arguments are:
parallel=true: Whether to use multithreading. Ignored for the first two methods.method=default_diff_method(∂): Default method for evaluating the interpolant.default_diff_method(∂)returnsDirect(). The method must be aAbstractDifferentiator.interpolant_method=Sibson(): The method used for evaluating the interpolant to estimatezᵢfor the latter three methods. SeeAbstractInterpolatorfor the available methods.rng=Random.default_rng(): The random number generator used for estimatingzᵢfor the latter three methods, or for constructing the natural coordinates.project=false: Whether to project any extrapolated points onto the boundary of the convex hull of the data sites and perform two-point interpolation, or to simply replace any extrapolated values withInf, when evaluating the interpolant in the latter three methods.use_cubic_terms=true: If estimating second order derivatives, whether to use cubic terms. Only relevant formethod == Direct().alpha=0.1: If estimating second order derivatives, the weighting parameter used for estimating the second order derivatives. Only relevant formethod == Iterative().use_sibson_weight=true: Whether to weight the residuals in the associated least squares problems by the associated Sibson coordinates. Only relevant formethod == Iterative()iforder == 2.
The outputs are:
order == 1: The scalar methods return aTupleof the form(∂x, ∂y), while the vector methods return a vector ofTuples of the form(∂x, ∂y).order == 2: The scalar methods return a(∇, ℋ), where∇is aTupleof the form(∂x, ∂y)andℋis aTupleof the form(∂xx, ∂yy, ∂xy). The vector methods return a vector of(∇, ℋ)s.
Until we implement ghost point extrapolation, behaviour near the convex hull of your data sites may in some cases be undesirable, despite the extrapolation method we describe above, even for points that are inside the convex hull. If you want to control this  behaviour so that you discard any points that are very close to the convex hull, see identify_exterior_points and the tol  keyword argument.
NaturalNeighbours.generate_gradients — Functiongenerate_gradients(
    tri,
    z,
    derivative_caches=[DerivativeCache(tri) for _ in 1:Base.Threads.nthreads()],
    neighbour_caches=[NaturalNeighboursCache(tri) for _ in 1:Base.Threads.nthreads()];
    parallel=true
)Generate gradients at the data sites defined by the triangulation tri with associated function values tri.
Arguments
tri: ATriangulationobject.z: A vector of function values at the data sites.derivative_caches=[DerivativeCache(tri) for _ in 1:Base.Threads.nthreads()]: A vector ofDerivativeCacheobjects, one for each thread.neighbour_caches=[NaturalNeighboursCache(tri) for _ in 1:Base.Threads.nthreads()]: A vector ofNaturalNeighboursCacheobjects, one for each thread.
Keyword Arguments
parallel=true: Whether to use multithreading or not.
Output
∇: A vector of gradients at the data sites. Each element is aTupledefining the gradient entries.
NaturalNeighbours.generate_derivatives — Functiongenerate_derivatives(
    tri,
    z,
    derivative_caches=[DerivativeCache(tri) for _ in 1:Base.Threads.nthreads()],
    neighbour_caches=[NaturalNeighboursCache(tri) for _ in 1:Base.Threads.nthreads()];
    parallel=true,
    method=Direct(),
    use_cubic_terms=true,
    alpha=0.1,
    initial_gradients=dwrap(method) == Direct() ? nothing : generate_gradients(tri, z, derivative_caches, neighbour_caches; method=dwrap(method), parallel, rng)
)Generate derivatives at the data sites defined by the triangulation tri with associated function values tri.
Arguments
tri: ATriangulationobject.z: A vector of function values at the data sites.derivative_caches=[DerivativeCache(tri) for _ in 1:Base.Threads.nthreads()]: A vector ofDerivativeCacheobjects, one for each thread.neighbour_caches=[NaturalNeighboursCache(tri) for _ in 1:Base.Threads.nthreads()]: A vector ofNaturalNeighboursCacheobjects, one for each thread.
Keyword Arguments
parallel=true: Whether to use multithreading or not.method=Direct(): The method used for generating the derivatives. SeeAbstractDifferentiator.use_cubic_terms=true: Whether to use cubic terms for estimating the second order derivatives. Only relevant formethod == Direct().alpha=0.1: The weighting parameter used for estimating the second order derivatives. Only relevant formethod == Iterative().initial_gradients=dwrap(method) == Direct() ? nothing : generate_gradients(tri, z, derivative_caches, neighbour_caches; method=dwrap(method), parallel): The initial gradients used for estimating the second order derivatives. Only relevant formethod == Iterative().
Output
∇: A vector of gradients at the data sites. Each element is aTupledefining the gradient entries.ℋ: A vector of Hessians at the data sites. Each element is aTupledefining the Hessian entries in the form(H[1, 1], H[2, 2], H[1, 2])(H[2, 1]is the same asH[2, 2]).
NaturalNeighbours.AbstractInterpolator — Typeabstract type AbstractInterpolator{D}Abstract type for defining the method used for evaluating an interpolant. D is, roughly, defined to be  the smoothness at the data sites (currently only relevant for Sibson). The available subtypes are:
Sibson(d): Interpolate via the Sibson interpolant, withC(d)continuity at the data sites. Only defined forD ∈ (0, 1). IfD == 1, gradients must be provided.Triangle(d): Interpolate based on vertices of the triangle that the point resides in, withC(0)continuity at the data sites.Dis ignored.Nearest(d): Interpolate by returning the function value at the nearest data site.Ddoesn't mean much here (it could beD = ∞), and so it is ignored and replaced with0.Laplace(d): Interpolate via the Laplace interpolant, withC(0)continuity at the data sites.Dis ignored.Farin(d): Interpolate using the Farin interpolant, withC(1)continuity at the data sites.dis ignored.Hiyoshi(d): Interpolate using the Hiyoshi interpolant, withC(d)continuity at the data sites. Currently, only defined ford == 2.
Our implementation of Sibson(0)'s coordinates follows this article with some simple modifications.
NaturalNeighbours.AbstractDifferentiator — Typeabstract type AbstractDifferentiator endAbstract type for defining the method used for differentiating an interpolant or generating derivatives at data sites.
Direct(): Generate derivatives directly with one least squares problem.Iterative(): Generate derivatives iteratively: Gradients are estimated first, and then both gradients and Hessians are estimated with the initial gradients used to refine the results.
NaturalNeighbours.Sibson — TypeSibson(d=0)Interpolate using Sibson's coordinates with C(d) continuity at the data sites.
NaturalNeighbours.Hiyoshi — TypeHiyoshi(d)Interpolate using Hiyoshi's C(d) interpolant. Hiyoshi's interpolant C(0) is not yet implemented,  but we do not make any conversions to C(2) like in e.g. Farin(), e.g. Farin() gets  converted to Farin(1) but, to support possible later versions, Hiyoshi() does not get  converted to Hiyoshi(2).
NaturalNeighbours.Farin — TypeFarin()Interpolate using Farin's C(1) interpolant.
NaturalNeighbours.Laplace — TypeLaplace()Interpolate using Laplace's coordinates.
NaturalNeighbours.Triangle — TypeTriangle(; allow_cache = true)Interpolate using a piecewise linear interpolant over the underlying triangulation.
The Triangle() interpolator is special as it will cache the coordinates used  for each triangle. In particular, when an interpolator is evaluated with the  Triangle() method, the object returned from Triangle() will store all  the coordinates. For this reason, if you want to reuse Triangle() for different  evaluations of the interpolant, you should be sure to reuse the same instance rather  than reinstantiating it every single time. If you do not want this behaviour, set  allow_cache = false.
If you only ever call the scalar-argument version of the interpolant, no caching will  be done even with allow_cache = true.
NaturalNeighbours.Nearest — TypeNearest()Interpolate by taking the function value at the nearest data site.
NaturalNeighbours.Direct — TypeDirect()Generate derivatives directly with one least squares problem.
NaturalNeighbours.Iterative — TypeIterative()Generate derivatives iteratively: Gradients are estimated first, and then both gradients and Hessians are estimated with the initial gradients used to refine the results.
NaturalNeighbours.identify_exterior_points — Functionidentify_exterior_points(x, y, points, boundary_nodes; tol = 0.0)Given a polygon described by (points, boundary_nodes), matching the  specification of polygons in DelaunayTriangulation.jl, returns a vector of indices of the points defined by (x, y) that are outside of the polygon.
Use tol to specify a tolerance for the distance to the polygon.
identify_exterior_points(x, y, itp::NaturalNeighboursInterpolant; tol = 0.0)Returns the indices of the points defined by the vectors (x, y) that are  outside of the underlying triangulation to the interpolant itp.
Use tol to specify a tolerance for the distance to the triangulation.