{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Particle Tracker\n", "================\n", "\n", "An example of PlasmaPy's particle tracker class.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import astropy.units as u\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "from plasmapy.formulary import ExB_drift, gyrofrequency\n", "from plasmapy.particles import Particle\n", "from plasmapy.plasma.grids import CartesianGrid\n", "from plasmapy.simulation.particle_tracker.particle_tracker import ParticleTracker\n", "from plasmapy.simulation.particle_tracker.save_routines import IntervalSaveRoutine\n", "from plasmapy.simulation.particle_tracker.termination_conditions import (\n", " TimeElapsedTerminationCondition,\n", ")" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": "Take a look at the docs to :func:`~plasmapy.formulary.frequencies.gyrofrequency` and :class:`~plasmapy.simulation.particle_tracker.particle_tracker.ParticleTracker` for more information" }, { "cell_type": "markdown", "metadata": {}, "source": [ "Initialize a :class:`~plasmapy.plasma.grids.CartesianGrid` object. This will be the source of electric and magnetic\n", "fields for our particles to move in.\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "grid_length = 10\n", "grid = CartesianGrid(-1 * u.m, 1 * u.m, num=grid_length)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Initialize the fields. We'll take B in the x direction\n", "and E in the y direction, which gets us an E cross B drift\n", "in the negative z direction.\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "Bx_fill = 4 * u.T\n", "Bx = np.full(grid.shape, Bx_fill.value) * u.T\n", "\n", "Ey_fill = 2 * u.V / u.m\n", "Ey = np.full(grid.shape, Ey_fill.value) * u.V / u.m\n", "\n", "grid.add_quantities(B_x=Bx, E_y=Ey)\n", "ExB_drift(\n", " np.asarray([0, Ey_fill.value, 0]) * u.V / u.m,\n", " np.asarray([Bx_fill.value, 0, 0]) * u.T,\n", ")" ] }, { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "|ParticleTracker| takes arrays of particle positions and velocities of the shape [nparticles, 3], so these arrays represent one particle starting at the origin." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x0 = [[0, 0, 0]] * u.m\n", "v0 = [[1, 0, 0]] * u.m / u.s\n", "particle = Particle(\"p+\")" ] }, { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "Initialize our stop condition and save routine. We can determine a relevant\n", "duration for the experiment by calculating the gyroperiod for the particle." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "particle_gyroperiod = 1 / gyrofrequency(Bx_fill, particle).to(\n", " u.Hz, equivalencies=u.dimensionless_angles()\n", ")\n", "\n", "simulation_duration = 100 * particle_gyroperiod\n", "save_interval = particle_gyroperiod / 10\n", "\n", "termination_condition = TimeElapsedTerminationCondition(simulation_duration)\n", "save_routine = IntervalSaveRoutine(save_interval)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "Initialize the trajectory calculation." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "simulation = ParticleTracker(\n", " grid,\n", " save_routine=save_routine,\n", " termination_condition=termination_condition,\n", " verbose=False,\n", ")" ] }, { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "We still have to initialize the particle's velocity. We'll limit ourselves to\n", "one in the x direction, parallel to the magnetic field B -\n", "that way, it won't turn in the z direction.\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "simulation.load_particles(x0, v0, particle)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Run the simulation." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "simulation.run()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can take a look at the trajectory in the z direction:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "results = save_routine.results\n", "particle_trajectory = results[\"x\"][:, 0]\n", "particle_position_z = particle_trajectory[:, 2]\n", "\n", "plt.scatter(results[\"time\"], particle_position_z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "or plot the shape of the trajectory in 3D:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "tags": [ "nbsphinx-thumbnail" ] }, "outputs": [], "source": [ "fig = plt.figure()\n", "ax = fig.add_subplot(projection=\"3d\")\n", "\n", "ax.plot(*particle_trajectory.T)\n", "ax.set_xlabel(\"X\")\n", "ax.set_ylabel(\"Y\")\n", "ax.set_zlabel(\"Z\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a test, we calculate the mean velocity in the z direction from the\n", "velocity:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "v_mean = results[\"v\"][:, :, 2].mean()\n", "print(\n", " f\"The calculated drift velocity is {v_mean:.4f} to compare with the \"\n", " f\"expected E0/B0 = {-(Ey_fill / Bx_fill).value:.4f}\"\n", ")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }