|
fitpack
Modern Fortran library for curve and surface fitting with splines
|
This tutorial covers periodic spline fitting with fitpack_periodic_curve: constructing a B-spline \( y = s(x) \) that satisfies periodic boundary conditions, evaluating it, and computing derivatives and integrals across the period boundary.
A periodic spline enforces continuity of the function and all its derivatives up to order \( k-1 \) at the period boundary:
\[ s^{(j)}(x_1) = s^{(j)}(x_m), \quad j = 0, 1, \ldots, k-1 \]
This is the natural choice whenever the underlying signal is inherently periodic, for example:
The type fitpack_periodic_curve extends fitpack_curve and inherits all of its methods (eval, dfdx, integral, zeros, destroy, etc.). The only difference is that fitting calls the percur algorithm instead of curfit, which constructs a periodic knot vector and ties the B-spline coefficients at the boundary.
Given \( m \) data points \( (x_i, y_i) \) with \( x_1 < x_2 < \cdots < x_m \), the period is \( P = x_m - x_1 \). The percur routine places a wrapped knot vector: interior knots \( t_{k+2}, \ldots, t_{n-k-1} \) lie inside \( [x_1, x_m) \), while the boundary knots satisfy
\[ t_{j} = t_{n-2k+j} - P, \quad j = 1, \ldots, k, \qquad t_{n-k+j} = t_{k+1+j} + P, \quad j = 1, \ldots, k \]
The B-spline coefficients are tied so that \( c_{n-k-1+j} = c_j \) for \( j = 1, \ldots, k \), which guarantees that the spline and its first \( k-1 \) derivatives are continuous across the period boundary.
As with fitpack_curve, the smoothing parameter \( s \) controls the trade-off between fidelity and smoothness:
\[ \sum_{i=1}^{m-1} \left( w_i \bigl(y_i - s(x_i)\bigr) \right)^2 \leq s \]
Note that the last data point \( (x_m, y_m) \) defines the period length but is not included in the residual sum (only \( m-1 \) points are fitted).
Fit the periodic function \( f(x) = \cos(x) + \sin(2x) \) on \( [0, 2\pi] \). The data must include the right endpoint \( x_m = 2\pi \) so that percur can determine the period.
The call to curve\new_fit loads the data and performs a smoothing fit in one step. Because fitpack_periodic_curve extends fitpack_curve, all evaluation and query methods work identically.
A key property of the periodic spline is that function values and derivatives match at the endpoints. After fitting, verify:
For a cubic spline ( \( k = 3 \)), the values, first derivatives, and second derivatives all match to machine precision:
\[ s(x_1) = s(x_m), \quad s'(x_1) = s'(x_m), \quad s''(x_1) = s''(x_m) \]
This is not the case for a non-periodic fitpack_curve, where the boundary derivatives are generally unrelated.
The curve\integral method works with periodic splines exactly as with non-periodic ones. The integration limits need not coincide with the data range. For example, integrate from \( \pi/2 \) to \( 3\pi \) (which crosses the period boundary at \( 2\pi \)):
For the test function \( f(x) = \cos(x) + \sin(2x) \) the exact integral is
\[ \int_{\pi/2}^{3\pi} \bigl[\cos(x) + \sin(2x)\bigr] \, dx = \Bigl[\sin(x) - \frac{1}{2}\cos(2x)\Bigr]_{\pi/2}^{3\pi} = -\frac{3}{2} \]
The periodic variant supports the same fitting modes as fitpack_curve:
| Method | Call | Description |
|---|---|---|
| Smoothing | curve\new_fit(x, y, smoothing=s) | Automatic knot placement with smoothing constraint |
| Re-fit | curve\fit(smoothing=s) | Change smoothing on existing data |
| Interpolation | curve\interpolate() | Pass through all data points ( \( s = 0 \)) |
Lowering the smoothing parameter increases the number of knots and brings the spline closer to the data:
A self-contained program demonstrating periodic fitting, evaluation, periodicity verification, integration, interpolation, and a smoothing sweep is provided in the repository:
examples/example_periodic_curve.f90