def test_residual(self): """ This test loads a SurfaceXYZFourier that interpolates the xyz coordinates of a surface in the NCSX configuration that was computed on a previous branch of pyplasmaopt. Here, we verify that the Boozer residual at these interpolation points is small. """ s = get_exact_surface() coils, currents, ma = get_ncsx_data() stellarator = CoilCollection(coils, currents, 3, True) bs = BiotSavart(stellarator.coils, stellarator.currents) bs_tf = BiotSavart(stellarator.coils, stellarator.currents) weight = 1. tf = ToroidalFlux(s, bs_tf) # these data are obtained from `boozer` branch of pyplamsaopt tf_target = 0.41431152 iota = -0.44856192 boozer_surface = BoozerSurface(bs, s, tf, tf_target) x = np.concatenate((s.get_dofs(), [iota])) r0 = boozer_surface.boozer_penalty_constraints( x, derivatives=0, constraint_weight=weight, optimize_G=False, scalarize=False) # the residual should be close to zero for all entries apart from the y # and z coordinate at phi=0 and theta=0 (and the corresponding rotations) ignores_idxs = np.zeros_like(r0) ignores_idxs[[1, 2, 693, 694, 695, 1386, 1387, 1388, -2, -1]] = 1 assert np.max(np.abs(r0[ignores_idxs < 0.5])) < 1e-8 assert np.max(np.abs(r0[-2:])) < 1e-6
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 subtest_boozer_penalty_constraints_gradient(self, surfacetype, stellsym, optimize_G=False): np.random.seed(1) coils, currents, ma = get_ncsx_data() stellarator = CoilCollection(coils, currents, 3, True) bs = BiotSavart(stellarator.coils, stellarator.currents) bs_tf = BiotSavart(stellarator.coils, stellarator.currents) s = get_surface(surfacetype, stellsym) s.fit_to_curve(ma, 0.1) weight = 11.1232 tf = ToroidalFlux(s, bs_tf) tf_target = 0.1 boozer_surface = BoozerSurface(bs, s, tf, tf_target) iota = -0.3 x = np.concatenate((s.get_dofs(), [iota])) if optimize_G: x = np.concatenate((x, [ 2. * np.pi * np.sum(np.abs(bs.coil_currents)) * (4 * np.pi * 10**(-7) / (2 * np.pi)) ])) f0, J0 = boozer_surface.boozer_penalty_constraints( x, derivatives=1, constraint_weight=weight, optimize_G=optimize_G) h = np.random.uniform(size=x.shape) - 0.5 Jex = J0 @ h err_old = 1e9 epsilons = np.power(2., -np.asarray(range(7, 20))) print( "################################################################################" ) for eps in epsilons: f1 = boozer_surface.boozer_penalty_constraints( x + eps * h, derivatives=0, constraint_weight=weight, optimize_G=optimize_G) Jfd = (f1 - f0) / eps err = np.linalg.norm(Jfd - Jex) / np.linalg.norm(Jex) print(err / err_old, f0, f1) assert err < err_old * 0.55 err_old = err print( "################################################################################" )
def subtest_boozer_constrained_jacobian(self, surfacetype, stellsym, optimize_G=False): np.random.seed(1) coils, currents, ma = get_ncsx_data() stellarator = CoilCollection(coils, currents, 3, True) bs = BiotSavart(stellarator.coils, stellarator.currents) bs_tf = BiotSavart(stellarator.coils, stellarator.currents) s = get_surface(surfacetype, stellsym) s.fit_to_curve(ma, 0.1) tf = ToroidalFlux(s, bs_tf) tf_target = 0.1 boozer_surface = BoozerSurface(bs, s, tf, tf_target) iota = -0.3 lm = [0., 0.] x = np.concatenate((s.get_dofs(), [iota])) if optimize_G: x = np.concatenate((x, [ 2. * np.pi * np.sum(np.abs(bs.coil_currents)) * (4 * np.pi * 10**(-7) / (2 * np.pi)) ])) xl = np.concatenate((x, lm)) res0, dres0 = boozer_surface.boozer_exact_constraints( xl, derivatives=1, optimize_G=optimize_G) h = np.random.uniform(size=xl.shape) - 0.5 dres_exact = dres0 @ h err_old = 1e9 epsilons = np.power(2., -np.asarray(range(7, 20))) print( "################################################################################" ) for eps in epsilons: res1 = boozer_surface.boozer_exact_constraints( xl + eps * h, derivatives=0, optimize_G=optimize_G) dres_fd = (res1 - res0) / eps err = np.linalg.norm(dres_fd - dres_exact) print(err / err_old) assert err < err_old * 0.55 err_old = err print( "################################################################################" )
def test_interpolated_field_convergence_rate(self): R0test = 1.5 B0test = 0.8 B0 = ToroidalField(R0test, B0test) coils, currents, _ = get_ncsx_data(Nt_coils=5, Nt_ma=10, ppp=5) stellarator = CoilCollection(coils, currents, 3, True) bs = BiotSavart(stellarator.coils, stellarator.currents) old_err_1 = 1e6 old_err_2 = 1e6 btotal = bs + B0 for n in [4, 8, 16]: rmin = 1.5 rmax = 1.7 rsteps = n phimin = 0 phimax = 2 * np.pi phisteps = n * 16 zmin = -0.1 zmax = 0.1 zsteps = n bsh = InterpolatedField(btotal, 2, [rmin, rmax, rsteps], [phimin, phimax, phisteps], [zmin, zmax, zsteps], True) err_1 = np.mean(bsh.estimate_error_B(1000)) err_2 = np.mean(bsh.estimate_error_GradAbsB(1000)) print(err_1, err_2) assert err_1 < 0.6**3 * old_err_1 assert err_2 < 0.6**3 * old_err_2 old_err_1 = err_1 old_err_2 = err_2
def test_poincare_plot(self): coils, currents, ma = get_ncsx_data(Nt_coils=15) nfp = 3 stellarator = CoilCollection(coils, currents, nfp, True) bs = BiotSavart(stellarator.coils, stellarator.currents) n = 10 rrange = (1.0, 1.9, n) phirange = (0, 2*np.pi/nfp, n*2) zrange = (0, 0.4, n) bsh = InterpolatedField( bs, UniformInterpolationRule(2), rrange, phirange, zrange, True, nfp=3, stellsym=True ) nlines = 4 r0 = np.linalg.norm(ma.gamma()[0, :2]) z0 = ma.gamma()[0, 2] R0 = [r0 + i*0.01 for i in range(nlines)] Z0 = [z0 for i in range(nlines)] nphis = 4 phis = np.linspace(0, 2*np.pi/nfp, nphis, endpoint=False) res_tys, res_phi_hits = compute_fieldlines( bsh, R0, Z0, tmax=1000, phis=phis, stopping_criteria=[]) try: import matplotlib # noqa plot_poincare_data(res_phi_hits, phis, '/tmp/fieldlines.png') except ImportError: pass
def subtest_boozer_penalty_constraints_hessian(self, surfacetype, stellsym, optimize_G=False): np.random.seed(1) coils, currents, ma = get_ncsx_data() stellarator = CoilCollection(coils, currents, 3, True) bs = BiotSavart(stellarator.coils, stellarator.currents) bs_tf = BiotSavart(stellarator.coils, stellarator.currents) s = get_surface(surfacetype, stellsym) s.fit_to_curve(ma, 0.1) tf = ToroidalFlux(s, bs_tf) tf_target = 0.1 boozer_surface = BoozerSurface(bs, s, tf, tf_target) iota = -0.3 x = np.concatenate((s.get_dofs(), [iota])) if optimize_G: x = np.concatenate((x, [ 2. * np.pi * np.sum(np.abs(bs.coil_currents)) * (4 * np.pi * 10**(-7) / (2 * np.pi)) ])) f0, J0, H0 = boozer_surface.boozer_penalty_constraints( x, derivatives=2, optimize_G=optimize_G) h1 = np.random.uniform(size=x.shape) - 0.5 h2 = np.random.uniform(size=x.shape) - 0.5 d2f = h1 @ H0 @ h2 err_old = 1e9 epsilons = np.power(2., -np.asarray(range(10, 20))) print( "################################################################################" ) for eps in epsilons: fp, Jp = boozer_surface.boozer_penalty_constraints( x + eps * h1, derivatives=1, optimize_G=optimize_G) d2f_fd = (Jp @ h2 - J0 @ h2) / eps err = np.abs(d2f_fd - d2f) / np.abs(d2f) print(err / err_old) assert err < err_old * 0.55 err_old = err
def test_get_set_points_cyl_cart(self): coils, currents, _ = get_ncsx_data(Nt_coils=5, Nt_ma=10, ppp=5) stellarator = CoilCollection(coils, currents, 3, True) bs = BiotSavart(stellarator.coils, stellarator.currents) points_xyz = np.asarray([[0.5, 0.6, 0.7]]) points_rphiz = np.zeros_like(points_xyz) points_rphiz[:, 0] = np.linalg.norm(points_xyz[:, 0:2], axis=1) points_rphiz[:, 1] = np.mod( np.arctan2(points_xyz[:, 1], points_xyz[:, 0]), 2 * np.pi) points_rphiz[:, 2] = points_xyz[:, 2] bs.set_points_cyl(points_rphiz) # import IPython; IPython.embed() # import sys; sys.exit() assert np.allclose(bs.get_points_cyl(), points_rphiz) assert np.allclose(bs.get_points_cart(), points_xyz) bs.set_points_cart(points_xyz) assert np.allclose(bs.get_points_cyl(), points_rphiz) assert np.allclose(bs.get_points_cart(), points_xyz)
def test_poincare_ncsx_known(self): coils, currents, ma = get_ncsx_data(Nt_coils=25) nfp = 3 stellarator = CoilCollection(coils, currents, nfp, True) currents = [-c for c in currents] bs = BiotSavart(stellarator.coils, stellarator.currents) R0 = [np.linalg.norm(ma.gamma()[0, :2])] Z0 = [ma.gamma()[0, 2]] phis = np.arctan2(ma.gamma()[:, 1], ma.gamma()[:, 0]) res_tys, res_phi_hits = compute_fieldlines( bs, R0, Z0, tmax=10, phis=phis, stopping_criteria=[]) for i in range(len(phis)-1): assert np.linalg.norm(ma.gamma()[i+1, :] - res_phi_hits[0][i, 2:5]) < 1e-4
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_interpolated_field_close_with_symmetries(self): R0test = 1.5 B0test = 0.8 B0 = ToroidalField(R0test, B0test) coils, currents, _ = get_ncsx_data(Nt_coils=10, Nt_ma=10, ppp=5) nfp = 3 stellarator = CoilCollection(coils, currents, nfp, True) bs = BiotSavart(stellarator.coils, stellarator.currents) btotal = bs + B0 n = 12 rmin = 1.5 rmax = 1.7 rsteps = n phimin = 0 phimax = 2 * np.pi / nfp phisteps = n * 32 // nfp zmin = 0. zmax = 0.1 zsteps = n // 2 bsh = InterpolatedField(btotal, 4, [rmin, rmax, rsteps], [phimin, phimax, phisteps], [zmin, zmax, zsteps], True, nfp=nfp, stellsym=True) N = 1000 points = np.random.uniform(size=(N, 3)) points[:, 0] = points[:, 0] * (rmax - rmin) + rmin points[:, 1] = points[:, 1] * (nfp * phimax - phimin) + phimin points[:, 2] = points[:, 2] * (2 * zmax) - zmax btotal.set_points_cyl(points) dB = btotal.GradAbsB() B = btotal.B() dBc = btotal.GradAbsB_cyl() Bc = btotal.B_cyl() bsh.set_points_cyl(points) Bh = bsh.B() dBh = bsh.GradAbsB() Bhc = bsh.B_cyl() dBhc = bsh.GradAbsB_cyl() assert np.allclose(B, Bh, rtol=1e-3) assert np.allclose(dB, dBh, rtol=1e-3) assert np.allclose(Bc, Bhc, rtol=1e-3) assert np.allclose(dBc, dBhc, rtol=1e-3)
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_interpolated_field_close_no_sym(self): R0test = 1.5 B0test = 0.8 B0 = ToroidalField(R0test, B0test) coils, currents, _ = get_ncsx_data(Nt_coils=5, Nt_ma=10, ppp=5) stellarator = CoilCollection(coils, currents, 3, True) bs = BiotSavart(stellarator.coils, stellarator.currents) btotal = bs + B0 n = 8 rmin = 1.5 rmax = 1.7 rsteps = n phimin = 0 phimax = 2 * np.pi phisteps = n * 16 zmin = -0.1 zmax = 0.1 zsteps = n bsh = InterpolatedField(btotal, 4, [rmin, rmax, rsteps], [phimin, phimax, phisteps], [zmin, zmax, zsteps], True) N = 100 points = np.random.uniform(size=(N, 3)) points[:, 0] = points[:, 0] * (rmax - rmin) + rmin points[:, 1] = points[:, 1] * (phimax - phimin) + phimin points[:, 2] = points[:, 2] * (zmax - zmin) + zmin btotal.set_points_cyl(points) dB = btotal.GradAbsB() B = btotal.B() dBc = btotal.GradAbsB_cyl() Bc = btotal.B_cyl() bsh.set_points_cyl(points) Bh = bsh.B() dBh = bsh.GradAbsB() Bhc = bsh.B_cyl() dBhc = bsh.GradAbsB_cyl() assert np.allclose(B, Bh, rtol=1e-2) assert np.allclose(dB, dBh, rtol=1e-2) assert np.allclose(Bc, Bhc, rtol=1e-2) assert np.allclose(dBc, dBhc, rtol=1e-2)
def test_poincare_caryhanson(self): # Test with a known magnetic field - optimized Cary&Hanson configuration # with a magnetic axis at R=0.9413. Field created using the Biot-Savart # solver given a set of two helical coils created using the CurveHelical # class. The total magnetic field is a superposition of a helical and # a toroidal magnetic field. coils = [CurveHelical(200, 2, 5, 2, 1., 0.3) for i in range(2)] coils[0].set_dofs(np.concatenate(([np.pi/2, 0.2841], [0, 0]))) coils[1].set_dofs(np.concatenate(([0, 0], [0, 0.2933]))) currents = [3.07e5, -3.07e5] Btoroidal = ToroidalField(1.0, 1.0) Bhelical = BiotSavart(coils, currents) bs = Bhelical+Btoroidal ma = CurveXYZFourier(300, 1) magnetic_axis_radius = 0.9413 ma.set_dofs([0, 0, magnetic_axis_radius, 0, magnetic_axis_radius, 0, 0, 0, 0]) R0 = [np.linalg.norm(ma.gamma()[0, :2])] Z0 = [ma.gamma()[0, 2]] phis = np.arctan2(ma.gamma()[:, 1], ma.gamma()[:, 0]) res_tys, res_phi_hits = compute_fieldlines( bs, R0, Z0, tmax=2, phis=phis, stopping_criteria=[]) for i in range(len(res_phi_hits[0])): assert np.linalg.norm(ma.gamma()[i+1, :] - res_phi_hits[0][i, 2:5]) < 2e-3
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())