|
| 1 | +# This file defines Clebsch-Gordan tensors |
| 2 | +# one tensor is defined from 3 simple objects s1, s2 and s3 |
| 3 | +# and contains the coefficients fusing s1 ⊗ s2 -> s3 |
| 4 | + |
| 5 | +using HalfIntegers: half |
| 6 | +using WignerSymbols: clebschgordan |
| 7 | + |
| 8 | +using GradedUnitRanges: dual |
| 9 | +using SymmetrySectors: |
| 10 | + AbelianStyle, |
| 11 | + AbstractSector, |
| 12 | + NotAbelianStyle, |
| 13 | + SymmetryStyle, |
| 14 | + O2, |
| 15 | + SU, |
| 16 | + istrivial, |
| 17 | + quantum_dimension, |
| 18 | + sector_label, |
| 19 | + trivial, |
| 20 | + zero_odd |
| 21 | +using TensorAlgebra: contract |
| 22 | +using TensorProducts: ⊗ |
| 23 | + |
| 24 | +function symbol_1j(s::AbstractSector) |
| 25 | + cgt = clebsch_gordan_tensor(s, dual(s), trivial(s), 1) |
| 26 | + return sqrt(quantum_dimension(s)) * cgt[:, :, 1] |
| 27 | +end |
| 28 | + |
| 29 | +function clebsch_gordan_tensor( |
| 30 | + s1::AbstractSector, |
| 31 | + s2::AbstractSector, |
| 32 | + s3::AbstractSector, |
| 33 | + arrow1::Bool, |
| 34 | + arrow2::Bool, |
| 35 | + inner_mult_index::Int, |
| 36 | +) |
| 37 | + cgt = clebsch_gordan_tensor(s1, s2, s3, inner_mult_index) |
| 38 | + if arrow1 |
| 39 | + flip1 = symbol_1j(s1) |
| 40 | + cgt = contract((1, 2, 3), flip1, (4, 1), cgt, (4, 2, 3)) |
| 41 | + end |
| 42 | + if arrow2 |
| 43 | + flip2 = symbol_1j(s2) |
| 44 | + cgt = contract((1, 2, 3), flip2, (4, 2), cgt, (1, 4, 3)) |
| 45 | + end |
| 46 | + return cgt |
| 47 | +end |
| 48 | + |
| 49 | +function clebsch_gordan_tensor(s1::S, s2::S, s3::S, outer_mult_index::Int) where {S} |
| 50 | + return clebsch_gordan_tensor(SymmetryStyle(S), s1, s2, s3, outer_mult_index) |
| 51 | +end |
| 52 | + |
| 53 | +function clebsch_gordan_tensor( |
| 54 | + ::AbelianStyle, s1::S, s2::S, s3::S, outer_mult_index::Int |
| 55 | +) where {S} |
| 56 | + @assert outer_mult_index == 1 |
| 57 | + return s1 ⊗ s2 == s3 ? ones((1, 1, 1)) : zeros((1, 1, 1)) |
| 58 | +end |
| 59 | + |
| 60 | +function clebsch_gordan_tensor(::NotAbelianStyle, s1::O2, s2::O2, s3::O2, ::Int) |
| 61 | + return clebsch_gordan_tensor(s1, s2, s3) # no outer multiplicity |
| 62 | +end |
| 63 | + |
| 64 | +function clebsch_gordan_tensor(s1::O2, s2::O2, s3::O2) |
| 65 | + d1 = quantum_dimension(s1) |
| 66 | + d2 = quantum_dimension(s2) |
| 67 | + d3 = quantum_dimension(s3) |
| 68 | + cgt = zeros((d1, d2, d3)) |
| 69 | + s3 ∉ blocklabels(s1 ⊗ s2) && return cgt |
| 70 | + |
| 71 | + # adapted from TensorKit |
| 72 | + l1 = sector_label(s1) |
| 73 | + l2 = sector_label(s2) |
| 74 | + l3 = sector_label(s3) |
| 75 | + if l3 <= 0 # 0even or 0odd |
| 76 | + if l1 <= 0 && l2 <= 0 |
| 77 | + cgt[1, 1, 1, 1] = 1.0 |
| 78 | + else |
| 79 | + if istrivial(s3) |
| 80 | + cgt[1, 2, 1, 1] = 1.0 / sqrt(2) |
| 81 | + cgt[2, 1, 1, 1] = 1.0 / sqrt(2) |
| 82 | + else |
| 83 | + cgt[1, 2, 1, 1] = 1.0 / sqrt(2) |
| 84 | + cgt[2, 1, 1, 1] = -1.0 / sqrt(2) |
| 85 | + end |
| 86 | + end |
| 87 | + elseif l1 <= 0 # 0even or 0odd |
| 88 | + cgt[1, 1, 1, 1] = 1.0 |
| 89 | + cgt[1, 2, 2, 1] = s1 == zero_odd(O2) ? -1.0 : 1.0 |
| 90 | + elseif l2 == 0 |
| 91 | + cgt[1, 1, 1, 1] = 1.0 |
| 92 | + cgt[2, 1, 2, 1] = s2 == zero_odd(O2) ? -1.0 : 1.0 |
| 93 | + elseif l3 == l1 + l2 |
| 94 | + cgt[1, 1, 1, 1] = 1.0 |
| 95 | + cgt[2, 2, 2, 1] = 1.0 |
| 96 | + elseif l3 == l1 - l2 |
| 97 | + cgt[1, 2, 1, 1] = 1.0 |
| 98 | + cgt[2, 1, 2, 1] = 1.0 |
| 99 | + elseif l3 == l2 - l1 |
| 100 | + cgt[2, 1, 1, 1] = 1.0 |
| 101 | + cgt[1, 2, 2, 1] = 1.0 |
| 102 | + end |
| 103 | + return cgt |
| 104 | +end |
| 105 | + |
| 106 | +function clebsch_gordan_tensor(::NotAbelianStyle, s1::SU{2}, s2::SU{2}, s3::SU{2}, ::Int) |
| 107 | + return clebsch_gordan_tensor(s1, s2, s3) # no outer multiplicity |
| 108 | +end |
| 109 | + |
| 110 | +function clebsch_gordan_tensor(s1::SU{2}, s2::SU{2}, s3::SU{2}) |
| 111 | + d1 = quantum_dimension(s1) |
| 112 | + d2 = quantum_dimension(s2) |
| 113 | + d3 = quantum_dimension(s3) |
| 114 | + j1 = half(d1 - 1) |
| 115 | + j2 = half(d2 - 1) |
| 116 | + j3 = half(d3 - 1) |
| 117 | + cgtensor = Array{Float64,3}(undef, (d1, d2, d3)) |
| 118 | + for (i, j, k) in Iterators.product(1:d1, 1:d2, 1:d3) |
| 119 | + m1 = j1 - i + 1 |
| 120 | + m2 = j2 - j + 1 |
| 121 | + m3 = j3 - k + 1 |
| 122 | + cgtensor[i, j, k] = clebschgordan(j1, m1, j2, m2, j3, m3) |
| 123 | + end |
| 124 | + return cgtensor |
| 125 | +end |
| 126 | + |
| 127 | +function clebsch_gordan_tensor( |
| 128 | + ::NotAbelianStyle, s1::SU{3}, s2::SU{3}, s3::SU{3}, outer_mult_index::Int |
| 129 | +) |
| 130 | + d1 = quantum_dimension(s1) |
| 131 | + d2 = quantum_dimension(s2) |
| 132 | + d3 = quantum_dimension(s3) |
| 133 | + cgtensor = zeros(d1, d2, d3) |
| 134 | + # dummy |
| 135 | + return cgtensor |
| 136 | +end |
0 commit comments