21 inline explicit DynamicSGroup() : m_numIndices(1), m_elements(), m_generators(), m_globalFlags(0) {
22 m_elements.push_back(ge(Generator(0, 0, 0)));
24 inline DynamicSGroup(
const DynamicSGroup& o)
25 : m_numIndices(o.m_numIndices),
26 m_elements(o.m_elements),
27 m_generators(o.m_generators),
28 m_globalFlags(o.m_globalFlags) {}
29 inline DynamicSGroup(DynamicSGroup&& o)
30 : m_numIndices(o.m_numIndices), m_elements(), m_generators(o.m_generators), m_globalFlags(o.m_globalFlags) {
31 std::swap(m_elements, o.m_elements);
33 inline DynamicSGroup& operator=(
const DynamicSGroup& o) {
34 m_numIndices = o.m_numIndices;
35 m_elements = o.m_elements;
36 m_generators = o.m_generators;
37 m_globalFlags = o.m_globalFlags;
40 inline DynamicSGroup& operator=(DynamicSGroup&& o) {
41 m_numIndices = o.m_numIndices;
42 std::swap(m_elements, o.m_elements);
43 m_generators = o.m_generators;
44 m_globalFlags = o.m_globalFlags;
48 void add(
int one,
int two,
int flags = 0);
50 template <
typename Gen_>
51 inline void add(Gen_) {
52 add(Gen_::One, Gen_::Two, Gen_::Flags);
54 inline void addSymmetry(
int one,
int two) { add(one, two, 0); }
55 inline void addAntiSymmetry(
int one,
int two) { add(one, two, NegationFlag); }
56 inline void addHermiticity(
int one,
int two) { add(one, two, ConjugationFlag); }
57 inline void addAntiHermiticity(
int one,
int two) { add(one, two, NegationFlag | ConjugationFlag); }
59 template <
typename Op,
typename RV,
typename Index, std::size_t N,
typename... Args>
60 inline RV apply(
const std::array<Index, N>& idx, RV initial, Args&&... args)
const {
61 eigen_assert(N >= m_numIndices &&
62 "Can only apply symmetry group to objects that have at least the required amount of indices.");
63 for (std::size_t i = 0; i < size(); i++)
64 initial = Op::run(h_permute(i, idx, std::make_integer_sequence<int, N>{}), m_elements[i].flags, initial,
65 std::forward<Args>(args)...);
69 template <
typename Op,
typename RV,
typename Index,
typename... Args>
70 inline RV apply(
const std::vector<Index>& idx, RV initial, Args&&... args)
const {
71 eigen_assert(idx.size() >= m_numIndices &&
72 "Can only apply symmetry group to objects that have at least the required amount of indices.");
73 for (std::size_t i = 0; i < size(); i++)
74 initial = Op::run(h_permute(i, idx), m_elements[i].flags, initial, std::forward<Args>(args)...);
78 inline int globalFlags()
const {
return m_globalFlags; }
79 inline std::size_t size()
const {
return m_elements.size(); }
81 template <
typename Tensor_,
typename... IndexTypes>
82 inline internal::tensor_symmetry_value_setter<Tensor_, DynamicSGroup> operator()(Tensor_& tensor,
83 typename Tensor_::Index firstIndex,
84 IndexTypes... otherIndices)
const {
85 static_assert(
sizeof...(otherIndices) + 1 == Tensor_::NumIndices,
86 "Number of indices used to access a tensor coefficient must be equal to the rank of the tensor.");
87 return operator()(tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices>{{firstIndex, otherIndices...}});
90 template <
typename Tensor_>
91 inline internal::tensor_symmetry_value_setter<Tensor_, DynamicSGroup> operator()(
92 Tensor_& tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices>
const& indices)
const {
93 return internal::tensor_symmetry_value_setter<Tensor_, DynamicSGroup>(tensor, *
this, indices);
98 std::vector<int> representation;
101 for (std::size_t i = 0; i < representation.size(); i++)
102 if (i != (
size_t)representation[i])
return false;
110 constexpr Generator(
int one_,
int two_,
int flags_) : one(one_), two(two_), flags(flags_) {}
113 std::size_t m_numIndices;
114 std::vector<GroupElement> m_elements;
115 std::vector<Generator> m_generators;
118 template <
typename Index, std::size_t N,
int... n>
119 inline std::array<Index, N> h_permute(std::size_t which,
const std::array<Index, N>& idx,
120 std::integer_sequence<int, n...>)
const {
121 return std::array<Index, N>{{idx[n >= m_numIndices ? n : m_elements[which].representation[n]]...}};
124 template <
typename Index>
125 inline std::vector<Index> h_permute(std::size_t which,
const std::vector<Index>& idx)
const {
126 std::vector<Index> result;
127 result.reserve(idx.size());
128 for (
auto k : m_elements[which].representation) result.push_back(idx[k]);
129 for (std::size_t i = m_numIndices; i < idx.size(); i++) result.push_back(idx[i]);
133 inline GroupElement ge(Generator
const& g)
const {
135 result.representation.reserve(m_numIndices);
136 result.flags = g.flags;
137 for (std::size_t k = 0; k < m_numIndices; k++) {
138 if (k == (std::size_t)g.one)
139 result.representation.push_back(g.two);
140 else if (k == (std::size_t)g.two)
141 result.representation.push_back(g.one);
143 result.representation.push_back(
int(k));
148 GroupElement mul(GroupElement, GroupElement)
const;
149 inline GroupElement mul(Generator g1, GroupElement g2)
const {
return mul(ge(g1), g2); }
151 inline GroupElement mul(GroupElement g1, Generator g2)
const {
return mul(g1, ge(g2)); }
153 inline GroupElement mul(Generator g1, Generator g2)
const {
return mul(ge(g1), ge(g2)); }
155 inline int findElement(GroupElement e)
const {
156 for (
auto ee : m_elements) {
157 if (ee.representation == e.representation)
return ee.flags ^ e.flags;
162 void updateGlobalFlags(
int flagDiffOfSameGenerator);