#!/usr/bin/env python # coding: utf-8 # # Homework 2 # **due 09/19/2018 at 11:59pm** # # ## Problem 1 # 1. Write a piece of code to compare the deviation between `ODE_integration_exponential_integrator` and the actual Larmor radius. We call the difference between them the error $e$. # 2. Vary the number of time steps and the number of integration steps and plot how the error $e$ varies as a function of both. # 3. What can you conclude? # # ## Problem 2 # When electric fields and magnetic fields are presents, charged particles do not simply gyrate, they move along the electric field direction also. When the electric field is purely perpendicular to B, the charge particle is said to drift, hence the name *ExB drift*. We are going to use `ODE_integration_exponential_integrator` to compute the drift velocity of an electron inside a magnetic field $\vec B=(0,0,1)$ and in an electric field $\vec E=(100,0,0)$. # 1. Compute analytically the gyration period $t_{Larmor}$ # 2. What is its numerical value? # 3. Starting with $t_{initial}=0$ and ending at $t_{final}=5\,t_{Larmor}$, find the distance traveled by the electron and infer the velocity from this value. # 4. Redo 1,2 and 3 for a proton. Is the proton traveling in the same direction? # # ## Problem 3 # If you remember we had a little problem with `OED_integration_E`. If we integrated our ODE for too long, then an electron inside a 1V electric field would eventually go faster than the speed of light. `ODE_integration_exponential_integrator` takes into account relativistic correction and really avoid this problem. # 1. Using the exact same initial values of position and velocity, find out what is the velocity of the electron after 3s. If it does go faster than the speed of light, increase the number of time steps. # # Let's imagine that you want to build a particle accelerator using a steady electric field of $1kV/m$ to accelerate an electron to $0.999c_{light}$ # 2. How long should the accelerator be? # 2. How long should it be if you ignore relativistic corrections, i.e. use `OED_integration_E`? # In[1]: import math from math import sqrt as sqrt import numpy as np from scipy.linalg import expm from numpy.linalg import norm import matplotlib.pyplot as plt import matplotlib.colors as colors #to display inside the notebook! get_ipython().run_line_magic('matplotlib', 'inline') # # Solutions # ## Problem 1 # Let's look first at the impact of the impact of number of time steps and integration steps on `ODE_integration_exponential_integrator`. For that we need to generate a two dimensional grid holding both the number of time steps and the number of iteration steps. We can reuse part of `comp_E` from HW01-Problem 3 to do that. First, let's import all the required functions. # In[2]: def get_E(r,t): return np.array([0,0,0]) def get_B(r,t): return np.array([0,0,1]) def Lorentz_factor(v): v2=norm(v)**2 c=299792458 return 1./sqrt(1-v2/c**2) def EM_field_tensor(E,B): c=299792458 F_mu_nu=np.array([0,E[0]/c,E[1]/c,E[2]/c,E[0]/c,0,-B[2],B[1],E[1]/c,B[2],0,-B[0],E[2]/c,-B[1],B[0],0]) F_mu_nu.shape=(4,4) return F_mu_nu # Now, we load `ODE_integration_exponential_integrator`. # In[3]: def ODE_integration_exponential_integrator(initial_position,initial_velocity,time_frame,n_steps,n_integrate): c=299792458 loc=np.zeros((3,n_steps)) #3 for x,y,z loc[:,0]=initial_position v=initial_velocity gamma=Lorentz_factor(v) p_old=np.array([m*c,m*v[0],m*v[1],m*v[2]])*gamma p_new=np.zeros(4) t=0 dt=(time_frame[1]-time_frame[0])/n_steps ds=dt/n_integrate for i in range(1,n_steps,1): #solution of the momentum equation B=get_B(loc[:,i-1],t) E=get_E(loc[:,i-1],t) F_mu_nu=EM_field_tensor(E,B) p_new=np.matmul(expm(q/(m*gamma)*F_mu_nu*dt),p_old) gamma=p_new[0]/(m*c) P=np.zeros((4,4)) s=0. dPds=np.eye(4)*ds/2 x=np.zeros(4) for j in range(0,n_integrate,1): #trapezoidal integration to get the trajectory s+=ds if (i>0): P+=dPds dPds=expm(q/(m*gamma)*F_mu_nu*s)*ds/2 if (i==0): P+=dPds P+=dPds x=np.matmul(P,p_old)/(m*gamma) loc[:,i]=x[1:4]+loc[:,i-1] #new position p_old=p_new t+=dt return loc # We will keep the same initial conditions as the ones used in Ch02. The charged particle will start at $(0,0,0)$ so we can get the Larmor radius easily, by taking the maximum value along the x-direction. We use the gyration period `t_gyration` as our time unit, though it is not required as long as the run the integration by more than several periods. # In[4]: m=9e-31 q=-1.6e-19 r_initial=np.array([0,0,0]) v_initial=np.array([1000,0,0]) t_gyration=m/(abs(q)*norm(get_B(r_initial,0)))*(2*math.pi) r_Larmor=norm(v_initial)*m/(abs(q)*norm(get_B(r_initial,0))) time_frame=[0,2*t_gyration] # We now write the loop to compute the error for both integration steps. # In[5]: def comp_error(steps,n): X=np.zeros(n) Y=np.zeros(n) err=np.zeros(n) k=0 l=0 for i in range(steps[0],steps[1],int((steps[1]-steps[0])/n[0])): if (k