Source code for aerosandbox.modeling.splines.hermite

import aerosandbox.numpy as np
from typing import Union


[docs]def linear_hermite_patch( x: Union[float, np.ndarray], x_a: float, x_b: float, f_a: float, f_b: float, ) -> Union[float, np.ndarray]: """ Computes the linear Hermite polynomial patch that passes through the given endpoints f_a and f_b. Args: x: Scalar or array of values at which to evaluate the patch. x_a: The x-coordinate of the first endpoint. x_b: The x-coordinate of the second endpoint. f_a: The function value at the first endpoint. f_b: The function value at the second endpoint. Returns: The value of the patch evaluated at the input x. Returns a scalar if x is a scalar, or an array if x is an array. """ return (x - x_a) * (f_b - f_a) / (x_b - x_a) + f_a
[docs]def cubic_hermite_patch( x: Union[float, np.ndarray], x_a: float, x_b: float, f_a: float, f_b: float, dfdx_a: float, dfdx_b: float, extrapolation: str = 'continue', ) -> Union[float, np.ndarray]: """ Computes the cubic Hermite polynomial patch that passes through the given endpoints and endpoint derivatives. Args: x: Scalar or array of values at which to evaluate the patch. x_a: The x-coordinate of the first endpoint. x_b: The x-coordinate of the second endpoint. f_a: The function value at the first endpoint. f_b: The function value at the second endpoint. dfdx_a: The derivative of the function with respect to x at the first endpoint. dfdx_b: The derivative of the function with respect to x at the second endpoint. extrapolation: A string indicating how to handle extrapolation outside of the domain [x_a, x_b]. Valid values are "continue", which continues the patch beyond the endpoints, and "clip", which clips the patch at the endpoints. Default is "continue". Returns: The value of the patch evaluated at the input x. Returns a scalar if x is a scalar, or an array if x is an array. """ dx = x_b - x_a t = (x - x_a) / dx # Nondimensional distance along the patch if extrapolation == 'continue': pass elif extrapolation == 'clip': t = np.clip(t, 0, 1) else: raise ValueError("Bad value of `extrapolation`!") return ( (t ** 3) * (1 * f_b) + (t ** 2 * (1 - t)) * (3 * f_b - 1 * dfdx_b * dx) + (t * (1 - t) ** 2) * (3 * f_a + 1 * dfdx_a * dx) + ((1 - t) ** 3) * (1 * f_a) )
[docs]def cosine_hermite_patch( x: Union[float, np.ndarray], x_a: float, x_b: float, f_a: float, f_b: float, dfdx_a: float, dfdx_b: float, extrapolation: str = 'continue', ) -> Union[float, np.ndarray]: """ Computes a Hermite patch (i.e., values + derivatives at endpoints) that uses a cosine function to blend between linear segments. The end result is conceptually similar to a cubic Hermite patch, but computation is faster and the patch is C^\infty-continuous. Args: x: Scalar or array of values at which to evaluate the patch. x_a: The x-coordinate of the first endpoint. x_b: The x-coordinate of the second endpoint. f_a: The function value at the first endpoint. f_b: The function value at the second endpoint. dfdx_a: The derivative of the function with respect to x at the first endpoint. dfdx_b: The derivative of the function with respect to x at the second endpoint. extrapolation: A string indicating how to handle extrapolation outside of the domain [x_a, x_b]. Valid values are "continue", which continues the patch beyond the endpoints, and "linear", which extends the patch linearly at the endpoints. Default is "continue". Returns: The value of the patch evaluated at the input x. Returns a scalar if x is a scalar, or an array if x is an array. """ t = (x - x_a) / (x_b - x_a) # Nondimensional distance along the patch if extrapolation == 'continue': pass elif extrapolation == 'linear': t = np.clip(t, 0, 1) else: raise ValueError("Bad value of `extrapolation`!") l1 = (x - x_a) * dfdx_a + f_a l2 = (x - x_b) * dfdx_b + f_b b = 0.5 + 0.5 * np.cos(np.pi * t) return b * l1 + (1 - b) * l2
if __name__ == '__main__': import matplotlib.pyplot as plt import aerosandbox.tools.pretty_plots as p
[docs] x = np.linspace(-1, 2, 500)
plt.plot( x, cubic_hermite_patch( x, x_a=0, x_b=1, f_a=0, f_b=1, dfdx_a=-0.5, dfdx_b=-1, extrapolation='clip' ) ) p.equal() p.show_plot()