API Reference

All public symbols are re-exported from the top-level albums package and documented below in their defining submodule.

Submodules

albums.mbtrack2_to_pycolleff

Module with conversion function to go from mbtrack2 to pycolleff.

synchrotron_to_pycolleff(synchrotron, I0, Vrf, bunch_number)[source]

Return a pycolleff Ring element from the synchrotron element data.

Parameters
  • synchrotron (mbtrack2.tracking.synchrotron.Synchrotron) – Parameters description.

  • I0 (float) – Beam current in [A].

  • Vrf (float) – RF voltage in [V].

  • bunch_number (int) – Total number of bunches filled.

Returns

ring – pycolleff Ring object.

Return type

pycolleff.colleff.Ring

cavityresonator_to_pycolleff(cavres, Impedance=True)[source]

Convenience method to export a CavityResonator to pycolleff.

Parameters
  • cavres (mbtrack2.tracking.rf.CavityResonator) – CavityResonator object.

  • Impedance (bool, optional) – If True, export as impedance (i.e. ImpedanceSource.Methods.ImpedanceDFT). If False, export as wake (i.e. ImpedanceSource.Methods.Wake). Default is True.

Returns

cav

Return type

pycolleff ImpedanceSource object

impedance_to_pycolleff(impedance)[source]

Convenience method to export impedance to pycolleff. Only implemented for longitudinal impedance.

Parameters

impedance (mbtrack2.impedance.wakefield.Impedance) – Impedance object.

Returns

imp – pycolleff ImpedanceSource object

Return type

pycolleff.longitudinal_equilibrium.ImpedanceSource

albums.optimiser

Module where the optimization functions are defined.

_require_r_factor(flow) None[source]

Reject flows whose equilibrium does not compute a meaningful R-factor.

_is_unstable(res) bool[source]

True if any instability theory in the Result flags an instability.

_equilibrium_not_converged(res) bool[source]

The equilibrium solve failed.

_theories_not_converged(res) bool[source]

The equilibrium converged but a theory did not converge.

evaluate_R(B: SystemState, flow, eq_opts: EquilibriumOptions, theory_opts: TheoryOptions = TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), is_equilibrium: bool = False) float[source]

Evaluate the R-factor (or the equilibrium-only R-factor) of one operating point as a score to be minimised.

Parameters
  • B (SystemState) – The system to evaluate.

  • flow (Flow) – Flow object used for solving.

  • eq_opts (EquilibriumOptions) – Beam current, integration boundary and solver options.

  • theory_opts (TheoryOptions) – Shared theory inputs (used only when is_equilibrium is False).

  • is_equilibrium (bool) – If True, evaluate the equilibrium only (no instability theories). The score is then only penalised for non-convergence. If False, it is also penalised at any unstable operating point, and at any point where a theory failed to converge.

Returns

Negative R-factor if successful and stable, a penalty (10) otherwise.

Return type

float

maximize_R(ring: Synchrotron, cavity_list: list[CavityResonator], flow, psi0_HC: float, bounds, eq_opts: EquilibriumOptions, theory_opts: TheoryOptions = TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), opti_opts: OptimiserOptions = OptimiserOptions(method_opti='COBYLA', tol_opti=0.01, maxiter_opti=1000, rhobeg_opti=0.1, method='Nelder-Mead', tol=0.05, loop_option=False, add_psi_loop=0.02, max_loop=200, auto_psi_input=False, xi_init_input=0.8, debug=False), is_equilibrium: bool = False) float[source]

Optimise the harmonic-cavity tuning angle to maximise the R-factor.

Parameters
  • ring (Synchrotron) – Ring configuration.

  • cavity_list (list of CavityResonator) – Main cavity in position 0, the harmonic cavity (whose psi is optimised) in position 1.

  • flow (Flow) – Solve flow.

  • psi0_HC (float) – Initial guess for the harmonic-cavity tuning angle in degrees.

  • bounds (tuple) – (lower, upper) bounds for the tuning angle.

  • eq_opts (EquilibriumOptions) – Beam current, integration boundary and solver options.

  • theory_opts (TheoryOptions) – Shared theory inputs (used only when is_equilibrium is False).

  • opti_opts (OptimiserOptions) – scipy and loop settings of the optimisation.

  • is_equilibrium (bool) – If True, optimise the equilibrium-only R-factor (no instability theories).

Returns

Optimal tuning angle in degrees, or 90 on failure.

Return type

float

Raises

IncompatibleFlowError – If the flow’s equilibrium does not provide a meaningful R-factor (Capability.TOUSCHEK_LIFETIME_RATIO), e.g. a Bosch flow.

_get_vals(ring: Synchrotron, cavity_list: list[CavityResonator], flow, psi0_HC: float, bounds, eq_opts: EquilibriumOptions, theory_opts: TheoryOptions = TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), opti_opts: OptimiserOptions = OptimiserOptions(method_opti='COBYLA', tol_opti=0.01, maxiter_opti=1000, rhobeg_opti=0.1, method='Nelder-Mead', tol=0.05, loop_option=False, add_psi_loop=0.02, max_loop=200, auto_psi_input=False, xi_init_input=0.8, debug=False), is_equilibrium: bool = False) tuple[source]

Optimise psi_HC then return (psi, Result) at the chosen operating point.

Drives maximize_R, optionally seeding the initial guess from xi_init_input (auto_psi_input) and, when loop_option is set, stepping psi outward until a stable point is found. is_equilibrium selects equilibrium-only solving and the matching stability check.

albums.options

Typed option objects for the ALBuMS pipeline:

  • EquilibriumOptions : everything that defines a beam-equilibrium solve.

  • TheoryOptions : the run-time inputs shared by the instability theories.

  • OptimiserOptions : the settings of the tuning-angle optimisation.

  • ScanOptions : grid-evaluation settings for scans.

  • PlotOptions : display settings for the 2D scan and optimisation plots.

class EquilibriumOptions(I0: float | None = None, tau_boundary: float | None = None, passive_harmonic_cavity: bool = True, auto_set_MC_theta: bool = True, optimal_tunning: bool = True, max_counter: int = 200, auto_set_for_xi: bool = False, xi: float | None = None, F_init: Any = None, set_MC_phase_HCpassive: bool = False, niter: int = 200, tol: float = 1e-08, beta: float = 0.1, m: int = 3, print_flag: bool = False, filling: Any = None, impedance: Any = None)[source]

Bases: object

Everything that defines a beam-equilibrium solve.

Variables
  • solver) (**Common options** (read by every equilibrium) –

  • I0 (float or None) – Beam current in [A]. None until set; SystemState raises if a solve is attempted while it is still None.

  • tau_boundary (float or None) – Half-window in [s] for the potential and form-factor integrals. If None, 0.1 times the RF period (0.1 * ring.T1) is used.

  • passive_harmonic_cavity (bool) – If True the harmonic cavity is treated as passive (beam-driven); if False as active (generator-driven).

  • auto_set_MC_theta (bool) – If True the main-cavity synchronous phase is set automatically from the energy loss before solving. Not read by the active-Bosch solver, which derives the main-cavity phase from xi instead (see auto_set_for_xi).

  • optimal_tunning (bool) – If True the harmonic-cavity detuning is set to its optimal value for the target bunch lengthening before solving.

  • specific** (**Alves) –

  • max_counter (int) – Maximum number of fixed-point iterations of the Bosch form-factor loop.

  • specific**

  • auto_set_for_xi (bool) – If True the cavity settings are chosen to reach the requested force ratio xi instead of being used as given.

  • xi (float or None) – Target main-to-harmonic force ratio used when auto_set_for_xi is True.

  • specific**

  • F_init (array-like or None) – Initial guess for the per-cavity amplitude form factor. None starts from all ones.

  • set_MC_phase_HCpassive (bool) – If True, correct the main-cavity phase in the passive-harmonic-cavity case when the beam losses exceed the main-cavity voltage.

  • specific**

  • niter (int) – Maximum number of iterations of the self-consistent equilibrium loop.

  • tol (float) – Convergence tolerance on the form factor for the self-consistent loop.

  • beta (float) – Under-relaxation factor between 0 and 1 damping each update step of the loop.

  • m (int) – Number of azimuthal harmonics kept in the form-factor expansion.

  • print_flag (bool) – If True, print convergence diagnostics during the loop.

  • filling (array-like or None) – Filling pattern (per-bucket current weights); None means uniform filling.

  • impedance (object or None) – Additional longitudinal impedance source or sources added to the cavity impedances; None for cavities only.

I0: float | None = None
tau_boundary: float | None = None
passive_harmonic_cavity: bool = True
auto_set_MC_theta: bool = True
optimal_tunning: bool = True
max_counter: int = 200
auto_set_for_xi: bool = False
xi: float | None = None
F_init: Any = None
set_MC_phase_HCpassive: bool = False
niter: int = 200
tol: float = 1e-08
beta: float = 0.1
m: int = 3
print_flag: bool = False
filling: Any = None
impedance: Any = None
__init__(I0: float | None = None, tau_boundary: float | None = None, passive_harmonic_cavity: bool = True, auto_set_MC_theta: bool = True, optimal_tunning: bool = True, max_counter: int = 200, auto_set_for_xi: bool = False, xi: float | None = None, F_init: Any = None, set_MC_phase_HCpassive: bool = False, niter: int = 200, tol: float = 1e-08, beta: float = 0.1, m: int = 3, print_flag: bool = False, filling: Any = None, impedance: Any = None) None
class TheoryOptions(mode_coupling: bool = True, f_HOM: float | numpy.ndarray = 0, Z_HOM: float | numpy.ndarray = 0)[source]

Bases: object

Run-time inputs shared by the instability theories.

Variables
  • specific** (**HOMCoupledBunch) –

  • mode_coupling (bool) – If True the zero-frequency stability test includes mode coupling. Pair False with a flow using the no-coupling Robinson theory.

  • specific**

  • f_HOM (float or array-like) – Higher-order-mode resonant frequency or frequencies in [Hz] for the coupled-bunch theory. 0 disables the HOM.

  • Z_HOM (float or array-like) – Shunt impedance or impedances of the HOM in ohms.

mode_coupling: bool = True
f_HOM: float | numpy.ndarray = 0
Z_HOM: float | numpy.ndarray = 0
__init__(mode_coupling: bool = True, f_HOM: float | numpy.ndarray = 0, Z_HOM: float | numpy.ndarray = 0) None
class OptimiserOptions(method_opti: str = 'COBYLA', tol_opti: float = 0.01, maxiter_opti: int = 1000, rhobeg_opti: float = 0.1, method: str = 'Nelder-Mead', tol: float = 0.05, loop_option: bool = False, add_psi_loop: float = 0.02, max_loop: int = 200, auto_psi_input: bool = False, xi_init_input: float = 0.8, debug: bool = False)[source]

Bases: object

Settings for the harmonic-cavity tuning-angle optimisation.

Variables
  • method_opti (str) – scipy.optimize.minimize method for the R-factor maximisation.

  • tol_opti (float) – Convergence tolerance for the R-factor maximisation.

  • maxiter_opti (int) – Maximum number of iterations for the R-factor maximisation.

  • rhobeg_opti (float) – Initial COBYLA step size (rhobeg) for the R-factor maximisation.

  • method (str) – scipy.optimize.minimize method for the psi minimisation.

  • tol (float) – Convergence tolerance for the psi minimisation.

  • loop_option (bool) – If True, after the optimisation step the tuning angle outward until a stable operating point is found.

  • add_psi_loop (float) – Increment in degrees applied to the tuning angle on each iteration of the stabilisation loop.

  • max_loop (int) – Maximum number of stabilisation-loop iterations before giving up.

  • auto_psi_input (bool) – If True, derive the initial tuning-angle guess from xi_init_input instead of the supplied initial guess.

  • xi_init_input (float) – Target force ratio used to derive the initial tuning-angle guess when auto_psi_input is True.

  • debug (bool) – If True, print optimisation diagnostics.

method_opti: str = 'COBYLA'
tol_opti: float = 0.01
maxiter_opti: int = 1000
rhobeg_opti: float = 0.1
method: str = 'Nelder-Mead'
tol: float = 0.05
loop_option: bool = False
add_psi_loop: float = 0.02
max_loop: int = 200
auto_psi_input: bool = False
xi_init_input: float = 0.8
debug: bool = False
__init__(method_opti: str = 'COBYLA', tol_opti: float = 0.01, maxiter_opti: int = 1000, rhobeg_opti: float = 0.1, method: str = 'Nelder-Mead', tol: float = 0.05, loop_option: bool = False, add_psi_loop: float = 0.02, max_loop: int = 200, auto_psi_input: bool = False, xi_init_input: float = 0.8, debug: bool = False) None
class ScanOptions(skip: bool = False)[source]

Bases: object

Grid-evaluation settings for the parameter and optimisation scans.

These control how the grid is swept, not what is plotted (see PlotOptions).

Variables

skip (bool) – If True, stop scanning a row early once grid points stop converging. Saves time on regions that are uniformly non-physical.

skip: bool = False
__init__(skip: bool = False) None
class PlotOptions(contour: bool = True, title: bool = True, axes: Any = None, colorbar: bool = True, cbar_v: tuple = (None, None), show_legend: bool = True, n_contour: int = 15, marker_size: float = 80, alpha: float = 0.7, manual_clabel: bool = False, colorplot: bool = True, contour_alpha: float = 1, contour_linestyles: str = '-', cmap: str = 'viridis', log_color: bool = False, save: bool = False)[source]

Bases: object

Display settings for the 2D scan and optimisation plots.

Every knob has a documented default in one place.

Variables
  • contour (bool) – If True, overlay contour lines on the colour map.

  • title (bool) – If True, set the axes title to the scan name.

  • axes (matplotlib.axes.Axes or None) – Existing axes to draw on; None creates a new figure and axes.

  • colorbar (bool) – If True, draw the colour bar.

  • cbar_v (tuple of (float or None, float or None)) – The (vmin, vmax) colour-map limits; (None, None) auto-scales.

  • show_legend (bool) – If True, draw the instability-marker legend.

  • n_contour (int) – Number of contour levels.

  • marker_size (float) – Scatter marker size for instability flags.

  • alpha (float) – Scatter marker transparency.

  • manual_clabel (bool) – If True, place contour labels interactively.

  • colorplot (bool) – If True, draw the filled colour map (set False for contour-only plots).

  • contour_alpha (float) – Contour line transparency.

  • contour_linestyles (str) – Contour line style.

  • cmap (str) – Matplotlib colour map name for the background image.

  • log_color (bool) – If True, log-normalise the background colour map via matplotlib LogNorm (cbar_v sets the LogNorm limits). Only strictly positive data is shown; use for quantities spanning orders of magnitude (e.g. growth rates).

  • save (bool) – If True, write the figure to a PNG named from the scan and flow.

contour: bool = True
title: bool = True
axes: Any = None
colorbar: bool = True
cbar_v: tuple = (None, None)
show_legend: bool = True
n_contour: int = 15
marker_size: float = 80
alpha: float = 0.7
manual_clabel: bool = False
colorplot: bool = True
contour_alpha: float = 1
contour_linestyles: str = '-'
cmap: str = 'viridis'
log_color: bool = False
save: bool = False
__init__(contour: bool = True, title: bool = True, axes: Any = None, colorbar: bool = True, cbar_v: tuple = (None, None), show_legend: bool = True, n_contour: int = 15, marker_size: float = 80, alpha: float = 0.7, manual_clabel: bool = False, colorplot: bool = True, contour_alpha: float = 1, contour_linestyles: str = '-', cmap: str = 'viridis', log_color: bool = False, save: bool = False) None

albums.plot_func

Module with the core plotting functions.

configure_plot(ax=None, title=None, xlabel=None, ylabel=None, grid=True, legend=True)[source]

Helper function to configure plot appearance.

save_plot(name, label, plot_2D, tau_boundary=None)[source]

Helper function to save plots with consistent naming.

create_grid(var1, var2, var1_unit, var2_unit)[source]

Helper function to create grids and scaled variables.

plot_image(ax, data, extent, clabel, var1_grid, var2_grid, cmap='viridis', vmin=None, vmax=None, norm=None, colorbar=True, contour=False, colorplot=True, contour_dict={})[source]

Helper function to handle 2D data visualization.

_as_result_array(out)[source]

A ResultArray from either a ResultArray or a raw results_to_arrays dict.

_categories(out)[source]

Flat per-category arrays the plotters consume.

_aggregate_growth(ra)[source]

Most-unstable growth rate at each grid point, reduced over every theory in the result that carries a growth rate.

_theory_growth(ra, spec)[source]

(data, label) for a per-theory growth quantity.

spec is “<theory_name>” or “<theory_name>:<mode>”. Growth is read straight from the theory’s own storage (ra.theories[name]) and masked to the points where that theory (or the selected mode) flags an instability.

_background_data(ra, quantity)[source]

The (data, colour-bar label) for one background quantity.

Equilibrium quantities (“xi”, “bunch_length”, “Touschek”) and the optimiser-only “psi” map read the flow-agnostic categories. Growth quantities are keyed on the theory name: “growth” gives the most-unstable map across all theories, while “growth_<theory_name>” (optionally “growth_<theory_name>:<mode>”) reads one theory’s growth rate, masked where it flags an instability.

_robinson_markers(unstable, coupled)[source]

(mask, marker, label, color) tuples for a Robinson-family theory’s 4 modes.

_instability_markers(ra)[source]

Yield (mask, marker, label, color) for every instability the result holds.

Driven by the theories actually present in ra.theories, so the plot reflects the flow, and multiple theories of the same physical category (for example two PTBL theories) each get their own marker for benchmarking.

_equilibrium_not_converged_mask(ra)[source]

Points where the Stage-1 equilibrium solve itself failed (no theory ran).

_theory_not_converged_mask(ra)[source]

Points where the equilibrium converged but some theory’s own convergence check (root-finder) failed, and no theory flags an instability there (so the point isn’t already decisively explained, e.g. by zero-frequency instability).

plot_scan(out, var1, var2, var1_unit, var2_unit, var1_label, var2_label, quantity, plot_opts=None, name=None, flow='', tau_boundary=None)[source]

Plot one background quantity over the 2D scan grid and overlay every instability the flow produced.

Parameters
  • out (ResultArray or dict) – The scan result.

  • var1 (numpy.ndarray) – Scan axes (outer, inner).

  • var2 (numpy.ndarray) – Scan axes (outer, inner).

  • var1_unit (float) – Display scaling for each axis.

  • var2_unit (float) – Display scaling for each axis.

  • var1_label (str) – Axis labels.

  • var2_label (str) – Axis labels.

  • quantity (str) – Background colour-map quantity (see _background_data for the list).

  • plot_opts (PlotOptions, optional) – Display settings; defaults to PlotOptions().

  • name (optional) – Used for the title and the saved-file name.

  • flow (optional) – Used for the title and the saved-file name.

  • tau_boundary (optional) – Used for the title and the saved-file name.

albums.system

Module introducing the class SystemState bundles the synchrotron and rf parameters and is the entry point for fixed parameterset ALBuMS computations.

class SystemState(ring: Synchrotron, cavity_list: list[CavityResonator])[source]

Bases: object

This class bundles the synchrotron and rf parameters and is the entry point for fixed parameterset ALBuMS computations.

Use run to drive a Flow, composed of:
  • a chosen equilibrium solver (Bosch, Venturini or Alves).

  • paired with a chosen subset of instability theories (see albums.theories).

See albums.flow.DEFAULT_FLOWS for the prebuilt Bosch/Venturini/Alves flows, or build a custom Flow.

Parameters
  • ring (Synchrotron object) – Ring parameters.

  • cavity_list (list of CavityResonator objects) – At least two cavities: the main cavity in position 0, followed by one or more harmonic cavities.

run(flow, eq_opts, theory_opts)[source]

Solve the equilibrium and evaluate a flow’s theories.

run_equilibrium(flow, eq_opts)[source]

Solve only the beam equilibrium.

References

[1] : Bosch, R. A., K. J. Kleman, and J. J. Bisognano. “Robinson instabilities with a higher-harmonic cavity.” Physical Review Special Topics-Accelerators and Beams 4.7 (2001): 074401.

[2] : Bosch, R. A., and C. S. Hsue. “Suppression of longitudinal coupled-bunch instabilities by a passive higher harmonic cavity.” Proceedings of International Conference on Particle Accelerators. IEEE, 1993.

[3] : Gamelin, A., Yamamoto, N. (2021). Equilibrium bunch density distribution with multiple active and passive RF cavities. IPAC’21 (MOPAB069).

[4] : Venturini, M. (2018). Passive higher-harmonic rf cavities with general settings and multibunch instabilities in electron storage rings. Physical Review Accelerators and Beams, 21(11), 114404.

[5] : Alves, Murilo B., and Fernando H. de Sá. “Equilibrium of longitudinal bunch distributions in electron storage rings with arbitrary impedance sources and generic filling patterns.” Physical Review Accelerators and Beams 26.9 (2023): 094402.

[6] : de Sá, F., & Alves, M. (2023). pycolleff and cppcolleff: modules for impedance analysis and wake-field induced instabilities evaluation. (Version 0.1.0) [Computer software]. https://doi.org/10.5281/zenodo.7974571

[7] : He, Tianlong. “Novel perturbation method for judging the stability of the equilibrium solution in the presence of passive harmonic cavities.” Physical Review Accelerators and Beams 25.9 (2022): 094402.

__init__(ring: Synchrotron, cavity_list: list[CavityResonator])[source]
_solve(solver: EquilibriumSolver, eq_opts: EquilibriumOptions) Equilibrium[source]
run_equilibrium(flow: Flow, eq_opts: EquilibriumOptions) Result[source]

Solve only the beam equilibrium of a flow (no instability theories) and return a Result carrying bunch length, R-factor and xi.

Parameters
  • flow (Flow) – The (equilibrium solver, theories) pipeline; only its equilibrium solver is used here.

  • eq_opts (EquilibriumOptions) – The beam current, integration boundary and every solver option.

Returns

Structured result with theories={} (no instability theory evaluated).

Return type

Result

run(flow: Flow, eq_opts: EquilibriumOptions, theory_opts: TheoryOptions = TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0)) Result[source]

Run a Flow: solve the beam equilibrium with the flow’s equilibrium method, then evaluate each of its instability theories, returning a structured Result.

The flow selects the equilibrium solver and the subset of theories.

Parameters
  • flow (Flow) – The (equilibrium solver, theories) pipeline. Use one of albums.DEFAULT_FLOWS or build a custom Flow.

  • eq_opts (EquilibriumOptions) – The beam current, integration boundary and every solver option.

  • theory_opts (TheoryOptions, optional) – The run-time inputs shared by the theories (HOM parameters, mode coupling). Defaults to TheoryOptions().

Returns

Structured result, result.theories[name] holds each TheoryResult.

Return type

Result

albums.equilibrium

Stage 1 of the ALBuMS pipeline: beam-equilibrium solvers.

References

[1] : Bosch, R. A., K. J. Kleman, and J. J. Bisognano. “Robinson instabilities with a higher-harmonic cavity.” Physical Review Special Topics-Accelerators and Beams 4.7 (2001): 074401.

[2] : Bosch, R. A., and C. S. Hsue. “Suppression of longitudinal coupled-bunch instabilities by a passive higher harmonic cavity.” Proceedings of International Conference on Particle Accelerators. IEEE, 1993.

[3] : Gamelin, A., Yamamoto, N. (2021). Equilibrium bunch density distribution with multiple active and passive RF cavities. IPAC’21 (MOPAB069).

[4] : Venturini, M. (2018). Passive higher-harmonic rf cavities with general settings and multibunch instabilities in electron storage rings. Physical Review Accelerators and Beams, 21(11), 114404.

[5] : Alves, Murilo B., and Fernando H. de Sá. “Equilibrium of longitudinal bunch distributions in electron storage rings with arbitrary impedance sources and generic filling patterns.” Physical Review Accelerators and Beams 26.9 (2023): 094402.

class Capability(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: str, Enum

What an equilibrium snapshot makes available to downstream theories.

AMPLITUDE_FORM_FACTOR = 'amplitude_form_factor'
TAYLOR_POTENTIAL = 'taylor_potential'
PHASE_FORM_FACTOR = 'phase_form_factor'
MBTRACK2_BLE = 'mbtrack2_ble'
PYCOLLEFF_LE = 'pycolleff_le'
FULL_DISTRIBUTION = 'full_distribution'
ARBITRARY_FILLING = 'arbitrary_filling'
BROADBAND_IMPEDANCE = 'broadband_impedance'
TOUSCHEK_LIFETIME_RATIO = 'touschek_lifetime_ratio'
static _generate_next_value_(name, start, count, last_values)

Generate the next value when not given.

name: the name of the member start: the initial start value or None count: the number of existing members last_values: the list of values assigned

_new_member_(**kwargs)

Create and return a new object. See help(type) for accurate signature.

_use_args_ = True
_member_names_ = ['AMPLITUDE_FORM_FACTOR', 'TAYLOR_POTENTIAL', 'PHASE_FORM_FACTOR', 'MBTRACK2_BLE', 'PYCOLLEFF_LE', 'FULL_DISTRIBUTION', 'ARBITRARY_FILLING', 'BROADBAND_IMPEDANCE', 'TOUSCHEK_LIFETIME_RATIO']
_member_map_ = {'AMPLITUDE_FORM_FACTOR': Capability.AMPLITUDE_FORM_FACTOR, 'ARBITRARY_FILLING': Capability.ARBITRARY_FILLING, 'BROADBAND_IMPEDANCE': Capability.BROADBAND_IMPEDANCE, 'FULL_DISTRIBUTION': Capability.FULL_DISTRIBUTION, 'MBTRACK2_BLE': Capability.MBTRACK2_BLE, 'PHASE_FORM_FACTOR': Capability.PHASE_FORM_FACTOR, 'PYCOLLEFF_LE': Capability.PYCOLLEFF_LE, 'TAYLOR_POTENTIAL': Capability.TAYLOR_POTENTIAL, 'TOUSCHEK_LIFETIME_RATIO': Capability.TOUSCHEK_LIFETIME_RATIO}
_value2member_map_ = {'amplitude_form_factor': Capability.AMPLITUDE_FORM_FACTOR, 'arbitrary_filling': Capability.ARBITRARY_FILLING, 'broadband_impedance': Capability.BROADBAND_IMPEDANCE, 'full_distribution': Capability.FULL_DISTRIBUTION, 'mbtrack2_ble': Capability.MBTRACK2_BLE, 'phase_form_factor': Capability.PHASE_FORM_FACTOR, 'pycolleff_le': Capability.PYCOLLEFF_LE, 'taylor_potential': Capability.TAYLOR_POTENTIAL, 'touschek_lifetime_ratio': Capability.TOUSCHEK_LIFETIME_RATIO}
_unhashable_values_ = []
_member_type_

alias of str

_value_repr_()

Return repr(self).

class Equilibrium(converged: bool, I0: float | None = None, bunch_length: float | None = None, a: float | None = None, b: float | None = None, c: float | None = None, F: np.ndarray | None = None, PHI: np.ndarray | None = None, backend_BLE: BeamLoadingEquilibrium | None = None, backend_LE: LongitudinalEquilibrium | None = None, cavity_list: list[CavityResonator] | None = None, Touschek: float = nan, xi: float | None = None, capabilities: frozenset[Capability] = <factory>)[source]

Bases: object

Immutable result of a Stage-1 solve, passed to every Stage-2 theory.

Fields are None when the producing solver does not provide them; a theory must never read a field outside the solver’s capabilities (the Flow validation guarantees it never has to).

converged: bool
I0: float | None = None
bunch_length: float | None = None
a: float | None = None
b: float | None = None
c: float | None = None
F: np.ndarray | None = None
PHI: np.ndarray | None = None
backend_BLE: BeamLoadingEquilibrium | None = None
backend_LE: LongitudinalEquilibrium | None = None
cavity_list: list[CavityResonator] | None = None
Touschek: float = nan
xi: float | None = None
capabilities: frozenset[Capability]
has(*caps: Capability) bool[source]
__init__(converged: bool, I0: float | None = None, bunch_length: float | None = None, a: float | None = None, b: float | None = None, c: float | None = None, F: np.ndarray | None = None, PHI: np.ndarray | None = None, backend_BLE: BeamLoadingEquilibrium | None = None, backend_LE: LongitudinalEquilibrium | None = None, cavity_list: list[CavityResonator] | None = None, Touschek: float = nan, xi: float | None = None, capabilities: frozenset[Capability] = <factory>) None
class EquilibriumSolver(*args, **kwargs)[source]

Bases: Protocol

Stage-1 strategy interface.

solve receives the ring, the cavity list (mutated in place) and an EquilibriumOptions bundle (carrying the beam current, the integration boundary and every solver option), and returns an Equilibrium stamped with provides.

name: str
provides: frozenset[albums.equilibrium.Capability]
solve(ring: Synchrotron, cavity_list: list[CavityResonator], opts: EquilibriumOptions) Equilibrium[source]
__init__(*args, **kwargs)
_abc_impl = <_abc._abc_data object>
_is_protocol = True
_is_runtime_protocol = True
resolve_tau_boundary(ring: Synchrotron, tau_boundary: float | None) float[source]

Integration half-window: the given value, or 0.1 times the RF period.

_compute_xi(cavity_list: list[CavityResonator]) float[source]

First-harmonic/main ‘force’ ratio (Bosch near Eq. 7).

Defined for any list of two or more cavities (element 0 is the main cavity); uses the first harmonic cavity. A per-harmonic-cavity xi is left for the full multi-harmonic-cavity physics.

_passive_bosch(ring: Synchrotron, cavity_list: list[CavityResonator], tau_boundary: float, opts: EquilibriumOptions) tuple[source]
_active_bosch(ring: Synchrotron, cavity_list: list[CavityResonator], tau_boundary: float, opts: EquilibriumOptions) tuple[source]
_venturini(ring: Synchrotron, cavity_list: list[CavityResonator], tau_boundary: float, opts: EquilibriumOptions) tuple[source]
_alves(ring: Synchrotron, cavity_list: list[CavityResonator], tau_boundary: float, opts: EquilibriumOptions) tuple[source]
class _SolverRepr[source]

Bases: object

Mixin giving the stateless solver classes a clean ClassName() repr.

class BoschEquilibrium[source]

Bases: _SolverRepr

Original Bosch [1] iteration. Amplitude form factor + bunch length only.

name = 'Bosch'
provides = frozenset({Capability.AMPLITUDE_FORM_FACTOR, Capability.TAYLOR_POTENTIAL})
solve(ring: Synchrotron, cavity_list: list[CavityResonator], opts: EquilibriumOptions) Equilibrium[source]
class VenturiniEquilibrium[source]

Bases: _SolverRepr

Venturini [3,4] via mbtrack2 BeamLoadingEquilibrium. Passive and active HC.

name = 'Venturini'
provides = frozenset({Capability.AMPLITUDE_FORM_FACTOR, Capability.MBTRACK2_BLE, Capability.PHASE_FORM_FACTOR, Capability.TAYLOR_POTENTIAL, Capability.TOUSCHEK_LIFETIME_RATIO})
solve(ring: Synchrotron, cavity_list: list[CavityResonator], opts: EquilibriumOptions) Equilibrium[source]
class AlvesEquilibrium[source]

Bases: _SolverRepr

Alves [5] via pycolleff LongitudinalEquilibrium. Passive HC only.

name = 'Alves'
provides = frozenset({Capability.AMPLITUDE_FORM_FACTOR, Capability.ARBITRARY_FILLING, Capability.BROADBAND_IMPEDANCE, Capability.FULL_DISTRIBUTION, Capability.PHASE_FORM_FACTOR, Capability.PYCOLLEFF_LE, Capability.TAYLOR_POTENTIAL, Capability.TOUSCHEK_LIFETIME_RATIO})
solve(ring: Synchrotron, cavity_list: list[CavityResonator], opts: EquilibriumOptions) Equilibrium[source]

albums.theories

Stage 2 of the ALBuMS pipeline: instability theories.

Each theory takes the SystemState and the Stage-1 Equilibrium, and returns a TheoryResult. The actual physics lives in albums.physics so theories.py does only the orchestration.

class Category(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: str, Enum

Physical category a theory belongs to.

The flow-agnostic accessors (Result / ResultArray) resolve “the Robinson result” / “the PTBL result” by category, so several concrete theories can share one category. Values are independent of each theory’s name.

ZERO_FREQUENCY = 'zero_frequency'
ROBINSON = 'robinson'
HOM = 'hom'
PTBL = 'ptbl'
static _generate_next_value_(name, start, count, last_values)

Generate the next value when not given.

name: the name of the member start: the initial start value or None count: the number of existing members last_values: the list of values assigned

_new_member_(**kwargs)

Create and return a new object. See help(type) for accurate signature.

_use_args_ = True
_member_names_ = ['ZERO_FREQUENCY', 'ROBINSON', 'HOM', 'PTBL']
_member_map_ = {'HOM': Category.HOM, 'PTBL': Category.PTBL, 'ROBINSON': Category.ROBINSON, 'ZERO_FREQUENCY': Category.ZERO_FREQUENCY}
_value2member_map_ = {'hom': Category.HOM, 'ptbl': Category.PTBL, 'robinson': Category.ROBINSON, 'zero_frequency': Category.ZERO_FREQUENCY}
_unhashable_values_ = []
_member_type_

alias of str

_value_repr_()

Return repr(self).

class TheoryResult(name: str, unstable: bool | numpy.ndarray, growth_rate: float | numpy.ndarray = 0.0, mode_frequency: numpy.ndarray | None = None, converged: bool | numpy.ndarray = True, extra: dict = <factory>)[source]

Bases: object

Outcome of one instability theory at one operating point.

name: str
unstable: bool | numpy.ndarray
growth_rate: float | numpy.ndarray = 0.0
mode_frequency: numpy.ndarray | None = None
converged: bool | numpy.ndarray = True
extra: dict
__init__(name: str, unstable: bool | numpy.ndarray, growth_rate: float | numpy.ndarray = 0.0, mode_frequency: numpy.ndarray | None = None, converged: bool | numpy.ndarray = True, extra: dict = <factory>) None
class InstabilityTheory(*args, **kwargs)[source]

Bases: Protocol

Stage-2 strategy interface.

The evaluate methods receives the SystemState, the Stage-1 Equilibrium and a TheoryOptions bundle, and returns a TheoryResult.

name: str
requires: frozenset[albums.equilibrium.Capability]
evaluate(state: SystemState, eq: Equilibrium, opts: TheoryOptions) TheoryResult[source]
__init__(*args, **kwargs)
_abc_impl = <_abc._abc_data object>
_is_protocol = True
_is_runtime_protocol = True
class _TheoryRepr[source]

Bases: object

Mixin giving the theory classes a clean repr from their instance config.

class ZeroFrequency[source]

Bases: _TheoryRepr

Zero-frequency (DC Robinson) instability.

Physics: albums.physics.zero_frequency.zero_frequency_instability.

name = 'zero_frequency'
category = 'zero_frequency'
requires = frozenset({Capability.AMPLITUDE_FORM_FACTOR})
evaluate(state: SystemState, eq: Equilibrium, opts: TheoryOptions) TheoryResult[source]
class RobinsonCoupling[source]

Bases: _TheoryRepr

Robinson dipole/quadrupole modes with mode coupling.

Physics: albums.physics.robinson.robinson_coupling.

name = 'robinson_coupling'
category = 'robinson'
coupled = True
requires = frozenset({Capability.AMPLITUDE_FORM_FACTOR, Capability.TAYLOR_POTENTIAL})
evaluate(state: SystemState, eq: Equilibrium, opts: TheoryOptions) TheoryResult[source]
class RobinsonNoCoupling[source]

Bases: _TheoryRepr

Robinson dipole to octupole modes without mode coupling.

Physics: albums.physics.robinson.robinson_no_coupling.

name = 'robinson_no_coupling'
category = 'robinson'
coupled = False
requires = frozenset({Capability.AMPLITUDE_FORM_FACTOR, Capability.TAYLOR_POTENTIAL})
evaluate(state: SystemState, eq: Equilibrium, opts: TheoryOptions) TheoryResult[source]
class HOMCoupledBunch[source]

Bases: _TheoryRepr

HOM-driven dipole coupled-bunch instability.

Reads the f_HOM / Z_HOM fields of TheoryOptions at evaluation time. Physics: albums.physics.coupled_bunch.dipole_coupled_bunch.

name = 'hom_coupled_bunch'
category = 'hom'
requires = frozenset({Capability.AMPLITUDE_FORM_FACTOR, Capability.TAYLOR_POTENTIAL})
evaluate(state: SystemState, eq: Equilibrium, opts: TheoryOptions) TheoryResult[source]
class BoschMode1[source]

Bases: _TheoryRepr

Bosch coupled-bunch mode l=1 with Landau threshold.

Physics: albums.physics.ptbl.coupled_bunch_mode1.

name = 'bosch_mode1'
category = 'ptbl'
requires = frozenset({Capability.AMPLITUDE_FORM_FACTOR, Capability.TAYLOR_POTENTIAL})
evaluate(state: SystemState, eq: Equilibrium, opts: TheoryOptions) TheoryResult[source]
class PTBLHe[source]

Bases: _TheoryRepr

Periodic transient beam loading (PTBL) instability via He’s perturbation criterion.

Physics: albums.physics.ptbl.ptbl_he.

name = 'ptbl_he'
category = 'ptbl'
requires = frozenset({Capability.AMPLITUDE_FORM_FACTOR, Capability.PHASE_FORM_FACTOR})
evaluate(state: SystemState, eq: Equilibrium, opts: TheoryOptions) TheoryResult[source]
class PTBLAlves(max_azi: int = 10, max_rad: int = 10)[source]

Bases: _TheoryRepr

Periodic transient beam loading (PTBL) instability via Alves mode analysis.

Needs the pycolleff LE + full distribution, so Alves only. Physics: albums.physics.ptbl.ptbl_alves.

name = 'ptbl_alves'
category = 'ptbl'
requires = frozenset({Capability.FULL_DISTRIBUTION, Capability.PYCOLLEFF_LE})
__init__(max_azi: int = 10, max_rad: int = 10)[source]

max_azi, max_rad : truncation of the azimuthal / radial mode expansion.

evaluate(state: SystemState, eq: Equilibrium, opts: TheoryOptions) TheoryResult[source]
class RobinsonGLMCI(max_azi: int = 2, max_rad: int = 0)[source]

Bases: _TheoryRepr

Robinson instabilities via the Gaussian longitudinal mode-coupling instability (GLMCI) method. Alves only.

Physics: albums.physics.robinson.robinson_glmci.

name = 'robinson_glmci'
category = 'robinson'
coupled = True
requires = frozenset({Capability.FULL_DISTRIBUTION, Capability.PYCOLLEFF_LE})
__init__(max_azi: int = 2, max_rad: int = 0)[source]

max_azi, max_rad : truncation of the azimuthal / radial mode expansion.

evaluate(state: SystemState, eq: Equilibrium, opts: TheoryOptions) TheoryResult[source]
names_in_category(category: Category) tuple[str, ...][source]

Theory names belonging to a physical category, in precedence order.

coupled_robinson_names() tuple[str, ...][source]

Robinson-family theory names whose plot uses the fast mode-coupling marker.

albums.flow

Stage 3 of the ALBuMS pipeline: flows, the aggregated result, and the computed compatibility matrix.

exception IncompatibleFlowError[source]

Bases: ValueError

Raised by Flow.validate when a theory needs a capability the solver does not provide.

class Result(converged: bool, equilibrium: ~albums.equilibrium.Equilibrium, theories: dict[str, albums.theories.TheoryResult] = <factory>, Touschek: float = nan, xi: float | None = None)[source]

Bases: object

Aggregated outcome of running a flow at one operating point.

converged: bool
equilibrium: Equilibrium
theories: dict[str, albums.theories.TheoryResult]
Touschek: float = nan
xi: float | None = None
get(*names: str) albums.theories.TheoryResult | None[source]

Return the first present TheoryResult among names, else None.

property any_unstable: bool
property zero_frequency: bool
property robinson_flags: ndarray
property hom: bool
property ptbl: bool
property growth_robinson: ndarray
property growth_zero_frequency: float
property growth_PTBL: float | numpy.ndarray
__init__(converged: bool, equilibrium: ~albums.equilibrium.Equilibrium, theories: dict[str, albums.theories.TheoryResult] = <factory>, Touschek: float = nan, xi: float | None = None) None
class Flow(equilibrium: EquilibriumSolver, theories: list[albums.theories.InstabilityTheory], name: str | None = None)[source]

Bases: object

A user-chosen pipeline: one equilibrium solver + a subset of theories.

equilibrium: EquilibriumSolver
theories: list[albums.theories.InstabilityTheory]
name: str | None = None
required_capabilities() frozenset[albums.equilibrium.Capability][source]
validate() None[source]

Raise IncompatibleFlowError if any theory is incompatible with the chosen equilibrium solver. Call this before any compute.

is_valid() bool[source]
__init__(equilibrium: EquilibriumSolver, theories: list[albums.theories.InstabilityTheory], name: str | None = None) None
flow_label(flow) str[source]

Short label for filenames: the flow name (or ‘custom’), or the name string.

is_compatible(solver: EquilibriumSolver, theory: InstabilityTheory) bool[source]
compatibility_matrix(solvers: Optional[Iterable[EquilibriumSolver]] = None, theories: Optional[Iterable[InstabilityTheory]] = None) str[source]

Render the solver x theory compatibility table as a Markdown string.

Generated from the capability sets so the docs cannot drift from the code.

albums.saveload

HDF5 save/load helpers for scan outputs.

The scan output is a nested dict of numpy arrays mirroring Result (produced by results_to_arrays), optionally with a scan_meta group carrying the swept axes/labels/flow; it is written to nested HDF5 groups and read back into a ResultArray. The on-disk schema is therefore generated from the dataclasses — there is no hand-maintained key list. Optimisation scans now use this same format (the optimised psi map lives in scan_meta/extra).

_write_group(grp, data: dict) None[source]

Recursively write a (possibly nested) dict of arrays into an HDF5 group.

_read_group(grp) dict[source]

Recursively read an HDF5 group into a (possibly nested) dict of arrays.

save_hdf5(filename: str, data_dict: dict) None[source]

Write a (possibly nested) dict of arrays to filename (mode “w”).

load_hdf5(filename: str) dict[source]

Read filename into a (possibly nested) dict of arrays.

save_out(name: str, out) None[source]

Save a scan result (a ResultArray or its nested dict) to <name>.hdf5.

Prefer result.save(name), which also writes the scan metadata; this helper persists the raw data dict only.

load_out(file: str)[source]

Load a scan result from an HDF5 file as a ResultArray (with metadata).

albums.scan

Module where parameter scans and optimization scans are defined.

Every scan takes a SystemState (the ring + cavity list bundle) together with a resolved set of typed option objects (EquilibriumOptions, TheoryOptions, and for the optimisation scans OptimiserOptions), plus a ScanOptions controlling the sweep itself. These are bundled with the resolved flow into a ScanContext. The cavity list is deep-copied out of the state, so the caller’s SystemState is left untouched as grid points mutate cavity attributes.

_local_rows(var1)[source]

This rank’s slice of var1 plus the matching global row indices.

Splitting is even-as-possible (np.array_split), so a rank may own 0+ rows; the global indices let after-opti passes address the full gathered psi map.

_progress(total)[source]

One consolidated progress bar, shown on rank 0 only.

class ScanContext(cavity_list: list[CavityResonator], ring: Synchrotron, flow: object, eq_opts: EquilibriumOptions, theory_opts: TheoryOptions = <factory>, opti_opts: OptimiserOptions = <factory>, scan_opts: ScanOptions = <factory>, psi0_HC: float | None = None, bounds: tuple | None = None, RoQ: float | None = None)[source]

Bases: object

Everything a scan grid point needs, bundled once per scan.

Variables
  • cavity_list (list of CavityResonator) – Main cavity in position 0, the harmonic cavity in position 1.

  • ring (Synchrotron) – Ring configuration.

  • flow (Flow) – The already-resolved solve flow.

  • eq_opts (EquilibriumOptions) – Beam current, integration boundary and solver options.

  • theory_opts (TheoryOptions) – Shared theory inputs.

  • opti_opts (OptimiserOptions) – Optimisation settings (used by the optimisation scans only).

  • scan_opts (ScanOptions) – Sweep settings (skip).

  • bounds (psi0_HC,) – Initial guess and bounds for the optimisation scans.

  • RoQ (float or None) – Fixed R/Q value used by scan_psi_HC_Q0.

cavity_list: list[CavityResonator]
ring: Synchrotron
flow: object
eq_opts: EquilibriumOptions
theory_opts: TheoryOptions
opti_opts: OptimiserOptions
scan_opts: ScanOptions
psi0_HC: float | None = None
bounds: tuple | None = None
RoQ: float | None = None
__init__(cavity_list: list[CavityResonator], ring: Synchrotron, flow: object, eq_opts: EquilibriumOptions, theory_opts: TheoryOptions = <factory>, opti_opts: OptimiserOptions = <factory>, scan_opts: ScanOptions = <factory>, psi0_HC: float | None = None, bounds: tuple | None = None, RoQ: float | None = None) None
_make_ctx(state, flow, eq_opts, theory_opts, opti_opts=None, scan_opts=None, **extra) ScanContext[source]

Build a ScanContext, resolving the flow once with the chosen mode coupling.

The cavity list is deep-copied out of state so that mutating cavity attributes per grid point never touches the caller’s SystemState.

_strip_unpicklable(res)[source]

Drop the live backend handles / cavity objects from a Result before MPI pickling. results_to_arrays ignores these fields anyway, and the pycolleff backend_LE carries an unpicklable closure (see physics.ptbl.prepare_alves_le).

_run_grid(func, var1, var2, ctx)[source]

Evaluate func(v1, v2, ctx) over the var1 x var2 grid, returning a 2D object array of Result on rank 0 (None on other ranks).

var1 rows are split across MPI ranks and object-gathered (pickling) to the root — the entries are Result objects (nested arrays + dataclasses), so the buffer-based comm.Gather cannot be used. Grid points skipped by the skip fast-path stay None and are filled with sentinels downstream.

__scan(func, var1, var2, ctx)[source]
_result(ctx, grid, var1, var2, u1, u2, l1, l2, extra=None)[source]

Rank-0: wrap the gathered grid into a self-describing ResultArray (axes, units, labels, flow). Returns None on other ranks.

__scan_opti(func, var1, var2, ctx)[source]

Optimisation grid: gather the full Result per point to root, and the optimised psi to every rank (needed by the after-opti pass).

__scan_after_opti(func, psi, var1, var2, psi_add, ctx)[source]
__psi_I0(psi, I0, ctx)[source]
scan_psi_I0(state, psi_HC_vals, currents, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__psi_RoQ(psi, RoQ, ctx)[source]
scan_psi_RoQ(state, psi_HC_vals, RoQ_vals, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__opti_I0_RoQ(I0, RoQ, ctx)[source]
__opti_I0_RoQ_equilibrium(I0, RoQ, ctx)[source]
_opti_result(ctx, grid, psi, var1, var2, u1, u2, l1, l2)[source]

Build the optimisation ResultArray with the optimised psi grid in extra.

scan_RoQ_I0(state, current_vals, RoQ_vals, flow, eq_opts, psi0_HC, bounds, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), opti_opts=OptimiserOptions(method_opti='COBYLA', tol_opti=0.01, maxiter_opti=1000, rhobeg_opti=0.1, method='Nelder-Mead', tol=0.05, loop_option=False, add_psi_loop=0.02, max_loop=200, auto_psi_input=False, xi_init_input=0.8, debug=False), scan_opts=ScanOptions(skip=False), scan_after_opti=True, psi_add_after_opti=-0.1)[source]

Optimise psi_HC over a current x R/Q grid.

Returns the optimisation ResultArray (background quantities xi/Touschek/ bunch_length/psi + flow instability markers). When scan_after_opti is True, a second scan re-run slightly off the optimum is attached as result.after_opti.

scan_RoQ_I0_equilibrium(state, current_vals, RoQ_vals, flow, eq_opts, psi0_HC, bounds, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), opti_opts=OptimiserOptions(method_opti='COBYLA', tol_opti=0.01, maxiter_opti=1000, rhobeg_opti=0.1, method='Nelder-Mead', tol=0.05, loop_option=False, add_psi_loop=0.02, max_loop=200, auto_psi_input=False, xi_init_input=0.8, debug=False), scan_opts=ScanOptions(skip=False))[source]
__opti_Q0_RoQ(Q0, RoQ, ctx)[source]
__opti_Q0_RoQ_equilibrium(Q0, RoQ, ctx)[source]
scan_RoQ_Q0(state, Q0_vals, RoQ_vals, flow, eq_opts, psi0_HC, bounds, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), opti_opts=OptimiserOptions(method_opti='COBYLA', tol_opti=0.01, maxiter_opti=1000, rhobeg_opti=0.1, method='Nelder-Mead', tol=0.05, loop_option=False, add_psi_loop=0.02, max_loop=200, auto_psi_input=False, xi_init_input=0.8, debug=False), scan_opts=ScanOptions(skip=False), scan_after_opti=True, psi_add_after_opti=-0.1)[source]
scan_RoQ_Q0_equilibrium(state, Q0_vals, RoQ_vals, flow, eq_opts, psi0_HC, bounds, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), opti_opts=OptimiserOptions(method_opti='COBYLA', tol_opti=0.01, maxiter_opti=1000, rhobeg_opti=0.1, method='Nelder-Mead', tol=0.05, loop_option=False, add_psi_loop=0.02, max_loop=200, auto_psi_input=False, xi_init_input=0.8, debug=False), scan_opts=ScanOptions(skip=False))[source]
__psi_I0_RoQ(psi, I0, RoQ, ctx)[source]
__psi_Q0_RoQ(psi, Q0, RoQ, ctx)[source]
__psi_QL(psi, QL, ctx)[source]
scan_psi_QL(state, psi_HC_vals, QL_vals, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__psi_MCdet(psi, det, ctx)[source]
scan_psi_MCdet(state, psi_HC_vals, MCdet_vals, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__psi_MCRs(psi, Rs, ctx)[source]
scan_psi_MC_Rs(state, psi_HC_vals, MC_Rs_vals, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__psi_MC_beta(psi, beta, ctx)[source]
scan_psi_MC_beta(state, psi_HC_vals, MC_beta_vals, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__psi_HC_Q0(psi, Q0, ctx)[source]
scan_psi_HC_Q0(state, psi_HC_vals, HC_Q0_vals, RoQ, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__MC_Vc_HC_Vc_active(MC_Vc, HC_Vc, ctx)[source]
scan_MC_Vc_HC_Vc_active(state, MC_Vc_vals, HC_Vc_vals, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__MC_Vc_MC_psi_active(MC_Vc, MC_psi, ctx)[source]
scan_MC_Vc_MC_psi_active(state, MC_Vc_vals, MC_psi_vals, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__MC_psi_HC_psi_active(MC_psi, HC_psi, ctx)[source]
scan_MC_psi_HC_psi_active(state, MC_psi_vals, HC_psi_vals, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__HC_beta_I0_active(HC_beta, I0, ctx)[source]
scan_HC_beta_I0_active(state, HC_beta_vals, I0_vals, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]
__MC_psi_I0(psi, I0, ctx)[source]
scan_MC_psi_I0(state, psi_MC_vals, I0_vals, flow, eq_opts, theory_opts=TheoryOptions(mode_coupling=True, f_HOM=0, Z_HOM=0), scan_opts=ScanOptions(skip=False))[source]

albums.result_io

Turn a grid of Result objects into a nested dict of numpy arrays whose structure mirrors Result itself — the single source of truth for the scan / HDF5 schema (it is generated from the dataclass definitions, never hand-maintained).

The output layout, for a scan over var1 × var2 grid points:

converged                         (V1, V2)            bool
Touschek                          (V1, V2)            float
xi                                (V1, V2)            float
equilibrium/<field>               (V1, V2[, k])       float / bool
theories/<name>/<field>           (V1, V2[, n])       float / bool

Only numeric / boolean (and numeric ndarray) fields are persisted; live backend handles (Equilibrium.backend_BLE / backend_LE), the cavity_list and the capabilities set are non-serialisable and skipped automatically by the type filter. Missing points (failed/None results, or a theory absent from a given flow) are filled with a sentinel: NaN for floats, False for booleans.

_is_numeric(v) bool[source]

True if v can be stored in an HDF5 dataset as-is.

_collect(grid_shape: tuple, getter: Callable, *, skip_if_all_none: bool = False)[source]

Build one numpy array over the grid from getter applied per point.

getter returns the field value for a grid point (or None if the result is missing / the field is unset). The trailing shape and dtype are inferred from the first non-None, numeric sample; non-numeric samples are skipped (returns None). Missing points get a NaN (float) / False (bool) sentinel.

results_to_arrays(results: ndarray) dict[source]

Convert an object array of Result into a nested dict.

Parameters

results (numpy.ndarray) – Object array (any leading shape — typically 1D or 2D) whose entries are Result instances, or None for grid points that were skipped.

Returns

Nested {field: array | {subfield: array}} mirroring Result (see the module docstring for the layout).

Return type

dict

fields_of_result()[source]

Field names of Result (imported lazily to avoid a cycle with flow).

_result_attr(r, name)[source]
_eq_attr(r, name)[source]
_theory_attr(r, theory_name, attr)[source]
class ResultArray(data: dict, *, var1=None, var2=None, var1_unit: float = 1.0, var2_unit: float = 1.0, var1_label: str | None = None, var2_label: str | None = None, name: str | None = None, flow=None, tau_boundary=None, extra: dict | None = None)[source]

Bases: object

A grid of scan results, stored as the nested dict of arrays produced by results_to_arrays.

Wraps that dict with vectorized, flow-agnostic accessors (the grid-level analogue of Result’s category accessors), ND indexing, HDF5 save/load and a plotting shortcut. Missing categories or grid points read back as sentinels (False for flags, NaN for floats).

A scan additionally attaches scan metadata — the swept axes, their display units/labels, the flow and a name — so the object is self-describing: result.plot(“xi”) and result.save() need no further arguments. A bare ResultArray(data) (built by results_to_arrays or loaded from a plain HDF5 file) leaves these as None/identity and still works. The extra dict holds optimisation-only maps (e.g. the optimised psi grid) that are not part of the Result schema but are plottable as a background quantity.

Parameters
  • data (dict) – Nested dict from results_to_arrays (or loaded from HDF5).

  • var1 (numpy.ndarray, optional) – The swept axes (outer, inner). None for a bare result.

  • var2 (numpy.ndarray, optional) – The swept axes (outer, inner). None for a bare result.

  • var1_unit (float) – Multiplicative display scaling for each axis.

  • var2_unit (float) – Multiplicative display scaling for each axis.

  • var1_label (str, optional) – Axis labels for plots.

  • var2_label (str, optional) – Axis labels for plots.

  • name (str) – Base name used for plot titles and saved files.

  • flow (Flow or str, optional) – The flow that produced the scan (used for the saved-file label only; marker derivation reads the theory names already stored in data).

  • tau_boundary (float, optional) – Resolved integration half-window, used only in the Bosch plot filename.

  • extra (dict, optional) – Named 2D arrays outside the Result schema (e.g. {“psi”: grid}).

__init__(data: dict, *, var1=None, var2=None, var1_unit: float = 1.0, var2_unit: float = 1.0, var1_label: str | None = None, var2_label: str | None = None, name: str | None = None, flow=None, tau_boundary=None, extra: dict | None = None)[source]
property shape: tuple

Grid shape (var1, var2).

to_dict() dict[source]

The underlying nested dict of arrays.

point(idx) dict[source]

The values at one grid point as a nested dict (no Result rebuilt).

_theory(names)[source]
_field(group, key, tail=(), fill=False, dtype=<class 'bool'>)[source]
property converged
property Touschek
property xi
property bunch_length

RMS bunch length per grid point, in [s].

property theories: dict
property zero_frequency
property robinson_flags
property modes
property converged_modes
property hom
property ptbl
property growth_robinson
property growth_zero_frequency
property growth_ptbl
_collapse_trailing(arr: ndarray, reduce: Callable) ndarray[source]

Reduce an array of shape self.shape followed by trailing dimensions down to self.shape, where the trailing dimension(s) are whatever per-mode axes the field carries (possibly none). Grid-dimension-agnostic: works for 1D and 2D scans alike.

property any_unstable: ndarray

True where at least one theory in this result flags instability at that point. Grid-level analogue of Result.any_unstable.

Points where a theory didn’t run (e.g. because the equilibrium itself failed there) read as not-unstable.

property theory_converged: ndarray

True where every theory that tracks its own convergence (TheoryResult.converged) succeeded. Theories that don’t track convergence default to True and have no effect, so a new theory with a ‘converged’ field is picked up automatically.

categories() dict[source]

Flat per-category arrays under the legacy names used by the plotters.

_meta_dict() dict[source]

The scan-metadata group written next to the data on save.

static _meta_kwargs(meta: dict) dict[source]

Turn a loaded scan-metadata group back into __init__ keyword args.

save(name: str) None[source]

Save to <name>.hdf5 (nested HDF5 groups), including scan metadata.

classmethod load(file: str) ResultArray[source]

Load a ResultArray (with any scan metadata) from a nested-HDF5 file.

plot(quantity, var1=None, var2=None, var1_unit=None, var2_unit=None, var1_label=None, var2_label=None, plot_opts=None, name=None, flow=None, tau_boundary=None)[source]

Plot one background quantity plus the flow’s instability markers.

Axes metadata (var1/var2, units, labels, name, flow, tau_boundary) fall back to the values stored on the result, so a scan output plots with just result.plot(“xi”). A bare ResultArray must supply var1 and var2.

Physics kernel

albums.physics.potential

Equilibrium-derived closed-form quantities: RF potential well, bunch length, form factors, incoherent (Robinson) frequency and the Landau-damping threshold.

These are the low-level quantities shared by the Stage-1 solvers (albums.equilibrium) and by nearly every Stage-2 theory.

References

[1] Bosch, R. A., K. J. Kleman, and J. J. Bisognano. “Robinson instabilities

with a higher-harmonic cavity.” Physical Review Special Topics-Accelerators and Beams 4.7 (2001): 074401.

potential_decomposition(ring: Synchrotron, cavity_list: list[CavityResonator]) tuple[float, float, float][source]

Taylor coefficients of the RF potential well about the synchronous point.

Parameters
  • ring (Synchrotron) – Ring parameters.

  • cavity_list (list of CavityResonator) – Solved cavities.

Returns

a, b, c – Quadratic, cubic and quartic potential-well coefficients.

Return type

float

References

Eq. (4)-(6) in [1].

bunch_length(ring: Synchrotron, a: float, b: float, c: float, tau_boundary: float) float[source]

RMS bunch length from the potential-well distribution.

Integrates the Boltzmann distribution of the quartic potential well over [-tau_boundary, tau_boundary] and returns its standard deviation.

Parameters
  • ring (Synchrotron) – Ring parameters.

  • a (float) – Potential-well coefficients from potential_decomposition.

  • b (float) – Potential-well coefficients from potential_decomposition.

  • c (float) – Potential-well coefficients from potential_decomposition.

  • tau_boundary (float) – Integration half-width in [s].

Returns

RMS bunch length in [s].

Return type

float

References

Eq. (8) in [1].

form_factors(f: float, m: int, bunch_length: float) float[source]

Gaussian-bunch amplitude form factor at harmonic m of frequency f.

Parameters
  • f (float) – Fundamental frequency in [Hz].

  • m (int) – Harmonic number of the cavity.

  • bunch_length (float) – RMS bunch length in [s].

Returns

Form factor exp(-(m omega sigma)^2 / 2) in [0, 1].

Return type

float

robinson_frequency(ring: Synchrotron, cavity_list: list[CavityResonator], F: np.ndarray) float[source]

Incoherent synchrotron (Robinson) angular frequency omega_r.

Parameters
  • ring (Synchrotron) – Ring parameters.

  • cavity_list (list of CavityResonator) – Solved cavities.

  • F (numpy.ndarray) – Amplitude form factor per cavity.

Returns

Synchrotron angular frequency in [rad/s].

Return type

float

References

Eq. (10) in [1].

landau_threshold(ring: Synchrotron, omega_r: float, c: float, b: float) np.ndarray[source]

Landau-damping frequency-spread threshold for modes mu = 1..4.

Parameters
  • ring (Synchrotron) – Ring parameters.

  • omega_r (float) – Synchrotron angular frequency from robinson_frequency.

  • c (float) – Quartic and cubic potential-well coefficients from potential_decomposition.

  • b (float) – Quartic and cubic potential-well coefficients from potential_decomposition.

Returns

Shape (4, 1) thresholds for the dipole, quadrupole, sextupole and octupole modes.

Return type

numpy.ndarray

References

Eq. (19) in [1].

albums.physics.robinson

Robinson (coupled-bunch mode 0) instabilities: - Coupled/uncoupled Robinson dipole to octupole modes, including fast mode-coupling, based on Bosch equations [1]. - Robinson instabilites using the Gaussian longitudinal mode-coupling instability method [2].

References

[1] Bosch, R. A., K. J. Kleman, and J. J. Bisognano. “Robinson instabilities

with a higher-harmonic cavity.” Physical Review Special Topics-Accelerators and Beams 4.7 (2001): 074401.

[2] Alves, Murilo B. “Theoretical models for longitudinal coupled-bunch instabilities

driven by harmonic cavities in electron storage rings.” Physical Review Accelerators and Beams 28.3 (2025): 034401.

omega_n(ring: Synchrotron, cavity: CavityResonator) float[source]

Detuned resonant angular frequency of a cavity. Near Eq. (B.3) in [1].

phi_pm(ring: Synchrotron, cavity: CavityResonator, Omega: float, sign: str) float[source]

Upper (“+”) / lower (“-”) sideband phase. Near Eq. (B.4) in [1].

A_tilde(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, Omega: float) float[source]

Cavity transfer term à (dipole). Bosch Appendix B [1].

B_tilde(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, Omega: float, bunch_length: float) float[source]

Cavity transfer term B̃ (quadrupole). Bosch Appendix B [1].

D_tilde(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, Omega: float, bunch_length: float) float[source]

Cavity transfer cross-term D̃. Bosch Appendix B [1].

a_tilde(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, Omega: float) float[source]

Cavity transfer term ã (dipole damping). Bosch Appendix B [1].

b_tilde(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, Omega: float, bunch_length: float) float[source]

Cavity transfer term b̃ (quadrupole damping). Bosch Appendix B [1].

d_tilde(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, Omega: float, bunch_length: float) float[source]

Cavity transfer cross-term d̃. Bosch Appendix B [1].

ar_B11(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, Omega: float, bunch_length: float, omega_r: float) float[source]

Coupled-mode damping rate. Eq. (B.11) in [1].

Omega_B13(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, Omega: float, alpha_r: float, bunch_length: float, omega_r: float, sign: str, abs_val: bool = True, return_root: bool = False) float[source]

Coupled-mode frequency (or its discriminant). Eq. (B.13) in [1].

robinson_damping_rate(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, Omega: float, mu: int, bunch_length: float) float[source]

Radiation-free Robinson damping rate of mode mu. Eq. (16) in [1].

robinson_no_coupling(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, omega_r: float, bunch_length: float, landau_threshold: np.ndarray) tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray][source]

Robinson modes mu = 1..4 solved independently (no mode coupling).

For each mode the coherent frequency is found from the dispersion relation, then flagged unstable if its (radiation-included) damping rate is negative and its complex frequency shift exceeds the Landau threshold.

Parameters
  • ring (Synchrotron) – Ring parameters.

  • cavity_list (list of CavityResonator) – Solved cavities.

  • I0 (float) – Beam current in A.

  • F (numpy.ndarray) – Amplitude form factor per cavity.

  • omega_r (float) – Synchrotron angular frequency.

  • bunch_length (float) – RMS bunch length in [s].

  • landau_threshold (numpy.ndarray) – Per-mode thresholds from landau_threshold.

Returns

  • robinson (numpy.ndarray of bool, shape (4,)) – Instability flag per mode.

  • Omega (numpy.ndarray, shape (4,)) – Coherent angular frequency per mode.

  • converged (numpy.ndarray of bool, shape (4,)) – Root-finder convergence per mode.

  • growth (numpy.ndarray, shape (4,)) – Net growth rate (radiation included) per mode.

References

Eq. (15)-(16) in [1].

robinson_coupling(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, omega_r: float, bunch_length: float, landau_threshold: np.ndarray, abs_val: bool = True) tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray][source]

Coupled Robinson dipole/quadrupole modes with fast mode-coupling.

Solves the coupled dipole and quadrupole dispersion relations (Eq. B.11/B.13), flags each as Landau-stabilised or not, and detects fast mode-coupling when the discriminant goes negative.

Parameters
  • ring (Synchrotron) – Ring parameters.

  • cavity_list (list of CavityResonator) – Solved cavities.

  • I0 (float) – Beam current in A.

  • F (numpy.ndarray) – Amplitude form factor per cavity.

  • omega_r (float) – Synchrotron angular frequency.

  • bunch_length (float) – RMS bunch length in [s].

  • landau_threshold (numpy.ndarray) – Per-mode thresholds from landau_threshold.

  • abs_val (bool, optional) – Take the absolute value of the discriminant when solving (default True).

Returns

  • robinson (numpy.ndarray of bool, shape (4,)) – [coupled_dipole, coupled_quadrupole, fast_coupling_by_dipole, fast_coupling_by_quadrupole].

  • Omega (numpy.ndarray, shape (2,)) – Coherent dipole and quadrupole angular frequencies.

  • converged (numpy.ndarray of bool, shape (2,)) – Root-finder convergence for dipole and quadrupole.

  • growth (numpy.ndarray, shape (4,)) – Net growth rate per entry of robinson.

References

Appendix B, Eq. (B.11)-(B.13) in [1].

robinson_glmci(ring: Synchrotron, LE: LongitudinalEquilibrium, max_azi: int = 2, max_rad: int = 0) tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray][source]

Robinson (coupled-bunch mode 0) instabilites using the Gaussian longitudinal mode-coupling instability method [2].

This method does not distinguish between dipole Robinson, quadrupole Robisonson or fast-mode coupling instability. A positive result is flagged as fast-mode coupling instabilty.

Parameters
  • ring (Synchrotron) – Ring parameters.

  • LE (LongitudinalEquilibrium) – Solved pycolleff equilibrium handle.

  • max_azi (int, optional) – Maximum azimuthal mode number (default 2).

  • max_rad (int, optional) – Maximum radial mode number (default 0).

Returns

  • robinson (numpy.ndarray of bool, shape (4,)) – [False, False, FMCI, FMCI] (the fast-coupling dipole/quadrupole slots).

  • Omega (numpy.ndarray, shape (2,)) – Real parts of the first two eigenfrequencies.

  • converged (numpy.ndarray of bool, shape (2,)) – Always [True, True] (the eigensolver does not iterate).

  • growth (numpy.ndarray, shape (4,)) – Net growth rate placed in the fast-coupling slots.

References

Alves [2].

albums.physics.zero_frequency

Zero-frequency (DC Robinson) instability: the per-mode mu = 1..4 stability bound without mode coupling, and the coupled criterion built from the Robinson terms [1].

References

[1] Bosch, R. A., K. J. Kleman, and J. J. Bisognano. “Robinson instabilities

with a higher-harmonic cavity.” Physical Review Special Topics-Accelerators and Beams 4.7 (2001): 074401.

zero_frequency_no_coupling(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, mu: int, bunch_length: float) float[source]

Per-mode zero-frequency stability bound (no coupling). Eq. (14) in [1].

zero_frequency_instability(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, omega_r: float, bunch_length: float, mode_coupling: bool) bool[source]

Zero-frequency (DC Robinson) instability test.

Parameters
  • ring (Synchrotron) – Ring parameters.

  • cavity_list (list of CavityResonator) – Solved cavities.

  • I0 (float) – Beam current in A.

  • F (numpy.ndarray) – Amplitude form factor per cavity.

  • omega_r (float) – Synchrotron angular frequency from robinson_frequency.

  • bunch_length (float) – RMS bunch length in [s].

  • mode_coupling (bool) – If True use the coupled criterion (Eq. B.12); otherwise the per-mode mu = 1..4 criterion (Eq. 14).

Returns

True if the equilibrium is zero-frequency unstable.

Return type

bool

References

Eq. (14) / (B.12) in [1].

albums.physics.coupled_bunch

HOM-driven longitudinal dipole coupled-bunch instability: - Growth-rate estimate using Bosch [1] resonant approximation, compared against approxmiate the Landau-damping threshold from rf potential decomposition.

References

[1] Bosch, R. A., K. J. Kleman, and J. J. Bisognano. “Robinson instabilities

with a higher-harmonic cavity.” Physical Review Special Topics-Accelerators and Beams 4.7 (2001): 074401.

dipole_coupled_bunch_growth_rate(ring: Synchrotron, I0: float, f_HOM: float, Z_HOM: float, bunch_length: float, omega_r: float) float[source]

Resonant dipole coupled-bunch growth rate. Eq. (22) in [1].

dipole_coupled_bunch(ring: Synchrotron, I0: float, f_HOM: float | np.ndarray, Z_HOM: float | np.ndarray, bunch_length: float, omega_r: float, landau: np.ndarray) bool[source]

HOM-driven dipole coupled-bunch instability test.

Uses the resonant dipole_coupled_bunch_growth_rate for each HOM in the supplied list. The instability is flagged only if the HOM growth rate exceeds both radiation damping and the dipole Landau threshold.

Parameters
  • ring (Synchrotron) – Ring parameters.

  • I0 (float) – Beam current in A.

  • f_HOM (float or array-like) – HOM resonant frequency in [Hz] and shunt impedance in [Ohm].

  • Z_HOM (float or array-like) – HOM resonant frequency in [Hz] and shunt impedance in [Ohm].

  • bunch_length (float) – RMS bunch length in [s].

  • omega_r (float) – Synchrotron angular frequency.

  • landau (numpy.ndarray) – Landau thresholds from landau_threshold; only the dipole entry landau[0] is used.

Returns

True if HOM-driven coupled-bunch unstable.

Return type

bool

Raises

ValueError – If f_HOM and Z_HOM have mismatched lengths.

References

Eq. (22) in [1].

albums.physics.ptbl

Periodic transient beam loading (PTBL) (also called coupled bunch mode l=±1 instability).

Three backends:

  • ptbl_he: He’s perturbation criterion [1].

  • ptbl_alves: Gaussian longitudinal mode-coupling instabilty method [2].

  • coupled_bunch_mode1: Bosch [1] l=±1 coupled-bunch dipole mode [3].

References

[1] He, Tianlong. “Novel perturbation method for judging the stability of the

equilibrium solution in the presence of passive harmonic cavities.” Physical Review Accelerators and Beams 25.9 (2022): 094402.

[2] Alves, Murilo B. “Theoretical models for longitudinal coupled-bunch instabilities

driven by harmonic cavities in electron storage rings.” Physical Review Accelerators and Beams 28.3 (2025): 034401.

[3] He, Tianlong. “Novel perturbation method for judging the stability of the

equilibrium solution in the presence of passive harmonic cavities.” Physical Review Accelerators and Beams 25.9 (2022): 094402.

ptbl_he(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, PHI: np.ndarray) bool[source]

PTBL stability test via He’s perturbation criterion (eta > 1).

Parameters
  • ring (Synchrotron) – Ring parameters (uses h, T0).

  • cavity_list (list of CavityResonator) – Solved cavities (main then harmonic).

  • I0 (float) – Beam current in A.

  • F (numpy.ndarray) – Amplitude form factor per cavity (F[1] is the harmonic cavity).

  • PHI (numpy.ndarray) – Phase form factor per cavity (PHI[1] is the harmonic cavity).

Returns

True if PTBL-unstable (eta > 1).

Return type

bool

References

He [1].

coupled_bunch_mode1_damping_rate(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, Omega: float, mu: int, bunch_length: float) float[source]

Damping rate of the l=±1 coupled-bunch mode. Eq. (15) in [3].

coupled_bunch_mode1(ring: Synchrotron, cavity_list: list[CavityResonator], I0: float, F: np.ndarray, omega_r: float, bunch_length: float, landau_threshold: np.ndarray) tuple[np.ndarray, np.ndarray, np.ndarray][source]

Coupled-bunch dipole mode l=±1 (Bosch mode-1 criterion).

Parameters
  • ring (Synchrotron) – Ring parameters.

  • cavity_list (list of CavityResonator) – Solved cavities.

  • I0 (float) – Beam current in A.

  • F (numpy.ndarray) – Amplitude form factor per cavity.

  • omega_r (float) – Synchrotron angular frequency.

  • bunch_length (float) – RMS bunch length in [s].

  • landau_threshold (numpy.ndarray) – Per-mode thresholds from landau_threshold.

Returns

  • coupled_mode1 (numpy.ndarray of bool, shape (2,)) – Instability flag for the +1 and -1 modes.

  • modes (numpy.ndarray, shape (2,)) – Coherent angular frequency for each mode.

  • converged (numpy.ndarray of bool, shape (2,)) – Root-finder convergence per mode.

References

Eq. (15) in [3].

prepare_alves_le(ring: Synchrotron, LE: LongitudinalEquilibrium) None[source]

Set the synchrotron tune from the bunch length and select ImpedanceDFT.

ptbl_alves(ring: Synchrotron, LE: LongitudinalEquilibrium, max_azi: int = 10, max_rad: int = 10) tuple[bool, float][source]

PTBL via Gaussian longitudinal mode-coupling instability method (coupled-bunch mode 1).

Also flag the usual coupled-bunch instability of mode 1 as PTBL.

Parameters
  • ring (Synchrotron) – Ring parameters (uses omega1, tau).

  • LE (LongitudinalEquilibrium) – Solved pycolleff equilibrium handle (Equilibrium.backend_LE).

  • max_azi (int, optional) – Maximum azimuthal mode number (default 10).

  • max_rad (int, optional) – Maximum radial mode number (default 10).

Returns

  • unstable (bool) – True if the largest net growth rate is positive.

  • growth (float) – Net growth rate (eigenvalue imaginary part minus radiation damping).

References

Alves [2].