Skip to content

Latest commit

 

History

History
96 lines (75 loc) · 5.81 KB

IONIZATION.md

File metadata and controls

96 lines (75 loc) · 5.81 KB

Using the Ionization module

Currently, the primary feature of rswarp is the extended Ionization class. Warp's built-in Ionization class allows interaction and creation of arbitrary species in an impact ionization event, but is missing some features, which this extended class aims to implement.

An example of a Warp simulation with ionization can be found at examples/ionization.py. The relevant portions are described below:

from __future__ import division
import numpy as np
from warp import *
from rswarp.utilities.ionization import Ionization
from rswarp.utilities.beam_distributions import createKV

simulateIonization = True

beam_ke = 100  # beam kinetic energy, in eV
beam_gamma = beam_ke/511e3 + 1
beam_beta = np.sqrt(1-1/beam_gamma**2)
sw = 1

This is setup similar to most Warp simulations, except that we import some utilities from rswarp.

beam = Species(type=Electron, name='e-', weight=0)
# These two species represent the emitted particles
h2plus = Species(type=Dihydrogen, charge_state=+1, name='H2+', weight=0)
emittedelec = Species(type=Electron, name='emitted e-', weight=0)

Here, we create the species that will participate in the ionization event. For this example, we treat the incident and emitted electrons as separate Species objects, but it is possible to specify the same Species object for both, so that cascading events may be simulated.

...

if simulateIonization is True:
    target_pressure = 1  # in Pa
    target_temp = 273  # in K
    target_density = target_pressure / boltzmann / target_temp  # in 1/m^3

    ioniz = Ionization(
        stride=100,
        xmin=w3d.xmmin,
        xmax=w3d.xmmax,
        ymin=w3d.ymmin,
        ymax=w3d.ymmax,
        zmin=(w3d.zmmin + w3d.zmmax)/2. - w3d.dz*3,
        zmax=(w3d.zmmin + w3d.zmmax)/2. + w3d.dz*3,
        nx=w3d.nx,
        ny=w3d.ny,
        nz=w3d.nz,
        l_verbose=True
    )

The initialization routine of the Ionization object is identical to Warp. We also calculate the number density of the target gas in terms of more useful engineering parameters here.

    ioniz.add(
        incident_species=beam,
        emitted_species=[h2plus, emittedelec],

If we replaced emittedelec with beam here, we would allow for an arbitrary number of additional ionization events.

        cross_section=h2crosssections.h2_ioniz_crosssection,
        # cross_section=lambda nnew, vi: 1e-20,
        emitted_energy0=[0, h2crosssections.ejectedEnergy],
        # emitted_energy0=[0, lambda nnew, vi: 1./np.sqrt(1.-((vi/2.)/clight)**2) * emass*clight/jperev],
        emitted_energy_sigma=[0, 0],
        # sampleEmittedAngle=lambda nnew, emitted_energy, incident_energy: np.random.uniform(0, 2*np.pi, size=nnew),
        sampleEmittedAngle=h2crosssections.generateAngle,
        # sampleIncidentAngle=lambda nnew, emitted_energy, incident_energy, emitted_theta: np.random.uniform(0, 2*np.pi, size=nnew),

Here, specify the influence of the total, singly-differential, and doubly-differential cross-sections. Warp's built-in behavior allows specifying cross_section as either a constant, or a callable function with a single argument vi, an ndarray containing the velocities of the incident particles. In rswarp, this ability to pass a callable (or list thereof) also applies to emitted_energy0 and emitted_energy_sigma, with the arguments as shown in the commented-out lambdas above. The example as written uses the rsoopic module for its functions describing these distributions for hydrogen.

sampleIncidentAngle and sampleEmittedAngle allow the user to specify a callable for specifying the angles (relative to the incident particle's trajectory) of the incident and emitted particles after ionization, respectively. The arguments to these functions are the number of particles nnew, and the emitted and incident energies. sampleIncidentAngle also takes an additional argument for the angles given to the emitted particles after calling sampleEmittedAngle (this means sampleIncidentAngle will only be called if sampleEmittedAngle is specified). Together, these two functions allow the user to implement emission behavior that resolves momentum transferred to an emitted particle.

Breaking from Warp's behavior, if these sample functions are not specified, the emitted particle will be traveling in the same direction as the incident particle, with a velocity appropriate to its selected energy.

        writeAngleDataDir=diagDir + '/angleDiagnostic',
        writeAnglePeriod=10,

These parameters control writing out of angles of emitted particles. These diagnostics are moderately slow at present, so it is best to leave them disabled unless benchmarking the class's behavior.

        l_remove_incident=False,
        l_remove_target=False,
        ndens=target_density
    )

The Ionization.generate() method is the focus of these extensions, and attention has been given to making the necessary changes in a way that allows reuse for other ionization problems. Specifically, the portion of this method that generates new particles when an ionization event occurs has been extracted into the Ionization.generateEmittedVelocity method, and the method modified to check if the emitted_energy0 and emitted_energy_sigma arguments of passed to Ionization.add are callable, and if so, uses them to generate emission energy on-demand in the same way that a callable can be passed for the cross_section argument. In this way, any user of this extended Ionization class can specify arbitrary emission energy distributions, likely forgoing setting emitted_energy_sigma at all in favor of handling the spread of the desired input in emitted_energy0 itself.