8#include <boost/math/special_functions/round.hpp>
9#include <gsl/gsl_complex_math.h>
10#include <gsl/gsl_eigen.h>
19 return std::make_shared<SymmetryElementIdentity>();
32 return std::make_shared<SymmetryElementTranslation>(operation.
vector());
45 return std::make_shared<SymmetryElementInversion>(operation.
vector() / 2);
51 inversionMatrix *= -1;
53 return operation.
matrix() == inversionMatrix;
72 gsl_matrix *gslMatrix = gsl_matrix_alloc(matrix.
numRows(), matrix.
numCols());
74 for (
size_t r = 0; r < matrix.
numRows(); ++r) {
75 for (
size_t c = 0; c < matrix.
numCols(); ++c) {
76 gsl_matrix_set(gslMatrix, r, c,
static_cast<double>(matrix[r][c]));
95 gsl_matrix *gslMatrix = gsl_matrix_alloc(rows, cols);
97 gsl_matrix_set_identity(gslMatrix);
117 gsl_eigen_genv_workspace *eigenWs = gsl_eigen_genv_alloc(matrix.
numRows());
119 gsl_vector_complex *alpha = gsl_vector_complex_alloc(3);
120 gsl_vector *beta = gsl_vector_alloc(3);
121 gsl_matrix_complex *eigenVectors = gsl_matrix_complex_alloc(3, 3);
123 gsl_eigen_genv(eigenMatrix, identityMatrix, alpha, beta, eigenVectors, eigenWs);
124 gsl_eigen_genv_sort(alpha, beta, eigenVectors, GSL_EIGEN_SORT_ABS_DESC);
130 for (
size_t i = 0; i < matrix.
numCols(); ++i) {
131 double eigenValue = GSL_REAL(gsl_complex_div_real(gsl_vector_complex_get(alpha, i), gsl_vector_get(beta, i)));
133 if (
fabs(eigenValue - determinant) < 1e-9) {
134 for (
size_t j = 0; j < matrix.
numRows(); ++j) {
135 double element = GSL_REAL(gsl_matrix_complex_get(eigenVectors, j, i));
137 eigenVector[j] = element;
142 eigenVector *= determinant;
144 double sumOfElements = eigenVector.
X() + eigenVector.
Y() + eigenVector.
Z();
146 if (sumOfElements < 0) {
150 gsl_matrix_free(eigenMatrix);
151 gsl_matrix_free(identityMatrix);
152 gsl_eigen_genv_free(eigenWs);
153 gsl_vector_complex_free(alpha);
154 gsl_vector_free(beta);
155 gsl_matrix_complex_free(eigenVectors);
158 for (
size_t i = 0; i < 3; ++i) {
159 double absoluteValue =
fabs(eigenVector[i]);
160 if (absoluteValue != 0.0 && (eigenVector[i] < min && (absoluteValue -
fabs(min)) < 1e-9)) {
161 min = eigenVector[i];
166 for (
size_t i = 0; i < 3; ++i) {
167 axis[i] =
static_cast<int>(boost::math::round(eigenVector[i] / min));
183 return std::make_shared<SymmetryElementRotation>(symbol, axis, translation, rotationSense);
191 int trace = matrix.
Trace();
193 return (abs(trace) != 3) && !(trace == 1 && determinant == -1);
199 const V3R &rotationAxis)
const {
203 Kernel::V3D generatedPoint = operation * pointOffAxis;
206 matrix.
setColumn(0, pointOnAxis2 - pointOnAxis1);
207 matrix.
setColumn(1, pointOffAxis - pointOnAxis1);
208 matrix.
setColumn(2, generatedPoint - pointOnAxis1);
212 if (determinant < 0) {
224 int trace = matrix.
Trace();
227 if (trace == 0 && determinant == -1) {
233 if (determinant < 0) {
242 if (translation != 0) {
250 {
V3R(0, 0, 0),
"m"}, {
V3R(1, 0, 0) / 2,
"a"}, {V3R(0, 1, 0) / 2,
"b"}, {V3R(0, 0, 1) / 2,
"c"},
251 {V3R(1, 1, 0) / 2,
"n"}, {V3R(1, 0, 1) / 2,
"n"}, {V3R(0, 1, 1) / 2,
"n"}, {V3R(1, 1, 1) / 2,
"n"},
252 {V3R(1, 1, 0) / 4,
"d"}, {V3R(1, 0, 1) / 4,
"d"}, {V3R(0, 1, 1) / 4,
"d"}, {V3R(1, 1, 1) / 4,
"d"}};
263 return std::make_shared<SymmetryElementMirror>(symbol, axis, translation);
278 for (
size_t i = 0; i < 3; ++i) {
279 translation[i] = rawTranslation[i] >
RationalNumber(1, 2) ? rawTranslation[i] - 1 : rawTranslation[i];
288 if (symbol.empty()) {
307 std::string operationIdentifier = operation.
identifier();
318 throw std::runtime_error(
"Could not process symmetry operation '" + operationIdentifier +
"'.");
321 insertPrototype(operationIdentifier, generator->generateElement(operation));
333 const std::string &generatorClassName) {
343 return (prototypeIterator->second)->clone();
354 [&operation](
const auto &generator) { return generator->canProcess(operation); });
#define DECLARE_SYMMETRY_ELEMENT_GENERATOR(classname)
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
std::unordered_set< std::string > m_generatorNames
void subscribe(const AbstractSymmetryElementGenerator_sptr &generator, const std::string &generatorClassName)
Subscribes a generator and stores its class name for later checks.
AbstractSymmetryElementGenerator_sptr getGenerator(const SymmetryOperation &operation) const
Returns a generator that can process the supplied symmetry operation or an invalid pointer if no appr...
std::map< std::string, SymmetryElement_sptr > m_prototypes
std::vector< AbstractSymmetryElementGenerator_sptr > m_generators
SymmetryElement_sptr createFromPrototype(const std::string &identifier) const
Creates a SymmetryElement from an internally stored prototype.
bool isSubscribed(const std::string &generatorClassName) const
Checks whether a generator with that class name is already subscribed.
void insertPrototype(const std::string &identifier, const SymmetryElement_sptr &prototype)
Inserts the provided prototype into the factory.
SymmetryElement_sptr createSymElement(const SymmetryOperation &operation)
Creates a SymmetryElement from a SymmetryOperation.
This implementation of AbstractSymmetryElementGenerator produces only identity elements.
SymmetryElement_sptr generateElement(const SymmetryOperation &operation) const override
Generates an instance of SymmetryElementIdentity.
bool canProcess(const SymmetryOperation &operation) const override
Checks that the SymmetryOperation has no translation and the matrix is of order 1.
This implementation of AbstractSymmetryElementGenerator produces only inversion elements.
bool canProcess(const SymmetryOperation &operation) const override
Checks that the matrix is identity matrix multiplied with -1.
SymmetryElement_sptr generateElement(const SymmetryOperation &operation) const override
Generates an instance of SymmetryElementInversion with the inversion point equal to the vector of the...
SymmetryElementMirrorGenerator also inherits from SymmetryElementWithAxisGenerator.
SymmetryElement_sptr generateElement(const SymmetryOperation &operation) const override
Generates an instance of SymmetryElementMirror with the corresponding symbol, axis and translation ve...
std::string determineSymbol(const SymmetryOperation &operation) const override
Determines the symbol from the translation vector using a map.
bool canProcess(const SymmetryOperation &operation) const override
Checks that the trace of the matrix is 1 and the determinant is -1.
static std::map< V3R, std::string > g_glideSymbolMap
SymmetryElementRotationGenerator inherits from SymmetryElementWithAxisGenerator, using its methods fo...
SymmetryElement_sptr generateElement(const SymmetryOperation &operation) const override
Generates an instance of SymmetryElementRotation with the corresponding symbol, axis,...
bool canProcess(const SymmetryOperation &operation) const override
Checks the trace and determinat of the matrix to determine if the matrix belongs to a rotation.
std::string determineSymbol(const SymmetryOperation &operation) const override
Determines the Hermann-Mauguin symbol of the rotation-, rotoinversion- or screw-axis.
SymmetryElementRotation::RotationSense determineRotationSense(const SymmetryOperation &operation, const V3R &rotationAxis) const
Determines the rotation sense according to the description in ITA 11.2.
This implementation of AbstractSymmetryElementGenerator produces only translation elements.
SymmetryElement_sptr generateElement(const SymmetryOperation &operation) const override
Generates an instance of SymmetryElementTranslation with the vector of the operation as translation v...
bool canProcess(const SymmetryOperation &operation) const override
Checks that the order of the matrix is 1 and the operation has a translation.
V3R determineAxis(const Kernel::IntMatrix &matrix) const
Returns the symmetry axis for the given matrix.
V3R determineTranslation(const SymmetryOperation &operation) const
Returns the reduced vector of the operation.
Crystallographic symmetry operations are composed of a rotational component, which is represented by ...
std::string identifier() const
Returns the string-identifier for this symmetry operation.
const Kernel::IntMatrix & matrix() const
Returns a const reference to the internally stored matrix.
const V3R & reducedVector() const
SymmetryOperation::reducedVector.
bool hasTranslation() const
Returns true if the operation has a translational component.
size_t order() const
Returns the order of the symmetry operation.
const V3R & vector() const
Returns a const reference to the internall stored vector.
V3R getPositiveVector() const
Returns a V3R with absolute components.
T determinant() const
Calculate the determinant.
T Trace() const
Trace of the matrix.
size_t numRows() const
Return the number of rows in the matrix.
void setColumn(const size_t nCol, const std::vector< T > &newCol)
size_t numCols() const
Return the number of columns in the matrix.
constexpr double X() const noexcept
Get x.
constexpr double Y() const noexcept
Get y.
constexpr double Z() const noexcept
Get z.
boost::rational< int > RationalNumber
V3R :
MANTID_GEOMETRY_DLL gsl_matrix * getGSLIdentityMatrix(size_t rows, size_t cols)
Returns a GSL-indentity matrix.
std::shared_ptr< AbstractSymmetryElementGenerator > AbstractSymmetryElementGenerator_sptr
MANTID_GEOMETRY_DLL gsl_matrix * getGSLMatrix(const Kernel::IntMatrix &matrix)
Returns a GSL-matrix for the given IntMatrix.
std::shared_ptr< SymmetryElement > SymmetryElement_sptr
std::string to_string(const wide_integer< Bits, Signed > &n)