Last active
March 16, 2018 20:22
-
-
Save williamrijksen/e63ba234d768ecc72724b21eaefc9d0c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
======================================== | |
======Magnetic field simulation========= | |
======================================== | |
Created by R. van Manen and William Rijksen | |
Version 4 | |
Magnetic field simulation is based on: | |
Modeling a cylindrical permanent magnet with a surface charge of magnetic monopoles | |
(http://jimhawley.ca/downloads/Permanent_Magnet_With_Magnetic_Monopole_Surface_Charge.pdf) | |
Structure of this python script: | |
(1) Initialization | |
(a) loading libraries | |
(b) closing plot windows | |
(2) Constants | |
(a) sensor related constants | |
(b) magnet related constants | |
(c) axis limits of the field plot | |
(d) resolutions | |
(e) trajectory | |
(3) Variables | |
(4) Pre processing | |
(a) trajectory start and end points | |
(b) sensor orientation vector format | |
(c) sensor limits | |
(5) Function definitions | |
(a) magnetic Field Simulation | |
(b) trajectory length | |
(c) all inclusive length function | |
(6) Processing | |
(a) field calculations | |
(b) trajectory calculations | |
(c) brute force trajectory length | |
(7) Post processing | |
(a) plot window | |
(b) field plot | |
(c) trajectory plot | |
""" | |
"============(1) Initialization===============================================" | |
#Loading libraries | |
import numpy as np | |
import matplotlib.pyplot as plt | |
import matplotlib.patches as patches | |
from scipy import integrate | |
from sys import platform | |
#closing plot windows | |
plt.close("all") | |
"============(2) Constants====================================================" | |
#sensor related constants | |
S_sat = 37.5 #Sensor saturation [mT] | |
S_sen = 40 #Sensor sensitivity [mV/mT] | |
S_vrf = 3.3 #Sensor reference voltage [V] | |
ADC_res = 12 #ADconverter resolution [Bit] | |
S_res = 0.5 #Target resolution [mm/bit] | |
#magnet related constants | |
M_h = 5e-3 #Magnet height [m] | |
M_r = 2.5e-3 #Magnet radius [m] | |
Br = 1.45 #Remanence field [T] | |
#axis limits of the field plot | |
F_Zmax = 50e-3 #[m] | |
F_Zmin = -50e-3 #[m] | |
F_Rmax = 40e-3 #[m] | |
F_Rmin = -40e-3 #[m] | |
#resolutions | |
F_res = 25 #Resolution of Field plot [-] | |
T_res = 100 #Resolution of Trajectory plot [-] | |
#trajectory | |
T_L = 40e-3 #Trajectory length [m] | |
"============(3) Variables====================================================" | |
T_dis = 0e-3 #Trajectory distance from center [m] | |
M_or = 0/180*np.pi #Trajectory orientation [rad] | |
S_OR = 0/180*np.pi | |
"============(4) Pre processing===============================================" | |
#trajectory start and end points | |
T_R0 = T_dis*np.cos(M_or) #[m] | |
T_R1 = T_dis*np.cos(M_or)+np.sin(M_or)*T_L #[m] | |
T_Z0 = -T_dis*np.sin(M_or) #[m] | |
T_Z1 = -T_dis*np.sin(M_or)+np.cos(M_or)*T_L #[m] | |
T_lin = np.linspace(0,T_L,T_res) | |
#sensor orientation vector format | |
M_OR = [np.sin(M_or),np.cos(M_or)] | |
#sensor limits | |
B_max = S_sat/10**3 #Maximum magnetic field [T] | |
B_min = -S_sat/10**3 #Minimum magnetic field [T] | |
dB_min = S_vrf*10**3/(2**ADC_res*S_res*S_sen) #Minimal magnetic field gradient [T/m] | |
dB_max = -dB_min #Maximum magnetic field gradient [T/m] | |
"============(5) Function definitions=========================================" | |
#magnetic Field Function | |
def B_r(z,f,P_z,P_r): | |
return Br*M_r/(4*np.pi)*((P_z-z)*np.cos(f))/(P_r**2+M_r**2+(P_z-z)**2-2*M_r*P_r*np.cos(f))**(3/2) | |
def B_z(z,f,P_z,P_r): | |
return Br*M_r/(4*np.pi)*(M_r-P_r*np.cos(f))/(P_r**2+M_r**2+(P_z-z)**2-2*M_r*P_r*np.cos(f))**(3/2) | |
def lb(z): | |
return -M_h/2 | |
def ub(z): | |
return M_h/2 | |
def MFF(P_z,P_r): | |
(R,abserr) = integrate.dblquad(B_r,0,2*np.pi,lb,ub,args=(P_z,P_r)) | |
(Z,abserr) = integrate.dblquad(B_z,0,2*np.pi,lb,ub,args=(P_z,P_r)) | |
return (R,Z) | |
MFF = np.vectorize(MFF) | |
#trajectory length | |
def Length(B,dB,Bmin,Bmax,dBmin,dBmax): | |
T_linR = np.linspace(0,T_L,T_res*15) | |
B = np.interp(T_linR,T_lin,B) | |
dB = np.interp(T_linR,T_lin,dB) | |
vector = np.invert(np.all([dB<dBmin,dB>dBmax],axis=0)) | |
vector = np.all([vector,B<Bmax,B>Bmin],axis=0) | |
temp = np.sign(dB) | |
vector[np.where(temp[1:]!=temp[:-1])]=0 | |
T_length = 0 | |
while any(vector): | |
T_length += 1 | |
vector = [vector[i] and vector[i] == vector[i+1] for i in range(len(vector)-1)] | |
T_length = T_length*T_L/(T_res*15-1) | |
return T_length | |
#Length = np.vectorize(Length) | |
#all inclusive length function | |
def BF_length(M_or): | |
T_R0 = T_dis*np.cos(M_or) #[m] | |
T_R1 = T_dis*np.cos(M_or)+np.sin(M_or)*T_L #[m] | |
T_Z0 = -T_dis*np.sin(M_or) #[m] | |
T_Z1 = -T_dis*np.sin(M_or)+np.cos(M_or)*T_L #[m] | |
M_OR = [np.sin(M_or),np.cos(M_or)] | |
T_Zlin = np.linspace(T_Z0,T_Z1,T_res) | |
T_Rlin = np.linspace(T_R0,T_R1,T_res) | |
T_B = MFF(T_Zlin,T_Rlin) | |
T_Bprj = np.dot(M_OR,T_B)*np.cos(S_OR) | |
T_dBprj = np.gradient(T_Bprj,T_lin[1]) | |
T_l = Length(T_Bprj,T_dBprj,B_min,B_max,dB_min,dB_max) | |
return T_l | |
BF_length = np.vectorize(BF_length) | |
#Optimization function | |
def OPT_length(x): | |
M_or = x[0] | |
T_R0 = T_dis*np.cos(M_or) #[m] | |
T_R1 = T_dis*np.cos(M_or)+np.sin(M_or)*T_L #[m] | |
T_Z0 = -T_dis*np.sin(M_or) #[m] | |
T_Z1 = -T_dis*np.sin(M_or)+np.cos(M_or)*T_L #[m] | |
M_OR = [np.sin(M_or),np.cos(M_or)] | |
T_Zlin = np.linspace(T_Z0,T_Z1,T_res) | |
T_Rlin = np.linspace(T_R0,T_R1,T_res) | |
T_B = MFF(T_Zlin,T_Rlin) | |
T_Bprj = np.dot(M_OR,T_B)*np.cos(S_OR) | |
T_dBprj = np.gradient(T_Bprj,T_lin[1]) | |
T_l = 0.1/(Length(T_Bprj,T_dBprj,B_min,B_max,dB_min,dB_max)+1e-9) | |
return T_l | |
"============(6) Processing===================================================" | |
#field calculations | |
F_Zlin = np.linspace(F_Zmin,F_Zmax,F_res) | |
F_Rlin = np.linspace(F_Rmin,F_Rmax,F_res) | |
F_B = MFF(F_Zlin[:,None], F_Rlin[None,:]) | |
F_Babs = (F_B[0]**2+F_B[1]**2)**(1/2) | |
#Optimization | |
x0 = 0 | |
#OPT = sp.optimize.minimize(OPT_length,x0,method='Powell', | |
# options={'disp': True}) | |
#M_or = OPT.x*1 | |
T_R0 = T_dis*np.cos(M_or) #[m] | |
T_R1 = T_dis*np.cos(M_or)+np.sin(M_or)*T_L #[m] | |
T_Z0 = -T_dis*np.sin(M_or) #[m] | |
T_Z1 = -T_dis*np.sin(M_or)+np.cos(M_or)*T_L #[m] | |
M_OR = [np.sin(M_or),np.cos(M_or)] | |
T_lin = np.linspace(0,T_L,T_res) | |
#trajectory calculations | |
T_Zlin = np.linspace(T_Z0,T_Z1,T_res) | |
T_Rlin = np.linspace(T_R0,T_R1,T_res) | |
T_B = MFF(T_Zlin,T_Rlin) | |
T_Babs = (T_B[0]**2+T_B[1]**2)**(1/2) | |
T_Bprj = np.dot(M_OR,T_B)*np.cos(S_OR) | |
T_dBprj = np.gradient(T_Bprj,T_lin[1]) | |
T_l = Length(T_Bprj,T_dBprj,B_min,B_max,dB_min,dB_max) | |
"============(7) Post processing==============================================" | |
#plot window | |
PW = plt.figure() | |
if platform == "win32": | |
mngr = plt.get_current_fig_manager() | |
mngr.window.setGeometry(-1700,250,1500, 700) | |
#Field plot | |
Field = PW.add_subplot(121, aspect='equal') | |
Field.add_patch(patches.Rectangle((-M_r*1e3, -M_h/2*1e3),M_r*2*1e3,M_h*1e3)) #magnet | |
plt.contourf(F_Rlin*1e3,F_Zlin*1e3,np.log(F_Babs),100,cmap=plt.cm.hot_r) #magnetic field strenght color | |
plt.plot([T_R0*1e3,T_R1*1e3],[T_Z0*1e3,T_Z1*1e3], color='b',linewidth=3) #trajectory | |
plt.streamplot(F_Rlin*1e3,F_Zlin*1e3,F_B[0],F_B[1],color='k',linewidth=0.2) #magnetic field lines | |
plt.axis((F_Rmin*1e3,F_Rmax*1e3,F_Zmin*1e3,F_Zmax*1e3)) | |
plt.title('Magnetic Field [M_or = {0: .4f}]'.format(M_or)) | |
plt.xlabel('r [mm]') | |
plt.ylabel('z [mm]') | |
#Trajectory plot | |
Traject = PW.add_subplot(122) | |
plt.plot(-10,0,'ko',label='Length = %.1f [mm]'%(T_l*1e3)) #length legend item | |
plt.plot(T_lin*1e3,T_Babs*1e3, label='|M| [mT]') #abs(M) | |
plt.plot(T_lin*1e3,T_Bprj*1e3, label='Projected |M| [mT]') #abs(Mprj) | |
Traject.fill_between(T_lin*1e3,-100,100, | |
where= np.logical_and(T_dBprj < dB_min,T_dBprj > dB_max), | |
facecolor='grey', label='unsensitive') #unsensitive regions | |
plt.title('Magnetic Field @ sensor path') | |
plt.xlabel('x [mm]') | |
plt.ylabel('|M| [mT]') | |
plt.axis((0,T_lin[-1]*1e3,B_min*1e3,B_max*1e3)) | |
plt.legend() | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment