Mantid
Loading...
Searching...
No Matches
IPowderDiffPeakFunction.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//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
11#include "MantidAPI/Jacobian.h"
14
15#include <boost/lexical_cast.hpp>
16#include <cmath>
17
18const double IGNOREDCHANGE = 1.0E-9;
19
20namespace Mantid::API {
21
23
24//----------------------------------------------------------------------------------------------
29 : m_centre(0.), m_dcentre(0.), m_fwhm(0.), m_hasNewParameterValue(false), m_cellParamValueChanged(false),
30 m_sortedProfileParameterNames(), m_unitCell(), m_unitCellSize(0.), m_parameterValid(false), mH(0), mK(0), mL(0),
31 mHKLSet(false), LATTICEINDEX(9999), HEIGHTINDEX(9999) {
32 // Set peak's radius from configuration
33 auto peakRadius = Kernel::ConfigService::Instance().getValue<int>("curvefitting.peakRadius");
34 if (peakRadius.is_initialized() && peakRadius.get() != s_peakRadius) {
35 setPeakRadius(peakRadius.get());
36 }
37}
38
39//----------------------------------------------------------------------------------------------
45void IPowderDiffPeakFunction::setParameter(size_t i, const double &value, bool explicitlySet) {
46 double origparamvalue = getParameter(i);
47 if (fabs(origparamvalue - value) > IGNOREDCHANGE) {
49 }
50 ParamFunction::setParameter(i, value, explicitlySet);
51}
52
53//----------------------------------------------------------------------------------------------
59void IPowderDiffPeakFunction::setParameter(const std::string &name, const double &value, bool explicitlySet) {
60 double origparamvalue = getParameter(name);
61 if (fabs(origparamvalue - value) > IGNOREDCHANGE) {
63 }
64 ParamFunction::setParameter(name, value, explicitlySet);
65}
66
67//----------------------------------------------------------------------------------------------
71 // Re-calcualte peak parameters if required
74
75 return m_centre;
76}
77
78//----------------------------------------------------------------------------------------------
86//----------------------------------------------------------------------------------------------
97//----------------------------------------------------------------------------------------------
101
102//----------------------------------------------------------------------------------------------
106 double height = this->getParameter(HEIGHTINDEX);
107 return height;
108}
109
110//----------------------------------------------------------------------------------------------
115 calculateParameters(false);
116
117 return m_fwhm;
118}
119
120//----------------------------------------------------------------------------------------------
123double IPowderDiffPeakFunction::getMaximumValue(const std::vector<double> &xValues, size_t &indexmax) const {
124 // Calculate function with given data points
125 std::vector<double> out(xValues.size(), 0.);
126 function(out, xValues);
127
128 // Find out the maximum value
129 double max = -DBL_MAX;
130 indexmax = 0;
131 for (size_t i = 0; i < out.size(); ++i) {
132 if (out[i] > max) {
133 max = out[i];
134 indexmax = i;
135 }
136 }
137
138 return max;
139}
140
141//----------------------------------------------------------------------------------------------
145 // Check validity and set flag
146 if (mHKLSet) {
147 // Throw exception if tried to reset the miller index
148 std::stringstream errss;
149 errss << "Profile function " << name() << "cannot have (HKL) reset.";
150 throw std::runtime_error(errss.str());
151 } else {
152 // Set flag
153 mHKLSet = true;
154 }
155
156 // Set value
157 mH = static_cast<int>(h);
158 mK = static_cast<int>(k);
159 mL = static_cast<int>(l);
160
161 // Check value valid or not
162 if (mH * mH + mK * mK + mL * mL < 1.0E-8) {
163 std::stringstream errmsg;
164 errmsg << "H = K = L = 0 is not allowed";
165 throw std::invalid_argument(errmsg.str());
166 }
167}
168
169//----------------------------------------------------------------------------------------------
172void IPowderDiffPeakFunction::getMillerIndex(int &h, int &k, int &l) {
173 h = static_cast<int>(mH);
174 k = static_cast<int>(mK);
175 l = static_cast<int>(mL);
176}
177
178//----------------------------------------------------------------------------------------------
183 if (r > 0) {
184 s_peakRadius = r;
185
186 // std::string setting = boost::lexical_cast<std::string>(r);
187 // Kernel::ConfigService::Instance().setString("curvefitting.peakRadius",setting);
188 }
189}
190
191//----------------------------------------------------------------------------------------------
195 auto candname = lower_bound(m_sortedProfileParameterNames.begin(), m_sortedProfileParameterNames.end(), paramname);
196 if (candname == m_sortedProfileParameterNames.end())
197 return false;
198
199 return *candname != paramname;
200}
201
202//------------------------- External Functions
203//---------------------------------------------------
204// FIXME : This is the same function used for ThermalNeutron... ...
207std::complex<double> E1(std::complex<double> z) {
208 std::complex<double> exp_e1;
209
210 double rz = real(z);
211 double az = abs(z);
212
213 if (fabs(az) < 1.0E-8) {
214 // If z = 0, then the result is infinity... diverge!
215 std::complex<double> r(1.0E300, 0.0);
216 exp_e1 = r;
217 } else if (az <= 10.0 || (rz < 0.0 && az < 20.0)) {
218 // Some interesting region, equal to integrate to infinity, converged
219 // cout << "[DB] Type 1\n";
220
221 std::complex<double> r(1.0, 0.0);
222 exp_e1 = r;
223 std::complex<double> cr = r;
224
225 for (size_t k = 1; k <= 150; ++k) {
226 auto dk = double(k);
227 cr = -cr * dk * z / ((dk + 1.0) * (dk + 1.0));
228 exp_e1 += cr;
229 if (abs(cr) < abs(exp_e1) * 1.0E-15) {
230 // cr is converged to zero
231 break;
232 }
233 } // ENDFOR k
234
235 const double el = 0.5772156649015328;
236 exp_e1 = -el - log(z) + (z * exp_e1);
237 } else {
238 // Rest of the region
239 std::complex<double> ct0(0.0, 0.0);
240 for (int k = 120; k > 0; --k) {
241 std::complex<double> dk(double(k), 0.0);
242 ct0 = dk / (10.0 + dk / (z + ct0));
243 } // ENDFOR k
244
245 exp_e1 = 1.0 / (z + ct0);
246 exp_e1 = exp_e1 * exp(-z);
247 if (rz < 0.0 && fabs(imag(z)) < 1.0E-10) {
248 std::complex<double> u(0.0, 1.0);
249 exp_e1 = exp_e1 - (M_PI * u);
250 }
251 }
252
253 return exp_e1;
254}
255
256} // namespace Mantid::API
double value
The value of the point.
Definition: FitMW.cpp:51
const double IGNOREDCHANGE
#define fabs(x)
Definition: Matrix.cpp:22
virtual std::string name() const =0
Returns the function's name.
virtual void setPeakRadius(const int &r)
Set peak's radius.
virtual void setMillerIndex(int h, int k, int l)
Set Miller Indicies.
virtual double height() const
Get peak's intensity.
virtual void setHeight(const double h)
Set peak's height.
virtual double getMaximumValue(const std::vector< double > &xValues, size_t &indexmax) const
Get maximum value on a given set of data points.
void setParameter(size_t i, const double &value, bool explicitlySet=true) override
Override setting a new value to the i-th parameter.
virtual void getMillerIndex(int &h, int &k, int &l)
Get Miller Index from this peak.
virtual void calculateParameters(bool explicitoutput) const =0
Calculate peak parameters (alpha, beta, sigma2..)
bool m_hasNewParameterValue
Flag if any parameter value changed.
virtual double fwhm() const
Get peakl's FWHM.
virtual void function(std::vector< double > &out, const std::vector< double > &xValues) const =0
IPowderDiffPeakFunction()
Constructor and Destructor.
static int s_peakRadius
Local function for GSL minimizer.
std::vector< std::string > m_sortedProfileParameterNames
Peak profile parameters names in ascending order.
virtual bool hasProfileParameter(std::string paramname)
Check whether a parameter is a profile parameter.
virtual double centre() const
Overwrite IFunction base class methods.
void setParameter(size_t, const double &value, bool explicitlySet=true) override
Set i-th parameter.
double getParameter(size_t i) const override
Get i-th parameter.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::complex< double > MANTID_API_DLL E1(std::complex< double > z)
Integral for Gamma.