def test_distance(self): c = CurveRZFourier(100, 1, 1, False) dofs = c.get_dofs() dofs[0] = 1. c.set_dofs(dofs) s = SurfaceRZFourier(mpol=1, ntor=1) s.fit_to_curve(c, 0.2, flip_theta=True) xyz = np.asarray([[0, 0, 0], [1., 0, 0], [2., 0., 0]]) d = signed_distance_from_surface(xyz, s) assert np.allclose(d, [-0.8, 0.2, -0.8]) s.fit_to_curve(c, 0.2, flip_theta=False) d = signed_distance_from_surface(xyz, s) assert np.allclose(d, [-0.8, 0.2, -0.8])
def test_guidingcenterphihits(self): bsh = self.bsh ma = self.ma nparticles = 2 m = PROTON_MASS q = ELEMENTARY_CHARGE Ekin = 9000 * ONE_EV nphis = 10 phis = np.linspace(0, 2 * np.pi, nphis, endpoint=False) mpol = 5 ntor = 5 nfp = 3 s = SurfaceRZFourier(mpol=mpol, ntor=ntor, stellsym=True, nfp=nfp, quadpoints_phi=np.linspace(0, 1, nfp * 2 * ntor + 1, endpoint=False), quadpoints_theta=np.linspace(0, 1, 2 * mpol + 1, endpoint=False)) s.fit_to_curve(ma, 0.10, flip_theta=False) sc = SurfaceClassifier(s, h=0.1, p=2) if with_evtk: sc.to_vtk('/tmp/classifier') # check that the axis is classified as inside the domain assert sc.evaluate(ma.gamma()[:1, :]) > 0 assert sc.evaluate(2 * ma.gamma()[:1, :]) < 0 np.random.seed(1) gc_tys, gc_phi_hits = trace_particles_starting_on_curve( ma, bsh, nparticles, tmax=1e-4, seed=1, mass=m, charge=q, Ekin=Ekin, umin=-0.1, umax=+0.1, phis=phis, mode='gc_vac', stopping_criteria=[LevelsetStoppingCriterion(sc)]) if with_evtk: particles_to_vtk(gc_tys, '/tmp/particles_gc') for i in range(nparticles): assert validate_phi_hits(gc_phi_hits[i], bsh, nphis)
def test_tracing_on_surface_runs(self): bsh = self.bsh ma = self.ma nparticles = 1 m = PROTON_MASS q = ELEMENTARY_CHARGE tmax = 1e-3 Ekin = 9000 * ONE_EV np.random.seed(1) ntor = 1 mpol = 1 stellsym = True nfp = 3 phis = np.linspace(0, 1, 50, endpoint=False) thetas = np.linspace(0, 1, 50, endpoint=False) s = SurfaceRZFourier(mpol=mpol, ntor=ntor, stellsym=stellsym, nfp=nfp, quadpoints_phi=phis, quadpoints_theta=thetas) s.fit_to_curve(ma, 0.03, flip_theta=False) gc_tys, gc_phi_hits = trace_particles_starting_on_surface( s, bsh, nparticles, tmax=tmax, seed=1, mass=m, charge=q, Ekin=Ekin, umin=-0.80, umax=-0.70, phis=[], mode='gc_vac', tol=1e-11, stopping_criteria=[IterationStoppingCriterion(10)]) assert len(gc_tys[0]) == 11
def test_stopping_criteria(self): bsh = self.bsh ma = self.ma nparticles = 1 m = PROTON_MASS q = ELEMENTARY_CHARGE tmax = 1e-3 Ekin = 9000 * ONE_EV np.random.seed(1) gc_tys, gc_phi_hits = trace_particles_starting_on_curve( ma, bsh, nparticles, tmax=tmax, seed=1, mass=m, charge=q, Ekin=Ekin, umin=-0.80, umax=-0.70, phis=[], mode='gc_vac', tol=1e-11, stopping_criteria=[IterationStoppingCriterion(10)]) assert len(gc_tys[0]) == 11 # consider a particle with mostly perpendicular velocity so that it get's lost ntor = 1 mpol = 1 stellsym = True nfp = 3 phis = np.linspace(0, 1, 50, endpoint=False) thetas = np.linspace(0, 1, 50, endpoint=False) s = SurfaceRZFourier(mpol=mpol, ntor=ntor, stellsym=stellsym, nfp=nfp, quadpoints_phi=phis, quadpoints_theta=thetas) s.fit_to_curve(ma, 0.03, flip_theta=False) sc = SurfaceClassifier(s, h=0.1, p=2) gc_tys, gc_phi_hits = trace_particles_starting_on_curve( ma, bsh, nparticles, tmax=tmax, seed=1, mass=m, charge=q, Ekin=Ekin, umin=-0.01, umax=+0.01, phis=[], mode='gc_vac', tol=1e-11, stopping_criteria=[LevelsetStoppingCriterion(sc)]) if with_evtk: particles_to_vtk(gc_tys, '/tmp/particles_gc') assert gc_phi_hits[0][-1][1] == -1 assert np.all(sc.evaluate(gc_tys[0][:, 1:4]) > 0)
mpol = 5 ntor = 5 stellsym = True nfp = 3 constraint_weight = 1e0 phis = np.linspace(0, 1 / nfp, 25, endpoint=False) thetas = np.linspace(0, 1, 25, endpoint=False) s = SurfaceRZFourier(mpol=mpol, ntor=ntor, stellsym=stellsym, nfp=nfp, quadpoints_phi=phis, quadpoints_theta=thetas) s.fit_to_curve(ma, 0.2, flip_theta=True) # First optimize at fixed volume qfm = QfmResidual(s, bs) qfm.J() vol = Volume(s) vol_target = vol.J() qfm_surface = QfmSurface(bs, s, vol, vol_target) res = qfm_surface.minimize_qfm_penalty_constraints_LBFGS( tol=1e-12, maxiter=1000, constraint_weight=constraint_weight) print( f"||vol constraint||={0.5*(s.volume()-vol_target)**2:.8e}, ||residual||={np.linalg.norm(qfm.J()):.8e}"