Simpatico  v1.10
SymmetryGroup.h
1 #ifndef UTIL_SYMMETRY_GROUP_H
2 #define UTIL_SYMMETRY_GROUP_H
3 
4 #include <iostream>
5 #include <vector>
6 
7 namespace Util {
8 
9 
28  template <class Symmetry>
30  {
31 
32  public:
33 
37  SymmetryGroup();
38 
42  SymmetryGroup(const SymmetryGroup& other);
43 
48 
57  bool add(Symmetry& symmetry);
58 
62  void makeCompleteGroup();
63 
70  const Symmetry* find(const Symmetry& symmetry) const;
71 
75  const Symmetry& identity() const;
76 
80  int size() const;
81 
86 
90  Symmetry& operator [] (int i);
91 
95  const Symmetry& operator [] (int i) const;
96 
100  bool isValid() const;
101 
102  private:
103 
104  std::vector<Symmetry> elements_;
105 
106  Symmetry identity_;
107 
108  };
109 
110 
111  // Method definitions
112 
113  /*
114  * Default constructor
115  */
116  template <class Symmetry>
118  {
119  identity_ = Symmetry::identity();
120  elements_.push_back(identity_);
121  }
122 
123  /*
124  * Copy constructor
125  */
126  template <class Symmetry>
128  {
129  identity_ = other.identity();
130  for (int i = 0; i < other.size(); ++i) {
131  elements_.push_back(other.elements_[i]);
132  }
133  }
134 
135  /*
136  * Destructor
137  */
138  template <class Symmetry>
140  {}
141 
142  /*
143  * Assignment operator.
144  */
145  template <class Symmetry>
148  {
149  if (this != &other) {
150  identity_ = other.identity();
151  elements_.clear();
152  for (int i = 0; i < other.size(); ++i) {
153  elements_.push_back(other.elements_[i]);
154  }
155  }
156  return *this;
157  }
158 
159  /*
160  * Find an element in the group, return const pointer to its address.
161  *
162  * Return a null pointer if symmetry is not a member of the group.
163  */
164  template <class Symmetry>
165  const Symmetry* SymmetryGroup<Symmetry>::find(const Symmetry& symmetry) const
166  {
167  for (int i=0; i < size(); ++i) {
168  if (symmetry == elements_[i]) {
169  return &(elements_[i]);
170  }
171  }
172  // Return null pointer if not found
173  return 0;
174  }
175 
176  /*
177  * Add a new element to the group.
178  */
179  template <class Symmetry>
180  bool SymmetryGroup<Symmetry>::add(Symmetry& symmetry)
181  {
182  const Symmetry* ptr = find(symmetry);
183  bool added;
184 
185  if (ptr == 0) {
186  elements_.push_back(symmetry);
187  added = true;
188  } else {
189  added = false;
190  }
191  return added;
192  }
193 
194  /*
195  * Create a complete group.
196  */
197  template <class Symmetry>
199  {
200  Symmetry a, b, c;
201  int i, j, n;
202  bool added, complete;
203 
204  // Add all inverses
205  n = size();
206  for (i = 0; i < n; ++i) {
207  a = elements_[i].inverse();
208  add(a);
209  }
210 
211  // Add all products of existing elements, and their inverses
212  complete = false;
213  while (!complete) {
214  complete = true;
215  n = size();
216  for (i = 0; i < n; ++i) {
217  a = elements_[i];
218  for (j = 0; j < n; ++j) {
219  b = elements_[j];
220  c = a*b;
221  added = add(c);
222  if (added) {
223  complete = false;
224  }
225  b = c.inverse();
226  added = add(b);
227  if (added) {
228  complete = false;
229  }
230  }
231  }
232  }
233 
234  }
235 
236 
237  /*
238  * Check validity of this group.
239  */
240  template <class Symmetry>
242  {
243  Symmetry a, b, c;
244  int i, j, n;
245 
246  // Check for inclusion of identity element
247  c = Symmetry::identity();
248  if (find(c) == 0) {
249  UTIL_THROW("Identity element is not in group");
250  }
251 
252  // Check inverses, uniqueness, and completeness
253  n = size();
254  for (i = 0; i < n; ++i) {
255  a = elements_[i];
256  c = a.inverse();
257  if (find(c) == 0) {
258  UTIL_THROW("Inverse of element not in group");
259  }
260  for (j = 0; j < n; ++j) {
261  b = elements_[j];
262  if (i != j) {
263  if (a == b) {
264  UTIL_THROW("An element of the group is not unique");
265  }
266  }
267  c = a*b;
268  if (find(c) == 0) {
269  UTIL_THROW("Product of two element is not in group");
270  }
271  }
272  }
273 
274  // If no Exceptions have been thrown, return true
275  return true;
276 
277  }
278 
279  /*
280  * Return the current size of the group.
281  */
282  template <class Symmetry>
283  inline int SymmetryGroup<Symmetry>::size() const
284  { return elements_.size(); }
285 
286  /*
287  * Return identity element.
288  */
289  template <class Symmetry>
290  inline const Symmetry& SymmetryGroup<Symmetry>::identity() const
291  { return identity_; }
292 
293  /*
294  * Element access operator (by reference).
295  */
296  template <class Symmetry> inline
298  { return elements_[i]; }
299 
300  /*
301  * Element access operator (by reference).
302  */
303  template <class Symmetry> inline
304  const Symmetry& SymmetryGroup<Symmetry>::operator [] (int i) const
305  { return elements_[i]; }
306 
307 }
308 #endif
Class template for a group of elements of type Symmetry.
Definition: SymmetryGroup.h:29
bool add(Symmetry &symmetry)
Add a new element to the group.
SymmetryGroup & operator=(const SymmetryGroup &other)
Assignment operator.
Symmetry & operator[](int i)
Element access operator (by reference).
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
Utility classes for scientific computation.
Definition: accumulators.mod:1
SymmetryGroup()
Default constructor.
const Symmetry & identity() const
Return a reference to the identity element.
bool isValid() const
Return true if valid complete group, or throw an Exception.
void makeCompleteGroup()
Generate a complete group from the current elements.
const Symmetry * find(const Symmetry &symmetry) const
Find a symmetry within a group.
int size() const
Return number of elements in group.
~SymmetryGroup()
Destructor.