forked from npshub/mantid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
UnitConversion.cpp
141 lines (129 loc) · 5.94 KB
/
UnitConversion.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidKernel/UnitConversion.h"
#include "MantidKernel/Unit.h"
#include "MantidKernel/UnitFactory.h"
#include <cmath>
#include <stdexcept>
namespace Mantid::Kernel {
/**
* Convert a single value between the given units (as strings)
* @param src :: The starting unit
* @param dest :: The destination unit
* @param srcValue :: The value to convert
* @param l1 :: The source-sample distance (in metres)
* @param l2 :: The sample-detector distance (in metres)
* @param theta :: The scattering angle (in radians)
* @param emode :: The energy mode enumeration
* @param efixed :: Value of fixed energy: EI (emode=1) or EF (emode=2) (in
* meV)
* @return The value converted to the destination unit
*/
double UnitConversion::run(const std::string &src, const std::string &dest, const double srcValue, const double l1,
const double l2, const double theta, const DeltaEMode::Type emode, const double efixed) {
Unit_sptr srcUnit = UnitFactory::Instance().create(src);
Unit_sptr destUnit = UnitFactory::Instance().create(dest);
if ((srcUnit->unitID() == "dSpacing") || (destUnit->unitID() == "dSpacing")) {
throw std::runtime_error("This signature is deprecated for d Spacing unit conversions");
}
UnitParametersMap params{{UnitParams::l2, l2}, {UnitParams::twoTheta, theta}, {UnitParams::efixed, efixed}};
return UnitConversion::run(*srcUnit, *destUnit, srcValue, l1, emode, params);
} // namespace Kernel
double UnitConversion::run(const std::string &src, const std::string &dest, const double srcValue, const double l1,
const DeltaEMode::Type emode, const UnitParametersMap ¶ms) {
Unit_sptr srcUnit = UnitFactory::Instance().create(src);
Unit_sptr destUnit = UnitFactory::Instance().create(dest);
return UnitConversion::run(*srcUnit, *destUnit, srcValue, l1, emode, params);
}
/**
* Convert a single value between the given units (overload for Unit objects)
* @param srcUnit :: The starting unit
* @param destUnit :: The destination unit
* @param srcValue :: The value to convert
* @param l1 :: The source-sample distance (in metres)
* @param emode :: The energy mode enumeration
* @param params :: Map containing optional parameters eg
* The sample-detector distance (in metres)
* The scattering angle (in radians)
* Fixed energy: EI (emode=1) or EF (emode=2)(in meV)
* Delta (not currently used)
* @return The value converted to the destination unit
*/
double UnitConversion::run(Unit &srcUnit, Unit &destUnit, const double srcValue, const double l1,
const DeltaEMode::Type emode, const UnitParametersMap ¶ms) {
double factor(0.0), power(0.0);
if (srcUnit.quickConversion(destUnit, factor, power)) {
return convertQuickly(srcValue, factor, power);
} else {
return convertViaTOF(srcUnit, destUnit, srcValue, l1, emode, params);
}
}
//---------------------------------------------------------------------------------------------
// Private methods
//---------------------------------------------------------------------------------------------
/**
* Perform a quick conversion by raising the value to a power & multiplying by
* the factor
* @param srcValue :: The value to convert
* @param factor :: A multiplicative constant
* @param power :: Raise the src value to this power
* @return The converted unit
*/
double UnitConversion::convertQuickly(const double srcValue, const double factor, const double power) {
return factor * std::pow(srcValue, power);
}
/**
* @param srcUnit :: The starting unit
* @param destUnit :: The destination unit
* @param srcValue :: The value to convert
* @param l1 :: The source-sample distance (in metres)
* @param emode :: The energy mode enumeration
* @param params :: Map containing optional parameters eg
* The sample-detector distance (in metres)
* The scattering angle (in radians)
* Fixed energy: EI (emode=1) or EF (emode=2)(in meV)
* Delta (not currently used)
* @return The value converted to the destination unit
*/
double UnitConversion::convertViaTOF(Unit &srcUnit, Unit &destUnit, const double srcValue, const double l1,
const DeltaEMode::Type emode, const UnitParametersMap ¶ms) {
// Translate the emode to the int formulation
int emodeAsInt(0);
switch (emode) {
case DeltaEMode::Elastic:
emodeAsInt = 0;
break;
case DeltaEMode::Direct:
emodeAsInt = 1;
break;
case DeltaEMode::Indirect:
emodeAsInt = 2;
break;
default:
throw std::invalid_argument("UnitConversion::convertViaTOF - Unknown emode " + std::to_string(emode));
};
const double tof = srcUnit.convertSingleToTOF(srcValue, l1, emodeAsInt, params);
return destUnit.convertSingleFromTOF(tof, l1, emodeAsInt, params);
}
/**
* Convert a to ElasticQ
* @param theta :: The scattering angle (in radians)
* @param efixed :: Value of fixed energy: EI (emode=1) or EF (emode=2) (in
* meV)
* @return The value converted to ElasticQ
*/
double UnitConversion::convertToElasticQ(const double theta, const double efixed) {
Mantid::Kernel::Units::Energy energyUnit;
double wavelengthFactor(0.0), wavelengthPower(0.0);
energyUnit.quickConversion("Wavelength", wavelengthFactor, wavelengthPower);
const double stheta = std::sin(theta);
// Calculate the wavelength to allow it to be used to convert to elasticQ.
double wavelength = wavelengthFactor * std::pow(efixed, wavelengthPower);
// The MomentumTransfer value.
return 4.0 * M_PI * stheta / wavelength;
}
} // namespace Mantid::Kernel