Skip to content
Projects

wellbalanced

Type part of a name or a dotted path

Global (0D) and 1D fluid models of low-temperature plasmas.

A global model balances, averaged over a chamber, the density of every species and the electron energy (and optionally the gas temperature): the reactions, the losses to the walls, the feed and pumping of the gases and external sources such as a fast beam. Reactions take their rates from plasmacoll’s cross sections, the same data its Monte Carlo collisions use, so a fluid and a kinetic model of the same plasma differ in their physics, not their data.

:class:Fluid1D resolves the same plasma along one dimension: drift-diffusion of every species, the electron energy and Poisson’s equation, implicit, with boundaries that can be changed between steps.

:class:GasDynamics is the neutral gas of a sputtering magnetron, argon and the sputtered metal as one compressible gas in one or two dimensions (its boundaries and sources are in :mod:wellbalanced.gasdynamics).

:class:RFDriver is a 0D RF driver: a global model of its plasma and a transformer model of the coil’s coupling, giving the coil current and the RF power transfer efficiency (:mod:wellbalanced.driver). The spatially resolved models are in :mod:wellbalanced.spatial: :class:InductiveField2D, the inductive RF field of coil windings, conductors and a prescribed plasma in a 2D cut or in r–z, with cold or viscous electrons, and :class:DriverCoupling, that field with a power-dependent plasma.

The solves, time steps and runs carry scope-profiler regions tagged "wellbalanced", an opt-in tag: they record nothing unless an application enables it, e.g. with scope_profiler.setup(enable_tags=["wellbalanced"]).

Attributes

NameDescription
ELECTRONNo description.
MATERIALSNo description.

Classes

NameDescription
BoundaryThe condition of one species at one end.
CellGridCells of a tensor-product grid with any edges, in a cut or in r–z.
ChamberThe volume and walls of the plasma.
CoilThe RF coil: turns windings of radius (m) over length (m).
ConductorA perfect conductor (E = 0 inside): one or several connected shapes.
CuspMulticusp magnetic confinement: cusp lines with a field at the wall.
DriftFluid2DThe magnetron plane of the module docstring.
DriftFluid2DStateThe fields on the (nx, ny) cells.
DriverCouplingA field model and a power-dependent plasma model, solved together.
DriverStateA driver at one absorbed power: its plasma and the coil's view of it.
Fluid1DA plasma between x = 0 and length on cells cells; see the module docstring.
FluidSpeciesA species carried by the fluid model.
FluidStateThe fields on the cells and the fluxes on the faces.
GasDynamicsTwo-species compressible gas in 1D or 2D; see the module docstring.
GasStateThe gas on the grid: the primitive variables at one time.
GasTemperatureThe gas temperature as a balance: heating by the reactions against conduction.
GlobalModelThe balances of a plasma in a chamber; see the module docstring.
GlobalStateA solution of the global model, with every term of its balances.
InductiveField2DThe magnetoquasistatic field of coil windings, conductors and a plasma.
InductiveSolutionThe time-harmonic field of :meth:InductiveField2D.solve, as complex amplitudes.
MagnetronThe ionization region of a magnetron: geometry, gas and target; see the module docstring.
PlasmaRegionThe cells of a plasma: the union of shapes minus the union of excluded.
PotentialBoundaryThe potential at one end: a value (V) or the field E (V/m) there.
RFDriverA cylindrical RF driver: its plasma's global model and its coil.
ReactionOne reaction of the model.
SpeciesA species of the plasma or the gas.
SpokeReportWhat a run says about its azimuthal structure, in the terms of the experiments.
TargetMaterialThe sputtered metal and the response of the target to the ions.
VolumeSourceAn external volume source, e.g. ionization or stripping by a fast beam.
WallReactionA neutral species lost at the walls, with a probability per impact.
WindingOne coil winding: a region carrying sign times the coil current.

Functions

NameDescription
spoke_reportThe :class:SpokeReport of a run over a time window (the last half by default).
stackThe datasets of a scan joined along the scanned parameter.

Modules

  • datasetsThe results as xarray datasets, labelled for plotting.
  • driftfluid2dA 2D axial-azimuthal drift-fluid model of a magnetron: gradient-drift instability and spokes.
  • driverA 0D model of an inductive RF driver: a global model and a transformer model.
  • fluid1dA 1D fluid model of a low-temperature plasma: drift-diffusion, electron energy, Poisson.
  • gasdynamicsA compressible neutral-gas model for the gas in front of a sputtering target.
  • global_modelA global (volume-averaged, 0D) model of a low-temperature plasma.
  • magnetronA global model of the ionization region of a (HiPIMS) magnetron discharge.
  • neutralizerA beam-driven plasma neutralizer: the beam's charge states and the plasma it makes.
  • reactionsReactions: reactants, products, a rate coefficient and the energy they exchange.
  • spatialSpatially resolved (2D) models: the inductive RF field of a driver, in a cut or in r–z.
  • speciesSpecies of a plasma: name, mass and charge.

ELECTRONattributemodule attribute#

ELECTRON = Species('e', ELECTRON_MASS, -1)

MATERIALSattributemodule attribute#

MATERIALS: dict[str, TargetMaterial] = {
  m.name: m for m in (
    _material('Al', 26.982, 5.986, 3, 0.65, 0.55),
    _material('Cr', 51.996, 6.767, 1, 0.9, 0.8),
    _material('Cu', 63.546, 7.726, 1, 1.0, 1.0),
    _material('Ti', 47.867, 6.828, 2, 0.4, 0.3),
    _material('Au', 196.967, 9.226, 1, 2.4, 2.5),
    _material('Mo', 95.95, 7.092, 1, 0.7, 0.8),
    _material('Nb', 92.906, 6.759, 1, 0.5, 0.6)
  )
}

Boundaryclassdataclass#

class Boundary(kind: str, value: float = 0.0, temperature: float | None = None, reflection: float = 0.0)

The condition of one species at one end.

Use the constructors: :meth:wall, :meth:density, :meth:flux, :meth:symmetry. value is the density (m^-3) or the flux into the domain (m^-2 s^-1); temperature (eV) the electron temperature of a prescribed electron density; reflection the wall’s reflection coefficient.

kindattributeinstance attribute#

kind: str

reflectionattributeclass attributeinstance attribute#

reflection: float = 0.0

temperatureattributeclass attributeinstance attribute#

temperature: float | None = None

valueattributeclass attributeinstance attribute#

value: float = 0.0

densitymethodclassmethod#

def density(value: float, temperature: float | None = None) -> Boundary

A prescribed density at the boundary (and, for electrons, temperature).

fluxmethodclassmethod#

def flux(value: float, temperature: float | None = None) -> Boundary

A prescribed flux into the domain (and, for electrons, their temperature).

symmetrymethodclassmethod#

def symmetry() -> Boundary

No flux.

wallmethodclassmethod#

def wall(reflection: float = 0.0) -> Boundary

An absorbing wall: outflow (1 - r)/(1 + r) (max(v_drift, 0) + v_th / 2) n.

CellGridclass#

class CellGrid(x_edges: Sequence[float] | np.ndarray, y_edges: Sequence[float] | np.ndarray, *, geometry: Geometry = 'cartesian', boundaries: tuple[AxisBoundary, AxisBoundary] = ('dirichlet', 'dirichlet'))

Cells of a tensor-product grid with any edges, in a cut or in r–z.

Parameters

NameTypeDefaultDescription
x_edgesSequence[float] | np.ndarrayrequiredCell edges of the first axis (x, or r from >= 0) [m].
y_edgesSequence[float] | np.ndarrayrequiredCell edges of the second axis (y, or z) [m].
geometryGeometry'cartesian'"cartesian" or "cylindrical".
boundariestuple[AxisBoundary, AxisBoundary]('dirichlet', 'dirichlet')The boundary of each axis: "dirichlet" (the field is 0 at the edge), "neumann" (no flux) or "periodic". In r–z the radial axis cannot be periodic, and its lower boundary is the axis when the first edge is 0, whatever is given.

boundariesattributeinstance attribute#

boundaries = tuple(boundaries)

cell_areasattributeinstance attribute#

cell_areas = np.outer(np.diff(self.x_edges), np.diff(self.y_edges))

cell_volumesattributeinstance attribute#

cell_volumes = self.cell_areas * self.circumference

circumferenceattributeinstance attribute#

circumference = np.ones(self.shape) if geometry == 'cartesian' else np.broadcast_to(2.0 * np.pi * self.x[:, None], self.shape).copy()

geometryattributeinstance attribute#

geometry: Geometry = geometry

shapeattributeinstance attribute#

shape = (self.x.size, self.y.size)

sizeattributeinstance attribute#

size = self.shape[0] * self.shape[1]

xattributeinstance attribute#

x = 0.5 * self.x_edges[1:] + self.x_edges[:-1]

x_edgesattributeinstance attribute#

x_edges = np.asarray(x_edges, dtype=float)

yattributeinstance attribute#

y = 0.5 * self.y_edges[1:] + self.y_edges[:-1]

y_edgesattributeinstance attribute#

y_edges = np.asarray(y_edges, dtype=float)

coordinate_namesproperty#

coordinate_names: tuple[str, str]

("x", "y") or ("r", "z").

cylindricalproperty#

cylindrical: bool

Whether the grid is the axisymmetric r–z plane.

dimsproperty#

dims: tuple[str, ...]

The dimensions of a field in a dataset: the two axes.

on_axisproperty#

on_axis: bool

Whether the r–z domain reaches the axis (its first radial edge is 0).

cell_fieldmethod#

def cell_field(value: CellField, dtype: Any = float) -> np.ndarray

A :data:CellField evaluated on the cell centres, shape :attr:shape.

coordinatesmethod#

def coordinates() -> dict[str, tuple[str, np.ndarray, dict[str, str]]]

The cell-centre coordinates as xarray coordinate entries.

curlmethod#

def curl(a: np.ndarray) -> tuple[np.ndarray, np.ndarray]

The in-plane curl of the normal field a on the cell centres.

(d_y a, -d_x a) in the cut; (-d_z a, (1 / r) d(r a) / dr) in r–z.

curl_curlmethod#

def curl_curl(face_coefficient: np.ndarray | None = None, active: np.ndarray | None = None) -> sp.csr_matrix

The curl-curl of the normal field, integrated over the cells (symmetric).

(K a)_i is V_i (curl curl a)_i for the field a on the cells, zero at the Dirichlet edges. face_coefficient (a cell field) scales each face by the mean of its two cells, the coefficient of curl (mu curl a), e.g. a viscosity. With active, only those cells are unknowns: a face to an inactive cell becomes a Dirichlet edge (a = 0) at the face, and the rows and columns of inactive cells are zero.

locatemethod#

def locate(x: float, y: float) -> tuple[int, int]

The cell whose centre is nearest to (x, y) along each axis.

maskmethod#

def mask(shape: Any) -> np.ndarray

The cells whose centre a shape (anything with contains_points) contains.

contains_points takes the (2, n) centres; a CuPy result is copied to the host.

net_currentmethod#

def net_current(residual: np.ndarray, region: np.ndarray) -> Any

The current through a region’s cross-section from V J on its cells.

union_maskmethod#

def union_mask(shapes: Sequence[Any]) -> np.ndarray

The cells any of shapes contains.

wall_cellsmethod#

def wall_cells(inside: np.ndarray) -> np.ndarray

The cells of inside with a face to a cell outside it or to the domain’s edge.

The axis of an r–z domain and periodic seams are not walls.

Chamberclassdataclass#

class Chamber(volume: float, wall_area: float, ion_loss_area: float | None = None, h_factor: float = 1.0, cusp: Cusp | None = None)

The volume and walls of the plasma.

Attributes

NameTypeDescription
volumefloatThe volume in m^3.
wall_areafloatThe total wall area in m^2, seen by the neutrals.
ion_loss_areafloat | NoneThe area in m^2 through which ions leave unconfined; the whole wall if None.
h_factorfloatThe edge-to-centre density ratio at that area.
cuspCusp | NoneMagnetic cusps through which ions leave as well.

cuspattributeclass attributeinstance attribute#

cusp: Cusp | None = None

h_factorattributeclass attributeinstance attribute#

h_factor: float = 1.0

ion_loss_areaattributeclass attributeinstance attribute#

ion_loss_area: float | None = None

volumeattributeinstance attribute#

volume: float

wall_areaattributeinstance attribute#

wall_area: float

ion_areamethod#

def ion_area(electron_temperature: float, ion_temperature: float, ion_mass: float) -> float

Return the effective area in m^2 through which an ion leaves at u_B.

Coilclassdataclass#

class Coil(turns: float, radius: float, length: float, field_factor: float | None = None)

The RF coil: turns windings of radius (m) over length (m).

field_factor is the ratio of its inductance to the long-solenoid one; Nagaoka’s coefficient of the coil if None.

field_factorattributeclass attributeinstance attribute#

field_factor: float | None = None

lengthattributeinstance attribute#

length: float

radiusattributeinstance attribute#

radius: float

turnsattributeinstance attribute#

turns: float

factorproperty#

factor: float

The inductance ratio used: field_factor or Nagaoka’s coefficient.

inductanceproperty#

inductance: float

The coil’s inductance without plasma, K mu0 pi b^2 N^2 / l in H.

Conductorclassdataclass#

class Conductor(shapes: Sequence[Any], floating: bool = False, name: str = '')

A perfect conductor (E = 0 inside): one or several connected shapes.

Attributes

NameTypeDescription
shapesSequence[Any]The shapes it is made of (anything with contains_points).
floatingboolFalse (grounded, the default): a = 0 inside, the value of the far boundary, any net current. True (in a cut only): one uniform unknown A_z and zero net current, a closed loop of plates.
namestrA label for :attr:InductiveSolution.conductor_currents.

floatingattributeclass attributeinstance attribute#

floating: bool = False

nameattributeclass attributeinstance attribute#

name: str = ''

shapesattributeinstance attribute#

shapes: Sequence[Any]

Cuspclassdataclass#

class Cusp(field: float, line_length: float)

Multicusp magnetic confinement: cusp lines with a field at the wall.

line_length (m) is the total length of the cusp lines, field (T) the field at the wall. The ions leave through a strip of the hybrid leak width w = 4 sqrt(rho_e rho_i) along the lines, with rho = sqrt(m T) / (e B) the gyroradius at the thermal speed sqrt(T / m).

fieldattributeinstance attribute#

field: float

line_lengthattributeinstance attribute#

line_length: float

areamethod#

def area(electron_temperature: float, ion_temperature: float, ion_mass: float) -> float

Return the leak area in m^2.

leak_widthmethod#

def leak_width(electron_temperature: float, ion_temperature: float, ion_mass: float) -> float

Return the leak width in m.

DriftFluid2Dclassdataclass#

class DriftFluid2D(length_x: float, length_y: float, nx: int, ny: int, voltage: float = 260.0, magnetic_field: Callable[[Any], Any] | float = 0.0, gas_density: float = 1.45e+20, electron_temperature: float | None = 5.0, momentum_rate: float | Callable[[Any], Any] = argon_momentum_rate, ion_friction_rate: float = 1e-15, ion_mass_u: float = 39.948, ion_temperature: float = 0.025, ionization_rate: Callable[[Any], Any] = argon_ionization_rate, excitation_rate: Callable[[Any], Any] | None = argon_excitation_rate, ionization_energy_ev: float = 15.76, excitation_energy_ev: float = 11.56, secondary_emission: float = 0.06, cathode_current_density: float | None = None, secondary_energy_ev: float = 1.0, refill_rate: float = 10000.0, depletion: float = 1.0, field_bc: float | None = None, periodic_x: bool = False, heating_scale: float = 1.0, diamagnetic: float = 1.0, anode_thermal_flux: bool = False, floor_added: dict = lambda : {'ne': 0.0, 'ni': 0.0, 'N': 0.0}(), _rate_override: np.ndarray | None = None, _lu: spla.SuperLU | None = None, bohm: float = 0.0, external_sources: dict[str, np.ndarray] = dict())

The magnetron plane of the module docstring.

Attributes

NameTypeDescription
length_xfloatThe cathode-anode gap (m).
length_yfloatThe azimuthal period (m).
nxintCells along x.
nyintCells along y (at least 4).
voltagefloatThe discharge voltage (V): the cathode is at -voltage, the anode at 0.
magnetic_fieldCallable[[Any], Any] | floatB_z(x) in T: a callable of the cell positions, or a number.
gas_densityfloatThe neutral density at rest N_0 (m^-3).
electron_temperaturefloat | NoneT_e held fixed (eV), or None for the energy equation.
momentum_ratefloat | Callable[[Any], Any]Electron-neutral momentum-transfer rate coefficient k_en (m^3/s), nu_en = k_en N: a number, or a function of T_e (eV; the default is the PLACEHOLDER :func:argon_momentum_rate).
ion_friction_ratefloatIon-neutral momentum-transfer rate coefficient (m^3/s). PLACEHOLDER.
ion_mass_ufloatThe ion mass in atomic mass units (argon).
ion_temperaturefloatT_i in eV (also the gas temperature).
ionization_rateCallable[[Any], Any]Rate coefficient (m^3/s) as a function of T_e (eV).
excitation_rateCallable[[Any], Any] | NoneExcitation rate coefficient (m^3/s) as a function of T_e, or None for none; excitation_energy_ev is the energy it costs (eV), and ionization_energy_ev the energy an ionization costs. Both are channels of the electron energy loss, with the elastic loss 3 (m / M) nu_en (T_e - T_i).
secondary_emissionfloatElectrons emitted per ion hitting the cathode. PLACEHOLDER.
cathode_current_densityfloat | NoneIf given (A/m^2), the cathode emits this net electron current density, whatever the ion flux, instead of secondary_emission per ion. This is the condition of Boeuf’s PIC (j_e0 = 0.03 A/m^2, the electrons returning to the cathode re-emitted): a fixed gamma makes the discharge an avalanche whenever gamma M >= 1 (M the multiplication), a fixed emitted current gives a stable steady state with gamma_net = j_e0 / j_ion.
secondary_energy_evfloatTemperature of the emitted electrons (eV).
refill_ratefloatRelaxation rate (1/s) of the gas towards N_0 (the gas flow and the sputter wind): the explicit parameter, with depletion, of the neutral dynamics.
depletionfloatFraction of the ionization events that remove a neutral (1: full depletion, 0: a frozen gas).
field_bcfloat | NoneNone for the electrodes at -voltage and 0 V. A number E_0 (V/m) replaces them by a fixed axial field E_x = E_0 at both ends (a pinned potential), so that a perturbation can be uniform along x: the setting for comparing with the local dispersion relation.
heating_scalefloatFactor on the Joule heating of the electron energy (a diagnostic switch).
floor_addeddictRunning total of the density (summed over cells, m^-3) that the floor N_FLOOR on ne, ni and N created in the Euler stages, a diagnostic of how much charge the limiter invents; reset it to zero to start counting.
anode_thermal_fluxboolAdds the thermal flux of an absorbing wall, n v_bar / 2 with v_bar = sqrt(8 e T_e / (pi m)) (Hagelaar et al. 2000, reflection 0), to the drift flux of the electrons at the anode, which otherwise only leave at the drift rate; the outflow is then the larger of the two, and the density next to the anode falls to what carries the current. Tested for Boeuf’s case without success: the 1D discharge then decays and runs away (no sheath barrier for the wall flux), so it is off.
diamagneticfloatFactor on the electron pressure-gradient (diamagnetic) force in the fluxes and the Poisson solve (a diagnostic switch for the linear analysis; 1 is the model).
periodic_xboolPeriodic along x as well, for a uniform plasma in a uniform field field_bc (required) and a uniform B: pure Fourier modes (k_x, k_y) exist, which is what the local dispersion relation describes.
bohmfloatalpha of the anomalous frequency alpha omega_ce / 16 (0 off).
external_sourcesdict[str, np.ndarray]Volume sources added to the time derivative of an unknown ("ne", "ni", "N", "vx", "vy", "w"), numbers or arrays on the cells, per unit time. :meth:stationary_sources returns the ones that make a given state stationary.

anode_thermal_fluxattributeclass attributeinstance attribute#

anode_thermal_flux: bool = False

bohmattributeclass attributeinstance attribute#

bohm: float = 0.0

cathode_current_densityattributeclass attributeinstance attribute#

cathode_current_density: float | None = None

depletionattributeclass attributeinstance attribute#

depletion: float = 1.0

diamagneticattributeclass attributeinstance attribute#

diamagnetic: float = 1.0

electron_temperatureattributeclass attributeinstance attribute#

electron_temperature: float | None = 5.0

excitation_energy_evattributeclass attributeinstance attribute#

excitation_energy_ev: float = 11.56

excitation_rateattributeclass attributeinstance attribute#

excitation_rate: Callable[[Any], Any] | None = argon_excitation_rate

external_sourcesattributeclass attributeinstance attribute#

external_sources: dict[str, np.ndarray] = field(default_factory=dict)

field_bcattributeclass attributeinstance attribute#

field_bc: float | None = None

floor_addedattributeclass attributeinstance attribute#

floor_added: dict = field(default_factory=lambda : {'ne': 0.0, 'ni': 0.0, 'N': 0.0})

gas_densityattributeclass attributeinstance attribute#

gas_density: float = 1.45e+20

heating_scaleattributeclass attributeinstance attribute#

heating_scale: float = 1.0

ion_friction_rateattributeclass attributeinstance attribute#

ion_friction_rate: float = 1e-15

ion_mass_uattributeclass attributeinstance attribute#

ion_mass_u: float = 39.948

ion_temperatureattributeclass attributeinstance attribute#

ion_temperature: float = 0.025

ionization_energy_evattributeclass attributeinstance attribute#

ionization_energy_ev: float = 15.76

ionization_rateattributeclass attributeinstance attribute#

ionization_rate: Callable[[Any], Any] = argon_ionization_rate

length_xattributeinstance attribute#

length_x: float

length_yattributeinstance attribute#

length_y: float

magnetic_fieldattributeclass attributeinstance attribute#

magnetic_field: Callable[[Any], Any] | float = 0.0

momentum_rateattributeclass attributeinstance attribute#

momentum_rate: float | Callable[[Any], Any] = argon_momentum_rate

nxattributeinstance attribute#

nx: int

nyattributeinstance attribute#

ny: int

periodic_xattributeclass attributeinstance attribute#

periodic_x: bool = False

refill_rateattributeclass attributeinstance attribute#

refill_rate: float = 10000.0

secondary_emissionattributeclass attributeinstance attribute#

secondary_emission: float = 0.06

secondary_energy_evattributeclass attributeinstance attribute#

secondary_energy_ev: float = 1.0

voltageattributeclass attributeinstance attribute#

voltage: float = 260.0

charge_residualmethod#

def charge_residual(state: DriftFluid2DState) -> float

Largest |eps0 div E - rho| / (e n): how far the state is from Poisson’s equation.

electric_fieldmethod#

def electric_field(state: DriftFluid2DState) -> np.ndarray

The cell-centre electric field (E_x, E_y), shape (2, nx, ny) (V/m).

electron_fluxmethod#

def electron_flux(state: DriftFluid2DState)

The electron flux on the x-faces (nx + 1, ny) and the y-faces (nx, ny) (m^-2 s^-1).

exb_velocitymethod#

def exb_velocity(state: DriftFluid2DState) -> np.ndarray

The cell-centre E x B drift (E x B) / B^2, shape (2, nx, ny) (m/s).

initial_statemethod#

def initial_state(density: float | np.ndarray = 1000000000000000.0, electron_temperature: float | None = None, gas_density: float | np.ndarray | None = None, potential: np.ndarray | None = None) -> DriftFluid2DState

A quasi-neutral plasma of density (a number or an (nx, ny) array).

The potential is the vacuum one (linear between the electrodes) unless given.

linear_modesmethod#

def linear_modes(state: DriftFluid2DState, mode: int, frozen: tuple[str, ...] = (), epsilon: float = 1e-06) -> LinearModes

Linear stability of a y-uniform state to the azimuthal mode mode, x-resolved.

The Jacobian of the semi-discrete operator (the time derivative of every unknown, with the potential from Poisson’s equation) about state, restricted to perturbations exp(i k y), k = 2 pi mode / length_y: one column per unknown and cell, by finite differences with a cosine and a sine perturbation (the operator is real and invariant along y, so the response to exp(i k y) stays in that mode). The electrodes, the gradients, the Hall tensor and the energy equation are all in it; nothing is x-uniform or local. The state is made stationary by sources of its own residual (as :meth:stationary_sources); external_sources are restored afterwards.

frozen switches off responses, to see what each does: "temperature" (T_e held at its value, no energy perturbation), "ionization" (the ionization source held at its base value), "gas" (the neutral density not perturbed).

With s = gamma - i omega the eigenvalues, exp(i k y + s t), gamma > 0 grows and omega / k > 0 moves along +y (the E x B direction when E_x < 0 and B_z > 0).

runmethod#

def run(state: DriftFluid2DState, t_end: float, dt: float | None = None, cfl: float = 0.4, record_every: float | None = None, probe_x: float | None = None, callback: Callable[[DriftFluid2DState], None] | None = None) -> Run

Advance state by t_end seconds and record the electron density along y.

Parameters

NameTypeDefaultDescription
stateDriftFluid2DStaterequiredThe initial state.
t_endfloatrequiredThe duration (s).
dtfloat | NoneNoneA fixed step (s); by default the step is re-chosen from cfl every 20 steps.
cflfloat0.4The Courant number of the chosen step.
record_everyfloat | NoneNoneThe recording interval (s); t_end / 200 by default.
probe_xfloat | NoneNoneWhere along x to record (m); mid-gap by default.
callbackCallable[[DriftFluid2DState], None] | NoneNoneCalled with the state at every recording.

stationary_sourcesmethod#

def stationary_sources(state: DriftFluid2DState) -> dict[str, np.ndarray]

The external sources that make state stationary (well-balanced equilibria).

Sets external_sources to -d u / d t of the state without them and returns it, so that the state is a steady state of the discrete equations and only a perturbation evolves; the way to test linear growth on an equilibrium that the physical sources would not hold.

stepmethod#

def step(state: DriftFluid2DState, dt: float) -> DriftFluid2DState

Advance by dt with SSP-RK3; the potential of the result is that of the last stage.

suggest_timestepmethod#

def suggest_timestep(state: DriftFluid2DState, cfl: float = 0.4) -> float

A step with Courant number cfl: electron drift, ions, and diffusion.

The diffusive limit is that of the (explicit) energy and density diffusion with D = (5/3) mu_perp T_e, which becomes the binding one where B is small and the electrons are hot.

DriftFluid2DStateclassdataclass#

class DriftFluid2DState(x: np.ndarray, y: np.ndarray, electron_density: np.ndarray, ion_density: np.ndarray, ion_velocity: np.ndarray, gas_density: np.ndarray, electron_temperature: np.ndarray, potential: np.ndarray, time: float = 0.0)

The fields on the (nx, ny) cells.

Attributes

NameTypeDescription
xnp.ndarrayCell centres along x (m).
ynp.ndarrayCell centres along y (m).
electron_densitynp.ndarrayn_e (m^-3).
ion_densitynp.ndarrayn_i (m^-3).
ion_velocitynp.ndarray(v_x, v_y) of the ions, shape (2, nx, ny) (m/s).
gas_densitynp.ndarrayThe neutral density N (m^-3).
electron_temperaturenp.ndarrayT_e (eV).
potentialnp.ndarrayphi (V).
timefloatTime (s).

electron_densityattributeinstance attribute#

electron_density: np.ndarray

electron_temperatureattributeinstance attribute#

electron_temperature: np.ndarray

gas_densityattributeinstance attribute#

gas_density: np.ndarray

ion_densityattributeinstance attribute#

ion_density: np.ndarray

ion_velocityattributeinstance attribute#

ion_velocity: np.ndarray

potentialattributeinstance attribute#

potential: np.ndarray

timeattributeclass attributeinstance attribute#

time: float = 0.0

xattributeinstance attribute#

x: np.ndarray

yattributeinstance attribute#

y: np.ndarray

copymethod#

def copy() -> DriftFluid2DState

A deep copy.

to_datasetmethod#

def to_dataset() -> xr.Dataset

The state as a labelled dataset on (x, y).

DriverCouplingclassdataclass#

class DriverCoupling(field: Callable[[PlasmaProfile], InductiveField2D], plasma: Callable[[float], tuple[PlasmaProfile, Any]], network_resistance: float, depth: float | None = None)

A field model and a power-dependent plasma model, solved together.

Attributes

NameTypeDescription
fieldCallable[[PlasmaProfile], InductiveField2D]profile -> InductiveField2D.
plasmaCallable[[float], tuple[PlasmaProfile, Any]]absorbed power [W] -> (PlasmaProfile, anything).
network_resistancefloatR_net [Ohm].
depthfloat | NoneThe effective depth of a cut [m]; None in r–z.

depthattributeclass attributeinstance attribute#

depth: float | None = None

fieldattributeinstance attribute#

field: Callable[[PlasmaProfile], InductiveField2D]

network_resistanceattributeinstance attribute#

network_resistance: float

plasmaattributeinstance attribute#

plasma: Callable[[float], tuple[PlasmaProfile, Any]]

at_absorbed_powermethod#

def at_absorbed_power(power: float) -> CoupledState

The operating point where the plasma absorbs power W.

at_rf_powermethod#

def at_rf_power(rf_power: float, *, guess: float | None = None, tolerance: float = 1e-06, max_iterations: int = 50, relaxation: float = 1.0) -> CoupledState

The operating point at the generator power rf_power W.

Iterates P <- P + relaxation (eta(P) P_RF - P) from guess (half the generator power by default) until |eta P_RF - P| < tolerance P_RF.

DriverStateclassdataclass#

class DriverState(plasma: GlobalState, power: float, frequency: float, collision_frequency: float, coil_impedance: complex, network_resistance: float, skin_depth: float)

A driver at one absorbed power: its plasma and the coil’s view of it.

Attributes

NameTypeDescription
plasmaGlobalStateThe steady state of the driver’s global model.
powerfloatThe power the plasma absorbs in W.
frequencyfloatThe RF frequency in Hz.
collision_frequencyfloatThe electrons’ momentum-transfer frequency nu_m (1/s).
coil_impedancecomplexZ_s in Ohm; its real part is R_s.
network_resistancefloatR_net in Ohm.
skin_depthfloat1 / Re k in m.

coil_impedanceattributeinstance attribute#

coil_impedance: complex

collision_frequencyattributeinstance attribute#

collision_frequency: float

frequencyattributeinstance attribute#

frequency: float

network_resistanceattributeinstance attribute#

network_resistance: float

plasmaattributeinstance attribute#

plasma: GlobalState

powerattributeinstance attribute#

power: float

skin_depthattributeinstance attribute#

skin_depth: float

coil_currentproperty#

coil_current: float

The coil current amplitude sqrt(2 P / R_s) in A.

coil_voltageproperty#

coil_voltage: float

The voltage amplitude across the coil, |Z_s| I, in V.

efficiencyproperty#

efficiency: float

The RF power transfer efficiency R_s / (R_s + R_net).

plasma_resistanceproperty#

plasma_resistance: float

R_s = Re Z_s in Ohm.

rf_powerproperty#

rf_power: float

The power the generator delivers, P / eta, in W.

to_datasetmethod#

def to_dataset() -> xr.Dataset

The plasma’s dataset with the coupling’s quantities.

Fluid1Dclassdataclass#

class Fluid1D(species: Sequence[FluidSpecies], reactions: Sequence[Reaction], length: float, cells: int, fixed: Mapping[str, float | np.ndarray] = dict(), gas_temperature: float = 0.025, electron_temperature: float | None = None, boundaries: dict[str, dict[str, Boundary]] = dict(), potential: dict[str, PotentialBoundary] = dict(), heating: float | np.ndarray = 0.0, sources: Mapping[str, float | np.ndarray] = dict(), volume_sources: Sequence[VolumeSource] = ())

A plasma between x = 0 and length on cells cells; see the module docstring.

Attributes

NameTypeDescription
speciesSequence[FluidSpecies]The fluid species, the electrons ("e") included.
reactionsSequence[Reaction]The volume reactions; reactants that are not fluid species must be in fixed.
lengthfloatThe domain length (m).
cellsintThe number of cells.
fixedMapping[str, float | np.ndarray]Densities of species not carried by the model, e.g. the gas (m^-3, a number or an array on the cells).
gas_temperaturefloatT_g in eV.
electron_temperaturefloat | NoneNone solves the electron energy equation; a number holds T_e fixed (isothermal electrons).
boundariesdict[str, dict[str, Boundary]]{"left": {species: Boundary}, "right": {...}}; a species missing at an end has a wall there.
potentialdict[str, PotentialBoundary]{"left": PotentialBoundary, "right": ...}; grounded if missing.
heatingfloat | np.ndarrayPower to the electrons (W/m^3), a number or an array on the cells.
sourcesMapping[str, float | np.ndarray]External volume sources {species: rate} (m^-3 s^-1), numbers or arrays on the cells.
volume_sourcesSequence[VolumeSource]External sources as for the global model, e.g. a beam’s (:meth:wellbalanced.neutralizer.Neutralizer.beam_sources): rates per unit density of fluid or fixed species, numbers or arrays on the cells, with the energy they give the electrons.

boundariesattributeclass attributeinstance attribute#

boundaries: dict[str, dict[str, Boundary]] = field(default_factory=dict)

cellsattributeinstance attribute#

cells: int

electron_temperatureattributeclass attributeinstance attribute#

electron_temperature: float | None = None

fixedattributeclass attributeinstance attribute#

fixed: Mapping[str, float | np.ndarray] = field(default_factory=dict)

gas_temperatureattributeclass attributeinstance attribute#

gas_temperature: float = 0.025

heatingattributeclass attributeinstance attribute#

heating: float | np.ndarray = 0.0

lengthattributeinstance attribute#

length: float

potentialattributeclass attributeinstance attribute#

potential: dict[str, PotentialBoundary] = field(default_factory=dict)

reactionsattributeinstance attribute#

reactions: Sequence[Reaction]

sourcesattributeclass attributeinstance attribute#

sources: Mapping[str, float | np.ndarray] = field(default_factory=dict)

speciesattributeinstance attribute#

species: Sequence[FluidSpecies]

volume_sourcesattributeclass attributeinstance attribute#

volume_sources: Sequence[VolumeSource] = ()

advancemethod#

def advance(unknowns: np.ndarray, duration: float, dt: float) -> np.ndarray

Step duration seconds with steps of at most dt, halving failed ones.

balancemethod#

def balance(state: FluidState) -> dict[str, float]

Return the volume source minus the net outflow of every species.

In m^-2 s^-1 (per unit area of the slab); zero at a steady state.

boundarymethod#

def boundary(end: str, name: str) -> Boundary

The condition of a species at an end (a wall unless set).

energy_balancemethod#

def energy_balance(state: FluidState) -> dict[str, float]

Return the electron energy terms, integrated over the slab (eV m^-2 s^-1).

heating (external), field (work of the field, -Gamma_e E), reactions (lost in collisions, negative), sources (given by the volume sources) and walls (the energy flux out through both ends, negative); at a steady state they sum to zero.

packmethod#

def pack(densities: Mapping[str, np.ndarray | float], electron_temperature: np.ndarray | float = 2.0, potential: np.ndarray | float = 0.0, fluxes: Mapping[str, np.ndarray | float] | None = None) -> np.ndarray

The unknowns of fields on the cells (densities by name, T_e, phi).

fluxes start the species with momentum: on the cells + 1 faces (as :attr:FluidState.fluxes), on the cells - 1 faces between cells, or a number; zero if missing.

set_boundarymethod#

def set_boundary(end: str, name: str, boundary: Boundary) -> None

Change the condition of a species at an end, e.g. between steps.

statemethod#

def state(unknowns: np.ndarray, time: float = 0.0, converged: bool = True) -> FluidState

The :class:FluidState of a vector of unknowns.

steady_statemethod#

def steady_state(unknowns: np.ndarray, *, dt: float = 1e-09, growth: float = 2.0, max_dt: float = 1.0, max_steps: int = 400) -> FluidState

Return the steady state.

Steps in pseudo-time from unknowns with a step growing from dt up to max_dt, then solves the steady equations from there. A failed step is retried with a quarter of it; below a millionth of the first step the search stops and the state is returned with converged=False.

stepmethod#

def step(unknowns: np.ndarray, dt: float) -> tuple[np.ndarray, bool]

One backward-Euler step of dt seconds; return the new unknowns and success.

FluidSpeciesclassdataclass#

class FluidSpecies(species: Species, mobility: float = 0.0, diffusion: float | None = None, momentum: bool = False)

A species carried by the fluid model.

Attributes

NameTypeDescription
speciesSpeciesName, mass and charge.
mobilityfloatmu in m^2/(V s) (charged species).
diffusionfloat | NoneD in m^2/s; for a charged species None takes the Einstein relation D = mu T (T_e for electrons, T_g for ions).
momentumboolSolve the momentum equation of this ion species (with the friction e / (M mu) of its mobility) instead of drift-diffusion.

diffusionattributeclass attributeinstance attribute#

diffusion: float | None = None

mobilityattributeclass attributeinstance attribute#

mobility: float = 0.0

momentumattributeclass attributeinstance attribute#

momentum: bool = False

speciesattributeinstance attribute#

species: Species

nameproperty#

name: str

The species name.

FluidStateclassdataclass#

class FluidState(x: np.ndarray, faces: np.ndarray, densities: dict[str, np.ndarray], electron_temperature: np.ndarray, potential: np.ndarray, fluxes: dict[str, np.ndarray], reaction_rates: dict[str, np.ndarray], time: float = 0.0, converged: bool = True)

The fields on the cells and the fluxes on the faces.

Attributes

NameTypeDescription
xnp.ndarrayCell centres (m).
facesnp.ndarrayFace positions (m).
densitiesdict[str, np.ndarray]Density of every fluid species on the cells (m^-3).
electron_temperaturenp.ndarrayT_e on the cells (eV).
potentialnp.ndarrayphi on the cells (V).
fluxesdict[str, np.ndarray]Flux of every fluid species on the faces (m^-2 s^-1), positive along x; "energy" is the electron energy flux (eV m^-2 s^-1).
reaction_ratesdict[str, np.ndarray]Volume rate of every reaction on the cells (m^-3 s^-1).
timefloatTime (s) of the state; inf for a steady state.
convergedboolWhether the last solve converged.

convergedattributeclass attributeinstance attribute#

converged: bool = True

densitiesattributeinstance attribute#

densities: dict[str, np.ndarray]

electron_temperatureattributeinstance attribute#

electron_temperature: np.ndarray

facesattributeinstance attribute#

faces: np.ndarray

fluxesattributeinstance attribute#

fluxes: dict[str, np.ndarray]

potentialattributeinstance attribute#

potential: np.ndarray

reaction_ratesattributeinstance attribute#

reaction_rates: dict[str, np.ndarray]

timeattributeclass attributeinstance attribute#

time: float = 0.0

xattributeinstance attribute#

x: np.ndarray

integralmethod#

def integral(values: np.ndarray) -> float

The integral of a cell field over the domain.

to_datasetmethod#

def to_dataset() -> xr.Dataset

The state as a labelled dataset.

Fields on the cells x, fluxes on the faces x_face, per species and reaction.

velocitymethod#

def velocity(name: str) -> np.ndarray

The mean velocity of a species on the faces (m/s): its flux over the density there.

The density on a face between cells is the mean of the two; on an end face, that of the cell next to it.

GasDynamicsclass#

class GasDynamics(length: float, cells: int, *, width: float = 1.0, cells_y: int = 1, gas_mass: float = ARGON_MASS, metal_mass: float = 47.867 * ATOMIC_MASS, gamma: float = 5.0 / 3.0, diffusion: float | Callable[[np.ndarray, np.ndarray], np.ndarray] | None = None, thermal_conductivity: float | Callable[[np.ndarray], np.ndarray] = 0.0, boundaries: Mapping[str, Boundary] | None = None, limiter: str = 'vanleer', cfl: float = 0.4, source_cfl: float = 0.2)

Two-species compressible gas in 1D or 2D; see the module docstring.

Parameters

NameTypeDefaultDescription
lengthfloatrequiredLength of the domain along x in m (the target at x = 0).
cellsintrequiredNumber of cells along x.
widthfloat1.0Width in y in m (the depth of a 1D model: totals are per m^2 for 1).
cells_yint1Number of cells along y (1: one-dimensional).
gas_massfloatARGON_MASSThe mass of an atom of the gas in kg (argon).
metal_massfloat47.867 * ATOMIC_MASSThe mass of a metal atom in kg (titanium by default).
gammafloat5.0 / 3.0The adiabatic index (5/3: monatomic).
diffusionfloat | Callable[[np.ndarray, np.ndarray], np.ndarray] | NoneNoneThe binary diffusion coefficient D in m^2/s: a number or a function of the temperature (K) and the pressure (Pa) arrays (see :func:binary_diffusion). None: no diffusion.
thermal_conductivityfloat | Callable[[np.ndarray], np.ndarray]0.0kappa in W/(m K) (number or function of T); 0: none.
boundariesMapping[str, Boundary] | NoneNoneThe conditions at "left" and "right" (default: a wall at the left, an outflow at the right).
limiterstr'vanleer'"minmod", "vanleer" (default), "mc" or "none" (central slopes: second order on smooth flow, not monotone).
cflfloat0.4The Courant number of the hyperbolic step.
source_cflfloat0.2The largest share of the content of a cell that a wall emission, a source or a sink may add or remove in one step.

boundariesattributeinstance attribute#

boundaries: dict[str, Boundary] = {'left': Boundary.wall(), 'right': Boundary.outflow()}

budgetattributeinstance attribute#

budget = dict.fromkeys(QUANTITIES, 0.0)

cflattributeinstance attribute#

cfl = cfl

diffusionattributeinstance attribute#

diffusion = diffusion

exchangeattributeinstance attribute#

exchange: list[IonExchange] = []

gammaattributeinstance attribute#

gamma = gamma

limiterattributeinstance attribute#

limiter = limiter

massesattributeinstance attribute#

masses = {'gas': gas_mass, 'metal': metal_mass}

relaxationattributeinstance attribute#

relaxation: list[ThermalRelaxation] = []

sink_frequenciesattributeinstance attribute#

sink_frequencies: dict[str, float | np.ndarray] = {}

sinksattributeinstance attribute#

sinks: dict[str, float | np.ndarray] = {}

source_cflattributeinstance attribute#

source_cfl = source_cfl

sourcesattributeinstance attribute#

sources: list[VolumeSource] = []

stepsattributeinstance attribute#

steps = 0

thermal_conductivityattributeinstance attribute#

thermal_conductivity = thermal_conductivity

timeattributeinstance attribute#

time = 0.0

xattributeinstance attribute#

x = np.arange(cells) + 0.5 * self.dx

yattributeinstance attribute#

y = np.arange(cells_y) + 0.5 * self.dy

runmethod#

def run(t_end: float, *, callback: Callable[[GasDynamics], None] | None = None, every: int = 1) -> GasState

Step until time == t_end (the last step is shortened); returns the state.

Parameters

NameTypeDefaultDescription
t_endfloatrequiredThe end time in s.
callbackCallable[[GasDynamics], None] | NoneNoneCalled with the model after every every steps.
everyint1The interval of the callback in steps.

set_statemethod#

def set_state(gas_density: float | np.ndarray, metal_density: float | np.ndarray = 0.0, u: float | np.ndarray = 0.0, v: float | np.ndarray = 0.0, pressure: float | np.ndarray = 1.0, *, time: float = 0.0) -> None

Set the gas: mass densities (kg/m^3), velocities (m/s) and the pressure (Pa).

Each is a number, an array of (nx,) along x ((nx, 1) is also accepted) or of the grid’s shape.

set_uniformmethod#

def set_uniform(pressure: float, temperature: float, metal_fraction: float = 0.0) -> None

A gas at rest of one pressure, temperature and metal mass fraction.

stable_stepmethod#

def stable_step() -> float

The acoustic CFL time step of the current state.

statemethod#

def state() -> GasState

The current gas as a :class:GasState.

steady_statemethod#

def steady_state(tolerance: float = 1e-08, max_time: float = 1.0, check_every: int = 200) -> GasState

Step until the density of the gas and of the metal stop changing.

Stops when the largest relative change of the densities over check_every steps, per unit time of length / c, is below tolerance.

Raises

RuntimeError
If max_time is reached first.

stepmethod#

def step(dt: float | None = None) -> float

Advance one step (the stable step by default); returns the step taken.

temperaturemethod#

def temperature(prim: np.ndarray | None = None) -> np.ndarray

The temperature field in K.

totalsmethod#

def totals() -> dict[str, float]

The integrals of the conserved quantities over the domain (per unit depth).

GasStateclassdataclass#

class GasState(time: float, x: np.ndarray, y: np.ndarray, gas_density: np.ndarray, metal_density: np.ndarray, u: np.ndarray, v: np.ndarray, pressure: np.ndarray, temperature: np.ndarray, gas_number: np.ndarray, metal_number: np.ndarray)

The gas on the grid: the primitive variables at one time.

Attributes

NameTypeDescription
timefloatThe time in s.
xnp.ndarrayCell centres along the axis, m.
ynp.ndarrayCell centres across, m.
gas_densitynp.ndarrayArgon mass density, kg/m^3, shape (nx, ny).
metal_densitynp.ndarrayMetal mass density, kg/m^3.
unp.ndarrayAxial velocity, m/s.
vnp.ndarrayAzimuthal velocity, m/s.
pressurenp.ndarrayPressure, Pa.
temperaturenp.ndarrayTemperature, K.
gas_numbernp.ndarrayArgon number density, m^-3.
metal_numbernp.ndarrayMetal number density, m^-3.

gas_densityattributeinstance attribute#

gas_density: np.ndarray

gas_numberattributeinstance attribute#

gas_number: np.ndarray

metal_densityattributeinstance attribute#

metal_density: np.ndarray

metal_numberattributeinstance attribute#

metal_number: np.ndarray

pressureattributeinstance attribute#

pressure: np.ndarray

temperatureattributeinstance attribute#

temperature: np.ndarray

timeattributeinstance attribute#

time: float

uattributeinstance attribute#

u: np.ndarray

vattributeinstance attribute#

v: np.ndarray

xattributeinstance attribute#

x: np.ndarray

yattributeinstance attribute#

y: np.ndarray

to_datasetmethod#

def to_dataset() -> xr.Dataset

The state as a labelled dataset: x (and y when the grid has more than one cell).

GasTemperatureclassdataclass#

class GasTemperature(wall_temperature: float, conductivity: float, diffusion_length: float, heat_capacity: float = 2.5)

The gas temperature as a balance: heating by the reactions against conduction.

The conduction loss is kappa (T_g - T_w) / Lambda^2 (W/m^3), with the thermal conductivity kappa (W/m/K) and the diffusion length Lambda (m) of the chamber. heat_capacity is the heat capacity per particle in units of k (3/2 for atoms, 5/2 for diatomic molecules), which only sets how fast the temperature moves towards its steady state.

conductivityattributeinstance attribute#

conductivity: float

diffusion_lengthattributeinstance attribute#

diffusion_length: float

heat_capacityattributeclass attributeinstance attribute#

heat_capacity: float = 2.5

wall_temperatureattributeinstance attribute#

wall_temperature: float

GlobalModelclassdataclass#

class GlobalModel(species: Sequence[Species], reactions: Sequence[Reaction], chamber: Chamber, power: float | Callable[[float], float] = 0.0, fixed: Mapping[str, float] = dict(), feed: Mapping[str, float] = dict(), pumping_speed: float = 0.0, sources: Sequence[VolumeSource] = (), wall_reactions: Sequence[WallReaction] = (), ion_wall_products: Mapping[str, Mapping[str, float]] = dict(), gas_temperature: float | GasTemperature = 0.025, thermalize_electrons: bool = False)

The balances of a plasma in a chamber; see the module docstring.

Attributes

NameTypeDescription
speciesSequence[Species]Every species, the electrons (named "e") included.
reactionsSequence[Reaction]The volume reactions.
chamberChamberVolume, walls and confinement.
powerfloat | Callable[[float], float]Power absorbed by the electrons in W, or a function of the time in s, power(t), for :meth:GlobalModel.evolve (a steady state is then taken at t = 0).
fixedMapping[str, float]Densities held fixed (m^-3), e.g. a gas at a given pressure.
feedMapping[str, float]Particles per second fed into the chamber, by species.
pumping_speedfloatVolume per second (m^3/s) pumped out, of every neutral species that is not held fixed.
sourcesSequence[VolumeSource]External volume sources.
wall_reactionsSequence[WallReaction]Losses of neutral species at the walls.
ion_wall_productsMapping[str, Mapping[str, float]]What an ion returns to the volume after reaching the wall, {ion: {product: number}}, e.g. {"H2+": {"H2": 1}}.
gas_temperaturefloat | GasTemperatureA fixed gas temperature in eV, or its balance.
thermalize_electronsboolKeep T_e >= T_g. Without sources of energy the wall losses cool the electrons of a decaying plasma below the gas, which no elastic collision allows; set it for afterglows.

chamberattributeinstance attribute#

chamber: Chamber

feedattributeclass attributeinstance attribute#

feed: Mapping[str, float] = field(default_factory=dict)

fixedattributeclass attributeinstance attribute#

fixed: Mapping[str, float] = field(default_factory=dict)

gas_temperatureattributeclass attributeinstance attribute#

gas_temperature: float | GasTemperature = 0.025

ion_wall_productsattributeclass attributeinstance attribute#

ion_wall_products: Mapping[str, Mapping[str, float]] = field(default_factory=dict)

powerattributeclass attributeinstance attribute#

power: float | Callable[[float], float] = 0.0

pumping_speedattributeclass attributeinstance attribute#

pumping_speed: float = 0.0

reactionsattributeinstance attribute#

reactions: Sequence[Reaction]

sourcesattributeclass attributeinstance attribute#

sources: Sequence[VolumeSource] = ()

speciesattributeinstance attribute#

species: Sequence[Species]

thermalize_electronsattributeclass attributeinstance attribute#

thermalize_electrons: bool = False

wall_reactionsattributeclass attributeinstance attribute#

wall_reactions: Sequence[WallReaction] = ()

evaluatemethod#

def evaluate(state: np.ndarray, converged: bool = True, t: float = 0.0) -> GlobalState

Return the :class:GlobalState of a state vector at t, with every term.

evolvemethod#

def evolve(times: Sequence[float] | np.ndarray, initial: Mapping[str, float] | GlobalState | None = None, *, breakpoints: Sequence[float] = ()) -> list[GlobalState]

The states at times (s) of the balances integrated in time.

The integration starts at times[0] from initial (see :meth:steady_state) with an implicit method, driven by power(t) if that is a function. Stop at every breakpoints time inside the interval, where the drive jumps (the edges of a pulse), so the step size does not have to find them.

scanmethod#

def scan(parameter: str, values: Sequence[Any], **guess: float) -> list[GlobalState]

Steady states for every value of a field of the model.

Each starts from the last (a continuation); guess starts the first.

steady_statemethod#

def steady_state(initial: Mapping[str, float] | GlobalState | None = None, *, t_max: float = 10.0, tolerance: float = 1e-08) -> GlobalState

Return the steady state.

The balances are integrated in pseudo-time from initial (densities by name, "Te" and "Tg" in eV; a previous :class:GlobalState for a continuation) with an implicit method for up to t_max seconds, and the end point refined with a root finder. converged is set when every relative rate of change is below tolerance times the fastest rate of the model’s processes.

GlobalStateclassdataclass#

class GlobalState(densities: dict[str, float], electron_temperature: float, gas_temperature: float, reaction_rates: dict[str, float], wall_losses: dict[str, float], power: dict[str, float], particle_balance: dict[str, float], converged: bool = True)

A solution of the global model, with every term of its balances.

Attributes

NameTypeDescription
densitiesdict[str, float]Every species’ density in m^-3, the electrons included.
electron_temperaturefloatT_e in eV.
gas_temperaturefloatT_g in eV.
reaction_ratesdict[str, float]Volume rate of every reaction (m^-3 s^-1), by name.
wall_lossesdict[str, float]Volume rate at which every species reaches the walls (m^-3 s^-1), the electrons included.
powerdict[str, float]Electron power terms in W (positive: gained), by channel; at steady state they sum to zero.
particle_balancedict[str, float]dn/dt of every species (m^-3 s^-1); zero at steady state, except for a species held fixed, where it is the rate the reactions consume it at (and its feed would have to make up).
convergedboolWhether the steady state was reached.

convergedattributeclass attributeinstance attribute#

converged: bool = True

densitiesattributeinstance attribute#

densities: dict[str, float]

electron_temperatureattributeinstance attribute#

electron_temperature: float

gas_temperatureattributeinstance attribute#

gas_temperature: float

particle_balanceattributeinstance attribute#

particle_balance: dict[str, float]

powerattributeinstance attribute#

power: dict[str, float]

reaction_ratesattributeinstance attribute#

reaction_rates: dict[str, float]

wall_lossesattributeinstance attribute#

wall_losses: dict[str, float]

electron_densityproperty#

electron_density: float

n_e in m^-3.

electronegativitymethod#

def electronegativity(negative_ions: Iterable[str]) -> float

sum n_- / n_e for the named negative ions.

ionization_degreemethod#

def ionization_degree(gases: Iterable[str]) -> float

n_e / (n_e + sum n_gas) for the named gases.

to_datasetmethod#

def to_dataset() -> xr.Dataset

The state as a labelled dataset (dimensions species, reaction, channel).

InductiveField2Dclass#

class InductiveField2D(x_edges: Sequence[float] | np.ndarray | None = None, y_edges: Sequence[float] | np.ndarray | None = None, *, frequency: float, windings: Sequence[Winding] = (), conductors: Sequence[Conductor] = (), electron_density: CellField = 0.0, collision_frequency: CellField = 0.0, electron_temperature: CellField | None = None, electron_viscosity: CellField | None = None, plasma_region: PlasmaRegion | None = None, boundaries: tuple[AxisBoundary, AxisBoundary] | None = None, geometry: Geometry | None = None, electron_drift: Any = None, grid: CellGrid | PatchGrid | None = None)

The magnetoquasistatic field of coil windings, conductors and a plasma.

Parameters

NameTypeDefaultDescription
x_edgesSequence[float] | np.ndarray | NoneNoneCell edges of the first axis (x, or r from >= 0) [m]: a tensor grid; or give grid.
y_edgesSequence[float] | np.ndarray | NoneNoneCell edges of the second axis (y, or z) [m].
frequencyfloatrequiredThe driving frequency [Hz].
windingsSequence[Winding]()The coil windings; each carries sign times the coil current.
conductorsSequence[Conductor]()The perfect conductors.
electron_densityCellField0.0n_e [m^-3] on the cells (set to zero in the windings, the conductors and outside plasma_region).
collision_frequencyCellField0.0The electron momentum-transfer frequency nu [1/s].
electron_temperatureCellField | NoneNoneT_e [eV]: with it, the electrons carry the collisional viscosity (2/3) n_e e T_e / nu (nu > 0 in the plasma).
electron_viscosityCellField | NoneNonemu_e [Pa s] directly, instead of from T_e; zero gives the momentum balance without viscosity (the cold plasma, solved with u).
plasma_regionPlasmaRegion | NoneNoneWhere the plasma is; everywhere if None.
boundariestuple[AxisBoundary, AxisBoundary] | NoneNoneThe boundary of each axis (see :class:CellGrid); default ("dirichlet", "dirichlet"), or the grid’s.
geometryGeometry | NoneNone"cartesian" (a cut, A_z) or "cylindrical" (r–z, A_phi); default "cartesian", or the grid’s.
electron_driftAnyNoneThe in-plane electron velocity for the RF Lorentz force; not implemented until Fluid2D provides it.
gridCellGrid | PatchGrid | NoneNoneA grid instead of the edges, e.g. a :class:~wellbalanced.spatial.patches.PatchGrid (its geometry and boundaries are the model’s).

collision_frequencyattributeinstance attribute#

collision_frequency = grid.cell_field(collision_frequency)

conductor_masksattributeinstance attribute#

conductor_masks = [grid.union_mask(c.shapes) for c in self.conductors]

conductorsattributeinstance attribute#

conductors = tuple(conductors)

electron_densityattributeinstance attribute#

electron_density = grid.cell_field(electron_density)

frequencyattributeinstance attribute#

frequency = float(frequency)

gridattributeinstance attribute#

grid: CellGrid | PatchGrid = grid

viscosityattributeinstance attribute#

viscosity = self._viscosity(electron_temperature, electron_viscosity)

winding_masksattributeinstance attribute#

winding_masks = [grid.mask(w.shape) for w in self.windings]

windingsattributeinstance attribute#

windings = tuple(windings)

plasmaproperty#

plasma: np.ndarray

The plasma cells: a positive electron density.

shapeproperty#

shape: tuple[int, ...]

The shape of a field: cells along each axis, or (n,) leaf cells.

xproperty#

x: np.ndarray

Cell centres of the first axis [m].

yproperty#

y: np.ndarray

Cell centres of the second axis [m].

conductivitymethod#

def conductivity(omega: float) -> np.ndarray

sigma = n_e e^2 / (m_e (nu + i omega)) [S/m] on the cells (cold plasma).

modified_frequencymethodstaticmethod#

def modified_frequency(frequency: float, dt: float) -> float

The frequency whose harmonic solution the trapezoidal steady state equals.

omega' = (2 / dt) tan(omega dt / 2), as a frequency [Hz].

solvemethod#

def solve(coil_current: complex = 1.0, *, frequency: float | None = None) -> InductiveSolution

The time-harmonic field for a coil current amplitude [A].

frequency overrides the model’s (the time-dependent form’s modified frequency is the use of it).

time_steppermethod#

def time_stepper(dt: float) -> InductiveTimeStepper

The time-dependent form with steps of dt [s] (cold plasma only).

InductiveSolutionclassdataclass#

class InductiveSolution(grid: CellGrid | PatchGrid, frequency: float, coil_current: complex, vector_potential: np.ndarray, plasma_current_density: np.ndarray, source_current_density: np.ndarray, electron_density: np.ndarray, collision_frequency: np.ndarray, electron_velocity: np.ndarray | None = None, viscous_power: float = 0.0, conductor_currents: dict[str, complex] = dict())

The time-harmonic field of :meth:InductiveField2D.solve, as complex amplitudes.

The instant value of an amplitude X is Re(X exp(i omega t)). Extensive quantities are totals in r–z and per unit length along z in a cut.

coil_currentattributeinstance attribute#

coil_current: complex

collision_frequencyattributeinstance attribute#

collision_frequency: np.ndarray

conductor_currentsattributeclass attributeinstance attribute#

conductor_currents: dict[str, complex] = field(default_factory=dict)

electron_densityattributeinstance attribute#

electron_density: np.ndarray

electron_velocityattributeclass attributeinstance attribute#

electron_velocity: np.ndarray | None = None

frequencyattributeinstance attribute#

frequency: float

gridattributeinstance attribute#

grid: CellGrid | PatchGrid

plasma_current_densityattributeinstance attribute#

plasma_current_density: np.ndarray

source_current_densityattributeinstance attribute#

source_current_density: np.ndarray

vector_potentialattributeinstance attribute#

vector_potential: np.ndarray

viscous_powerattributeclass attributeinstance attribute#

viscous_power: float = 0.0

absorbed_powerproperty#

absorbed_power: float

The power the plasma absorbs [W] (per unit length in a cut [W/m]).

cell_areasproperty#

cell_areas: np.ndarray

The cross-section areas of the cells [m^2].

cell_volumesproperty#

cell_volumes: np.ndarray

The cell volumes [m^3] (per metre along z in a cut).

electric_fieldproperty#

electric_field: np.ndarray

E = -i omega a [V/m], normal to the plane.

friction_powerproperty#

friction_power: float

The part of :attr:absorbed_power the friction with the gas dissipates.

magnetic_fieldproperty#

magnetic_field: tuple[np.ndarray, np.ndarray]

The in-plane field [T]: (B_x, B_y) in a cut, (B_r, B_z) in r–z.

omegaproperty#

omega: float

The angular frequency [1/s].

power_densityproperty#

power_density: np.ndarray

The time-averaged absorbed power density 1/2 Re(J E*) [W/m^3].

source_powerproperty#

source_power: complex

The complex power the windings deliver [W] (per unit length in a cut).

-1/2 sum E J_coil* dV; its real part equals :attr:absorbed_power, its imaginary part is the reactive power, positive for the inductive load.

xproperty#

x: np.ndarray

Cell centres of the first axis (x or r) [m]; per cell on patches.

yproperty#

y: np.ndarray

Cell centres of the second axis (y or z) [m]; per cell on patches.

efficiencymethod#

def efficiency(network_resistance: float, depth: float | None = None) -> float

The RF power transfer efficiency R_p / (R_p + R_net).

for_powermethod#

def for_power(power: float, depth: float | None = None) -> InductiveSolution

The solution whose plasma absorbs power [W] (over depth in a cut).

plasma_resistancemethod#

def plasma_resistance(depth: float | None = None) -> float

The plasma resistance seen by the coil, 2 P / |I|^2 [Ohm].

depth [m] turns the power per unit length of a cut into the device’s; an r–z solution takes none.

scaledmethod#

def scaled(coil_current: complex) -> InductiveSolution

The same solution for another coil current (the problem is linear).

to_datasetmethod#

def to_dataset() -> xr.Dataset

The amplitudes and the power density as a labelled dataset.

Magnetronclassdataclass#

class Magnetron(material: TargetMaterial = TITANIUM, target_area: float = 0.001, region_height: float = 0.02, side_area: float = 0.0001, h_factor: float = 0.5, pressure: float = 1.0, gas_temperature: float = 300.0, refill_time: float = 0.0001, wind_efficiency: float = 0.0, heating_fraction: float = 1.0, seed: float = 1e+19)

The ionization region of a magnetron: geometry, gas and target; see the module docstring.

The defaults are placeholders of the order of a 3 inch magnetron, not a particular device.

Attributes

NameTypeDescription
materialTargetMaterialThe target material.
target_areafloatThe area of the racetrack the ions hit, in m^2.
region_heightfloatThe height of the ionization region above it in m; the volume is target_area * region_height.
side_areafloatThe other boundaries ions leave the region through, in m^2.
h_factorfloatThe edge-to-centre density ratio at the boundaries.
pressurefloatThe argon filling pressure in Pa, at gas_temperature.
gas_temperaturefloatThe gas temperature in K.
refill_timefloatThe time in s in which the argon of the region is replaced.
wind_efficiencyfloatAr atoms pushed out per sputtered atom (0: no sputter wind).
heating_fractionfloatThe share of the secondary electron energy the plasma electrons keep: at most 1 if the secondary electron yield is right; a larger value, as :meth:calibrate_heating may find, means the yield of the placeholder material is too low (only the product matters).
seedfloatA pair source in m^-3 s^-1 that stands for the residual plasma and preionization at the start of a pulse; it keeps the density from decaying to zero in the afterglow.

gas_temperatureattributeclass attributeinstance attribute#

gas_temperature: float = 300.0

h_factorattributeclass attributeinstance attribute#

h_factor: float = 0.5

heating_fractionattributeclass attributeinstance attribute#

heating_fraction: float = 1.0

materialattributeclass attributeinstance attribute#

material: TargetMaterial = TITANIUM

pressureattributeclass attributeinstance attribute#

pressure: float = 1.0

refill_timeattributeclass attributeinstance attribute#

refill_time: float = 0.0001

region_heightattributeclass attributeinstance attribute#

region_height: float = 0.02

seedattributeclass attributeinstance attribute#

seed: float = 1e+19

side_areaattributeclass attributeinstance attribute#

side_area: float = 0.0001

target_areaattributeclass attributeinstance attribute#

target_area: float = 0.001

wind_efficiencyattributeclass attributeinstance attribute#

wind_efficiency: float = 0.0

chamberproperty#

chamber: Chamber

The region as a chamber: ions leave through the target and the sides.

gas_densityproperty#

gas_density: float

The argon filling density in m^-3.

speciesproperty#

species: dict[str, Species]

The species by role: e, gas, gas_ion, metal, metal_ion.

volumeproperty#

volume: float

The volume of the ionization region in m^3.

bohm_flux_coefficientmethod#

def bohm_flux_coefficient(te: float, ion: str) -> float

The loss rate of the ion named ion to the target per unit density, in 1/s.

h u_B(T_e) A_t / V.

calibrate_heatingmethod#

def calibrate_heating(current: float, voltage: float) -> Magnetron

A copy whose heating fraction makes the dc discharge current match current.

The share of the secondary electron energy that heats the plasma is the least known closure. The model’s own ion current to the target, I_D of :meth:target_currents, rises with it; this fits it to one measured point so that the others are predictions. A value above 1 means the secondary electron yield is too low; it raises a ValueError if no value up to 10 does, which says that the sputter yields or the geometry are off.

current_scanmethod#

def current_scan(currents: Sequence[float], voltage: float | Callable[[float], float]) -> xr.Dataset

The dc states against the discharge current, with the spoke diagnostics.

voltage is a number or a function of the current V_D(I_D), e.g. the measured characteristic. Every state starts from the last (a continuation); the dataset has the densities (species), the :meth:diagnostics and the model’s I_D over current.

diagnosticsmethod#

def diagnostics(state: GlobalState) -> dict[str, float]

The quantities that decide the spoke regime, for a state.

  • rarefaction: n_Ar in the region over the filling density (1: none; the sputter wind and the ionization of the gas lower it);
  • metal_to_argon: the neutral metal over the neutral argon density;
  • metal_ion_fraction: the metal share of the ion flux to the target;
  • self_sputtering_share: the share of the sputtered flux that the metal ions make (1: the discharge runs on the metal alone);
  • electron_density in m^-3, and the electron temperature in eV;
  • discharge_current: the model’s I_D in A, to compare with the prescribed one.

guessmethod#

def guess(ion_density: float = 1e+17) -> dict[str, float]

A starting state: the filling gas and a plasma of ion_density.

heating_powermethod#

def heating_power(current: float, voltage: float) -> float

The power the plasma electrons absorb at a discharge current and voltage, in W.

P = f gamma / (1 + gamma) I_D V_D, with gamma the secondary electron yield of the argon ions.

metal_ionizationmethod#

def metal_ionization(state: GlobalState) -> float

The ionized fraction of the metal in the region, n_M+ / (n_M + n_M+).

modelmethod#

def model(current: float | Callable[[float], float], voltage: float | Callable[[float], float]) -> GlobalModel

The global model driven by the discharge current I_D(t) and voltage V_D(t).

Each is a number (dc) or a function of the time in s, e.g. from :func:pulse.

pulsemethod#

def pulse(current: float, voltage: float, on_time: float, period: float, *, periods: int = 20, points: int = 200, tolerance: float = 0.001, initial: Mapping[str, float] | GlobalState | None = None) -> xr.Dataset

The periodic state of a rectangular pulse, as a dataset over the time t in a period.

The discharge current and voltage are current and voltage for on_time seconds of every period, and zero in between. Periods are run until the densities at the start of a period change by less than tolerance (relative, in the log) from one period to the next, or periods are done; attrs["periodicity_error"] is the last change and attrs["periods"] how many were run. The variables are the densities, the electron temperature, the model’s currents at the target (I_D, I_<ion>), the sputtered flux and the metal ion fraction.

reactionsmethod#

def reactions() -> list[Reaction]

The ionization, excitation, elastic and charge-exchange reactions.

scanmethod#

def scan(parameter: str, values: list, current: float, voltage: float) -> list[GlobalState]

Dc states for values of a field of the magnetron, each started from the last.

sourcesmethod#

def sources() -> list[VolumeSource]

Sputtering and the sputter wind by the ion flux to the target, and the seed.

steady_statemethod#

def steady_state(current: float, voltage: float, initial: Mapping[str, float] | GlobalState | None = None) -> GlobalState

The dc state at a discharge current and voltage.

target_currentsmethod#

def target_currents(state: GlobalState) -> dict[str, float]

The currents and fluxes at the target for a state.

Returns the ion currents I_<ion> to the target in A, the discharge current I_D including the secondary electrons, the sputtered atom flux sputtered in 1/s, the metal_ion_fraction of the ion flux to the target and the metal_ion_density_fraction of the ion density.

PlasmaRegionclassdataclass#

class PlasmaRegion(shapes: Sequence[Any], excluded: Sequence[Any] = ())

The cells of a plasma: the union of shapes minus the union of excluded.

Attributes

NameTypeDescription
shapesSequence[Any]Shapes whose union is the region (e.g. the driver and the expansion region as two rectangles, a T in r–z).
excludedSequence[Any]Shapes cut out of it (e.g. an internal structure).

excludedattributeclass attributeinstance attribute#

excluded: Sequence[Any] = ()

shapesattributeinstance attribute#

shapes: Sequence[Any]

maskmethod#

def mask(grid: CellGrid | PatchGrid) -> np.ndarray

The cells whose centre is in the region, shape grid.shape.

wall_facesmethod#

def wall_faces(grid: CellGrid | PatchGrid) -> np.ndarray

The region’s cells that have a neighbour outside it (or the domain edge).

The cells next to a wall, where a fluid model applies its wall conditions; the axis of an r–z domain and periodic seams are not walls.

PotentialBoundaryclassdataclass#

class PotentialBoundary(kind: str, value: float = 0.0)

The potential at one end: a value (V) or the field E (V/m) there.

kindattributeinstance attribute#

kind: str

valueattributeclass attributeinstance attribute#

value: float = 0.0

fieldmethodclassmethod#

def field(value: float = 0.0) -> PotentialBoundary

A prescribed field, zero for a symmetry plane.

potentialmethodclassmethod#

def potential(value: float) -> PotentialBoundary

A prescribed potential.

RFDriverclassdataclass#

class RFDriver(species: Sequence[Species], reactions: Sequence[Reaction], fixed: Mapping[str, float], radius: float, length: float, coil_turns: float, coil_radius: float, frequency: float, network_resistance: float, momentum_transfer: Sequence[str], ion_mean_free_path: float, skin_density_factor: float = 1.0, coil_length: float | None = None, field_factor: float | None = None, coupling: Literal['transformer', 'solenoid'] = 'transformer', model_options: Mapping[str, Any] = dict())

A cylindrical RF driver: its plasma’s global model and its coil.

The chamber is the driver’s cylinder; the ions leave through its whole wall, the end open to the expansion region included, with the low-pressure edge-to-centre ratios h_L = 0.86 / sqrt(3 + l / (2 lambda_i)) (ends) and h_R = 0.8 / sqrt(4 + R / lambda_i) (side) of Lieberman and Lichtenberg (sec. 10.2) for the ion mean free path lambda_i.

Attributes

NameTypeDescription
speciesSequence[Species]Every species, the electrons ("e") included.
reactionsSequence[Reaction]The volume reactions.
fixedMapping[str, float]Densities held fixed (m^-3), the gases.
radiusfloatThe plasma radius R in m.
lengthfloatThe driver’s length in m.
coil_turnsfloatThe coil’s turns N.
coil_radiusfloatThe coil’s radius b in m.
coil_lengthfloat | NoneThe coil’s length l in m; the driver’s if None.
frequencyfloatThe RF frequency in Hz.
network_resistancefloatR_net in Ohm.
momentum_transferSequence[str]Names of the reactions whose rates per electron make up nu_m (the elastic electron collisions).
ion_mean_free_pathfloatlambda_i in m.
skin_density_factorfloatThe electron density of the skin layer over the volume average.
field_factorfloat | NoneThe coil’s inductance over the long-solenoid one; Nagaoka’s coefficient if None.
couplingLiteral['transformer', 'solenoid']"transformer" (:func:transformer_impedance) or "solenoid", the exact uniform column (:func:solenoid_impedance).
model_optionsMapping[str, Any]Further fields of the :class:GlobalModel (gas temperature, wall reactions, ion wall products, …).

coil_lengthattributeclass attributeinstance attribute#

coil_length: float | None = None

coil_radiusattributeinstance attribute#

coil_radius: float

coil_turnsattributeinstance attribute#

coil_turns: float

couplingattributeclass attributeinstance attribute#

coupling: Literal['transformer', 'solenoid'] = 'transformer'

field_factorattributeclass attributeinstance attribute#

field_factor: float | None = None

fixedattributeinstance attribute#

fixed: Mapping[str, float]

frequencyattributeinstance attribute#

frequency: float

ion_mean_free_pathattributeinstance attribute#

ion_mean_free_path: float

lengthattributeinstance attribute#

length: float

model_optionsattributeclass attributeinstance attribute#

model_options: Mapping[str, Any] = field(default_factory=dict)

momentum_transferattributeinstance attribute#

momentum_transfer: Sequence[str]

network_resistanceattributeinstance attribute#

network_resistance: float

radiusattributeinstance attribute#

radius: float

reactionsattributeinstance attribute#

reactions: Sequence[Reaction]

skin_density_factorattributeclass attributeinstance attribute#

skin_density_factor: float = 1.0

speciesattributeinstance attribute#

species: Sequence[Species]

chamberproperty#

chamber: Chamber

The driver’s cylinder with its effective edge-to-centre ratio.

coilproperty#

coil: Coil

The coil.

couplemethod#

def couple(plasma: GlobalState, power: float) -> DriverState

The coil’s view of a plasma absorbing power W.

modelmethod#

def model(power: float) -> GlobalModel

The global model of the driver plasma absorbing power W.

scanmethod#

def scan(parameter: str, values: Sequence[Any], *, power: float | None = None, guess: GlobalState | Mapping[str, float] | None = None) -> list[DriverState]

Driver states for every value of "power" or a field of the driver.

Each global model starts from the last state (a continuation); a scan of a field needs the absorbed power.

solvemethod#

def solve(power: float, guess: GlobalState | Mapping[str, float] | None = None) -> DriverState

The driver absorbing power W; guess starts the global model.

Reactionclassdataclass#

class Reaction(reactants: Sequence[str], products: Sequence[str], rate: float | RateTable | RateFunction, temperature: str = 'electron', electron_energy_loss: float = 0.0, gas_heating: float = 0.0, elastic_mass: float | None = None, name: str = '')

One reaction of the model.

Attributes

NameTypeDescription
reactantsSequence[str]Species names, repeated for a species that appears twice.
productsSequence[str]Species names, repeated likewise.
ratefloat | RateTable | RateFunctionK in m^3/s (for two reactants): a number, a :class:plasmacoll.RateTable, or a function of the temperature in eV.
temperaturestr"electron" or "gas", the temperature K depends on.
electron_energy_lossfloatEnergy in eV the electrons lose per reaction (negative for a gain, e.g. superelastic or detachment energy).
gas_heatingfloatEnergy in eV the gas gains per reaction (Franck-Condon fragments, charge exchange).
elastic_massfloat | NoneFor an elastic electron collision, the target mass in kg: the electrons then lose 3 (m_e / M) (T_e - T_g) per collision.
namestrA name for diagnostics; built from the equation if empty.

elastic_massattributeclass attributeinstance attribute#

elastic_mass: float | None = None

electron_energy_lossattributeclass attributeinstance attribute#

electron_energy_loss: float = 0.0

gas_heatingattributeclass attributeinstance attribute#

gas_heating: float = 0.0

nameattributeclass attributeinstance attribute#

name: str = ''

productsattributeinstance attribute#

products: Sequence[str]

rateattributeinstance attribute#

rate: float | RateTable | RateFunction

reactantsattributeinstance attribute#

reactants: Sequence[str]

temperatureattributeclass attributeinstance attribute#

temperature: str = 'electron'

stoichiometryproperty#

stoichiometry: dict[str, int]

Net change of every species per reaction (products minus reactants).

coefficientmethod#

def coefficient(electron_temperature: float, gas_temperature: float) -> float

Return K at the temperatures (eV).

coefficientsmethod#

def coefficients(electron_temperature: np.ndarray | float, gas_temperature: np.ndarray | float) -> np.ndarray

Return K at arrays of temperatures (eV), e.g. on the cells of a mesh.

electron_lossmethod#

def electron_loss(electron_temperature: float, gas_temperature: float) -> float

Energy in eV the electrons lose per reaction.

from_cross_sectionmethodclassmethod#

def from_cross_section(reactants: Sequence[str], products: Sequence[str], cross_section: CrossSection, reduced_mass: float, *, incident_mass: float | None = None, temperature: str = 'electron', electron_energy_loss: float = 0.0, gas_heating: float = 0.0, elastic_mass: float | None = None, name: str = '') -> Reaction

A reaction whose rate is cross_section averaged over a Maxwellian.

reduced_mass (kg) is the electron mass for electron impact; incident_mass is needed for a table in the lab frame (see :func:plasmacoll.rate_coefficient).

from_processmethodclassmethod#

def from_process(process: CollisionProcess, reactants: Sequence[str], products: Sequence[str], *, incident_mass: float = ELECTRON_MASS, target_mass: float | None = None, temperature: str = 'electron', gas_heating: float = 0.0) -> Reaction

A reaction from a plasmacoll process: its cross section, frame and energy loss.

The reactants and products are given here, since a process only names the species it tracks. target_mass (kg) gives the reduced mass and, for an elastic process, the energy transfer; without it the target is taken as infinitely heavy.

gas_gainmethod#

def gas_gain(electron_temperature: float, gas_temperature: float) -> float

Energy in eV the gas gains per reaction.

Speciesclassdataclass#

class Species(name: str, mass: float, charge: int = 0)

A species of the plasma or the gas.

Attributes

NameTypeDescription
namestrA unique name, used by the reactions ("e" for electrons).
massfloatThe mass in kg.
chargeintThe charge in elementary charges.

chargeattributeclass attributeinstance attribute#

charge: int = 0

massattributeinstance attribute#

mass: float

nameattributeinstance attribute#

name: str

is_electronproperty#

is_electron: bool

Whether this is the electron species.

is_neutralproperty#

is_neutral: bool

Whether the species has no charge.

atomicmethodclassmethod#

def atomic(name: str, mass_u: float, charge: int = 0) -> Species

A species of mass mass_u in atomic mass units, minus the electrons of its charge.

SpokeReportclassdataclass#

class SpokeReport(mode: int, wavelength: float, growth_rate: float, phase_velocity: float, exb_velocity: float, relative_direction: int, speed_ratio: float, cathode_modulation: float, potential_hump: float, azimuthal_field: float, window: tuple[float, float])

What a run says about its azimuthal structure, in the terms of the experiments.

Attributes

NameTypeDescription
modeintThe dominant azimuthal mode number m >= 1 (largest time-averaged amplitude).
wavelengthfloatlength_y / m (m).
growth_ratefloatGrowth rate (1/s) of that mode over the window.
phase_velocityfloatPhase velocity (m/s) along +y.
exb_velocityfloatThe azimuthal E x B velocity (m/s) at the probe, averaged over the window and y.
relative_directionint+1 if the mode moves along E x B, -1 against it.
speed_ratiofloat|phase_velocity| / |exb_velocity|.
cathode_modulationfloatPeak-to-peak density modulation next to the cathode, (max - min) / (2 mean) along y, averaged over the window.
potential_humpfloatmax_y(phi) - mean_y(phi) at the probe (V), window average.
azimuthal_fieldfloatmax_y |E_y| at the probe (V/m), window average.
windowtuple[float, float]The (t0, t1) (s) of the analysis.

azimuthal_fieldattributeinstance attribute#

azimuthal_field: float

cathode_modulationattributeinstance attribute#

cathode_modulation: float

exb_velocityattributeinstance attribute#

exb_velocity: float

growth_rateattributeinstance attribute#

growth_rate: float

modeattributeinstance attribute#

mode: int

phase_velocityattributeinstance attribute#

phase_velocity: float

potential_humpattributeinstance attribute#

potential_hump: float

relative_directionattributeinstance attribute#

relative_direction: int

speed_ratioattributeinstance attribute#

speed_ratio: float

wavelengthattributeinstance attribute#

wavelength: float

windowattributeinstance attribute#

window: tuple[float, float]

TargetMaterialclassdataclass#

class TargetMaterial(name: str, mass_u: float, ionization_energy: float, outer_electrons: int, argon_yield: float, self_yield: float, argon_secondary: float, self_secondary: float, charge_exchange: float, verified: bool = False)

The sputtered metal and the response of the target to the ions.

Attributes

NameTypeDescription
namestrThe element, e.g. "Ti"; the species are name and name+.
mass_ufloatThe atomic mass in u.
ionization_energyfloatThe first ionization energy in eV.
outer_electronsintThe electrons of the outer shell in the Lotz formula.
argon_yieldfloatAtoms sputtered per Ar+ at the cathode-fall energy.
self_yieldfloatAtoms sputtered per metal ion (self-sputtering).
argon_secondaryfloatSecondary electrons emitted per Ar+.
self_secondaryfloatSecondary electrons emitted per metal ion.
charge_exchangefloatRate of Ar+ + M -> Ar + M+ in m^3/s.
verifiedboolFalse while the yields and rates are placeholders.

argon_secondaryattributeinstance attribute#

argon_secondary: float

argon_yieldattributeinstance attribute#

argon_yield: float

charge_exchangeattributeinstance attribute#

charge_exchange: float

ionization_energyattributeinstance attribute#

ionization_energy: float

mass_uattributeinstance attribute#

mass_u: float

nameattributeinstance attribute#

name: str

outer_electronsattributeinstance attribute#

outer_electrons: int

self_secondaryattributeinstance attribute#

self_secondary: float

self_yieldattributeinstance attribute#

self_yield: float

verifiedattributeclass attributeinstance attribute#

verified: bool = False

VolumeSourceclassdataclass#

class VolumeSource(changes: Mapping[str, int], rate: float | np.ndarray | Callable[[float, float], float], per: Sequence[str] = (), electron_energy: float = 0.0, name: str = 'source')

An external volume source, e.g. ionization or stripping by a fast beam.

Its rate is rate * prod n_per (m^-3 s^-1): rate alone, or per unit density of the species per (for a beam of density n_b and speed v_b ionizing a gas with the cross section sigma, rate = n_b sigma v_b and per = ("gas",)). Each event changes the densities by changes and gives the electrons electron_energy (eV). rate may be a function of the electron and gas temperatures in eV, rate(T_e, T_g), for a source that follows the plasma, e.g. sputtering by the ion flux to a target (per = ("Ar+",), rate the Bohm flux times the yield per volume). In a :class:~wellbalanced.Fluid1D it may also be an array on the cells, a source that varies in space.

changesattributeinstance attribute#

changes: Mapping[str, int]

electron_energyattributeclass attributeinstance attribute#

electron_energy: float = 0.0

nameattributeclass attributeinstance attribute#

name: str = 'source'

perattributeclass attributeinstance attribute#

per: Sequence[str] = ()

rateattributeinstance attribute#

rate: float | np.ndarray | Callable[[float, float], float]

coefficientmethod#

def coefficient(electron_temperature: float, gas_temperature: float) -> float

Return rate at the temperatures (eV).

WallReactionclassdataclass#

class WallReaction(species: str, probability: float, products: Mapping[str, float] = dict())

A neutral species lost at the walls, with a probability per impact.

It returns products ({name: number}), e.g. WallReaction("H", 0.1, {"H2": 0.5}) for atoms recombining to molecules.

probabilityattributeinstance attribute#

probability: float

productsattributeclass attributeinstance attribute#

products: Mapping[str, float] = field(default_factory=dict)

speciesattributeinstance attribute#

species: str

Windingclassdataclass#

class Winding(shape: Any, sign: float = 1.0, name: str = '')

One coil winding: a region carrying sign times the coil current.

Attributes

NameTypeDescription
shapeAnyA 2D shape with contains_points (e.g. a :class:simgeometry.Circle of the tube’s radius).
signfloatThe direction of the current: +1 or -1 (the two sides of a driver in a cut carry opposite signs), or a turn count.
namestrA label for the diagnostics.

nameattributeclass attributeinstance attribute#

name: str = ''

shapeattributeinstance attribute#

shape: Any

signattributeclass attributeinstance attribute#

sign: float = 1.0

spoke_reportfunction#

def spoke_report(run: Run, window: tuple[float, float] | None = None) -> SpokeReport

The :class:SpokeReport of a run over a time window (the last half by default).

stackfunction#

def stack(results: Sequence[_HasDataset], dim: str, values: Sequence[Any] | np.ndarray, *, long_name: str | None = None, units: str = '', attrs: Mapping[str, Any] | None = None) -> xr.Dataset

The datasets of a scan joined along the scanned parameter.

Parameters

NameTypeDefaultDescription
resultsSequence[_HasDataset]requiredThe results, e.g. of :meth:GlobalModel.scan.
dimstrrequiredThe name of the new dimension, e.g. "power".
valuesSequence[Any] | np.ndarrayrequiredThe parameter’s value of every result.
long_namestr | NoneNoneIts label; dim if None.
unitsstr''Its units.
attrsMapping[str, Any] | NoneNoneFurther attributes of the dataset.