This page was generated from
doc/euclidean/natural-uniform.ipynb.
Interactive online version:
.
Uniform Natural Splines§
[1]:
import sympy as sp
sp.init_printing(order='rev-lex')
[2]:
from utility import NamedExpression
[3]:
t = sp.symbols('t')
[4]:
a3, a4, b3, b4, c3, c4, d3, d4 = sp.symbols('a:dbm3:5')
[5]:
b_monomial = sp.Matrix([t**3, t**2, t, 1]).T
[6]:
p3 = NamedExpression('pbm3', d3 * t**3 + c3 * t**2 + b3 * t + a3)
p4 = NamedExpression('pbm4', d4 * t**3 + c4 * t**2 + b4 * t + a4)
display(p3, p4)
$\displaystyle \boldsymbol{p}_{3} = \boldsymbol{d}_{3} t^{3} + \boldsymbol{c}_{3} t^{2} + \boldsymbol{b}_{3} t + \boldsymbol{a}_{3}$
$\displaystyle \boldsymbol{p}_{4} = \boldsymbol{d}_{4} t^{3} + \boldsymbol{c}_{4} t^{2} + \boldsymbol{b}_{4} t + \boldsymbol{a}_{4}$
[7]:
pd3 = p3.diff(t)
pd4 = p4.diff(t)
display(pd3, pd4)
$\displaystyle \frac{d}{d t} \boldsymbol{p}_{3} = 3 \boldsymbol{d}_{3} t^{2} + 2 \boldsymbol{c}_{3} t + \boldsymbol{b}_{3}$
$\displaystyle \frac{d}{d t} \boldsymbol{p}_{4} = 3 \boldsymbol{d}_{4} t^{2} + 2 \boldsymbol{c}_{4} t + \boldsymbol{b}_{4}$
[8]:
equations = [
p3.evaluated_at(t, 0).with_name('xbm3'),
p3.evaluated_at(t, 1).with_name('xbm4'),
p4.evaluated_at(t, 0).with_name('xbm4'),
p4.evaluated_at(t, 1).with_name('xbm5'),
pd3.evaluated_at(t, 0).with_name('xbmdot3'),
pd3.evaluated_at(t, 1).with_name('xbmdot4'),
pd4.evaluated_at(t, 0).with_name('xbmdot4'),
pd4.evaluated_at(t, 1).with_name('xbmdot5'),
]
display(*equations)
$\displaystyle \boldsymbol{x}_{3} = \boldsymbol{a}_{3}$
$\displaystyle \boldsymbol{x}_{4} = \boldsymbol{d}_{3} + \boldsymbol{c}_{3} + \boldsymbol{b}_{3} + \boldsymbol{a}_{3}$
$\displaystyle \boldsymbol{x}_{4} = \boldsymbol{a}_{4}$
$\displaystyle \boldsymbol{x}_{5} = \boldsymbol{d}_{4} + \boldsymbol{c}_{4} + \boldsymbol{b}_{4} + \boldsymbol{a}_{4}$
$\displaystyle \dot{\boldsymbol{x}}_{3} = \boldsymbol{b}_{3}$
$\displaystyle \dot{\boldsymbol{x}}_{4} = 3 \boldsymbol{d}_{3} + 2 \boldsymbol{c}_{3} + \boldsymbol{b}_{3}$
$\displaystyle \dot{\boldsymbol{x}}_{4} = \boldsymbol{b}_{4}$
$\displaystyle \dot{\boldsymbol{x}}_{5} = 3 \boldsymbol{d}_{4} + 2 \boldsymbol{c}_{4} + \boldsymbol{b}_{4}$
[9]:
coefficients = sp.solve(equations, [a3, a4, b3, b4, c3, c4, d3, d4])
for c, e in coefficients.items():
display(NamedExpression(c, e))
$\displaystyle \boldsymbol{a}_{3} = \boldsymbol{x}_{3}$
$\displaystyle \boldsymbol{b}_{3} = \dot{\boldsymbol{x}}_{3}$
$\displaystyle \boldsymbol{c}_{3} = - \dot{\boldsymbol{x}}_{4} - 2 \dot{\boldsymbol{x}}_{3} + 3 \boldsymbol{x}_{4} - 3 \boldsymbol{x}_{3}$
$\displaystyle \boldsymbol{d}_{3} = \dot{\boldsymbol{x}}_{4} + \dot{\boldsymbol{x}}_{3} - 2 \boldsymbol{x}_{4} + 2 \boldsymbol{x}_{3}$
$\displaystyle \boldsymbol{a}_{4} = \boldsymbol{x}_{4}$
$\displaystyle \boldsymbol{b}_{4} = \dot{\boldsymbol{x}}_{4}$
$\displaystyle \boldsymbol{c}_{4} = - \dot{\boldsymbol{x}}_{5} - 2 \dot{\boldsymbol{x}}_{4} + 3 \boldsymbol{x}_{5} - 3 \boldsymbol{x}_{4}$
$\displaystyle \boldsymbol{d}_{4} = \dot{\boldsymbol{x}}_{5} + \dot{\boldsymbol{x}}_{4} - 2 \boldsymbol{x}_{5} + 2 \boldsymbol{x}_{4}$
NB: these are the same constants as in \(M_H\) (see Uniform Hermite Splines)!
[10]:
pdd3 = pd3.diff(t)
pdd4 = pd4.diff(t)
display(pdd3, pdd4)
$\displaystyle \frac{d^{2}}{d t^{2}} \boldsymbol{p}_{3} = 6 \boldsymbol{d}_{3} t + 2 \boldsymbol{c}_{3}$
$\displaystyle \frac{d^{2}}{d t^{2}} \boldsymbol{p}_{4} = 6 \boldsymbol{d}_{4} t + 2 \boldsymbol{c}_{4}$
[11]:
sp.Eq(pdd3.expr.subs(t, 1), pdd4.expr.subs(t, 0))
[11]:
$\displaystyle 6 \boldsymbol{d}_{3} + 2 \boldsymbol{c}_{3} = 2 \boldsymbol{c}_{4}$
[12]:
_.subs(coefficients).simplify()
[12]:
$\displaystyle 3 \boldsymbol{x}_{3} = - \dot{\boldsymbol{x}}_{5} - 4 \dot{\boldsymbol{x}}_{4} - \dot{\boldsymbol{x}}_{3} + 3 \boldsymbol{x}_{5}$
generalize by setting index \(4 \to i\)
\begin{equation*}
\dot{\boldsymbol{x}}_{i-1}
+
4 \dot{\boldsymbol{x}}_{i}
+
\dot{\boldsymbol{x}}_{i+1}
=
3 (\boldsymbol{x}_{i+1} - \boldsymbol{x}_{i-1})
\end{equation*}
\begin{equation*}
\left[
\begin{matrix}
1 & 4 & 1 && \cdots & 0 \\
& 1 & 4 & 1 && \vdots \\
&& \ddots & \ddots && \\
\vdots && 1 & 4 & 1 & \\
0 & \cdots && 1 & 4 & 1
\end{matrix}
\right]
\left[
\begin{matrix}
\dot{\boldsymbol{x}}_0\\
\dot{\boldsymbol{x}}_1\\
\vdots\\
\dot{\boldsymbol{x}}_{N-2}\\
\dot{\boldsymbol{x}}_{N-1}
\end{matrix}
\right]
=
\left[
\begin{matrix}
3 (\boldsymbol{x}_2 - \boldsymbol{x}_0)\\
3 (\boldsymbol{x}_3 - \boldsymbol{x}_1)\\
\vdots\\
3 (\boldsymbol{x}_{N-2} - \boldsymbol{x}_{N-4})\\
3 (\boldsymbol{x}_{N-1} - \boldsymbol{x}_{N-3})
\end{matrix}
\right]
\end{equation*}
\(N\) columns, \(N-2\) rows
End Conditions§
add first and last row
end conditions can be mixed, e.g. “clamped” at the beginning and “natural” at the end.
The Python class splines.Natural uses “natural” end conditions by default.
Natural§
notebook about “natural” end conditions
Get the uniform case by setting \(\Delta_i = 1\).
\begin{align*}
2 \dot{\boldsymbol{x}}_0
+
\dot{\boldsymbol{x}}_1
&=
3 (\boldsymbol{x}_1 - \boldsymbol{x}_0)
\\
\dot{\boldsymbol{x}}_{N-2}
+
2 \dot{\boldsymbol{x}}_{N-1}
&=
3 (\boldsymbol{x}_{N-1} - \boldsymbol{x}_{N-2})
\end{align*}
\begin{equation*}
\left[
\begin{matrix}
2 & 1 &&& \cdots & 0\\
1 & 4 & 1 &&& \vdots \\
& 1 & 4 & 1 && \\
&& \ddots & \ddots && \\
&& 1 & 4 & 1 & \\
\vdots &&& 1 & 4 & 1\\
0 & \cdots &&& 1 & 2
\end{matrix}
\right]
\left[
\begin{matrix}
\dot{\boldsymbol{x}}_0\\
\dot{\boldsymbol{x}}_1\\
\vdots\\
\dot{\boldsymbol{x}}_{N-2}\\
\dot{\boldsymbol{x}}_{N-1}
\end{matrix}
\right]
=
\left[
\begin{matrix}
3 (\boldsymbol{x}_1 - \boldsymbol{x}_0)\\
3 (\boldsymbol{x}_2 - \boldsymbol{x}_0)\\
3 (\boldsymbol{x}_3 - \boldsymbol{x}_1)\\
\vdots\\
3 (\boldsymbol{x}_{N-2} - \boldsymbol{x}_{N-4})\\
3 (\boldsymbol{x}_{N-1} - \boldsymbol{x}_{N-3})\\
3 (\boldsymbol{x}_{N-1} - \boldsymbol{x}_{N-2})
\end{matrix}
\right]
\end{equation*}
Clamped§
clamped (end tangents are given)
\begin{align*}
\dot{\boldsymbol{x}}_0 &= D_\text{begin}\\
\dot{\boldsymbol{x}}_{N-1} &= D_\text{end}
\end{align*}
\begin{equation*}
\left[
\begin{matrix}
1 &&&& \cdots & 0\\
1 & 4 & 1 &&& \vdots \\
& 1 & 4 & 1 && \\
&& \ddots & \ddots && \\
&& 1 & 4 & 1 & \\
\vdots &&& 1 & 4 & 1\\
0 & \cdots &&&& 1
\end{matrix}
\right]
\left[
\begin{matrix}
\dot{\boldsymbol{x}}_0\\
\dot{\boldsymbol{x}}_1\\
\vdots\\
\dot{\boldsymbol{x}}_{N-2}\\
\dot{\boldsymbol{x}}_{N-1}
\end{matrix}
\right]
=
\left[
\begin{matrix}
D_\text{begin}\\
3 (\boldsymbol{x}_2 - \boldsymbol{x}_0)\\
3 (\boldsymbol{x}_3 - \boldsymbol{x}_1)\\
\vdots\\
3 (\boldsymbol{x}_{N-2} - \boldsymbol{x}_{N-4})\\
3 (\boldsymbol{x}_{N-1} - \boldsymbol{x}_{N-3})\\
D_\text{begin}
\end{matrix}
\right]
\end{equation*}
Closed§
\begin{equation*}
\left[
\begin{matrix}
4 & 1 && \cdots & 0 & 1\\
1 & 4 & 1 && 0 & 0 \\
& 1 & 4 & 1 && \vdots \\
&& \ddots & \ddots && \\
\vdots && 1 & 4 & 1 & \\
0 & 0 && 1 & 4 & 1\\
1 & 0 & \cdots && 1 & 4
\end{matrix}
\right]
\left[
\begin{matrix}
\dot{\boldsymbol{x}}_0\\
\dot{\boldsymbol{x}}_1\\
\vdots\\
\dot{\boldsymbol{x}}_{N-2}\\
\dot{\boldsymbol{x}}_{N-1}
\end{matrix}
\right]
=
\left[
\begin{matrix}
3 (\boldsymbol{x}_1 - \boldsymbol{x}_{N-1})\\
3 (\boldsymbol{x}_2 - \boldsymbol{x}_0)\\
3 (\boldsymbol{x}_3 - \boldsymbol{x}_1)\\
\vdots\\
3 (\boldsymbol{x}_{N-2} - \boldsymbol{x}_{N-4})\\
3 (\boldsymbol{x}_{N-1} - \boldsymbol{x}_{N-3})\\
3 (\boldsymbol{x}_{0} - \boldsymbol{x}_{N-2})
\end{matrix}
\right]
\end{equation*}
Solving the System of Equations§
tridiagonal matrix algorithm
https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
https://www.cfd-online.com/Wiki/Tridiagonal_matrix_algorithm
https://gist.github.com/cbellei/8ab3ab8551b8dfc8b081c518ccd9ada9
https://gist.github.com/TheoChristiaanse/d168b7e57dd30342a81aa1dc4eb3e469