Particle
dexter.InitialConditions(time0: float, theta0: float, psip0: float, rho0: float, zeta0: float, mu: float)
A set of initial conditions.
The initial conditions are defined on the \((t, \theta, \psi_p, \rho, \zeta, \mu)\) space.
Example
Creating an InitialConditions set:
Parameters:
-
time0(float) –The initial time.
-
theta0(float) –The initial \(\theta\) angle.
-
psip0(float) –The initial poloidal magnetic flux \(\psi_p\).
-
rho0(float) –The initial parallel gyro radius \(\rho\).
-
zeta0(float) –The initial \(\zeta\) angle.
-
mu(float) –The magnetic moment \(\mu\).
dexter.MappingParameters(section: PoincareSection, alpha: float, intersections: int)
Defines all the necessary parameters of a Mapping.
Example
Creating an MappingParameters:
Parameters:
-
section(PoincareSection) –The surface of section \(\Sigma\), defined by an equation \(x_i = \alpha\), where \(x_i = \theta\) or \(\zeta\).
-
alpha(float) –The constant that defines the surface of section (modulo \(2π\)).
-
intersections(int) –The number of interections to calculate.
dexter.Particle(initial_conditions: InitialConditions)
A Particle.
By taking \(\mu = 0\) and \(\rho \rightarrow 0\), the particle traces magnetic field lines.
Attributes:
-
initial_conditions(InitialConditions) –The initial conditions set.
-
evolution(Evolution) –The evolution time series of the particle's integration.
-
status(str) –The particle's integration status.
-
frequencies(Frequencies) –The particle's calculated frequencies.
-
initial_energy(float) –The particle's initial energy, calculated from its initial state, in Normalized Units.
-
final_energy(float) –The particle's final energy, calculated from its final state, in Normalized Units.
Parameters:
-
initial_conditions(InitialConditions) –The initial conditions set.
Example
Creating a Particle from an InitialConditions set:
Methods:
-
integrate–Integrates the particle, storing its evolution.
-
map–Integrates the particle, storing its intersections with the Poincare
-
calculate_frequencies–Calculates \(\omega_\theta\), \(\omega_\zeta\) and \(q_{kinetic}\).
dexter.Particle.integrate(qfactor: Qfactor, bfield: Bfield, currents: Currents, perturbation: Perturbation, t_eval: tuple[float, float]) -> None
Integrates the particle, storing its evolution.
Parameters:
-
qfactor(Qfactor) –The equilibrium's qfactor.
-
currents(Currents) –The equilibrium's plasma current.
-
bfield(Bfield) –The equilibrium's magnetic field.
-
perturbation(Perturbation) –The equilibrium's perturbation.
-
t_eval(tuple[float, float]) –The time span \((t_0, t_f)\) in which to integrate the particle, in Normalized Units.
dexter.Particle.map(qfactor: Qfactor, currents: Currents, bfield: Bfield, perturbation: Perturbation, params: MappingParameters) -> None
Integrates the particle, storing its intersections with the Poincare
surface defined by params.
Parameters:
-
qfactor(Qfactor) –The equilibrium's qfactor.
-
currents(Currents) –The equilibrium's plasma current.
-
bfield(Bfield) –The equilibrium's magnetic field.
-
perturbation(Perturbation) –The equilibrium's perturbation.
-
params(MappingParameters) –The parameters of the Poincare mapping.
dexter.Particle.calculate_frequencies(qfactor: Qfactor, currents: Currents, bfield: Bfield, perturbation: Perturbation) -> None
Calculates \(\omega_\theta\), \(\omega_\zeta\) and \(q_{kinetic}\).
Note
\(\omega_\theta\) is calculated by integrating for a single period with respect to the \(\theta-\psi_p\) variables.
The orbit frequency \(\omega_\zeta\) corresponds to the bounce/transit averaged rate of toroidal precession \(\Delta\zeta / T_\omega\).
Finally, \(q_{kinetic} = \omega_\zeta / \omega_\theta\).
Tip
Avoid using values like \(\pi, 0\) for \(\theta\). The solver looks for intersections with the initial \(\theta-\psi_p\) values, but \(\pi\) and \(0\) tend to be local minima/maxima, and therefore no intersections can be detected. Use 'random' intermediate values instead.
Parameters:
-
qfactor(Qfactor) –The equilibrium's qfactor.
-
currents(Currents) –The equilibrium's plasma current.
-
bfield(Bfield) –The equilibrium's magnetic field.
-
perturbation(Perturbation) –The equilibrium's perturbation.
Example
>>> initial = dx.InitialConditions(
... time0=0,
... theta0=1,
... psip0=0.8*qfactor.psip_wall,
... rho0=1e-5,
... zeta0=0,
... mu=1e-6,
... )
>>>
>>> particle = dx.Particle(initial)
>>>
>>> particle.calculate_frequencies(
... qfactor=qfactor,
... currents=currents,
... bfield=bfield,
... perturbation=dx.Perturbation([]),
... )
>>> print(particle.frequencies) # doctest: +SKIP
Frequencies {
omega_theta: "0.0000357",
omega_zeta: "0.0000033",
qkinetic: "0.0911628",
}
dexter.Evolution
Stores the time series of the particle's orbit.
Not meant to be constructed. It is stored as a particle's attribute.
Attributes:
-
time(NDArray1D) –The time evolution
-
theta(NDArray1D) –The \(\theta\) time series.
-
psip(NDArray1D) –The \(\psi_p\) time series.
-
rho(NDArray1D) –The \(\rho_{||}\) time series.
-
zeta(NDArray1D) –The \(\zeta\) time series.
-
psi(NDArray1D) –The \(\psi\) time series.
-
ptheta(NDArray1D) –The \(P_\theta\) time series.
-
pzeta(NDArray1D) –The \(P_\zeta\) time series.
-
energy(NDArray1D) –The energy time series.
-
energy_std(float) –The relative standard deviation (\(\sigma/\mu\)) of the energy time series.
-
steps_taken(int) –The total number of steps taken to complete the integration.
-
steps_stored(int) –The number of points stored. This can different from the
steps_takenattribute, for example whenmappinga particle, in which case only the intersections are stored.
Example
dexter.Frequencies
Stores the Particle's calculated \(\omega_\theta\), \(\omega_\zeta\) and \(q_{kinetic}\).
The values are calculated from Particle.calculate_frequencies since they
must be calculated in a specific order. Otherwise they are absent.