Creating particles
During the generate
Warp has a number of standard particle distributions built in for creating beams. This is described in the manual, in the section on particle loading. The text below describes how to create particles for cases that are not covered by the built in code.
In Warp, particles can be created initially, or during a simulation. Here's how to create particles at the start of a simulation. The basic process is to write a function that creates particles and then install the function so that it is called at the correct time during the generate. The initial charge density and self field solution will include the newly loaded particles. Below is a simple example. This code would be placed before the generate statement in the input file. The plasma_ions, plasma_electrons and beam are all created by Species.
def createmyplasma():
plasma_ions.add_uniform_cylinder(...)
plasma_electrons.add_uniform_cylinder(...)
installparticleloader(createmyplasma)
Instead of using add_uniform_cylinder, the function can create its own particle data and then pass it into the addparticles method. See the documentation of addparticles for more information. For example:
def createmybeam():
beam.addparticles(...)
installparticleloader(createmybeam)
During the simulation
Creating particles directly
While the simulation is in progress, new particles can be directly added at the time of injection. As above, a function needs to be written that creates the particles and then the function is installed so that it is called at the appropriate place during the time step. Here's an example:
def injectelectrons():
electrons.addparticles(...)
installuserinjection(injectelectrons)
After the installation, the function injectelectrons will be called every time step. It will be called just before the particle boundary conditions are applied and before the charge or current density is calculated. Because of this, it is OK if some of the particles added are inside of conductors or outside of the grid.
This method should be used when the added particles fill a finite volume of space, for example when modeling the formation of a plasma via ionization of a background neutral gas.
Creating particles to be injected
With injection turned on, with top.inject=1, a function that creates the particles to be injected can be installed so that it is called at the appropriate place during injection (instead of having Warp create the particles). The function should create particles that are distributed on the injection surface, relative to the location of the surface. During injection, the code will take the particles created by the function and advance them a fractional time step to fill the volume in front of the surface. The function should directly fill arrays that are used during injection. This function will be called for each species that is being injected - the variable w3d.inj_js signifies which species is currently being injected. Note that top.ainject and top.binject must be greater than the maximum position of the particles loaded (relative to the source center). Particles outside of ainject and binject may be skipped.
Here is an example, injecting a non-uniform distribution of particles from a circular emitting surface.
top.inject = 1
top.ainject = source_radius
top.binject = source_radius
w3d.l_inj_user_particles_v = true
def nonlinearsource():
if w3d.inj_js == electrons1.js:
# --- inject np particles of species electrons1
# --- Create the particles on the surface
r = source_radius*random.random(np)
theta = 2.*pi*random.random(np)
x = r*cos(theta)
y = r*sin(theta)
# --- Setup the injection arrays
w3d.npgrp = np
gchange('Setpwork3d')
# --- Fill in the data. All have the same z-velocity, vz1.
w3d.xt[:] = x
w3d.yt[:] = y
w3d.uxt[:] = 0.
w3d.uyt[:] = 0.
w3d.uzt[:] = vz1
installuserparticlesinjection(nonlinearsource)
The flag w3d.l_inj_user_particles_v is turned on since, in this example, the velocities are also being specified. If the flag was false (the default), Warp would set the velocities with a Gaussian distribution using the usual input quantities for injection. There is also the flag w3d.l_inj_user_particles_z which must be set to true if the z position of the particles is specified (putting the data into the w3d.zt array). Note that the z position should be relative to top.zinject.
There is also the flag w3d.l_inj_user_particles_dt, which is set when the function specifies the fractional time advance (in units of seconds) that the particles should be advanced off of the surface. The data is put into the array w3d.bpt. This option is not recommended for use, except for special purposes.
There are two additional flags that may need to be set. Normally, when injection is turned on (top.inject > 0), Warp uses a special field calculation for particles near the emitting surface, enforcing a field profile described by the Child-Langmiur space-charge limited emission theory. For more general purposes, this profile may not be appropriate. The flag top.linj_enormcl can be set to false to turn off the Child-Langmuir profile. When this is done, the flag top.linj_efromgrid should also be set to true.
This method should be used when injecting particles from an emitting surface, or from the edge of the simulation domain.