<jupyter_start><jupyter_text>3D $\vec{v}\times\vec{B}$ acceleration:\begin{equation*}a_{\mathrm{Lorentz}} = \vec{v} \times \vec{\omega}\end{equation*}where\begin{equation*}\vec{\omega} = \begin{pmatrix}\frac{q B_x}{m} \\ \frac{q B_y}{m} \\ \frac{q B_z}{m}\end{pmatrix}\end{equation*}  Ford & O'Connel (1991) results in the following system of equations:\begin{equation*}\begin{pmatrix}1 & -\tau \omega_z & \tau \omega_y \\\tau \omega_z & 1 & -\tau \omega_x \\-\tau \omega_y & \tau \omega_x & 1\end{pmatrix}\begin{pmatrix}a_x \\ a_y \\ a_z\end{pmatrix} = \vec{v} \times \vec{\omega}\end{equation*}  Determinant of the matrix is $1 + \tau^2 \omega^2$  Inverse given by:\begin{equation*}M^{-1} = \frac{1}{1 + \tau^2 \omega^2}\begin{pmatrix}1 + \tau^2 \omega_x^2 & \tau^2 \omega_x \omega_y + \tau \omega_z & \tau^2 \omega_x \omega_z - \tau \omega_y\\\tau^2 \omega_x \omega_y - \tau \omega_z & 1 + \tau^2 \omega_y^2 & \tau^2 \omega_y \omega_z + \tau \omega_x\\\tau^2 \omega_x \omega_z + \tau \omega_y & \tau^2 \omega_z \omega_y - \tau \omega_x & 1 + \tau^2 \omega_z^2\end{pmatrix}\end{equation*}  So general form is:\begin{align*}\left(1 + \tau^2 \omega^2\right) a_x &= \omega_z v_y - \omega_y v_z  - \tau(\omega_z^2 + \omega_y^2) v_x + \tau \omega_x (\omega_z v_z + \omega_y v_y) \\\left(1 + \tau^2 \omega^2\right) a_y &= \omega_x v_z - \omega_z v_x  - \tau(\omega_z^2 + \omega_x^2) v_y + \tau \omega_y (\omega_z v_z + \omega_x v_x)\\\left(1 + \tau^2 \omega^2\right) a_z &= \omega_y v_x - \omega_y v_x  - \tau(\omega_x^2 + \omega_y^2) v_z + \tau \omega_z (\omega_x v_x + \omega_y v_y)\\\end{align*}  Solution to this is constant velocity in the direction of the magnetic field, plus rotation around.<jupyter_code># Test values
B = [0, 0, 1]
vel = [0, 1, 1]
q = 1
m = 1
tau = 0.025

solver = Ford1991Solver(charge=q, mass=m, b_field=B, tau=tau)
bmag = np.linalg.norm(B)
omega = bmag * q / m

# Calculate track for 3 rotations
time = np.linspace(0, 6.0 * np.pi / omega, 100)
x, y, z, _, _, _ = solver.analytic_solution(time)

# Plot results
fig = plt.figure(figsize=[18,12])
ax0 = fig.add_subplot(1,3,1, projection='3d')
ax0.plot(x, y, z)
ax0.view_init(elev=15, azim=-30)
ax1 = fig.add_subplot(1,3,2, projection='3d')
ax1.plot(x, y, z)
ax1.view_init(elev=0, azim=90)
ax2 = fig.add_subplot(1,3,3, projection='3d')
ax2.plot(x, y, z)
ax2.view_init(elev=90, azim=0)
B = [0, 1, 0]
vel = [0,1,1]
bmag = np.linalg.norm(B)
omega = bmag * q / m

# Calculate track for 3 rotations
time = np.linspace(0, 6.0 * np.pi / omega, 100)
solver = Ford1991Solver(charge=q, mass=m, b_field=B, tau=tau)
x, y, z, _, _, _ = solver.analytic_solution(time, v0=vel)

# Plot results
fig = plt.figure(figsize=[18,12])
ax0 = fig.add_subplot(1,3,1, projection='3d')
ax0.plot(x, y, z)
ax0.view_init(elev=15, azim=-30)
ax1 = fig.add_subplot(1,3,2, projection='3d')
ax1.plot(x, y, z)
ax1.view_init(elev=0, azim=90)
ax2 = fig.add_subplot(1,3,3, projection='3d')
ax2.plot(x, y, z)
ax2.view_init(elev=90, azim=0)
B = [0, 1, 1]
vel=[1,1,0]
bmag = np.linalg.norm(B)
omega = bmag * q / m

# Calculate track for 3 rotations
time = np.linspace(0, 6.0 * np.pi / omega, 100)
solver = Ford1991Solver(charge=q, mass=m, b_field=B, tau=tau)
x, y, z, _, _, _ = solver.analytic_solution(time, v0=vel)

# Plot results
fig = plt.figure(figsize=[18,12])
ax0 = fig.add_subplot(1,3,1, projection='3d')
ax0.plot(x, y, z)
ax0.view_init(elev=15, azim=-30)
ax0.set_xlabel('x')
ax0.set_ylabel('y')
ax0.set_zlabel('z')
ax1 = fig.add_subplot(1,3,2, projection='3d')
ax1.plot(x, y, z)
ax1.view_init(elev=0, azim=90)
ax2 = fig.add_subplot(1,3,3, projection='3d')
ax2.plot(x, y, z)
ax2.view_init(elev=90, azim=0)
B = np.array([0, 0, 1])
solver = Ford1991Solver(charge=q, mass=m, b_field=B, tau=tau)
vel0 = np.array([0,1,1])
res = solver.solve(3, v0=vel0)
x = res.y[0]
y = res.y[1]
z = res.y[2]
fig = plt.figure(figsize=[18,12])
ax0 = fig.add_subplot(1,3,1, projection='3d')
ax0.plot(x, y, z)
ax0.view_init(elev=15, azim=-30)
ax1 = fig.add_subplot(1,3,2, projection='3d')
ax1.plot(x, y, z)
ax1.view_init(elev=0, azim=90)
ax2 = fig.add_subplot(1,3,3, projection='3d')
ax2.plot(x, y, z)
ax2.view_init(elev=90, azim=0)
B = np.array([0, 1, 0])
solver = Ford1991Solver(charge=q, mass=m, b_field=B, tau=tau)
vel0 = np.array([0,1,1])
res = solver.solve(3, v0=vel0)
x = res.y[0]
y = res.y[1]
z = res.y[2]
fig = plt.figure(figsize=[18,12])
ax0 = fig.add_subplot(1,3,1, projection='3d')
ax0.plot(x, y, z)
ax0.view_init(elev=15, azim=-30)
ax1 = fig.add_subplot(1,3,2, projection='3d')
ax1.plot(x, y, z)
ax1.view_init(elev=0, azim=90)
ax2 = fig.add_subplot(1,3,3, projection='3d')
ax2.plot(x, y, z)
ax2.view_init(elev=90, azim=0)
B = np.array([0, 1, 1])
solver = Ford1991Solver(charge=q, mass=m, b_field=B, tau=tau)
vel0 = np.array([1,1,0])
res = solver.solve(3, v0=vel0)
x = res.y[0]
y = res.y[1]
z = res.y[2]
fig = plt.figure(figsize=[18,12])
ax0 = fig.add_subplot(1,3,1, projection='3d')
ax0.plot(x, y, z)
ax0.view_init(elev=15, azim=-30)
ax1 = fig.add_subplot(1,3,2, projection='3d')
ax1.plot(x, y, z)
ax1.view_init(elev=0, azim=90)
ax2 = fig.add_subplot(1,3,3, projection='3d')
ax2.plot(x, y, z)
ax2.view_init(elev=90, azim=0)
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_zlabel('z')
x, y, z, vx, vy, vz = solver.analytic_solution(res.t, v0=vel0)
error_plot(res.t, res.y[0], y_exact=x, ylabel='x', xlabel='t')
error_plot(res.t, res.y[1], y_exact=y, ylabel='y', xlabel='t')
error_plot(res.t, res.y[2], y_exact=z, ylabel='z', xlabel='t')
plt.plot(res.t, res.y[0] - x, label='Error(x)')
plt.plot(res.t, res.y[1] - y, label='Error(y)')
plt.plot(res.t, res.y[2] - z, label='Error(z)')
plt.xlim(left=0.0)
plt.legend()
plt.tight_layout()
# Try non-default initial position
x0 = np.ones(3)
res = solver.solve(3, x0=x0, v0=vel0)
x, y, z, vx, vy, vz = solver.analytic_solution(res.t, x0=x0, v0=vel0)
plt.plot(res.t, res.y[0] - x, label='Error(x)')
plt.plot(res.t, res.y[1] - y, label='Error(y)')
plt.plot(res.t, res.y[2] - z, label='Error(z)')
plt.xlim(left=0.0)
plt.legend()
plt.tight_layout()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.21695925803246108, 'fraction_numerical': 0.06591586618085458, 'mean_word_length': 4.6757518796992485, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '594959', 'license': 'MIT', 'n_tokens_mistral': 3075, 'n_tokens_neox': 2926, 'n_words': 567, 'path': 'python/Ford1991_3D.ipynb', 'repo_name': 'QTNM/Electron-Tracking', 'size': '6038'}