Package: biot-savart
Biot-Savart Magnetic Field CalculatorThis tool numerically solves for the 3D vector magnetic field around an arbitrarily shaped coil specified by the user, in a discrete and finite volume surrounding the coil. The code is optimized to use NumPy vectorization for fast calculations.
Latest Version: V5.0 (June 20, 2021)By Mingde Yin and Ryan ZazoBasic Overview of FunctionalityGiven an input coil, the tool can both calculate, and plot the magnetic field vector over a finite discrete volume of space around the coil.The coil is passed into the program as a set of vertices describing the geometry of the coil, as well as the amount of current flowing through a given segment of the coil. (SeeFormattingsection)Atarget volumeis produced as a series of points within a rectangular prism bounding box around the coil. The magnetic field at each point in the target volume is obtained by numerically integrating using the Biot-Savart law, resulting in a 4D array of size (X, Y, Z, 3) as the output, which is saved to a file usingnumpy.save().The entire process of producing the finished target volume is done through the functionwrite_target_volume().A calculated target volume can be loaded in usingread_target_volume(). This target volume array can then be plotted using the built-in plotting functions.InstallationHave Python 3.x installedInstallnumpyandmatplotlibClone or download the repository to your machineData Input and Calculating the FieldYou can produce and calculate a target volume usingwrite_target_volume(), which writes a calcualted target volume to a file which can be loaded and used later usingread_target_volume(filename).Parameters Breakdowninput_filename: Name of input file. SeeCoil Formatfor detailsoutput_filename: The name of the file in which we store the finished target volume.box_size: (x, y, z) tuple with the dimensions of the target volume in cmstart_point: (x, y, z) tuple representing the bottom left corner spatial position of the target volume (with respect to the coil) AKA the offsetcoil_resolution: How long each discretized coil subsegment should be, in cmvolume_resolution: Division of volumetric meshgrid (generate a point in the target volume every volume_resolution cm)Increasingcoil_resolutionaffects runtime linearly, whereas increasingvolume_resolutionincreases runtime cubically.coil_resolutioncan be reduced to around 0.01 cm with acceptable results, andvolume_resolutionshould be kept no lower than 0.1 cm. We recommend using 1 cm for both, if you can tolerate it.Coil FormatThe coil is represented as a series of (X,Y,Z) coordinates which define the vertices of the coil spatially, along with an additional coordinate (I) which defines the amount of current flowing from that vertex to the next one.Plaintext fileThe file contains each (X,Y,Z,I) entry on a new lineThe format of each line should be"x,y,z,I\n"For instance:0,0,1,2
0,1,1,3
1,1,1,4Means that:There are 2 amps of current running between points 1 and 2There are 3 amps of current running between points 2 and 3The last bit of current is functionally useless.An Example Coil (coil.txt):0,0,0,1
10,0,0,1
10,10,0,1
20,10,0,1Here's what the coil looks like (static/coil.svg), plotted usingplot_coil("coil.txt").Understanding the Coordinate System and Indexing a Finished Target VolumeAll positions in this program are described with respect to the position of the coil. This means, for the above coil, abox_sizeof(10, 10, 10), with astart_pointof(-5, -5, -5)creates a box with its middle centred about the first vertex of the coil at(0, 0, 0). In other words, it's as you would expect.When indexing a finished target volume, you must be wary of both thevolume_resolutionand thestart_point. For instance, avolume_resolutionof 0.5 cm means that would would need to first subtract the starting point, and then multiply incoming coordinates by 2 to get the correct array index for the target volume.If you are happy with just reading the field vector at some point in space, there is the built in functionget_field_vector(), which will do this for you. However, you you want to perform complex operations on the system, it is advisable to work with the full size arrays directly.Plotting a Target Volumeplot_coil()takes in an input filename for a coil stored in the format above, and graphs is in 3D.plot_fields()produces contour plots of the Bx, By, and Bz components of the magnetic field along a certain plane.Parameters BreakdownBfields: a calculated target volume array, which can be read fromread_target_volume()start_point, box_size, vol_resolution: Same as abovewhich_plane: ['x', 'y', 'z'] the plane upon which you wish to graphlevel: the level of the plane on which you wish to graph (same coordinate system as the coil)num_contours: the number of contours producedExample: Helmholtz Coils, plotted at z = 0Results in a graph that looks like:A Strategy for Complex Coil SystemsIf you want to plot the effects of multiple coils, you can simply save several target volumes with the samebox_size,start_point, andvol_resolution, then add them together (See Helmholtz Coil Example Below).This approach is ideal for systems with complicated geometry, as it is easy to construct a several simple coils, and analyse their overall effect by adding their fields together in this way.Producing CoilsYou can either produce your own coils according to the rules specified above, or use some of the built in functions.create_B_x_rectangle(),create_B_y_rectangle(),create_B_x_rectangle()produce rectangular coils of adjustable dimensions at adjustable positions.Similarly,create_Bx_circle(),create_By_circle(),create_By_circle()produce circular coils of adjustable dimensions at adjustable positions.helmholtz_coils()creates a pair of circular helmholtz coils, spaced apart in the z axis.ExamplesBasic example using coil.txtcoil.txt:0,0,0,1
10,0,0,1
10,10,0,1
20,10,0,1importbiot_savartasbsbs.write_target_volume("coil.txt","coil",(30,15,15),(-5,-0.5,-2.5),1,1)# generates a target volume from the coil stored at coil.txt# uses a 30 x 15 x 15 bounding box, starting at (-5, -0.5, -2.5)# uses 1 cm resolutionbs.plot_coil("coil.txt")# plots the coil stored at coil.txtfields,positions=bs.read_target_volume("coil")# reads the volume we createdbs.plot_fields(fields,positions,which_plane='z',level=5,num_contours=50)# plots the fields we just produced# plotting along the plane x = 5, with 50 contoursOutput:Helmholtz Coilsimportbiot_savartasbsbs.helmholtz_coils("helm1.txt","helm2.txt",50,5,2,1)# makes a pair of helmholtz coils# 50 segments each, with radius of 5 cm# spaced out by 2 cm, located at z = +/- 1 respectively# 1 amp of currentbs.plot_coil("helm1.txt","helm2.txt")bs.write_target_volume("helm1.txt","targetvol1",(10,10,10),(-5,-5,-5),0.5,0.5)bs.write_target_volume("helm2.txt","targetvol2",(10,10,10),(-5,-5,-5),0.5,0.5)# use a target volume of size 10, centred about originh1,pos1=bs.read_target_volume("targetvol1")h2,pos2=bs.read_target_volume("targetvol2")# produce the target volumes we want# use linear superposition of magnetic fields, to get the combined effects of multiple coilsh_total=h1+h2bs.plot_fields(h_total,pos1,which_plane='z',level=0,num_contours=50)Output:Key Optimization TechniquesThe tool uses a couple of techniques to accelerate computation and increase precision.Evaluation of the target volume is performed using numpy meshgrids, which improve speed dramatically; almost 1000 times faster than using traditional for loops.Integration is performed using Richardson Extrapolation, which allows for higher precision without needing extra function evaluations.Changelogv1: Initial Releasev2: Code accelerated using numpy meshgridsv2.1: Tkinter dialogs for opening & saving files. Defaults of 1 cm resolution in calculation.v3: Plotting code integrated.v3.1: Minor cosmetic improvements to plot.v3.2: 3D plot of coil geometry.v3.3/3.4: Plotted B-fields together but code is long.v3.5/3.6: all B-field plots togetherv3.7: B-fields plotted together with 50 levels (now works on windows) and combined v3.3 and v3.5v3.8: Changed up all np.aranges to np.linspaces and changed up the plotting
code to work with non-integer step sizes and non-integer levelsv4: Using Richardson Extrapolation for midpoint rule to improve accuracy (5 to 30x better at 1.4x speed penalty), tweaked linspaces to correctly do step sizev4.1: Minor change in function indexing to use more numpy, cleaning up for exportv4.2: Changed the linspaces a bit to make everything more symmetricv4.3: Added in many functions for plotting rectangular and circular coils, cleaned up functions to be more consistent, and flexible.v5.0: Rewrite of some major parts of code, make the core computation engine fully vectorized