Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
71 views
in Technique[技术] by (71.8m points)

python 3.x - How to plot computed values?

How to plot force lines one by one? Now, the slice plots an equal part of all force lines.

The desired result is to plot the shortest lines completely and do not draw the big force lines.

enter image description here

The code is:

import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import ode as ode

# Class for defining charge's position and magnitude
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]



# Defining charges
charges=[ charge(-2, [-0.1, 0]), charge(2, [0.1, 0])]
 
# Calculation of field lines
x0, x1=-3, 3
y0, y1=-3, 3
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:
        dt=-dt
    # loop over field lines starting in different directions around current charge
    for alpha in np.linspace(0, 2*np.pi*15/16, 16):
        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)
        while r.successful():
            r.integrate(r.t+dt)
            x.append(r.y[0])
            y.append(r.y[1])
            hit_charge=False
            # check if field line left drwaing area or 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 or (not (x0<r.y[0] and r.y[0]<x1)) or 
                    (not (y0<r.y[1] and r.y[1]<y1)):
                break
        xs.append(x)
        ys.append(y)


fig, ax = plt.subplots(figsize = (5,5))

# plot field line
for x, y in zip(xs,ys):
    plt.plot(x[:25], y[:25], color="k")

ax.set_xlim(-0.5, 0.5)
ax.set_ylim(-1, 1)
plt.show()

My question is related to # plot field line, xs and ys are generated in the loop before.

The code is composed of classes, a loop that computes xs and ys, and the plotting part follows.

question from:https://stackoverflow.com/questions/65871424/how-to-plot-computed-values

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Just print only those lines whose x coords are within the orginal charges x positions plus a certain tolerance eps (due to numerical errors):

eps = 1e-3
for x, y in zip(xs,ys):
    if min(x) >= charges[0].pos[0] - eps and max(x) <= charges[1].pos[0] + eps:
        plt.plot(x[:25], y[:25], color="k")

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...