Quadratic Zeeman polarization wings

Script: examples/reproduce_halpha_wings.py

Demonstrates the polarization-wing effect at B = 500 T and B = 1000 T: at high field the quadratic Zeeman term shifts the 3p(\(m_l=\pm1\)) → 2s transitions away from the main Hα cluster, creating distinct shoulders/wings in the σ± components that only appear when quadratic_zeeman=True. A modest ion temperature (Ti_ev=Te) is used so the underlying Stark-Zeeman components — narrower than natural linewidth at this low density — are resolved on the plotted grid rather than undersampled.

Code

  1#!/usr/bin/env python3
  2"""
  3reproduce_halpha_wings.py
  4=========================
  5Focused examination of Hα (n=3→2, Z=1) σ+, σ−, π polarization components
  6at B = 500 T and B = 1000 T, comparing with and without the quadratic
  7(diamagnetic) Zeeman term.
  8
  9Physical picture
 10----------------
 11Without QZ all σ+ (or all σ−) Hα transitions are degenerate at
 12  E_σ+ = E0 + μ_B·B     (all Δml=+1 components)
 13  E_σ− = E0 − μ_B·B
 14
 15With QZ the diagonal shift of each |n,l,ml⟩ state is
 16  ΔE_QZ = (e²B²/8mₑ) · ⟨r²⟩_nl · ⟨sin²θ⟩_{l,ml}
 17
 18For n=3 the relevant shifts (B=1000 T):
 19  3p, ml=±1: +8.87 meV   ← LARGEST in n=3
 20  3s, ml=0 : +8.50 meV
 21  3d, ml=±2: +6.65 meV
 22  3d, ml=±1: +4.43 meV
 23  3d, ml=0 : +3.69 meV
 24
 25For n=2:
 26  2s, ml=0 : +1.72 meV
 27  2p, ml=±1: +1.48 meV
 28  2p, ml=0 : +0.74 meV
 29
 30The dominant oscillator-strength contributor is 3d→2p (radial dipole ≈4.75 a₀).
 31The 3p→2s transitions (radial dipole ≈3.06 a₀, oscillator fraction ~21 %)
 32have LARGER n=3 QZ shifts, so they appear as a separate shoulder:
 33
 34  σ+ wing: 3p(ml=+1) → 2s(ml=0)   at E0 + μ_B·B + (8.87−1.72) = E0+μ_B·B+7.1 meV
 35  σ− wing: 3p(ml=−1) → 2s(ml=0)   at E0 − μ_B·B + (8.87−1.72) = E0−μ_B·B+7.1 meV
 36            → this is ~7 meV NEARER to E0 than the main 3d cluster
 37
 38These wings are ONLY present with quadratic_zeeman=True.
 39"""
 40
 41import numpy as np
 42import matplotlib.pyplot as plt
 43import sys, os
 44sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
 45
 46from starkzee.static_profile import calculate_static_profile
 47from starkzee.utils import reduced_mass_rydberg_ev, BOHR_MAGNETON_EV_T
 48
 49# ── parameters ───────────────────────────────────────────────────────────────
 50Z, n_u, n_l = 1, 3, 2
 51Ne, Te      = 1e17, 5.0
 52E0          = (Z**2) * reduced_mass_rydberg_ev(Z, 1) * (1.0/n_l**2 - 1.0/n_u**2)
 53
 54# Fine energy grid — wide enough to cover both σ± at B=1000 T
 55DET_HALF = 0.10          # ±100 meV
 56NPTS     = 4000
 57det      = np.linspace(-DET_HALF, DET_HALF, NPTS)   # eV
 58energies = E0 + det
 59
 60# ── compute profiles ─────────────────────────────────────────────────────────
 61results = {}
 62for B in [500.0, 1000.0]:
 63    print(f"  B={int(B)} T: without QZ …", end=" ", flush=True)
 64    pi_nq, sp_nq, sm_nq = calculate_static_profile(
 65        n_u, n_l, Z, B, Ne, Te, energies,
 66        num_f=30, num_mu=8,
 67        use_screening=True, quadratic_zeeman=False,
 68        frequency_dependent_width=False, Ti_ev=Te)
 69    print("done.  With QZ …", end=" ", flush=True)
 70    pi_yq, sp_yq, sm_yq = calculate_static_profile(
 71        n_u, n_l, Z, B, Ne, Te, energies,
 72        num_f=30, num_mu=8,
 73        use_screening=True, quadratic_zeeman=True,
 74        frequency_dependent_width=False, Ti_ev=Te)
 75    print("done.")
 76    results[B] = dict(
 77        pi_nq=pi_nq, sp_nq=sp_nq, sm_nq=sm_nq,
 78        pi_yq=pi_yq, sp_yq=sp_yq, sm_yq=sm_yq,
 79    )
 80
 81# ── plot ─────────────────────────────────────────────────────────────────────
 82det_meV = det * 1e3   # meV axis
 83
 84fig, axes = plt.subplots(2, 3, figsize=(15, 9), sharey='row')
 85fig.suptitle(
 86    r"H$\alpha$ (n=3→2, Z=1) polarization wings from quadratic Zeeman"
 87    "\n"
 88    r"$N_e = 10^{17}$ m$^{-3}$, $T_e = 5$ eV — solid: with QZ, dashed: without QZ",
 89    fontsize=12)
 90
 91pol_labels = [r"$\pi$", r"$\sigma^+$", r"$\sigma^-$"]
 92pol_keys   = [("pi_nq", "pi_yq"), ("sp_nq", "sp_yq"), ("sm_nq", "sm_yq")]
 93pol_colors = ["tab:blue", "tab:red", "tab:green"]
 94
 95for row, B in enumerate([500.0, 1000.0]):
 96    r = results[B]
 97    zeeman_meV = BOHR_MAGNETON_EV_T * B * 1e3
 98
 99    # Expected wing positions (meV from E0)
100    # QZ shifts at this B (all scale as B²):
101    coeff = (1.60218e-19 * B**2 * (5.29177e-11)**2 / (8 * 9.10938e-31)) * 1e3  # meV
102    qz_3p_pm1 = coeff * 180 * 4/5      # n=3,l=1,ml=±1: r2=180, sin2=4/5
103    qz_3d_ml2 = coeff * 126 * 6/7      # n=3,l=2,ml=±2: r2=126, sin2=6/7
104    qz_2s     = coeff * 42  * 2/3      # n=2,l=0,ml=0
105    qz_2p_pm1 = coeff * 30  * 4/5      # n=2,l=1,ml=±1
106
107    wing_sigp_meV  = zeeman_meV + (qz_3p_pm1 - qz_2s)
108    wing_sigm_meV  = -zeeman_meV + (qz_3p_pm1 - qz_2s)
109    main_sigp_meV  = zeeman_meV + (qz_3d_ml2 - qz_2p_pm1)
110    main_sigm_meV  = -zeeman_meV + (qz_3d_ml2 - qz_2p_pm1)
111
112    for col, (label, (nq_key, yq_key), color) in enumerate(
113            zip(pol_labels, pol_keys, pol_colors)):
114        ax = axes[row, col]
115        nq = r[nq_key]
116        yq = r[yq_key]
117        peak = max(yq.max(), nq.max(), 1e-20)
118
119        ax.plot(det_meV, nq / peak, 'k--', lw=1.2, alpha=0.8, label='No QZ')
120        ax.plot(det_meV, yq / peak, color=color, lw=1.8, label='With QZ')
121
122        # Annotate expected wing positions
123        if col == 1:  # σ+
124            ax.axvline(wing_sigp_meV, color='orange', ls=':', lw=1.2,
125                       label=f'3p(ml=+1)→2s wing\n({wing_sigp_meV:.1f} meV)')
126            ax.axvline(main_sigp_meV, color='gray',   ls=':', lw=1.0,
127                       label=f'3d cluster edge\n({main_sigp_meV:.1f} meV)')
128        if col == 2:  # σ−
129            ax.axvline(wing_sigm_meV, color='orange', ls=':', lw=1.2,
130                       label=f'3p(ml=−1)→2s wing\n({wing_sigm_meV:.1f} meV)')
131            ax.axvline(main_sigm_meV, color='gray',   ls=':', lw=1.0,
132                       label=f'3d cluster edge\n({main_sigm_meV:.1f} meV)')
133
134        ax.set_xlabel('Detuning from $E_0$ (meV)', fontsize=10)
135        ax.set_ylabel('Normalized intensity', fontsize=9)
136        ax.set_title(f'B = {int(B)} T — {label}', fontsize=11)
137        ax.legend(fontsize=7.5, loc='upper right')
138        ax.grid(True, alpha=0.25)
139        ax.set_xlim(-100, 100)
140        ax.set_ylim(-0.02, None)
141
142plt.tight_layout()
143out = "halpha_wings.png"
144plt.savefig(out, dpi=200, bbox_inches='tight')
145print(f"\nSaved {out}")
146plt.show()

Result

Hα pi, sigma-plus, and sigma-minus components at B=500T and B=1000T with and without quadratic Zeeman, showing wing shoulders

π, σ+, σ− components at B = 500 T and B = 1000 T; solid = with quadratic Zeeman, dashed = without. The 3p→2s wing is resolved as a distinct shoulder at B = 1000 T.