Envelope model for laser wakefield acceleration¶
The goal of this tutorial is to give an introduction to the use of the laser envelope model with Smilei. Before starting with this tutorial, we recommend to complete first the tutorial on Azimuthal-mode-decomposition cylindrical geometry. In that Tutorial, Laser Wakefield Acceleration is simulated in a standard way, i.e. the laser is defined through its electromagnetic fields defined on the grid. We recommend also to complete the tutorial Field initialization for a relativistic electron bunch to familiarize with the diagnostics involving the macro-particle quantities.
With 2 MPI processes and 20 OpenMP threads this simulation should run in a few minutes. (remember to set the number of OpenMP threads as explained in Setup).
The following features will be addressed:
Automatic conversion of the output to SI units (
pint
Python module required)Laser envelope initialization “in the box”
Initialization of the species interacting with the laser envelope
Observation of relativistic self-focusing
Automatic conversion of the output to SI units (
pint
Python module required)Analysis of the grid fields when an envelope is present
Use of the envelope ionization module.
Use of the B-TIS3 interpolation scheme with a laser envelope
Physical configuration¶
An ultra high intensity laser enters an under dense plasma. It propagates in the plasma and creates a non linear plasma wave in its wake. The start of the plasma is made of a mixture of hydrogen and nitrogen, while the rest of the plasma is made of pure hydrogen. The laser field is strong enough to ionize the hydrogen and the first 5 levels of the nitrogen much before the arrival of the laser peak field, thus the hydrogen will be assumed ionized and the nitrogen ionized up to level 5. The field of the laser peak is intense enough to further ionize the nitrogen ions. Some of the newly released electrons are trapped and accelerated in the plasma wave behind the laser (hence the name laser wakefield acceleration with ionization injection).
The simulation is run with a Laser Envelope model for the laser pulse. This allows to simulate the laser-plasma interaction in an underdense plasma without the need to resolve the high frequency oscillations of the laser pulse. This way, we can use a coarser cell size along the laser propagation direction x and a coarser timestep, obtaining considerable speed-ups for our simulations. Thus, although the envelope represents a laser pulse, you won’t see the laser oscillations at wavelength \(\lambda_0\) since we are using a laser envelope model.
Furthermore, the simulation of this tutorial is run in cylindrical geometry (only one azimuthal mode), which further speeds-up the simulations. The envelope model is available also in other geometries.
Note
The simulation in this tutorial uses a few macro-particles per cell and a coarse mesh to keep the computational time reasonable. Physically relevant simulations of the considered phenomena would require more macro-particles and a finer mesh. Apart from the numerical artefacts whose mitigation will be addressed in this tutorial, the noise in the grid quantities will be caused also by the small number of macro-particles.
Preparing the case study¶
Download this input file and open it with your favorite editor.
First, note how we defined variables for physical constants and for conversions
from SI units to normalized units. Specifying a reference length, in this case
the laser wavelength, is important to treat ionization. This information is found
in the reference_angular_frequency_SI
argument in the Main
block.
The laser is initialized via the use of LaserEnvelope
block. The laser envelope will be initialized in the box. The longitudinal
profile of the laser is called time_envelope
in analogy with a standard
laser, but it does not represent a temporal variation during the simulation
as when the laser is injected from a window border, as in the tutorial in
Azimuthal-mode-decomposition cylindrical geometry.
To visualize it more easily, think of substituting the time t
with the x
coordinate.
Thus, the center of the laser profile (i.e. its position at t=0
) must be chosen
inside the simulation domain. Note that the focus of the laser can have a longitudinal
position different from the laser center.
We have used the "explicit_reduced_dispersion"
solver for the envelope equation.
For short propagation distances without strong self-focusing (see later in this tutorial)
you can use also the quicker "explicit"
solver.
However, when long propagation distances or quick envelope evolutions
occur in a plasma we recommend to use "explicit_reduced_dispersion"
to have more accurate results.
In those situations the results using the two solvers can be considerably different.
The stability condition for "explicit_reduced_dispersion"
is more strict, so it is
possible that you will need a smaller integration timestep to use it.
Action Run the simulation and open the results:
import happi
S = happi.Open("/example/path/to/the/simulation")
Conversion to SI units¶
We have specified the reference_angular_frequency_SI
in the Main
block
of our input namelist. Therefore, if you have built happi
with the pint
Python module,
you should be able to automatically convert the normalized units of the outputs
towards SI units, as will be shown in the commands of this tutorial.
To do this, while opening the diagnostic you will specify the units in your plot,
e.g. units = ["um","GV/m"]
. If happi
was not built with the pint
module
or if you want to see the results in normalized units, just omit these units
and remember to adjust the vmin
and vmax
of your plot commands.
A subtlety: the envelope of the vector potential vs the envelope of the electric field¶
First, let’s study the laser propagation. Note the MovingWindow
block and
that the window starts moving since the very first iteration of the simulation.
This allows the simulation domain to constantly shift toward the x direction
in order to follow the laser propagation.
Plot the values on the propagation axis of the fields called Env_A_abs
and Env_E_abs
,
with the same scale. For this, use the diagnostic Fields
(if the timestep is
not provided, the last one is plotted by default):
Env_A=S.Probe.Probe0("Env_A_abs", label="Env_A")
Env_E=S.Probe.Probe0("Env_E_abs", label="Env_E")
happi.multiSlide(Env_A,Env_E)
Here we have used the happi
command multiSlide
, that it is analogous to
the command multiPlot
, but allows to slide between multiple timesteps.
Note that we have not converted these outputs to SI units, since in laser wakefield
acceleration the peak normalized field (often called a0
) of the laser pulse can give important information
on the wave excitation regime (nonlinear for a0 > 1.
for example, linear for a0 << 1.
).
Do you see some differences when the simulation advances?
The complex envelope field used for calculations is the envelope of the vector potential
\(\tilde{A}\). In the diagnostics, you can plot its absolute value through Env_A_abs
.
Instead, the field Env_E_abs
is the absolute value of the envelope of the electric field \(\tilde{E}\),
the latter defined to allow comparisons with the field of a standard laser:
\(\tilde{E}=-(\partial_t-ik_0c)\tilde{A}\) (see Smilei’s website for the derivation).
Remember that as explained in the documentation, when the laser
temporal variations are quick, the difference between the two fields will be
sensitive. Both the fields are complex quantities, the abs means that their
absolute value is plotted. These quick temporal evolutions can occur during the
propagation in plasmas.
You can see how the two fields evolve differently in this nonlinear case extracting the data at all timesteps and computing the peak of the field at each timestep:
import numpy as np
import matplotlib.pyplot as plt
dt = S.namelist.dt
timesteps = S.Probe.Probe0("Env_E_abs").getAvailableTimesteps()
Env_A_abs = S.Probe.Probe0("Env_A_abs").getData()
Env_A_abs = np.asarray(Env_A_abs)
Env_A_abs = np.amax(Env_A_abs,axis=1)
plt.plot(timesteps*dt,Env_A_abs,label="|Env_A|")
Env_E_abs = S.Probe.Probe0("Env_E_abs").getData()
Env_E_abs = np.asarray(Env_E_abs)
Env_E_abs = np.amax(Env_E_abs,axis=1)
plt.plot(timesteps*dt,Env_E_abs,label="|Env_E|")
plt.ylabel("field peak [normalized units]")
plt.xlabel("t [normalized units]")
plt.legend()
In the namelist we have specified a peak value for the field equal to a0=1.8
,
and that is the peak value that the laser field in Env_E_abs
would reach in vacuum at the focal plane.
From the previous plot you can see that the laser reaches higher values.
This is due to relativistic self-focusing that occurs in plasmas when the laser
power exceeds the power threshold for the occurrence of this phenomenon.
The interaction of the plasma on the laser pulse propagation is quantified by the
field Env_Chi
, which appears in the envelope equation.
Action Visualize in 2D the envelope fields on the plane xy through the other Probes
defined in the namelist, e.g.:
S.Probe.Probe1("Env_E_abs").slide()
Wakefield excitation¶
Now let’s observe the wakefield formation in the trail of the laser
envelope. Remember that the pusher scheme to use when a laser envelope model is present is
either pusher="ponderomotive_boris"
or pusher="ponderomotive_borisBTIS3"
.
Action Check that the defined Species
has a compatible pusher
scheme.
Through the diagnostic Probe
and the option animate
or slide
, you can follow
the envelope propagation and plasma evolution during the simulation. As before, you can plot the
absolute value of the envelope Env_E_abs
.
You can also follow the formation of the plasma wave, plotting the electron density Rho
.
To see it more clearly, we recommend the use of the option vmax
in the
slide()
or plot()
function, for example:
S.Probe.Probe1("-Rho",units=["um","pC/cm^3"]).slide(figure=2, vmin=0.,vmax=1.5e12)
Note the formation of a bubble behind the laser, whose borders are full of electrons and whose interior is emptied (or almost emptied in some regimes) of electrons.
The longitudinal electric field on axis, very important for electron
Laser Wakefield Acceleration, can be plotted with the Probe
defined on the propagation axis,
choosing the field Ex
in your diagnostic:
S.Probe.Probe0("Ex",units=["um","GV/m"]).slide(figure=3)
Through the function multiSlide
, follow the evolution of the envelope and of
electron density on the axis:
envelope_E = S.Probe.Probe0("20*Env_E_abs",units=["um"],label="20*Env_E_abs")
Ex = S.Probe.Probe0("Ex",label="Ex",units=["um","GV/m"])
happi.multiSlide(Ex,envelope_E)
Note that we have multiplied the laser normalized electric field by 10 in the last command to have a more readable scale in the plot.
The evolution of both the envelope and the electron density can be studied in 2D at the same time through the transparent argument of the multiSlide function. We’ll make transparent all the values of Env_E_abs below 1.:
Rho = S.Probe.Probe1("-Rho",units=["um","pC/cm^3"],cmap="Blues_r",vmin=0.,vmax=1.5e12)
Env_E = S.Probe.Probe1("Env_E_abs",units=["um"],cmap="hot",vmin=0.8,transparent="under")
happi.multiSlide(Rho,Env_E,xmin=0)
This way you should see the laser pulse envelope and the plasma wave in the electron density.
Envelope ionization module¶
As explained in the tutorial for Field ionization, to correctly model
tunnel ionization it is essential to specify a reference frequency, which is already
done in the Main
block of this tutorial’s namelist.
Afterwards, you have to specify a Species
that will be ionized, in this case "nitrogen5plus"
,
whose charge
state at the start of the simulation is lower than its atomic_number
.
Note also that you can keep this Species
frozen and at the same time able to be
ionized. This will avoid spending time in moving macro-particles that do not move too much,
as the nitrogen ions of this laser wakefield simulation set-up.
The new electrons created from the tunnel ionization of this Species
will be
stored in another Species
, specified in ionization_electrons
of "nitrogen5plus"
.
In our case this Species
at the start of the simulation has zero macro-particles.
We could have chosen an already populated species of electrons like bckgelectron
,
but if you want to keep them separated like in this case it can be useful for diagnostics
(although it can take more simulation time, due to cache efficiency).
To ionize "nitrogen5plus"
, a ionization_model
must be selected in its Species
block. Since we are using a laser envelope model, we must use the "tunnel_envelope_averaged"
model.
Physically tunnel ionization occurs at the peaks of the laser field, but these peaks
are not part of an envelope model, by definition.
How can we model tunnel ionization with a laser envelope model then?
The model "tunnel_envelope_averaged"
uses an ADK ionization rate averaged over the
laser oscillations, and a similar averaging is taken into account when the newly created
electrons are initialized, to correctly recreate their transverse momentum dispersion
and the drift in their x direction from tunnel ionization occurring in relativistic regimes.
More details on this model can be found here.
Action Visualize the density of the electrons created through ionization:
S.Probe.Probe1("-Rho_electronfromion",units=["um","pC/cm^3"]).slide(figure=2, vmin=0.,vmax=1.5e12)
Run two new simulations, changing the fraction of the nitrogen dopant in the gas mixture,
stored in the variable dopant_N_concentration=0.10
(i.e. ten percent of nitrogen).
Try a value 1.5 times larger and 1.5 times smaller. How does the Rho_electronfromion
change?
Action Using the same techniques you have used in the tutorial Field initialization for a relativistic electron bunch, try to plot the energy spectrum of the electrons created through ionization.
Reducing the effects of Numerical Cherenkov Radiation¶
As already discussed in this tutorial Azimuthal-mode-decomposition cylindrical geometry,
the use of finite difference solvers for Maxwell’s equations introduces a numerical
dispersion, that interacting with relativistic macro-particles will generate
a numerical artefact called Numerical Cherenkov Radiation.
In that tutorial two methods are shown to cope with this artefact, one of which is
the B-TIS3 interpolation scheme described in
P.-L. Bourgeois and X. Davoine, Journal of Plasma Physics 89 (2023),
that does not remove the Numerical Cherenkov Radiation, but considerably reduces
its effects on the macro-particles, with minimal increase of the simulation time.
Now we will see how to use this feature with a laser envelope model.
The tricky part with an envelope model is that this feature works well only when
the normalized timestep (or dt
) is close to the normalized cell length along x (or dx
), which is
not always compatible with the stability of the envelope solver, expecially
the "explicit_reduced_dispersion"
. Try have at least dt>=0.9*dx
to use
the B-TIS3, but check that the solver results (i.e. the envelope fields) do not
increase exponentially due to a too high dt
.
Action: Run the same simulation again in a new folder, changing the variable use_BTIS3_interpolation
before the Main
block to True
. Note how this changes the pusher
to "ponderomotive_borisBTIS3"
and adds some fields to the Probes
in the namelist.
Check how the electron beam shape changes:
S.Probe.Probe1("-Rho",units=["um","pC/cm^3"]).slide(figure=2, vmin=0.,vmax=1.5e12)
Afterwards, check this combination of Probes
, proportional to the force acting
on the macro-particles along the y direction:
S.Probe.Probe1("Ey-c*BzBTIS3",units=["um","GV/m"]).slide(figure=3,vmin=-20,vmax=20,cmap="seismic")
What difference do you observe if you compare it with the equivalent combination
in the simulation without the B-TIS3 scheme (using Bz
instead of BzBTIS3
)?
Try to repeat the previous postprocessing commands of the tutorial, comparing the results of the simulation using the B-TIS3 and those of the one which did not use it. What differences do you observe?