|
fitpack
Modern Fortran library for curve and surface fitting with splines
|
This tutorial covers bivariate spline fitting to scattered data with fitpack_surface: constructing a tensor-product B-spline \( z = s(x, y) \) from irregularly sampled \( (x_i, y_i, z_i) \) triples, controlling smoothness, and evaluating derived quantities.
Use fitpack_surface whenever your observations are not aligned on a rectangular grid. If the data do lie on a regular grid, prefer fitpack_grid_surface instead (see Grid and Parametric Surface Tutorial).
Given \( m \) scattered observations \( (x_i, y_i, z_i) \) with positive weights \( w_i \), FITPACK determines a tensor-product B-spline
\[ s(x, y) = \sum_{i=1}^{n_x - k_x - 1} \sum_{j=1}^{n_y - k_y - 1} c_{ij} \, B_i^{k_x}(x) \, B_j^{k_y}(y) \]
that minimizes the thin-plate smoothing energy subject to a residual constraint:
\[ \sum_{i=1}^{m} \bigl( w_i \, (z_i - s(x_i, y_i)) \bigr)^2 \leq S \]
where \( S \) is the user-supplied smoothing parameter. Knot positions and the number of knots \( n_x, n_y \) are chosen automatically by the surfit algorithm.
The default spline degree is bicubic ( \( k_x = k_y = 3 \)). Degrees 1 through 5 are supported.
The code below fits a spline to 200 quasi-randomly distributed samples of \( f(x,y) = \sin(\pi x) \cos(\pi y) \) on \( [0,1]^2 \).
surf\new_fit(x, y, z, w, smoothing, order) stores the data, allocates workspace, and performs a smoothing fit in a single call. It returns an integer(FP_FLAG) error code.
Evaluate the fitted surface at one or many scattered points:
Both surf\eval variants call the unscattered spline evaluator bispeu, so the input points need not be sorted.
Evaluate on every node of a rectangular output grid:
The result has shape (size(y_grid), size(x_grid)).
Compute \( \partial^{n_x+n_y} s / \partial x^{n_x} \partial y^{n_y} \) at scattered points or on a grid:
The derivative order arguments nux, nuy must satisfy \( 0 \leq n_x < k_x \) and \( 0 \leq n_y < k_y \).
Integrate the surface over a rectangular sub-domain \( [x_1, x_2] \times [y_1, y_2] \):
The two arguments are 2-element arrays lower = [x_lo, y_lo] and upper = [x_hi, y_hi].
Extract a one-dimensional profile by fixing one coordinate:
The returned fitpack_curve is a full 1D spline that can be evaluated, differentiated, and integrated independently.
Build a new fitpack_surface whose evaluation gives a partial derivative of the original:
The resulting surface has reduced degree \( (k_x - n_x, \; k_y - n_y) \).
The smoothing parameter \( S \) controls the trade-off between fidelity and smoothness. Smaller \( S \) forces more knots and a closer fit; larger \( S \) yields a smoother approximation.
Special cases:
surf\interpolate().After any fit, surf\mse() returns the weighted sum of squared residuals \( f_p \), and surf\knots returns a 2-element integer array \( [n_x, n_y] \).
The same three strategies available for curves work for surfaces:
| Method | Call | Description |
|---|---|---|
| Automatic knots | surf\fit(smoothing=s) | Knots chosen to satisfy the smoothing constraint |
| Interpolation | surf\interpolate() | Passes through all data points ( \( S = 0 \)) |
| Least-squares | surf\least_squares() | User-supplied knots, no smoothing constraint |
All routines return an integer(FP_FLAG) error code:
| Flag | Meaning |
|---|---|
FITPACK_OK (0) | Success |
FITPACK_INTERPOLATING_OK (-1) | Interpolating spline returned |
FITPACK_S_TOO_SMALL (1) | Smoothing too small for the knot budget |
FITPACK_MAXIT (2) | Maximum iterations reached |
FITPACK_INPUT_ERROR (10) | Invalid input data |
A self-contained program demonstrating all of the features above is provided in examples/example_surface.f90. Build and run it with: