def test_biotsavart_coil_current_taylortest(self): coil0 = get_coil() current0 = 1e4 coil1 = get_coil(perturb=True) current1 = 1e3 bs = BiotSavart([coil0, coil1], [current0, current1]) points = np.asarray( 17 * [[-1.41513202e-03, 8.99999382e-01, -3.14473221e-04]]) bs.set_points(points) B = bs.B() J = bs.dB_by_dX() H = bs.d2B_by_dXdX() dB = bs.dB_by_dcoilcurrents() dJ = bs.d2B_by_dXdcoilcurrents() dH = bs.d3B_by_dXdXdcoilcurrents() h = 1. bs.currents_optim[0].set_dofs(1e4 + h) bs.invalidate_cache() Bp = bs.B() Jp = bs.dB_by_dX() Hp = bs.d2B_by_dXdX() bs.currents_optim[0].set_dofs(1e4 - h) bs.invalidate_cache() Bm = bs.B() Jm = bs.dB_by_dX() Hm = bs.d2B_by_dXdX() dB_approx = (Bp - Bm) / (2 * h) dJ_approx = (Jp - Jm) / (2 * h) dH_approx = (Hp - Hm) / (2 * h) assert np.linalg.norm(dB[0] - dB_approx) < 1e-15 assert np.linalg.norm(dJ[0] - dJ_approx) < 1e-15 assert np.linalg.norm(dH[0] - dH_approx) < 1e-13
def subtest_biotsavart_d2B_by_dXdX_taylortest(self, idx): coil = get_coil() bs = BiotSavart([coil], [1e4]) points = np.asarray( 17 * [[-1.41513202e-03, 8.99999382e-01, -3.14473221e-04]]) bs.set_points(points) dB_by_dX, d2B_by_dXdX = bs.dB_by_dX(), bs.d2B_by_dXdX() for d1 in range(3): for d2 in range(3): second_deriv = d2B_by_dXdX[idx, d1, d2] err = 1e6 for i in range(5, 10): eps = 0.5**i ed2 = np.zeros((1, 3)) ed2[0, d2] = 1. bs.set_points(points + eps * ed2) dB_dXp = bs.dB_by_dX()[idx, d1] bs.set_points(points - eps * ed2) dB_dXm = bs.dB_by_dX()[idx, d1] second_deriv_est = (dB_dXp - dB_dXm) / (2. * eps) new_err = np.linalg.norm(second_deriv - second_deriv_est) assert new_err < 0.30 * err err = new_err
def test_dBdX_by_dcoilcoeff_reverse_taylortest(self): np.random.seed(1) coil = get_coil() bs = BiotSavart([coil], [1e4]) points = np.asarray( 17 * [[-1.41513202e-03, 8.99999382e-01, -3.14473221e-04]]) points += 0.001 * (np.random.rand(*points.shape) - 0.5) bs.set_points(points) coil_dofs = np.asarray(coil.get_dofs()) B = bs.B() dBdX = bs.dB_by_dX() J0 = np.sum(dBdX**2) dJ = bs.B_and_dB_vjp(B, dBdX) h = 1e-2 * np.random.rand(len(coil_dofs)).reshape(coil_dofs.shape) dJ_dh = 2 * np.sum(dJ[1][0] * h) err = 1e6 for i in range(5, 10): eps = 0.5**i coil.set_dofs(coil_dofs + eps * h) bs.clear_cached_properties() dBdXh = bs.dB_by_dX() Jh = np.sum(dBdXh**2) deriv_est = (Jh - J0) / eps err_new = np.linalg.norm(deriv_est - dJ_dh) assert err_new < 0.55 * err err = err_new
def subtest_biotsavart_gradient_symmetric_and_divergence_free(self, idx): coil = get_coil() bs = BiotSavart([coil], [1e4]) points = np.asarray( 17 * [[-1.41513202e-03, 8.99999382e-01, -3.14473221e-04]]) points += 0.001 * (np.random.rand(*points.shape) - 0.5) bs.set_points(points) dB = bs.dB_by_dX() assert abs(dB[idx][0, 0] + dB[idx][1, 1] + dB[idx][2, 2]) < 1e-14 assert np.allclose(dB[idx], dB[idx].T)
def test_helicalcoil_Bfield(self): point = [[-1.41513202e-03, 8.99999382e-01, -3.14473221e-04]] field = [[-0.00101961, 0.20767292, -0.00224908]] derivative = [[[0.47545098, 0.01847397, 1.10223595], [0.01847426, -2.66700072, 0.01849548], [1.10237535, 0.01847085, 2.19154973]]] coils = [CurveHelical(100, 2, 5, 2, 1., 0.3) for i in range(2)] coils[0].set_dofs(np.concatenate(([0, 0], [0, 0]))) coils[1].set_dofs(np.concatenate(([np.pi / 2, 0], [0, 0]))) currents = [-3.07e5, 3.07e5] Bhelical = BiotSavart(coils, currents) Bhelical.set_points(point) assert np.allclose(Bhelical.B(), field) assert np.allclose(Bhelical.dB_by_dX(), derivative)
def test_sum_Bfields(self): pointVar = 1e-1 npoints = 20 points = np.asarray( npoints * [[-1.41513202e-03, 8.99999382e-01, -3.14473221e-04]]) points += pointVar * (np.random.rand(*points.shape) - 0.5) # Set up helical field coils = [CurveHelical(101, 2, 5, 2, 1., 0.3) for i in range(2)] coils[0].set_dofs(np.concatenate(([np.pi / 2, 0], [0, 0]))) coils[1].set_dofs(np.concatenate(([0, 0], [0, 0]))) currents = [-2.1e5, 2.1e5] Bhelical = BiotSavart(coils, currents) # Set up toroidal fields Btoroidal1 = ToroidalField(1., 1.) Btoroidal2 = ToroidalField(1.2, 0.1) # Set up sum of the three in two different ways Btotal1 = MagneticFieldSum([Bhelical, Btoroidal1, Btoroidal2]) Btotal2 = Bhelical + Btoroidal1 + Btoroidal2 Btotal3 = Btoroidal1 + Btoroidal2 # Evaluate at a given point Bhelical.set_points(points) Btoroidal1.set_points(points) Btoroidal2.set_points(points) Btotal1.set_points(points) Btotal2.set_points(points) Btotal3.set_points(points) # Verify assert np.allclose(Btotal1.B(), Btotal2.B()) assert np.allclose(Bhelical.B() + Btoroidal1.B() + Btoroidal2.B(), Btotal1.B()) assert np.allclose(Btotal1.dB_by_dX(), Btotal2.dB_by_dX()) assert np.allclose( Bhelical.dB_by_dX() + Btoroidal1.dB_by_dX() + Btoroidal2.dB_by_dX(), Btotal1.dB_by_dX()) assert np.allclose(Btoroidal1.d2B_by_dXdX() + Btoroidal2.d2B_by_dXdX(), Btotal3.d2B_by_dXdX()) assert np.allclose(Btoroidal1.A() + Btoroidal2.A(), Btotal3.A()) assert np.allclose(Btoroidal1.dA_by_dX() + Btoroidal2.dA_by_dX(), Btotal3.dA_by_dX()) assert np.allclose(Btoroidal1.d2A_by_dXdX() + Btoroidal2.d2A_by_dXdX(), Btotal3.d2A_by_dXdX())
def subtest_biotsavart_dBdX_taylortest(self, idx): coil = get_coil() bs = BiotSavart([coil], [1e4]) points = np.asarray( 17 * [[-1.41513202e-03, 8.99999382e-01, -3.14473221e-04]]) points += 0.001 * (np.random.rand(*points.shape) - 0.5) bs.set_points(points) B0 = bs.B()[idx] dB = bs.dB_by_dX()[idx] for direction in [ np.asarray((1., 0, 0)), np.asarray((0, 1., 0)), np.asarray((0, 0, 1.)) ]: deriv = dB.T.dot(direction) err = 1e6 for i in range(5, 10): eps = 0.5**i bs.set_points(points + eps * direction) Beps = bs.B()[idx] deriv_est = (Beps - B0) / (eps) new_err = np.linalg.norm(deriv - deriv_est) assert new_err < 0.55 * err err = new_err
def test_circularcoil_Bfield(self): current = 1.2e7 radius = 1.12345 center = [0.12345, 0.6789, 1.23456] pointVar = 1e-1 npoints = 1 ## verify the field at the center of a coil in the xy plane Bfield = CircularCoil(I=current, r0=radius) points = np.array([[1e-10, 0, 0.]]) Bfield.set_points(points) assert np.allclose(Bfield.B(), [[0, 0, current / 1e7 * 2 * np.pi / radius]]) # Verify that divergence is zero dB1_by_dX = Bfield.dB_by_dX() assert np.allclose( dB1_by_dX[:, 0, 0] + dB1_by_dX[:, 1, 1] + dB1_by_dX[:, 2, 2], np.zeros((npoints))) # Verify that, as a vacuum field, grad B=grad grad phi so that grad_i B_j = grad_j B_i transpGradB1 = [dBdx.T for dBdx in dB1_by_dX] assert np.allclose(dB1_by_dX, transpGradB1) ### compare to biosavart(circular_coil) ## at these points points = np.asarray( npoints * [[-1.41513202e-03, 8.99999382e-01, -3.14473221e-04]]) points += pointVar * (np.random.rand(*points.shape) - 0.5) ## verify with a x^2+z^2=radius^2 circular coil normal = [np.pi / 2, 0] coils = [CurveXYZFourier(300, 1)] coils[0].set_dofs( [center[0], radius, 0., center[1], 0., 0., center[2], 0., radius]) Bcircular = BiotSavart(coils, [current]) Bfield = CircularCoil(I=current, r0=radius, normal=normal, center=center) Bfield.set_points(points) Bcircular.set_points(points) dB1_by_dX = Bfield.dB_by_dX() transpGradB1 = [dBdx.T for dBdx in dB1_by_dX] assert np.allclose(Bfield.B(), Bcircular.B()) assert np.allclose(Bfield.dB_by_dX(), Bcircular.dB_by_dX()) assert np.allclose( dB1_by_dX[:, 0, 0] + dB1_by_dX[:, 1, 1] + dB1_by_dX[:, 2, 2], np.zeros((npoints))) assert np.allclose(dB1_by_dX, transpGradB1) # use normal = [0, 1, 0] normal = [0, 1, 0] coils = [CurveXYZFourier(300, 1)] coils[0].set_dofs( [center[0], radius, 0., center[1], 0., 0., center[2], 0., radius]) Bcircular = BiotSavart(coils, [current]) Bfield = CircularCoil(I=current, r0=radius, normal=normal, center=center) Bfield.set_points(points) Bcircular.set_points(points) dB1_by_dX = Bfield.dB_by_dX() transpGradB1 = [dBdx.T for dBdx in dB1_by_dX] assert np.allclose(Bfield.B(), Bcircular.B()) assert np.allclose(Bfield.dB_by_dX(), Bcircular.dB_by_dX()) assert np.allclose( dB1_by_dX[:, 0, 0] + dB1_by_dX[:, 1, 1] + dB1_by_dX[:, 2, 2], np.zeros((npoints))) assert np.allclose(dB1_by_dX, transpGradB1) ## verify with a y^2+z^2=radius^2 circular coil normal = [np.pi / 2, np.pi / 2] coils = [CurveXYZFourier(300, 1)] coils[0].set_dofs( [center[0], 0, 0., center[1], radius, 0., center[2], 0., radius]) Bcircular = BiotSavart(coils, [current]) Bfield = CircularCoil(I=current, r0=radius, normal=normal, center=center) Bfield.set_points(points) Bcircular.set_points(points) dB1_by_dX = Bfield.dB_by_dX() transpGradB1 = [dBdx.T for dBdx in dB1_by_dX] assert np.allclose(Bfield.B(), Bcircular.B()) assert np.allclose(Bfield.dB_by_dX(), Bcircular.dB_by_dX()) assert np.allclose(dB1_by_dX[:, 0, 0] + dB1_by_dX[:, 1, 1] + dB1_by_dX[:, 2, 2], np.zeros((npoints))) # divergence assert np.allclose(dB1_by_dX, transpGradB1) # symmetry of the gradient Bfield.set_points([[0.1, 0.2, 0.3]]) Afield = Bfield.A() assert np.allclose(Afield, [[0, 5.15786, -2.643056]]) # use normal=[1,0,0] normal = [1, 0, 0] coils = [CurveXYZFourier(300, 1)] coils[0].set_dofs( [center[0], 0, 0., center[1], radius, 0., center[2], 0., radius]) Bcircular = BiotSavart(coils, [current]) Bfield = CircularCoil(I=current, r0=radius, normal=normal, center=center) Bfield.set_points(points) Bcircular.set_points(points) dB1_by_dX = Bfield.dB_by_dX() transpGradB1 = [dBdx.T for dBdx in dB1_by_dX] assert np.allclose(Bfield.B(), Bcircular.B()) assert np.allclose(Bfield.dB_by_dX(), Bcircular.dB_by_dX()) assert np.allclose(dB1_by_dX[:, 0, 0] + dB1_by_dX[:, 1, 1] + dB1_by_dX[:, 2, 2], np.zeros((npoints))) # divergence assert np.allclose(dB1_by_dX, transpGradB1) # symmetry of the gradient ## verify with a x^2+y^2=radius^2 circular coil center = [0, 0, 0] normal = [0, 0] coils = [CurveXYZFourier(300, 1)] coils[0].set_dofs( [center[0], 0, radius, center[1], radius, 0., center[2], 0., 0.]) Bcircular = BiotSavart(coils, [current]) coils2 = [CurveRZFourier(300, 1, 1, True)] coils2[0].set_dofs([radius, 0, 0]) Bcircular2 = BiotSavart(coils, [current]) Bfield = CircularCoil(I=current, r0=radius, normal=normal, center=center) Bfield.set_points(points) Bcircular.set_points(points) Bcircular2.set_points(points) dB1_by_dX = Bfield.dB_by_dX() transpGradB1 = [dBdx.T for dBdx in dB1_by_dX] assert np.allclose(Bfield.B(), Bcircular.B()) assert np.allclose(Bfield.B(), Bcircular2.B()) assert np.allclose(Bfield.dB_by_dX(), Bcircular.dB_by_dX()) assert np.allclose(Bfield.dB_by_dX(), Bcircular2.dB_by_dX()) assert np.allclose(dB1_by_dX[:, 0, 0] + dB1_by_dX[:, 1, 1] + dB1_by_dX[:, 2, 2], np.zeros((npoints))) # divergence assert np.allclose(dB1_by_dX, transpGradB1) # symmetry of the gradient # use normal = [0, 0, 1] center = [0, 0, 0] normal = [0, 0, 1] coils = [CurveXYZFourier(300, 1)] coils[0].set_dofs( [center[0], 0, radius, center[1], radius, 0., center[2], 0., 0.]) Bcircular = BiotSavart(coils, [current]) coils2 = [CurveRZFourier(300, 1, 1, True)] coils2[0].set_dofs([radius, 0, 0]) Bcircular2 = BiotSavart(coils, [current]) Bfield = CircularCoil(I=current, r0=radius, normal=normal, center=center) Bfield.set_points(points) Bcircular.set_points(points) Bcircular2.set_points(points) dB1_by_dX = Bfield.dB_by_dX() transpGradB1 = [dBdx.T for dBdx in dB1_by_dX] assert np.allclose(Bfield.B(), Bcircular.B()) assert np.allclose(Bfield.B(), Bcircular2.B()) assert np.allclose(Bfield.dB_by_dX(), Bcircular.dB_by_dX()) assert np.allclose(Bfield.dB_by_dX(), Bcircular2.dB_by_dX()) assert np.allclose(dB1_by_dX[:, 0, 0] + dB1_by_dX[:, 1, 1] + dB1_by_dX[:, 2, 2], np.zeros((npoints))) # divergence assert np.allclose(dB1_by_dX, transpGradB1) # symmetry of the gradient