Mantid
Loading...
Searching...
No Matches
Meier.cpp
Go to the documentation of this file.
1// Mantid Repository : https: // github.com/mantidproject/mantid
2//
3// Copyright © 2022 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 +
10#include <cmath>
11#include <valarray>
12
14
15using namespace CurveFitting;
16
17using namespace Kernel;
18
19using namespace API;
20
22
23namespace {
24std::string isPositiveAndMultipleOf05(double value) {
25 double temp = value * 2;
26 if (temp <= 0.0) {
27 return "Spin value should be greater than zero";
28 }
29 if (floor(temp) != ceil(temp)) {
30 return "Spin value should be a multiple of 0.5";
31 }
32 return "";
33}
34
35double getSinSquared(const double &cosSquared) { return 1 - cosSquared; }
36
37double getCosSquared(const double &cos2squared) { return 0.5 * (1 + std::sqrt(cos2squared)); }
38} // namespace
39
41 declareParameter("A0", 0.5, "Amplitude");
42 declareParameter("FreqD", 0.01, "Angular Frequency due to dipolar coupling (MHz)");
43 declareParameter("FreqQ", 0.05,
44 "Angular Frequency due to quadrupole interaction of the nuclear spin (MHz) due to a field gradient"
45 "exerted by the presence of the muon");
46 declareParameter("Sigma", 0.2, "Gaussian decay rate");
47 declareParameter("Lambda", 0.1, "Exponential decay rate");
48 // J, Total angular momentum quanutm number
50 Mantid::Kernel::LambdaValidator<double>(isPositiveAndMultipleOf05));
51}
52
53void Meier::function1D(double *out, const double *xValues, const size_t nData) const {
54 const double J = getAttribute("Spin").asDouble();
55
56 const double A0 = getParameter("A0");
57 const double J2 = round(2 * J);
58 const double Lambda = getParameter("Lambda");
59 const double Sigma = getParameter("Sigma");
60
61 std::valarray<double> xValArray(xValues, nData);
62
63 const std::valarray<double> gau = std::exp(-0.5 * pow((Sigma * xValArray), 2));
64 const std::valarray<double> Lor = std::exp(-Lambda * xValArray);
65
66 std::valarray<double> positiveLambda;
67 std::valarray<double> negativeLambda;
68 std::valarray<double> cos2AlphaSquared;
69
70 precomputeIntermediateSteps(cos2AlphaSquared, negativeLambda, positiveLambda, J2);
71
72 std::valarray<double> Px;
73 calculatePx(Px, xValArray, cos2AlphaSquared, negativeLambda, positiveLambda, J2);
74
75 std::valarray<double> Pz;
76 calculatePz(Pz, xValArray, cos2AlphaSquared, negativeLambda, positiveLambda, J2);
77
78 const std::valarray<double> outValArray = A0 * gau * Lor * (1. / 3.) * (2 * Px + Pz);
79 std::copy(begin(outValArray), end(outValArray), out);
80}
81
90void Meier::precomputeIntermediateSteps(std::valarray<double> &cos2AlphaSquared, std::valarray<double> &negativeLambda,
91 std::valarray<double> &positiveLambda, const double &J2) const {
92 const double FreqD = getParameter("FreqD");
93 const double FreqQ = getParameter("FreqQ");
94 const double J = J2 / 2;
95
96 const double OmegaD = 2 * M_PI * FreqD;
97 const double OmegaQ = 2 * M_PI * FreqQ;
98
99 const size_t size = int(J2 + 2);
100 cos2AlphaSquared.resize(size);
101 negativeLambda.resize(size);
102 positiveLambda.resize(size);
103
104 double m = -J;
105 double q1 = getQ1(m, OmegaQ, OmegaD);
106 double q2 = getQ2(m, J, OmegaD);
107 double q3 = getQ3(m, OmegaQ, OmegaD);
108 double qq = getQQ(q1, q2);
109 double Wm = std::sqrt(qq);
110
111 positiveLambda[0] = getPositiveLambda(q3, Wm);
112 negativeLambda[0] = getBaseLambda(OmegaQ, OmegaD, J);
113 cos2AlphaSquared[0] = getCos2AlphaSquared(q1, qq);
114
115 for (size_t i = 1; i < size - 1; i++) {
116 m = static_cast<double>(i) - J;
117 q1 = getQ1(m, OmegaQ, OmegaD);
118 q2 = getQ2(m, J, OmegaD);
119 q3 = getQ3(m, OmegaQ, OmegaD);
120 qq = getQQ(q1, q2);
121 Wm = std::sqrt(qq);
122
123 positiveLambda[i] = getPositiveLambda(q3, Wm);
124 negativeLambda[i] = getNegativeLambda(q3, Wm);
125 cos2AlphaSquared[i] = getCos2AlphaSquared(q1, qq);
126 }
127
128 m = static_cast<double>(size) - 1 - J;
129 q1 = getQ1(m, OmegaQ, OmegaD);
130 q2 = getQ2(m, J, OmegaD);
131 q3 = getQ3(m, OmegaQ, OmegaD);
132 qq = getQQ(q1, q2);
133 Wm = std::sqrt(qq);
134
135 positiveLambda[size - 1] = getBaseLambda(OmegaQ, OmegaD, J);
136 negativeLambda[size - 1] = getNegativeLambda(q3, Wm);
137 cos2AlphaSquared[size - 1] = getCos2AlphaSquared(q1, qq);
138}
139
148double Meier::getQ1(const double &m, const double &OmegaQ, const double &OmegaD) const {
149 return (OmegaQ + OmegaD) * (2 * m - 1);
150}
151
160double Meier::getQ2(const double &m, const double &J, const double &OmegaD) const {
161 return OmegaD * std::sqrt(J * (J + 1) - m * (m - 1));
162}
163
172double Meier::getQ3(const double &m, const double &OmegaQ, const double &OmegaD) const {
173 return OmegaQ * (2 * pow(m, 2) - 2 * m + 1) + OmegaD;
174}
175
183double Meier::getQQ(const double &q1, const double &q2) const { return pow(q1, 2) + pow(q2, 2); }
184
192double Meier::getPositiveLambda(const double &q3, const double &Wm) const { return 0.5 * (q3 + Wm); }
193
201double Meier::getNegativeLambda(const double &q3, const double &Wm) const { return 0.5 * (q3 - Wm); }
202
212double Meier::getBaseLambda(const double &OmegaQ, const double &OmegaD, const double &J) const {
213 return OmegaQ * pow(J, 2) - OmegaD * J;
214}
215
223double Meier::getCos2AlphaSquared(const double &q1, const double &qq) const { return qq > 0 ? pow(q1, 2) / qq : 0; }
224
234void Meier::calculatePx(std::valarray<double> &Px, const std::valarray<double> &xValues,
235 const std::valarray<double> &cos2AlphaSquared, const std::valarray<double> &negativeLambda,
236 const std::valarray<double> &positiveLambda, const double &J2) const {
237 std::valarray<double> tx(xValues.size());
238 for (int i = 0; i < int(J2) + 1; i++) {
239 const double cosAlphaSquared = getCosSquared(cos2AlphaSquared[i]);
240 const double sinAlphaSquared = getSinSquared(cosAlphaSquared);
241
242 const double cosAlphaSquared2 = getCosSquared(cos2AlphaSquared[i + 1]);
243 const double sinAlphaSquared2 = getSinSquared(cosAlphaSquared2);
244
245 const std::valarray<double> a =
246 cosAlphaSquared2 * sinAlphaSquared * std::cos((positiveLambda[i + 1] - positiveLambda[i]) * xValues);
247 const std::valarray<double> b =
248 cosAlphaSquared2 * cosAlphaSquared * std::cos((positiveLambda[i + 1] - negativeLambda[i]) * xValues);
249 const std::valarray<double> c =
250 sinAlphaSquared2 * sinAlphaSquared * std::cos((negativeLambda[i + 1] - positiveLambda[i]) * xValues);
251 const std::valarray<double> d =
252 sinAlphaSquared2 * cosAlphaSquared * std::cos((negativeLambda[i + 1] - negativeLambda[i]) * xValues);
253 tx += a + b + c + d;
254 }
255 const double J = J2 / 2;
256 Px = tx / (2 * J + 1);
257}
258
268void Meier::calculatePz(std::valarray<double> &Pz, const std::valarray<double> &xValues,
269 const std::valarray<double> &cos2AlphaSquared, const std::valarray<double> &negativeLambda,
270 const std::valarray<double> &positiveLambda, const double &J2) const {
271 std::valarray<double> tz(xValues.size());
272 for (size_t i = 1; i < (size_t)J2 + 1; i++) {
273 const double sin2AlphaSquared = getSinSquared(cos2AlphaSquared[i]);
274 tz += cos2AlphaSquared[i] + sin2AlphaSquared * std::cos((positiveLambda[i] - negativeLambda[i]) * xValues);
275 }
276 const double J = J2 / 2;
277 Pz = (1 + tz) / (2 * J + 1);
278}
279} // namespace Mantid::CurveFitting::Functions
double value
The value of the point.
Definition FitMW.cpp:51
#define DECLARE_FUNCTION(classname)
Macro for declaring a new type of function to be used with the FunctionFactory.
Attribute is a non-fitting parameter.
Definition IFunction.h:285
double asDouble() const
Returns double value if attribute is a double, throws exception otherwise.
virtual Attribute getAttribute(const std::string &name) const
Return a value of attribute attName.
void declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue)
Declare a single attribute.
void declareParameter(const std::string &name, double initValue=0, const std::string &description="") override
Declare a new parameter.
double getParameter(size_t i) const override
Get i-th parameter.
void init() override
Function initialization. Declare function parameters in this method.
Definition Meier.cpp:40
double getCos2AlphaSquared(const double &q1, const double &qq) const
Calculates and returns the value of cos 2*alpha sequared at a given index i This function is used by ...
Definition Meier.cpp:223
void calculatePz(std::valarray< double > &Pz, const std::valarray< double > &xValues, const std::valarray< double > &cos2AlphaSquared, const std::valarray< double > &negativeLambda, const std::valarray< double > &positiveLambda, const double &J2) const
Calculates the polarization in the z direction.
Definition Meier.cpp:268
double getQ1(const double &m, const double &OmegaQ, const double &OmegaD) const
Calculates and returns the value of q1 This function is used by precomputeIntermediateSteps to calcul...
Definition Meier.cpp:148
double getQ3(const double &J, const double &OmegaQ, const double &OmegaD) const
Calculates and returns the value of q2 This function is used by precomputeIntermediateSteps to calcul...
Definition Meier.cpp:172
double getNegativeLambda(const double &q3, const double &Wm) const
Calculates and returns the value of negative lambda This function is used by precomputeIntermediateSt...
Definition Meier.cpp:201
void function1D(double *out, const double *xValues, const size_t nData) const override
Function you want to fit to.
Definition Meier.cpp:53
void calculatePx(std::valarray< double > &Px, const std::valarray< double > &xValues, const std::valarray< double > &cos2AlphaSquared, const std::valarray< double > &negativeLambda, const std::valarray< double > &positiveLambda, const double &J2) const
Calculates the polarization in the x direction.
Definition Meier.cpp:234
void precomputeIntermediateSteps(std::valarray< double > &cos2AlphaSquared, std::valarray< double > &negativeLambda, std::valarray< double > &positiveLambda, const double &J2) const
Precomputes intermediate terms used to calculate the polrization in the x and z directions.
Definition Meier.cpp:90
double getPositiveLambda(const double &q3, const double &Wm) const
Calculates and returns the value of positive lambda This function is used by precomputeIntermediateSt...
Definition Meier.cpp:192
double getQ2(const double &m, const double &J, const double &OmegaD) const
Calculates and returns the value of q2 This function is used by precomputeIntermediateSteps to calcul...
Definition Meier.cpp:160
double getBaseLambda(const double &OmegaQ, const double &OmegaD, const double &J) const
Calculates and returns the value of lambda for the special cases i.e it is the value of the first ele...
Definition Meier.cpp:212
double getQQ(const double &q1, const double &q2) const
Calculates and returns the value of qq This function is used by precomputeIntermediateSteps to calcul...
Definition Meier.cpp:183
LambdaValidator provides a quick way to create custom validation objects using a validator function o...