From 285ff1dbcc3450d38b8b6a00f81c3cf03db8764b Mon Sep 17 00:00:00 2001
From: Michael Wedel <michael.wedel@psi.ch>
Date: Mon, 8 Jun 2015 17:03:33 +0200
Subject: [PATCH] Refs #12749. Using reduced translation vector in reflection
 conditions

---
 .../Crystal/SymmetryOperation.h               |  5 +-
 .../src/Crystal/SymmetryElementFactory.cpp    | 26 +-------
 .../src/Crystal/SymmetryOperation.cpp         | 62 +++++++++++++++----
 .../test/SymmetryElementFactoryTest.h         |  5 ++
 .../Geometry/test/SymmetryOperationTest.h     | 15 +++++
 5 files changed, 74 insertions(+), 39 deletions(-)

diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/SymmetryOperation.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/SymmetryOperation.h
index b89acd6824f..fdb10b8f6c0 100644
--- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/SymmetryOperation.h
+++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Crystal/SymmetryOperation.h
@@ -129,7 +129,7 @@ public:
 
   const Kernel::IntMatrix &matrix() const;
   const V3R &vector() const;
-  V3R reducedVector() const;
+  const V3R &reducedVector() const;
 
   size_t order() const;
   std::string identifier() const;
@@ -163,11 +163,14 @@ protected:
   void init(const Kernel::IntMatrix &matrix, const V3R &vector);
 
   size_t getOrderFromMatrix(const Kernel::IntMatrix &matrix) const;
+  V3R getReducedVector(const Kernel::IntMatrix &matrix,
+                       const V3R &vector) const;
 
   size_t m_order;
   Kernel::IntMatrix m_matrix;
   Kernel::IntMatrix m_inverseMatrix;
   V3R m_vector;
+  V3R m_reducedVector;
   std::string m_identifier;
 };
 
diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/SymmetryElementFactory.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/SymmetryElementFactory.cpp
index bca48f4c68e..6c98097cca3 100644
--- a/Code/Mantid/Framework/Geometry/src/Crystal/SymmetryElementFactory.cpp
+++ b/Code/Mantid/Framework/Geometry/src/Crystal/SymmetryElementFactory.cpp
@@ -56,31 +56,7 @@ bool SymmetryElementInversionGenerator::canProcess(
   return operation.matrix() == inversionMatrix;
 }
 
-/**
- * @brief SymmetryElementWithAxisGenerator::determineTranslation
- *
- * According to ITA, 11.2, the translation component of a symmetry operation
- * can be termined with the following algorithm. First, a matrix \f$W\f$ is
- * calculated using the symmetry operation \f$S\f$ and its powers up to its
- * order \f$k\f$, adding the matrices of the resulting operations:
- *
- * \f[
- *  W = W_1(S^0) + W_2(S^1) + \dots + W_k(S^{k-1})
- * \f]
- *
- * The translation vector is then calculation from the vector \f$w\f$ of the
- * operation:
- *
- * \f[
- *  t = \frac{1}{k}\cdot (W \times w)
- * \f]
- *
- * For operations which do not have translation components, this algorithm
- * returns a 0-vector.
- *
- * @param operation :: Symmetry operation, possibly with translation vector.
- * @return Translation vector.
- */
+/// Returns the reduced vector of the operation.
 V3R SymmetryElementWithAxisGenerator::determineTranslation(
     const SymmetryOperation &operation) const {
   return operation.reducedVector();
diff --git a/Code/Mantid/Framework/Geometry/src/Crystal/SymmetryOperation.cpp b/Code/Mantid/Framework/Geometry/src/Crystal/SymmetryOperation.cpp
index 2aa2da30741..86b49b05879 100644
--- a/Code/Mantid/Framework/Geometry/src/Crystal/SymmetryOperation.cpp
+++ b/Code/Mantid/Framework/Geometry/src/Crystal/SymmetryOperation.cpp
@@ -11,7 +11,7 @@ namespace Geometry {
 SymmetryOperation::SymmetryOperation()
     : m_order(1), m_matrix(Kernel::IntMatrix(3, 3, true)),
       m_inverseMatrix(Kernel::IntMatrix(3, 3, true)), m_vector(),
-      m_identifier() {
+      m_reducedVector(), m_identifier() {
   m_identifier = SymmetryOperationSymbolParser::getNormalizedIdentifier(
       m_matrix, m_vector);
 }
@@ -44,7 +44,8 @@ SymmetryOperation::SymmetryOperation(const Kernel::IntMatrix &matrix,
 SymmetryOperation::SymmetryOperation(const SymmetryOperation &other)
     : m_order(other.m_order), m_matrix(other.m_matrix),
       m_inverseMatrix(other.m_inverseMatrix), m_vector(other.m_vector),
-      m_identifier(other.m_identifier) {}
+      m_reducedVector(other.m_reducedVector), m_identifier(other.m_identifier) {
+}
 
 /// Assignment operator
 SymmetryOperation &SymmetryOperation::
@@ -53,6 +54,7 @@ operator=(const SymmetryOperation &other) {
   m_matrix = other.m_matrix;
   m_inverseMatrix = other.m_inverseMatrix;
   m_vector = other.m_vector;
+  m_reducedVector = other.m_reducedVector;
   m_identifier = other.m_identifier;
 
   return *this;
@@ -69,10 +71,11 @@ void SymmetryOperation::init(const Kernel::IntMatrix &matrix,
   m_inverseMatrix = m_inverseMatrix.Transpose();
 
   m_vector = getWrappedVector(vector);
-
   m_order = getOrderFromMatrix(m_matrix);
   m_identifier = SymmetryOperationSymbolParser::getNormalizedIdentifier(
       m_matrix, m_vector);
+
+  m_reducedVector = getReducedVector(m_matrix, m_vector);
 }
 
 /// Returns a const reference to the internally stored matrix
@@ -81,16 +84,31 @@ const Kernel::IntMatrix &SymmetryOperation::matrix() const { return m_matrix; }
 /// Returns a const reference to the internall stored vector
 const V3R &SymmetryOperation::vector() const { return m_vector; }
 
-V3R SymmetryOperation::reducedVector() const {
-  Kernel::IntMatrix translationMatrix(3, 3, false);
-
-  for (size_t i = 0; i < order(); ++i) {
-    translationMatrix += ((*this) ^ i).matrix();
-  }
-
-  return (translationMatrix * m_vector) *
-         RationalNumber(1, static_cast<int>(order()));
-}
+/**
+ * @brief SymmetryOperation::reducedVector
+ *
+ * According to ITA, 11.2, the translation component of a symmetry operation
+ * can be termined with the following algorithm. First, a matrix \f$W\f$ is
+ * calculated using the symmetry operation \f$S\f$ and its powers up to its
+ * order \f$k\f$, adding the matrices of the resulting operations:
+ *
+ * \f[
+ *  W = W_1(S^0) + W_2(S^1) + \dots + W_k(S^{k-1})
+ * \f]
+ *
+ * The translation vector is then calculation from the vector \f$w\f$ of the
+ * operation:
+ *
+ * \f[
+ *  t = \frac{1}{k}\cdot (W \times w)
+ * \f]
+ *
+ * For operations which do not have translation components, this algorithm
+ * returns a 0-vector.
+ *
+ * @return Translation vector.
+ */
+const V3R &SymmetryOperation::reducedVector() const { return m_reducedVector; }
 
 /**
  * Returns the order of the symmetry operation
@@ -242,6 +260,24 @@ SymmetryOperation::getOrderFromMatrix(const Kernel::IntMatrix &matrix) const {
   throw std::runtime_error("There is something wrong with supplied matrix.");
 }
 
+V3R SymmetryOperation::getReducedVector(const Kernel::IntMatrix &matrix,
+                                        const V3R &vector) const {
+  Kernel::IntMatrix translationMatrix(3, 3, false);
+
+  for (size_t i = 0; i < order(); ++i) {
+    Kernel::IntMatrix tempMatrix(3, 3, true);
+
+    for (size_t j = 0; j < i; ++j) {
+      tempMatrix *= matrix;
+    }
+
+    translationMatrix += tempMatrix;
+  }
+
+  return (translationMatrix * vector) *
+         RationalNumber(1, static_cast<int>(order()));
+}
+
 /**
  * Wraps a V3R to the interval (0, 1]
  *
diff --git a/Code/Mantid/Framework/Geometry/test/SymmetryElementFactoryTest.h b/Code/Mantid/Framework/Geometry/test/SymmetryElementFactoryTest.h
index 35991f81e70..74a8017f832 100644
--- a/Code/Mantid/Framework/Geometry/test/SymmetryElementFactoryTest.h
+++ b/Code/Mantid/Framework/Geometry/test/SymmetryElementFactoryTest.h
@@ -199,6 +199,11 @@ public:
     V3R glideVectorC = V3R(0, 0, 1) / 2;
     SymmetryOperation glidePlaneC("x,-y,z+1/2");
     TS_ASSERT_EQUALS(generator.determineTranslation(glidePlaneC), glideVectorC);
+
+    V3R screwVectorThreeFourth = V3R(3, 0, 0) / 4;
+    SymmetryOperation fourThreeScrewAxis("x+3/4,-z+3/4,y+1/4");
+    TS_ASSERT_EQUALS(generator.determineTranslation(fourThreeScrewAxis),
+                     screwVectorThreeFourth);
   }
 
   void testSymmetryElementRotationDetermineRotationSense() {
diff --git a/Code/Mantid/Framework/Geometry/test/SymmetryOperationTest.h b/Code/Mantid/Framework/Geometry/test/SymmetryOperationTest.h
index 6eb759f2bea..79c338cd527 100644
--- a/Code/Mantid/Framework/Geometry/test/SymmetryOperationTest.h
+++ b/Code/Mantid/Framework/Geometry/test/SymmetryOperationTest.h
@@ -260,6 +260,21 @@ public:
 
     }
 
+    void testReducedVector()
+    {
+        SymmetryOperation fourThreeScrewAxis("x+3/4,-z+3/4,y+1/4");
+        TS_ASSERT_EQUALS(fourThreeScrewAxis.reducedVector(),  V3R(3, 0, 0) / 4);
+
+        SymmetryOperation glidePlaneC("x,-y,z+1/2");
+        TS_ASSERT_EQUALS(glidePlaneC.reducedVector(), V3R(0, 0, 1) / 2);
+
+        SymmetryOperation noTranslation("-x,-y,-z");
+        TS_ASSERT_EQUALS(noTranslation.reducedVector(), V3R(0, 0, 0));
+
+        SymmetryOperation noTranslationShifted("-x+1/8,-y+1/8,-z+1/8");
+        TS_ASSERT_EQUALS(noTranslationShifted.reducedVector(), V3R(0, 0, 0));
+    }
+
     void testPower()
     {
         SymmetryOperation mirror("x,-y,z");
-- 
GitLab