title Dynamics of a particle jupyter python3 ```{python} from functools import lru_cache import numpy as np from scipy.integrate import solve_ivp import matplotlib.pyplot as plt from mpl_toolkits import mplot3d from ipywidgets import interact, interactive, fixed, interact_manual import ipywidgets as widgets ``` ## Death Star dynamics (Dynamics & Relativity Sheet 1 Question 4) The equation of motion $$ \ddot{\mathbf{r}} = k \mathbf{r} \wedge \dot{\mathbf{r}} $$ could represent the dynamics of a charged particle moving under a magnetic field $$ \mathbf{B} = \frac{-km}{q} \mathbf{r} $$ with field lines pointing radially inwards. Hence a particle moving radially (in a straight line and parallel to a magnetic field line) will experience no force, and move with constant velocity. Because the magnetic force is always perpendicular to the direction of velocity, the force does no work on the particle and therefore the speed is constant. If the particle has a velocity component in an angular (non-radial) direction, then the magnetic force will cause the particle to execute a spiralling motion around a radial axis. The frequency of the spiralling and the angular momentum in fact increase with time, since, far from the origin, the magnetic field is very strong and points in a more uniform direction. Note that the high-frequency motion is not very well captured by the following numerical solutions: for example, [aliasing](https://en.wikipedia.org/wiki/Aliasing) is visible. ```{python} def fun(t, xu, k): x, u = xu[:3], xu[3:] return [*u, *(k * np.cross(x, u))] ``` ```{python} @interact( k=widgets.FloatSlider(min=0, max=30, value=6, continuous_update=False), r0=widgets.FloatSlider(min=0, max=4, value=1, continuous_update=False), v0_rad=widgets.FloatSlider(min=-2, max=2, value=0.5, continuous_update=False), v0_perp=widgets.FloatSlider(min=0, max=4, value=2, continuous_update=False), ) def death_star_demo(k, r0, v0_rad, v0_perp): sol = solve_ivp( fun, (0, 10), [r0, 0, 0, v0_rad, v0_perp, 0], args=(k,), # dense_output=True, t_eval=np.arange(0, 10, 0.01) ) assert sol.success, sol.message xs, ys, zs = sol.y[0, :], sol.y[1, :], sol.y[2, :] us, vs, ws = sol.y[3, :], sol.y[4, :], sol.y[5, :] fig = plt.figure(figsize=(14, 8)) ax = fig.add_subplot(121, projection="3d") ax.plot(xs, ys, zs) ax.set_xlim((-0.2, 3)) ax.set_ylim((-0.2, 3)) ax.set_zlim((-0.2, 3)) ax = fig.add_subplot(322) ax.plot(sol.t, xs, 'r', sol.t, ys, 'g', sol.t, zs, 'b') ax.plot(sol.t, (xs**2 + ys**2 + zs**2)**0.5, 'k') ax.grid() ax.legend(('$x$', '$y$', '$z$', r'$|\mathbf{x}|$',)) ax = fig.add_subplot(324) ax.plot(sol.t, us, 'r', sol.t, vs, 'g', sol.t, ws, 'b') ax.plot(sol.t, (us**2 + vs**2 + ws**2)**0.5, 'k') ax.grid() ax.legend(('$u$', '$v$', '$w$', r'$|\dot{\mathbf{x}}|$',)) ax = fig.add_subplot(326) ang_mom = ((ys * ws - zs * vs)**2 + (zs * us - xs * ws)**2 + (xs * vs - ys * us)**2) ** 0.5 ax.plot(sol.t, ang_mom, 'k') # ax.set_ylim((0, 6)) ax.legend((r'$|\mathbf{L}|$',)) ax.grid() # ax.set_xscale('log') # ax.set_yscale('log') ax.set_xlabel('$t$') plt.show() ``` ## Planar polar dynamics In planar polar coordinates $(r, \theta)$, the equations of motion are $$ \ddot{r} = \frac{1}{m} f_r + r \dot{\theta}^2 , \qquad \ddot{\theta} = \frac{1}{r} \left(\frac{1}{m} f_\theta - 2\dot{r}\dot{\theta} \right). $$ ## Gravitational field and radiation pressure (Dynamics & Relativity Sheet 2 Question 4) ```{python} def fun(t, y, mu): r, th, r_dot, th_dot = y if r < 0.05: return (0, 0, 0, 0) f_r = - 1 / r**2 - mu * r_dot f_th = - mu * r * th_dot r_ddot = f_r + r * th_dot**2 th_ddot = (1/r) * (f_th - 2 * r_dot * th_dot) return (r_dot, th_dot, r_ddot, th_ddot) tmax = 30 @lru_cache() def solver(mu, r0, v0): sol = solve_ivp( fun, (0, tmax), [r0, 0, 0, v0], args=(mu,), t_eval=np.arange(0, tmax, 0.01), method='Radau' ) assert sol.success, sol.message return sol ``` ```{python} @interact( mu=widgets.FloatSlider(min=0, max=2, value=0.1), r0=widgets.FloatSlider(min=0.1, max=2, value=1), v0=widgets.FloatSlider(min=-2, max=2, value=1) ) def radiation_pressure_demo(mu, r0, v0): sol = solver(mu, r0, v0) rs, ths, r_dots, th_dots = sol.y fig, ax = plt.subplots(figsize=(8, 8)) ax.set_facecolor("black") ax.plot( rs * np.cos(ths), rs * np.sin(ths), 'gray' ) ax.scatter( rs * np.cos(ths), rs * np.sin(ths), s=((sol.t-min(sol.t))/(max(sol.t) - min(sol.t)))*30, # s=2, c=sol.t, cmap='hot' ) ax.set_aspect('equal') xmin = ymin = -2 xmax = ymax = 2 ax.set_xlim((xmin, xmax)) ax.set_xticks(np.arange(xmin, xmax, 0.5)) ax.set_ylim((ymin, ymax)) ax.set_yticks(np.arange(ymin, ymax, 0.5)) ax.grid() plt.show() ``` ## A $1/r^3$ attractive force (Dynamics & Relativity Sheet 2 Question 6) ```{python} def fun(t, y, k): r, th, r_dot, th_dot = y if r < 0.05: return (0, 0, 0, 0) f_r = - k / r**3 f_th = 0 r_ddot = f_r + r * th_dot**2 th_ddot = (1/r) * (f_th - 2 * r_dot * th_dot) return (r_dot, th_dot, r_ddot, th_ddot) tmax = 30 @lru_cache() def solver(r0, v0, k): sol = solve_ivp( fun, (0, tmax), [r0, 0, 0, v0], args=(k,), t_eval=np.arange(0, tmax, 0.01), method='Radau' ) assert sol.success, sol.message return sol ``` ```{python} @interact( r0=widgets.FloatSlider(min=0.1, max=2, value=1), v0=widgets.FloatSlider(min=0, max=2, value=0.975, step=0.025), k=widgets.FloatSlider(min=0, max=2, value=1), ) def inverse_cube_demo(r0, v0, k): sol = solver(r0, v0, k) rs, ths, r_dots, th_dots = sol.y fig, ax = plt.subplots(figsize=(8, 8)) ax.set_facecolor("black") ax.plot( rs * np.cos(ths), rs * np.sin(ths), 'gray' ) ax.scatter( rs * np.cos(ths), rs * np.sin(ths), s=((sol.t-min(sol.t))/(max(sol.t) - min(sol.t)))*30, # s=2, c=sol.t, cmap='hot' ) ax.set_aspect('equal') xmin = ymin = -2 xmax = ymax = 2 ax.set_xlim((xmin, xmax)) ax.set_xticks(np.arange(xmin, xmax, 0.5)) ax.set_ylim((ymin, ymax)) ax.set_yticks(np.arange(ymin, ymax, 0.5)) ax.grid() plt.show() ```