6#include <unordered_map>
7#include <unordered_set>
17template <
typename S1,
typename S2>
20template <
typename S1,
typename S2>
23 constexpr static int Nq = S1::Nq + S2::Nq;
35template <
typename S1_,
typename S2_>
46 static std::string
name() {
return S1_::name() +
"×" + S2_::name(); }
48 static constexpr std::size_t
Nq = S1_::Nq + S2_::Nq;
61 static constexpr bool ANY_NON_ABELIAN = S1::ANY_NON_ABELIAN or S2::ANY_NON_ABELIAN;
62 static constexpr bool ANY_ABELIAN = S1::ANY_ABELIAN or S2::ANY_ABELIAN;
63 static constexpr bool ANY_IS_TRIVIAL = S1::ANY_IS_TRIVIAL or S2::ANY_IS_TRIVIAL;
64 static constexpr bool ANY_IS_MODULAR = S1::ANY_IS_MODULAR or S2::ANY_IS_MODULAR;
66 static constexpr bool ANY_IS_BOSONIC = S1::ANY_IS_BOSONIC or S2::ANY_IS_BOSONIC;
67 static constexpr bool ANY_IS_SPIN = S1::ANY_IS_SPIN or S2::ANY_IS_SPIN;
70 static constexpr bool ALL_NON_ABELIAN = S1::ALL_NON_ABELIAN and S2::ALL_NON_ABELIAN;
71 static constexpr bool ALL_ABELIAN = S1::ALL_ABELIAN and S2::ALL_ABELIAN;
72 static constexpr bool ALL_IS_TRIVIAL = S1::ALL_IS_TRIVIAL and S2::ALL_IS_TRIVIAL;
73 static constexpr bool ALL_IS_MODULAR = S1::ALL_IS_MODULAR and S2::ALL_IS_MODULAR;
74 static constexpr bool ALL_IS_FERMIONIC = S1::ALL_IS_FERMIONIC and S2::ALL_IS_FERMIONIC;
75 static constexpr bool ALL_IS_BOSONIC = S1::ALL_IS_BOSONIC and S2::ALL_IS_BOSONIC;
76 static constexpr bool ALL_IS_SPIN = S1::ALL_IS_SPIN and S2::ALL_IS_SPIN;
78 static constexpr bool IS_CHARGE_SU2() {
return S1_::IS_CHARGE_SU2() or S2_::IS_CHARGE_SU2(); }
79 static constexpr bool IS_SPIN_SU2() {
return S1_::IS_SPIN_SU2() or S2_::IS_SPIN_SU2(); }
81 static constexpr bool IS_SPIN_U1() {
return S1_::IS_SPIN_U1() or S2_::IS_SPIN_U1(); }
83 static constexpr bool NO_SPIN_SYM() {
return S1_::NO_SPIN_SYM() and S2_::NO_SPIN_SYM(); }
84 static constexpr bool NO_CHARGE_SYM() {
return S1_::NO_CHARGE_SYM() and S2_::NO_CHARGE_SYM(); }
88 inline static constexpr std::array<KIND, Nq>
kind() {
return util::join(S1_::kind(), S2_::kind()); }
90 inline static constexpr qType qvacuum() {
return join(S1_::qvacuum(), S2_::qvacuum()); }
91 inline static constexpr std::array<
qType, S1::lowest_qs().size() * S2::lowest_qs().size()>
lowest_qs()
93 std::array<
qType, S1::lowest_qs().size() * S2::lowest_qs().size()> out;
95 for(
const auto& q1 : S1::lowest_qs())
96 for(
const auto& q2 : S2::lowest_qs()) {
97 out[index] =
join(q1, q2);
105 auto [ql, qr] = disjoin<S1_::Nq, S2_::Nq>(q);
106 return join(S1_::conj(ql), S2_::conj(qr));
111 auto [ql, qr] = disjoin<S1_::Nq, S2_::Nq>(q);
112 return S1_::degeneracy(ql) * S2_::degeneracy(qr);
126 auto [q1l, q1r] = disjoin<S1_::Nq, S2_::Nq>(q1);
127 auto [q2l, q2r] = disjoin<S1_::Nq, S2_::Nq>(q2);
128 auto [q3l, q3r] = disjoin<S1_::Nq, S2_::Nq>(q3);
129 return S1::multiplicity(q1l, q2l, q3l) * S2::multiplicity(q1r, q2r, q3r);
140 auto [ql, qr] = disjoin<S1::Nq, S2::Nq>(q);
141 return S1::coeff_twist(ql) * S2::coeff_twist(qr);
146 auto [ql, qr] = disjoin<S1_::Nq, S2_::Nq>(q);
147 return S1::coeff_FS(ql) * S2::coeff_FS(qr);
150 template <
typename PlainLib>
153 auto [ql, qr] = disjoin<S1_::Nq, S2_::Nq>(q);
155 auto Tl = S1::template one_j_tensor<PlainLib>(ql, world);
156 auto Tr = S2::template one_j_tensor<PlainLib>(qr, world);
164 template <
typename PlainLib>
168 auto [q1l, q1r] = disjoin<S1_::Nq, S2_::Nq>(q1);
169 auto [q2l, q2r] = disjoin<S1_::Nq, S2_::Nq>(q2);
170 auto [q3l, q3r] = disjoin<S1_::Nq, S2_::Nq>(q3);
172 auto Tl = S1::template CGC<PlainLib>(q1l, q2l, q3l, alpha, world);
173 auto Tr = S2::template CGC<PlainLib>(q1r, q2r, q3r, alpha, world);
179 auto [ql1, ql2] = disjoin<S1_::Nq, S2_::Nq>(ql);
180 auto [qr1, qr2] = disjoin<S1_::Nq, S2_::Nq>(qr);
181 auto [qf1, qf2] = disjoin<S1_::Nq, S2_::Nq>(qf);
182 return S1::coeff_turn(ql1, qr1, qf1) * S2::coeff_turn(ql2, qr2, qf2);
188 auto [q1l, q1r] = disjoin<S1_::Nq, S2_::Nq>(q1);
189 auto [q2l, q2r] = disjoin<S1_::Nq, S2_::Nq>(q2);
190 auto [q3l, q3r] = disjoin<S1_::Nq, S2_::Nq>(q3);
191 auto [Ql, Qr] = disjoin<S1_::Nq, S2_::Nq>(Q);
192 auto [Q12l, Q12r] = disjoin<S1_::Nq, S2_::Nq>(Q12);
193 auto [Q23l, Q23r] = disjoin<S1_::Nq, S2_::Nq>(Q23);
195 Scalar out = S1_::coeff_recouple(q1l, q2l, q3l, Ql, Q12l, Q23l) * S2_::coeff_recouple(q1r, q2r, q3r, Qr, Q12r, Q23r);
201 auto [ql1, ql2] = disjoin<S1_::Nq, S2_::Nq>(ql);
202 auto [qr1, qr2] = disjoin<S1_::Nq, S2_::Nq>(qr);
203 auto [qf1, qf2] = disjoin<S1_::Nq, S2_::Nq>(qf);
204 return S1::coeff_swap(ql1, qr1, qf1) * S2::coeff_swap(ql2, qr2, qf2);
220template <
typename S1_,
typename S2_>
223 auto [ql1, ql2] = disjoin<S1_::Nq, S2_::Nq>(ql);
224 auto [qr1, qr2] = disjoin<S1_::Nq, S2_::Nq>(qr);
225 std::vector<typename S1_::qType> firstSym = S1_::basis_combine(ql1, qr1);
226 std::vector<typename S2_::qType> secondSym = S2_::basis_combine(ql2, qr2);
228 std::vector<qType> vout;
229 for(
const auto& q1 : firstSym)
230 for(
const auto& q2 : secondSym) { vout.push_back(
join(q1, q2)); }
234template <
typename S1_,
typename S2_>
237 auto [q1l, q1r] = disjoin<S1_::Nq, S2_::Nq>(q1);
238 Scalar out = S1_::coeff_dot(q1l) * S2_::coeff_dot(q1r);
242template <
typename S1_,
typename S2_>
245 auto [q1l, q1r] = disjoin<S1_::Nq, S2_::Nq>(q1);
246 auto [q2l, q2r] = disjoin<S1_::Nq, S2_::Nq>(q2);
247 Scalar out = S1_::coeff_rightOrtho(q1l, q2l) * S2_::coeff_rightOrtho(q1r, q2r);
260template <
typename S1_,
typename S2_>
263 auto [q1l, q1r] = disjoin<S1_::Nq, S2_::Nq>(q1);
264 auto [q2l, q2r] = disjoin<S1_::Nq, S2_::Nq>(q2);
265 auto [q3l, q3r] = disjoin<S1_::Nq, S2_::Nq>(q3);
266 auto [q4l, q4r] = disjoin<S1_::Nq, S2_::Nq>(q4);
267 auto [q5l, q5r] = disjoin<S1_::Nq, S2_::Nq>(q5);
268 auto [q6l, q6r] = disjoin<S1_::Nq, S2_::Nq>(q6);
270 Scalar out = S1_::coeff_6j(q1l, q2l, q3l, q4l, q5l, q6l) * S2_::coeff_6j(q1r, q2r, q3r, q4r, q5r, q6r);
274template <
typename S1_,
typename S2_>
285 auto [q1l, q1r] = disjoin<S1_::Nq, S2_::Nq>(q1);
286 auto [q2l, q2r] = disjoin<S1_::Nq, S2_::Nq>(q2);
287 auto [q3l, q3r] = disjoin<S1_::Nq, S2_::Nq>(q3);
288 auto [q4l, q4r] = disjoin<S1_::Nq, S2_::Nq>(q4);
289 auto [q5l, q5r] = disjoin<S1_::Nq, S2_::Nq>(q5);
290 auto [q6l, q6r] = disjoin<S1_::Nq, S2_::Nq>(q6);
291 auto [q7l, q7r] = disjoin<S1_::Nq, S2_::Nq>(q7);
292 auto [q8l, q8r] = disjoin<S1_::Nq, S2_::Nq>(q8);
293 auto [q9l, q9r] = disjoin<S1_::Nq, S2_::Nq>(q9);
295 Scalar out = S1_::coeff_9j(q1l, q2l, q3l, q4l, q5l, q6l, q7l, q8l, q9l) * S2_::coeff_9j(q1r, q2r, q3r, q4r, q5r, q6r, q7r, q8r, q9r);
299template <
typename S1_,
typename S2_>
302 auto [q1l, q1r] = disjoin<S1_::Nq, S2_::Nq>(q1);
303 auto [q2l, q2r] = disjoin<S1_::Nq, S2_::Nq>(q2);
304 auto [q3l, q3r] = disjoin<S1_::Nq, S2_::Nq>(q3);
305 return (S1_::triangle(q1l, q2l, q3l) and S2_::triangle(q1r, q2r, q3r));
Definition: CombSym.hpp:8
XpedWorld & getUniverse()
Definition: Mpi.hpp:49
constexpr std::array< T, LL+RL > join(const std::array< T, LL > rhs, const std::array< T, RL > lhs, detail::num_tuple< LLs... >, detail::num_tuple< RLs... >)
Definition: JoinArray.hpp:41
constexpr qarray< Nq1+Nq2 > join(qarray< Nq1 > rhs, qarray< Nq2 > lhs)
Definition: qarray.hpp:147
CTF::Tensor< Scalar > TType
Definition: PlainInterface_Cyclops_impl.cpp:13
static constexpr bool ALL_NON_ABELIAN
Definition: S1xS2.hpp:70
static Scalar coeff_dot(const qType &q1)
Definition: S1xS2.hpp:235
static constexpr std::array< int, Nq > MOD_N
Definition: S1xS2.hpp:58
static constexpr bool ALL_IS_BOSONIC
Definition: S1xS2.hpp:75
S2_ S2
Definition: S1xS2.hpp:42
static constexpr bool IS_CHARGE_SU2()
Definition: S1xS2.hpp:78
static Scalar coeff_turn(const qType &ql, const qType &qr, const qType &qf)
Definition: S1xS2.hpp:177
qarray< Nq > qType
Definition: S1xS2.hpp:86
static constexpr bool ALL_IS_FERMIONIC
Definition: S1xS2.hpp:74
static Scalar coeff_swap(const qType &ql, const qType &qr, const qType &qf)
Definition: S1xS2.hpp:199
static std::size_t multiplicity(const qType &q1, const qType &q2, const qType &q3)
Definition: S1xS2.hpp:124
static Scalar coeff_9j(const qType &q1, const qType &q2, const qType &q3, const qType &q4, const qType &q5, const qType &q6, const qType &q7, const qType &q8, const qType &q9)
Definition: S1xS2.hpp:275
static constexpr std::array< bool, Nq > IS_TRIVIAL
Definition: S1xS2.hpp:53
static constexpr bool ANY_IS_SPIN
Definition: S1xS2.hpp:67
static constexpr bool NO_SPIN_SYM()
Definition: S1xS2.hpp:83
static constexpr bool ANY_IS_MODULAR
Definition: S1xS2.hpp:64
return PlainLib::tensorProd(Tl, Tr)
S1_::Scalar Scalar
Definition: S1xS2.hpp:39
static constexpr std::array< qType, S1::lowest_qs().size() *S2::lowest_qs().size()> lowest_qs()
Definition: S1xS2.hpp:91
static constexpr bool ALL_IS_SPIN
Definition: S1xS2.hpp:76
static constexpr bool ALL_ABELIAN
Definition: S1xS2.hpp:71
static Scalar coeff_3j(const qType &q1, const qType &q2, const qType &q3, int q1_z, int q2_z, int q3_z)
Definition: S1xS2.hpp:162
static constexpr bool NO_CHARGE_SYM()
Definition: S1xS2.hpp:84
static constexpr qType qvacuum()
Definition: S1xS2.hpp:90
static constexpr bool ALL_IS_TRIVIAL
Definition: S1xS2.hpp:72
static constexpr bool ALL_HAS_MULTIPLICITIES
Definition: S1xS2.hpp:69
static std::vector< qType > basis_combine(const qType &ql, const qType &qr)
Definition: S1xS2.hpp:221
static constexpr bool ANY_ABELIAN
Definition: S1xS2.hpp:62
static constexpr std::array< bool, Nq > NON_ABELIAN
Definition: S1xS2.hpp:51
static constexpr std::array< bool, Nq > ABELIAN
Definition: S1xS2.hpp:52
static qType random_q()
Definition: S1xS2.hpp:115
static bool triangle(const qType &q1, const qType &q2, const qType &q3)
Definition: S1xS2.hpp:300
static constexpr std::array< bool, Nq > IS_MODULAR
Definition: S1xS2.hpp:54
static constexpr bool IS_SPIN_U1()
Definition: S1xS2.hpp:81
static constexpr std::size_t Nq
Definition: S1xS2.hpp:48
static constexpr std::array< bool, Nq > HAS_MULTIPLICITIES
Definition: S1xS2.hpp:50
static constexpr bool ANY_NON_ABELIAN
Definition: S1xS2.hpp:61
static constexpr bool IS_SPIN_SU2()
Definition: S1xS2.hpp:79
static constexpr bool ANY_HAS_MULTIPLICITIES
Definition: S1xS2.hpp:60
static constexpr std::array< KIND, Nq > kind()
Definition: S1xS2.hpp:88
static constexpr bool ANY_IS_TRIVIAL
Definition: S1xS2.hpp:63
S1xS2()
Definition: S1xS2.hpp:44
static constexpr std::array< bool, Nq > IS_FERMIONIC
Definition: S1xS2.hpp:55
static Scalar coeff_rightOrtho(const qType &, const qType &)
Definition: S1xS2.hpp:243
static constexpr bool ANY_IS_BOSONIC
Definition: S1xS2.hpp:66
static Scalar coeff_6j(const qType &q1, const qType &q2, const qType &q3, const qType &q4, const qType &q5, const qType &q6)
Definition: S1xS2.hpp:261
static int degeneracy(const qType &q)
Definition: S1xS2.hpp:109
S1_ S1
Definition: S1xS2.hpp:41
auto Tl
Definition: S1xS2.hpp:172
auto Tr
Definition: S1xS2.hpp:173
static Scalar coeff_recouple(const qType &q1, const qType &q2, const qType &q3, const qType &Q, const qType &Q12, const qType &Q23)
Definition: S1xS2.hpp:186
static PlainLib::template TType< Scalar, 2 > one_j_tensor(const qType &q, mpi::XpedWorld &world=mpi::getUniverse())
Definition: S1xS2.hpp:151
static Scalar coeff_twist(const qType &q)
Definition: S1xS2.hpp:138
static qType conj(const qType &q)
Definition: S1xS2.hpp:103
static std::string name()
Definition: S1xS2.hpp:46
static constexpr std::array< bool, Nq > IS_BOSONIC
Definition: S1xS2.hpp:56
static constexpr bool ALL_IS_MODULAR
Definition: S1xS2.hpp:73
static Scalar coeff_FS(const qType &q)
Definition: S1xS2.hpp:144
static constexpr bool ANY_IS_FERMIONIC
Definition: S1xS2.hpp:65
static constexpr std::array< bool, Nq > IS_SPIN
Definition: S1xS2.hpp:57
Definition: SymBase.hpp:14
S1::Scalar Scalar
Definition: S1xS2.hpp:25
qarray< Nq > qType
Definition: S1xS2.hpp:24
Definition: SymBase.hpp:10
Definition: qarray.hpp:30