slopes.f
141 lines · 2 definitions · on GitHub (7be4133)
Python version: slopes.py, 92 lines, on the right (switch to Python above the code).
Variables on this page (1)
Purpose
Computes the derivative at each node for the shape-preserving quadratic splines of McAllister and Roulier (coded by S. L. Dodd and M. Roulier, N.C. State University). Its comment: "the slopes provided will insure that an osculatory quadratic spline will have one additional knot between two adjacent points of interpolation. Convexity and monotonicity are preserved wherever these conditions are compatible with the data."
How it fits
Called by OSPLIN before MEVAL evaluates the spline (with SEARCH). It contains a second routine, SAFEDIVIDE, added by KC. No COMMON blocks.
The method
At each interior node $i$, with the slopes $m_1$, $m_2$ of the chords to its two neighbors:
- if $m_1 m_2 \le 0$ (a local extremum or a flat chord), the derivative is 0;
- otherwise the chord with the larger slope is extended until it reaches the level of the far neighbor, at $\bar x$, and the derivative is the slope of the line from the node to the far neighbor's level at $\hat x$, the midpoint between $\bar x$ and the far node. For $|m_1| > |m_2|$: $$\bar x = x_i + \frac{y_{i+1} - y_i}{m_1},\qquad \hat x = \tfrac12(\bar x + x_{i+1}),\qquad y'_i = \frac{y_{i+1} - y_i}{\hat x - x_i}.$$
At each end node, the derivative is the slope from the midpoint of the end interval, where it takes the value of the line through the neighbor node with that node's derivative, to the end node. It is set to 0 if that would reverse the sign of the end chord, or to $2m$, twice the end chord's slope $m$, if the two chords nearest that end have opposite signs.
Two divisions go through SAFEDIVIDE, which returns 0 instead of dividing by zero: the slope $m_2$ in the loop (line 96↗) and the derivative at the last node (line 105↗). A zero denominator means two equal abscissae, which would make the spline ill-defined anyway, so the 0 hides the problem, and a check in OSPLIN might be clearer; which caller can pass a table with two equal abscissae is CHOOSE's question 1.
Definitions
subroutineSLOPES
The derivatives at the nodes, as above. MTAB is declared REAL*8 explicitly (under the implicit typing of rp_1 its name would have made it an integer; now every name is declared).
Uses modules DIMENSIONS_MOD
Called by OSPLIN
Flowchart of its calls, in order (2)
subroutineSAFEDIVIDE
Returns NUMERATOR/DENOMINATOR, or 0 when either is zero. Added by KC (2025-05-31) to avoid floating-point exceptions.
Called by SLOPES ×2
Change log
The changes since rp_1
Changed since rp_1. Declarations only: the array size JSON from DIMENSIONS_MOD, IMPLICIT NONE in both routines.