4.6 Linear systems in software
Software 4.6.1 (Liouville’s formula). For \(x'' + 0.2x' + (1 + 0.5\cos t)x = 0\), a damped oscillator with a periodically varying stiffness, the fundamental matrix is computed by integrating \(\Phi ' = A(t)\Phi \) from \(\Phi (0) = I\); here \(\tr A = -0.2\):
>>> import numpy as np >>> from scipy.integrate import solve_ivp >>> A = lambda t: np.array([[0.0, 1.0], [-(1 + 0.5 * np.cos(t)), -0.2]]) >>> def fund(t, z): # Phi' = A(t) Phi, Phi(0) = I ... return (A(t) @ z.reshape(2, 2)).ravel() ... >>> sol = solve_ivp(fund, (0, 20), np.eye(2).ravel(), rtol=1e-11, atol=1e-13, ... dense_output=True) >>> for t in (5.0, 10.0, 20.0): ... Phi = sol.sol(t).reshape(2, 2) ... print(t, round(np.linalg.det(Phi), 8), round(np.exp(-0.2 * t), 8)) ... 5.0 0.36787944 0.36787944 10.0 0.13533528 0.13533528 20.0 0.01831564 0.01831564
Reading the output. The determinant of the numerically computed \(\Phi (t)\) equals \(e^{-0.2t}\) to eight decimals at every time, although \(\Phi \) itself has no closed form: the stiffness varies with time, but only the trace matters for the volume. This is a useful check on numerical work: a computed fundamental matrix whose determinant drifts from Liouville’s value has accumulated error.
MATLAB/Octave: integrate @(t, z) reshape(A(t)*reshape(z, 2, 2), 4, 1) with ode45 from reshape(eye(2), 4, 1).
Software 4.6.2 (Variation of parameters). For \(y'' + y = \sec t\) on \((-\pi /2, \pi /2)\), with \(y_1 = \cos t\), \(y_2 = \sin t\):
>>> import sympy as sp
>>> t = sp.symbols('t')
>>> y1, y2, g = sp.cos(t), sp.sin(t), 1 / sp.cos(t) # y'' + y = sec t
>>> W = sp.simplify(y1 * y2.diff(t) - y2 * y1.diff(t)); W
1
>>> yp = sp.simplify(-y1 * sp.integrate(y2 * g / W, t)
... + y2 * sp.integrate(y1 * g / W, t)); yp
t*sin(t) + log(cos(t))*cos(t)
>>> sp.simplify(yp.diff(t, 2) + yp - g)
0
Reading the output. The Wronskian is \(1\), and the particular solution is \(y_p = t\sin t + \cos t\log \cos t\), which the last line confirms by substitution. The method of undetermined coefficients cannot produce this, because \(\sec t\) is not of the exponential-polynomial form it requires.
MATLAB/Octave: syms y(t); dsolve(diff(y, 2) + y == sec(t)).
Software 4.6.3 (A non-commuting coefficient matrix). For \(B(t) = \begin {bmatrix} 1 & t\\ 0 & 0\end {bmatrix}\), compare the true transition matrix \(\Phi (1, 0)\) with \(\exp \int _0^1B(s)\,ds\):
>>> from scipy.linalg import expm >>> B = lambda t: np.array([[1.0, t], [0.0, 0.0]]) >>> intB = lambda t: np.array([[t, t**2 / 2], [0.0, 0.0]]) >>> B(1.0) @ intB(1.0) - intB(1.0) @ B(1.0) # they do not commute array([[ 0. , -0.5], [ 0. , 0. ]]) >>> Phi = solve_ivp(lambda t, z: (B(t) @ z.reshape(2, 2)).ravel(), (0, 1), ... np.eye(2).ravel(), rtol=1e-12, atol=1e-13).y[:, -1] >>> np.round(Phi.reshape(2, 2), 6), np.round(expm(intB(1.0)), 6) (array([[2.718282, 0.718282], [0. , 1. ]]), array([[2.718282, 0.859141], [0. , 1. ]]))
Reading the output. \(B(1)\) and \(\int _0^1B\) do not commute, and the two matrices differ in their top-right entry: the true value is \(e - 2 = 0.718282\), obtained by solving \(x_2 = c\), \(x_1' = x_1 + tc\) directly, while the exponential gives \((e - 1)/2 = 0.859141\). Proposition 4.5.1 cannot be used without checking commutativity.
MATLAB/Octave: expm([1 0.5; 0 0]) for the exponential.
Questions on this section
Stuck on something here? Ask below and it stays attached to this topic.