Question #175539

Write a GUI to visualize electric field lines of point charges located in a plane.


The functionality the program should provide

  • Positive and negative point charges are displayed as blue and red dots, respectively.
  • The area of the dot is proportional to the magnitude of the charge.
  • 32 field lines emerge from each positive charge
  • A left-mouse press and release on a charge deletes the charge
  • A left-mouse press not on a charge followed by a mouse motion adds a charge as follows:
  •  location of new charge is the mouse-press position.
  •  magnitude of the charge is round(dx), where dx is the x-positional difference between location of mouse-release and mouse-press. 
  • A left-mouse press on a charge followed by a mouse motion drags the charge resulting in:
  • charges being redrawn,
  • field lines being recalculated and displayed.
  • For better responsiveness, in dragging mode only 8 field lines per charge are used and only the changed elements of the figure are redrawn, not the full figure.

Expert's answer

import matplotlib.pyplot as plt
import numpy as np
import plot.offline as py
from scipy.integrate import ode as ode
py.init_notebook_mode()

class charge:
    def __init__(self, q, pos):
        self.q = q
        self.pos = pos


def E_point_charge(q, a, x, y):
    return q * (x - a[0]) / ((x - a[0]) ** 2 + (y - a[1]) ** 2) ** (1.5), \
           q * (y - a[1]) / ((x - a[0]) ** 2 + (y - a[1]) ** 2) ** (1.5)


def E_total(x, y, charges):
    Ex, Ey = 0, 0
    for C in charges:
        E = E_point_charge(C.q, C.pos, x, y)
        Ex = Ex + E[0]
        Ey = Ey + E[1]
    return [Ex, Ey]


def E_dir(t, y, charges):
    Ex, Ey = E_total(y[0], y[1], charges)
    n = np.sqrt(Ex ** 2 + Ey * Ey)
    return [Ex / n, Ey / n]


#--- part 3-------------


charges = [charge( 1, [0.56, 0.56]),
           charge(-1, [0.26, 0.76]),
           charge( 1, [0.66, 0.16]),
           charge(-1, [0.66, 0.86]) ]

# calculate field lines
R = 0.01
# loop over all charges
xs, ys = [], []
for C in charges:
    # plot field lines starting in current charge
    dt = 0.8*R
    if C.q < 0:
       
        continue
    # loop over field lines starting in different directions
    # around current charge
    for alpha in np.linspace(0, 2*np.pi*31/32, 32):
        r = ode(E_dir)
        r.set_integrator('vode')
        r.set_f_params(charges)
        x = [ C.pos[0] + np.cos(alpha)*R ]
        y = [ C.pos[1] + np.sin(alpha)*R ]
        r.set_initial_value([x[0], y[0]], 0)
        cnt = 0
        while r.successful():
            Enorm = E_total(r.y[0],r.y[1],charges)
            Enorm = (Enorm[0]**2 + Enorm[1]**2)**0.5
            a = 5
            dt = R*a*Enorm**(-0.4)
            #if cnt % 1000 == 0:
            #    print(r.y[0],r.y[1],Enorm,dt2)
            #cnt += 1
            r.integrate(r.t+dt)
            x.append(r.y[0])
            y.append(r.y[1])
            hit_charge=False
            # check if field line ends in some charge
            for C2 in charges:
                if np.sqrt((r.y[0]-C2.pos[0])**2+(r.y[1]-C2.pos[1])**2)<R:
                    hit_charge = True
            if hit_charge:
                break
        xs.append(x)
        ys.append(y)

#----- part 4---------------
fig = plt.figure(figsize=(7, 7),facecolor="w")
ax = fig.add_subplot(111)

# plot field line
for x, y in zip(xs,ys):
    ax.plot(x, y, color="k",lw=0.8)

# plot point charges
for C in charges:
    if C.q>0:
        ax.plot(C.pos[0], C.pos[1], 'ro', ms=10*np.sqrt(C.q))
    if C.q<0:
        ax.plot(C.pos[0], C.pos[1], 'bo', ms=10*np.sqrt(-C.q))


ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_aspect('equal','datalim')
plt.savefig('electric_field_lines_pyplot_wo_mayavi.png',
            dpi=250,bbox_inches="tight",pad_inches=0.02)
plt.show()

Need a fast expert's response?

Submit order

and get a quick answer at the best price

for any assignment or question with DETAILED EXPLANATIONS!

LATEST TUTORIALS
APPROVED BY CLIENTS