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"]).
Classes
| Name | Description |
|---|---|
Boundary | The condition of one species at one end. |
CellGrid | Cells of a tensor-product grid with any edges, in a cut or in r–z. |
Chamber | The volume and walls of the plasma. |
Coil | The RF coil: turns windings of radius (m) over length (m). |
Conductor | A perfect conductor (E = 0 inside): one or several connected shapes. |
Cusp | Multicusp magnetic confinement: cusp lines with a field at the wall. |
DriftFluid2D | The magnetron plane of the module docstring. |
DriftFluid2DState | The fields on the (nx, ny) cells. |
DriverCoupling | A field model and a power-dependent plasma model, solved together. |
DriverState | A driver at one absorbed power: its plasma and the coil's view of it. |
Fluid1D | A plasma between x = 0 and length on cells cells; see the module docstring. |
FluidSpecies | A species carried by the fluid model. |
FluidState | The fields on the cells and the fluxes on the faces. |
GasDynamics | Two-species compressible gas in 1D or 2D; see the module docstring. |
GasState | The gas on the grid: the primitive variables at one time. |
GasTemperature | The gas temperature as a balance: heating by the reactions against conduction. |
GlobalModel | The balances of a plasma in a chamber; see the module docstring. |
GlobalState | A solution of the global model, with every term of its balances. |
InductiveField2D | The magnetoquasistatic field of coil windings, conductors and a plasma. |
InductiveSolution | The time-harmonic field of :meth:InductiveField2D.solve, as complex amplitudes. |
Magnetron | The ionization region of a magnetron: geometry, gas and target; see the module docstring. |
PlasmaRegion | The cells of a plasma: the union of shapes minus the union of excluded. |
PotentialBoundary | The potential at one end: a value (V) or the field E (V/m) there. |
RFDriver | A cylindrical RF driver: its plasma's global model and its coil. |
Reaction | One reaction of the model. |
Species | A species of the plasma or the gas. |
SpokeReport | What a run says about its azimuthal structure, in the terms of the experiments. |
TargetMaterial | The sputtered metal and the response of the target to the ions. |
VolumeSource | An external volume source, e.g. ionization or stripping by a fast beam. |
WallReaction | A neutral species lost at the walls, with a probability per impact. |
Winding | One coil winding: a region carrying sign times the coil current. |
Functions
| Name | Description |
|---|---|
spoke_report | The :class:SpokeReport of a run over a time window (the last half by default). |
stack | The 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#
wellbalanced.speciesView sourceELECTRON = Species('e', ELECTRON_MASS, -1)MATERIALSattributemodule attribute#
wellbalanced.magnetronView sourceMATERIALS: 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#
wellbalanced.fluid1dView sourceclass 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: strreflectionattributeclass attributeinstance attribute#
reflection: float = 0.0temperatureattributeclass attributeinstance attribute#
temperature: float | None = Nonevalueattributeclass attributeinstance attribute#
value: float = 0.0densitymethodclassmethod#
def density(value: float, temperature: float | None = None) -> BoundaryA prescribed density at the boundary (and, for electrons, temperature).
fluxmethodclassmethod#
def flux(value: float, temperature: float | None = None) -> BoundaryA prescribed flux into the domain (and, for electrons, their temperature).
symmetrymethodclassmethod#
def symmetry() -> BoundaryNo flux.
wallmethodclassmethod#
def wall(reflection: float = 0.0) -> BoundaryAn absorbing wall: outflow (1 - r)/(1 + r) (max(v_drift, 0) + v_th / 2) n.
CellGridclass#
wellbalanced.spatial.gridView sourceclass 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
| Name | Type | Default | Description |
|---|---|---|---|
x_edges | Sequence[float] | np.ndarray | required | Cell edges of the first axis (x, or r from >= 0) [m]. |
y_edges | Sequence[float] | np.ndarray | required | Cell edges of the second axis (y, or z) [m]. |
geometry | Geometry | 'cartesian' | "cartesian" or "cylindrical". |
boundaries | tuple[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.circumferencecircumferenceattributeinstance 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 = geometryshapeattributeinstance 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: boolWhether 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: boolWhether the r–z domain reaches the axis (its first radial edge is 0).
cell_fieldmethod#
def cell_field(value: CellField, dtype: Any = float) -> np.ndarrayA :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_matrixThe 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.ndarrayThe 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) -> AnyThe current through a region’s cross-section from V J on its cells.
union_maskmethod#
def union_mask(shapes: Sequence[Any]) -> np.ndarrayThe cells any of shapes contains.
wall_cellsmethod#
def wall_cells(inside: np.ndarray) -> np.ndarrayThe 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#
wellbalanced.global_modelView sourceclass 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
| Name | Type | Description |
|---|---|---|
volume | float | The volume in m^3. |
wall_area | float | The total wall area in m^2, seen by the neutrals. |
ion_loss_area | float | None | The area in m^2 through which ions leave unconfined;
the whole wall if None. |
h_factor | float | The edge-to-centre density ratio at that area. |
cusp | Cusp | None | Magnetic cusps through which ions leave as well. |
cuspattributeclass attributeinstance attribute#
cusp: Cusp | None = Noneh_factorattributeclass attributeinstance attribute#
h_factor: float = 1.0ion_loss_areaattributeclass attributeinstance attribute#
ion_loss_area: float | None = Nonevolumeattributeinstance attribute#
volume: floatwall_areaattributeinstance attribute#
wall_area: floatCoilclassdataclass#
wellbalanced.driverView sourceclass 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 = Nonelengthattributeinstance attribute#
length: floatradiusattributeinstance attribute#
radius: floatturnsattributeinstance attribute#
turns: floatConductorclassdataclass#
wellbalanced.spatial.inductiveView sourceclass Conductor(shapes: Sequence[Any], floating: bool = False, name: str = '')A perfect conductor (E = 0 inside): one or several connected shapes.
Attributes
| Name | Type | Description |
|---|---|---|
shapes | Sequence[Any] | The shapes it is made of (anything with contains_points). |
floating | bool | False (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. |
name | str | A label for :attr:InductiveSolution.conductor_currents. |
Cuspclassdataclass#
wellbalanced.global_modelView sourceclass 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).
DriftFluid2Dclassdataclass#
wellbalanced.driftfluid2dView sourceclass 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
| Name | Type | Description |
|---|---|---|
length_x | float | The cathode-anode gap (m). |
length_y | float | The azimuthal period (m). |
nx | int | Cells along x. |
ny | int | Cells along y (at least 4). |
voltage | float | The discharge voltage (V): the cathode is at -voltage, the anode at 0. |
magnetic_field | Callable[[Any], Any] | float | B_z(x) in T: a callable of the cell positions, or a number. |
gas_density | float | The neutral density at rest N_0 (m^-3). |
electron_temperature | float | None | T_e held fixed (eV), or None for the energy equation. |
momentum_rate | float | 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_rate | float | Ion-neutral momentum-transfer rate coefficient (m^3/s). PLACEHOLDER. |
ion_mass_u | float | The ion mass in atomic mass units (argon). |
ion_temperature | float | T_i in eV (also the gas temperature). |
ionization_rate | Callable[[Any], Any] | Rate coefficient (m^3/s) as a function of T_e (eV). |
excitation_rate | Callable[[Any], Any] | None | Excitation 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_emission | float | Electrons emitted per ion hitting the cathode. PLACEHOLDER. |
cathode_current_density | float | None | If 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_ev | float | Temperature of the emitted electrons (eV). |
refill_rate | float | Relaxation 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. |
depletion | float | Fraction of the ionization events that remove a neutral (1: full depletion, 0: a frozen gas). |
field_bc | float | None | None 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_scale | float | Factor on the Joule heating of the electron energy (a diagnostic switch). |
floor_added | dict | Running 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_flux | bool | Adds 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. |
diamagnetic | float | Factor 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_x | bool | Periodic 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. |
bohm | float | alpha of the anomalous frequency alpha omega_ce / 16 (0 off). |
external_sources | dict[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 = Falsebohmattributeclass attributeinstance attribute#
bohm: float = 0.0cathode_current_densityattributeclass attributeinstance attribute#
cathode_current_density: float | None = Nonedepletionattributeclass attributeinstance attribute#
depletion: float = 1.0diamagneticattributeclass attributeinstance attribute#
diamagnetic: float = 1.0electron_temperatureattributeclass attributeinstance attribute#
electron_temperature: float | None = 5.0excitation_energy_evattributeclass attributeinstance attribute#
excitation_energy_ev: float = 11.56excitation_rateattributeclass attributeinstance attribute#
excitation_rate: Callable[[Any], Any] | None = argon_excitation_rateexternal_sourcesattributeclass attributeinstance attribute#
external_sources: dict[str, np.ndarray] = field(default_factory=dict)field_bcattributeclass attributeinstance attribute#
field_bc: float | None = Nonefloor_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+20heating_scaleattributeclass attributeinstance attribute#
heating_scale: float = 1.0ion_friction_rateattributeclass attributeinstance attribute#
ion_friction_rate: float = 1e-15ion_mass_uattributeclass attributeinstance attribute#
ion_mass_u: float = 39.948ion_temperatureattributeclass attributeinstance attribute#
ion_temperature: float = 0.025ionization_energy_evattributeclass attributeinstance attribute#
ionization_energy_ev: float = 15.76ionization_rateattributeclass attributeinstance attribute#
ionization_rate: Callable[[Any], Any] = argon_ionization_ratelength_xattributeinstance attribute#
length_x: floatlength_yattributeinstance attribute#
length_y: floatmagnetic_fieldattributeclass attributeinstance attribute#
magnetic_field: Callable[[Any], Any] | float = 0.0momentum_rateattributeclass attributeinstance attribute#
momentum_rate: float | Callable[[Any], Any] = argon_momentum_ratenxattributeinstance attribute#
nx: intnyattributeinstance attribute#
ny: intperiodic_xattributeclass attributeinstance attribute#
periodic_x: bool = Falserefill_rateattributeclass attributeinstance attribute#
refill_rate: float = 10000.0secondary_emissionattributeclass attributeinstance attribute#
secondary_emission: float = 0.06secondary_energy_evattributeclass attributeinstance attribute#
secondary_energy_ev: float = 1.0voltageattributeclass attributeinstance attribute#
voltage: float = 260.0charge_residualmethod#
def charge_residual(state: DriftFluid2DState) -> floatLargest |eps0 div E - rho| / (e n): how far the state is from Poisson’s equation.
electric_fieldmethod#
def electric_field(state: DriftFluid2DState) -> np.ndarrayThe 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.ndarrayThe 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) -> DriftFluid2DStateA 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) -> LinearModesLinear 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) -> RunAdvance state by t_end seconds and record the electron density along y.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
state | DriftFluid2DState | required | The initial state. |
t_end | float | required | The duration (s). |
dt | float | None | None | A fixed step (s); by default the step is re-chosen from cfl
every 20 steps. |
cfl | float | 0.4 | The Courant number of the chosen step. |
record_every | float | None | None | The recording interval (s); t_end / 200 by default. |
probe_x | float | None | None | Where along x to record (m); mid-gap by default. |
callback | Callable[[DriftFluid2DState], None] | None | None | Called 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) -> DriftFluid2DStateAdvance 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) -> floatA 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#
wellbalanced.driftfluid2dView sourceclass 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
| Name | Type | Description |
|---|---|---|
x | np.ndarray | Cell centres along x (m). |
y | np.ndarray | Cell centres along y (m). |
electron_density | np.ndarray | n_e (m^-3). |
ion_density | np.ndarray | n_i (m^-3). |
ion_velocity | np.ndarray | (v_x, v_y) of the ions, shape (2, nx, ny) (m/s). |
gas_density | np.ndarray | The neutral density N (m^-3). |
electron_temperature | np.ndarray | T_e (eV). |
potential | np.ndarray | phi (V). |
time | float | Time (s). |
electron_densityattributeinstance attribute#
electron_density: np.ndarrayelectron_temperatureattributeinstance attribute#
electron_temperature: np.ndarraygas_densityattributeinstance attribute#
gas_density: np.ndarrayion_densityattributeinstance attribute#
ion_density: np.ndarrayion_velocityattributeinstance attribute#
ion_velocity: np.ndarraypotentialattributeinstance attribute#
potential: np.ndarraytimeattributeclass attributeinstance attribute#
time: float = 0.0xattributeinstance attribute#
x: np.ndarrayyattributeinstance attribute#
y: np.ndarraycopymethod#
def copy() -> DriftFluid2DStateA deep copy.
to_datasetmethod#
def to_dataset() -> xr.DatasetThe state as a labelled dataset on (x, y).
DriverCouplingclassdataclass#
wellbalanced.spatial.couplingView sourceclass 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
depthattributeclass attributeinstance attribute#
depth: float | None = Nonefieldattributeinstance attribute#
field: Callable[[PlasmaProfile], InductiveField2D]network_resistanceattributeinstance attribute#
network_resistance: floatplasmaattributeinstance attribute#
plasma: Callable[[float], tuple[PlasmaProfile, Any]]at_absorbed_powermethod#
def at_absorbed_power(power: float) -> CoupledStateThe 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) -> CoupledStateThe 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#
wellbalanced.driverView sourceclass 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
| Name | Type | Description |
|---|---|---|
plasma | GlobalState | The steady state of the driver’s global model. |
power | float | The power the plasma absorbs in W. |
frequency | float | The RF frequency in Hz. |
collision_frequency | float | The electrons’ momentum-transfer frequency nu_m (1/s). |
coil_impedance | complex | Z_s in Ohm; its real part is R_s. |
network_resistance | float | R_net in Ohm. |
skin_depth | float | 1 / Re k in m. |
coil_impedanceattributeinstance attribute#
coil_impedance: complexcollision_frequencyattributeinstance attribute#
collision_frequency: floatfrequencyattributeinstance attribute#
frequency: floatnetwork_resistanceattributeinstance attribute#
network_resistance: floatplasmaattributeinstance attribute#
plasma: GlobalStatepowerattributeinstance attribute#
power: floatskin_depthattributeinstance attribute#
skin_depth: floatcoil_currentproperty#
coil_current: floatThe coil current amplitude sqrt(2 P / R_s) in A.
coil_voltageproperty#
coil_voltage: floatThe voltage amplitude across the coil, |Z_s| I, in V.
efficiencyproperty#
efficiency: floatThe RF power transfer efficiency R_s / (R_s + R_net).
plasma_resistanceproperty#
plasma_resistance: floatR_s = Re Z_s in Ohm.
rf_powerproperty#
rf_power: floatThe power the generator delivers, P / eta, in W.
to_datasetmethod#
def to_dataset() -> xr.DatasetThe plasma’s dataset with the coupling’s quantities.
Fluid1Dclassdataclass#
wellbalanced.fluid1dView sourceclass 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
| Name | Type | Description |
|---|---|---|
species | Sequence[FluidSpecies] | The fluid species, the electrons ("e") included. |
reactions | Sequence[Reaction] | The volume reactions; reactants that are not fluid species
must be in fixed. |
length | float | The domain length (m). |
cells | int | The number of cells. |
fixed | Mapping[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_temperature | float | T_g in eV. |
electron_temperature | float | None | None solves the electron energy equation;
a number holds T_e fixed (isothermal electrons). |
boundaries | dict[str, dict[str, Boundary]] | {"left": {species: Boundary}, "right": {...}}; a
species missing at an end has a wall there. |
potential | dict[str, PotentialBoundary] | {"left": PotentialBoundary, "right": ...}; grounded if missing. |
heating | float | np.ndarray | Power to the electrons (W/m^3), a number or an array on the cells. |
sources | Mapping[str, float | np.ndarray] | External volume sources {species: rate} (m^-3 s^-1), numbers
or arrays on the cells. |
volume_sources | Sequence[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: intelectron_temperatureattributeclass attributeinstance attribute#
electron_temperature: float | None = Nonefixedattributeclass attributeinstance attribute#
fixed: Mapping[str, float | np.ndarray] = field(default_factory=dict)gas_temperatureattributeclass attributeinstance attribute#
gas_temperature: float = 0.025heatingattributeclass attributeinstance attribute#
heating: float | np.ndarray = 0.0lengthattributeinstance attribute#
length: floatpotentialattributeclass 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.ndarrayStep 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) -> BoundaryThe 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.ndarrayThe 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) -> NoneChange 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) -> FluidStateThe :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) -> FluidStateReturn 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#
wellbalanced.fluid1dView sourceclass FluidSpecies(species: Species, mobility: float = 0.0, diffusion: float | None = None, momentum: bool = False)A species carried by the fluid model.
Attributes
| Name | Type | Description |
|---|---|---|
species | Species | Name, mass and charge. |
mobility | float | mu in m^2/(V s) (charged species). |
diffusion | float | None | D in m^2/s; for a charged species None takes the
Einstein relation D = mu T (T_e for electrons, T_g for ions). |
momentum | bool | Solve 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 = Nonemobilityattributeclass attributeinstance attribute#
mobility: float = 0.0momentumattributeclass attributeinstance attribute#
momentum: bool = Falsespeciesattributeinstance attribute#
species: SpeciesFluidStateclassdataclass#
wellbalanced.fluid1dView sourceclass 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
| Name | Type | Description |
|---|---|---|
x | np.ndarray | Cell centres (m). |
faces | np.ndarray | Face positions (m). |
densities | dict[str, np.ndarray] | Density of every fluid species on the cells (m^-3). |
electron_temperature | np.ndarray | T_e on the cells (eV). |
potential | np.ndarray | phi on the cells (V). |
fluxes | dict[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_rates | dict[str, np.ndarray] | Volume rate of every reaction on the cells (m^-3 s^-1). |
time | float | Time (s) of the state; inf for a steady state. |
converged | bool | Whether the last solve converged. |
convergedattributeclass attributeinstance attribute#
converged: bool = Truedensitiesattributeinstance attribute#
densities: dict[str, np.ndarray]electron_temperatureattributeinstance attribute#
electron_temperature: np.ndarrayfacesattributeinstance attribute#
faces: np.ndarrayfluxesattributeinstance attribute#
fluxes: dict[str, np.ndarray]potentialattributeinstance attribute#
potential: np.ndarrayreaction_ratesattributeinstance attribute#
reaction_rates: dict[str, np.ndarray]timeattributeclass attributeinstance attribute#
time: float = 0.0xattributeinstance attribute#
x: np.ndarrayintegralmethod#
def integral(values: np.ndarray) -> floatThe integral of a cell field over the domain.
to_datasetmethod#
def to_dataset() -> xr.DatasetThe 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.ndarrayThe 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#
wellbalanced.gasdynamicsView sourceclass 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
| Name | Type | Default | Description |
|---|---|---|---|
length | float | required | Length of the domain along x in m (the target at x = 0). |
cells | int | required | Number of cells along x. |
width | float | 1.0 | Width in y in m (the depth of a 1D model: totals are per m^2 for 1). |
cells_y | int | 1 | Number of cells along y (1: one-dimensional). |
gas_mass | float | ARGON_MASS | The mass of an atom of the gas in kg (argon). |
metal_mass | float | 47.867 * ATOMIC_MASS | The mass of a metal atom in kg (titanium by default). |
gamma | float | 5.0 / 3.0 | The adiabatic index (5/3: monatomic). |
diffusion | float | Callable[[np.ndarray, np.ndarray], np.ndarray] | None | None | The 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_conductivity | float | Callable[[np.ndarray], np.ndarray] | 0.0 | kappa in W/(m K) (number or function of T); 0: none. |
boundaries | Mapping[str, Boundary] | None | None | The conditions at "left" and "right" (default: a wall at the
left, an outflow at the right). |
limiter | str | 'vanleer' | "minmod", "vanleer" (default), "mc" or "none"
(central slopes: second order on smooth flow, not monotone). |
cfl | float | 0.4 | The Courant number of the hyperbolic step. |
source_cfl | float | 0.2 | The 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 = cfldiffusionattributeinstance attribute#
diffusion = diffusionexchangeattributeinstance attribute#
exchange: list[IonExchange] = []gammaattributeinstance attribute#
gamma = gammalimiterattributeinstance attribute#
limiter = limitermassesattributeinstance 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_cflsourcesattributeinstance attribute#
sources: list[VolumeSource] = []stepsattributeinstance attribute#
steps = 0thermal_conductivityattributeinstance attribute#
thermal_conductivity = thermal_conductivitytimeattributeinstance attribute#
time = 0.0xattributeinstance attribute#
x = np.arange(cells) + 0.5 * self.dxyattributeinstance attribute#
y = np.arange(cells_y) + 0.5 * self.dyrunmethod#
def run(t_end: float, *, callback: Callable[[GasDynamics], None] | None = None, every: int = 1) -> GasStateStep until time == t_end (the last step is shortened); returns the state.
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) -> NoneSet 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) -> NoneA gas at rest of one pressure, temperature and metal mass fraction.
stable_stepmethod#
def stable_step() -> floatThe acoustic CFL time step of the current state.
statemethod#
def state() -> GasStateThe current gas as a :class:GasState.
steady_statemethod#
def steady_state(tolerance: float = 1e-08, max_time: float = 1.0, check_every: int = 200) -> GasStateStep 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_timeis reached first.
stepmethod#
def step(dt: float | None = None) -> floatAdvance one step (the stable step by default); returns the step taken.
temperaturemethod#
def temperature(prim: np.ndarray | None = None) -> np.ndarrayThe temperature field in K.
totalsmethod#
def totals() -> dict[str, float]The integrals of the conserved quantities over the domain (per unit depth).
GasStateclassdataclass#
wellbalanced.gasdynamicsView sourceclass 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
| Name | Type | Description |
|---|---|---|
time | float | The time in s. |
x | np.ndarray | Cell centres along the axis, m. |
y | np.ndarray | Cell centres across, m. |
gas_density | np.ndarray | Argon mass density, kg/m^3, shape (nx, ny). |
metal_density | np.ndarray | Metal mass density, kg/m^3. |
u | np.ndarray | Axial velocity, m/s. |
v | np.ndarray | Azimuthal velocity, m/s. |
pressure | np.ndarray | Pressure, Pa. |
temperature | np.ndarray | Temperature, K. |
gas_number | np.ndarray | Argon number density, m^-3. |
metal_number | np.ndarray | Metal number density, m^-3. |
gas_densityattributeinstance attribute#
gas_density: np.ndarraygas_numberattributeinstance attribute#
gas_number: np.ndarraymetal_densityattributeinstance attribute#
metal_density: np.ndarraymetal_numberattributeinstance attribute#
metal_number: np.ndarraypressureattributeinstance attribute#
pressure: np.ndarraytemperatureattributeinstance attribute#
temperature: np.ndarraytimeattributeinstance attribute#
time: floatuattributeinstance attribute#
u: np.ndarrayvattributeinstance attribute#
v: np.ndarrayxattributeinstance attribute#
x: np.ndarrayyattributeinstance attribute#
y: np.ndarrayto_datasetmethod#
def to_dataset() -> xr.DatasetThe state as a labelled dataset: x (and y when the grid has more than one cell).
GasTemperatureclassdataclass#
wellbalanced.global_modelView sourceclass 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.
GlobalModelclassdataclass#
wellbalanced.global_modelView sourceclass 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
| Name | Type | Description |
|---|---|---|
species | Sequence[Species] | Every species, the electrons (named "e") included. |
reactions | Sequence[Reaction] | The volume reactions. |
chamber | Chamber | Volume, walls and confinement. |
power | float | 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). |
fixed | Mapping[str, float] | Densities held fixed (m^-3), e.g. a gas at a given pressure. |
feed | Mapping[str, float] | Particles per second fed into the chamber, by species. |
pumping_speed | float | Volume per second (m^3/s) pumped out, of every neutral species that is not held fixed. |
sources | Sequence[VolumeSource] | External volume sources. |
wall_reactions | Sequence[WallReaction] | Losses of neutral species at the walls. |
ion_wall_products | Mapping[str, Mapping[str, float]] | What an ion returns to the volume after reaching
the wall, {ion: {product: number}}, e.g. {"H2+": {"H2": 1}}. |
gas_temperature | float | GasTemperature | A fixed gas temperature in eV, or its balance. |
thermalize_electrons | bool | Keep 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: Chamberfeedattributeclass 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.025ion_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.0pumping_speedattributeclass attributeinstance attribute#
pumping_speed: float = 0.0reactionsattributeinstance attribute#
reactions: Sequence[Reaction]sourcesattributeclass attributeinstance attribute#
sources: Sequence[VolumeSource] = ()speciesattributeinstance attribute#
species: Sequence[Species]thermalize_electronsattributeclass attributeinstance attribute#
thermalize_electrons: bool = Falsewall_reactionsattributeclass attributeinstance attribute#
wall_reactions: Sequence[WallReaction] = ()evaluatemethod#
def evaluate(state: np.ndarray, converged: bool = True, t: float = 0.0) -> GlobalStateReturn 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) -> GlobalStateReturn 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#
wellbalanced.global_modelView sourceclass 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
| Name | Type | Description |
|---|---|---|
densities | dict[str, float] | Every species’ density in m^-3, the electrons included. |
electron_temperature | float | T_e in eV. |
gas_temperature | float | T_g in eV. |
reaction_rates | dict[str, float] | Volume rate of every reaction (m^-3 s^-1), by name. |
wall_losses | dict[str, float] | Volume rate at which every species reaches the walls (m^-3 s^-1), the electrons included. |
power | dict[str, float] | Electron power terms in W (positive: gained), by channel; at steady state they sum to zero. |
particle_balance | dict[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). |
converged | bool | Whether the steady state was reached. |
convergedattributeclass attributeinstance attribute#
converged: bool = Truedensitiesattributeinstance attribute#
densities: dict[str, float]electron_temperatureattributeinstance attribute#
electron_temperature: floatgas_temperatureattributeinstance attribute#
gas_temperature: floatparticle_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]electronegativitymethod#
def electronegativity(negative_ions: Iterable[str]) -> floatsum n_- / n_e for the named negative ions.
ionization_degreemethod#
def ionization_degree(gases: Iterable[str]) -> floatn_e / (n_e + sum n_gas) for the named gases.
to_datasetmethod#
def to_dataset() -> xr.DatasetThe state as a labelled dataset (dimensions species, reaction, channel).
InductiveField2Dclass#
wellbalanced.spatial.inductiveView sourceclass 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
| Name | Type | Default | Description |
|---|---|---|---|
x_edges | Sequence[float] | np.ndarray | None | None | Cell edges of the first axis (x, or r from >= 0) [m]: a
tensor grid; or give grid. |
y_edges | Sequence[float] | np.ndarray | None | None | Cell edges of the second axis (y, or z) [m]. |
frequency | float | required | The driving frequency [Hz]. |
windings | Sequence[Winding] | () | The coil windings; each carries sign times the coil current. |
conductors | Sequence[Conductor] | () | The perfect conductors. |
electron_density | CellField | 0.0 | n_e [m^-3] on the cells (set to zero in the windings, the
conductors and outside plasma_region). |
collision_frequency | CellField | 0.0 | The electron momentum-transfer frequency nu [1/s]. |
electron_temperature | CellField | None | None | T_e [eV]: with it, the electrons carry the collisional
viscosity (2/3) n_e e T_e / nu (nu > 0 in the plasma). |
electron_viscosity | CellField | None | None | mu_e [Pa s] directly, instead of from T_e; zero gives
the momentum balance without viscosity (the cold plasma, solved with u). |
plasma_region | PlasmaRegion | None | None | Where the plasma is; everywhere if None. |
boundaries | tuple[AxisBoundary, AxisBoundary] | None | None | The boundary of each axis (see :class:CellGrid); default
("dirichlet", "dirichlet"), or the grid’s. |
geometry | Geometry | None | None | "cartesian" (a cut, A_z) or "cylindrical" (r–z,
A_phi); default "cartesian", or the grid’s. |
electron_drift | Any | None | The in-plane electron velocity for the RF Lorentz force; not
implemented until Fluid2D provides it. |
grid | CellGrid | PatchGrid | None | None | A 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 = gridviscosityattributeinstance 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.ndarrayThe 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.ndarrayCell centres of the first axis [m].
yproperty#
y: np.ndarrayCell centres of the second axis [m].
conductivitymethod#
def conductivity(omega: float) -> np.ndarraysigma = 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) -> floatThe 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) -> InductiveSolutionThe 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) -> InductiveTimeStepperThe time-dependent form with steps of dt [s] (cold plasma only).
InductiveSolutionclassdataclass#
wellbalanced.spatial.inductiveView sourceclass 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: complexcollision_frequencyattributeinstance attribute#
collision_frequency: np.ndarrayconductor_currentsattributeclass attributeinstance attribute#
conductor_currents: dict[str, complex] = field(default_factory=dict)electron_densityattributeinstance attribute#
electron_density: np.ndarrayelectron_velocityattributeclass attributeinstance attribute#
electron_velocity: np.ndarray | None = Nonefrequencyattributeinstance attribute#
frequency: floatgridattributeinstance attribute#
grid: CellGrid | PatchGridplasma_current_densityattributeinstance attribute#
plasma_current_density: np.ndarraysource_current_densityattributeinstance attribute#
source_current_density: np.ndarrayvector_potentialattributeinstance attribute#
vector_potential: np.ndarrayviscous_powerattributeclass attributeinstance attribute#
viscous_power: float = 0.0absorbed_powerproperty#
absorbed_power: floatThe power the plasma absorbs [W] (per unit length in a cut [W/m]).
cell_areasproperty#
cell_areas: np.ndarrayThe cross-section areas of the cells [m^2].
cell_volumesproperty#
cell_volumes: np.ndarrayThe cell volumes [m^3] (per metre along z in a cut).
electric_fieldproperty#
electric_field: np.ndarrayE = -i omega a [V/m], normal to the plane.
friction_powerproperty#
friction_power: floatThe 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: floatThe angular frequency [1/s].
power_densityproperty#
power_density: np.ndarrayThe time-averaged absorbed power density 1/2 Re(J E*) [W/m^3].
source_powerproperty#
source_power: complexThe 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.ndarrayCell centres of the first axis (x or r) [m]; per cell on patches.
yproperty#
y: np.ndarrayCell centres of the second axis (y or z) [m]; per cell on patches.
efficiencymethod#
def efficiency(network_resistance: float, depth: float | None = None) -> floatThe RF power transfer efficiency R_p / (R_p + R_net).
for_powermethod#
def for_power(power: float, depth: float | None = None) -> InductiveSolutionThe solution whose plasma absorbs power [W] (over depth in a cut).
plasma_resistancemethod#
def plasma_resistance(depth: float | None = None) -> floatThe 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) -> InductiveSolutionThe same solution for another coil current (the problem is linear).
to_datasetmethod#
def to_dataset() -> xr.DatasetThe amplitudes and the power density as a labelled dataset.
Magnetronclassdataclass#
wellbalanced.magnetronView sourceclass 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
| Name | Type | Description |
|---|---|---|
material | TargetMaterial | The target material. |
target_area | float | The area of the racetrack the ions hit, in m^2. |
region_height | float | The height of the ionization region above it in m; the
volume is target_area * region_height. |
side_area | float | The other boundaries ions leave the region through, in m^2. |
h_factor | float | The edge-to-centre density ratio at the boundaries. |
pressure | float | The argon filling pressure in Pa, at gas_temperature. |
gas_temperature | float | The gas temperature in K. |
refill_time | float | The time in s in which the argon of the region is replaced. |
wind_efficiency | float | Ar atoms pushed out per sputtered atom (0: no sputter wind). |
heating_fraction | float | The 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). |
seed | float | A 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.0h_factorattributeclass attributeinstance attribute#
h_factor: float = 0.5heating_fractionattributeclass attributeinstance attribute#
heating_fraction: float = 1.0materialattributeclass attributeinstance attribute#
material: TargetMaterial = TITANIUMpressureattributeclass attributeinstance attribute#
pressure: float = 1.0refill_timeattributeclass attributeinstance attribute#
refill_time: float = 0.0001region_heightattributeclass attributeinstance attribute#
region_height: float = 0.02seedattributeclass attributeinstance attribute#
seed: float = 1e+19side_areaattributeclass attributeinstance attribute#
side_area: float = 0.0001target_areaattributeclass attributeinstance attribute#
target_area: float = 0.001wind_efficiencyattributeclass attributeinstance attribute#
wind_efficiency: float = 0.0chamberproperty#
chamber: ChamberThe region as a chamber: ions leave through the target and the sides.
gas_densityproperty#
gas_density: floatThe argon filling density in m^-3.
speciesproperty#
species: dict[str, Species]The species by role: e, gas, gas_ion, metal, metal_ion.
volumeproperty#
volume: floatThe volume of the ionization region in m^3.
bohm_flux_coefficientmethod#
def bohm_flux_coefficient(te: float, ion: str) -> floatThe 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) -> MagnetronA 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.DatasetThe 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_Arin 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_densityin m^-3, and the electron temperature in eV;discharge_current: the model’sI_Din 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) -> floatThe 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) -> floatThe 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]) -> GlobalModelThe 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.DatasetThe 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) -> GlobalStateThe 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#
wellbalanced.spatial.regionsView sourceclass PlasmaRegion(shapes: Sequence[Any], excluded: Sequence[Any] = ())The cells of a plasma: the union of shapes minus the union of excluded.
Attributes
| Name | Type | Description |
|---|---|---|
shapes | Sequence[Any] | Shapes whose union is the region (e.g. the driver and the expansion region as two rectangles, a T in r–z). |
excluded | Sequence[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.ndarrayThe cells whose centre is in the region, shape grid.shape.
wall_facesmethod#
def wall_faces(grid: CellGrid | PatchGrid) -> np.ndarrayThe 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#
wellbalanced.fluid1dView sourceclass 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: strvalueattributeclass attributeinstance attribute#
value: float = 0.0fieldmethodclassmethod#
def field(value: float = 0.0) -> PotentialBoundaryA prescribed field, zero for a symmetry plane.
potentialmethodclassmethod#
def potential(value: float) -> PotentialBoundaryA prescribed potential.
RFDriverclassdataclass#
wellbalanced.driverView sourceclass 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
| Name | Type | Description |
|---|---|---|
species | Sequence[Species] | Every species, the electrons ("e") included. |
reactions | Sequence[Reaction] | The volume reactions. |
fixed | Mapping[str, float] | Densities held fixed (m^-3), the gases. |
radius | float | The plasma radius R in m. |
length | float | The driver’s length in m. |
coil_turns | float | The coil’s turns N. |
coil_radius | float | The coil’s radius b in m. |
coil_length | float | None | The coil’s length l in m; the driver’s if None. |
frequency | float | The RF frequency in Hz. |
network_resistance | float | R_net in Ohm. |
momentum_transfer | Sequence[str] | Names of the reactions whose rates per electron make up
nu_m (the elastic electron collisions). |
ion_mean_free_path | float | lambda_i in m. |
skin_density_factor | float | The electron density of the skin layer over the volume average. |
field_factor | float | None | The coil’s inductance over the long-solenoid one;
Nagaoka’s coefficient if None. |
coupling | Literal['transformer', 'solenoid'] | "transformer" (:func:transformer_impedance) or
"solenoid", the exact uniform column (:func:solenoid_impedance). |
model_options | Mapping[str, Any] | Further fields of the :class:GlobalModel (gas
temperature, wall reactions, ion wall products, …). |
coil_lengthattributeclass attributeinstance attribute#
coil_length: float | None = Nonecoil_radiusattributeinstance attribute#
coil_radius: floatcoil_turnsattributeinstance attribute#
coil_turns: floatcouplingattributeclass attributeinstance attribute#
coupling: Literal['transformer', 'solenoid'] = 'transformer'field_factorattributeclass attributeinstance attribute#
field_factor: float | None = Nonefixedattributeinstance attribute#
fixed: Mapping[str, float]frequencyattributeinstance attribute#
frequency: floation_mean_free_pathattributeinstance attribute#
ion_mean_free_path: floatlengthattributeinstance attribute#
length: floatmodel_optionsattributeclass attributeinstance attribute#
model_options: Mapping[str, Any] = field(default_factory=dict)momentum_transferattributeinstance attribute#
momentum_transfer: Sequence[str]network_resistanceattributeinstance attribute#
network_resistance: floatradiusattributeinstance attribute#
radius: floatreactionsattributeinstance attribute#
reactions: Sequence[Reaction]skin_density_factorattributeclass attributeinstance attribute#
skin_density_factor: float = 1.0speciesattributeinstance attribute#
species: Sequence[Species]chamberproperty#
chamber: ChamberThe driver’s cylinder with its effective edge-to-centre ratio.
coilproperty#
coil: CoilThe coil.
couplemethod#
def couple(plasma: GlobalState, power: float) -> DriverStateThe coil’s view of a plasma absorbing power W.
modelmethod#
def model(power: float) -> GlobalModelThe 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) -> DriverStateThe driver absorbing power W; guess starts the global model.
Reactionclassdataclass#
wellbalanced.reactionsView sourceclass 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
| Name | Type | Description |
|---|---|---|
reactants | Sequence[str] | Species names, repeated for a species that appears twice. |
products | Sequence[str] | Species names, repeated likewise. |
rate | float | RateTable | RateFunction | K in m^3/s (for two reactants): a number, a
:class:plasmacoll.RateTable, or a function of the temperature in eV. |
temperature | str | "electron" or "gas", the temperature K depends on. |
electron_energy_loss | float | Energy in eV the electrons lose per reaction (negative for a gain, e.g. superelastic or detachment energy). |
gas_heating | float | Energy in eV the gas gains per reaction (Franck-Condon fragments, charge exchange). |
elastic_mass | float | None | For an elastic electron collision, the target mass in kg:
the electrons then lose 3 (m_e / M) (T_e - T_g) per collision. |
name | str | A name for diagnostics; built from the equation if empty. |
elastic_massattributeclass attributeinstance attribute#
elastic_mass: float | None = Noneelectron_energy_lossattributeclass attributeinstance attribute#
electron_energy_loss: float = 0.0gas_heatingattributeclass attributeinstance attribute#
gas_heating: float = 0.0nameattributeclass attributeinstance attribute#
name: str = ''productsattributeinstance attribute#
products: Sequence[str]rateattributeinstance attribute#
rate: float | RateTable | RateFunctionreactantsattributeinstance 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) -> floatReturn K at the temperatures (eV).
coefficientsmethod#
def coefficients(electron_temperature: np.ndarray | float, gas_temperature: np.ndarray | float) -> np.ndarrayReturn 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) -> floatEnergy 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 = '') -> ReactionA 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) -> ReactionA 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) -> floatEnergy in eV the gas gains per reaction.
Speciesclassdataclass#
wellbalanced.speciesView sourceclass Species(name: str, mass: float, charge: int = 0)A species of the plasma or the gas.
Attributes
chargeattributeclass attributeinstance attribute#
charge: int = 0massattributeinstance attribute#
mass: floatnameattributeinstance attribute#
name: strSpokeReportclassdataclass#
wellbalanced.driftfluid2dView sourceclass 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
| Name | Type | Description |
|---|---|---|
mode | int | The dominant azimuthal mode number m >= 1 (largest time-averaged amplitude). |
wavelength | float | length_y / m (m). |
growth_rate | float | Growth rate (1/s) of that mode over the window. |
phase_velocity | float | Phase velocity (m/s) along +y. |
exb_velocity | float | The azimuthal E x B velocity (m/s) at the probe, averaged over the
window and y. |
relative_direction | int | +1 if the mode moves along E x B, -1 against it. |
speed_ratio | float | |phase_velocity| / |exb_velocity|. |
cathode_modulation | float | Peak-to-peak density modulation next to the cathode,
(max - min) / (2 mean) along y, averaged over the window. |
potential_hump | float | max_y(phi) - mean_y(phi) at the probe (V), window average. |
azimuthal_field | float | max_y |E_y| at the probe (V/m), window average. |
window | tuple[float, float] | The (t0, t1) (s) of the analysis. |
azimuthal_fieldattributeinstance attribute#
azimuthal_field: floatcathode_modulationattributeinstance attribute#
cathode_modulation: floatexb_velocityattributeinstance attribute#
exb_velocity: floatgrowth_rateattributeinstance attribute#
growth_rate: floatmodeattributeinstance attribute#
mode: intphase_velocityattributeinstance attribute#
phase_velocity: floatpotential_humpattributeinstance attribute#
potential_hump: floatrelative_directionattributeinstance attribute#
relative_direction: intspeed_ratioattributeinstance attribute#
speed_ratio: floatwavelengthattributeinstance attribute#
wavelength: floatwindowattributeinstance attribute#
window: tuple[float, float]TargetMaterialclassdataclass#
wellbalanced.magnetronView sourceclass 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
| Name | Type | Description |
|---|---|---|
name | str | The element, e.g. "Ti"; the species are name and name+. |
mass_u | float | The atomic mass in u. |
ionization_energy | float | The first ionization energy in eV. |
outer_electrons | int | The electrons of the outer shell in the Lotz formula. |
argon_yield | float | Atoms sputtered per Ar+ at the cathode-fall energy. |
self_yield | float | Atoms sputtered per metal ion (self-sputtering). |
argon_secondary | float | Secondary electrons emitted per Ar+. |
self_secondary | float | Secondary electrons emitted per metal ion. |
charge_exchange | float | Rate of Ar+ + M -> Ar + M+ in m^3/s. |
verified | bool | False while the yields and rates are placeholders. |
argon_secondaryattributeinstance attribute#
argon_secondary: floatargon_yieldattributeinstance attribute#
argon_yield: floatcharge_exchangeattributeinstance attribute#
charge_exchange: floationization_energyattributeinstance attribute#
ionization_energy: floatmass_uattributeinstance attribute#
mass_u: floatnameattributeinstance attribute#
name: strouter_electronsattributeinstance attribute#
outer_electrons: intself_secondaryattributeinstance attribute#
self_secondary: floatself_yieldattributeinstance attribute#
self_yield: floatverifiedattributeclass attributeinstance attribute#
verified: bool = FalseVolumeSourceclassdataclass#
wellbalanced.global_modelView sourceclass 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.0nameattributeclass attributeinstance attribute#
name: str = 'source'perattributeclass attributeinstance attribute#
per: Sequence[str] = ()rateattributeinstance attribute#
rate: float | np.ndarray | Callable[[float, float], float]WallReactionclassdataclass#
wellbalanced.global_modelView sourceclass 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.
Windingclassdataclass#
wellbalanced.spatial.inductiveView sourceclass Winding(shape: Any, sign: float = 1.0, name: str = '')One coil winding: a region carrying sign times the coil current.
Attributes
spoke_reportfunction#
wellbalanced.driftfluid2dView sourcedef spoke_report(run: Run, window: tuple[float, float] | None = None) -> SpokeReportThe :class:SpokeReport of a run over a time window (the last half by default).
stackfunction#
wellbalanced.datasetsView sourcedef 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.DatasetThe datasets of a scan joined along the scanned parameter.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
results | Sequence[_HasDataset] | required | The results, e.g. of :meth:GlobalModel.scan. |
dim | str | required | The name of the new dimension, e.g. "power". |
values | Sequence[Any] | np.ndarray | required | The parameter’s value of every result. |
long_name | str | None | None | Its label; dim if None. |
units | str | '' | Its units. |
attrs | Mapping[str, Any] | None | None | Further attributes of the dataset. |