PSCF v1.4.0
SymmetryGroup.tpp
1#ifndef PRDC_SYMMETRY_GROUP_TPP
2#define PRDC_SYMMETRY_GROUP_TPP
3
4/*
5* Pscfatico - Simulation Package for Polymeric and Molecular Liquids
6*
7* Copyright 2015 - 2025, 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 {
15namespace Prdc {
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 * Assignment operator.
46 */
47 template <class Symmetry>
50 {
51 if (this != &other) {
52 identity_ = other.identity();
53 elements_.clear();
54 for (int i = 0; i < other.size(); ++i) {
55 elements_.push_back(other.elements_[i]);
56 }
57 }
58 return *this;
59 }
60
61 /*
62 * Find an element in the group, return const pointer to its address.
63 *
64 * Return a null pointer if symmetry is not a member of the group.
65 */
66 template <class Symmetry>
67 Symmetry const * SymmetryGroup<Symmetry>::find(Symmetry const& symmetry)
68 const
69 {
70 for (int i=0; i < size(); ++i) {
71 if (symmetry == elements_[i]) {
72 return &(elements_[i]);
73 }
74 }
75 // Return null pointer if not found
76 return 0;
77 }
78
79 /*
80 * Add a new element to the group.
81 */
82 template <class Symmetry>
83 bool SymmetryGroup<Symmetry>::add(Symmetry& symmetry)
84 {
85 // Check if symmetry is already present
86 const Symmetry* ptr = find(symmetry);
87
88 // If not already present, add symmetry to this group
89 bool added;
90 if (ptr == 0) {
91 elements_.push_back(symmetry);
92 added = true;
93 } else {
94 added = false;
95 }
96 return added;
97 }
98
99 /*
100 * Create a complete group.
101 */
102 template <class Symmetry>
104 {
105 Symmetry a, b, c;
106 int i, j, n;
107 bool added, complete;
108
109 // Add all inverses
110 n = size();
111 for (i = 0; i < n; ++i) {
112 a = elements_[i].inverse();
113 add(a);
114 }
115
116 // Add all products of existing elements, and their inverses
117 complete = false;
118 while (!complete) {
119 complete = true;
120 n = size();
121 for (i = 0; i < n; ++i) {
122 a = elements_[i];
123 for (j = 0; j < n; ++j) {
124 b = elements_[j];
125 c = a*b;
126 added = add(c);
127 if (added) {
128 complete = false;
129 }
130 b = c.inverse();
131 added = add(b);
132 if (added) {
133 complete = false;
134 }
135 }
136 }
137 }
138
139 }
140
141 /*
142 * Clear all elements except the identity.
143 */
144 template <class Symmetry>
146 {
147 elements_.clear();
148 identity_ = Symmetry::identity();
149 elements_.push_back(identity_);
150 }
151
152 /*
153 * Determine if two space groups are equivalent.
154 */
155 template <class Symmetry>
156 bool
158 (SymmetryGroup<Symmetry> const & other) const
159 {
160 if (size() != other.size()) {
161 return false;
162 } else {
163 Symmetry const * ptr = 0;
164 for (int i = 0; i < size(); ++i) {
165 ptr = other.find(elements_[i]);
166 if (ptr == 0) return false;
167 }
168 for (int i = 0; i < other.size(); ++i) {
169 ptr = find(other.elements_[i]);
170 if (ptr == 0) return false;
171 }
172 }
173 return true;
174 }
175
176 /*
177 * Determine if two space groups are inequivalent.
178 */
179 template <class Symmetry>
180 bool
182 (SymmetryGroup<Symmetry> const & other) const
183 { return !(*this == other); }
184
185 /*
186 * Check validity of this group.
187 */
188 template <class Symmetry>
190 {
191 Symmetry a, b, c;
192 int i, j, n;
193
194 // Check for inclusion of identity element
195 c = Symmetry::identity();
196 if (find(c) == 0) {
197 UTIL_THROW("Identity element is not in group");
198 }
199
200 // Check inverses, uniqueness, and completeness
201 n = size();
202 for (i = 0; i < n; ++i) {
203 a = elements_[i];
204 c = a.inverse();
205 if (find(c) == 0) {
206 UTIL_THROW("Inverse of element not in group");
207 }
208 for (j = 0; j < n; ++j) {
209 b = elements_[j];
210 if (i != j) {
211 if (a == b) {
212 UTIL_THROW("An element of the group is not unique");
213 }
214 }
215 c = a*b;
216 if (find(c) == 0) {
217 UTIL_THROW("Product of two element is not in group");
218 }
219 }
220 }
221
222 // If no Exceptions have been thrown, return true
223 return true;
224
225 }
226
227}
228}
229#endif
void makeCompleteGroup()
Generate a complete group from the current elements.
const Symmetry * find(const Symmetry &symmetry) const
Find a symmetry within a group.
bool add(Symmetry &symmetry)
Add a new element to the group.
SymmetryGroup< Symmetry > & operator=(const SymmetryGroup< Symmetry > &other)
Assignment operator.
void clear()
Remove all elements except the identity.
bool isValid() const
Return true if valid complete group, or throw an Exception.
SymmetryGroup()
Default constructor.
int size() const
Return number of elements in group (i.e., the order of the group).
const Symmetry & identity() const
Return a reference to the identity element.
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:49
void add(fftw_complex &z, fftw_complex const &a, fftw_complex const &b)
Addition of fftw_complex numbers, z = a + b.
Periodic fields and crystallography.
Definition complex.cpp:11
PSCF package top-level namespace.