.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorials/00_basic_tutorial.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_tutorials_00_basic_tutorial.py: Basic tutorial ============== This tutorial illustrates some of the basic capabilities of Wake-T: - Creating, visualizing, and accessing the data of a particle bunch. - Tracking a particle bunch though the simplest beamline element (a drift). - Analyzing and visualizing the results. - Write simulation data to disk. .. GENERATED FROM PYTHON SOURCE LINES 14-30 Creating a particle distribution -------------------------------- Particle bunches, together with the different beamline elements, are the main components of Wake-T. They can be generated by manually creating a ``ParticleBunch`` instance, or by using some of the built-in utilities (e.g. create gaussian bunch, read from file). Manually generating a particle bunch ```````````````````````````````````` The most general way of generating a ``ParticleBunch`` is by providing the 7 arrays containing the charge (in Coulomb), position (in meter) and momentum (in :math:`m_e c`) of each macroparticle. The following code illustrates this by creating a random distribution of :math:`10^4` particles with a charge of 30 pC and an average longitudinal momentum of 100 MeV/c. .. GENERATED FROM PYTHON SOURCE LINES 30-52 .. code-block:: Python import numpy as np import scipy.constants as ct from wake_t import ParticleBunch # Create particle arrays for an electron bunch with 30pC of charge. n_part = int(1e4) q = -np.ones(n_part) * 30e-12 / n_part # C w = q / (-ct.e) x = np.random.rand(n_part) * 1e-6 # m y = np.random.rand(n_part) * 1e-6 # m z = np.random.rand(n_part) * 1e-6 # m px = np.random.rand(n_part) # m_e c py = np.random.rand(n_part) # m_e c pz = np.random.rand(n_part) + 100 / 0.511 # m_e c # Create particle bunch. bunch = ParticleBunch(w, x, y, z, px, py, pz, name="random_bunch") # Show phase space. bunch.show() .. image-sg:: /tutorials/images/sphx_glr_00_basic_tutorial_001.png :alt: 00 basic tutorial :srcset: /tutorials/images/sphx_glr_00_basic_tutorial_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 53-64 Using built-in utilities ```````````````````````` Generating a beam by hand is not always necessary, and many times it is more convenient to use some of the built-in utilities. These allow for easily generating Gausian beams or reading an existing distribution from disk. The example below shows how to generate a Gaussian bunch with a normalized emittance of :math:`1 \ \mathrm{\mu m}`, an RMS transverse size of :math:`3 \ \mathrm{\mu m}`, an RMS duration of :math:`3 \ \mathrm{fs}`, an average energy of :math:`100 \ \mathrm{MeV}` with a :math:`1 \ \%` spread and a total charge of :math:`30 \ \mathrm{pC}`. .. GENERATED FROM PYTHON SOURCE LINES 64-98 .. code-block:: Python from wake_t.utilities.bunch_generation import get_gaussian_bunch_from_size # Beam parameters. emitt_nx = emitt_ny = 1e-6 # m s_x = s_y = 3e-6 # m s_t = 3.0 # fs gamma_avg = 100 / 0.511 gamma_spread = 1.0 # % q_bunch = 30 # pC xi_avg = 0.0 # m n_part = 1e4 # Create particle bunch. bunch = get_gaussian_bunch_from_size( emitt_nx, emitt_ny, s_x, s_y, gamma_avg, gamma_spread, s_t, xi_avg, q_bunch, n_part, name="elec_bunch", ) # Store bunch copy (will be needed later). bunch_bkp = bunch.copy() # Show phase space. bunch.show() .. image-sg:: /tutorials/images/sphx_glr_00_basic_tutorial_002.png :alt: 00 basic tutorial :srcset: /tutorials/images/sphx_glr_00_basic_tutorial_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 99-107 Accessing the data in a ``ParticleBunch`` ----------------------------------------- The particle arrays of a ``ParticleBunch`` can be easily accesses (and manipulated) through the ``q``, ``x``, ``y``, ``xi``, ``px``, ``py`` and ``pz`` attributes. As an example, the code below visualizes the transverse phase space of the bunch by directly accessing the particle arrays. .. GENERATED FROM PYTHON SOURCE LINES 107-116 .. code-block:: Python import matplotlib.pyplot as plt plot = plt.hist2d(bunch.x, bunch.px, weights=bunch.q, bins=100) plt.xlabel("x [m]") plt.ylabel("px [m_e c]") cbar = plt.colorbar() cbar.set_label("Q [C]") .. image-sg:: /tutorials/images/sphx_glr_00_basic_tutorial_003.png :alt: 00 basic tutorial :srcset: /tutorials/images/sphx_glr_00_basic_tutorial_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 117-129 Tracking the beam though a drift -------------------------------- Now that we know how to create and handle a particle bunch, we can simulate its evolution throughout our accelerator beamline. In this tutorial, we will use the simplest beamline element (a ``Drift``) to illustrate how this is done in Wake-T. .. note:: The input ``ParticleBunch`` is updated as it propagates through the beamline. If you need to keep the original distribution, make a copy of it before starting the tracking. .. GENERATED FROM PYTHON SOURCE LINES 129-142 .. code-block:: Python # Import required elements. from wake_t import Drift # Create a 1 cm drift. drift = Drift(length=1e-2) # Track our beam though the drift. drift.track(bunch) # Visualize bunch phase space after propagating though the drift. bunch.show() .. image-sg:: /tutorials/images/sphx_glr_00_basic_tutorial_004.png :alt: 00 basic tutorial :srcset: /tutorials/images/sphx_glr_00_basic_tutorial_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Drift ----- Length = 0.0100 m CSR off. Tracking in 1 step(s)... [--------------------] Done (0.001840353012084961 s). -------------------------------------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 143-157 Getting the beam evolution -------------------------- In the code above, the particle bunch is updated after tracking, but we have no trace of its evolution along the drift. To generate several outputs as the beam propagates, each beamline element offers the attribute ``n_out``, which determines how many outputs per element will be generated. Generating multiple outputs ``````````````````````````` To obtain the particle distribution at several steps along the ``Drift``, we will simply modify the example above by adding ``n_out=5``. When performing this will now result in a list containing 5 ``ParticleBunch`` which correspond to the state of the bunch at :math:`z = 0.2 \ cm`, :math:`0.4 \ cm`, :math:`0.6 \ cm`, :math:`0.8 \ cm` and :math:`1.0 \ cm`. .. GENERATED FROM PYTHON SOURCE LINES 157-171 .. code-block:: Python # Get again the original distribution. bunch = bunch_bkp.copy() # Create a 1 cm drift with 5 outputs (one every 0.2 cm). drift = Drift(length=1e-2, n_out=5) # Perform tracking and store outputs in a list. bunch_list_out = drift.track(bunch) # Visualize all steps. for bunch_out in bunch_list_out: bunch_out.show() .. rst-class:: sphx-glr-horizontal * .. image-sg:: /tutorials/images/sphx_glr_00_basic_tutorial_005.png :alt: 00 basic tutorial :srcset: /tutorials/images/sphx_glr_00_basic_tutorial_005.png :class: sphx-glr-multi-img * .. image-sg:: /tutorials/images/sphx_glr_00_basic_tutorial_006.png :alt: 00 basic tutorial :srcset: /tutorials/images/sphx_glr_00_basic_tutorial_006.png :class: sphx-glr-multi-img * .. image-sg:: /tutorials/images/sphx_glr_00_basic_tutorial_007.png :alt: 00 basic tutorial :srcset: /tutorials/images/sphx_glr_00_basic_tutorial_007.png :class: sphx-glr-multi-img * .. image-sg:: /tutorials/images/sphx_glr_00_basic_tutorial_008.png :alt: 00 basic tutorial :srcset: /tutorials/images/sphx_glr_00_basic_tutorial_008.png :class: sphx-glr-multi-img * .. image-sg:: /tutorials/images/sphx_glr_00_basic_tutorial_009.png :alt: 00 basic tutorial :srcset: /tutorials/images/sphx_glr_00_basic_tutorial_009.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-script-out .. code-block:: none Drift ----- Length = 0.0100 m CSR off. Tracking in 5 step(s)... [---- ] Tracking in 5 step(s)... [-------- ] Tracking in 5 step(s)... [------------ ] Tracking in 5 step(s)... [---------------- ] Tracking in 5 step(s)... [--------------------] Done (0.009705781936645508 s). -------------------------------------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 172-178 Evolution of beam parameters along the drift ```````````````````````````````````````````` Having several output steps also allows us to easily obtain the evolution of the beam parameters. Wake-T provides a simple built-in function to perform the analysis of commont beam parameters. The code below showcases it use: .. GENERATED FROM PYTHON SOURCE LINES 178-193 .. code-block:: Python from wake_t.diagnostics import analyze_bunch_list bunch_params = analyze_bunch_list(bunch_list_out) z = bunch_params["prop_dist"] * 1e2 # cm b_x = bunch_params["beta_x"] # m e_nx = bunch_params["emitt_x"] * 1e6 # µm fig, axes = plt.subplots(2, 1, sharex=True) axes[0].plot(z, b_x) axes[1].plot(z, e_nx) axes[0].set(ylabel="$\\beta_{x}$ [m]") axes[1].set(xlabel="z [m]", ylabel="$\\epsilon_{n,x}$ [µm]") plt.show() .. image-sg:: /tutorials/images/sphx_glr_00_basic_tutorial_010.png :alt: 00 basic tutorial :srcset: /tutorials/images/sphx_glr_00_basic_tutorial_010.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 194-203 Generating openPMD output ------------------------- So far, the examples seen until now do not generate any data files. In oder to write the simulation steps to disk, the option ``opmd_diag=True`` must be used when calling the ``track`` method. This will generate ``n_out`` openPMD files in `.h5` format containing the particle species and fields at each simulation step. This files can be read out and analyzed with tools such as ``openPMD-viewer`` or ``VisualPIC``. .. GENERATED FROM PYTHON SOURCE LINES 203-214 .. code-block:: Python # Get again the original distribution. bunch = bunch_bkp.copy() # Create a 1 cm drift with 5 outputs (one every 0.2 cm). drift = Drift(length=1e-2, n_out=5) # Perform tracking and store outputs in a list. bunch_list_out = drift.track(bunch, opmd_diag=True, diag_dir="tutorial_00_diags") .. rst-class:: sphx-glr-script-out .. code-block:: none Drift ----- Length = 0.0100 m CSR off. Tracking in 5 step(s)... [---- ] Tracking in 5 step(s)... [-------- ] Tracking in 5 step(s)... [------------ ] Tracking in 5 step(s)... [---------------- ] Tracking in 5 step(s)... [--------------------] Done (0.025922536849975586 s). -------------------------------------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 215-217 By default, if ``diag_dir`` is not specified, the output files are stored in the ``'diags'`` folder. .. GENERATED FROM PYTHON SOURCE LINES 217-223 .. code-block:: Python import os # List output files. for file in os.listdir("tutorial_00_diags/hdf5/"): print(file) .. rst-class:: sphx-glr-script-out .. code-block:: none data00000004.h5 data00000000.h5 data00000001.h5 data00000003.h5 data00000002.h5 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 4.158 seconds) .. _sphx_glr_download_tutorials_00_basic_tutorial.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 00_basic_tutorial.ipynb <00_basic_tutorial.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 00_basic_tutorial.py <00_basic_tutorial.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 00_basic_tutorial.zip <00_basic_tutorial.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_