Queue¶
dexter.Queue(initial_conditions: QueueInitialConditions)
¶
A collection of multiple Particles, constructed from a
QueueInitialConditions.
Example
>>> num = 100
>>> psit0s = np.linspace(0, 0.15, num)
>>> initial_conditions = dex.QueueInitialConditions.Boozer(
... t0=np.zeros(num),
... flux0=dex.MagneticFluxArray.Toroidal(psit0s),
... theta0=np.zeros(num),
... zeta0=np.zeros(num),
... rho0=np.full(num, 1e-5),
... mu0=np.full(num, 1e-6),
... )
>>>
>>> # Queue setup and integration
>>> queue = dex.Queue(initial_conditions)
Attributes:
-
initial_conditions(QueueInitialConditions) –The Queue's initial conditions
-
routines(list[Routine]) –The routines Queue has run
-
energy_array(Array1) –A 1D array with the particle's energies.
-
energy_var_array–A 1D array with the particle's energy variances.
-
omega_theta_array(Array1) –A 1D array with the particle's $\omega_\theta$.
-
omega_zeta_array(Array1) –A 1D array with the particle's $\omega_\zeta$.
-
qkinetic_array(Array1) –A 1D array with the particle's $q_{kin}$.
Note
In arrays containing particle quantities, the particles are visited in order of instantiation.
FromParticles(particles: Collection[Particle]) -> Queue
classmethod
¶
Creates a Queue from a collection of Particles, copying all their attributes.
The particles do not have to be initialized, but they must be defined on the same coordinate set (boozer/mixed).
integrate(machine: Machine, teval: tuple[float, float], solver_params: SolverParams | None = None)
¶
Integrates the particles for a specific time interval.
The time interval is in Normalized Units (inverse gyro-frequency).
Parameters:
-
machine(Machine) –The machine in which to integrate the particles.
-
teval(tuple[float, float]) –The time span $(t_0, t_f)$ in which to integrate the particles, in Normalized Units.
-
solver_params(SolverParams | None, default:None) –The parameters passed to the solver.
Example
>>> # Machine setup
>>> LCFS = dex.MagneticFlux.Toroidal(0.45)
>>> machine = dex.Machine(
... qfactor=dex.ParabolicQfactor(qaxis=1.1, qlast=4.1, lcfs=LCFS),
... current=dex.LarCurrent(),
... bfield=dex.LarBfield(),
... perturbation=dex.Perturbation(
... [
... dex.FluteMode(epsilon=1e-3, lcfs=LCFS, m=1, n=3, phase=0),
... dex.FluteMode(epsilon=1e-3, lcfs=LCFS, m=2, n=3, phase=0),
... ]
... )
... )
>>>
>>> # Initial conditions setup
>>> num = 10
>>> psit0s = dex.MagneticFluxArray.Toroidal(np.linspace(0, machine.psit_last.value, num))
>>> initial_conditions = dex.QueueInitialConditions.Boozer(
... t0=np.zeros(num),
... flux0=psit0s,
... theta0=np.zeros(num),
... zeta0=np.zeros(num),
... rho0=np.full(num, 1e-5),
... mu0=np.full(num, 1e-6),
... )
>>>
>>> # Queue setup and integration
>>> queue = dex.Queue(initial_conditions)
>>>
>>> solver_params = dex.SolverParams(
... method=dex.SteppingMethod.EnergyAdaptiveStep(rel_tol=1e-7, abs_tol=1e-9),
... max_steps=100_000,
... )
>>> queue.integrate(machine, teval=(0, 1e2), solver_params=solver_params)
intersect(machine: Machine, intersect_params: IntersectParams, solver_params: SolverParams | None = None)
¶
Integrates the particles, calculating their intersections with a constant $\theta$ or $\zeta$ surface.
Using the method described by Hénon we can force the solver to step exactly on the intersection surface.
The differences between two consecutive values of the corresponding angle variable are guaranteed to be $2\pi \pm \epsilon$, where $\epsilon$ a number smaller than the solver’s relative tolerance.
Parameters:
-
machine(Machine) –The machine in which to integrate the particles.
-
intersect_params(IntersectParams) –The intersection parameters.
-
solver_params(SolverParams | None, default:None) –The parameters passed to the solver.
Example
>>> # Machine setup
>>> LCFS = dex.MagneticFlux.Toroidal(0.45)
>>> machine = dex.Machine(
... qfactor=dex.ParabolicQfactor(qaxis=1.1, qlast=4.1, lcfs=LCFS),
... current=dex.LarCurrent(),
... bfield=dex.LarBfield(),
... perturbation=dex.Perturbation(
... [
... dex.FluteMode(epsilon=1e-3, lcfs=LCFS, m=1, n=3, phase=0),
... dex.FluteMode(epsilon=1e-3, lcfs=LCFS, m=2, n=3, phase=0),
... ]
... )
... )
>>>
>>> # Initial conditions and Intersection Parameters setup
>>> num = 10
>>> psit0s = dex.MagneticFluxArray.Toroidal(np.linspace(0, machine.psit_last.value, num))
>>> initial_conditions = dex.QueueInitialConditions.Boozer(
... t0=np.zeros(num),
... flux0=psit0s,
... theta0=np.zeros(num),
... zeta0=np.zeros(num),
... rho0=np.full(num, 1e-6),
... mu0=np.full(num, 1e-4),
... )
>>>
>>> # Queue setup and integration
>>> queue = dex.Queue(initial_conditions)
>>>
>>> intersect_params = dex.IntersectParams("ConstZeta", angle=3.1415, turns=5)
>>> queue.intersect(machine, intersect_params)
close(machine: Machine, periods: int = 1, discard_arrays: bool = True, solver_params: SolverParams | None = None)
¶
Integrates the particles for a certain amount of $\theta-\psi$ periods.
Parameters:
-
machine(Machine) –The machine in which to integrate the particles.
-
periods(int, default:1) –The amount of periods to integrate.
-
discard_arrays(bool, default:True) –Whether or not to discard the integration timeseries after the routine is finished. Quantities such as $q_{kin}$ are still calculated.
-
solver_params(SolverParams | None, default:None) –The parameters passed to the solver.
Example
>>> # Machine setup
>>> LCFS = dex.MagneticFlux.Toroidal(0.45)
>>> machine = dex.Machine(
... qfactor=dex.ParabolicQfactor(qaxis=1.1, qlast=4.1, lcfs=LCFS),
... current=dex.LarCurrent(),
... bfield=dex.LarBfield(),
... )
>>>
>>> # Initial conditions and Intersection Parameters setup
>>> num = 10
>>> psit0s = dex.MagneticFluxArray.Toroidal(np.linspace(0, machine.psit_last.value, num))
>>> initial_conditions = dex.QueueInitialConditions.Boozer(
... t0=np.zeros(num),
... flux0=psit0s,
... theta0=np.zeros(num),
... zeta0=np.zeros(num),
... rho0=np.full(num, 1e-5),
... mu0=np.full(num, 1e-6),
... )
>>>
>>> # Queue setup and integration
>>> queue = dex.Queue(initial_conditions)
>>> queue.close(machine)
classify(machine: Machine)
¶
Classifies the particles’ orbit using their position on the $(E, P_\zeta, \mu=const)$ plane without integrating.
Note
This method follows R. B. White's rules for classifying
orbits. it only works for up-down symmetric equilibria with radial electric field.
See the "$E-P_\zeta$ Positions" section on the Diagrams tab for explanation.
Parameters:
-
machine(Machine) –The machine in which to classify the particles.
Example
>>> # Machine setup
>>> LCFS = dex.MagneticFlux.Toroidal(0.45)
>>> machine = dex.Machine(
... qfactor=dex.ParabolicQfactor(qaxis=1.1, qlast=4.1, lcfs=LCFS),
... current=dex.LarCurrent(),
... bfield=dex.LarBfield(),
... )
>>>
>>> # Initial conditions and Intersection Parameters setup
>>> num = 10
>>> psit0s = dex.MagneticFluxArray.Toroidal(np.linspace(0, machine.psit_last.value, num))
>>> initial_conditions = dex.QueueInitialConditions.Boozer(
... t0=np.zeros(num),
... flux0=psit0s,
... theta0=np.zeros(num),
... zeta0=np.zeros(num),
... rho0=np.full(num, 1e-5),
... mu0=np.full(num, 1e-6),
... )
>>>
>>> # Queue setup and integration
>>> queue = dex.Queue(initial_conditions)
>>> queue.classify(machine)
particles() -> list[Particle]
¶
Returns a list with all the contained objects.
Note that calling this method copies all particles.
retain_pzeta(start: float, end: float) -> None
¶
retain_energy(start: float, end: float) -> None
¶
retain_energy_pzeta_positions(positions: Iterable[EnergyPzetaPosition])
¶
Iterates through self’s particles, keeping only the ones with an
EnergyPzetaPosition that matches an element of positions.
Parameters:
-
positions(Iterable[EnergyPzetaPosition]) –The $E-P_\zeta$ positions.
retain_orbit_types(orbit_types: Iterable[OrbitType])
¶
__getitem__(index: int) -> Particle
¶
Returns a copy of the index-th particle.
__len__() -> int
¶
Returns the particle count.
plot_qkinetic_pzeta(machine: Machine, **kwargs: Any)
¶
Wrapper around dexter.plot_qkinetic_pzeta.
Parameters:
-
machine(Machine) –The machine in which the particle was integrated.
-
**kwargs(Any, default:{}) –Extra arguments passed to
dexter.plot_qkinetic_pzeta.
plot_qkinetic_energy(machine: Machine, **kwargs: Any)
¶
Wrapper around dexter.plot_qkinetic_energy.
Parameters:
-
machine(Machine) –The machine in which the particle was integrated.
-
**kwargs(Any, default:{}) –Extra arguments passed to
dexter.plot_qkinetic_energy.
plot_pzeta_poincare(machine: Machine, intersect_params: IntersectParams, **kwargs: Any)
¶
Wrapper around dexter.plot_pzeta_poincare.
Parameters:
-
machine(Machine) –The machine in which the particle was integrated.
-
intersect_params(IntersectParams) –The queue's intersection parameters.
-
**kwargs(Any, default:{}) –Extra arguments passed to
dexter.plot_poloidal_drift.
plot_rz_poincare(machine: Machine, intersect_params: IntersectParams, **kwargs: Any)
¶
Wrapper around dexter.plot_rz_poincare.
Parameters:
-
machine(Machine) –The machine in which the particle was integrated.
-
intersect_params(IntersectParams) –The queue's intersection parameters.
-
**kwargs(Any, default:{}) –Extra arguments passed to
dexter.plot_poloidal_drift.