Mantid
Loading...
Searching...
No Matches
Group.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
9
10#include <algorithm>
11
12namespace Mantid::Geometry {
13
15Group::Group() : m_allOperations(), m_operationSet(), m_axisSystem() {
16 std::vector<SymmetryOperation> operation(1);
17 setSymmetryOperations(operation);
18}
19
22Group::Group(const std::string &symmetryOperationString) : m_allOperations(), m_operationSet(), m_axisSystem() {
23 setSymmetryOperations(SymmetryOperationFactory::Instance().createSymOps(symmetryOperationString));
24}
25
28Group::Group(const std::vector<SymmetryOperation> &symmetryOperations)
29 : m_allOperations(), m_operationSet(), m_axisSystem() {
30 setSymmetryOperations(symmetryOperations);
31}
32
34size_t Group::order() const { return m_allOperations.size(); }
35
38
40std::vector<SymmetryOperation> Group::getSymmetryOperations() const { return m_allOperations; }
41
43bool Group::containsOperation(const SymmetryOperation &operation) const {
44 return std::find(m_allOperations.begin(), m_allOperations.end(), operation) != m_allOperations.end();
45}
46
56Group Group::operator*(const Group &other) const {
57 std::vector<SymmetryOperation> result;
58 result.reserve(order() * other.order());
59
60 // performs multiplication between all operations in the Group and the all from the other Group
61 std::transform(
62 m_allOperations.begin(), m_allOperations.end(), std::back_inserter(result), [&result, &other](auto &operation) {
63 std::transform(other.m_allOperations.begin(), other.m_allOperations.end(), std::back_inserter(result),
64 [&operation](const auto &otherOp) { return operation * otherOp; });
65 return operation;
66 });
67 return Group(result);
68}
69
72std::vector<Kernel::V3D> Group::operator*(const Kernel::V3D &vector) const {
73 std::vector<Kernel::V3D> result;
74 result.reserve(m_allOperations.size());
75 std::transform(m_allOperations.cbegin(), m_allOperations.cend(), std::back_inserter(result),
76 [&vector](const auto &operation) { return Geometry::getWrappedVector(operation * vector); });
77
78 std::sort(result.begin(), result.end(), AtomPositionsLessThan());
79 result.erase(std::unique(result.begin(), result.end()), result.end());
80
81 return result;
82}
83
117bool Group::isInvariant(const Kernel::DblMatrix &tensor, double tolerance) const {
118 auto transformTensor = [](const Kernel::DblMatrix &opMatrix, const Kernel::DblMatrix &tensor) {
119 return opMatrix.Tprime() * tensor * opMatrix;
120 };
121
122 return std::all_of(m_allOperations.cbegin(), m_allOperations.cend(), [&](const SymmetryOperation &op) {
123 return transformTensor(convertMatrix<double>(op.matrix()), tensor).equals(tensor, tolerance);
124 });
125}
126
128bool Group::operator==(const Group &other) const { return m_operationSet == other.m_operationSet; }
129
131bool Group::operator!=(const Group &other) const { return !(this->operator==(other)); }
132
136 switch (axiom) {
137 case Closure:
138 return isClosed();
139 case Identity:
140 return hasIdentity();
141 case Inversion:
142 return eachElementHasInverse();
143 case Associativity:
144 return associativityHolds();
145 default:
146 return false;
147 }
148}
149
162
165void Group::setSymmetryOperations(const std::vector<SymmetryOperation> &symmetryOperations) {
166 if (symmetryOperations.empty()) {
167 throw std::invalid_argument("Group needs at least one element.");
168 }
169
170 m_operationSet.clear();
171 std::transform(symmetryOperations.cbegin(), symmetryOperations.cend(),
173
174 m_allOperations = std::vector<SymmetryOperation>(m_operationSet.begin(), m_operationSet.end());
176}
177
181Group::getCoordinateSystemFromOperations(const std::vector<SymmetryOperation> &symmetryOperations) const {
182 for (const auto &symmetryOperation : symmetryOperations) {
183 std::vector<int> matrix = symmetryOperation.matrix();
184 if (std::count(matrix.begin(), matrix.end(), 0) == 5) {
185 return Group::Hexagonal;
186 }
187 }
188
189 return Group::Orthogonal;
190}
191
193bool Group::isClosed() const {
194 Group result = (*this) * (*this);
195
196 // If the order is different, there are additional or fewer elements
197 if (result.order() != order()) {
198 return false;
199 }
200
201 // Also, all operations need to be equal.
202 std::vector<SymmetryOperation> ops = result.getSymmetryOperations();
203 for (size_t i = 0; i < ops.size(); ++i) {
204 if (ops[i] != m_allOperations[i]) {
205 return false;
206 }
207 }
208
209 return true;
210}
211
213bool Group::hasIdentity() const {
214 // Since the identity element does not change, this is an easy check.
216}
217
220 return std::all_of(m_allOperations.cbegin(), m_allOperations.cend(), [this](const auto &operation) {
221 return this->containsOperation(getUnitCellIntervalOperation(operation.inverse()));
222 });
223}
224
244bool Group::associativityHolds() const { return true; }
245
249 if (!lhs || !rhs) {
250 throw std::invalid_argument("One of the operands is null. Aborting.");
251 }
252
253 return std::make_shared<const Group>((*lhs) * (*rhs));
254}
255
257std::vector<Kernel::V3D> operator*(const Group_const_sptr &lhs, const Kernel::V3D &rhs) {
258 if (!lhs) {
259 throw std::invalid_argument("Cannot use null pointer for multiplication.");
260 }
261
262 return (*lhs) * rhs;
263}
264
267 if (!lhs || !rhs) {
268 throw std::invalid_argument("One of the operands is null. Aborting.");
269 }
270
271 return (*lhs) == (*rhs);
272}
273
275bool operator!=(const Group_const_sptr &lhs, const Group_const_sptr &rhs) { return !(operator==(lhs, rhs)); }
276
277} // namespace Mantid::Geometry
const std::vector< double > & rhs
double tolerance
Less-than-functor for comparison of atom positions with specifiable precision.
Definition: Group.h:37
The class Group represents a set of symmetry operations (or symmetry group).
Definition: Group.h:135
Group operator*(const Group &other) const
Multiplication operator of two groups.
Definition: Group.cpp:56
CoordinateSystem m_axisSystem
Definition: Group.h:175
bool operator!=(const Group &other) const
Returns true if groups are different from eachother.
Definition: Group.cpp:131
bool isGroup() const
Returns whether the group fulfills the four group axioms.
Definition: Group.cpp:161
bool isInvariant(const Kernel::DblMatrix &tensor, double tolerance=1e-8) const
Returns true if the tensor is invariant under the group operations.
Definition: Group.cpp:117
std::vector< SymmetryOperation > getSymmetryOperations() const
Returns a vector with all symmetry operations.
Definition: Group.cpp:40
Group()
Default constructor. Creates a group with one symmetry operation (identity).
Definition: Group.cpp:15
CoordinateSystem getCoordinateSystem() const
Returns the axis system of the group (either orthogonal or hexagonal).
Definition: Group.cpp:37
bool fulfillsAxiom(GroupAxiom axiom) const
Checks whether a certain group axiom is fulfilled, can be used as a more fine-grained alternative to ...
Definition: Group.cpp:135
bool associativityHolds() const
Checks that associativity holds, i.e.
Definition: Group.cpp:244
bool hasIdentity() const
Returns true if the group has the identity element.
Definition: Group.cpp:213
bool isClosed() const
Returns true if the group is closed, i.e. all elements of G * G are in G.
Definition: Group.cpp:193
bool operator==(const Group &other) const
Returns true if both groups contain the same set of symmetry operations.
Definition: Group.cpp:128
std::vector< SymmetryOperation > m_allOperations
Definition: Group.h:173
void setSymmetryOperations(const std::vector< SymmetryOperation > &symmetryOperations)
Assigns symmetry operations, throws std::invalid_argument if vector is empty.
Definition: Group.cpp:165
bool containsOperation(const SymmetryOperation &operation) const
Returns true if the group contains the supplied operation.
Definition: Group.cpp:43
bool eachElementHasInverse() const
Returns true if the inverse of each element is in the group.
Definition: Group.cpp:219
CoordinateSystem getCoordinateSystemFromOperations(const std::vector< SymmetryOperation > &symmetryOperations) const
Returns the axis system based on the given symmetry operations.
Definition: Group.cpp:181
size_t order() const
Returns the order of the group, which is the number of symmetry operations.
Definition: Group.cpp:34
std::set< SymmetryOperation > m_operationSet
Definition: Group.h:174
Crystallographic symmetry operations are composed of a rotational component, which is represented by ...
Matrix< T > Tprime() const
Transpose the matrix.
Definition: Matrix.cpp:766
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Class for 3D vectors.
Definition: V3D.h:34
MANTID_GEOMETRY_DLL bool operator==(const Group_const_sptr &lhs, const Group_const_sptr &rhs)
Equality operator for shared pointers.
Definition: Group.cpp:266
MANTID_GEOMETRY_DLL Group_const_sptr operator*(const Group_const_sptr &lhs, const Group_const_sptr &rhs)
Convenience operator* for directly multiplying groups using shared pointers.
Definition: Group.cpp:248
MANTID_GEOMETRY_DLL bool operator!=(const Group_const_sptr &lhs, const Group_const_sptr &rhs)
Inequality operator for shared pointers.
Definition: Group.cpp:275
MANTID_GEOMETRY_DLL SymmetryOperation getUnitCellIntervalOperation(const SymmetryOperation &symOp)
Returns a SymmetryOperation with the vector wrapped to the interval (0, 1].
std::shared_ptr< const Group > Group_const_sptr
Definition: Group.h:179