lie_groups/representation/casimir.rs
1//! Casimir operators for Lie algebras.
2//!
3//! The Casimir operators are elements of the center of the universal enveloping
4//! algebra U(𝔤) that commute with all group generators. They provide crucial
5//! invariants for classifying irreducible representations.
6//!
7//! # Mathematical Background
8//!
9//! ## Quadratic Casimir Operator
10//!
11//! The **quadratic Casimir** C₂ is defined as:
12//! ```text
13//! C₂ = Σᵢ Tᵢ² (sum over orthonormal basis of 𝔤)
14//! ```
15//!
16//! **Key Property**: In any irreducible representation ρ:
17//! ```text
18//! ρ(C₂) = c₂(ρ) · I
19//! ```
20//! where c₂(ρ) is a scalar eigenvalue that labels the representation.
21//!
22//! ## Physical Interpretation
23//!
24//! For different Lie groups, C₂ has different physical meanings:
25//! - **SU(2)**: C₂ = J² (total angular momentum squared)
26//! - **SU(3)**: C₂ labels quark and gluon color representations
27//! - **Lorentz group**: C₂ and C₃ label particle mass and spin
28//!
29//! ## Higher Casimirs
30//!
31//! For Lie algebras of rank r (dimension of Cartan subalgebra),
32//! there are r independent Casimir operators:
33//! - Rank 1 (SU(2), SO(3)): only C₂
34//! - Rank 2 (SU(3), SO(5)): C₂ and C₃
35//! - Rank n (SU(n+1)): C₂, C₃, ..., C_{n+1}
36//!
37//! # Examples
38//!
39//! ## SU(2) Eigenvalues
40//!
41//! For spin-j representation:
42//! ```text
43//! c₂(j) = j(j+1)
44//!
45//! j = 0: c₂ = 0 (scalar)
46//! j = 1/2: c₂ = 3/4 (spinor)
47//! j = 1: c₂ = 2 (vector/adjoint)
48//! j = 3/2: c₂ = 15/4
49//! ```
50//!
51//! ## SU(3) Eigenvalues
52//!
53//! For representation (p,q):
54//! ```text
55//! c₂(p,q) = (1/3)(p² + q² + pq + 3p + 3q)
56//!
57//! (0,0): c₂ = 0 (trivial/singlet)
58//! (1,0): c₂ = 4/3 (fundamental/quark)
59//! (0,1): c₂ = 4/3 (antifundamental/antiquark)
60//! (1,1): c₂ = 3 (adjoint/gluon)
61//! ```
62//!
63//! # References
64//!
65//! - **Georgi**: "Lie Algebras in Particle Physics" (1999), Chapter 3
66//! - **Cahn**: "Semi-Simple Lie Algebras and Their Representations" (1984), Chapter 7
67//! - **Gilmore**: "Lie Groups, Lie Algebras, and Some of Their Applications" (1974)
68
69/// Casimir operators for Lie algebras.
70///
71/// This trait provides methods for computing eigenvalues of Casimir operators
72/// in different irreducible representations.
73///
74/// # Implementation Notes
75///
76/// For a Lie algebra 𝔤:
77/// 1. Implement `quadratic_casimir_eigenvalue()` using the standard formula
78/// 2. For rank > 1 algebras, optionally implement `higher_casimir_eigenvalues()`
79/// 3. Use exact rational arithmetic where possible (e.g., 4/3 not 1.333...)
80///
81/// # Type Safety
82///
83/// This trait is defined as a standalone trait (not requiring `LieAlgebra`)
84/// to allow flexible implementation strategies. Implementors should ensure
85/// they also implement `LieAlgebra`.
86pub trait Casimir {
87 /// Type representing irreducible representations of this algebra.
88 ///
89 /// # Examples
90 /// - SU(2): `Spin` (half-integer j)
91 /// - SU(3): `Su3Irrep` (Dynkin labels (p,q))
92 /// - SU(N): `YoungTableau` or `DynkinLabels`
93 type Representation;
94
95 /// Eigenvalue of the quadratic Casimir operator in a given irrep.
96 ///
97 /// For an irreducible representation ρ, this computes the scalar c₂(ρ)
98 /// such that ρ(C₂) = c₂(ρ) · I.
99 ///
100 /// # Arguments
101 ///
102 /// * `irrep` - The irreducible representation
103 ///
104 /// # Returns
105 ///
106 /// The eigenvalue c₂(ρ) as a real number.
107 ///
108 /// # Examples
109 ///
110 /// ```ignore
111 /// use lie_groups::{Su2Algebra, Casimir, Spin};
112 ///
113 /// // Spin-1/2 (spinor): c₂ = 3/4
114 /// let c2 = Su2Algebra::quadratic_casimir_eigenvalue(&Spin::HALF);
115 /// assert_eq!(c2, 0.75);
116 /// ```
117 fn quadratic_casimir_eigenvalue(irrep: &Self::Representation) -> f64;
118
119 /// Eigenvalues of higher Casimir operators (optional).
120 ///
121 /// For algebras of rank r > 1, there are r - 1 additional independent
122 /// Casimir operators beyond C₂.
123 ///
124 /// # Returns
125 ///
126 /// A vector of eigenvalues [c₃(ρ), c₄(ρ), ...] for the given irrep.
127 /// Default implementation returns empty vector (no higher Casimirs).
128 ///
129 /// # Examples
130 ///
131 /// For SU(3) with cubic Casimir C₃:
132 /// ```ignore
133 /// let higher = Su3Algebra::higher_casimir_eigenvalues(&irrep);
134 /// let c3 = higher[0]; // Cubic Casimir eigenvalue
135 /// ```
136 fn higher_casimir_eigenvalues(_irrep: &Self::Representation) -> Vec<f64> {
137 vec![]
138 }
139
140 /// Dimension of the Cartan subalgebra (rank of the algebra).
141 ///
142 /// This determines the number of independent Casimir operators:
143 /// - Rank 1: only C₂ (SU(2), SO(3))
144 /// - Rank 2: C₂ and C₃ (SU(3), SO(5))
145 /// - Rank n: C₂, ..., C_{n+1} (SU(n+1))
146 ///
147 /// # Returns
148 ///
149 /// The rank as a positive integer.
150 fn rank() -> usize;
151
152 /// Number of independent Casimir operators.
153 ///
154 /// This equals the rank of the algebra.
155 ///
156 /// # Returns
157 ///
158 /// The number of Casimirs (rank).
159 fn num_casimirs() -> usize {
160 Self::rank()
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167
168 // Placeholder test to ensure module compiles
169 #[test]
170 fn test_trait_compiles() {
171 // This test verifies that the Casimir trait is well-formed
172 // Actual tests are in the implementation modules (su2.rs, su3.rs)
173 }
174
175 /// Test the Casimir identity: ∑_a T^a · T^a = C(R) · I
176 ///
177 /// This is the fundamental identity relating Casimir eigenvalues to
178 /// the sum of squared generators. For a representation R of a Lie algebra:
179 /// ```text
180 /// ∑_a T^a_{ij} T^a_{jk} = C(R) δ_{ik}
181 /// ```
182 ///
183 /// where T^a are the generators in representation R and C(R) is the
184 /// quadratic Casimir eigenvalue.
185 ///
186 /// For SU(2) fundamental (j=1/2):
187 /// - Generators: T^a = σ^a/2 (Pauli matrices / 2)
188 /// - Casimir: C_{1/2} = j(j+1) = 3/4
189 /// - Identity: (σ^1/2)² + (σ^2/2)² + (σ^3/2)² = 3/4 · I
190 #[test]
191 fn test_casimir_identity_su2_fundamental() {
192 use crate::representation::Spin;
193 use crate::su2::Su2Algebra;
194 use ndarray::Array2;
195 use num_complex::Complex64;
196
197 // SU(2) generators in fundamental representation: T^a = σ^a/2
198 // Pauli matrices:
199 // σ^1 = [[0, 1], [1, 0]]
200 // σ^2 = [[0, -i], [i, 0]]
201 // σ^3 = [[1, 0], [0, -1]]
202
203 let sigma1: Array2<Complex64> = Array2::from_shape_vec(
204 (2, 2),
205 vec![
206 Complex64::new(0.0, 0.0),
207 Complex64::new(1.0, 0.0),
208 Complex64::new(1.0, 0.0),
209 Complex64::new(0.0, 0.0),
210 ],
211 )
212 .unwrap();
213
214 let sigma2: Array2<Complex64> = Array2::from_shape_vec(
215 (2, 2),
216 vec![
217 Complex64::new(0.0, 0.0),
218 Complex64::new(0.0, -1.0),
219 Complex64::new(0.0, 1.0),
220 Complex64::new(0.0, 0.0),
221 ],
222 )
223 .unwrap();
224
225 let sigma3: Array2<Complex64> = Array2::from_shape_vec(
226 (2, 2),
227 vec![
228 Complex64::new(1.0, 0.0),
229 Complex64::new(0.0, 0.0),
230 Complex64::new(0.0, 0.0),
231 Complex64::new(-1.0, 0.0),
232 ],
233 )
234 .unwrap();
235
236 // T^a = σ^a / 2
237 let t1 = &sigma1 / Complex64::new(2.0, 0.0);
238 let t2 = &sigma2 / Complex64::new(2.0, 0.0);
239 let t3 = &sigma3 / Complex64::new(2.0, 0.0);
240
241 // Compute ∑_a T^a · T^a
242 let casimir_sum = t1.dot(&t1) + t2.dot(&t2) + t3.dot(&t3);
243
244 // Expected: C_{1/2} · I = (3/4) · I
245 let expected_casimir = Su2Algebra::quadratic_casimir_eigenvalue(&Spin::HALF);
246 let expected_matrix: Array2<Complex64> =
247 Array2::eye(2) * Complex64::new(expected_casimir, 0.0);
248
249 // Verify the identity
250 for i in 0..2 {
251 for j in 0..2 {
252 let diff = (casimir_sum[[i, j]] - expected_matrix[[i, j]]).norm();
253 assert!(
254 diff < 1e-10,
255 "Casimir identity violated at ({},{}): got {}, expected {}",
256 i,
257 j,
258 casimir_sum[[i, j]],
259 expected_matrix[[i, j]]
260 );
261 }
262 }
263
264 // Also verify the Casimir value is 3/4
265 assert!(
266 (expected_casimir - 0.75).abs() < 1e-10,
267 "C_{{1/2}} should be 3/4"
268 );
269 }
270
271 /// Test Casimir identity for SU(2) adjoint representation (j=1).
272 ///
273 /// For the adjoint representation of SU(2):
274 /// - Dimension: 3 (same as dim(su(2)))
275 /// - Casimir: `C_1` = j(j+1) = 2
276 ///
277 /// The generators in the adjoint are related to structure constants.
278 /// Using the physics convention with (T^a)_{bc} = -i f^{abc} (antisymmetric),
279 /// we verify that ∑_a (T^a)_{bc} (T^a)_{cd} is proportional to δ_{bd}.
280 ///
281 /// # Convention Note
282 ///
283 /// The Levi-Civita contraction gives:
284 /// ∑_{a,c} ε_{abc} ε_{acd} = -2 δ_{bd}
285 ///
286 /// The factor of -2 (rather than +2) comes from the antisymmetric
287 /// (real) generator convention. The magnitude |C| = 2 matches the
288 /// formula `C_j` = j(j+1) = 2 for j=1.
289 #[test]
290 fn test_casimir_identity_su2_adjoint() {
291 use crate::representation::Spin;
292 use crate::su2::Su2Algebra;
293
294 // ε tensor (Levi-Civita symbol)
295 let epsilon = |a: usize, b: usize, c: usize| -> f64 {
296 if (a, b, c) == (0, 1, 2) || (a, b, c) == (1, 2, 0) || (a, b, c) == (2, 0, 1) {
297 1.0
298 } else if (a, b, c) == (0, 2, 1) || (a, b, c) == (2, 1, 0) || (a, b, c) == (1, 0, 2) {
299 -1.0
300 } else {
301 0.0
302 }
303 };
304
305 // Build adjoint generators: (t^a)_{bc} = ε_{abc}
306 let mut t_adj: [[[f64; 3]; 3]; 3] = [[[0.0; 3]; 3]; 3];
307 for a in 0..3 {
308 for b in 0..3 {
309 for c in 0..3 {
310 t_adj[a][b][c] = epsilon(a, b, c);
311 }
312 }
313 }
314
315 // Compute sum: (∑_a T^a T^a)_{bd} = ∑_a ∑_c T^a_{bc} T^a_{cd}
316 let mut casimir_sum = [[0.0; 3]; 3];
317 for b in 0..3 {
318 for d in 0..3 {
319 for a in 0..3 {
320 for c in 0..3 {
321 casimir_sum[b][d] += t_adj[a][b][c] * t_adj[a][c][d];
322 }
323 }
324 }
325 }
326
327 // Result: ∑_{a,c} ε_{abc} ε_{acd} = -2 δ_{bd}
328 // The magnitude matches C_adjoint = 2, sign is negative due to
329 // real antisymmetric generator convention.
330 let expected_casimir = Su2Algebra::quadratic_casimir_eigenvalue(&Spin::ONE);
331
332 for b in 0..3 {
333 for d in 0..3 {
334 // Note: sign is negative for real antisymmetric generators
335 let expected = if b == d { -expected_casimir } else { 0.0 };
336 let diff = (casimir_sum[b][d] - expected).abs();
337 assert!(
338 diff < 1e-10,
339 "Adjoint Casimir identity violated at ({},{}): got {}, expected {}",
340 b,
341 d,
342 casimir_sum[b][d],
343 expected
344 );
345 }
346 }
347
348 // Verify diagonal value is -2 (magnitude matches C_1 = 2)
349 assert!(
350 (casimir_sum[0][0].abs() - expected_casimir).abs() < 1e-10,
351 "|∑_a (T^a T^a)_{{00}}| should equal C_adjoint = 2"
352 );
353 }
354}