Mantid
Loading...
Searching...
No Matches
OrientedLattice.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
10namespace Mantid::Geometry {
13
14namespace {
15const double TWO_PI = 2. * M_PI;
16}
17
22 if (Umatrix.isRotation()) {
23 U = Umatrix;
24 UB = U * getB();
25 ModUB = UB * getModHKL();
26 } else
27 throw std::invalid_argument("U is not a proper rotation");
28}
29
39OrientedLattice::OrientedLattice(const double _a, const double _b, const double _c, const DblMatrix &Umatrix)
40 : UnitCell(_a, _b, _c) {
41 if (Umatrix.isRotation()) {
42 U = Umatrix;
43 UB = U * getB();
44 ModUB = UB * getModHKL();
45 } else
46 throw std::invalid_argument("U is not a proper rotation");
47}
48
59OrientedLattice::OrientedLattice(const double _a, const double _b, const double _c, const double _alpha,
60 const double _beta, const double _gamma, const DblMatrix &Umatrix, const int angleunit)
61 : UnitCell(_a, _b, _c, _alpha, _beta, _gamma, angleunit) {
62 if (Umatrix.isRotation()) {
63 U = Umatrix;
64 UB = U * getB();
65 ModUB = UB * getModHKL();
66 } else
67 throw std::invalid_argument("U is not a proper rotation");
68}
69
74OrientedLattice::OrientedLattice(const UnitCell &uc, const DblMatrix &Umatrix) : UnitCell(uc), U(Umatrix) {
75 if (Umatrix.isRotation()) {
76 U = Umatrix;
77 UB = U * getB();
78 ModUB = UB * getModHKL();
79 } else
80 throw std::invalid_argument("U is not a proper rotation");
81}
82
85const DblMatrix &OrientedLattice::getU() const { return U; }
86
95const DblMatrix &OrientedLattice::getUB() const { return UB; }
96
97const DblMatrix &OrientedLattice::getModUB() const { return ModUB; }
98
103void OrientedLattice::setU(const DblMatrix &newU, const bool force) {
104 // determinant ==1 or (determinant == +/-1 and force)
105 if (newU.isRotation() || (force && newU.isOrthogonal())) {
106 U = newU;
107 UB = U * getB();
108 ModUB = UB * getModHKL();
109 } else
110 throw std::invalid_argument("U is not a proper rotation");
111}
112
116 // check if determinant is close to 0. The 1e-10 value is arbitrary
117 if (std::fabs(newUB.determinant()) > 1e-10) {
118 UB = newUB;
119 DblMatrix newGstar, B;
120 newGstar = newUB.Tprime() * newUB;
121 this->recalculateFromGstar(newGstar);
122 B = this->getB();
123 B.Invert();
124 U = newUB * B;
125 } else
126 throw std::invalid_argument("determinant of UB is too close to 0");
127}
128
133 ModUB = newModUB;
134 DblMatrix UBinv, newModHKL;
135 UBinv = getUB();
136 UBinv.Invert();
137 newModHKL = UBinv * ModUB;
138 setModHKL(newModHKL);
139}
140
146 DblMatrix UBinv = this->getUB();
147 UBinv.Invert();
148 V3D out = UBinv * Q / TWO_PI; // transform back to HKL
149 return out;
150}
151
157 DblMatrix T = this->getUB();
158 V3D t1 = V3D(T[0][0], T[1][0], T[2][0]);
159 V3D t2 = V3D(T[0][1], T[1][1], T[2][1]);
160 V3D t3 = V3D(T[0][2], T[1][2], T[2][2]);
161
162 t1.normalize();
163 t2.normalize();
164 t3.normalize();
165
166 T.setRow(0, t1);
167 T.setRow(1, t2);
168 T.setRow(2, t3);
169 return T * dir;
170}
171
176V3D OrientedLattice::qFromHKL(const V3D &hkl) const { return UB * hkl * TWO_PI; }
177
183 V3D z(0, 0, 1);
184 DblMatrix UBinv = UB;
185 UBinv.Invert();
186 return UBinv * z;
187}
188
196 V3D x(1, 0, 0);
197 DblMatrix UBinv = UB;
198 UBinv.Invert();
199 return UBinv * x;
200}
201
216 const DblMatrix &BMatrix = this->getB();
217 V3D buVec = BMatrix * u;
218 V3D bvVec = BMatrix * v;
219 // try to make an orthonormal system
220 if (buVec.norm2() < 1e-10)
221 throw std::invalid_argument("|B.u|~0");
222 if (bvVec.norm2() < 1e-10)
223 throw std::invalid_argument("|B.v|~0");
224 buVec.normalize(); // 1st unit vector, along Bu
225 V3D bwVec = buVec.cross_prod(bvVec);
226 const auto norm = bwVec.norm();
227 if (norm < 1e-5) {
228 // 3rd unit vector, perpendicular to Bu,Bv
229 throw std::invalid_argument("u and v are parallel");
230 }
231 bwVec /= norm;
232 // 2nd unit vector, perpendicular to Bu, in the Bu,Bv plane
233 bvVec = bwVec.cross_prod(buVec);
234 DblMatrix tau(3, 3), lab(3, 3);
235 /*lab = U tau
236 / 0 1 0 \ /bu[0] bv[0] bw[0]\
237 | 0 0 1 | = U |bu[1] bv[1] bw[1]|
238 \ 1 0 0 / \bu[2] bv[2] bw[2]/
239 */
240 lab[0][1] = 1.;
241 lab[1][2] = 1.;
242 lab[2][0] = 1.;
243 tau[0][0] = buVec[0];
244 tau[0][1] = bvVec[0];
245 tau[0][2] = bwVec[0];
246 tau[1][0] = buVec[1];
247 tau[1][1] = bvVec[1];
248 tau[1][2] = bwVec[1];
249 tau[2][0] = buVec[2];
250 tau[2][1] = bvVec[2];
251 tau[2][2] = bwVec[2];
252 tau.Invert();
253 this->setU(lab * tau);
254 return getU();
255}
256
261void OrientedLattice::saveNexus(Nexus::File *file, const std::string &group) const {
262 file->makeGroup(group, "NXcrystal", true);
263 file->writeData("unit_cell_a", this->a());
264 file->writeData("unit_cell_b", this->b());
265 file->writeData("unit_cell_c", this->c());
266 file->writeData("unit_cell_alpha", this->alpha());
267 file->writeData("unit_cell_beta", this->beta());
268 file->writeData("unit_cell_gamma", this->gamma());
269 file->writeData("unit_cell_a_error", this->errora());
270 file->writeData("unit_cell_b_error", this->errorb());
271 file->writeData("unit_cell_c_error", this->errorc());
272 file->writeData("unit_cell_alpha_error", this->erroralpha());
273 file->writeData("unit_cell_beta_error", this->errorbeta());
274 file->writeData("unit_cell_gamma_error", this->errorgamma());
275 // Save the UB matrix
276 std::vector<double> ub = this->UB.getVector();
277 const Nexus::DimVector dims(2, 3); // 3x3 matrix
278 file->writeData("orientation_matrix", ub, dims);
279
280 // Save the modulated UB matrix
281 std::vector<double> modUB = this->ModUB.getVector();
282 file->writeData("modulated_orientation_matrix", modUB, dims);
283 std::vector<double> errorModHKL = this->errorModHKL.getVector();
284 file->writeData("modulated_hkl_error", errorModHKL, dims);
285 file->writeData("maximum_order", this->getMaxOrder());
286 file->writeData("cross_term", int(this->getCrossTerm()));
287
288 file->closeGroup();
289}
290
295void OrientedLattice::loadNexus(Nexus::File *file, const std::string &group) {
296 file->openGroup(group, "NXcrystal");
297 std::vector<double> ub;
298 file->readData("orientation_matrix", ub);
299 // Turn into a matrix
300 DblMatrix ubMat(ub);
301 // This will set the lattice parameters and the U matrix:
302 this->setUB(ubMat);
303
304 try {
306 file->readData("unit_cell_a_error", errora);
307 file->readData("unit_cell_b_error", errorb);
308 file->readData("unit_cell_c_error", errorc);
309 file->readData("unit_cell_alpha_error", erroralpha);
310 file->readData("unit_cell_beta_error", errorbeta);
311 file->readData("unit_cell_gamma_error", errorgamma);
313
314 std::vector<double> modUB;
315 file->readData("modulated_orientation_matrix", modUB);
316 DblMatrix ModUBMat(modUB);
317 this->setModUB(ModUBMat);
318
319 std::vector<double> errorModHKL;
320 file->readData("modulated_hkl_error", errorModHKL);
321 DblMatrix ErrorModHKL(errorModHKL);
322 this->setErrorModHKL(ErrorModHKL);
323
324 int maxOrder;
325 file->readData("maximum_order", maxOrder);
326 this->setMaxOrder(maxOrder);
327 int crossTerm;
328 file->readData("cross_term", crossTerm);
329 this->setCrossTerm(crossTerm);
330 } catch (Nexus::Exception const &) {
331 // Old files don't have these. Ignore
332 }
333 file->closeGroup();
334}
335
348bool OrientedLattice::GetUB(DblMatrix &UB, const V3D &a_dir, const V3D &b_dir, const V3D &c_dir) {
349 if (UB.numRows() != 3 || UB.numCols() != 3) {
350 throw std::invalid_argument("Find_UB(): UB matrix NULL or not 3X3");
351 }
352
353 UB.setRow(0, a_dir);
354 UB.setRow(1, b_dir);
355 UB.setRow(2, c_dir);
356 try {
357 UB.Invert();
358 } catch (...) {
359 return false;
360 }
361 return true;
362}
363
381bool OrientedLattice::GetABC(const DblMatrix &UB, V3D &a_dir, V3D &b_dir, V3D &c_dir) {
382 if (UB.numRows() != 3 || UB.numCols() != 3) {
383 throw std::invalid_argument("GetABC(): UB matrix NULL or not 3X3");
384 }
385
386 DblMatrix UB_inverse(UB);
387 try {
388 UB_inverse.Invert();
389 } catch (...) {
390 return false;
391 }
392 a_dir(UB_inverse[0][0], UB_inverse[0][1], UB_inverse[0][2]);
393 b_dir(UB_inverse[1][0], UB_inverse[1][1], UB_inverse[1][2]);
394 c_dir(UB_inverse[2][0], UB_inverse[2][1], UB_inverse[2][2]);
395
396 return true;
397}
404bool OrientedLattice::operator==(const OrientedLattice &other) const { return UB == other.UB; }
405bool OrientedLattice::operator!=(const OrientedLattice &other) const { return UB != other.UB; }
406} // namespace Mantid::Geometry
const int maxOrder
Class to implement UB matrix.
Kernel::V3D cosFromDir(const Kernel::V3D &dir) const
Calculate the direction cosine corresponding to a given direction.
Kernel::V3D getuVector() const
gets a vector along beam direction when goniometers are at 0.
void setU(const Kernel::DblMatrix &newU, const bool force=true)
Sets the U matrix.
Kernel::V3D getvVector() const
gets a vector in the horizontal plane, perpendicular to the beam direction when goniometers are at 0.
OrientedLattice(const Kernel::DblMatrix &Umatrix=Kernel::DblMatrix(3, 3, true))
Default constructor.
void setModUB(const Kernel::DblMatrix &newModUB)
Sets the Modulation UB matrix.
Kernel::V3D hklFromQ(const Kernel::V3D &Q) const
Calculate the hkl corresponding to a given Q-vector.
void setUB(const Kernel::DblMatrix &newUB)
Sets the UB matrix and recalculates lattice parameters.
static bool GetABC(const Kernel::DblMatrix &UB, Kernel::V3D &a_dir, Kernel::V3D &b_dir, Kernel::V3D &c_dir)
Get the real space edge vectors a,b,c corresponding to the UB matrix.
bool operator==(const OrientedLattice &other) const
const Kernel::DblMatrix & setUFromVectors(const Kernel::V3D &u, const Kernel::V3D &v)
Set the U rotation matrix, to provide the transformation, which translate an arbitrary vector V expre...
void recalculate() override
Private function, called at initialization or whenever lattice parameters are changed.
const Kernel::DblMatrix & getUB() const
Get the UB matrix.
void saveNexus(Nexus::File *file, const std::string &group) const
Save the object to an open NeXus file.
void loadNexus(Nexus::File *file, const std::string &group)
Load the object from an open NeXus file.
bool operator!=(const OrientedLattice &other) const
static bool GetUB(Kernel::DblMatrix &UB, const Kernel::V3D &a_dir, const Kernel::V3D &b_dir, const Kernel::V3D &c_dir)
Get the UB matrix corresponding to the real space edge vectors a,b,c.
Kernel::V3D qFromHKL(const Kernel::V3D &hkl) const
Calculate the hkl corresponding to a given Q-vector.
const Kernel::DblMatrix & getModUB() const
const Kernel::DblMatrix & getU() const
Get the U matrix.
void recalculateFromGstar(const Kernel::DblMatrix &NewGstar) override
Make recalculateFrom private.
Class to implement unit cell of crystals.
Definition UnitCell.h:44
const Kernel::DblMatrix & getB() const
Get the B-matrix.
Definition UnitCell.cpp:758
double alpha() const
Get lattice parameter.
Definition UnitCell.cpp:133
double erroralpha(const int angleunit=angDegrees) const
Get lattice parameter error.
Definition UnitCell.cpp:225
int getMaxOrder() const
Get max order.
Definition UnitCell.cpp:596
double c() const
Get lattice parameter.
Definition UnitCell.cpp:128
const Kernel::DblMatrix & getModHKL() const
Get modulation vectors for satellites.
Definition UnitCell.cpp:548
bool getCrossTerm() const
Get cross term boolean.
Definition UnitCell.cpp:602
double errorgamma(const int angleunit=angDegrees) const
Get lattice parameter error.
Definition UnitCell.cpp:252
double errorbeta(const int angleunit=angDegrees) const
Get lattice parameter error.
Definition UnitCell.cpp:239
Kernel::DblMatrix errorModHKL
Definition UnitCell.h:199
void setModHKL(double _dh1, double _dk1, double _dl1, double _dh2, double _dk2, double _dl2, double _dh3, double _dk3, double _dl3)
Set modulation vectors for satellites.
Definition UnitCell.cpp:353
double beta() const
Get lattice parameter.
Definition UnitCell.cpp:138
void setError(double _aerr, double _berr, double _cerr, double _alphaerr, double _betaerr, double _gammaerr, const int angleunit=angDegrees)
Set lattice parameter errors.
Definition UnitCell.cpp:325
double a() const
Get lattice parameter.
Definition UnitCell.cpp:118
virtual void recalculate()
Private function, called at initialization or whenever lattice parameters are changed.
Definition UnitCell.cpp:766
void setErrorModHKL(const Kernel::DblMatrix &newErrorModHKL)
Set modulation vectors for satellites.
Definition UnitCell.cpp:376
double b() const
Get lattice parameter.
Definition UnitCell.cpp:123
double errorc() const
Get lattice parameter error.
Definition UnitCell.cpp:218
void setCrossTerm(bool CT)
Set modulation vectors for satellites.
Definition UnitCell.cpp:528
void setMaxOrder(int MaxO)
Set modulation vectors for satellites.
Definition UnitCell.cpp:522
Kernel::DblMatrix B
B matrix for a right-handed coordinate system, in Busing-Levy convention.
Definition UnitCell.h:191
double gamma() const
Get lattice parameter.
Definition UnitCell.cpp:143
double errora() const
Get lattice parameter error.
Definition UnitCell.cpp:208
double errorb() const
Get lattice parameter error.
Definition UnitCell.cpp:213
T determinant() const
Calculate the determinant.
Definition Matrix.cpp:1048
T Invert()
LU inversion routine.
Definition Matrix.cpp:924
Matrix< T > Tprime() const
Transpose the matrix.
Definition Matrix.cpp:766
bool isRotation() const
Check if a matrix represents a proper rotation @ return :: true/false.
Definition Matrix.cpp:1422
void setRow(const size_t nRow, const std::vector< T > &newRow)
Definition Matrix.cpp:686
std::vector< T > getVector() const
Definition Matrix.cpp:77
size_t numRows() const
Return the number of rows in the matrix.
Definition Matrix.h:144
size_t numCols() const
Return the number of columns in the matrix.
Definition Matrix.h:147
bool isOrthogonal() const
Check if a matrix is orthogonal.
Definition Matrix.cpp:1442
Class for 3D vectors.
Definition V3D.h:34
double normalize()
Make a normalized vector (return norm value)
Definition V3D.cpp:129
constexpr V3D cross_prod(const V3D &v) const noexcept
Cross product (this * argument)
Definition V3D.h:284
double norm() const noexcept
Definition V3D.h:269
constexpr double norm2() const noexcept
Vector length squared.
Definition V3D.h:271
Class that provides for a standard Nexus exception.
std::vector< dimsize_t > DimVector