PSCF v1.1
SymmetryGroup.tpp
1#ifndef PSCF_SYMMETRY_GROUP_TPP
2#define PSCF_SYMMETRY_GROUP_TPP
3
4/*
5* Pscfatico - Simulation Package for Polymeric and Molecular Liquids
6*
7* Copyright 2016 - 2022, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include "SymmetryGroup.h"
12#include <util/global.h>
13
14namespace Pscf
15{
16
17 using namespace Util;
18
19 // Member function definitions (non-inline)
20
21 /*
22 * Default constructor
23 */
24 template <class Symmetry>
26 {
27 identity_ = Symmetry::identity();
28 elements_.push_back(identity_);
29 }
30
31 /*
32 * Copy constructor
33 */
34 template <class Symmetry>
36 {
37 elements_.clear();
38 identity_ = other.identity();
39 for (int i = 0; i < other.size(); ++i) {
40 elements_.push_back(other.elements_[i]);
41 }
42 }
43
44 /*
45 * Destructor
46 */
47 template <class Symmetry>
49 {}
50
51 /*
52 * Assignment operator.
53 */
54 template <class Symmetry>
57 {
58 if (this != &other) {
59 identity_ = other.identity();
60 elements_.clear();
61 for (int i = 0; i < other.size(); ++i) {
62 elements_.push_back(other.elements_[i]);
63 }
64 }
65 return *this;
66 }
67
68 /*
69 * Find an element in the group, return const pointer to its address.
70 *
71 * Return a null pointer if symmetry is not a member of the group.
72 */
73 template <class Symmetry>
74 Symmetry const * SymmetryGroup<Symmetry>::find(Symmetry const& symmetry)
75 const
76 {
77 for (int i=0; i < size(); ++i) {
78 if (symmetry == elements_[i]) {
79 return &(elements_[i]);
80 }
81 }
82 // Return null pointer if not found
83 return 0;
84 }
85
86 /*
87 * Add a new element to the group.
88 */
89 template <class Symmetry>
90 bool SymmetryGroup<Symmetry>::add(Symmetry& symmetry)
91 {
92 // Check if symmetry is already present
93 const Symmetry* ptr = find(symmetry);
94
95 // If not already present, add symmetry to this group
96 bool added;
97 if (ptr == 0) {
98 elements_.push_back(symmetry);
99 added = true;
100 } else {
101 added = false;
102 }
103 return added;
104 }
105
106 /*
107 * Create a complete group.
108 */
109 template <class Symmetry>
111 {
112 Symmetry a, b, c;
113 int i, j, n;
114 bool added, complete;
115
116 // Add all inverses
117 n = size();
118 for (i = 0; i < n; ++i) {
119 a = elements_[i].inverse();
120 add(a);
121 }
122
123 // Add all products of existing elements, and their inverses
124 complete = false;
125 while (!complete) {
126 complete = true;
127 n = size();
128 for (i = 0; i < n; ++i) {
129 a = elements_[i];
130 for (j = 0; j < n; ++j) {
131 b = elements_[j];
132 c = a*b;
133 added = add(c);
134 if (added) {
135 complete = false;
137 b = c.inverse();
138 added = add(b);
139 if (added) {
140 complete = false;
142 }
143 }
144 }
145
146 }
147
148 /*
149 * Clear all elements except the identity.
150 */
151 template <class Symmetry>
153 {
154 elements_.clear();
155 identity_ = Symmetry::identity();
156 elements_.push_back(identity_);
157 }
158
159 /*
160 * Determine if two space groups are equivalent.
161 */
162 template <class Symmetry>
163 bool
165 (SymmetryGroup<Symmetry> const & other) const
166 {
167 if (size() != other.size()) {
168 return false;
169 } else {
170 Symmetry const * ptr = 0;
171 for (int i = 0; i < size(); ++i) {
172 ptr = other.find(elements_[i]);
173 if (ptr == 0) return false;
174 }
175 for (int i = 0; i < other.size(); ++i) {
176 ptr = find(other.elements_[i]);
177 if (ptr == 0) return false;
178 }
179 }
180 return true;
181 }
182
183 /*
184 * Determine if two space groups are inequivalent.
185 */
186 template <class Symmetry>
187 bool
189 (SymmetryGroup<Symmetry> const & other) const
190 { return !(*this == other); }
191
192 /*
193 * Check validity of this group.
194 */
195 template <class Symmetry>
197 {
198 Symmetry a, b, c;
199 int i, j, n;
200
201 // Check for inclusion of identity element
202 c = Symmetry::identity();
203 if (find(c) == 0) {
204 UTIL_THROW("Identity element is not in group");
205 }
206
207 // Check inverses, uniqueness, and completeness
208 n = size();
209 for (i = 0; i < n; ++i) {
210 a = elements_[i];
211 c = a.inverse();
212 if (find(c) == 0) {
213 UTIL_THROW("Inverse of element not in group");
214 }
215 for (j = 0; j < n; ++j) {
216 b = elements_[j];
217 if (i != j) {
218 if (a == b) {
219 UTIL_THROW("An element of the group is not unique");
220 }
221 }
222 c = a*b;
223 if (find(c) == 0) {
224 UTIL_THROW("Product of two element is not in group");
225 }
226 }
227 }
228
229 // If no Exceptions have been thrown, return true
230 return true;
231
232 }
233
234}
235#endif
Class template for a group of elements.
Definition: SymmetryGroup.h:37
const Symmetry & identity() const
Return a reference to the identity element.
void clear()
Remove all elements except the identity.
~SymmetryGroup()
Destructor.
SymmetryGroup()
Default constructor.
const Symmetry * find(const Symmetry &symmetry) const
Find a symmetry within a group.
bool isValid() const
Return true if valid complete group, or throw an Exception.
int size() const
Return number of elements in group (i.e., the order of the group).
SymmetryGroup< Symmetry > & operator=(const SymmetryGroup< Symmetry > &other)
Assignment operator.
bool add(Symmetry &symmetry)
Add a new element to the group.
void makeCompleteGroup()
Generate a complete group from the current elements.
File containing preprocessor macros for error handling.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
C++ namespace for polymer self-consistent field theory (PSCF).
Utility classes for scientific computation.
Definition: accumulators.mod:1