def test_particle_exb_drift(): r""" Tests the particle stepper for a field with magnetic field in the Z direction, electric field in the y direction. This should produce a drift in the negative X direction, with the drift velocity v_e = ExB / B^2 which is independent of ion charge. """ test_plasma = uniform_magnetic_field() test_plasma.electric_field[1] = 1 * u.V / u.m expected_drift_velocity = -(test_plasma.electric_field_strength / test_plasma.magnetic_field_strength).mean() \ .to(u.m / u.s) s = Species(test_plasma, 'p', 5, dt=1e-10 * u.s, nt=int(5e3)) s.v[:, 2] += np.random.normal(size=s.N) * u.m / u.s s.run() p_init = models.Polynomial1D(degree=1) for x in s.position_history[:, :, 0].T: fit_p = fitting.LinearLSQFitter() p = fit_p(p_init, s.t, x) fit_velocity = p.parameters[1] * u.m / u.s assert np.allclose(x, p(s.t), atol=1e-3 * u.m), \ "x position doesn't follow linear fit!" assert np.isclose(expected_drift_velocity, fit_velocity, atol=1e-3 * u.m / u.s), \ "x velocity doesn't agree with expected drift velocity!" s.test_kinetic_energy()
def test_basic_species_functionality(): plasma = uniform_magnetic_field() s = Species(plasma=plasma, dt=1e-3 * u.s, nt=1) assert np.isclose(s.kinetic_energy, 0 * u.J, atol=1e-4 * u.J) # this should crash as neither `dt` nor `NT` are not provided with pytest.raises(ValueError): Species(plasma=plasma)
def test_particle_uniform_magnetic(): """ Tests the particle stepper for a uniform magnetic field motion. """ test_plasma = uniform_magnetic_field() particle_type = 'N-14++' s = Species(test_plasma, particle_type=particle_type, dt=1e-2 * u.s, nt=int(1e4)) perp_speed = 0.01 * u.m / u.s parallel_speed = 1e-5 * u.m / u.s mean_B = test_plasma.magnetic_field_strength.mean() expected_gyrofrequency = (s.q * mean_B / s.m).to(1 / u.s) expected_gyroradius = perp_speed / expected_gyrofrequency expected_gyroperiod = 2 * np.pi / expected_gyrofrequency dt = expected_gyroperiod / 100 s = Species(test_plasma, particle_type=particle_type, dt=dt, nt=int(1e4)) s.v[:, 1] = perp_speed s.v[:, 2] = parallel_speed s.run() x = s.position_history[:, 0, 0] z = s.position_history[:, 0, 2] try: params, stds = fit_sine_curve(x, s.t, expected_gyrofrequency) except RuntimeError as e: print(s) raise e estimated_gyroradius = np.abs(params[0]) * u.m estimated_gyroradius_std = np.abs(stds[0]) * u.m estimated_gyrofrequency = np.abs(params[1]) / u.s estimated_gyrofrequency_std = np.abs(stds[1]) / u.s assert np.isclose(expected_gyroradius, estimated_gyroradius, atol=estimated_gyroradius_std), \ "Gyroradii don't match!" assert np.isclose(expected_gyrofrequency, estimated_gyrofrequency, atol=estimated_gyrofrequency_std), \ "Gyrofrequencies don't match!" p_init = models.Polynomial1D(degree=1) fit_p = fitting.LinearLSQFitter() p = fit_p(p_init, s.t, z) assert np.allclose(z, p(s.t), atol=1e-4 * u.m), \ "z-velocity doesn't stay constant!" s.test_kinetic_energy()
def test_particle_nonuniform_grid(): ''' Test the particle stepper when the spatial domain dimensions are unequal ''' x = np.linspace(0, 1, 10) * u.m y = np.linspace(0, 1, 20) * u.m z = np.linspace(0, 1, 30) * u.m plasma = Plasma(x, y, z) Species(plasma, 'e', dt=1e-14 * u.s, nt=5).run()
############################################################ # Initialize the fields. We'll take $\vec{B}$ in the $\hat{x}$ direction # and $E$ in the $\hat{y}$ direction, which gets us an $E \times B$ drift # in $\hat{z}$. B0 = 4 * u.T plasma.magnetic_field[0, :, :, :] = np.ones((10, 10, 10)) * B0 E0 = 2 * u.V / u.m plasma.electric_field[1, :, :, :] = np.ones((10, 10, 10)) * E0 ############################################################ # Initialize the particle. We'll take one proton `p` with a timestep of # $10^{-10}s$ and run it for 10000 iterations. species = Species(plasma, 'p', 1, 1, 1e-10 * u.s, 10000) ############################################################ # Initialize the particle's velocity. We'll limit ourselves to one in the # $\hat{x}$ direction, parallel to the magnetic field $\vec{B}$ - that # way, it won't turn in the $\hat{z}$ direction. V0 = 1 * (u.m / u.s) species.v[0][0] = V0 ############################################################ # Run the pusher and plot the trajectory versus time. species.run() species.plot_time_trajectories()