title: Python: calculate the magnetic field of a wire using biot-savart-law
body: <p>I want to calculate the magnetic field of a wire using biot-savart-law. Some people recommend to use numpy arrays. At first i did it with vpython and it worked. But know I want to use Matplotlib for visualisation. Therefore I need arrays right? But I stuck now. </p>
  
  <p>I also posted this question to codereview, but they send me to stackoverflow.</p>
  
  <p>The problem is in this line --> bfield2 = konstante*I*cross(dl, (rx,ry,rz))/r**3</p>
  
  <pre><code>import matplotlib
  import numpy as np
  import matplotlib.cm as cm
  import matplotlib.mlab as mlab
  import matplotlib.pyplot as plt
  from visual import *
  
  I = 1
  mu0 = 1e-7
  konstante = mu0/(4*np.pi)
  
  # wire elements; always lenght one
  coord = [(0,0), (1,0), (2,0), (3,0), (4,0), (5,0), (6,0), (7,0), (8,0), (9,0), (9,1),
           (9,2), (9,3), (9,4), (9,5), (9,6), (9,7), (9,8)]
  # draw the wires
  #for i in range(len(coord)-1):
  #    wire = curve(pos=(coord[i],coord[i+1]), radius=0.2)
  
  # calculate the b-field
  def bfield(x,y,z):
      bfield3 = 0
      # number of wire elements
      for i in range(len(coord)-1):
          # center of the wire element
          wiremiddlex = coord[i][0]+(coord[i+1][0]-coord[i][0])/2.0
          wiremiddley = coord[i][1]+(coord[i+1][1]-coord[i][1])/2.0
          wiremiddlez = 0
          rx = x-wiremiddlex
          ry = y-wiremiddley
          rz = 0
          r = (rx**2+ry**2+rz**2)**0.5
          dl = ((coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0)
          bfield2 = konstante*I*cross(dl, (rx,ry,rz))/r**3 # i have to use numpy arrays
          bfield3 += (bfield2[0]**2 + bfield2[1]**2 + bfield2[2]**2)**0.5
      return bfield3
  
  # visualize
  xwidth=10
  ywidth=10
  delta = 1
  x = np.arange(0, xwidth, delta)
  y = np.arange(0, ywidth, delta)
  X, Y = np.meshgrid(x, y)
  slicee = 3
  Z = bfield(X,Y,slicee)
  
  plt.figure()
  CS = plt.contour(X, Y, Z)
  plt.clabel(CS, inline=1, fontsize=10)
  plt.title('Simplest default with labels')
  plt.show()
  </code></pre>
  
  <p>EDIT No. 7: I delete the other Edits. I don't want to confuse. The output in not correct. Please see the next Edit.</p>
  
  <pre><code># Calculation of a magnetic field of a wire
  # later I want to to it three dimensional
  
  import matplotlib
  import numpy as np
  import matplotlib.cm as cm
  import matplotlib.mlab as mlab
  import matplotlib.pyplot as plt
  from pylab import *
  
  I = 10000000000
  mu0 = 1e-7
  constant = mu0/(4*np.pi)
  
  # wire elements; always lenght one
  coord = [(0,0), (1,0), (2,0), (3,0), (4,0), (5,0), (6,0), (7,0), (8,0),
           (9,0), (9,1), (9,2), (9,3), (9,4), (9,5), (9,6), (9,7), (9,8),
           (8,8), (7,8), (6,8), (5,8)]
  
  # calculate the b-field
  def bfield(x,y,z):
      b2 = np.zeros((xwidth,ywidth))
      for x in range(xwidth):
          for y in range(ywidth):
              # number of wire elements
              for i in range(21):
                  rx = (coord[i][0]+coord[i+1][0])/2. - x
                  ry = (coord[i][1]+coord[i+1][1])/2. - y
                  rz = z * 1.0 # = z-0
                  r = (rx**2+ry**2+rz**2)**0.5 # distance r between field and middle of the wire
                  dl = np.array([(coord[i+1][0]-coord[i][0]), (coord[i+1][1]-coord[i][1]), 0])
                  b = np.cross(dl, np.array([rx,ry,rz]))
                  e = constant*I*b/r**3
                  b2[y][x] += e[2] # why not x y?
      return b2
  
  xwidth = 15 
  ywidth = 15
  delay = 1
  x = np.arange(0, xwidth, delay)
  y = np.arange(0, ywidth, delay)
  X, Y = np.meshgrid(x, y)
  slicee = 0.1
  Z = bfield(X,Y,slicee)
  
  # visualize
  plt.figure()
  CS = plt.contour(X, Y, Z)
  plt.clabel(CS, inline=1, fontsize=10)
  x1 = array([0,1,2,3,4,5,6,7,8,9,9,9,9,9,9,9,9,9,8,7,6,5])
  y1 = array([0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8,8,8,8])
  plot(x1,y1)
  plt.title('magnetic field')
  plt.show()
  </code></pre>
  
  <p>Last edit:
  Finally i did it without numpy.
  The following version works.</p>
  
  <pre><code># Calculation of a magnetic field of a wire
  # later I want to to it three dimensional
  
  import matplotlib
  import numpy as np
  import matplotlib.cm as cm
  import matplotlib.mlab as mlab
  import matplotlib.pyplot as plt
  from pylab import *
  
  # constant
  I = 10000000000
  mu0 = 1e-7
  constant = mu0/(4*np.pi)
  
  # wire position
  coord = [(10,10), (20,10), (20,20), (10,20), (10,25)]
  coord2 = []
  
  # devide path of the wire in parts of length one
  parts = 0
  for n in range(len(coord)-1):
      lengthx = coord[n+1][0] - coord[n][0]
      lengthy = coord[n+1][1] - coord[n][1]
      length = (lengthx**2 + lengthy**2)**.5
      for m in range(int(length)):
          coord2.append((coord[n][0]+lengthx/length*m, coord[n][1]+lengthy/length*m))
          parts += 1
  
  # calculate the b-field
  def bfield(x,y,z):
      b = 0
      for i in range(parts-1):
          dlx = coord2[i+1][0]-coord2[i][0]
          dly = coord2[i+1][1]-coord2[i][1] 
          dlz = 0
          dl = np.array([dlx,dly,dlz])
          rspace_minus_rwire_x = x - (coord2[i][0]+dlx)
          rspace_minus_rwire_y = y - (coord2[i][1]+dly)
          rspace_minus_rwire_z = z - 0
          rspace_minus_rwire = np.array([rspace_minus_rwire_x, rspace_minus_rwire_y, rspace_minus_rwire_z])
          absr = (rspace_minus_rwire_x**2 + rspace_minus_rwire_y**2 + rspace_minus_rwire_z**2)**0.5
          a = constant * I * np.cross(dl, rspace_minus_rwire) / absr**3
          b += (a[0]**2 + a[1]**2 + a[2]**2)**0.5
      return b
  
  xwidth = 26
  ywidth = 26
  z = 1
  bmatrix = np.zeros((xwidth,ywidth))
  for x in range(xwidth):
      for y in range(ywidth):
          bmatrix[x][y] = bfield(x,y,z)
  
  # visualize
  plt.figure()
  x = range(xwidth)
  y = range(ywidth)
  z = bmatrix[x][y].T
  contour(x,y,z,35)
  plt.show()
  </code></pre>