def test_ellipticV(): #random input INP = np.random.rand(1000, 4) # classical solution looped solC = [] for inp in INP: solC += [elliptic(inp[0], inp[1], inp[2], inp[3])] solC = np.array(solC) #vector solution solV = ellipticV(INP[:, 0], INP[:, 1], INP[:, 2], INP[:, 3]) assert np.amax(abs(solC - solV)) < 1e-10
def Bfield_Cylinder(MAG, pos, dim, Nphi0): # returns arr3 D, H = dim # magnet dimensions R = D / 2 x, y, z = pos # relative position r, phi = sqrt(x**2 + y**2), getPhi(x, y) # cylindrical coordinates # Mag part in z-direction B0z = MAG[2] # z-part of magnetization zP, zM = z + H / 2., z - H / 2. # some important quantitites Rpr, Rmr = R + r, R - r # special cases: # 0. volume cases no quantities are zero # 1. on surfaces: one quantity is zero # 2. on edge lines: two quantities are zero CASE = 0 for case in array([Rmr, zP, zM]): if (case < 1e-15 and -1e-15 < case): CASE += 1 # rounding is required to catch numerical problem cases like .5-.55=.05000000000000001 # which then result in 'normal' cases but the square eliminates the small digits # edge cases ---------------------------------------------- if CASE == 2: warn('Warning: getB Position directly on magnet surface', RuntimeWarning) return array([NaN, NaN, NaN]) # on-magnet surface cases---------------------------------- elif CASE == 1: if Rmr == 0: # on cylinder surface if abs(z) < H / 2: # directly on magnet warn('Warning: getB Position directly on magnet surface', RuntimeWarning) return array([NaN, NaN, NaN]) else: # on top or bottom surface if Rmr > 0: # directly on magnet warn('Warning: getB Position directly on magnet surface', RuntimeWarning) return array([NaN, NaN, NaN]) # Volume Cases and off-magnet surface cases---------------- SQ1 = sqrt(zP**2 + Rpr**2) SQ2 = sqrt(zM**2 + Rpr**2) alphP = R / SQ1 alphM = R / SQ2 betP = zP / SQ1 betM = zM / SQ2 kP = sqrt((zP**2 + Rmr**2) / (zP**2 + Rpr**2)) kM = sqrt((zM**2 + Rmr**2) / (zM**2 + Rpr**2)) gamma = Rmr / Rpr # radial field Br_Z = B0z * (alphP * elliptic(kP, 1, 1, -1) - alphM * elliptic(kM, 1, 1, -1)) / pi Bx_Z = Br_Z * cos(phi) By_Z = Br_Z * sin(phi) # axial field Bz_Z = B0z * R / (Rpr) * (betP * elliptic(kP, gamma**2, 1, gamma) - betM * elliptic(kM, gamma**2, 1, gamma)) / pi Bfield = array([Bx_Z, By_Z, Bz_Z]) # contribution from axial magnetization # Mag part in xy-direction requires a numeical algorithm B0xy = sqrt(MAG[0]**2 + MAG[1]**2) # xy-magnetization amplitude if B0xy > 0: tetta = arctan2(MAG[1], MAG[0]) gamma = arctan2(y, x) phi = gamma - tetta phi0s = 2 * pi / Nphi0 # discretization rR2 = 2 * r * R r2pR2 = r**2 + R**2 def I1x(phi0, z0): if r2pR2 - rR2 * cos(phi - phi0) == 0: return -1 / 2 / (z - z0)**2 else: G = 1 / sqrt(r2pR2 - rR2 * cos(phi - phi0) + (z - z0)**2) return (z - z0) * G / (r2pR2 - rR2 * cos(phi - phi0)) #USE VECTORIZED CODE FOR THE SUMMATION !!!! # radial component Br_XY = B0xy * R / 2 / Nphi0 * sum([ Sphi(n, Nphi0) * cos(phi0s * n) * (r - R * cos(phi - phi0s * n)) * (I1x(phi0s * n, -H / 2) - I1x(phi0s * n, H / 2)) for n in arange(Nphi0 + 1) ]) # angular component Bphi_XY = B0xy * R**2 / 2 / Nphi0 * sum([ Sphi(n, Nphi0) * cos(phi0s * n) * sin(phi - phi0s * n) * (I1x(phi0s * n, -H / 2) - I1x(phi0s * n, H / 2)) for n in arange(Nphi0 + 1) ]) # axial component Bz_XY = B0xy * R / 2 / Nphi0 * sum([ sum([(-1)**k * Sphi(n, Nphi0) * cos(phi0s * n) / sqrt(r2pR2 - rR2 * cos(phi - phi0s * n) + (z - z0)**2) for z0, k in zip([-H / 2, H / 2], [1, 2])]) for n in arange(Nphi0 + 1) ]) # translate r,phi to x,y coordinates phi = gamma Bx_XY = Br_XY * cos(phi) - Bphi_XY * sin(phi) By_XY = Br_XY * sin(phi) + Bphi_XY * cos(phi) Bfield = Bfield + array([Bx_XY, By_XY, Bz_XY]) # add M if inside the cylinder to make B out of H if r < R and abs(z) < H / 2: Bfield += array([MAG[0], MAG[1], 0]) return Bfield
def test_elliptic(): assert round(elliptic(.1, .2, .3, .4), 4) == 4.7173, "bad elliptic" assert round(ellipticK(.1), 4) == 1.6124, "bad ellipticK" assert round(ellipticE(.1), 4) == 1.5308, "bad ellipticE" assert round(ellipticPi(.1, .2), 4) == 1.752, "bad ellipticPi"