下面是一个我已经工作了几个星期的模型,随着我学习如何编码(给新手编码),慢慢地增加了更多的复杂性。如果不清楚的话,我试图建立一个由两种不同密度的粒子组成的模型,它们根据斯托克斯沉降速度(作为浓度的函数)沉降。我有麻烦让动画与第二个粒子(工作代码与一个动画粒子在底部)。为了调试代码,我分解了两个不同粒子的变量,但没有运气确定我做错了什么。在
任何帮助将不胜感激!在
import numpy as np
import matplotlib.pyplot as plt
from pylab import *
from matplotlib.animation import FuncAnimation
import random
import pdb
from scipy import spatial
from scipy.spatial import KDTree
n = 100
n2 = 50
sigma = 0.01
sigma2 = 0.01
pp = 2.56 # pp = particle density (Sphene=3.53) #(Feldspar=2.56)
#(g/cm^3)
pp2 = 3.53
pf = 2.7 # pf = fluid density(g/cm^3)
pf2 = 2.7
g = 9.8 # g = gravity (m/s^2)
g2 = 9.8
r = 0.003 # r = radius of sphere (meter)
r2 = 0.0002
mu = 0.53 # mu = dynamic viscosity of fluid (log10Poise)
mu2 = 0.53
rp = 0.01 #radius around particle to check for nearest neighbor
rp2 = 0.001
dt = 0.008
dt2 = 0.008
fig, ax = plt.subplots()
az = plt.axes(xlim=(-.5, .5), ylim=(-1, 0))
xdata, ydata = [0.0], [0.0]
xdata2, ydata2 = [0.0], [0.0]
ln, = plt.plot([], [], marker= 'o',
markerfacecolor='r',markeredgecolor='k', linestyle='None',
animated=True)
ln2, = plt.plot([], [], marker= 's',
markerfacecolor='b',markeredgecolor='k', linestyle='None',
animated=True)
#pdb.set_trace()
def v_stokes(pp,pf,g,r,mu):
top=2*(pp-pf)*g*(r**2)
bottom=9*mu
ws=top/bottom
return ws
def v_stokes2(pp2,pf2,g2,r2,mu2):
top2=2*(pp2-pf2)*g2*(r2**2)
bottom2=9*mu2
ws2=top2/bottom2
return ws2
def init():
ax.set_xlim( -2, 2)
ax.set_ylim(-10, 0)
return ln, ln2,
def concentration(xdata, ydata, rp):
coords = list(zip(xdata, ydata))
tree = spatial.KDTree(coords)
test = np.column_stack([xdata, ydata])
nnl = tree.query_ball_point(test, rp) #nearest neighbors as a list
#(had tree in here before test but shape was wrong)
#pdb.set.trace()
nnt = np.zeros(len(nnl)) #nearest neighbors total
for i in range(len(nnt)):
nnt[i] = len(nnl[i])
return nnt
def concentration2(xdata2, ydata2, rp2):
coords2 = list(zip(xdata2, ydata2))
tree2 = spatial.KDTree(coords2)
test2 = np.column_stack([xdata2, ydata2])
nnl2 = tree2.query_ball_point(test2, rp2)
nnt2 = np.zeros(len(nnl2)) #nearest neighbors total
for i in range(len(nnt2)):
nnt2[i] = len(nnl2[i])
return nnt2
#y0 = []
#y1 = []
#y2 = []
#y3 = []
#y4 = []
def update(frame):
global xdata
global ydata
global concentration, v_stokes, pp, pf, g, r, mu, rp, dt, n, sigma
xdata = xdata + np.random.normal(0, sigma, n)
wss = v_stokes(pp,pf,g,r,mu)
if frame == 0.0:
ydata = np.zeros(len(xdata)) #makes the ydata length = xdata at
#time 0 print(ydata)
rp = 0.003
if frame > 10:
rp = 0.008
cp = concentration(xdata, ydata, rp)
if np.any(cp == 1):
cp = cp-1
if frame > 0.0:
#y0.append(ydata)
#y1.append(wss)
#y2.append(cp)
#y3.append(dt)
#y4.append(xdata)
ydata = ydata + (wss*(1-cp)**3) - dt # [0]
for v in ydata:
if v < -1.001:
ydata = -1
ln.set_data(xdata, ydata)
return ln,
def update2(frame2):
global xdata2
global ydata2
global concentration2, v_stokes2, pp2, pf2, g2, r2, mu2, rp2, dt2,
n2, sigma2
xdata2 = xdata2 + np.random.normal(0, sigma2, n2)
wss2 = v_stokes2(pp2,pf2,g2,r2,mu2)
if frame2 == 0.0:
ydata2 = np.zeros(len(xdata2)) #makes the ydata length = xdata
#at time 0 print(ydata)
rp2 = 0.003
if frame2 > 10:
rp2 = 0.008
cp2 = concentration2(xdata2, ydata2, rp2)
if np.any(cp2 == 1):
cp2 = cp2-1
if frame2 > 0.0:
#y5.append(ydata2)
#y6.append(wss2)
#y7.append(cp2)
#y8.append(dt2)
#y9.append(xdata2)
ydata2 = ydata2 + (wss2*(1-cp2)**3) - dt2 # [0]
for v2 in ydata2:
if v2 < -1.001:
ydata2 = -1
ln2.set_data(xdata2, ydata2)
return ln2,
def update_all(i):
l1 = update(i)
l2 = update2(i)
return l1, l2,
ani = FuncAnimation(fig, update_all, frames=range(0,200),
init_func=init, blit=True, interval=100, repeat =
False)
# change frames=range(0:1000) to change the number of frames
plt.show()
下面是一个动画粒子的原始工作代码:
^{pr2}$
Tags:
^{} 期望第二个参数是一个可调用的(例如函数)来更新绘图。在
如果要更新两个函数,则需要将它们合并为一个函数
请注意,您需要以与通常相同的方式定义
plot
,并且需要在两个更新函数中返回line对象本身。在完整运行代码:
由于这两个粒子类的代码似乎大部分都是多余的,我建议通过将其放入一个类来简化它。在
import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from scipy import spatial n=100 sigma= 0.01 pp = 2.56 # pp = particle density (Sphene=3.53) #(Feldspar=2.56) #(g/cm^3) pp2 = 3.53 pf = 2.7 # pf = fluid density(g/cm^3) pf2 = 2.7 g = 9.8 # g = gravity (m/s^2) g2 = 9.8 r = 0.003 # r = radius of sphere (meter) r2 = 0.0002 mu = 0.53 # mu = dynamic viscosity of fluid (log10Poise) mu2 = 0.53 rp = 0.01 #radius around particle to check for nearest neighbor rp2 = 0.001 dt = 0.008 dt2 = 0.008 class Particles(): def __init__(self,ax, xdata, pp, pf, g, r, mu, rp, dt, n, marker="o",mfc="r"): self.xdata=xdata self.ydata = np.zeros(len(self.xdata)) self.pp=pp;self.pf=pf;self.g=g;self.r=r;self.mu=mu self.rp=rp;self.dt=dt;self.n=n self.ln, = ax.plot([], [], marker= marker, markerfacecolor=mfc,markeredgecolor='k', linestyle='None', animated=True) def v_stokes(self, pp,pf,g,r,mu): top=2*(pp-pf)*g*(r**2) bottom=9*mu return top/bottom def concentration(self,xdata, ydata, rp): coords = list(zip(xdata, ydata)) tree = spatial.KDTree(coords) test = np.column_stack([xdata, ydata]) nnl = tree.query_ball_point(test, rp) nnt = np.zeros(len(nnl)) #nearest neighbors total for i in range(len(nnt)): nnt[i] = len(nnl[i]) return nnt def update(self, frame): self.xdata += np.random.normal(0, sigma, n) if frame == 0: self.ydata = np.zeros(len(self.xdata)) wss = self.v_stokes(self.pp,self.pf,self.g,self.r,self.mu) cp = self.concentration(self.xdata, self.ydata, self.rp) if np.any(cp == 1): cp = cp-1 if frame > 0.0: self.ydata += (wss*(1-cp)**3) - dt for j,v in enumerate(self.ydata): if v < -1.001: self.ydata[j] = -1 self.ln.set_data(self.xdata, self.ydata) return self.ln fig, ax = plt.subplots() xdata, xdata2 = [0.0], [0.0] p1 = Particles(ax,xdata, pp, pf, g, r, mu, rp, dt, n, marker="o",mfc="r") p2 = Particles(ax,xdata2, pp2, pf2, g2, r2, mu2, rp2, dt2, n, marker="s",mfc="b") def init(): ax.set_xlim(-2, 2) ax.set_ylim(-1, 1) return p1.ln, p2.ln def update(i): l1 = p1.update(i) l2 = p2.update(i) return l1, l2 ani = FuncAnimation(fig, update, frames=range(0,200), init_func=init, blit=True, interval=100, repeat = False) plt.show()
;