Mantid
Loading...
Searching...
No Matches
ScalarUtils.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 +
7/* File: ScalarUtils.cpp */
8
13#include <algorithm>
14#include <stdexcept>
15
16using namespace Mantid::Geometry;
20
21static const std::string BRAVAIS_TYPE[15] = {
22 ReducedCell::CUBIC(), // F
23 ReducedCell::CUBIC(), // I
24 ReducedCell::CUBIC(), // P
25
27
29
32
37
41
43};
44
45static const std::string BRAVAIS_CENTERING[15] = {
46 ReducedCell::F_CENTERED(), // cubic
47 ReducedCell::I_CENTERED(), // cubic
48 ReducedCell::P_CENTERED(), // cubic
49
50 ReducedCell::P_CENTERED(), // hexagonal
51
52 ReducedCell::R_CENTERED(), // rhombohedral
53
54 ReducedCell::I_CENTERED(), // tetragonal
55 ReducedCell::P_CENTERED(), // tetragonal
56
57 ReducedCell::F_CENTERED(), // orthorhombic
58 ReducedCell::I_CENTERED(), // orthorhombic
59 ReducedCell::C_CENTERED(), // orthorhombic
60 ReducedCell::P_CENTERED(), // orthorhombic
61
62 ReducedCell::C_CENTERED(), // monoclinic
63 ReducedCell::I_CENTERED(), // monoclinic
64 ReducedCell::P_CENTERED(), // monoclinic
65
66 ReducedCell::P_CENTERED() // triclinic
67};
68
91std::vector<ConventionalCell> ScalarUtils::GetCells(const DblMatrix &UB, bool best_only, bool allowPermutations) {
92 std::vector<ConventionalCell> result;
93
94 size_t num_lattices = 15;
95 for (size_t i = 0; i < num_lattices; i++) {
96 std::vector<ConventionalCell> temp = GetCells(UB, BRAVAIS_TYPE[i], BRAVAIS_CENTERING[i], allowPermutations);
97 if (best_only) {
98 ConventionalCell info = GetCellBestError(temp, true);
99 temp.clear();
100 temp.emplace_back(info);
101 }
102 for (auto &k : temp)
103 AddIfBest(result, k);
104 }
105
106 return result;
107}
108
135std::vector<ConventionalCell> ScalarUtils::GetCells(const DblMatrix &UB, const std::string &cell_type,
136 const std::string &centering, bool allowPermutations) {
137 std::vector<ConventionalCell> result;
138
139 std::vector<DblMatrix> UB_list;
140 if (allowPermutations) {
141 double angle_tolerance = 2.0;
142 double length_factor = 1.05;
143 UB_list = GetRelatedUBs(UB, length_factor, angle_tolerance);
144 } else {
145 // Get exact form requested and not permutations
146 UB_list.emplace_back(UB);
147 }
148
149 for (auto &k : UB_list) {
150 std::vector<ConventionalCell> temp = GetCellsUBOnly(k, cell_type, centering, allowPermutations);
151
152 for (auto &cell : temp)
153 AddIfBest(result, cell);
154 }
155
156 return result;
157}
158
182std::vector<ConventionalCell> ScalarUtils::GetCellsUBOnly(const DblMatrix &UB, const std::string &cell_type,
183 const std::string &centering, bool allowPermutations) {
184 std::vector<ConventionalCell> result;
185
186 std::vector<double> lat_par;
188
189 for (size_t i = 0; i <= ReducedCell::NUM_CELL_TYPES; i++) {
190 ReducedCell rcell(i, lat_par[0], lat_par[1], lat_par[2], lat_par[3], lat_par[4], lat_par[5]);
191
192 if (rcell.GetCentering() == centering && rcell.GetCellType() == cell_type) {
193 ConventionalCell cell_info(UB, i, allowPermutations);
194 result.emplace_back(cell_info);
195 }
196 }
197
198 return result;
199}
200
217ConventionalCell ScalarUtils::GetCellForForm(const DblMatrix &UB, size_t form_num, bool allowPermutations) {
218 ConventionalCell info(UB);
219 ReducedCell form_0;
220 ReducedCell form;
221
222 double min_error = 1e20; // errors are usually < 10, so this is big enough
223
224 std::vector<double> l_params;
225 std::vector<DblMatrix> UB_list;
226 if (allowPermutations) {
227 double angle_tolerance = 2.0;
228 double length_factor = 1.05;
229 UB_list = GetRelatedUBs(UB, length_factor, angle_tolerance);
230 } else {
231 // Get exact form requested and not permutations
232 UB_list.emplace_back(UB);
233 }
234 for (auto &ub : UB_list) {
236
237 form_0 = ReducedCell(0, l_params[0], l_params[1], l_params[2], l_params[3], l_params[4], l_params[5]);
238
239 form = ReducedCell(form_num, l_params[0], l_params[1], l_params[2], l_params[3], l_params[4], l_params[5]);
240
241 double error = form_0.WeightedDistance(form);
242 if (error < min_error) {
243 info = ConventionalCell(ub, form_num, allowPermutations);
244 min_error = error;
245 }
246 }
247
248 return info;
249}
250
259void ScalarUtils::RemoveHighErrorForms(std::vector<ConventionalCell> &list, double level) {
260 if (list.empty()) // nothing to do
261 return;
262 const auto removeRangeBegin =
263 std::remove_if(list.begin(), list.end(), [level](const auto &cell) { return cell.GetError() > level; });
264 list.erase(removeRangeBegin, list.end());
265}
266
280ConventionalCell ScalarUtils::GetCellBestError(const std::vector<ConventionalCell> &list, bool use_triclinic) {
281 if (list.empty()) {
282 throw std::invalid_argument("GetCellBestError(): list is empty");
283 }
284
285 ConventionalCell info = list[0];
286 double min_error = 1.0e20;
287
288 bool min_found = false;
289 for (const auto &cell : list) {
290 std::string type = cell.GetCellType();
291 double error = cell.GetError();
292 if ((use_triclinic || type != ReducedCell::TRICLINIC()) && error < min_error) {
293 info = cell;
294 min_error = error;
295 min_found = true;
296 }
297 }
298
299 if (!min_found) {
300 throw std::invalid_argument("GetCellBestError(): no allowed form with min error");
301 }
302
303 return info;
304}
305
339std::vector<DblMatrix> ScalarUtils::GetRelatedUBs(const DblMatrix &UB, double factor, double angle_tolerance) {
340 std::vector<DblMatrix> result;
341
342 V3D a, b, c, a_vec, b_vec, c_vec, // vectors for generating reflections
343 m_a_vec, m_b_vec, m_c_vec; // of pairs of sides
344
345 V3D a_temp, b_temp, c_temp, // vectors for generating handedness
346 m_a_temp, m_b_temp, m_c_temp; // preserving permutations of sides
347
348 OrientedLattice::GetABC(UB, a_vec, b_vec, c_vec);
349
350 m_a_vec = a_vec * (-1.0);
351 m_b_vec = b_vec * (-1.0);
352 m_c_vec = c_vec * (-1.0);
353 // make list of reflections of all pairs
354 // of sides. NOTE: These preserve the
355 // ordering of magnitudes: |a|<=|b|<=|c|
356 V3D reflections[4][3] = {
357 {a_vec, b_vec, c_vec}, {m_a_vec, m_b_vec, c_vec}, {m_a_vec, b_vec, m_c_vec}, {a_vec, m_b_vec, m_c_vec}};
358
359 // make list of the angles that are not
360 // changed by each of the reflections. IF
361 // that angle is close to 90 degrees, then
362 // we may need to switch between all angles
363 // >= 90 and all angles < 90. An angle
364 // near 90 degrees may be mis-categorized
365 // due to errors in the data.
366 double alpha = b_vec.angle(c_vec) * 180.0 / M_PI;
367 double beta = c_vec.angle(a_vec) * 180.0 / M_PI;
368 double gamma = a_vec.angle(b_vec) * 180.0 / M_PI;
369 double angles[4] = {90.0, gamma, beta, alpha};
370
371 for (size_t row = 0; row < 4; row++) {
372 if (fabs(angles[row] - 90.0) < angle_tolerance) // if nearly 90,
373 { // try related cell
374 a_temp = reflections[row][0]; // +cell <-> -cell
375 b_temp = reflections[row][1];
376 c_temp = reflections[row][2];
377 // for each accepted reflection, try all
378 // modified premutations that preserve the
379 // handedness AND keep the cell edges
380 // nearly ordered as a <= b <= c.
381 m_a_temp = a_temp * (-1.0);
382 m_b_temp = b_temp * (-1.0);
383 m_c_temp = c_temp * (-1.0);
384
385 V3D permutations[6][3] = {{a_temp, b_temp, c_temp}, {m_a_temp, c_temp, b_temp}, {b_temp, c_temp, a_temp},
386 {m_b_temp, a_temp, c_temp}, {c_temp, a_temp, b_temp}, {m_c_temp, b_temp, a_temp}};
387
388 for (auto &permutation : permutations) {
389 a = permutation[0];
390 b = permutation[1];
391 c = permutation[2];
392 if (a.norm() <= factor * b.norm() && b.norm() <= factor * c.norm()) // could be Niggli within
393 { // experimental error
394 Matrix<double> temp_UB(3, 3, false);
395 OrientedLattice::GetUB(temp_UB, a, b, c);
396 result.emplace_back(temp_UB);
397 }
398 }
399 }
400 }
401
402 return result;
403}
404
418void ScalarUtils::AddIfBest(std::vector<ConventionalCell> &list, ConventionalCell &info) {
419 size_t form_num = info.GetFormNum();
420 double new_error = info.GetError();
421 bool done = false;
422 size_t i = 0;
423 while (!done && i < list.size()) {
424 if (list[i].GetFormNum() == form_num) // if found, replace if better
425 {
426 done = true;
427 if (list[i].GetError() > new_error)
428 list[i] = info;
429 } else
430 i++;
431 }
432
433 if (!done) // if never found, add to end of list
434 list.emplace_back(info);
435}
double error
Definition: IndexPeaks.cpp:133
#define fabs(x)
Definition: Matrix.cpp:22
static const std::string BRAVAIS_CENTERING[15]
Definition: ScalarUtils.cpp:45
static const std::string BRAVAIS_TYPE[15]
Definition: ScalarUtils.cpp:21
Instances of this class represent information about a selected conventional cell based on a specified...
std::string GetCellType() const
get the cell type name, as named in the ReducedCell class
size_t GetFormNum() const
get the form number for this conventional cell
double GetError() const
get the error in the scalars for this form
static bool GetLatticeParameters(const Kernel::DblMatrix &UB, std::vector< double > &lattice_par)
Get the lattice parameters for the specified orientation matrix.
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.
static bool GetUB(Kernel::DblMatrix &UB, const Kernel::V3D &a_dir, const Kernel::V3D &b_dir, const Kernel::V3D &c_dir)
Get the UB matix corresponding to the real space edge vectors a, b, c.
Instances of this class represent information about reduced cell types including the transformation r...
Definition: ReducedCell.h:32
std::string GetCellType() const
Get the cell type of this form.
static const std::string HEXAGONAL()
Definition: ReducedCell.h:53
double WeightedDistance(const ReducedCell &other) const
Get the maximum absolute weighted difference between the scalars for the specifed ReducedCellInfo obj...
static const std::string MONOCLINIC()
Definition: ReducedCell.h:57
static const std::string RHOMBOHEDRAL()
Definition: ReducedCell.h:54
static const std::string CUBIC()
Definition: ReducedCell.h:52
static const std::string F_CENTERED()
Definition: ReducedCell.h:61
static const std::string TRICLINIC()
Definition: ReducedCell.h:58
static const std::string R_CENTERED()
Definition: ReducedCell.h:65
std::string GetCentering() const
Get centering assigned to this form.
static const std::string TETRAGONAL()
Definition: ReducedCell.h:55
static const std::string ORTHORHOMBIC()
Definition: ReducedCell.h:56
static const std::string P_CENTERED()
Definition: ReducedCell.h:64
static const std::string I_CENTERED()
Definition: ReducedCell.h:62
static const std::string C_CENTERED()
Definition: ReducedCell.h:63
static void AddIfBest(std::vector< ConventionalCell > &list, ConventionalCell &info)
Add conventional cell to list if it has the least error for its form num.
static std::vector< ConventionalCell > GetCells(const Kernel::DblMatrix &UB, bool best_only, bool allowPermutations=false)
Get list of all possible conventional cells for UB, regardless of errors, using this UB,...
Definition: ScalarUtils.cpp:91
static std::vector< Kernel::DblMatrix > GetRelatedUBs(const Kernel::DblMatrix &UB, double factor, double angle_tolerance)
Get list of related cells obtained by reflecting pairs of sides with nearly a 90 degree angle between...
static void RemoveHighErrorForms(std::vector< ConventionalCell > &list, double level)
Remove cells from list that have scalar errors above the specified level.
static ConventionalCell GetCellBestError(const std::vector< ConventionalCell > &list, bool use_triclinic)
Get the cell from the list with the smallest error, possibly excluding triclinic cells.
static std::vector< ConventionalCell > GetCellsUBOnly(const Kernel::DblMatrix &UB, const std::string &cell_type, const std::string &centering, bool allowPermutations=false)
Get list of conventional cells for UB with specified type and centering, using ONLY this UB,...
static ConventionalCell GetCellForForm(const Kernel::DblMatrix &UB, size_t form_num, bool allowPermutations=false)
Get the best conventional cell for the form number, using the specified UB, and three related "almost...
Class for 3D vectors.
Definition: V3D.h:34
double angle(const V3D &) const
Angle between this and another vector.
Definition: V3D.cpp:165
double norm() const noexcept
Definition: V3D.h:263