Cómo conservar el impulso al integrar numéricamente la trayectoria de una partícula cargada a través de un campo magnético

Tengo el script de python adjunto a continuación, que está destinado a rastrear la trayectoria de una partícula cargada en un campo magnético estático y uniforme. Es muy simple calcular la fuerza instantánea sobre la partícula (es solo el producto cruzado de su velocidad con el campo magnético, B), pero desafortunadamente mi intento súper simple de integrar numéricamente los efectos de esta fuerza no conserva el impulso. .

Entiendo por qué no. Si imagino que en t=0, el vector de velocidad es [1,0,0] (con B=[0,0,1]), entonces la fuerza instantánea aplicada será algo así como F_mag = [0,a,0 ], pero la integración numérica aplica esta fuerza durante más de un período infinitesimal y, por lo tanto, en el siguiente paso de tiempo, la velocidad será [1,a,0], donde a es un valor distinto de cero, que claramente tiene una magnitud mayor que [ 1,0,0]. Cada impulso de paso aumentará en un factor proporcional a la velocidad. El impulso no se conserva --- ¡explosión exponencial (vea la imagen a continuación)!

He estudiado este interesante artículo que parece estar abordando mi problema. Funciona a través de una forma de calcular la siguiente posición de la partícula dada su posición en los dos pasos de tiempo anteriores. Pero quiero calcular la fuerza que el campo magnético está aplicando a la partícula (ya que eventualmente quiero incluir otras fuerzas en mi modelo).

¿Existe una forma sencilla de calcular la fuerza aplicada por el campo magnético de tal manera que se conserve el impulso? Puedo hacer que el tamaño del paso sea más pequeño, pero aún así el impulso crece exponencialmente, ¡no es lo ideal! También podría simplemente cambiar a Runge-Kutta en lugar de la simple integración de Euler, ¡pero pensé que podría haber una oportunidad aquí para hacer algo más inteligente! ¡Gracias de antemano por cualquier sugerencia que pueda tener!

from pylab import * 

DT = 0.1 
N_ITS = int(100.0/DT)

pos    = array([0.0,0.0,0.0],'f')
vel    = array([1.0,0.0,0.0],'f') 
mass   = 1.0 
charge = 1.0

# uniform magnetic field
B = array([0.0,0.0,1.0])

# track momentum for plotting
mom_h = []
# track position for plotting
pos_h = []

for _ in xrange(N_ITS) :
    ## total momentum
    mom = linalg.norm(vel)
    mom_h.append(mom)
    pos_h.append(array(pos))

    ### fixed magnetic field
    F_mag = array(-cross(vel,B))

    ### apply force
    vel += DT*F_mag/mass

    ### update position
    pos += vel*DT

figure(figsize=(6,10))
subplot2grid((2,1),(0,0)) 
title('position') 
pos_h = array(pos_h)    
plot(pos_h[:,0],pos_h[:,1])

subplot2grid((2,1),(1,0))
title('momentum') 
plot(mom_h)

show()

ingrese la descripción de la imagen aquí

¿ Sería la ciencia computacional un mejor hogar para esta pregunta?
@Q Mechanical Dado el papel de la conservación del impulso en la pregunta, podría ser un tema aquí. Estoy viendo esta metapregunta y creo que está muy cerca del límite entre el tema y fuera del tema, pero no alcanza ninguno de los criterios que identificamos como fuera del tema. (He ido y venido en esta decisión a lo largo de los años).
Eliminé algunos comentarios que respondían a la pregunta.
@DavidZ Mmm... ¿por qué? Esto es bastante molesto. Vi información útil publicada aquí en respuesta a mi pregunta, pero ahora ya no puedo acceder a esa información. ¿A quién beneficia borrar esos comentarios?
@weemattisnot Ayuda a que el sitio se mantenga limpio. Esas personas deberían haber publicado respuestas, no comentarios, y aún pueden hacerlo.
Creo que eliminar comentarios que responden preguntas hace más mal que bien. Seguramente sería mejor animar a los autores a dar respuestas y eliminar sus propios comentarios después de que lo hayan hecho.
Por cierto, cuando haces un gráfico de posición-posición, generalmente es mejor usar una relación de aspecto 'igual' para que las distancias en diferentes direcciones sean todas iguales.

Respuestas (1)

Con el delantero Euler, simplemente no tienes suerte. Debido a la forma en que se construye el esquema, siempre se comete un error en la cantidad de movimiento en la misma dirección, que luego se agrava y conduce a un comportamiento exponencial. Necesita un integrador simpléctico, siendo el más simple Leapfrog o cualquier otro integrador de Verlet. Estos aún no conservarán el impulso en un paso de tiempo a paso de tiempo, pero en promedio sobre una "órbita", es decir, un giro alrededor de la hélice para su partícula. A partir de ahí, puede establecer el intervalo de tiempo para mantener el error de impulso por debajo de cierta tolerancia, si lo desea.