magnetostatics.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. """Compute the magnetic field B in an iron cylinder,
  2. the copper wires, and the surrounding vacuum.
  3. Isolines of Az are also shown."""
  4. # https://fenicsproject.org/pub/tutorial/html/._ftut1015.html
  5. # conda install conda-forge::mshr
  6. from fenics import *
  7. from mshr import *
  8. from math import sin, cos, pi
  9. a = 1.0 # inner radius of iron cylinder
  10. b = 1.2 # outer radius of iron cylinder
  11. c_1 = 0.8 # radius for inner circle of copper wires
  12. c_2 = 1.4 # radius for outer circle of copper wires
  13. r = 0.1 # radius of copper wires
  14. R = 2.5 # radius of domain
  15. n = 5 # number of windings
  16. # Define geometry for background
  17. domain = Circle(Point(0, 0), R)
  18. # Define geometry for iron cylinder
  19. cylinder = Circle(Point(0, 0), b) - Circle(Point(0, 0), a)
  20. # Define geometry for wires (N = North (up), S = South (down))
  21. angles_N = [i*2*pi/n for i in range(n)]
  22. angles_S = [(i + 0.5)*2*pi/n for i in range(n)]
  23. wires_N = [Circle(Point(c_1*cos(v), c_1*sin(v)), r) for v in angles_N]
  24. wires_S = [Circle(Point(c_2*cos(v), c_2*sin(v)), r) for v in angles_S]
  25. # Set subdomain for iron cylinder
  26. domain.set_subdomain(1, cylinder)
  27. # Set subdomains for wires
  28. for (i, wire) in enumerate(wires_N):
  29. domain.set_subdomain(2 + i, wire)
  30. for (i, wire) in enumerate(wires_S):
  31. domain.set_subdomain(2 + n + i, wire)
  32. # Create mesh
  33. mesh = generate_mesh(domain, 64)
  34. # Define function space
  35. V = FunctionSpace(mesh, 'P', 1)
  36. # Define boundary condition
  37. bc = DirichletBC(V, Constant(0), 'on_boundary')
  38. # Define subdomain markers and integration measure
  39. markers = MeshFunction('size_t', mesh, 2, mesh.domains())
  40. dx = Measure('dx', domain=mesh, subdomain_data=markers)
  41. # Define current densities
  42. J_N = Constant(1.0)
  43. J_S = Constant(-1.0)
  44. # Define magnetic permeability
  45. class Permeability(UserExpression):
  46. def __init__(self, markers, **kwargs):
  47. self.markers = markers
  48. super().__init__(**kwargs)
  49. def eval_cell(self, values, x, cell):
  50. if self.markers[cell.index] == 0:
  51. values[0] = 4*pi*1e-7 # vacuum
  52. elif self.markers[cell.index] == 1:
  53. values[0] = 1e-5 # iron (should really be 6.3e-3)
  54. else:
  55. values[0] = 1.26e-6 # copper
  56. mu = Permeability(markers, degree=1)
  57. # Define variational problem
  58. A_z = TrialFunction(V)
  59. v = TestFunction(V)
  60. a = (1 / mu)*dot(grad(A_z), grad(v))*dx
  61. L_N = sum(J_N*v*dx(i) for i in range(2, 2 + n))
  62. L_S = sum(J_S*v*dx(i) for i in range(2 + n, 2 + 2*n))
  63. L = L_N + L_S
  64. # Solve variational problem
  65. A_z = Function(V)
  66. solve(a == L, A_z, bc)
  67. # Compute magnetic field (B = curl A)
  68. W = VectorFunctionSpace(mesh, 'P', 1)
  69. B = project(as_vector((A_z.dx(1), -A_z.dx(0))), W)
  70. # Plot solution
  71. from vedo.dolfin import plot
  72. plot(A_z, B,
  73. lw=0, # linewidth of mesh
  74. isolines={'n':10, 'lw':0, 'c':'black'},
  75. scalarbar=False,
  76. )