utils.func.make_derivative_func

utils.func.make_derivative_func(
    method='numpy',
    derivative=None,
    data=None,
    time=None,
)

Return a callable that evaluates the derivative of a forcing at arbitrary times.

Three usage modes:

  1. Pass-through — if derivative is already a callable, return it unchanged.
  2. Numpy mode — compute a finite-difference derivative via np.gradient, then fit a :class:scipy.interpolate.CubicSpline to the result. Suitable for non-uniformly spaced data.
  3. Scipy mode — fit a :class:scipy.interpolate.CubicSpline directly to data, then return its analytical first derivative. Slightly smoother than numpy mode for well-resolved data.

Parameters

method : str = 'numpy'

Derivative method when data is provided. One of 'numpy' (default) or 'scipy'.

derivative : callable or None = None

Pre-computed derivative function. If provided and callable, it is returned immediately without further processing. Default None.

data : array - like or None = None

Forcing values used to compute the derivative numerically. Required when derivative is None.

time : array - like or None = None

Time axis corresponding to data. If None, defaults to np.arange(len(data)).

Returns

deriv_func : callable

Callable with signature f(t) -> float that returns the derivative of the forcing at time t. In numpy and scipy modes this is a :class:~scipy.interpolate.CubicSpline (or its derivative object).

Raises

: ValueError

If derivative is provided but is not callable, if data is None when derivative is None, or if method is not 'numpy' or 'scipy'.

Examples

import numpy as np
import climatecritters as cc
from climatecritters.utils.func import make_derivative_func
from climatecritters.model_critters.g24 import Model3, calc_f

# Build a Forcing from a data array (gives access to .data and .time)
t_axis = np.linspace(-2000, 0, 4000)
f_vals = np.array([calc_f(t) for t in t_axis])
orb_forcing = cc.Forcing(data=f_vals, time=t_axis)

# Compute a smooth derivative and attach it to Model3
dfdt = make_derivative_func(method='scipy', data=orb_forcing.data,
                            time=orb_forcing.time)
model = Model3()
model.register_forcing('insolation', orb_forcing)
model.set_param_value('dfdt', dfdt)
output = model.integrate(t_span=(-2000, 0), y0=[0.0, 1], method='RK45',
                         kwargs={'max_step': 0.5})