15#include <boost/lexical_cast.hpp>
17#include <gsl/gsl_sf_erf.h>
30using namespace CurveFitting;
43 m_cancel(false), m_parallelException(false), m_dspaceCalculated(false) {
57 declareParameter(
"Dtt1", 1.0,
"coefficient 1 for d-spacing calculation for epithermal neutron part");
58 declareParameter(
"Dtt2", 1.0,
"coefficient 2 for d-spacing calculation for epithermal neutron part");
59 declareParameter(
"Dtt1t", 1.0,
"coefficient 1 for d-spacing calculation for thermal neutron part");
60 declareParameter(
"Dtt2t", 1.0,
"coefficient 2 for d-spacing calculation for thermal neutron part");
64 declareParameter(
"Tcross", 1.0,
"position of the centre of the crossover region");
67 declareParameter(
"Alph0", 1.6,
"exponential constant for rising part of epithermal neutron pulse");
68 declareParameter(
"Alph1", 1.5,
"exponential constant for rising part of expithermal neutron pulse");
69 declareParameter(
"Beta0", 1.6,
"exponential constant of decaying part of epithermal neutron pulse");
70 declareParameter(
"Beta1", 1.5,
"exponential constant of decaying part of epithermal neutron pulse");
71 declareParameter(
"Alph0t", 1.6,
"exponential constant for rising part of thermal neutron pulse");
72 declareParameter(
"Alph1t", 1.5,
"exponential constant for rising part of thermal neutron pulse");
73 declareParameter(
"Beta0t", 1.6,
"exponential constant of decaying part of thermal neutron pulse");
74 declareParameter(
"Beta1t", 1.5,
"exponential constant of decaying part of thermal neutron pulse");
78 "variance parameter 1 of the Gaussian "
79 "component of the psuedovoigt function");
81 "variance parameter 2 of the Gaussian "
82 "component of the psuedovoigt function");
84 "variance parameter 3 of the Gaussian "
85 "component of the psuedovoigt function");
88 "FWHM parameter 1 of the Lorentzian component "
89 "of the psuedovoigt function");
91 "FWHM parameter 2 of the Lorentzian component "
92 "of the psuedovoigt function");
94 "FWHM parameter 3 of the Lorentzian component "
95 "of the psuedovoigt function");
98 declareParameter(
"LatticeConstant", 10.0,
"lattice constant for the sample");
181 if (paramname ==
"Alpha")
183 else if (paramname ==
"Beta")
185 else if (paramname ==
"Sigma2")
187 else if (paramname ==
"Gamma")
189 else if (paramname ==
"d_h")
191 else if (paramname ==
"Eta")
193 else if (paramname ==
"TOF_h")
195 else if (paramname ==
"FWHM")
199 errss <<
"Parameter " << paramname <<
" does not exist in peak function " << this->
name()
200 <<
"'s calculated parameters. "
201 <<
"Candidates are Alpha, Beta, Sigma2, Gamma d_h and Eta. ";
202 throw runtime_error(errss.str());
241 double dh, tof_h, eta, alpha, beta, H, sigma2, gamma, N;
245 m_unitCell.
set(latticeconstant, latticeconstant, latticeconstant, 90.0, 90.0, 90.0);
255 double n = 0.5 * gsl_sf_erfc(wcross * (Tcross - 1 / dh));
257 double alpha_e = alph0 + alph1 * dh;
258 double alpha_t = alph0t - alph1t / dh;
259 alpha = 1 / (
n * alpha_e + (1 -
n) * alpha_t);
261 double beta_e = beta0 + beta1 * dh;
262 double beta_t = beta0t - beta1t / dh;
263 beta = 1 / (
n * beta_e + (1 -
n) * beta_t);
265 double Th_e = zero + dtt1 * dh;
266 double Th_t = zerot + dtt1t * dh - dtt2t / dh;
267 tof_h =
n * Th_e + (1 -
n) * Th_t;
269 sigma2 = sig0 * sig0 + sig1 * sig1 * std::pow(dh, 2) + sig2 * sig2 * std::pow(dh, 4);
270 gamma = gam0 + gam1 * dh + gam2 * std::pow(dh, 2);
275 N = alpha * beta * 0.5 / (alpha + beta);
288 if (alpha != alpha || beta != beta || sigma2 != sigma2 || gamma != gamma || H != H || H <= 0.) {
295 if (explicitoutput) {
297 errss <<
"alpha = " << alpha <<
", beta = " << beta <<
", N = " << N <<
"\n";
298 errss <<
" n = " <<
n <<
", alpha_e = " << alpha_e <<
", alpha_t = " << alpha_t <<
"\n";
299 errss <<
" dh = " << dh <<
", alph0t = " << alph0t <<
", alph1t = " << alph1t <<
", alph0 = " << alph0
300 <<
", alph1 = " << alph1 <<
"\n";
301 errss <<
" n = " <<
n <<
", beta_e = " << beta_e <<
", beta_t = " << beta_t <<
"\n";
302 errss <<
" dh = " << dh <<
", beta0t = " << beta0t <<
", beta1t = " << beta1t <<
"\n";
330 double invert_sqrt2sigma = 1.0 / sqrt(2.0 *
m_Sigma2);
336 for (
size_t id = 0;
id < nData; ++id) {
343 if (
fabs(dT) < peakrange) {
387 const double INVERT_SQRT2SIGMA = 1.0 / sqrt(2.0 *
m_Sigma2);
399 const double LEFT_VALUE =
m_centre - RANGE;
400 auto iter = std::lower_bound(xValues.begin(), xValues.end(), LEFT_VALUE);
402 const double RIGHT_VALUE =
m_centre + RANGE;
403 auto iter_end = std::lower_bound(iter, xValues.end(), RIGHT_VALUE);
406 std::size_t pos(std::distance(xValues.begin(), iter));
407 for (; iter != iter_end; ++iter) {
473 double H_G = sqrt(8.0 * sigma2 * M_LN2);
476 double temp1 = std::pow(H_L, 5) + 0.07842 * H_G * std::pow(H_L, 4) + 4.47163 * std::pow(H_G, 2) * std::pow(H_L, 3) +
477 2.42843 * std::pow(H_G, 3) * std::pow(H_L, 2) + 2.69269 * std::pow(H_G, 4) * H_L + std::pow(H_G, 5);
479 H = std::pow(temp1, 0.2);
482 double gam_pv = H_L / H;
483 eta = 1.36603 * gam_pv - 0.47719 * std::pow(gam_pv, 2) + 0.11116 * std::pow(gam_pv, 3);
485 if (eta > 1 || eta < 0) {
486 g_log.
warning() <<
"Calculated eta = " << eta <<
" is out of range [0, 1].\n";
495 const double beta,
const double H,
const double sigma2,
496 const double invert_sqrt2sigma,
const bool explicitoutput)
const {
497 const double u = 0.5 * alpha * (alpha * sigma2 + 2. *
x);
498 const double y = (alpha * sigma2 +
x) * invert_sqrt2sigma;
500 const double v = 0.5 * beta * (beta * sigma2 - 2. *
x);
501 const double z = (beta * sigma2 -
x) * invert_sqrt2sigma;
505 const double erfcy = gsl_sf_erfc(
y);
507 if (
fabs(erfcy) > DBL_MIN)
508 part1 = exp(u) * erfcy;
510 const double erfcz = gsl_sf_erfc(
z);
512 if (
fabs(erfcz) > DBL_MIN)
513 part2 = exp(v) * erfcz;
515 const double omega1 = (1. - eta) * N * (part1 + part2);
518 const double SQRT_H_5 = sqrt(H) * .5;
519 std::complex<double> p(alpha *
x, alpha * SQRT_H_5);
520 std::complex<double> q(-beta *
x, beta * SQRT_H_5);
523 omega2 = -1.0 * N * eta * (omega2a + omega2b) * M_2_PI;
525 const double omega = omega1 + omega2;
527 if (explicitoutput) {
528 if (omega <= NEG_DBL_MAX || omega >= DBL_MAX) {
530 errss <<
"Find omega = " << omega <<
" is infinity! omega1 = " << omega1 <<
", omega2 = " << omega2 <<
"\n";
531 errss <<
" u = " << u <<
", v = " << v <<
", erfc(y) = " << gsl_sf_erfc(
y) <<
", erfc(z) = " << gsl_sf_erfc(
z)
533 errss <<
" alpha = " << alpha <<
", x = " <<
x <<
" sigma2 = " << sigma2 <<
", N = " << N <<
"\n";
566 if (
name ==
"LatticeConstant") {
678 for (
size_t i = 0; i < nData; ++i) {
679 if (
fabs(xValues[i] - c) < dx) {
681 i0 =
static_cast<int>(i);
687 if (i0 < 0 ||
n == 0)
double value
The value of the point.
#define DECLARE_FUNCTION(classname)
Macro for declaring a new type of function to be used with the FunctionFactory.
Base class that represents the domain of a function.
static Kernel::Logger g_log
Logger instance.
void calNumericalDeriv(const FunctionDomain &domain, Jacobian &jacobian)
Calculate numerical derivatives.
An interface to a peak function, which extend the interface of IFunctionWithLocation by adding method...
bool m_cellParamValueChanged
An indicator to re-calculate peak d-space position.
bool m_parameterValid
Flag to indicate whether peaks' parameters value can generate a valid peak.
double m_unitCellSize
Unit cell size.
virtual double height() const
Get peak's intensity.
Geometry::UnitCell m_unitCell
Unit cell.
double m_centre
Centre of the peak.
bool m_hasNewParameterValue
Flag if any parameter value changed.
virtual double fwhm() const
Get peakl's FWHM.
double m_dcentre
Centre of the peak in d-space.
double m_fwhm
Peak's FWHM.
virtual double centre() const
Overwrite IFunction base class methods.
Represents the Jacobian in IFitFunction::functionDeriv.
void setParameter(size_t, const double &value, bool explicitlySet=true) override
Set i-th parameter.
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.
ThermalNeutronBk2BkExpConvPVoigt : Back-to-back exponential convoluted with pseudo Voigt for thermal ...
std::string name() const override
Overwrite IFunction base class methods.
void calHandEta(double sigma2, double gamma, double &H, double &eta) const
Calcualte H and Eta.
double calOmega(const double x, const double eta, const double N, const double alpha, const double beta, const double H, const double sigma2, const double invert_sqrt2sigma, const bool explicitoutput=false) const
Calculate peak profile I(TOF) = Omega(TOF)
void functionDeriv(const API::FunctionDomain &domain, API::Jacobian &jacobian) override
Derivative.
double getPeakParameter(const std::string &) override
Overwrite IPeakFunction base class methods.
void function1D(double *out, const double *xValues, const size_t nData) const override
Function you want to fit to.
void init() override
Overwrite IFunction base class method, which declare function parameters.
void setParameter(size_t i, const double &value, bool explicitlySet=true) override
Core function to calcualte peak values for whole region.
void functionLocal(double *out, const double *xValues, const size_t nData) const
Fuction local.
void function(std::vector< double > &out, const std::vector< double > &xValues) const override
Function (local) of the vector version.
virtual void functionDerivLocal(API::Jacobian *out, const double *xValues, const size_t nData)
Derivative.
static int s_peakRadius
Default value for the peak radius.
double m_Alpha
Set 2 functions to be hidden from client.
void calculateParameters(bool explicitoutput) const override
Calculate peak parameters (alpha, beta, sigma2..)
void set(double _a, double _b, double _c, double _alpha, double _beta, double _gamma, const int angleunit=angDegrees)
Set lattice parameters.
double d(double h, double k, double l) const
Return d-spacing ( ) for a given h,k,l coordinate.
Marks code as not implemented yet.
The Logger class is in charge of the publishing messages from the framework through various channels.
void notice(const std::string &msg)
Logs at notice level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
std::complex< double > MANTID_API_DLL E1(std::complex< double > z)
Integral for Gamma.
Kernel::Logger g_log("ExperimentInfo")
static logger object
Helper class which provides the Collimation Length for SANS instruments.