PyREC scaffolding (from YREC development, 7be4133)/ slopes.fGlossary

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)

json

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

lines 4–124 · GitHub

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)
repeated from label 10 (GO TO at line 97), lines 66–97
Compiler warnings (2)

gfortran -Wall -Wextra, compiling only; nothing was run.

  • line 66: Equality comparison for REAL(8) [-Wcompare-reals]
  • line 66: Equality comparison for REAL(8) [-Wcompare-reals]

subroutineSAFEDIVIDE

lines 129–141 · GitHub

Returns NUMERATOR/DENOMINATOR, or 0 when either is zero. Added by KC (2025-05-31) to avoid floating-point exceptions.

Called by SLOPES ×2

Compiler warnings (2)

gfortran -Wall -Wextra, compiling only; nothing was run.

  • line 136: Inequality comparison for REAL(8) [-Wcompare-reals]
  • line 136: Inequality comparison for REAL(8) [-Wcompare-reals]

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.