10 #ifndef EIGEN_CXX11_TENSORSYMMETRY_DYNAMICSYMMETRY_H
11 #define EIGEN_CXX11_TENSORSYMMETRY_DYNAMICSYMMETRY_H
13 #include "./InternalHeaderCheck.h"
20 inline explicit DynamicSGroup() : m_numIndices(1), m_elements(), m_generators(), m_globalFlags(0) { m_elements.push_back(ge(Generator(0, 0, 0))); }
21 inline DynamicSGroup(
const DynamicSGroup& o) : m_numIndices(o.m_numIndices), m_elements(o.m_elements), m_generators(o.m_generators), m_globalFlags(o.m_globalFlags) { }
22 inline DynamicSGroup(
DynamicSGroup&& o) : m_numIndices(o.m_numIndices), m_elements(), m_generators(o.m_generators), m_globalFlags(o.m_globalFlags) { std::swap(m_elements, o.m_elements); }
23 inline DynamicSGroup& operator=(
const DynamicSGroup& o) { m_numIndices = o.m_numIndices; m_elements = o.m_elements; m_generators = o.m_generators; m_globalFlags = o.m_globalFlags;
return *
this; }
24 inline DynamicSGroup& operator=(
DynamicSGroup&& o) { m_numIndices = o.m_numIndices; std::swap(m_elements, o.m_elements); m_generators = o.m_generators; m_globalFlags = o.m_globalFlags;
return *
this; }
26 void add(
int one,
int two,
int flags = 0);
28 template<
typename Gen_>
29 inline void add(Gen_) { add(Gen_::One, Gen_::Two, Gen_::Flags); }
30 inline void addSymmetry(
int one,
int two) { add(one, two, 0); }
31 inline void addAntiSymmetry(
int one,
int two) { add(one, two, NegationFlag); }
32 inline void addHermiticity(
int one,
int two) { add(one, two, ConjugationFlag); }
33 inline void addAntiHermiticity(
int one,
int two) { add(one, two, NegationFlag | ConjugationFlag); }
35 template<
typename Op,
typename RV,
typename Index, std::size_t N,
typename... Args>
36 inline RV apply(
const std::array<Index, N>& idx, RV initial, Args&&... args)
const
38 eigen_assert(N >= m_numIndices &&
"Can only apply symmetry group to objects that have at least the required amount of indices.");
39 for (std::size_t i = 0; i < size(); i++)
40 initial = Op::run(h_permute(i, idx,
typename internal::gen_numeric_list<int, N>::type()), m_elements[i].flags, initial, std::forward<Args>(args)...);
44 template<
typename Op,
typename RV,
typename Index,
typename... Args>
45 inline RV apply(
const std::vector<Index>& idx, RV initial, Args&&... args)
const
47 eigen_assert(idx.size() >= m_numIndices &&
"Can only apply symmetry group to objects that have at least the required amount of indices.");
48 for (std::size_t i = 0; i < size(); i++)
49 initial = Op::run(h_permute(i, idx), m_elements[i].flags, initial, std::forward<Args>(args)...);
53 inline int globalFlags()
const {
return m_globalFlags; }
54 inline std::size_t size()
const {
return m_elements.size(); }
56 template<
typename Tensor_,
typename... IndexTypes>
57 inline internal::tensor_symmetry_value_setter<Tensor_, DynamicSGroup> operator()(Tensor_& tensor,
typename Tensor_::Index firstIndex, IndexTypes... otherIndices)
const
59 static_assert(
sizeof...(otherIndices) + 1 == Tensor_::NumIndices,
"Number of indices used to access a tensor coefficient must be equal to the rank of the tensor.");
60 return operator()(tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices>{{firstIndex, otherIndices...}});
63 template<
typename Tensor_>
64 inline internal::tensor_symmetry_value_setter<Tensor_, DynamicSGroup> operator()(Tensor_& tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices>
const& indices)
const
66 return internal::tensor_symmetry_value_setter<Tensor_, DynamicSGroup>(tensor, *
this, indices);
70 std::vector<int> representation;
74 for (std::size_t i = 0; i < representation.size(); i++)
75 if (i != (
size_t)representation[i])
84 constexpr
inline Generator(
int one_,
int two_,
int flags_) : one(one_), two(two_), flags(flags_) {}
87 std::size_t m_numIndices;
88 std::vector<GroupElement> m_elements;
89 std::vector<Generator> m_generators;
92 template<
typename Index, std::size_t N,
int... n>
93 inline std::array<Index, N> h_permute(std::size_t which,
const std::array<Index, N>& idx, internal::numeric_list<int, n...>)
const
95 return std::array<Index, N>{{ idx[n >= m_numIndices ? n : m_elements[which].representation[n]]... }};
98 template<
typename Index>
99 inline std::vector<Index> h_permute(std::size_t which, std::vector<Index> idx)
const
101 std::vector<Index> result;
102 result.reserve(idx.size());
103 for (
auto k : m_elements[which].representation)
104 result.push_back(idx[k]);
105 for (std::size_t i = m_numIndices; i < idx.size(); i++)
106 result.push_back(idx[i]);
110 inline GroupElement ge(Generator
const& g)
const
113 result.representation.reserve(m_numIndices);
114 result.flags = g.flags;
115 for (std::size_t k = 0; k < m_numIndices; k++) {
116 if (k == (std::size_t)g.one)
117 result.representation.push_back(g.two);
118 else if (k == (std::size_t)g.two)
119 result.representation.push_back(g.one);
121 result.representation.push_back(
int(k));
126 GroupElement mul(GroupElement, GroupElement)
const;
127 inline GroupElement mul(Generator g1, GroupElement g2)
const
129 return mul(ge(g1), g2);
132 inline GroupElement mul(GroupElement g1, Generator g2)
const
134 return mul(g1, ge(g2));
137 inline GroupElement mul(Generator g1, Generator g2)
const
139 return mul(ge(g1), ge(g2));
142 inline int findElement(GroupElement e)
const
144 for (
auto ee : m_elements) {
145 if (ee.representation == e.representation)
146 return ee.flags ^ e.flags;
151 void updateGlobalFlags(
int flagDiffOfSameGenerator);
155 template<
typename... Gen>
161 add_all(internal::type_list<Gen...>());
163 inline DynamicSGroupFromTemplateArgs(DynamicSGroupFromTemplateArgs
const& other) : DynamicSGroup(other) { }
164 inline DynamicSGroupFromTemplateArgs(DynamicSGroupFromTemplateArgs&& other) : DynamicSGroup(other) { }
165 inline DynamicSGroupFromTemplateArgs<Gen...>& operator=(
const DynamicSGroupFromTemplateArgs<Gen...>& o) { DynamicSGroup::operator=(o);
return *
this; }
166 inline DynamicSGroupFromTemplateArgs<Gen...>& operator=(DynamicSGroupFromTemplateArgs<Gen...>&& o) { DynamicSGroup::operator=(o);
return *
this; }
169 template<
typename Gen1,
typename... GenNext>
170 inline void add_all(internal::type_list<Gen1, GenNext...>)
173 add_all(internal::type_list<GenNext...>());
176 inline void add_all(internal::type_list<>)
181 inline DynamicSGroup::GroupElement DynamicSGroup::mul(GroupElement g1, GroupElement g2)
const
183 eigen_internal_assert(g1.representation.size() == m_numIndices);
184 eigen_internal_assert(g2.representation.size() == m_numIndices);
187 result.representation.reserve(m_numIndices);
188 for (std::size_t i = 0; i < m_numIndices; i++) {
189 int v = g2.representation[g1.representation[i]];
190 eigen_assert(v >= 0);
191 result.representation.push_back(v);
193 result.flags = g1.flags ^ g2.flags;
197 inline void DynamicSGroup::add(
int one,
int two,
int flags)
199 eigen_assert(one >= 0);
200 eigen_assert(two >= 0);
201 eigen_assert(one != two);
203 if ((std::size_t)one >= m_numIndices || (std::size_t)two >= m_numIndices) {
204 std::size_t newNumIndices = (one > two) ? one : two + 1;
205 for (
auto& gelem : m_elements) {
206 gelem.representation.reserve(newNumIndices);
207 for (std::size_t i = m_numIndices; i < newNumIndices; i++)
208 gelem.representation.push_back(i);
210 m_numIndices = newNumIndices;
213 Generator g{one, two, flags};
214 GroupElement e = ge(g);
217 if (m_elements.size() == 1) {
219 m_elements.push_back(e);
224 updateGlobalFlags(e.flags);
227 if (m_elements.size() > 1)
228 m_generators.push_back(g);
232 int p = findElement(e);
234 updateGlobalFlags(p);
238 std::size_t coset_order = m_elements.size();
239 m_elements.push_back(e);
240 for (std::size_t i = 1; i < coset_order; i++)
241 m_elements.push_back(mul(m_elements[i], e));
242 m_generators.push_back(g);
244 std::size_t coset_rep = coset_order;
246 for (
auto g : m_generators) {
247 e = mul(m_elements[coset_rep], g);
251 m_elements.push_back(e);
252 for (std::size_t i = 1; i < coset_order; i++)
253 m_elements.push_back(mul(m_elements[i], e));
255 updateGlobalFlags(p);
258 coset_rep += coset_order;
259 }
while (coset_rep < m_elements.size());
262 inline void DynamicSGroup::updateGlobalFlags(
int flagDiffOfSameGenerator)
264 switch (flagDiffOfSameGenerator) {
271 m_globalFlags |= GlobalZeroFlag;
273 case ConjugationFlag:
275 m_globalFlags |= GlobalRealFlag;
277 case (NegationFlag | ConjugationFlag):
279 m_globalFlags |= GlobalImagFlag;
Dynamic symmetry group.
Definition: DynamicSymmetry.h:18
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index