00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 import math, random, unittest, cProfile
00029
00030
00031
00032
00033
00034
00035
00036 class Vector(object):
00037 """
00038 """
00039 def __init__(self, p = [0, 0, 0]):
00040 self.x = float(p[0])
00041 self.y = float(p[1])
00042 self.z = float(p[2])
00043
00044 def __getitem__(self, key):
00045 if(key == 0):
00046 return self.x
00047 elif(key == 1):
00048 return self.y
00049 elif(key == 2):
00050 return self.z
00051 else:
00052 raise Exception("Invalid key to Vector")
00053
00054 def __setitem__(self, key, value):
00055 if(key == 0):
00056 self.x = value
00057 elif(key == 1):
00058 self.y = value
00059 elif(key == 2):
00060 self.z = value
00061 else:
00062 raise Exception("Invalid key to Vector")
00063
00064 def copy(self):
00065 return Vector([self.x,self.y,self.z])
00066
00067 def __neg__(self):
00068 return Vector([-self.x,-self.y,-self.z])
00069
00070 def __abs__(self):
00071 return math.sqrt(self.x*self.x+self.y*self.y+self.z*self.z)
00072
00073 def __pow__(self, val):
00074 return abs(self)**val
00075
00076 def __add__(self, val):
00077 return Vector([self.x + val.x, self.y + val.y, self.z + val.z])
00078
00079 def __iadd__(self, val):
00080 self.x += val.x
00081 self.y += val.y
00082 self.z += val.z
00083 return self
00084
00085 def __sub__(self,val):
00086 return Vector([self.x - val.x, self.y - val.y, self.z - val.z])
00087
00088 def __isub__(self, val):
00089 self.x -= val.x
00090 self.y -= val.y
00091 self.z -= val.z
00092 return self
00093
00094 def __mul__(self, val):
00095 if type(val) == Vector:
00096 return self.x * val.x + self.y * val.y + self.z * val.z
00097 else:
00098 return Vector([self.x * val, self.y * val, self.z * val])
00099
00100 def __rmul__(self, val):
00101 if type(val) == Vector:
00102 return self.x * val.x + self.y * val.y + self.z * val.z
00103 else:
00104 return Vector([self.x * val, self.y * val, self.z * val])
00105
00106 def __imul__(self, val):
00107 self.x *= val
00108 self.y *= val
00109 self.z *= val
00110 return self
00111
00112 def __div__(self, val):
00113 return Vector([self.x / val, self.y / val, self.z / val])
00114
00115 def __idiv__(self, val):
00116 self.x /= val
00117 self.y /= val
00118 self.z /= val
00119 return self
00120
00121 def outer(self,b):
00122 return Vector([self.y*b.z-self.z*b.y,
00123 self.z*b.x-self.x*b.z,
00124 self.x*b.y-self.y*b.x])
00125
00126 def normalize(self):
00127 if abs(self)<1e-9:
00128 self.x = 0.0
00129 self.y = 0.0
00130 self.z = 0.0
00131 else:
00132 l = abs(self)
00133 self.x /= l
00134 self.y /= l
00135 self.z /= l
00136 return self
00137
00138 def __eq__(self,other):
00139 if (self.x==other.x) & (self.y==other.y) & (self.z==other.z):
00140 return True
00141 else:
00142 return False
00143
00144 def __ne__(self,other):
00145 return not(self==other)
00146
00147 def __repr__(self):
00148 return "[" + str(self.x) + "," + str(self.y) + "," + str(self.z) + "]"
00149
00150 def __str__(self):
00151 return "(" + str(self.x) + "," + str(self.y) + "," + str(self.z) + ")"
00152
00153 class TestVectorClass(unittest.TestCase):
00154 def setUp(self):
00155 self.x=Vector([1,0,0])
00156 self.y=Vector([0,1,0])
00157 self.z=Vector([0,0,1])
00158 self.a=Vector([3,0,0])
00159 self.b=Vector([0,4,0])
00160 self.c=Vector([3,4,0])
00161
00162 def testNeg(self):
00163 t = self.c.copy()
00164 t = -t
00165 self.assertEqual(t,Vector([-3,-4,0]))
00166
00167 def testAbs(self):
00168 t=abs(self.a)
00169 self.assertEqual(t,3.0)
00170 t=abs(self.c)
00171 self.assertEqual(t,5.0)
00172
00173 def testPow(self):
00174 t=self.a**2.0
00175 self.assertEqual(t,abs(self.a)**2.0)
00176 t=abs(self.c)
00177 self.assertEqual(t,5.0)
00178
00179 def testSimpleArithmetics(self):
00180 t = self.x+self.y
00181 self.assertEqual(t,Vector([1,1,0]))
00182 t -= self.y
00183 self.assertEqual(t,self.x)
00184 t = self.x - self.y
00185 self.assertEqual(t,Vector([1,-1,0]))
00186 t += self.y
00187 self.assertEqual(t,self.x)
00188 t = self.x * 3.0
00189 self.assertEqual(t,self.a)
00190 t /= 3.0
00191 self.assertEqual(t,self.x)
00192 t = self.a / 3.0
00193 self.assertEqual(t,self.x)
00194 t *= 3.0
00195 self.assertEqual(t,self.a)
00196 t = self.x * self.a
00197 self.assertEqual(t,3.0)
00198
00199 def testOuter(self):
00200 t=self.x.outer(self.y)
00201 self.assertEqual(t,self.z)
00202
00203 def testNormalize(self):
00204 t=self.a.normalize()
00205 self.assertEqual(t,self.x)
00206
00207 def initialize_magnetization_mx(r):
00208 """
00209 """
00210 return Vector([1.0, 0.0, 0.0])
00211
00212 def initialize_magnetization_my(r):
00213 """
00214 """
00215 return Vector([0.0, 1.0, 0.0])
00216
00217 def initialize_magnetization_mz(r):
00218 """
00219 """
00220 return Vector([0.0, 0.0, 1.0])
00221
00222 def initialize_magnetization_111(r):
00223 """
00224 """
00225 a=math.sqrt(1.0/3.0)
00226 return Vector([a, a, a])
00227
00228 def initialize_magnetization_theta_rad(r, theta = 0):
00229 """Set magnetization in x-z plane to desired angle theta (from z-axis)
00230 """
00231
00232 return Vector([math.sin(theta), 0.0, math.cos(theta)])
00233
00234 def initialize_magnetization_theta_deg(r, theta_deg = 0):
00235 m = initialize_magnetization_theta_rad(r,math.radians(theta_deg))
00236
00237 return m
00238
00239 def initialize_magnetization_phi_rad(r, phi = 0):
00240 """Set magnetization in x-y plane to desired angle
00241 """
00242
00243 return Vector([math.cos(theta), math.sin(theta), 0.0])
00244
00245 def initialize_magnetization_phi_deg(r,phi_deg = 0):
00246 m = initialize_magnetization_phi_rad(r,math.radians(phi_deg))
00247
00248 return m
00249
00250 def initialize_magnetization_random(r):
00251 """Random magnetization - inaccurate: not uniform on unit sphere!
00252 """
00253
00254 mx = random.uniform(-1, 1)
00255 my = random.uniform(-1, 1)
00256 mz = random.uniform(-1, 1)
00257
00258 return Vector([mx, my, mz])
00259
00260 def initialize_magnetization_flower(r, c = Vector([0.0,0.0,0.0]), f = 1.0):
00261 """Approximate flower state (around z-axis)
00262 """
00263
00264 m = Vector([r[0]-c[0],r[1]-c[1],1.0])
00265 if (r[2]<0):
00266 m *= -1.0
00267
00268 return m
00269
00270 def vortex(p, R):
00271 """Approximate vortex state
00272
00273 vortex centered at (cx, cy) with radius R:
00274 if R>0, then vortex is counter-clockwise in xy plane.
00275 if R<0, then vortex is clockwise in xy plane.
00276 center of vortex points in pol*z direction.
00277 """
00278
00279 r=p.copy()
00280 r[2]=0
00281 absr=abs(r)
00282
00283
00284 if absr <= math.fabs(R):
00285 A = 2.0*R*absr/(R*R+absr*absr)
00286
00287 if (absr > 1e-8):
00288 m = Vector([A*r[1]/absr, -A*r[0]/absr, pol*math.sqrt(1.0-A*A)])
00289 else:
00290 m = Vector([0.0, 0.0, pol])
00291
00292 else:
00293 m = Vector([r[1]/absr, -r[0]/absr, 0.0])
00294
00295 if R<0:
00296 m[0]=-m[0]
00297 m[1]=-m[1]
00298
00299 return m
00300
00301 def initialize_magnetization_vortex(r, c = Vector([0.0,0.0,0.0])):
00302 """Approximate vortex state
00303 """
00304
00305
00306 R = 0.1
00307
00308
00309 pol = 1.0
00310
00311 m = vortex(r-c, R)
00312 m[2] *= pol
00313
00314 return Vector(m)
00315
00316 def initialize_magnetization_blochwall(r, xpos = 0.0, width = 0.1):
00317 """Bloch wall (parallel to y-z plane)
00318 """
00319
00320 if (r[0] < xpos-width/2.0):
00321 m = Vector([0.0, 0.0, -1.0])
00322 elif (r[0] > xpos+width/2.0):
00323 m = Vector([0.0, 0.0, 1.0])
00324 else:
00325 m = Vector([0.0,
00326 math.cos((r[0]-xpos)/(width/2.0)*(math.pi/2.0)),
00327 math.sin((r[0]-xpos)/(width/2.0)*(math.pi/2.0))])
00328
00329 return m
00330
00331 def initialize_magnetization_head_to_head_transverse(x, y, z, xpos = 0.0, width = 0.1):
00332 """Transverse head-to-head wall
00333 """
00334
00335 if (r[0] < xpos-width/2.0):
00336 m = Vector([1.0, 0.0, 0.0])
00337 elif (r[0] > xpos+width/2.0):
00338 m = Vector([-1.0, 0.0, 0.0])
00339 else:
00340 m = Vector([-math.sin((x-xpos)/(width/2.0)*(math.pi/2.0)),
00341 math.cos((x-xpos)/(width/2.0)*(math.pi/2.0)),
00342 0.0])
00343
00344 return m
00345
00346 def initialize_magnetization_head_to_head_vortex(r, xpos = 0.0, width = 0.1):
00347 """Approximate vortex head-to-head wall
00348
00349 Head-to-head vortex wall at (0, 0) with radius R
00350 if R>0, then vortex is clockwise in xy plane.
00351 if R<0, then vortex is counter-clockwise in xy plane.
00352 center of vortex points in -z direction.
00353 """
00354
00355 if (x < xpos-width/2.0):
00356 m = Vector([1.0, 0.0, 0.0])
00357 elif (x > xpos+width/2.0):
00358 m = Vector([-1.0, 0.0, 0.0])
00359 else:
00360 m = vortex(r-c, R)
00361 m[2] *= pol
00362
00363 return m
00364
00365 def external_field_homogeneous(r, theta_deg = 0.0, phi_deg = 0.0, amp_T = 0.0):
00366 """
00367 """
00368
00369 theta = math.radians(theta_deg)
00370 phi = math.radians(phi_deg)
00371
00372 h = Vector([amp_T*math.sin(theta)*math.cos(phi),
00373 amp_T*math.sin(theta)*math.sin(phi),
00374 amp_T*math.cos(theta)])
00375
00376 return h
00377
00378 def external_field_time_scaling(t_ns):
00379 """
00380 """
00381
00382 if (t_ns<0):
00383 amp_T=0
00384 else:
00385 amp_T=t_ns
00386
00387 return amp_T
00388
00389 class Line:
00390 def __init__(self,a,b):
00391 self.start_point = a
00392 self.end_point = b
00393 self.vector = b-a
00394 self.length = abs(b-a)
00395
00396 def __str__(self):
00397 return "start_point: " + str(self.start_point) + "\n" + \
00398 "end_point: " + str(self.end_point) + "\n" + \
00399 "vector: " + str(self.vector) + "\n" + \
00400 "length: " + str(self.length) + "\n"
00401
00402 class TestLineClass(unittest.TestCase):
00403 def setUp(self):
00404 self.a=Vector([3,0,0])
00405 self.b=Vector([0,4,0])
00406 self.line=Line(self.a,self.b)
00407
00408 def testvector(self):
00409 self.assertEqual(self.line.vector,Vector([-3,4,0]))
00410
00411 def testlength(self):
00412 self.assertEqual(self.line.length,5)
00413
00414 class Segment:
00415 def __init__(self,s,a,b):
00416 self.start = s
00417 self.line = Line(a,b)
00418
00419 def __str__(self):
00420 return "start: " + str(self.start) + "\n" + str(self.line)
00421
00422 class Polygon:
00423 def __init__(self):
00424 self.segments = []
00425 self.length = 0.0
00426
00427 def append_segment(self,a,b):
00428 self.segments.append(Segment(self.length,a,b))
00429 self.length += abs(b-a)
00430
00431 def point(self,u):
00432 for s in self.segments:
00433 if (u>=s.start/self.length) & (u<(s.start+s.line.length)/self.length):
00434 p = s.line.start_point + (u-s.start/self.length)*s.line.vector/s.line.length*self.length
00435 return p
00436
00437 def vec(self,u,length):
00438 for s in self.segments:
00439 if (u>=s.start/self.length) & (u<(s.start+s.line.length)/self.length):
00440 v = Vector(s.line.vector)
00441 v.normalize()
00442 return v*length
00443
00444 def __str__(self):
00445 string = "Polygon of length " + str(self.length) + \
00446 " with " + str(len(self.segments)) + " segments\n"
00447 for s in self.segments:
00448 string += str(s)
00449 return string
00450
00451 def test_straight_poly():
00452 poly_points=[]
00453 poly_points.append(Vector([-100.0,0.0,0.0]))
00454 poly_points.append(Vector([ -50.0,0.0,0.0]))
00455 poly_points.append(Vector([ -10.0,0.0,0.0]))
00456 poly_points.append(Vector([ 0.0,0.0,0.0]))
00457 poly_points.append(Vector([ 5.0,0.0,0.0]))
00458 poly_points.append(Vector([ 30.0,0.0,0.0]))
00459 poly_points.append(Vector([ 100.0,0.0,0.0]))
00460 polygon = Polygon()
00461 for s in range(len(poly_points)-1):
00462 polygon.append_segment(poly_points[s],poly_points[s+1])
00463 return polygon
00464
00465 class TestPolygonClass(unittest.TestCase):
00466 def setUp(self):
00467 self.polygon = test_straight_poly()
00468
00469 def testpoints(self):
00470 self.assertEqual(self.polygon.point(0),self.polygon.segments[0].line.start_point)
00471 self.assertEqual(self.polygon.length,200)
00472 self.assertEqual(self.polygon.point(0.5),Vector([0,0,0]))
00473 self.assertEqual(self.polygon.point(0.99),Vector([98,0,0]))
00474 self.assertEqual(self.polygon.vec(0,1),Vector([1,0,0]))
00475
00476 def biot_savart(current_A, r, ds):
00477 """Calculate magnetic field according to Biot-Savart law
00478
00479 dB=mu0*I/(4 pi)* (ds x r)/r^3
00480
00481 http://en.wikipedia.org/wiki/Biot-Savart_law
00482 http://maxwell.byu.edu/~spencerr/websumm122/node70.html
00483 http://hyperphysics.phy-astr.gsu.edu/HBASE/magnetic/magcur.html#c2
00484 """
00485
00486
00487
00488
00489 if abs(r)<1e-9:
00490
00491 h = Vector([0,0,0])
00492 else:
00493 h = 1e-7*current_A*ds.outer(r)/abs(r)**3.0
00494 return h
00495
00496 class TestBiotSavart(unittest.TestCase):
00497 def setUp(self):
00498 self.polygon = test_straight_poly()
00499
00500 def testfield(self):
00501 h=biot_savart(1.0, Vector([0,0,1]), Vector([0.01,0,0]))
00502 self.assertAlmostEqual(abs(h)*1e9,1,5)
00503 h.normalize()
00504 self.assertEqual(h,Vector([0,-1,0]))
00505
00506 def field_of_wire_slow(wire,current_A,r):
00507 npoints=10000
00508 h = Vector()
00509 for u in range(0,npoints):
00510
00511 h += biot_savart(current_A, \
00512 wire.point(u*1.0/npoints)-r, \
00513 wire.vec(u*1.0/npoints,wire.length/npoints))
00514 return h
00515
00516 def field_of_wire(wire,current_A,r):
00517 npoints=1000
00518 h = Vector()
00519 for s in wire.segments:
00520 for u in range(0,npoints):
00521 h += biot_savart(current_A, \
00522 s.line.start_point+s.line.vector*u/npoints-r, \
00523 s.line.vector/npoints)
00524 return h
00525
00526 class Test_external_field_wire(unittest.TestCase):
00527 def setUp(self):
00528 self.polygon = test_straight_poly()
00529
00530
00531 def testfield(self):
00532 h = field_of_wire_slow(self.polygon,1.0,Vector([0,0,0.1]))
00533
00534 self.assertAlmostEqual(abs(h)*1e7,20,4)
00535 h.normalize()
00536 self.assertEqual(h,Vector([0,1,0]))
00537
00538 def initmag(x, y, z):
00539 """Initialize magnetization with desired function called in here.
00540
00541 This function must be define after all the initialize_magnetization_* functions!
00542 """
00543
00544 r = Vector([x,y,z])
00545 m = initialize_magnetization_mx(r)
00546
00547 m /= abs(m)
00548
00549 return m[0],m[1],m[2]
00550
00551 def hext_xyz2(x, y, z):
00552 """Set external field with desired function called in here.
00553
00554 This function must be define after all the external_field_* functions!
00555 """
00556
00557 h_T = external_field_homogeneous(x, y, z)
00558
00559 return h_T[0], h_T[1], h_T[2]
00560
00561 def hext_xyzt(x, y, z, t_ns):
00562 """Set external field with desired function called in here.
00563
00564 This function must be define after all the external_field_* functions!
00565 """
00566
00567 h_T = external_field_homogeneous(x, y, z)
00568 f = external_field_time_scaling(t_ns)
00569
00570 return h_T[0]*f, h_T[1]*f, h_T[2]*f
00571
00572
00573
00574
00575
00576
00577
00578 import time
00579 def timing(f, n, a):
00580 print f.__name__,
00581 r = range(n)
00582 t1 = time.clock()
00583 for i in r:
00584 f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a)
00585 t2 = time.clock()
00586 print round(t2-t1, 3)
00587
00588 def test_function_2col():
00589 astart = -3.0
00590 astop = 3.0
00591 nstep = 100
00592
00593 for i in range(nstep+1):
00594 a = astart+i*(astop-astart)/nstep
00595
00596
00597 v1 = hext_xyzt(0,0,0,a)
00598
00599 print a, v1
00600
00601 def misc3():
00602 import matplotlib.pyplot as plt
00603 plt.plotfile("x",cols=(0,1),delimiter=" ")
00604
00605 def wire_z():
00606 poly_points=[]
00607 poly_points.append(Vector([0.0,0.0, -10.0]))
00608 poly_points.append(Vector([0.0,0.0, 10.0]))
00609 polygon = Polygon()
00610 for s in range(len(poly_points)-1):
00611 polygon.append_segment(poly_points[s],poly_points[s+1])
00612 return polygon
00613
00614 def hext_f(t_ns):
00615 """
00616 """
00617
00618 tstart = 0.0
00619 fstart = 0.0
00620 tend = 50.0
00621 fend = 200.0
00622
00623 if t_ns < t_start:
00624 f=fstart
00625 elif t_ns < fend:
00626 f=fstart+(fend-fstart)*(t_ns-tstart)/(tend-tstart)
00627
00628 return f
00629
00630 coils = wire_z()
00631
00632 def hext_xyz(x, y, z):
00633 """Set external field with desired function called in here.
00634
00635 This function must be defined after all the external_field_* functions!
00636 """
00637
00638 h_T = field_of_wire(coils,0.001,Vector([x,y,z]))
00639
00640 return h_T[0], h_T[1], h_T[2]
00641
00642
00643 if __name__ == "__main__":
00644
00645
00646
00647 cProfile.run('print hext_xyz(1.0,0,0)')
00648
00649 unittest.main()