Code: Select all
%matplotlib ipympl
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
def ODE_r(x, t, params):
r, d1t_r = x
q, m, U_0, w, r_0 = params
derivs = [d1t_r,
-1 * (q / m) * U_0 * np.sin(w * t) * (r / r_0)]
return derivs
def ODE_z(y, t, params):
z, d1t_z = y
q, m, U_0, w, r_0 = params
derivs = [d1t_z,
(q / m) * U_0 * np.sin(w * t) * 2 * (z / r_0)]
return derivs
q = 1 # Mass of particle
q_u = sp.constants.e # Unit in e (C)
m = 1836 # Mass of particle
m_u = sp.constants.m_e # Unit in electron mass (kg)
U_0 = 10 # Amplitude of AC voltage
U_0_u = 1 # Unit in V
w = 4000 # Frequency of AC voltage
w_u = 1 # Unit in Hz
r_0 = 1000 # Geometrical factor
r_0_u = 1 # Unit?
# Initial values in m und m/s
r0 = 2e-6
d1t_r0 = 1e-3
z0 = -1e-6
d1t_z0 = 1e-3
# Define parameters for ODE solver and slider
def params(q, m, U_0, w, r_0):
func = [q*q_u, m*m_u, U_0*U_0_u, w*w_u, r_0]
return func
# Initial values for ODE solver
x0 = [r0, d1t_r0]
y0 = [z0, d1t_z0]
# Time array for solution (in s)
tStop = 0.1
tInc = 0.00005
Zeit = np.arange(0, tStop, tInc)
# Define numeric solution
def r_n(f, v0, t, parameters):
func = sp.integrate.odeint(f, v0, t, args=(parameters,))
return func[:,0]
def z_n(f, v0, t, parameters):
func = sp.integrate.odeint(f, v0, t, args=(parameters,))
return func[:,0]
fig = plt.figure(figsize=(8, 11), dpi=100)
ax = fig.add_subplot(111)
# Adjust the subplots region to leave some space for the sliders and buttons
fig.subplots_adjust(left=0.15, bottom=0.4)
# Draw the initial plot
# The 'line' variable is used for modifying the line later
[line] = ax.plot(r_n(ODE_r, x0, Zeit, params(q, m, U_0, w, r_0)), z_n(ODE_z, y0, Zeit, params(q, m, U_0, w, r_0)),
marker=',',
linestyle='-',
color='#008080',
label='trajectory')
#ax.set_xlim([0, 1])
#ax.set_ylim([-10, 10])
plt.xlabel('r / m')
plt.ylabel('z / m')
plt.title('Particle trajectory in the r - z plane of a Paul trap',
fontsize=12)
# plt.legend(loc='best', fancybox=True, shadow=True)
plt.grid(True)
# Sliders for tweaking the parameters
axis_color = 'lightgoldenrodyellow'
q_slider_ax = fig.add_axes([0.25, 0.3, 0.65, 0.03], facecolor=axis_color)
q_slider = Slider(q_slider_ax, 'q / e', -1, 10, valinit=q, valfmt='%0.0f')
m_slider_ax = fig.add_axes([0.25, 0.25, 0.65, 0.03], facecolor=axis_color)
m_slider = Slider(m_slider_ax, 'm / m_e', 1, 2000, valinit=m, valfmt='%0.0f')
U_slider_ax = fig.add_axes([0.25, 0.2, 0.65, 0.03], facecolor=axis_color)
U_slider = Slider(U_slider_ax, 'U_0 / V', 1, 100, valinit=U_0, valfmt='%0.0f')
w_slider_ax = fig.add_axes([0.25, 0.15, 0.65, 0.03], facecolor=axis_color)
w_slider = Slider(w_slider_ax, 'Freq / Hz', 1, 10000, valinit=w, valfmt='%0.0f')
r_slider_ax = fig.add_axes([0.25, 0.1, 0.65, 0.03], facecolor=axis_color)
r_slider = Slider(r_slider_ax, 'r_0', 1, 10000, valinit=r_0, valfmt='%0.0f')
# Define an action for modifying the line when any slider's value changes
def sliders_on_changed(val):
line.set_xdata(r_n(ODE_r, x0, Zeit, params(q.val, m.val, U_0.val, w.val, r_0.val)))
line.set_ydata(z_n(ODE_z, y0, Zeit, params(q.val, m.val, U_0.val, w.val, r_0.val)))
fig.canvas.draw_idle()
q_slider.on_changed(sliders_on_changed)
m_slider.on_changed(sliders_on_changed)
U_slider.on_changed(sliders_on_changed)
w_slider.on_changed(sliders_on_changed)
r_slider.on_changed(sliders_on_changed)
# Add a button for resetting the parameters
reset_button_ax = fig.add_axes([0.8, 0.05, 0.1, 0.04])
reset_button = Button(reset_button_ax, 'Reset', color=axis_color, hovercolor='0.975')
def reset_button_on_clicked(mouse_event):
q_slider.reset()
w_slider.reset()
reset_button.on_clicked(reset_button_on_clicked)
plt.show()
Ich muss eine Teilchenbahn in einer Paul-Falle zeichnen, indem ich zwei ODEs zweiter Ordnung numerisch integriere.
Problem:
Der größte Teil des Codes funktioniert wie vorgesehen. Das Problem tritt beim Schieberegler auf.
Ich kann mit dem Schieberegler interagieren, aber der Plot wird nicht aktualisiert, zumindest scheint es so.
Die wahrscheinlichsten Probleme sind meiner Meinung nach :
- Entweder funktionieren die Schieberegler, aber der neue Plot liegt außerhalb des Bereichs. Auch der Maßstab muss geändert werden. Ist es möglich, wie beim Zurücksetzen eine Schaltfläche für die automatische Skalierung hinzuzufügen?
- Oder die Schieberegler funktionieren nicht. Ich bin mir nicht sicher, warum. Vielleicht hängt es mit der numerischen Integration zusammen? Wie kann ich das Problem dann beheben?