Bugs and improvement: yangdikun@gmail.com
In [ ]:
import numpy as np
from ipywidgets import interact, interactive, fixed, Layout
import ipywidgets as widgets
In [ ]:
import plotly.plotly as py
import plotly.graph_objs as go
from plotly import __version__
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
print(__version__) # requires version >= 1.9.0
init_notebook_mode(connected=True)
In [ ]:
# x, y, z: location of the observing point
# Bx, By, Bz: vector B field at the observing point in vaccum
def VerticalMagneticDipoleField(x, y, z):
r = (x**2 + y**2 + z**2)**(0.5)
Bx = 1e-7/r**3 * 3*x*z/r**2
By = 1e-7/r**3 * 3*y*z/r**2
Bz = 1e-7/r**3 * (3*z**2/r**2 - 1)
return Bx, By, Bz
In [ ]:
# radius: a float defining how far the field lines expand
# stepSize: length of the segments that make the field lines
# yloc, zloc: a single field line path in the y-z plane
def VerticalMagneticDipoleLine(radius,stepSize=1.):
x, y, z = 0., [radius], [-stepSize/4.]
while (y[-1]>=0.) & (z[-1] <= 0.):
_, By, Bz = VerticalMagneticDipoleField(x, y[-1], z[-1])
B = (By**2 + Bz**2)**(0.5)
By, Bz = By/B*stepSize, Bz/B*stepSize
y.append(y[-1]+By)
z.append(z[-1]+Bz)
y.pop()
z.pop()
yloc = np.r_[y[-1:0:-1], y]
zloc = np.r_[-np.array(z[-1:0:-1]),z]
return yloc, zloc
In [ ]:
# dipoleLoc: (x,y,z) of a magnetic dipole
# dipoleDec, dipoleInc: declination and inclination angles of the dipole direction in degree
# radii: a float vector defining the radii of the field line shells
# naz: number of azimuths for the plotting of field lines
# stepSize: length of the segments that make the field lines
# xloc, yloc, zloc: a collection of all field line paths
def MagneticDipoleLine(dipoleLoc,dipoleDec,dipoleInc,radii,naz=10,stepSize=1.):
x0, y0, z0 = dipoleLoc[0], dipoleLoc[1], dipoleLoc[2]
# rotation matrix
theta, alpha = -np.pi*(dipoleInc+90.)/180., -np.pi*dipoleDec/180.
Rx = np.array([[1.,0.,0.],[0.,np.cos(theta),-np.sin(theta)],[0.,np.sin(theta),np.cos(theta)]])
Rz = np.array([[np.cos(alpha),-np.sin(alpha),0.],[np.sin(alpha),np.cos(alpha),0.],[0.,0.,1.]])
R = np.dot(Rz,Rx) # Rz @ Rx
azimuth = np.linspace(0.,2*np.pi,num=naz,endpoint=False)
xloc, yloc, zloc = [], [], []
for r in radii:
hloc, vloc = VerticalMagneticDipoleLine(r,stepSize)
for a in azimuth:
x, y, z = np.sin(a)*hloc, np.cos(a)*hloc, vloc
xyz = np.dot(R, np.vstack((x,y,z)))
xloc.append(xyz[0]+x0)
yloc.append(xyz[1]+y0)
zloc.append(xyz[2]+z0)
return xloc, yloc, zloc
In [ ]:
# dipoleLoc: (x,y,z) of a magnetic dipole
# dipoleDec, dipoleInc: declination and inclination angles of the dipole direction in degree
# radius: radius of loop surface
# nseg: number of line segments that make a loop
# xloc, yloc, zloc: a collection of line paths for a loop and its normal direction
def MagneticDipoleLoop(dipoleLoc,dipoleDec,dipoleInc,radius,nseg=20):
x0, y0, z0 = dipoleLoc[0], dipoleLoc[1], dipoleLoc[2]
# rotation matrix
theta, alpha = -np.pi*(dipoleInc+90.)/180., -np.pi*dipoleDec/180.
Rx = np.array([[1.,0.,0.],[0.,np.cos(theta),-np.sin(theta)],[0.,np.sin(theta),np.cos(theta)]])
Rz = np.array([[np.cos(alpha),-np.sin(alpha),0.],[np.sin(alpha),np.cos(alpha),0.],[0.,0.,1.]])
R = np.dot(Rz,Rx) # Rz @ Rx
# loop path
azimuth = np.linspace(0.,2*np.pi,num=nseg+1,endpoint=True)
x, y, z = np.sin(azimuth)*radius, np.cos(azimuth)*radius, azimuth*0.
xyz = np.dot(R, np.vstack((x,y,z)))
xloc1, yloc1, zloc1 = xyz[0]+x0, xyz[1]+y0, xyz[2]+z0
# normal direction pointer
x, y, z = [0.,0.],[0.,0.],[0.,radius]
xyz = np.dot(R, np.vstack((x,y,z)))
xloc2, yloc2, zloc2 = xyz[0]+x0, xyz[1]+y0, xyz[2]+z0
return [xloc1,xloc2], [yloc1,yloc2], [zloc1,zloc2]
In [ ]:
# <<< Control Parameters: Change these numbers to visualize different scenarios
loopRadius = 0.5 # <<< radius of loop wires
stepSize = 0.2 # <<< length of line segments for plotting lines
nazimuth = 4 # <<< number of azimuths for plotting field lines
# define Loop 1 parameters
x1, y1, z1 = -2.0, 0.0, 0.0 # <<< location
dec1, inc1 = 0.0, -90.0 # <<< declination & inclination in degree
line1Radii = [3.0, 3.8] # <<< field lines are everywhere in space but we only plot a few layers specified by radii
enabled1 = True # <<< True or False to turn on or off the display of Loop 1
# define Loop 2 parameters
x2, y2, z2 = 0.0, 0.0, -1.0 # <<< location
dec2, inc2 = 90.0, 0.0 # <<< declination & inclination in degree
line2Radii = [12.0] # <<< field lines are everywhere in space but we only plot a few layers specified by radii
enabled2 = True # <<< True or False to turn on or off the display of Loop 2
# define Loop 3 parameters
x3, y3, z3 = 2.0, 0.0, 0.0 # <<< location
dec3, inc3 = 0.0, -90.0 # <<< declination & inclination in degree
enabled3 = True # <<< True or False to turn on or off the display of Loop 3
# Plotting Commands Below
# get line path for the 3 loops
loopx1, loopy1, loopz1 = MagneticDipoleLoop((x1,y1,z1),dec1,inc1,loopRadius)
loopx2, loopy2, loopz2 = MagneticDipoleLoop((x2,y2,z2),dec2,inc2,loopRadius)
loopx3, loopy3, loopz3 = MagneticDipoleLoop((x3,y3,z3),dec3,inc3,loopRadius)
# get line path for the field lines of loop 1 and 2
linex1, liney1, linez1 = MagneticDipoleLine((x1,y1,z1),dec1,inc1,line1Radii,nazimuth,stepSize)
linex2, liney2, linez2 = MagneticDipoleLine((x2,y2,z2),dec2,inc2,line2Radii,nazimuth,stepSize)
# create plot
data = []
if enabled1:
for xx,yy,zz in zip(loopx1,loopy1,loopz1):
data.append(go.Scatter3d(x=xx, y=yy, z=zz, mode='lines', line=dict(color='red',width=3)))
for xx,yy,zz in zip(linex1,liney1,linez1):
data.append(go.Scatter3d(x=xx, y=yy, z=zz, mode='lines', line=dict(color='red',width=5)))
if enabled2:
for xx,yy,zz in zip(loopx2,loopy2,loopz2):
data.append(go.Scatter3d(x=xx, y=yy, z=zz, mode='lines', line=dict(color='green',width=3)))
for xx,yy,zz in zip(linex2,liney2,linez2):
data.append(go.Scatter3d(x=xx, y=yy, z=zz, mode='lines', line=dict(color='green',width=5)))
if enabled3:
for xx,yy,zz in zip(loopx3,loopy3,loopz3):
data.append(go.Scatter3d(x=xx, y=yy, z=zz, mode='lines', line=dict(color='blue',width=3)))
layout = dict(width=1000, height=500, autosize=False, showlegend=False,
margin=go.Margin(l=5,r=5,b=5,t=5,pad=4),paper_bgcolor='#efefef',
scene = dict(aspectmode = 'data', aspectratio = dict(x=1, y=1, z=1),
camera = dict(up=dict(x=0,y=0,z=1),center=dict(x=0,y=0,z=0),eye=dict(x=0.1,y=-0.5,z=0.2)))
)
fig = dict(data=data, layout=layout)
iplot(fig)
In [ ]: