1use std::{ops::Neg, sync::LazyLock};
2
3use idenso::{color::CS, dirac::AGS, representations::initialize};
4
5use spenso::{
6 algebra::complex::Complex,
7 network::{
8 Network,
9 library::{
10 TensorLibraryData,
11 function_lib::{INBUILTS, PanicMissingConcrete, SymbolLib},
12 symbolic::{ExplicitKey, TensorLibrary},
13 },
14 parsing::ShadowedStructure,
15 store::NetworkStore,
16 },
17 structure::{PermutedStructure, TensorStructure, abstract_index::AbstractIndex, slot::AbsInd},
18 tensors::{
19 complex::RealOrComplexTensor,
20 data::{SetTensorData, SparseTensor, StorageTensor},
21 parametric::{MixedTensor, ParamOrConcrete},
22 },
23};
24use symbolica::{
25 atom::{Atom, Symbol},
26 parse_lit,
27};
28
29#[allow(clippy::similar_names)]
30pub fn gamma_data_dirac<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
31where
32 T: Clone + Neg<Output = T>,
33 N: TensorStructure,
34{
35 let c1 = Complex::<T>::new(one.clone(), zero.clone());
36 let z = Complex::<T>::new(zero.clone(), zero.clone());
37 let cn1 = Complex::<T>::new(-one.clone(), zero.clone());
38 let ci = Complex::<T>::new(zero.clone(), one.clone());
39 let cni = Complex::<T>::new(zero.clone(), -one.clone());
40 let mut gamma = SparseTensor::empty(structure, z);
41 gamma.set(&[0, 0, 0], c1.clone()).unwrap();
46 gamma.set(&[0, 1, 1], c1.clone()).unwrap();
47 gamma.set(&[0, 2, 2], cn1.clone()).unwrap();
48 gamma.set(&[0, 3, 3], cn1.clone()).unwrap();
49
50 gamma.set(&[1, 0, 3], c1.clone()).unwrap();
51 gamma.set(&[1, 1, 2], c1.clone()).unwrap();
52 gamma.set(&[1, 2, 1], cn1.clone()).unwrap();
53 gamma.set(&[1, 3, 0], cn1.clone()).unwrap();
54
55 gamma.set(&[2, 0, 3], cni.clone()).unwrap();
56 gamma.set(&[2, 1, 2], ci.clone()).unwrap();
57 gamma.set(&[2, 2, 1], ci.clone()).unwrap();
58 gamma.set(&[2, 3, 0], cni.clone()).unwrap();
59
60 gamma.set(&[3, 0, 2], c1.clone()).unwrap();
61 gamma.set(&[3, 1, 3], cn1.clone()).unwrap();
62 gamma.set(&[3, 2, 0], cn1.clone()).unwrap();
63 gamma.set(&[3, 3, 1], c1.clone()).unwrap();
64
65 gamma }
67
68#[allow(clippy::similar_names)]
69pub fn gamma_data_weyl<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
70where
71 T: Neg<Output = T> + Clone,
72 N: TensorStructure,
73{
74 let z = Complex::<T>::new(zero.clone(), zero.clone());
75 let c1 = Complex::<T>::new(one.clone(), zero.clone());
76 let cn1 = Complex::<T>::new(-one.clone(), zero.clone());
77 let ci = Complex::<T>::new(zero.clone(), one.clone());
78 let cni = Complex::<T>::new(zero.clone(), -one.clone());
79 let mut gamma = SparseTensor::empty(structure, z);
80 gamma.set(&[0, 2, 0], c1.clone()).unwrap();
85 gamma.set(&[1, 3, 0], c1.clone()).unwrap();
86 gamma.set(&[2, 0, 0], c1.clone()).unwrap();
87 gamma.set(&[3, 1, 0], c1.clone()).unwrap();
88
89 gamma.set(&[0, 3, 1], c1.clone()).unwrap();
90 gamma.set(&[1, 2, 1], c1.clone()).unwrap();
91 gamma.set(&[2, 1, 1], cn1.clone()).unwrap();
92 gamma.set(&[3, 0, 1], cn1.clone()).unwrap();
93
94 gamma.set(&[0, 3, 2], cni.clone()).unwrap();
95 gamma.set(&[1, 2, 2], ci.clone()).unwrap();
96 gamma.set(&[2, 1, 2], ci.clone()).unwrap();
97 gamma.set(&[3, 0, 2], cni.clone()).unwrap();
98
99 gamma.set(&[0, 2, 3], c1.clone()).unwrap();
100 gamma.set(&[1, 3, 3], cn1.clone()).unwrap();
101 gamma.set(&[2, 0, 3], cn1.clone()).unwrap();
102 gamma.set(&[3, 1, 3], c1.clone()).unwrap();
103
104 gamma }
106
107#[allow(clippy::similar_names)]
108pub fn gamma_transpose_weyl<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
109where
110 T: Neg<Output = T> + Clone,
111 N: TensorStructure,
112{
113 let z = Complex::<T>::new(zero.clone(), zero.clone());
114 let c1 = Complex::<T>::new(one.clone(), zero.clone());
115 let cn1 = Complex::<T>::new(-one.clone(), zero.clone());
116 let ci = Complex::<T>::new(zero.clone(), one.clone());
117 let cni = Complex::<T>::new(zero.clone(), -one.clone());
118 let mut gamma = SparseTensor::empty(structure, z);
119 gamma.set(&[2, 0, 0], c1.clone()).unwrap();
124 gamma.set(&[3, 1, 0], c1.clone()).unwrap();
125 gamma.set(&[0, 2, 0], c1.clone()).unwrap();
126 gamma.set(&[1, 3, 0], c1.clone()).unwrap();
127
128 gamma.set(&[3, 0, 1], c1.clone()).unwrap();
129 gamma.set(&[2, 1, 1], c1.clone()).unwrap();
130 gamma.set(&[1, 2, 1], cn1.clone()).unwrap();
131 gamma.set(&[0, 3, 1], cn1.clone()).unwrap();
132
133 gamma.set(&[3, 0, 2], cni.clone()).unwrap();
134 gamma.set(&[2, 1, 2], ci.clone()).unwrap();
135 gamma.set(&[1, 2, 2], ci.clone()).unwrap();
136 gamma.set(&[0, 3, 2], cni.clone()).unwrap();
137
138 gamma.set(&[2, 0, 3], c1.clone()).unwrap();
139 gamma.set(&[3, 1, 3], cn1.clone()).unwrap();
140 gamma.set(&[0, 2, 3], cn1.clone()).unwrap();
141 gamma.set(&[1, 3, 3], c1.clone()).unwrap();
142
143 gamma }
145
146#[allow(clippy::similar_names)]
147pub fn gamma_conj_data_weyl<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
148where
149 T: Neg<Output = T> + Clone,
150 N: TensorStructure,
151{
152 gamma_data_weyl(structure, one, zero).map_data(|a| {
153 let Complex { re, im } = a;
154 Complex { re, im: -im }
155 })
156}
157
158#[allow(clippy::similar_names)]
159pub fn gamma_adj_data_weyl<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
160where
161 T: Neg<Output = T> + Clone,
162 N: TensorStructure,
163{
164 gamma_transpose_weyl(structure, one, zero).map_data(|a| {
165 let Complex { re, im } = a;
166 Complex { re, im: -im }
167 })
168}
169
170pub fn gamma0_weyl<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
171where
172 T: Clone,
173 N: TensorStructure,
174{
175 let c1 = Complex::<T>::new(one, zero.clone());
176 let z = Complex::<T>::new(zero.clone(), zero.clone());
177 let mut gamma0 = SparseTensor::empty(structure, z);
178 gamma0.set(&[0, 2], c1.clone()).unwrap();
183 gamma0.set(&[1, 3], c1.clone()).unwrap();
184 gamma0.set(&[2, 0], c1.clone()).unwrap();
185 gamma0.set(&[3, 1], c1.clone()).unwrap();
186
187 gamma0
188}
189
190pub fn gamma5_dirac_data<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
191where
192 T: Clone,
193 N: TensorStructure,
194{
195 let c1 = Complex::<T>::new(one, zero.clone());
196
197 let z = Complex::<T>::new(zero.clone(), zero.clone());
198 let mut gamma5 = SparseTensor::empty(structure, z);
199
200 gamma5.set(&[0, 2], c1.clone()).unwrap();
201 gamma5.set(&[1, 3], c1.clone()).unwrap();
202 gamma5.set(&[2, 0], c1.clone()).unwrap();
203 gamma5.set(&[3, 1], c1.clone()).unwrap();
204
205 gamma5
206}
207
208pub fn gamma5_weyl_data<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
209where
210 T: Clone + Neg<Output = T>,
211 N: TensorStructure,
212{
213 let z = Complex::<T>::new(zero.clone(), zero.clone());
214 let c1 = Complex::<T>::new(one, zero);
215
216 let mut gamma5 = SparseTensor::empty(structure, z);
217
218 gamma5.set(&[0, 0], -c1.clone()).unwrap();
219 gamma5.set(&[1, 1], -c1.clone()).unwrap();
220 gamma5.set(&[2, 2], c1.clone()).unwrap();
221 gamma5.set(&[3, 3], c1.clone()).unwrap();
222
223 gamma5
224}
225
226#[allow(clippy::similar_names)]
227pub fn proj_m_data_dirac<T, N>(structure: N, half: T, zero: T) -> SparseTensor<Complex<T>, N>
228where
229 T: Clone + Neg<Output = T>,
230 N: TensorStructure,
231{
232 let z = Complex::<T>::new(zero.clone(), zero.clone());
233 let chalf = Complex::<T>::new(half.clone(), zero.clone());
236 let cnhalf = Complex::<T>::new(-half, zero);
237
238 let mut proj_m = SparseTensor::empty(structure, z);
239
240 proj_m.set(&[0, 0], chalf.clone()).unwrap();
241 proj_m.set(&[1, 1], chalf.clone()).unwrap();
242 proj_m.set(&[2, 2], chalf.clone()).unwrap();
243 proj_m.set(&[3, 3], chalf.clone()).unwrap();
244
245 proj_m.set(&[0, 2], cnhalf.clone()).unwrap();
246 proj_m.set(&[1, 3], cnhalf.clone()).unwrap();
247 proj_m.set(&[2, 0], cnhalf.clone()).unwrap();
248 proj_m.set(&[3, 1], cnhalf.clone()).unwrap();
249
250 proj_m
251}
252
253#[allow(clippy::similar_names)]
254pub fn proj_m_data_weyl<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
255where
256 T: Clone,
257 N: TensorStructure,
258{
259 let z = Complex::<T>::new(zero.clone(), zero.clone());
260 let c1 = Complex::<T>::new(one, zero);
262 let mut proj_m = SparseTensor::empty(structure, z);
263
264 proj_m.set(&[0, 0], c1.clone()).unwrap();
265 proj_m.set(&[1, 1], c1.clone()).unwrap();
266
267 proj_m
268}
269
270pub fn proj_p_data_dirac<T, N>(structure: N, half: T, zero: T) -> SparseTensor<Complex<T>, N>
271where
272 T: Clone,
273 N: TensorStructure,
274{
275 let z = Complex::<T>::new(zero.clone(), zero.clone());
276 let chalf = Complex::<T>::new(half, zero);
278
279 let mut proj_p = SparseTensor::empty(structure, z);
280
281 proj_p
282 .set(&[0, 0], chalf.clone())
283 .unwrap_or_else(|_| unreachable!());
284 proj_p
285 .set(&[1, 1], chalf.clone())
286 .unwrap_or_else(|_| unreachable!());
287 proj_p
288 .set(&[2, 2], chalf.clone())
289 .unwrap_or_else(|_| unreachable!());
290 proj_p
291 .set(&[3, 3], chalf.clone())
292 .unwrap_or_else(|_| unreachable!());
293
294 proj_p
295 .set(&[0, 2], chalf.clone())
296 .unwrap_or_else(|_| unreachable!());
297 proj_p
298 .set(&[1, 3], chalf.clone())
299 .unwrap_or_else(|_| unreachable!());
300 proj_p
301 .set(&[2, 0], chalf.clone())
302 .unwrap_or_else(|_| unreachable!());
303 proj_p
304 .set(&[3, 1], chalf.clone())
305 .unwrap_or_else(|_| unreachable!());
306
307 proj_p
308}
309
310#[allow(clippy::similar_names)]
311pub fn proj_p_data_weyl<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
312where
313 T: Clone,
314 N: TensorStructure,
315{
316 let z = Complex::<T>::new(zero.clone(), zero.clone());
317 let c1 = Complex::<T>::new(one, zero);
319 let mut proj_p = SparseTensor::empty(structure, z);
320
321 proj_p.set(&[2, 2], c1.clone()).unwrap();
322 proj_p.set(&[3, 3], c1.clone()).unwrap();
323
324 proj_p
325}
326
327pub fn su3_generator_data<N>(structure: N) -> SparseTensor<Complex<f64>, N>
331where
332 N: TensorStructure,
333{
334 let z = Complex::new(0., 0.);
335 let mut t = SparseTensor::empty(structure, z);
336 let h = 0.5;
337 let s = 1. / (2. * 3_f64.sqrt());
338
339 t.set(&[0, 0, 1], Complex::new(h, 0.)).unwrap();
340 t.set(&[0, 1, 0], Complex::new(h, 0.)).unwrap();
341
342 t.set(&[1, 0, 1], Complex::new(0., -h)).unwrap();
343 t.set(&[1, 1, 0], Complex::new(0., h)).unwrap();
344
345 t.set(&[2, 0, 0], Complex::new(h, 0.)).unwrap();
346 t.set(&[2, 1, 1], Complex::new(-h, 0.)).unwrap();
347
348 t.set(&[3, 0, 2], Complex::new(h, 0.)).unwrap();
349 t.set(&[3, 2, 0], Complex::new(h, 0.)).unwrap();
350
351 t.set(&[4, 0, 2], Complex::new(0., -h)).unwrap();
352 t.set(&[4, 2, 0], Complex::new(0., h)).unwrap();
353
354 t.set(&[5, 1, 2], Complex::new(h, 0.)).unwrap();
355 t.set(&[5, 2, 1], Complex::new(h, 0.)).unwrap();
356
357 t.set(&[6, 1, 2], Complex::new(0., -h)).unwrap();
358 t.set(&[6, 2, 1], Complex::new(0., h)).unwrap();
359
360 t.set(&[7, 0, 0], Complex::new(s, 0.)).unwrap();
361 t.set(&[7, 1, 1], Complex::new(s, 0.)).unwrap();
362 t.set(&[7, 2, 2], Complex::new(-2. * s, 0.)).unwrap();
363
364 t
365}
366
367pub fn su3_structure_f_data<N>(structure: N) -> SparseTensor<f64, N>
369where
370 N: TensorStructure,
371{
372 let mut f = SparseTensor::empty(structure, 0.);
373
374 fn set_antisymmetric<N>(f: &mut SparseTensor<f64, N>, a: usize, b: usize, c: usize, value: f64)
375 where
376 N: TensorStructure,
377 {
378 f.set(&[a, b, c], value).unwrap();
379 f.set(&[b, c, a], value).unwrap();
380 f.set(&[c, a, b], value).unwrap();
381 f.set(&[b, a, c], -value).unwrap();
382 f.set(&[a, c, b], -value).unwrap();
383 f.set(&[c, b, a], -value).unwrap();
384 }
385
386 set_antisymmetric(&mut f, 0, 1, 2, 1.);
387 set_antisymmetric(&mut f, 0, 3, 6, 0.5);
388 set_antisymmetric(&mut f, 0, 4, 5, -0.5);
389 set_antisymmetric(&mut f, 1, 3, 5, 0.5);
390 set_antisymmetric(&mut f, 1, 4, 6, 0.5);
391 set_antisymmetric(&mut f, 2, 3, 4, 0.5);
392 set_antisymmetric(&mut f, 2, 5, 6, -0.5);
393 set_antisymmetric(&mut f, 3, 4, 7, 3_f64.sqrt() / 2.);
394 set_antisymmetric(&mut f, 5, 6, 7, 3_f64.sqrt() / 2.);
395
396 f
397}
398
399pub fn su3_generator_data_atom<N>(structure: N) -> SparseTensor<Atom, N>
401where
402 N: TensorStructure,
403{
404 let mut t = SparseTensor::empty(structure, Atom::Zero);
405 let half = Atom::num(1) / Atom::num(2);
406 let sqrt3 = parse_lit!(sqrt(3));
407 let t8 = sqrt3.clone() / Atom::num(6);
408
409 t.set(&[0, 0, 1], half.clone()).unwrap();
410 t.set(&[0, 1, 0], half.clone()).unwrap();
411
412 t.set(&[1, 0, 1], -Atom::i() * half.clone()).unwrap();
413 t.set(&[1, 1, 0], Atom::i() * half.clone()).unwrap();
414
415 t.set(&[2, 0, 0], half.clone()).unwrap();
416 t.set(&[2, 1, 1], -half.clone()).unwrap();
417
418 t.set(&[3, 0, 2], half.clone()).unwrap();
419 t.set(&[3, 2, 0], half.clone()).unwrap();
420
421 t.set(&[4, 0, 2], -Atom::i() * half.clone()).unwrap();
422 t.set(&[4, 2, 0], Atom::i() * half.clone()).unwrap();
423
424 t.set(&[5, 1, 2], half.clone()).unwrap();
425 t.set(&[5, 2, 1], half.clone()).unwrap();
426
427 t.set(&[6, 1, 2], -Atom::i() * half).unwrap();
428 t.set(&[6, 2, 1], Atom::i() / Atom::num(2)).unwrap();
429
430 t.set(&[7, 0, 0], t8.clone()).unwrap();
431 t.set(&[7, 1, 1], t8.clone()).unwrap();
432 t.set(&[7, 2, 2], -sqrt3 / Atom::num(3)).unwrap();
433
434 t
435}
436
437pub fn su3_structure_f_data_atom<N>(structure: N) -> SparseTensor<Atom, N>
439where
440 N: TensorStructure,
441{
442 let mut f = SparseTensor::empty(structure, Atom::Zero);
443
444 fn set_antisymmetric<N>(
445 f: &mut SparseTensor<Atom, N>,
446 a: usize,
447 b: usize,
448 c: usize,
449 value: Atom,
450 ) where
451 N: TensorStructure,
452 {
453 f.set(&[a, b, c], value.clone()).unwrap();
454 f.set(&[b, c, a], value.clone()).unwrap();
455 f.set(&[c, a, b], value.clone()).unwrap();
456 f.set(&[b, a, c], -value.clone()).unwrap();
457 f.set(&[a, c, b], -value.clone()).unwrap();
458 f.set(&[c, b, a], -value).unwrap();
459 }
460
461 let half = Atom::num(1) / Atom::num(2);
462 let sqrt3_half = parse_lit!(sqrt(3)) / Atom::num(2);
463
464 set_antisymmetric(&mut f, 0, 1, 2, Atom::num(1));
465 set_antisymmetric(&mut f, 0, 3, 6, half.clone());
466 set_antisymmetric(&mut f, 0, 4, 5, -half.clone());
467 set_antisymmetric(&mut f, 1, 3, 5, half.clone());
468 set_antisymmetric(&mut f, 1, 4, 6, half.clone());
469 set_antisymmetric(&mut f, 2, 3, 4, half.clone());
470 set_antisymmetric(&mut f, 2, 5, 6, -half);
471 set_antisymmetric(&mut f, 3, 4, 7, sqrt3_half.clone());
472 set_antisymmetric(&mut f, 5, 6, 7, sqrt3_half);
473
474 f
475}
476
477#[allow(clippy::similar_names)]
478pub fn sigma_data<T, N>(structure: N, one: T, zero: T) -> SparseTensor<Complex<T>, N>
479where
480 T: Clone + Neg<Output = T>,
481 N: TensorStructure,
482{
483 let z = Complex::<T>::new(zero.clone(), zero.clone());
484 let c1 = Complex::<T>::new(one.clone(), zero.clone());
485 let cn1 = Complex::<T>::new(-one.clone(), zero.clone());
486 let ci = Complex::<T>::new(zero.clone(), one.clone());
487 let cni = Complex::<T>::new(zero.clone(), -one.clone());
488
489 let mut sigma = SparseTensor::empty(structure, z);
490 sigma.set(&[0, 2, 0, 1], c1.clone()).unwrap();
491 sigma.set(&[0, 2, 3, 0], c1.clone()).unwrap();
492 sigma.set(&[0, 3, 1, 2], c1.clone()).unwrap();
493 sigma.set(&[1, 0, 2, 2], c1.clone()).unwrap();
494 sigma.set(&[1, 1, 1, 2], c1.clone()).unwrap();
495 sigma.set(&[1, 3, 0, 2], c1.clone()).unwrap();
496 sigma.set(&[2, 2, 1, 0], c1.clone()).unwrap();
497 sigma.set(&[2, 2, 2, 1], c1.clone()).unwrap();
498 sigma.set(&[2, 3, 3, 2], c1.clone()).unwrap();
499 sigma.set(&[3, 0, 0, 2], c1.clone()).unwrap();
500 sigma.set(&[3, 3, 2, 2], c1.clone()).unwrap();
501 sigma.set(&[3, 1, 3, 2], c1.clone()).unwrap();
502 sigma.set(&[0, 1, 3, 0], ci.clone()).unwrap();
503 sigma.set(&[0, 3, 1, 1], ci.clone()).unwrap();
504 sigma.set(&[0, 3, 2, 0], ci.clone()).unwrap();
505 sigma.set(&[1, 0, 3, 3], ci.clone()).unwrap();
506 sigma.set(&[1, 1, 0, 3], ci.clone()).unwrap();
507 sigma.set(&[1, 1, 2, 0], ci.clone()).unwrap();
508 sigma.set(&[2, 1, 1, 0], ci.clone()).unwrap();
509 sigma.set(&[2, 3, 0, 0], ci.clone()).unwrap();
510 sigma.set(&[2, 3, 3, 1], ci.clone()).unwrap();
511 sigma.set(&[3, 0, 1, 3], ci.clone()).unwrap();
512 sigma.set(&[3, 1, 0, 0], ci.clone()).unwrap();
513 sigma.set(&[3, 1, 2, 3], ci.clone()).unwrap();
514 sigma.set(&[0, 0, 3, 2], cn1.clone()).unwrap();
515 sigma.set(&[0, 1, 0, 2], cn1.clone()).unwrap();
516 sigma.set(&[0, 2, 1, 3], cn1.clone()).unwrap();
517 sigma.set(&[1, 2, 0, 3], cn1.clone()).unwrap();
518 sigma.set(&[1, 2, 1, 1], cn1.clone()).unwrap();
519 sigma.set(&[1, 2, 2, 0], cn1.clone()).unwrap();
520 sigma.set(&[2, 0, 1, 2], cn1.clone()).unwrap();
521 sigma.set(&[2, 1, 2, 2], cn1.clone()).unwrap();
522 sigma.set(&[2, 2, 3, 3], cn1.clone()).unwrap();
523 sigma.set(&[3, 2, 0, 0], cn1.clone()).unwrap();
524 sigma.set(&[3, 2, 2, 3], cn1.clone()).unwrap();
525 sigma.set(&[3, 2, 3, 1], cn1.clone()).unwrap();
526 sigma.set(&[0, 0, 2, 3], cni.clone()).unwrap();
527 sigma.set(&[0, 0, 3, 1], cni.clone()).unwrap();
528 sigma.set(&[0, 1, 1, 3], cni.clone()).unwrap();
529 sigma.set(&[1, 0, 2, 1], cni.clone()).unwrap();
530 sigma.set(&[1, 3, 0, 1], cni.clone()).unwrap();
531 sigma.set(&[1, 3, 3, 0], cni.clone()).unwrap();
532 sigma.set(&[2, 0, 0, 3], cni.clone()).unwrap();
533 sigma.set(&[2, 0, 1, 1], cni.clone()).unwrap();
534 sigma.set(&[2, 1, 3, 3], cni.clone()).unwrap();
535 sigma.set(&[3, 0, 0, 1], cni.clone()).unwrap();
536 sigma.set(&[3, 3, 1, 0], cni.clone()).unwrap();
537 sigma.set(&[3, 3, 2, 1], cni.clone()).unwrap();
538
539 sigma
540}
541
542pub fn hep_lib<Aind: AbsInd, T: TensorLibraryData + Clone + Default>(
543 one: T,
544 zero: T,
545) -> TensorLibrary<MixedTensor<T, ExplicitKey<Aind>>, Aind>
546where
547{
548 let mut weyl = TensorLibrary::new();
549 initialize();
550 weyl.update_ids();
551
552 let gamma_key = PermutedStructure::identity(
553 gamma_data_weyl(AGS.gamma_strct::<Aind>(4), one.clone(), zero.clone()).into(),
554 );
555 weyl.insert_explicit(gamma_key);
557 let gamma_conj_key = PermutedStructure::identity(
558 gamma_conj_data_weyl(AGS.gamma_conj_strct::<Aind>(4), one.clone(), zero.clone()).into(),
559 );
560 weyl.insert_explicit(gamma_conj_key);
562 let gamma_adj_key = PermutedStructure::identity(
563 gamma_adj_data_weyl(AGS.gamma_adj_strct::<Aind>(4), one.clone(), zero.clone()).into(),
564 );
565 weyl.insert_explicit(gamma_adj_key);
567 let gamma0_key = PermutedStructure::identity(
568 gamma0_weyl(AGS.gamma0_strct::<Aind>(4), one.clone(), zero.clone()).into(),
569 );
570 weyl.insert_explicit(gamma0_key);
572
573 let gamma5_key = PermutedStructure::identity(
574 gamma5_weyl_data(AGS.gamma5_strct::<Aind>(4), one.clone(), zero.clone()).into(),
575 );
576 weyl.insert_explicit(gamma5_key);
577
578 let projm_key = PermutedStructure::identity(
579 proj_m_data_weyl(AGS.projm_strct::<Aind>(4), one.clone(), zero.clone()).into(),
580 );
581 weyl.insert_explicit(projm_key);
582
583 let projp_key = PermutedStructure::identity(
584 proj_p_data_weyl(AGS.projp_strct::<Aind>(4), one.clone(), zero.clone()).into(),
585 );
586 weyl.insert_explicit(projp_key);
587
588 weyl
589}
590
591pub fn insert_su3_color_tensors<Aind: AbsInd>(
592 lib: &mut TensorLibrary<MixedTensor<f64, ExplicitKey<Aind>>, Aind>,
593) {
594 initialize();
595
596 let t_key = PermutedStructure::identity(su3_generator_data(CS.t_strct::<Aind>(3, 8)).into());
597 lib.insert_explicit(t_key);
598
599 let f_key = PermutedStructure::identity(su3_structure_f_data(CS.f_strct::<Aind>(8)).into());
600 lib.insert_explicit(f_key);
601}
602
603pub fn hep_lib_su3<Aind: AbsInd>() -> TensorLibrary<MixedTensor<f64, ExplicitKey<Aind>>, Aind> {
604 let mut lib = hep_lib(1., 0.);
605 insert_su3_color_tensors(&mut lib);
606 lib
607}
608
609pub fn hep_lib_atom<Aind: AbsInd, T: TensorLibraryData + Clone + Default>()
610-> TensorLibrary<MixedTensor<T, ExplicitKey<Aind>>, Aind>
611where
612{
613 let mut weyl = TensorLibrary::new();
614 initialize();
615 weyl.update_ids();
616
617 let one = Atom::one();
618 let zero = Atom::Zero;
619
620 let gamma_key = PermutedStructure::identity(ParamOrConcrete::param(
621 gamma_data_weyl(AGS.gamma_strct::<Aind>(4), one.clone(), zero.clone())
622 .map_data(|a| a.re + a.im * Atom::i())
623 .into(),
624 ));
625 weyl.insert_explicit(gamma_key);
627 let gamma_conj_key = PermutedStructure::identity(ParamOrConcrete::param(
628 gamma_conj_data_weyl(AGS.gamma_conj_strct::<Aind>(4), one.clone(), zero.clone())
629 .map_data(|a| a.re + a.im * Atom::i())
630 .into(),
631 ));
632 weyl.insert_explicit(gamma_conj_key);
634 let gamma_adj_key = PermutedStructure::identity(ParamOrConcrete::param(
635 gamma_adj_data_weyl(AGS.gamma_adj_strct::<Aind>(4), one.clone(), zero.clone())
636 .map_data(|a| a.re + a.im * Atom::i())
637 .into(),
638 ));
639 weyl.insert_explicit(gamma_adj_key);
641 let gamma0_key = PermutedStructure::identity(ParamOrConcrete::param(
642 gamma0_weyl(AGS.gamma0_strct::<Aind>(4), one.clone(), zero.clone())
643 .map_data(|a| a.re + a.im * Atom::i())
644 .into(),
645 ));
646 weyl.insert_explicit(gamma0_key);
648
649 let gamma5_key = PermutedStructure::identity(ParamOrConcrete::param(
650 gamma5_weyl_data(AGS.gamma5_strct::<Aind>(4), one.clone(), zero.clone())
651 .map_data(|a| a.re + a.im * Atom::i())
652 .into(),
653 ));
654 weyl.insert_explicit(gamma5_key);
655
656 let projm_key = PermutedStructure::identity(ParamOrConcrete::param(
657 proj_m_data_weyl(AGS.projm_strct::<Aind>(4), one.clone(), zero.clone())
658 .map_data(|a| a.re + a.im * Atom::i())
659 .into(),
660 ));
661 weyl.insert_explicit(projm_key);
662
663 let projp_key = PermutedStructure::identity(ParamOrConcrete::param(
664 proj_p_data_weyl(AGS.projp_strct::<Aind>(4), one.clone(), zero.clone())
665 .map_data(|a| a.re + a.im * Atom::i())
666 .into(),
667 ));
668 weyl.insert_explicit(projp_key);
669
670 let color_t_key = PermutedStructure::identity(ParamOrConcrete::param(
671 su3_generator_data_atom(CS.t_strct::<Aind>(3, 8)).into(),
672 ));
673 weyl.insert_explicit(color_t_key);
674
675 let color_f_key = PermutedStructure::identity(ParamOrConcrete::param(
676 su3_structure_f_data_atom(CS.f_strct::<Aind>(8)).into(),
677 ));
678 weyl.insert_explicit(color_f_key);
679
680 weyl
681}
682
683pub type HepTensor<Aind> = MixedTensor<f64, ShadowedStructure<Aind>>;
684
685pub type HepNet<Aind> =
686 Network<NetworkStore<HepTensor<Aind>, Atom>, ExplicitKey<Aind>, Symbol, Aind>;
687
688pub static HEP_LIB: LazyLock<
689 TensorLibrary<MixedTensor<f64, ExplicitKey<AbstractIndex>>, AbstractIndex>,
690> = LazyLock::new(hep_lib_su3);
691
692pub static FUN_LIB: LazyLock<
693 SymbolLib<RealOrComplexTensor<f64, ShadowedStructure<AbstractIndex>>, PanicMissingConcrete>,
694> = LazyLock::new(|| {
695 let mut lib = PanicMissingConcrete::new_lib();
696 lib.insert(INBUILTS.conj, |a| match a {
697 RealOrComplexTensor::Complex(c) => RealOrComplexTensor::Complex(c.map_data(|x| x.conj())),
698 RealOrComplexTensor::Real(r) => RealOrComplexTensor::Real(r),
699 });
700 lib
701});
702
703#[cfg(test)]
704mod tests {
705
706 use spenso::{
707 network::{
708 Network, SingleSmallestDegree, SmallestDegreeIter, Steps,
709 parsing::{ParseSettings, ShadowedStructure, StrictTensorFilter},
710 store::NetworkStore,
711 },
712 structure::{HasStructure, abstract_index::AbstractIndex},
713 };
714 use symbolica::{
715 atom::{Atom, Symbol},
716 parse, parse_lit,
717 };
718
719 use super::*;
720
721 #[test]
722 fn simple_scalar() {
723 initialize();
724 let _a = HEP_LIB.get(&AGS.gamma_strct(4)).unwrap();
725
726 let expr = parse!("gamma(bis(4,l_5),bis(4,l_4),mink(4,l_4))*gamma(bis(4,l_6),bis(4,l_5),mink(4,l_4))*gamma(bis(4,l_4),bis(4,l_6),mink(4,l_5))*p(mink(4,l_5))
727 ",default_namespace="spenso");
728 let mut net = Network::<
736 NetworkStore<MixedTensor<f64, ShadowedStructure<AbstractIndex>>, Atom>,
737 _,
738 Symbol,
739 >::try_from_view(
740 expr.as_view(),
741 &*HEP_LIB,
742 &ParseSettings::default().with_strict_tensor_filter(StrictTensorFilter::ContainsReps),
743 )
744 .unwrap();
745
746 println!(
747 "{}",
748 net.dot_display_impl(
749 |a| a.to_string(),
750 |a| Some(format!("{}", a.global_name.unwrap())),
751 |a| a.structure().global_name.unwrap().to_string(),
752 |a| a.to_string()
753 )
754 );
755
756 net.execute::<Steps<1>, SmallestDegreeIter<1>, _, _, _>(&*HEP_LIB, &*FUN_LIB)
757 .unwrap();
758 println!(
759 "{}",
760 net.dot_display_impl(
761 |a| a.to_string(),
762 |a| Some(format!("{}", a.global_name?)),
763 |a| a
764 .structure()
765 .global_name
766 .map(|a| a.to_string())
767 .unwrap_or("".to_string()),
768 |a| a.to_string()
769 )
770 );
771 net.execute::<Steps<1>, SmallestDegreeIter<2>, _, _, _>(&*HEP_LIB, &*FUN_LIB)
772 .unwrap();
773 println!(
774 "{}",
775 net.dot_display_impl(
776 |a| a.to_string(),
777 |a| Some(format!("{}", a.global_name?)),
778 |a| a
779 .structure()
780 .global_name
781 .map(|a| a.to_string())
782 .unwrap_or("".to_string()),
783 |a| a.to_string()
784 )
785 );
786
787 println!(
788 "{}",
789 net.dot_display_impl(
790 |a| a.to_string(),
791 |_| None,
792 |a| a.to_string(),
793 |a| a.to_string()
794 )
795 );
796 }
805
806 #[test]
807 fn parse_problem() {
809 initialize();
810 let _a = HEP_LIB.get(&AGS.gamma_strct(4)).unwrap();
811
812 let expr = parse_lit!(
813 (-1 * G
814 ^ 3 * P(0, mink(4, 0))
815 * P(2, mink(4, 26))
816 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
817 * gamma(bis(4, 7), bis(4, 6), mink(4, 1))
818 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
819 + -1 * G
820 ^ 3 * P(0, mink(4, 26))
821 * P(1, mink(4, 1))
822 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
823 * gamma(bis(4, 7), bis(4, 6), mink(4, 0))
824 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
825 + -1 * G
826 ^ 3 * P(0, mink(4, 26))
827 * P(1, mink(4, 5))
828 * g(mink(4, 0), mink(4, 1))
829 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
830 * gamma(bis(4, 7), bis(4, 6), mink(4, 5))
831 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
832 + -1 * G
833 ^ 3 * P(0, mink(4, 5))
834 * P(2, mink(4, 26))
835 * g(mink(4, 0), mink(4, 1))
836 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
837 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
838 * gamma(bis(4, 7), bis(4, 6), mink(4, 5))
839 + -1 * G
840 ^ 3 * P(1, mink(4, 1))
841 * P(1, mink(4, 26))
842 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
843 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
844 * gamma(bis(4, 7), bis(4, 6), mink(4, 0))
845 + -1 * G
846 ^ 3 * P(1, mink(4, 26))
847 * P(1, mink(4, 5))
848 * g(mink(4, 0), mink(4, 1))
849 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
850 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
851 * gamma(bis(4, 7), bis(4, 6), mink(4, 5))
852 + -2 * G
853 ^ 3 * P(0, mink(4, 1))
854 * P(0, mink(4, 26))
855 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
856 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
857 * gamma(bis(4, 7), bis(4, 6), mink(4, 0))
858 + -2 * G
859 ^ 3 * P(0, mink(4, 1))
860 * P(1, mink(4, 26))
861 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
862 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
863 * gamma(bis(4, 7), bis(4, 6), mink(4, 0))
864 + -2 * G
865 ^ 3 * P(0, mink(4, 5))
866 * Q(0, mink(4, 5))
867 * g(mink(4, 0), mink(4, 1))
868 * gamma(bis(4, 3), bis(4, 2), mink(4, 4))
869 + -2 * G
870 ^ 3 * P(1, mink(4, 0))
871 * P(1, mink(4, 1))
872 * gamma(bis(4, 3), bis(4, 2), mink(4, 4))
873 + -2 * G
874 ^ 3 * P(1, mink(4, 0))
875 * P(2, mink(4, 26))
876 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
877 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
878 * gamma(bis(4, 7), bis(4, 6), mink(4, 1))
879 + -2 * G
880 ^ 3 * P(1, mink(4, 1))
881 * P(2, mink(4, 0))
882 * gamma(bis(4, 3), bis(4, 2), mink(4, 4))
883 + -2 * G
884 ^ 3 * P(1, mink(4, 5))
885 * P(2, mink(4, 5))
886 * g(mink(4, 0), mink(4, 1))
887 * gamma(bis(4, 3), bis(4, 2), mink(4, 4))
888 + -4 * G
889 ^ 3 * P(0, mink(4, 1))
890 * P(2, mink(4, 0))
891 * gamma(bis(4, 3), bis(4, 2), mink(4, 4))
892 + 2 * G
893 ^ 3 * P(0, mink(4, 0))
894 * P(0, mink(4, 1))
895 * gamma(bis(4, 3), bis(4, 2), mink(4, 4))
896 + 2 * G
897 ^ 3 * P(0, mink(4, 0))
898 * P(2, mink(4, 1))
899 * gamma(bis(4, 3), bis(4, 2), mink(4, 4))
900 + 2 * G
901 ^ 3 * P(0, mink(4, 1))
902 * P(2, mink(4, 26))
903 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
904 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
905 * gamma(bis(4, 7), bis(4, 6), mink(4, 0))
906 + 2 * G
907 ^ 3 * P(0, mink(4, 26))
908 * P(1, mink(4, 0))
909 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
910 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
911 * gamma(bis(4, 7), bis(4, 6), mink(4, 1))
912 + 2 * G
913 ^ 3 * P(0, mink(4, 5))
914 * P(2, mink(4, 5))
915 * g(mink(4, 0), mink(4, 1))
916 * gamma(bis(4, 3), bis(4, 2), mink(4, 4))
917 + 2 * G
918 ^ 3 * P(1, mink(4, 0))
919 * P(1, mink(4, 26))
920 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
921 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
922 * gamma(bis(4, 7), bis(4, 6), mink(4, 1))
923 + 2 * G
924 ^ 3 * P(1, mink(4, i))
925 ^ 2 * g(mink(4, 0), mink(4, 1)) * gamma(bis(4, 3), bis(4, 2), mink(4, 4)) + G
926 ^ 3 * P(1, mink(4, 1))
927 * P(2, mink(4, 26))
928 * gamma(bis(4, 3), bis(4, 7), mink(4, 4))
929 * gamma(bis(4, 6), bis(4, 2), mink(4, 26))
930 * gamma(bis(4, 7), bis(4, 6), mink(4, 0))),
931 default_namespace = "spenso"
932 );
933 let mut net = Network::<
936 NetworkStore<MixedTensor<f64, ShadowedStructure<AbstractIndex>>, Atom>,
937 _,
938 Symbol,
939 >::try_from_view(
940 expr.as_view(),
941 &*HEP_LIB,
942 &ParseSettings::default().with_strict_tensor_filter(StrictTensorFilter::ContainsReps),
943 )
944 .unwrap();
945
946 net.merge_ops();
947 println!(
948 "{}",
949 net.dot_display_impl(
950 |a| a.to_string(),
951 |a| Some(format!("{}", a.global_name.unwrap())),
952 |a| a.structure().global_name.unwrap().to_string(),
953 |a| a.to_string()
954 )
955 );
956
957 net.execute::<Steps<1>, SingleSmallestDegree<true>, _, _, _>(&*HEP_LIB, &(*FUN_LIB))
959 .unwrap();
960 println!(
997 "{}",
998 net.dot_display_impl(
999 |a| a.to_string(),
1000 |_| None,
1001 |a| a.structure().to_string().replace('\n', "\\n"),
1002 |a| a.to_string()
1003 )
1004 );
1005 }
1014
1015 #[test]
1016 fn transpose_test() {}
1017}