Calculate and plot the field of rectangular coils. Either single coils or Helmholtz pairs.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

625 lines
26 KiB

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. import logging as log
  4. import scipy.constants as cs
  5. from mpl_toolkits.axes_grid1 import host_subplot
  6. import mpl_toolkits.axisartist as AA
  7. # TODO:
  8. # -Different wire winding schemes
  9. # -Plot a cut through the Coil
  10. # -Plotte den erlaubten unsicherheitsbereich in die B-Feld plots. (durchsichtige Box sollte reichen)
  11. # -Möchte ich HHCoils als klasse oder funktion?
  12. # --> Einmal B berechnen und dann funktionen druaf anwenden oder einmal objekt kreieren?
  13. # --> Mit sinnvollen funktionen eigentlich kein unterschied
  14. # -Coords in meter oder mm
  15. """
  16. The following functions allow the calculation of the magnetic field of rectangular coils.
  17. The most important important inputs the following:
  18. -"distance" describes the distance between two coils in Helmholtz (HH) config in mm. In the case of a single coil,
  19. it is the offset of its plane from zero in mm.
  20. -"a" is the side length of the coil(s) in +/- x direction in mm, when the coil is lying in the z-plane.
  21. -"b" is the side length of the coil(s) in +/- y direction in mm, when the coil is lying in the z-plane.
  22. -"plane" describes the plane in which the coil lies. "plane = 'z'" describes a coil which extends in x and y
  23. direction with its sides and has an offset of "distance" mm in z direction.
  24. -The wire parameters layers, windings, wire_width and wire_height describe the winding of the coil. The side lengths
  25. "a" and "b" are defined with regard to the center of the coil winding. That means, a coil with side length a has
  26. wires extending from a-h to a+h, where h is the height of the accumulated winding layers.
  27. -NO REAL WINDING SCHEME IS IMPLEMENTED.
  28. Instead of crossing wires, the coil is made up of many single wire coils lying next to each other. In reality, a
  29. layer of 5 wires is followed by a layer of 4 wires, as the next layer always sits in the groves of the layer below.
  30. THIS IS NOT IMPLEMENTED. Here "layers =3, windings = 5" means that 15 wires in total sit perfectly on top of each
  31. other. They are not filling any gaps and have a height of exactly 3*(wire_height+insulation thickness).
  32. -The calculation is done once per wire, as if it where a coil without physical extend in the center of the wire.
  33. -The parameter "center_offset" allows for coils that are not centered around an axis, but have some offset.
  34. The center offset is to be given as a list of the three coords, that define the center of the coil (pair) in m(!).
  35. Note that the "distance" is calculated from this new center. For non ideal/crooked HH coils, define 2 individual
  36. coils with two individual centers.
  37. -The calculation of the field is done a whichever coordinates are given as an input to the various field calculation
  38. functions (mainly calc_B_field_coil() or HH_coil_calc_B_field). The coords have to be given in units of meters and
  39. the output will be a set of three components of the field for each coordinate in Gauss. The field can also be given
  40. in Tesla.
  41. """
  42. class RectangularCoil:
  43. def __init__(self, distance, a, b, plane, layers, windings, wire_width, wire_height, I, mu0=cs.mu_0,
  44. center_offset=None, insulation_thickness=0., is_round=True, winding_offset=False, unit="Gauss"):
  45. # if center is None:
  46. # center = [0, 0, 0]
  47. if not is_round:
  48. log.warning("Non-round wires not implemented yet. Please choose round wires instead.")
  49. if is_round:
  50. if wire_width != wire_height:
  51. log.error('Wire is round but width != height')
  52. self.distance = distance * 1e-3
  53. self.a = a * 1e-3
  54. self.b = b * 1e-3
  55. self.plane = plane
  56. self.layers = layers
  57. self.windings = windings
  58. self.wire_width = wire_width * 1e-3
  59. self.wire_height = wire_height * 1e-3
  60. self.I = I
  61. self.mu0 = mu0
  62. self.insulation_thickness = insulation_thickness * 1e-3
  63. self.is_round = is_round
  64. self.winding_offset = winding_offset
  65. self.unit = unit
  66. if center_offset is None:
  67. self.center_offset = [0,0,0]
  68. else:
  69. self.center_offset = center_offset
  70. def get_N(self):
  71. """
  72. Calculates number of windings
  73. """
  74. return self.layers * self.windings
  75. def wires(self):
  76. """
  77. According to the wire geometry the winding is done and layers of wires are stacked. Each loop of wire can then be treated as a coil each.
  78. """
  79. width = self.wire_width + 2 * self.insulation_thickness
  80. coil_width = self.windings * width
  81. coil_height = self.layers * width
  82. Coilwires = np.zeros( (self.get_N(), 3) ) # Each wire of the coil will be stored in Coilwires with Params = (distance, a, b)
  83. """
  84. This winding scheme just lays wires next to each other and on top of each other, but only their radius etc is used. The geometry is not yet accounted for.
  85. """
  86. # Fill in different Wirewinding schemes later
  87. """
  88. The Coil is centered around the parameters d,a,b
  89. """
  90. for L in range(self.layers):
  91. layer_offset = -coil_height / 2 + (2 * L + 1) * width / 2
  92. a_layer = self.a - layer_offset
  93. b_layer = self.b - layer_offset
  94. for W in range(self.windings):
  95. d_offset = -coil_width / 2 + (2 * W + 1) * width / 2
  96. distance_wire = self.distance - d_offset
  97. Coilwires[L * self.windings + W] = np.array([distance_wire, a_layer, b_layer])
  98. return Coilwires
  99. def calc_B_field_z_wire(self, coords, wire):
  100. x = coords[0]
  101. y = coords[1]
  102. z = coords[2]
  103. a_wire = wire[1] / 2 # The input is the side-length, but the calculation uses half-lengths of each side
  104. b_wire = wire[2] / 2
  105. c1 = a_wire + x
  106. c2 = a_wire - x
  107. c3 = -c2
  108. c4 = -c1
  109. d1 = y + b_wire
  110. d2 = d1
  111. d3 = y - b_wire
  112. d4 = d3
  113. r1 = np.sqrt((a_wire + x) ** 2 + (y + b_wire) ** 2 + z ** 2)
  114. r2 = np.sqrt((a_wire - x) ** 2 + (y + b_wire) ** 2 + z ** 2)
  115. r3 = np.sqrt((a_wire - x) ** 2 + (y - b_wire) ** 2 + z ** 2)
  116. r4 = np.sqrt((a_wire + x) ** 2 + (y - b_wire) ** 2 + z ** 2)
  117. const = self.mu0 * self.I / (4 * cs.pi)
  118. Bx = const * (z / (r1 * (r1 + d1)) - z / (r2 * (r2 + d2)) + z / (r3 * (r3 + d3)) - z / (r4 * (r4 + d4)))
  119. By = const * (z / (r1 * (r1 + c1)) - z / (r2 * (r2 - c2)) + z / (r3 * (r3 + c3)) - z / (r4 * (r4 - c4)))
  120. Bz = const * (-1 * d1 / (r1 * (r1 + c1)) - c1 / (r1 * (r1 + d1)) + d2 / (r2 * (r2 - c2)) - c2 / (
  121. r2 * (r2 + d2)) - d3 / (r3 * (r3 + c3)) - c3 / (r3 * (r3 + d3)) + d4 / (r4 * (r4 - c4)) - c4 / (
  122. r4 * (r4 + d4)))
  123. return Bx, By, Bz
  124. def calc_B_field_any_wire(self, coords, wire):
  125. x_coords = coords[0]
  126. y_coords = coords[1]
  127. z_coords = coords[2]
  128. distance_wire = wire[0]
  129. x_center = self.center_offset[0]
  130. y_center = self.center_offset[1]
  131. z_center = self.center_offset[2]
  132. """
  133. The input coords are the actual physical coordinates, at which the BField is to be calculated.
  134. The calculation is only done for Coils that lie in the z-plane. Therefore the input has to be rotated,
  135. and shifted in z-direction (depending on the winding) and the resulting fields are then rotated back.
  136. Therefore the parameter "plane" has to be given to determine in which plane the coil lies.
  137. """
  138. if self.plane == "x":
  139. x_center, y_center, z_center = -z_center, y_center, x_center
  140. x_coords, y_coords, z_coords = -z_coords, y_coords, x_coords
  141. elif self.plane == "y":
  142. x_center, y_center, z_center = x_center, -z_center, y_center
  143. x_coords, y_coords, z_coords = x_coords, -z_coords, y_coords
  144. elif self.plane == "z":
  145. pass
  146. else:
  147. log.error("Unexpected plane. Please choose 'x', 'y' or 'z'.")
  148. """
  149. The rotated coil now lies in the z-plane.
  150. By subtracting the distance_wire from the coords, the distnace of the wire to the z-plane is accounted for.
  151. Then, the accordingly rotated coordinates of the center of the coils can be subtracted likewise from the coords, where B is calculated.
  152. Therefore not the coil in the coordsys is shifted by +offset, but the coordsystem is shifted by -offset, which results in the same offset.
  153. """
  154. offset_coords = np.array([x_coords - x_center, y_coords - y_center, (z_coords - distance_wire - z_center)])
  155. x_field, y_field, z_field = self.calc_B_field_z_wire(offset_coords, wire)
  156. if self.plane == "x":
  157. x_field, y_field, z_field = z_field, y_field, -x_field
  158. elif self.plane == "y":
  159. x_field, y_field, z_field = x_field, z_field, -y_field
  160. elif self.plane == "z":
  161. pass
  162. else:
  163. log.error("Unexpected plane. Please choose 'x', 'y' or 'z'.")
  164. field = np.array([x_field, y_field, z_field])
  165. return field
  166. def calc_B_field_coil(self, coords): # B Field of one Coil. No HH config
  167. B_coil = np.zeros(np.shape(coords))
  168. Coil_Wires = self.wires()
  169. """
  170. To calculate B-Field of whole coil, calculate B-field once per wire
  171. """
  172. for l in range(self.layers):
  173. for w in range(self.windings):
  174. B_coil += self.calc_B_field_any_wire(coords, Coil_Wires[l * self.windings + w])
  175. if self.unit.lower() == "gauss":
  176. B_coil = B_coil * 1e4
  177. elif self.unit.lower() == "tesla":
  178. pass
  179. else:
  180. log.warning(f"{self.unit} Not recognized. Please choose unit 'gauss' or 'tesla'.")
  181. return B_coil
  182. def cooling(self, I_current, T):
  183. """
  184. Print current density and power
  185. Parameters
  186. ----------
  187. I_current : current in A
  188. T : temperature in degree Celsius
  189. Returns
  190. -------
  191. None.
  192. """
  193. j_dens = I_current / self.get_wire_area() * 1e-6
  194. Power = self.power(I_current, T)
  195. Voltage = self.resistance(T) * I_current
  196. print("")
  197. print("Cooling:")
  198. print(f" current density = {j_dens} A/mm^2")
  199. print(f" Power = {Power} W")
  200. print(f" U = {Voltage} V")
  201. def power(self, I_current, T):
  202. P = self.resistance(T) * I_current ** 2
  203. return P
  204. def resistance(self, T):
  205. """
  206. Calculates resistance of one coil of configuration
  207. Parameters
  208. ----------
  209. T : double
  210. temperature in degree Celsius
  211. Returns
  212. -------
  213. double
  214. resistance in Ohm
  215. """
  216. return RectangularCoil.resistivity_copper(T) * self.get_wire_length() / self.get_wire_area()
  217. def get_wire_length(self):
  218. """
  219. :return: Approximate length of wire per coil (m)
  220. """
  221. return self.get_N() * 2 * (self.a + self.b)
  222. def get_wire_area(self):
  223. """
  224. calculates wire area in m^2
  225. :return: float
  226. """
  227. if self.is_round:
  228. return np.pi * (self.wire_width / 2) ** 2
  229. return self.wire_width * self.wire_height
  230. @staticmethod
  231. def resistivity_copper(T):
  232. R_ref = 1.68e-8 # Resistance at T=20
  233. T_ref = 20 # degree celsius
  234. alpha = 0.00393
  235. R = R_ref * (1 + alpha * (T - T_ref))
  236. return R
  237. @staticmethod
  238. def HHCoil_calc_B_field(Coords, d, a, b, plane, layers, windings, wire_width, wire_height, I, mu0=4e-7 * np.pi,
  239. center_offset=None,
  240. insulation_thickness=0., is_round=True, winding_offset=False, unit="Gauss"):
  241. Coil1 = RectangularCoil(distance=d / 2, a=a, b=b, plane=plane, layers=layers, windings=windings,
  242. wire_width=wire_width, wire_height=wire_height, I=I, mu0=mu0, center_offset=center_offset,
  243. insulation_thickness=insulation_thickness, is_round=is_round,
  244. winding_offset=winding_offset, unit=unit)
  245. Coil2 = RectangularCoil(distance=-d / 2, a=a, b=b, plane=plane, layers=layers, windings=windings,
  246. wire_width=wire_width, wire_height=wire_height, I=I, mu0=mu0, center_offset=center_offset,
  247. insulation_thickness=insulation_thickness, is_round=is_round,
  248. winding_offset=winding_offset, unit=unit)
  249. B = Coil1.calc_B_field_coil(Coords)
  250. B += Coil2.calc_B_field_coil(Coords)
  251. return B
  252. @staticmethod
  253. def HHCoil_calc_total_B_field(Coords, d, a, b, plane, layers, windings, wire_width, wire_height, I,
  254. mu0=4e-7 * np.pi,
  255. center_offset=None,
  256. insulation_thickness=0., is_round=True, winding_offset=False, unit="Gauss"):
  257. Coil1 = RectangularCoil(distance=d / 2, a=a, b=b, plane=plane, layers=layers, windings=windings,
  258. wire_width=wire_width, wire_height=wire_height, I=I, mu0=mu0, center_offset=center_offset,
  259. insulation_thickness=insulation_thickness, is_round=is_round,
  260. winding_offset=winding_offset, unit=unit)
  261. Coil2 = RectangularCoil(distance=-d / 2, a=a, b=b, plane=plane, layers=layers, windings=windings,
  262. wire_width=wire_width, wire_height=wire_height, I=I, mu0=mu0, center_offset=center_offset,
  263. insulation_thickness=insulation_thickness, is_round=is_round,
  264. winding_offset=winding_offset, unit=unit)
  265. B = Coil1.calc_B_field_coil(Coords)
  266. B += Coil2.calc_B_field_coil(Coords)
  267. B = np.sqrt(B[0] ** 2 + B[1] ** 2 + B[2] ** 2)
  268. return B
  269. @staticmethod
  270. def grad(B_f, z):
  271. return np.gradient(B_f, z) # *1e3)
  272. @staticmethod
  273. def curv(B_f, z):
  274. return np.gradient(np.gradient(B_f, z)) # *1e3), z*1e3)
  275. @staticmethod
  276. def calc_B_i_grad(Field_i, Coords_i):
  277. """
  278. The '_i' is supposed to indicate, that this function only takes scalar inputs. Total field is possible as well.
  279. """
  280. Grad_Field = RectangularCoil.grad(Field_i, Coords_i)
  281. return Grad_Field
  282. @staticmethod
  283. def calc_B_i_curv(Field_i, Coords_i):
  284. Curv_Field = RectangularCoil.curv(Field_i, Coords_i)
  285. return Curv_Field
  286. @staticmethod
  287. def plot_B_i(Field_i, Coords_i, show=False):
  288. plt.plot(Coords_i, Field_i, ls="-", label=r"$B_{tot}$")
  289. plt.ylabel("Total Magnetic Field along axis")
  290. plt.xlabel("axis [m]")
  291. plt.ylabel("Magnetic field strength [G]")
  292. plt.grid()
  293. if show:
  294. plt.show()
  295. @staticmethod
  296. def plot_B_grad_i(Field_i, Coords_i, show=False):
  297. Grad_Field_i = RectangularCoil.calc_B_i_grad(Field_i, Coords_i)
  298. plt.plot(Coords_i, Grad_Field_i, ls="-.", label=r"$grad(B_{tot})$")
  299. plt.ylabel("Total Magnetic Field Gradient along axis")
  300. plt.xlabel("axis [m]")
  301. plt.ylabel("Magnetic field Gradient [G/m]")
  302. plt.grid()
  303. if show:
  304. plt.show()
  305. @staticmethod
  306. def plot_B_curv_i(Field_i, Coords_i, show=False):
  307. Curv_Field_i = RectangularCoil.calc_B_i_curv(Field_i, Coords_i)
  308. plt.plot(Coords_i, Curv_Field_i, ls="-.", label=r"$curv(B_{tot})$")
  309. plt.ylabel("Total Magnetic Field Curvature along axis")
  310. plt.xlabel("axis [m]")
  311. plt.ylabel("Magnetic field Curvature [G/m^2]")
  312. plt.grid()
  313. if show:
  314. plt.show()
  315. @staticmethod
  316. def plot_B_everything_fancy(Field_i, Coords_i, f=0, show=True):
  317. Grad_Field_i = RectangularCoil.grad(Field_i, Coords_i)
  318. Curv_Field_i = RectangularCoil.curv(Field_i, Coords_i)
  319. xmin, xmax = np.min(Coords_i) * (1 - f), np.max(Coords_i) * (1 + f)
  320. y0min, y0max = np.min(Field_i) * (1 - f), np.max(Field_i) * (1 + f)
  321. y1min, y1max = np.min(Grad_Field_i) * (1 - f), np.max(Grad_Field_i) * (1 + f)
  322. y2min, y2max = np.min(Curv_Field_i[2:-2:]) * (1 - f), np.max(Curv_Field_i[2:-2:]) * (1 + f)
  323. host = host_subplot(111, axes_class=AA.Axes)
  324. plt.subplots_adjust(right=0.75)
  325. par1 = host.twinx()
  326. par2 = host.twinx()
  327. new_fixed_axis = par2.get_grid_helper().new_fixed_axis
  328. par1.axis["right"] = new_fixed_axis(loc="right", axes=par1, offset=(0, 0))
  329. par1.axis["right"].toggle(all=True)
  330. par2.axis["right"] = new_fixed_axis(loc="right", axes=par2, offset=(60, 0))
  331. par2.axis["right"].toggle(all=True)
  332. host.set_xlim(xmin, xmax)
  333. host.set_ylim(y0min, y0max)
  334. host.set_xlabel("axis [m]")
  335. host.set_ylabel("Field strength [G]")
  336. par1.set_ylabel("Field Gradient [G/m]")
  337. par2.set_ylabel("Field Curvature [G/m^2]")
  338. p1, = host.plot(Coords_i, Field_i, label="Srength")
  339. p2, = par1.plot(Coords_i, Grad_Field_i, label="Gradient")
  340. p3, = par2.plot(Coords_i, Curv_Field_i, label="Curvature")
  341. par1.set_ylim(y1min, y1max)
  342. par2.set_ylim(y2min, y2max)
  343. host.legend()
  344. host.axis["left"].label.set_color(p1.get_color())
  345. par1.axis["right"].label.set_color(p2.get_color())
  346. par2.axis["right"].label.set_color(p3.get_color())
  347. host.grid()
  348. par1.grid(alpha=0.3)
  349. par2.grid(alpha=0.3)
  350. plt.draw()
  351. if show:
  352. plt.show()
  353. @staticmethod
  354. def plot_B_everything_simple(Field_i, Coords_i, f=1.1):
  355. RectangularCoil.plot_B_i(Field_i, Coords_i)
  356. RectangularCoil.plot_B_grad_i(Field_i, Coords_i)
  357. RectangularCoil.plot_B_curv_i(Field_i, Coords_i)
  358. plt.legend()
  359. plt.show()
  360. @staticmethod
  361. def homogenity_1D(Field_i, Coords_i, Range, perc=False):
  362. """
  363. first check whether 0 is in the list of coords or not
  364. if not, calc B(0).
  365. """
  366. clipped_coords = Coords_i[(-Range <= Coords_i)]
  367. clipped_coords = clipped_coords[(clipped_coords <= Range)]
  368. near0 = np.min(np.abs(Coords_i))
  369. index = np.where(np.abs(Coords_i) == near0)
  370. if near0 != 0:
  371. print(
  372. f"Point (0,0,0) not part of given coordinate list. Closest point is {near0} and will be used for calculation.")
  373. else:
  374. pass
  375. index1 = int(np.where(clipped_coords[0] == Coords_i)[0])
  376. index2 = int(np.where(clipped_coords[-1] == Coords_i)[0])
  377. homogenity = np.abs((Field_i - Field_i[index]) / Field_i[index])
  378. if perc:
  379. homogenity = homogenity[index1:index2 + 1:] * 100
  380. print(f"The max. inhomogenity in the range of +/- {Range}m was {np.max(np.abs(homogenity)) * 100} %")
  381. else:
  382. homogenity = homogenity[index1:index2 + 1:]
  383. print(f"The max. inhomogenity in the range of +/- {Range}m was {np.max(np.abs(homogenity)) }")
  384. return clipped_coords, homogenity
  385. def Mutual_Inductance_Rover(self):
  386. """
  387. Mutual inductance of two equal parallel rectangles according to Rosa & Grover
  388. p1,p2,p3 only introduced for readability
  389. """
  390. a = self.a * 100 # Converion to [cm]
  391. b = self.b * 100
  392. d = self.distance * 100
  393. p1 = (a + np.sqrt(a ** 2 + d ** 2)) * np.sqrt(b ** 2 + d ** 2) / ((a + np.sqrt(a ** 2 + b ** 2 + d ** 2)) * d)
  394. p2 = (b + np.sqrt(b ** 2 + d ** 2)) * np.sqrt(a ** 2 + d ** 2) / ((b + np.sqrt(a ** 2 + b ** 2 + d ** 2)) * d)
  395. p3 = np.sqrt(a ** 2 + b ** 2 + d ** 2) - np.sqrt(a ** 2 + d ** 2) - np.sqrt(b ** 2 + d ** 2) + d
  396. M = 4 * (a * np.log(p1) + b * np.log(p2)) + 8 * p3
  397. M *= self.get_N()**2 * 1e-9 #Conversion to SI and accounting for N wires
  398. return M
  399. def Self_Inductance_Rover(self):
  400. a = self.a * 100 #Converion to [cm]
  401. b = self.b * 100
  402. r = self.wire_width/2 *100
  403. diag = np.sqrt(a**2 + b**2)
  404. L = 4 * ( (a+b) * np.log(2*a*b / r) - a * np.log(a+diag) - b * np.log(b+diag) - 7/4 * (a+b) + 2 * (diag + r) )
  405. L *= self.get_N()**2 * 1e-9 #Conversion to SI and accounting for N wires
  406. return L
  407. @staticmethod
  408. def Self_Inductance_Abbot(alpha, beta, gamma, N):
  409. """
  410. Formula for self inductance of SQUARE coil by J.J.Abbott
  411. """
  412. L = (1e-5 * alpha**2 * N**2) / (3*alpha + 9*beta + 10*gamma)
  413. return L
  414. def Total_Inductance_Abbot(self):
  415. """
  416. Above Formula for self inductance used, but with modified alpha to roughly represent rect. coils.
  417. Total inductance then according to Grover
  418. """
  419. alpha = (self.a + self.b) / 2
  420. width = self.wire_width + 2 * self.insulation_thickness
  421. hight = self.wire_height + 2 * self.insulation_thickness
  422. beta = self.windings * width
  423. gamma = self.layers * hight
  424. N = self.get_N()
  425. dist = self.distance
  426. L_tot = RectangularCoil.Self_Inductance_Abbot(alpha, dist + gamma, gamma, N) + RectangularCoil.Self_Inductance_Abbot(alpha, dist - gamma, gamma, N) - 2 * RectangularCoil.Self_Inductance_Abbot(alpha, dist, gamma, N) + 2 * RectangularCoil.Self_Inductance_Abbot(alpha, beta, gamma, N)
  427. return L_tot
  428. def Total_Inductance_Rover(self):
  429. L = self.Self_Inductance_Rover()
  430. M = self.Mutual_Inductance_Rover()
  431. L_tot = 2 * (L+M)
  432. return L_tot
  433. @staticmethod
  434. def I_time_response(U, R, L, t):
  435. I = np.abs(U) / R * (1 - np.exp(-R * t*1e-3 / L))
  436. return I
  437. def main():
  438. """
  439. Up to 1e5 steps for up to 100 wires take a reasonable amount of time
  440. """
  441. x0 = np.linspace(-0.001, 0.001, 1000)
  442. y0 = np.ones(np.shape(x0)) * 0 / 2
  443. z0 = np.ones(np.shape(y0)) * 0 / 2
  444. Coordsx = np.array([x0, y0, z0])
  445. #Coordsx2 = np.array([x0-0.01, y0, z0])
  446. y1 = np.linspace(-0.001, 0.001, 1000)
  447. x1 = np.ones(np.shape(y1)) * 0 / 2
  448. z1 = np.ones(np.shape(y1)) * 0 / 2
  449. Coordsy = np.array([x1, y1, z1])
  450. z2 = np.linspace(-0.001, 0.001, 1000)
  451. y2 = np.ones(np.shape(z2)) * 0 / 2
  452. x2 = np.ones(np.shape(y2)) * 0 / 2
  453. Coordsz = np.array([x2, y2, z2])
  454. Rec_off = RectangularCoil( 78.4 / 2, 129.4, 206.4, "z", 10, 10, 0.5, 0.5, 1, center_offset=[0, 0.000, 0])
  455. Rec_off_2 = RectangularCoil(-78.4 / 2, 129.4, 206.4, "z", 10, 10, 0.5, 0.5, 1, center_offset=[0, -0.000, 0])
  456. BLA = Rec_off.calc_B_field_coil(Coordsz)
  457. BLA2 = Rec_off_2.calc_B_field_coil(Coordsz)
  458. FIELD_off = BLA + BLA2
  459. Rec = RectangularCoil( 86 / 2, 142.2, 206.4, "z", 10, 10, 0.5, 0.5, 1)
  460. Rec2 = RectangularCoil(-86 / 2, 142.2, 206.4, "z", 10, 10, 0.5, 0.5, 1)
  461. BLA3 = Rec.calc_B_field_coil(Coordsx)
  462. BLA4 = Rec2.calc_B_field_coil(Coordsx)
  463. FIELD = BLA3 + BLA4
  464. homx = RectangularCoil.homogenity_1D(FIELD[0], Coordsy[1], 0.001)
  465. homy = RectangularCoil.homogenity_1D(FIELD[1], Coordsy[1], 0.001)
  466. homz = RectangularCoil.homogenity_1D(FIELD[2], Coordsy[1], 0.001)
  467. #plt.plot(Coordsx[0], FIELD[0], label=r"$\Delta$B_x")
  468. #plt.plot(Coordsx[0], FIELD[1], label=r"$\Delta$B_y")
  469. #plt.plot(Coordsx[0], FIELD[2], label=r"$\Delta$B_z")
  470. plt.plot(Coordsx[0], FIELD[0], label="x_off", alpha=0.6)
  471. plt.plot(Coordsx[0], FIELD[1], label="y_off", alpha=0.6)
  472. plt.plot(Coordsx[0], FIELD[2], label="z_off", alpha=0.6)
  473. plt.legend()
  474. plt.show()
  475. """
  476. Field = RectangularCoil.HHCoil_calc_B_field(Coordsx, 78.4, 129.4, 206.4, "z", 10, 10, 0.5, 0.5, 1)
  477. plt.plot(Coordsx[0], Field[0], label="x2")
  478. plt.plot(Coordsx[0], Field[1], label="2y")
  479. plt.plot(Coordsx[0], Field[2], label="z2")
  480. plt.show()
  481. Rec.cooling(1,20)
  482. t = np.linspace(0, 12, 1000)
  483. L = Rec.Total_Inductance_Abbot()
  484. L2 = Rec.Total_Inductance_Rover()
  485. R = RectangularCoil.resistance(Rec, T=20)
  486. I = RectangularCoil.I_time_response(U=4.82, R=R, L=L, t=t)
  487. I2 = RectangularCoil.I_time_response(U=4.82, R=R, L=L2, t=t)
  488. print("Inductance Abbott: ",L,"\n inductance rosa: ",L2,R)
  489. print("Resistance: ",R)
  490. tau = L/R
  491. tau2 = L2/R
  492. plt.figure(1,figsize=[8,6])
  493. #plt.title("Time Response for a=145, b=207, d=87.3 with 10x10 windings and 6 Volts")
  494. plt.plot(t, I, label=r"Abbott")#: time constant $ \tau $"+f" = {tau:.2e} s")
  495. plt.plot(t, I2, label=r"Rover")#: time constant $ \tau $"+f" = {tau:.2e} s")
  496. plt.hlines(1/np.sqrt(2), t[0],t[-1], color="tab:green")
  497. plt.legend(fontsize=12)
  498. plt.ylabel("Current I [A]",fontsize=12)
  499. plt.xlabel("Time t [ms]",fontsize=12)
  500. plt.xlim(t[0],t[-1])
  501. plt.ylim(0,1.1)
  502. plt.grid()
  503. plt.show()"""
  504. """
  505. axis = np.linspace(-0.001, 0.001, 1000)
  506. zeros = np.ones(np.shape(axis)) * 0
  507. Coordsx = np.array([axis, zeros, zeros])
  508. Coordsy = np.array([zeros, axis, zeros])
  509. Coordsz = np.array([zeros, zeros, axis])
  510. Bxaxis = RectangularCoil.HHCoil_calc_B_field(Coordsx, 86, 142.2, 206.4, "z", 10, 10, 0.546, 0.546, 1)
  511. Byaxis = RectangularCoil.HHCoil_calc_B_field(Coordsy, 86, 142.2, 206.4, "z", 10, 10, 0.546, 0.546, 1)
  512. Bzaxis = RectangularCoil.HHCoil_calc_B_field(Coordsz, 86, 142.2, 206.4, "z", 10, 10, 0.546, 0.546, 1)
  513. #BDiagaxis = RectangularCoil.HHCoil_calc_B_field(CoordsDiag, 78.4, 129.4, 206.4, "z", 10, 10, 0.546, 0.546, 1)
  514. Btot = RectangularCoil.HHCoil_calc_total_B_field(Coordsz, 78.4, 129.4, 206.4, "z", 10, 10, 0.546, 0.546, 1)
  515. #hxaxis = RectangularCoil.homogenity_1D(Bxaxis[0], Coordsx[0], 0.001, perc=False)
  516. #hyaxis = RectangularCoil.homogenity_1D(Byaxis[2], Coordsy[1], 0.001, perc=False)
  517. #hzaxis = RectangularCoil.homogenity_1D(Bzaxis[2], Coordsz[2], 0.001, perc=False)
  518. #H = np.array([hxaxis,hyaxis,hzaxis])
  519. plt.plot(axis, Bxaxis[2], label="B_z along x-axis")
  520. plt.plot(axis, Byaxis[2], label="B_z along y-axis")
  521. plt.plot(axis, Bzaxis[2], label="B_z along z-axis")
  522. plt.legend()
  523. plt.grid()
  524. plt.ylabel(r"$B(\vec{r})$ [G]")
  525. plt.xlabel("Position [m]")
  526. plt.show()"""
  527. main()