# -*- coding: utf-8 -*- """ Created on Mon Nov 2 10:52:43 2020 @author: User """ #%% import numpy as np import matplotlib.pyplot as plt from IPython import get_ipython import magpylib as magpy import statsmodels.api as sm import os #%% ''' Para hacer el modelo de una bobina, vamos a aprovechar la clase "Collection" que posee Magpylib para juntar varias fuentes de corriente en una sola por superposición. Podemos modelar una bobina de dos maneras, una más simplificada y otra más precisa, pero más costosa computacionalmente (y puede llegar a tener más errores numéricos si no se hace bien). NOTA: Recordar que las unidades en Magpylib son: Corriente en Ampere [A] Posición en metros [m] Campo en Ampere sobre metro [A/m] ''' corriente = 1 # Corriente de la bobina en Ampere largo = 16e-2 # Largo de la bobina en metros n_espiras = 50 # Número de espiras diametro = 4e-2 # Diámetro en metros # Modelo simplificado: coil1 = magpy.Collection() # Definimos el objeto para la Bobina 1 for z in np.linspace(-largo/2, largo/2, n_espiras): # Definimos el devanado de la bobinas: winding = magpy.current.Circle(position=(0,0,z),orientation=None, diameter=diametro,current=corriente) coil1.add(winding) coil1.show() # Modelo más preciso: ts = np.linspace(-largo/2, largo/2, 1000) vertices = np.c_[diametro/2*np.cos((n_espiras/largo)*2*np.pi*ts), diametro/2*np.sin((n_espiras/largo)*2*np.pi*ts), ts] # Parametrizamos una espiral coil2 = magpy.current.Polyline(position=(0,0,0), orientation=None, vertices=vertices, current=corriente) # Creamos una fuente de corriente lineal con la forma de espiral coil2.show() #%% ''' Usamos Matplotlib para graficar la líneas de campo de las bobinas que creamos anteriormente. ''' fig, [ax1,ax2] = plt.subplots(1, 2, figsize=(13,5)) # creamos la grilla donde graficaremos: ts = np.linspace(-largo/2, largo/2, 20) grid = np.array([[(x,0,z) for x in ts] for z in ts]) # Obtenemos el campo y lo ploteamos: B = magpy.getB(coil1, grid) Bamp = np.linalg.norm(B, axis=2) Bamp /= np.amax(Bamp) sp = ax1.streamplot( grid[:,:,0], grid[:,:,2], B[:,:,0], B[:,:,2], density=2, color=Bamp, linewidth=np.sqrt(Bamp)*3, cmap='coolwarm', ) # Obtenemos el campo y lo ploteamos para la segunda bobina: B = magpy.getB(coil2, grid) Bamp = np.linalg.norm(B, axis=2) Bamp /= np.amax(Bamp) cp = ax2.contourf( grid[:,:,0], grid[:,:,2], Bamp, levels=100, cmap='coolwarm', ) ax2.streamplot( grid[:,:,0], grid[:,:,2], B[:,:,0], B[:,:,2], density=2, color='black', ) # Seteamos el estilo de las líneas, títulos y leyendas: ax1.set( title='Campo magnético de la Bobina con espiras', xlabel='x-position [m]', ylabel='z-position [m]', aspect=1, ) ax2.set( title='Campo magnético de la Bobina hilvanada', xlabel='x-position [m]', ylabel='z-position [m]', aspect=1, ) plt.colorbar(sp.lines, ax=ax1, label='[A/m]') plt.colorbar(cp, ax=ax2, label='[A/m]') plt.tight_layout() plt.show() #%% #Calculo del campo de la bobina en el eje z zi = 15e-2 # Posición inicial en m zf = 20e-2 # Posición final en m bobina = coil1 zs = np.linspace(zi,zf,1000) Bs = np.array([bobina.getB([0,0,z]) for z in zs] ) Bzs=Bs[:,2] # Nos quedamos con la componente en z ya que el resto es nulo. #Graficamos la dependencia del campo con la posición a los largo del eje del imán plt.figure(2) plt.plot(zs,Bzs,'bs') plt.xlabel("z(m)", fontsize=20) plt.ylabel("Bz(A/m)", fontsize=20) plt.tick_params(axis = 'both', which = 'both', length = 4, width = 2, labelsize = 15) plt.grid() #%% ''' Proponemos una función para el ajuste Bz=a/z**k, estudiamos relación logBz vs logz para encontrar k analizar rango de validez del modelo variando el límite de zs. ''' logzs=np.log10(zs) logBzs=np.log10(Bzs) Xs = sm.add_constant(logzs) ols_model = sm.OLS(logBzs,Xs) results = ols_model.fit() o,m=results.params ajuste=m*logzs+o print('pendiente=', m) print('ordenada al origen=', o) print('R^2=',results.rsquared) Bajuste=10**ajuste #realizamos gráfico y ajuste en escala log-log plt.figure(3) plt.plot(zs,Bajuste, 'r', label='Ajuste') plt.scatter(zs,Bzs, label = 'Simulación') plt.xscale('log') plt.yscale('log') plt.xlabel('z(m)') plt.ylabel('Bz(A/m)') plt.legend() #%% ---------- Ajustar datos experimentales ------------ ''' Cargamos el archivo con mediciones y hacemos el mismo proceso de ajuste pero ahora tenemos en cuenta que tienen error. ''' carpeta = '' # Poner ruta de la carpeta con los datos os.chdir(carpeta) path = 'nombre_arch.txt' # Nombre del archivo con los datos datos = np.loadtxt(path) z = datos[:,0] Bz = datos[:,1] err_z = 5*np.ones(len(z)) # Poner error err_Bz = datos[:, 2] logz=np.log10(zs) logBz=np.log10(Bzs) X = sm.add_constant(logz) ajuste = sm.WLS(logBz, X, weights=1.0 / (err_Bz ** 2)) resultados = ajuste.fit() print(resultados.summary()) #realizamos gráfico y ajuste en escala log-log plt.figure(4) plt.plot(zs,Bajuste, 'r', label='Ajuste') plt.errorbar(z,Bz, yerr=err_Bz, xerr=err_z, label = 'Datos') plt.xscale('log') plt.yscale('log') plt.xlabel('z(mm)') plt.ylabel('Bz(T)') #Chequear unidades plt.legend() #intervalo de confianza para ordenada al origen y pendiente oint,mint=resultados.conf_int(alpha=0.05) deltam=abs((mint[1]-mint[0])/2) deltao= abs((oint[1]-oint[0])/2) #%% ---------------------- IMÁN CILÍNDRICO (obsoleto para la v5)---------------- #NOTA: para la version 5 de magpylib hay que corregir las unidades. Pide M en A/m get_ipython().run_line_magic('matplotlib', 'qt5') pm=magpy.magnet.Cylinder(magnetization=[0,0,1000], dimension = [15,5]) # dimension (diameter,height) in mm. # no pos, angle, axis specified so default values are used print('magnatización',pm.magnetization) # Output: [0. 0. 1000.] print('dimensiones',pm.dimension) # Output: [15. 5.] print('posición',pm.position) # Output: [0. 0. 0.] print(pm.orientation.as_euler('xyz')) # Output: [0. 0. 0.] #print(pm.angle) # Output: 0.0 #print('eje',pm.xis) # Output: [0. 0. 1.] #s.move([1,2,3]) #s.setOrientation(angle,axis) #create sensor positions xs1 = np.linspace(-150,150,200) zs1 = np.linspace(-150,150,250) Bs1 = np.array([[pm.getB([x,0,z]) for x in xs1] for z in zs1]) plt.ion() plt.close("all") #Dibujamos las líneas de campo alrededor del imán plt.figure(1) X,Y = np.meshgrid(xs1,zs1) U,V = Bs1[:,:,0], Bs1[:,:,2] amp = np.sqrt(U**2+V**2) plt.contourf( X, Y, amp,np.linspace(0,130,50),cmap=plt.cm.brg) plt.streamplot(X, Y, U, V, color='w', density=3,linewidth=0.8) plt.title = 'Campo magnético del imán', plt.xlabel ('x-position [mm]'), plt.ylabel ('z-position [mm]'), plt.xlim=[-150,150] plt.ylim=[-150,150], plt.aspect = 1 #%% #Calculo del campo en el eje z zi = 30 # Posición inicial en mm zf = 300 # Posición final en mm zs = np.linspace(zi,zf,100) Bs = np.array([pm.getB([0,0,z]) for z in zs] ) Bzs=Bs[:,2] # Nos quedamos con la componente en z ya que el resto es nulo. #Graficamos la dependencia del campo con la posición a los largo del eje del imán plt.figure(2) plt.plot(zs,Bzs,'bs') plt.xlabel("z(mm)") plt.ylabel("Bz(T)") #%% ''' Proponemos una función para el ajuste Bz=a/z**k, estudiamos relación logBz vs logz para encontrar k analizar rango de validez del modelo variando el límite de zs. ''' logzs=np.log10(zs) logBzs=np.log10(Bzs) Xs = sm.add_constant(logzs) ols_model = sm.OLS(logBzs,Xs) results = ols_model.fit() o,m=results.params ajuste=m*logzs+o print('pendiente=', m) print('ordenada al origen=', o) print('R^2=',results.rsquared) Bajuste=10**ajuste #realizamos gráfico y ajuste en escala log-log plt.figure(3) plt.plot(zs,Bajuste, 'r', label='Ajuste') plt.scatter(zs,Bzs, label = 'Simulación') plt.xscale('log') plt.yscale('log') plt.xlabel('z(mm)') plt.ylabel('Bz(T)') plt.legend()