模拟由两个相对磁铁产生的无场点中的磁性粒子

计算科学 Python 流体动力学 计算物理学 电磁学
2021-12-14 05:43:10

在此处输入图像描述在这么短的时间内,这可能是一个长镜头,但我一直在努力为我正在从事的项目获取理论数据。该项目涉及使用非常简化的磁粉成像版本来分析流体。

因此,我在一些帮助下编写了一些代码,并且我很确定所有物理特性都是正确的,但是当我以 5E-5 的时间步长 (deltaT) 运行它时,代码会计算数千量级的速度,而它应该是以毫米每秒为单位。但是当代码的时间步长为 5E-6 时,它可以正确运行。问题是在这个时间步完成这些模拟所花费的时间很长,在我的实际实验中,其中一些花费了 20 多分钟。

基本上,我想知道是否有可能在这个时间步显着减少运行时间或能够增加模拟的时间步长。

这是我的代码:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation


#Arrays for storing time
#t1 = [0]
#t2 = [0]
#t3 = [0]
#t4 = [0]
#t5 = [0]
t6 = [0]

#Time Increment
deltaT = 5E-7
#Number of Particles
N = 100

#Viscosity
mu_w = 0.0010049
mu = 3*mu_w

#Geometry
radius = 0.0095
d = 0.023
L = 0.02

#Constants
mu_0 = 1.25663706E-6

#Particle Properties
p_rad = (4.9E-6)/2
m = 1.663223552E-13
moment = 60*m

x, y = np.mgrid[-1.15:1.15:151j, -1:1:151j]*1E-2

#Method for Magnetic Field
def B(x,y):
    H11 = 4/((L+2*y)*np.sqrt((4*(d-2*x)**2/(L+2*y)**2+4)))

    H12 = 4/((L+2*y)*np.sqrt((4*(d+2*x)**2/(L+2*y)**2+4)))

    H13 = 4/((L-2*y)*np.sqrt((4*(d+2*x)**2/(L-2*y)**2+4)))

    H14 = 4/((L-2*y)*np.sqrt((4*(d-2*x)**2/(L-2*y)**2+4)))

    H21 = 1/((d-2*x)**2*(np.sqrt(4*(d-2*x)**2/(L-2*y)**2+4)))

    H22 = 1/((d-2*x)**2*(np.sqrt(4*(d-2*x)**2/(L+2*y)**2+4)))

    H23 = 1/((d+2*x)**2*(np.sqrt(4*(d+2*x)**2/(L-2*y)**2+4)))

    H24 = 1/((d+2*x)**2*(np.sqrt(4*(d+2*x)**2/(L+2*y)**2+4)))

    H1 = (H11 - H12 - H13 + H14)
    H2 = (-4*(d-2*x))*(H21 - H22) + (-4*(d+2*x))*(H23 - H24)

    B1 = (H1*mu_0)*2666
    B2 = (H2*mu_0)*1700
    B = np.sqrt(B1**2+B2**2)
    return np.dstack((B1,B2,B))


B1 = B(x,y)[:,:,0]
B2 = B(x,y)[:,:,1]
Bt = B(x,y)[:,:,2]

#Contour Plot
levels = np.logspace(-2.5,1.23,10,base=10)
cp = plt.contourf(x, y, Bt, levels=levels, cmap=plt.cm.plasma,extend='max')
cb = plt.colorbar(cp)
plt.clim(0,2)

#X and Y increments
dxy = [0.023/151,0.02/151]

#Gradients of B, Bx & By
dB = np.gradient(Bt,dxy[0],dxy[1])
dBy = np.gradient(B1,dxy[1])[0]
dBx = np.gradient(B2,dxy[0])[1]

#Vector Field Plot
x, y = np.mgrid[-1.15:1.15:20j, -1:1:20j]*1E-2
Bq = B(x,y)[:,:,2]
dxy = [0.023/20, 0.02/20]
dBq = np.gradient(Bq,dxy[0],dxy[1])

quiv = plt.quiver(x, y, dBq[0], dBq[1])
plt.show()

#X Gradient Plot
plt.figure()
x = np.linspace(-0.0115,0.0115,151)
plt.plot(x,B2[75,:])
plt.title('Magnetic Field vs. Position in x-direction')
plt.xlabel('Position (m)')
plt.ylabel('Magnetic Field (T)')
plt.show()

#Y Gradient Plot
plt.figure()
y = np.linspace(-0.01,0.01,151)
plt.plot(y,-B1[:,75])
plt.title('Magnetic Field vs. Position in y-direction')
plt.xlabel('Position (m)')
plt.ylabel('Magnetic Field (T)')
plt.show()

#-----------------------------------------

yslice = 0.00375

xp = np.random.uniform(-radius,radius,N)
yp = np.random.uniform(-radius,radius,N)

v_x = np.zeros(N)
v_y = np.zeros(N)

#Arrays to store counts
#count1 = [0]
#count2 = [0]
#count3 = [0]
#count4 = [0]
#count5 = [0]
count6 = [0]

for i in range(0,N):
    while xp[i]**2 + yp[i]**2 > radius**2:
        xp[i] = np.random.uniform(-radius,radius,1)
        yp[i] = np.random.uniform(-radius,radius,1)


for i in range(0,N):
    if -yslice < yp[i] < yslice:
        count6[0] = count6[0] + 1

fig1 = plt.figure()
plt.plot(xp,yp,".")

Fmag_x = np.zeros(N)
Fmag_y = np.zeros(N)
Fdrag_x = np.zeros(N)
Fdrag_y = np.zeros(N)
deltaV_x = np.zeros(N)
deltaV_y = np.zeros(N)

timestep = 1

#Method to animate simulation
def update(j,plt,fig1):
    global xp, yp, v_x, v_y, t, timestep, count
    plt.cla()
    if min(xp**2 + yp**2) < radius**2:
        count6.append(0)
        t6.append(t6[timestep-1] + deltaT)
        print(t6[timestep])
        #print('fmag: ' + str(Fmag_x[0]))
        #print('fdrag: ' + str(Fdrag_x[0]))
        print('v(x): ' + str(v_x[0]))
        for i in range(0,N):
            if xp[i]**2 + yp[i]**2 < radius**2:

                #Interpolation Method
                Ix = int((xp[i]-(-0.0115))/(0.0115-(-0.0115))*150)
                #print(Ix)
                Iy = int((yp[i]-(-0.01))/(0.01-(-0.01))*150)
                #print(Iy)
                dBx1 = dBx[Ix,Iy]
                dBx2 = dBx[Ix,Iy+1]
                dBx3 = dBx[Ix+1,Iy]
                dBx4 = dBx[Ix+1,Iy+1]
                dBy1 = dBy[Ix,Iy]
                dBy2 = dBy[Ix,Iy+1]
                dBy3 = dBy[Ix+1,Iy]
                dBy4 = dBy[Ix+1,Iy+1]
                T = (xp[i]-x[Ix])/(x[Ix+1]-x[Ix])
                #print(T)
                U = (yp[i]-y[Iy])/(y[Iy+1]-y[Iy])
                #print(U)
                #Interpolated Gradients
                dBxx = (1-T)*(1-U)*dBx1+(1-T)*U*dBx2+T*(1-U)*dBx3+T*U*dBx4
                #print('dBx ' +str(dBxx))
                dByy = (1-T)*(1-U)*dBy1+(1-T)*U*dBy2+T*(1-U)*dBy3+T*U*dBy4
                #print('dBy ' +str(dByy))
                #Magnetic Force in X and Y
                Fmag_x[i] = moment*dBxx*(B(xp[i],yp[i])[:,:,0]/np.abs(B(xp[i],yp[i])[:,:,2]))
                Fmag_y[i] = moment*dByy*(B(xp[i],yp[i])[:,:,1]/np.abs(B(xp[i],yp[i])[:,:,2]))

                #Drag Force in X and Y
                Fdrag_x[i] = 6*np.pi*mu*p_rad*v_x[i]
                Fdrag_y[i] = 6*np.pi*mu*p_rad*v_y[i]

                #Increase in velocity
                deltaV_x[i] = (Fmag_x[i] - Fdrag_x[i])*deltaT/m
                deltaV_y[i] = (Fmag_y[i] - Fdrag_y[i])*deltaT/m

                #Velocity
                v_x[i] = v_x[i] + deltaV_x[i]
                v_y[i] = v_y[i] + deltaV_y[i]
                #v_x = moment*30/(6*np.pi*mu*p_rad)*xp[i]/np.abs(xp[i])
                #v_y = moment*40/(6*np.pi*mu*p_rad)*yp[i]/np.abs(yp[i])

                #New X and Y coordinates of particles
                xp[i] = xp[i] + (v_x[i]*deltaT)
                yp[i] = yp[i] + (v_y[i]*deltaT)

            #Counter
            if -yslice < yp[i] < yslice:
                count6[timestep] = count6[timestep] + 1
        timestep = timestep + 1
    plt.plot(xp,yp,".")
    plt.xlim(-radius,radius)
    plt.ylim(-radius,radius)

ani = animation.FuncAnimation(fig1, update, frames=1, fargs=(plt, fig1), interval=0.1)

#Distribution of particles
#theta = np.arctan2(yp,xp)
#plt.hist(theta,50)
#plt.title('Distribution of Particles Generated')
#plt.xlabel('Theta (Rads)')
#plt.ylabel('Number of Particles')
#plt.show()
1个回答

数值积分时,大导数可能是个问题。在我看来,您正在使用具有固定时间步长的欧拉方法。您可以考虑其他方法,例如可以帮助您获得更小的积分误差的预测器-校正器方法。

此外,在您的模型中,只要粒子靠近,您就会得到很大的导数,因为由于磁相互作用产生的力会随着粒子之间的距离而减小。因此,尽管您没有物理碰撞,但只要粒子足够接近,它们之间就会发生强烈的相互作用。更大的力意味着每个时间步长内速度的变化更大。

所以,我的建议是你计算每个粒子会感觉到的总加速度(你已经在你的代码中这样做了),并分别处理加速度超过给定阈值的粒子子集。对于该粒子子集,您可以细分时间步长并对这些粒子的运动进行更多的中间计算。

您也可以考虑对速度高于另一个阈值的粒子子集执行相同的操作。