Hi again!
FastInterpolations.jl is quickly evolving. I'm going to seek help on my common use cases of interpolating a field from numerical simulation outputs. As the boundary conditions are only supported for part of the methods (e.g. not for linear_interp), I am using WrapExtrap() currently in my workflow.
The grid setup in the following demo is a common pattern in Finite Volume simulations and periodic signal processing, where the grid points represent unique cell centers (or unique samples) and the total grid span is one short of the full period. In Interpolations.jl, this is distinguished by the gridstyle (OnGrid(), OnCell()) Interpolations.jl
Grid Configuration
- Coordinates: x = [0.5, 1.5, 2.5] ($N=3$ points).
- Values: y = [1.0, 2.0, 3.0].
- Spacing: $\Delta x = 1.0$.
- Desired Period: $L = N \times \Delta x = 3.0$.
This setup describes a domain of length 3.0 (e.g., $[0.0, 3.0]$) divided into 3 cells of width $1.0$. The data points are located at the cell centers. In a periodic system of this type:
- The point $x = 3.0$ is equivalent to $x = 0.0$.
- The point $x = 3.5$ is equivalent to $x = 0.5$ (the first cell center).
- Expected Value at $x=3.5$: 1.0.
The Issue with Standard Wrapping
By default, FastInterpolations.jl's Extrap(:wrap) uses the distance between the first and last points as the period ($L_{\text{default}} = x_{\text{end}} - x_{\text{start}} = 2.0$).
- Standard Result: $x=3.5 \pmod{2.0}$ maps to $x=1.5$.
- Returned Value: 2.0 (Incorrect for this grid type).
Expected native support
While cubic_interp supports this via PeriodicBC(endpoint=:exclusive, period=3.0), the generic and ND methods (linear_interp, cardinal_interp, etc.) do not currently provide a unified keyword-based way to specify the Exclusive Period $L$. Is it possible to have a similar support with Extrap(:warp) without the need of manual padding? Or if you have a better idea, let me know!
using FastInterpolations
println("--- Exclusive Periodic Grid Demo ---")
# 1. Setup an "Exclusive" Grid (e.g., cell centers)
# Grid: [0.5, 1.5, 2.5], Values: [1.0, 2.0, 3.0]
# Expected Period L = 3.0 (not 2.0! Next point at 3.5 should wrap to 0.5)
x = [0.5, 1.5, 2.5]
y = [1.0, 2.0, 3.0]
dx = 1.0
L_expected = 3.0
println("Original Grid: ", x)
println("Original Values: ", y)
println("Expected Period (N*dx): ", L_expected)
# 2. Standard FastInterpolations wrapping (Inclusive)
# This uses period = last(x) - first(x) = 2.0
itp_standard = linear_interp(x, y; extrap = Extrap(:wrap))
val_standard = itp_standard(3.5)
println("\nStandard Wrap (Inclusive):")
println(" Query at x=3.5 maps to: ", 0.5 + mod(3.5 - 0.5, 2.5 - 0.5))
println(" Value at x=3.5: ", val_standard)
# 3. Exclusive Wrap via Padding
# We add a virtual point at x=3.5 with value y=1.0
x_padded = [0.5, 1.5, 2.5, 3.5]
y_padded = [1.0, 2.0, 3.0, 1.0]
itp_exclusive = linear_interp(x_padded, y_padded; extrap = Extrap(:wrap))
val_exclusive = itp_exclusive(3.5)
println("\nExclusive Wrap (via Padding):")
println(" Query at x=3.5 maps to: ", 0.5 + mod(3.5 - 0.5, 3.5 - 0.5))
println(" Value at x=3.5: ", val_exclusive, " (Success!)")
# 4. Same demo for Cardinal (Order 3) Interpolation
# This is even more important for splines to ensure C2 continuity across the boundary
itp_cardinal = cardinal_interp(x_padded, y_padded; extrap = Extrap(:wrap))
val_cardinal = itp_cardinal(3.5)
println("\nCardinal Exclusive (Order 3):")
println(" Value at x=3.5: ", val_cardinal)
# 5. Native FastInterpolations PeriodicBC (Order 3)
# Note: For non-uniform grids (including Vector), we need to specify the period.
itp_periodicBC = cubic_interp(x, y; bc = PeriodicBC(endpoint = :exclusive, period = 3.0))
val_periodicBC = itp_periodicBC(3.5)
println("\nNative PeriodicBC (endpoint=:exclusive, period=3.0):")
println(" Value at x=3.5: ", val_periodicBC)
Original Grid: [0.5, 1.5, 2.5]
Original Values: [1.0, 2.0, 3.0]
Expected Period (N*dx): 3.0
Standard Wrap (Inclusive):
Query at x=3.5 maps to: 1.5
Value at x=3.5: 2.0
Exclusive Wrap (via Padding):
Query at x=3.5 maps to: 0.5
Value at x=3.5: 1.0 (Success!)
Cardinal Exclusive (Order 3):
Value at x=3.5: 1.0
Native PeriodicBC (endpoint=:exclusive, period=3.0):
Value at x=3.5: 1.0
Hi again!
FastInterpolations.jl is quickly evolving. I'm going to seek help on my common use cases of interpolating a field from numerical simulation outputs. As the boundary conditions are only supported for part of the methods (e.g. not for linear_interp), I am using
WrapExtrap()currently in my workflow.The grid setup in the following demo is a common pattern in Finite Volume simulations and periodic signal processing, where the grid points represent unique cell centers (or unique samples) and the total grid span is one short of the full period. In Interpolations.jl, this is distinguished by the
gridstyle(OnGrid(), OnCell()) Interpolations.jlGrid Configuration
This setup describes a domain of length 3.0 (e.g.,$[0.0, 3.0]$ ) divided into 3 cells of width $1.0$ . The data points are located at the cell centers. In a periodic system of this type:
The Issue with Standard Wrapping
By default,$L_{\text{default}} = x_{\text{end}} - x_{\text{start}} = 2.0$ ).
FastInterpolations.jl'sExtrap(:wrap)uses the distance between the first and last points as the period (Expected native support
While$L$ . Is it possible to have a similar support with
cubic_interpsupports this viaPeriodicBC(endpoint=:exclusive, period=3.0), the generic and ND methods (linear_interp,cardinal_interp, etc.) do not currently provide a unified keyword-based way to specify the Exclusive PeriodExtrap(:warp)without the need of manual padding? Or if you have a better idea, let me know!