static_profile

Core quasi-static Stark-Zeeman solver. For each electric microfield magnitude \(F\) and orientation \(\mu=\cos\theta\), the solver diagonalizes the full field-dependent Hamiltonian and accumulates the three polarization profiles.

\[H(F,\mu) = H_A + V_E(F,\mu), \qquad V_E(F,\mu) = F\mu\,M_z + F\sqrt{1-\mu^2}\,M_x.\]

The static profile is the microfield and angle average

\[I_q(\omega) = \int_0^\infty \int_0^1 W(F)\,I_q(\omega,F,\mu)\,d\mu\,dF, \qquad q \in \{\pi,\sigma^+,\sigma^-\}.\]
starkzee.static_profile.build_stark_matrix(n, Z, Fz, Fx)[source]

Build the (2n²) × (2n²) Stark electric-field perturbation matrix in eV.

The linear Stark interaction for an electron in an external electric field F = Fz ẑ + Fx x̂ is:

V_E = −e (z Fz + x Fx)

In the hydrogenic basis the matrix elements reduce to products of a radial element and an angular element. The within-shell (Δn = 0) radial element ⟨n, l | r | n, l±1⟩ is given analytically:

⟨n, l | r | n, l−1⟩ = (3n/2Z) √(n² − l²) [a₀]

The angular elements ⟨l, m_l | cos θ | l±1, m_l⟩ (for Fz) and the combinations for Fx are provided by angular_dipole_element().

The x-component is constructed as:

x/r = (T_{−1} + T_{+1}) / √2

where T_q are the spherical tensor components of r̂.

Parameters:
  • n (int) – Principal quantum number.

  • Z (int) – Nuclear charge.

  • Fz (float) – Electric field component along B (z-axis) [V m⁻¹].

  • Fx (float) – Electric field component perpendicular to B (x-axis) [V m⁻¹].

Returns:

Hermitian Stark perturbation matrix in eV.

Return type:

ndarray, shape (2n², 2n²), dtype complex

Notes

This matrix operates within a single n-shell; the quadratic Stark effect (coupling to n ± 1, ±2 shells) is neglected, which is valid when the Stark shift ≪ the shell spacing Z² Ry (1/n² − 1/(n+1)²).

starkzee.static_profile.solve_starkzee(n, Z, B, Fz, Fx, quadratic_zeeman=True, fine_structure=True, A=1, use_empirical_data=False, atom='H')[source]

Diagonalize the combined Stark + Zeeman Hamiltonian for shell n.

Adds the Stark perturbation build_stark_matrix() to the atomic/magnetic Hamiltonian build_hamiltonian() and diagonalizes the sum with numpy.linalg.eigh:

H = H_atom(B) + V_E(Fz, Fx)

This is the inner-loop solver called for every (microfield magnitude, microfield angle) quadrature point during profile integration.

Parameters:
  • n (int) – Principal quantum number.

  • Z (int) – Nuclear charge.

  • B (float) – Magnetic field [T].

  • Fz (float) – Electric field component along B [V m⁻¹].

  • Fx (float) – Electric field component perpendicular to B [V m⁻¹].

  • quadratic_zeeman (bool, optional) – Include the diamagnetic quadratic Zeeman term (default True).

  • fine_structure (bool, optional) – Include MV + Darwin corrections (default True).

  • use_empirical_data (bool, optional) – Use NIST empirical level energies for the field-free Hamiltonian instead of the analytic Rydberg formula (default False). The internal Hamiltonian is assembled in cm⁻¹; eigenvalues are converted back to eV before returning so callers see no unit change.

  • atom (str, optional) – Atom identifier passed to load_levels() when use_empirical_data=True (default "H").

Returns:

  • eigenvalues (ndarray, shape (2n²,)) – Energy eigenvalues in ascending order [eV].

  • eigenvectors (ndarray, shape (2n², 2n²)) – Orthonormal eigenstates as columns, in the canonical |n, l, m_l, m_s⟩ basis.

starkzee.static_profile.calculate_static_profile(n_u, n_l, Z, B, Ne_m3, Te_ev, energies_ev, num_f=20, num_mu=6, max_beta=10.0, use_screening=True, quadratic_zeeman=True, fine_structure=True, frequency_dependent_width=True, A=1, Ti_ev=None, species='H', electron_model='pppb', electron_operator=False, use_empirical_data=False, atom='H')[source]

Compute the static-ion Stark-Zeeman line profile for n_u → n_l.

Integrates the Stark-Zeeman Hamiltonian over the plasma microfield distribution using Gauss-Legendre quadrature for both the field magnitude and the angle μ = cos θ between the microfield and B. For each quadrature point the combined Hamiltonian H = H_atom(B) + V_E(Fz, Fx) is diagonalized and the transition intensities accumulated into three polarization components.

Parameters:
  • n_u (int) – Upper and lower principal quantum numbers.

  • n_l (int) – Upper and lower principal quantum numbers.

  • Z (int) – Nuclear charge (1 for hydrogen).

  • B (float) – Magnetic field [T]. B=0 is fully supported; at zero field the π/σ decomposition is physically meaningless (no preferred axis) and all three returned components are equal by spherical symmetry.

  • Ne_m3 (float) – Electron density [m⁻³].

  • Te_ev (float) – Electron temperature [eV].

  • energies_ev (array-like) – Photon energies at which to evaluate the profile [eV].

  • num_f (int, optional) – Number of microfield quadrature points (default 20). Ferri et al. (2022) recommend ~50; 20 is sufficient for hydrogen but should be increased for multi-electron atoms (future: set dynamically by atom type).

  • num_mu (int, optional) – Number of Gauss-Legendre angle points (default 6). Ferri et al. (2022) recommend ~30; 6 is sufficient for hydrogen but should be increased for multi-electron atoms (future: set dynamically by atom type).

  • max_beta (float, optional) – Upper limit of the reduced-microfield grid β = F/F₀ (default 10). The Holtsmark tail beyond β = 10 carries ~3 % of the probability, which the quadrature truncates and renormalizes away; increase this (together with num_f) when the quasi-static far wings matter. Forwarded to microfield_quadrature().

  • use_screening (bool, optional) – Use Hooper screened microfield distribution (default True).

  • quadratic_zeeman (bool, optional) – Include diamagnetic (quadratic) Zeeman term (default True).

  • fine_structure (bool, optional) – Include mass-velocity and Darwin corrections (Dirac fine structure) so that 2s_{1/2} = 2p_{1/2} (default True).

  • frequency_dependent_width (bool, optional) – When True (default), evaluate the GBK electron-impact width pointwise at the observation detuning from the gross-structure line center, w(E − E0), as in the PPPB operator Φ(Δω) of Ferri et al. (2022) Eq. (19), where Δω is “the frequency detuning from the line center”. Every component then shares the same frequency-dependent width function: a far-shifted σ± component receives a reduced width at its own position, and the far wings of all components relax toward the strong-collision floor C_n as G(Δω) → 0 (breakdown of the impact approximation), making the components non-Lorentzian. When False, use the single on-resonance value w(0) everywhere (faster; valid when the profile extent ≪ ω_c). Note the pointwise profile is not exactly area-normalized per component (the physical GBK non-Lorentzian shape isn’t either).

  • Ti_ev (float, optional) – Ion temperature [eV]. When supplied, Doppler broadening is folded into the Lorentzian accumulation as a Voigt profile, eliminating the need for a separate post-processing convolution. Default is None (bare Lorentzian, no Doppler).

  • species (str, optional) – Emitting species ('H', 'D', or 'T'); used to determine the ion mass for the Doppler width. Only relevant when Ti_ev is set. Default is 'H'.

  • electron_model (str, optional) – Electron-impact width prescription, forwarded to electron_impact_width_model(). 'pppb' (default) is the PPPB model (B-dependent ω_c cutoff); 'zest', 'zest-lee', 'zest-dufty' select the ZEST model with the GBK, Lee, or Dufty RPA G-function.

  • electron_operator (bool, optional) – When True, use the electron-impact operator diagonal: each Stark-Zeeman dressed state gets a width scaled by its own ⟨k|r²|k⟩ (electron_impact_r2_scaling()) instead of the shell-averaged scalar (default False). This is the ZEST operator treatment with the off-diagonal / c_k set to zero. The full PPPB operator (off-diagonal → complex intensity a_k + i c_k) and the lower-manifold d†·d contribution are not yet implemented — see the REVIEW note in electron_impact_r2_scaling(). Currently applied in the in-loop Lorentzian path; with Doppler-dominant grids (the post-FFT Lorentzian) the scalar resonance width is used.

  • use_empirical_data (bool, optional) – Use NIST empirical level energies for the field-free Hamiltonian instead of the analytic Dirac (spin-orbit + MV + Darwin) formula (default False); forwarded to build_hamiltonian(). The empirical levels include the Lamb shift, so the resulting profile centroid matches the measured NIST wavelength more closely than the pure-Dirac default, which is Lamb-shift-free. atomic_levels.json tabulates H (n ≤ 8), D (n ≤ 6), and T (n ≤ 3) levels — pass the matching atom for the emitting species: the default atom="H" combined with species='D'/'T' reproduces the plain-hydrogen line center, not the isotope-shifted one (~0.1-0.2 nm for Balmer-α).

  • atom (str, optional) – Atom identifier passed to load_levels() when use_empirical_data=True (default "H").

  • approximations (Notes on)

  • -----------------------

  • **sigma_D** (the Doppler width is computed as)

  • mean(energies_ev). (σ_D = E_mean × sqrt(Ti / mc²) where E_mean =)

  • Strictly

  • σ_D(dE_i) (each transition at energy dE_i should use)

  • but

  • H-alpha (the fractional error is ΔE/E ≈ Δ_Zeeman/E0 — about 0.03 % for)

  • practice. (at 10 T — and is negligible in)

  • step** (**Lorentzian FFT)

  • path) (Gaussian-loop)

  • uses (the post-loop Lorentzian convolution)

  • both (w_resonance (the on-resonance GBK width) for)

  • a (frequency_dependent_width settings — an FFT convolution cannot carry)

  • few (frequency-dependent width. The variation of w across the line is a)

  • σ_D. (% there and is negligible relative to)

  • resolution** (**Grid)

  • 2Δx) (σ_D ≤)

  • and (components narrower than the grid spacing are undersampled)

  • is (part of the integrated intensity is silently lost; a UserWarning)

  • grid. (emitted when w(0) < 2Δx. Supply Ti_ev or refine the)

Returns:

  • profile_pi (ndarray) – π (Δm = m_u − m_l = 0) polarization component.

  • profile_sig_plus (ndarray) – σ+ (Δm = +1, blue-shifted at B > 0; dipole channel q = m_l − m_u = −1) polarization component.

  • profile_sig_minus (ndarray) – σ− (Δm = −1, red-shifted; channel q = +1) polarization component.

Notes

Observable intensity at angle θ to B:

I(θ) = I_π sin²θ + ½(I_σ+ + I_σ−)(1 + cos²θ)

Transverse (θ = 90°): I_π + ½(I_σ+ + I_σ−). Along B (θ = 0°): I_σ+ + I_σ−. Angle-averaged: ⅔ (I_π + I_σ+ + I_σ−) (both sin²θ and ½(1+cos²θ) average to ⅔ over the sphere; for the isotropic case I_π = I_σ± = I this gives I(θ) = 2I at every angle, as it must).

starkzee.static_profile.discrete_transitions(n_u, n_l, Z, B, Fz=0.0, Fx=0.0, quadratic_zeeman=True, fine_structure=True, min_strength=0.0, A=1, radial_method=None, use_empirical_data=False, atom='H')[source]

Return all discrete Stark-Zeeman dipole transitions at a single field configuration.

Diagonalizes the Stark-Zeeman Hamiltonian for both shells and enumerates every (upper eigenstate i, lower eigenstate j, polarization q) triplet with non-zero dipole matrix element squared.

Parameters:
  • n_u (int) – Upper and lower principal quantum numbers.

  • n_l (int) – Upper and lower principal quantum numbers.

  • Z (int) – Nuclear charge.

  • B (float) – Magnetic field [T].

  • Fz (float, optional) – Electric field component along B [V m⁻¹] (default 0).

  • Fx (float, optional) – Electric field component perpendicular to B [V m⁻¹] (default 0).

  • quadratic_zeeman (bool, optional) – Include diamagnetic Zeeman term (default True).

  • fine_structure (bool, optional) – Include mass-velocity + Darwin corrections (default True).

  • min_strength (float, optional) – Discard transitions with dipole strength abs(d_q)² < min_strength [a₀²] (default 0).

  • A (int, optional) – Atomic mass number of the emitter (1 = H, 2 = D, 3 = T). Sets the reduced-mass Rydberg used for the absolute level energies (default 1).

  • radial_method ({"gordon", "quad", None}, optional) – Backend for the radial dipole elements. None (default) uses the module-level RADIAL_DIPOLE_METHOD ("gordon" exact closed form by default; "quad" is the numerical fallback). The two agree to ~1e-15.

  • use_empirical_data (bool, optional) – Use NIST empirical level energies (default False); forwarded to solve_starkzee().

  • atom (str, optional) – Atom identifier for empirical data (default "H"); forwarded to solve_starkzee().

Returns:

  • dict with five equal-length arrays sorted by transition energy

  • energy_ev – Transition energy E_upper_i − E_lower_j [eV].

  • q – Polarization integer q = m_l − m_u: 0 = π; q = −1 is σ+ (Δm = m_u − m_l = +1, blue-shifted at B > 0); q = +1 is σ− (red-shifted).

  • strength – abs(d_q(i→j))² [a₀²]. Summed over all transitions equals line_strength() (unitary invariance).

  • upper_idx – Upper eigenstate index (0 … 2n_u²−1).

  • lower_idx – Lower eigenstate index (0 … 2n_l²−1).