Mantid
Loading...
Searching...
No Matches
CalculateUMatrix.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 +
8#include "MantidAPI/Sample.h"
13
14namespace Mantid::Crystal {
15
16// Register the algorithm into the AlgorithmFactory
17DECLARE_ALGORITHM(CalculateUMatrix)
18
19using namespace Mantid::Kernel;
20using namespace Mantid::API;
21using namespace Mantid::DataObjects;
23
27 this->declareProperty(std::make_unique<WorkspaceProperty<IPeaksWorkspace>>("PeaksWorkspace", "", Direction::InOut),
28 "An input workspace.");
29 std::shared_ptr<BoundedValidator<double>> mustBePositive = std::make_shared<BoundedValidator<double>>();
30 mustBePositive->setLower(0.0);
31 std::shared_ptr<BoundedValidator<double>> reasonable_angle = std::make_shared<BoundedValidator<double>>();
32 reasonable_angle->setLower(5.0);
33 reasonable_angle->setUpper(175.0);
34 // put in negative values, so user is forced to input all parameters. no
35 // shortcuts :)
36 this->declareProperty("a", -1.0, mustBePositive, "Lattice parameter a");
37 this->declareProperty("b", -1.0, mustBePositive, "Lattice parameter b");
38 this->declareProperty("c", -1.0, mustBePositive, "Lattice parameter c");
39 this->declareProperty("alpha", -1.0, reasonable_angle, "Lattice parameter alpha");
40 this->declareProperty("beta", -1.0, reasonable_angle, "Lattice parameter beta");
41 this->declareProperty("gamma", -1.0, reasonable_angle, "Lattice parameter gamma");
42}
43
47 double a = this->getProperty("a");
48 double b = this->getProperty("b");
49 double c = this->getProperty("c");
50 double alpha = this->getProperty("alpha");
51 double beta = this->getProperty("beta");
52 double gamma = this->getProperty("gamma");
53 auto lattice = std::make_unique<OrientedLattice>(a, b, c, alpha, beta, gamma);
54 Matrix<double> B = lattice->getB();
55
56 IPeaksWorkspace_sptr ws = this->getProperty("PeaksWorkspace");
57 if (!ws)
58 throw std::runtime_error("Problems reading the peaks workspace");
59
60 size_t nIndexedpeaks = 0;
61 bool found2nc = false;
62 V3D old(0, 0, 0);
63 Matrix<double> Hi(4, 4), Si(4, 4), HS(4, 4), zero(4, 4);
64 for (int i = 0; i < ws->getNumberPeaks(); i++) {
65 Mantid::Geometry::IPeak &p = ws->getPeak(i);
66 double H = p.getH();
67 double K = p.getK();
68 double L = p.getL();
69 if (H * H + K * K + L * L > 0) {
70 nIndexedpeaks++;
71 if (!found2nc) {
72 if (nIndexedpeaks == 1) {
73 old = V3D(H, K, L);
74 } else {
75 if (!old.coLinear(V3D(0, 0, 0), V3D(H, K, L)))
76 found2nc = true;
77 }
78 }
79 V3D Qhkl = B * V3D(H, K, L);
80 Hi[0][0] = 0.;
81 Hi[0][1] = -Qhkl.X();
82 Hi[0][2] = -Qhkl.Y();
83 Hi[0][3] = -Qhkl.Z();
84 Hi[1][0] = Qhkl.X();
85 Hi[1][1] = 0.;
86 Hi[1][2] = Qhkl.Z();
87 Hi[1][3] = -Qhkl.Y();
88 Hi[2][0] = Qhkl.Y();
89 Hi[2][1] = -Qhkl.Z();
90 Hi[2][2] = 0.;
91 Hi[2][3] = Qhkl.X();
92 Hi[3][0] = Qhkl.Z();
93 Hi[3][1] = Qhkl.Y();
94 Hi[3][2] = -Qhkl.X();
95 Hi[3][3] = 0.;
96
97 V3D Qgon = p.getQSampleFrame();
98 Si[0][0] = 0.;
99 Si[0][1] = -Qgon.X();
100 Si[0][2] = -Qgon.Y();
101 Si[0][3] = -Qgon.Z();
102 Si[1][0] = Qgon.X();
103 Si[1][1] = 0.;
104 Si[1][2] = -Qgon.Z();
105 Si[1][3] = Qgon.Y();
106 Si[2][0] = Qgon.Y();
107 Si[2][1] = Qgon.Z();
108 Si[2][2] = 0.;
109 Si[2][3] = -Qgon.X();
110 Si[3][0] = Qgon.Z();
111 Si[3][1] = -Qgon.Y();
112 Si[3][2] = Qgon.X();
113 Si[3][3] = 0.;
114
115 HS += (Hi * Si);
116 }
117 }
118 // check if enough peaks are indexed or if HS is 0
119 if ((nIndexedpeaks < 2) || !found2nc)
120 throw std::invalid_argument("Less then two non-colinear peaks indexed");
121 if (HS == zero)
122 throw std::invalid_argument("Something really bad happened");
123
124 Matrix<double> Eval;
125 Matrix<double> Diag;
126 HS.Diagonalise(Eval, Diag);
127 Eval.sortEigen(Diag);
128 Mantid::Kernel::Quat qR(Eval[0][0], Eval[1][0], Eval[2][0],
129 Eval[3][0]); // the first column corresponds to the highest eigenvalue
130 DblMatrix U(qR.getRotation());
131 lattice->setU(U);
132
133 ws->mutableSample().setOrientedLattice(std::move(lattice));
134}
135
136} // namespace Mantid::Crystal
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
A property class for workspaces.
void exec() override
Run the algorithm.
void init() override
Initialise the properties.
Structure describing a single-crystal peak.
Definition: IPeak.h:26
virtual double getH() const =0
virtual double getK() const =0
virtual Mantid::Kernel::V3D getQSampleFrame() const =0
virtual double getL() const =0
Class to implement UB matrix.
Numerical Matrix class.
Definition: Matrix.h:42
void sortEigen(Matrix< T > &)
Sort eigenvectors.
Definition: Matrix.cpp:1295
int Diagonalise(Matrix< T > &, Matrix< T > &) const
(only Symmetric matrix)
Definition: Matrix.cpp:1319
Class for quaternions.
Definition: Quat.h:39
std::vector< double > getRotation(bool check_normalisation=false, bool throw_on_errors=false) const
returns the rotation matrix defined by this quaternion as an 9-point
Definition: Quat.cpp:453
Class for 3D vectors.
Definition: V3D.h:34
bool coLinear(const V3D &, const V3D &) const noexcept
Determines if this,B,C are colinear.
Definition: V3D.cpp:230
constexpr double X() const noexcept
Get x.
Definition: V3D.h:232
constexpr double Y() const noexcept
Get y.
Definition: V3D.h:233
constexpr double Z() const noexcept
Get z.
Definition: V3D.h:234
std::shared_ptr< IPeaksWorkspace > IPeaksWorkspace_sptr
shared pointer to Mantid::API::IPeaksWorkspace
@ InOut
Both an input & output workspace.
Definition: Property.h:55