24#include <gsl/gsl_math.h>
25#include <gsl/gsl_multifit_nlin.h>
26#include <gsl/gsl_sf_erf.h>
31using namespace CurveFitting;
35Kernel::Logger
g_log(
"IkedaCarpenterPV");
38using namespace Kernel;
40using namespace CurveFitting::SpecialFunctionSupport;
42using namespace Geometry;
43using namespace Constraints;
55 double minCutOff = 100.0 * std::numeric_limits<double>::min();
56 if (h0 > 0 && h0 < minCutOff)
58 if (h0 < 0 && h0 > -minCutOff)
79 if (sigmaSquared < 0) {
81 <<
"Likely due to a fit not converging properly\n"
82 <<
"If this is frequent problem please report to Mantid team.\n"
83 <<
"For now to calculate width force SigmaSquared positive.\n";
84 sigmaSquared = -sigmaSquared;
88 <<
"Likely due to a fit not converging properly\n"
89 <<
"If this is frequent problem please report to Mantid team.\n"
90 <<
"For now to calculate width force Gamma positive.\n";
94 return sqrt(8.0 * M_LN2 * sigmaSquared) + gamma;
106 "The integrated intensity of the peak. I.e. "
107 "approximately equal to HWHM times height of "
116 declareParameter(
"Kappa", 46.0,
"Controls contribution of slow decay term");
118 declareParameter(
"SigmaSquared", 1.0,
"standard deviation squared (Voigt Guassian broadening)");
127 auto mixingConstraint = std::make_unique<BoundaryConstraint>(
this, paramName, 0.0,
true);
128 mixingConstraint->setPenaltyFactor(1e9);
150 for (
size_t i = 0; i < nData; i++) {
161 if (sample !=
nullptr) {
164 g_log.
warning() <<
"No sample set for instrument in workspace.\n"
165 <<
"Can't calculate wavelength in IkedaCarpenter.\n"
166 <<
"Default all wavelengths to one.\n"
167 <<
"Solution is to load appropriate instrument into workspace.\n";
168 for (
size_t i = 0; i < nData; i++)
173 <<
"Can't calculate wavelength in IkedaCarpenter.\n"
174 <<
"Default all wavelengths to one.\n"
175 <<
"Solution call setMatrixWorkspace() for function.\n";
176 for (
size_t i = 0; i < nData; i++)
191 double fwhmGsq = 8.0 * M_LN2 * voigtSigmaSq;
192 double fwhmG = sqrt(fwhmGsq);
193 double fwhmG4 = fwhmGsq * fwhmGsq;
194 double fwhmL = voigtGamma;
195 double fwhmLsq = voigtGamma * voigtGamma;
196 double fwhmL4 = fwhmLsq * fwhmLsq;
198 H = pow(fwhmG4 * fwhmG + 2.69269 * fwhmG4 * fwhmL + 2.42843 * fwhmGsq * fwhmG * fwhmLsq +
199 4.47163 * fwhmGsq * fwhmLsq * fwhmL + 0.07842 * fwhmG * fwhmL4 + fwhmL4 * fwhmL,
203 H = std::numeric_limits<double>::epsilon() * 1000.0;
205 double tmp = fwhmL / H;
216 const double voigtsigmaSquared =
getParameter(
"SigmaSquared");
224 double sigmaSquared = gamma * gamma / (8.0 * M_LN2);
226 const double beta = 1 / beta0;
230 const double k = 0.05;
234 double someConst = std::numeric_limits<double>::max() / 100.0;
235 if (sigmaSquared > 0)
236 someConst = 1 / sqrt(2.0 * sigmaSquared);
237 else if (sigmaSquared < 0) {
238 g_log.
warning() <<
"sigmaSquared negative in functionLocal.\n";
244 for (
int i = 0; i < nData; i++) {
245 double diff = xValues[i] - X0;
248 double alpha = 1.0 / (alpha0 +
m_waveLength[i] * alpha1);
250 double a_minus = alpha * (1 - k);
251 double a_plus = alpha * (1 + k);
252 double x = a_minus - beta;
253 double y = alpha - beta;
254 double z = a_plus - beta;
256 double Nu = 1 - R * a_minus /
x;
257 double Nv = 1 - R * a_plus /
z;
258 double Ns = -2 * (1 - R * alpha /
y);
259 double Nr = 2 * R * alpha * alpha * beta * k * k / (
x *
y *
z);
261 double u = a_minus * (a_minus * sigmaSquared - 2 * diff) / 2.0;
262 double v = a_plus * (a_plus * sigmaSquared - 2 * diff) / 2.0;
263 double s = alpha * (alpha * sigmaSquared - 2 * diff) / 2.0;
264 double r = beta * (beta * sigmaSquared - 2 * diff) / 2.0;
266 double yu = (a_minus * sigmaSquared - diff) * someConst;
267 double yv = (a_plus * sigmaSquared - diff) * someConst;
268 double ys = (alpha * sigmaSquared - diff) * someConst;
269 double yr = (beta * sigmaSquared - diff) * someConst;
271 std::complex<double> zs = std::complex<double>(-alpha * diff, 0.5 * alpha * gamma);
272 std::complex<double> zu = (1 - k) * zs;
273 std::complex<double> zv = (1 + k) * zs;
274 std::complex<double> zr = std::complex<double>(-beta * diff, 0.5 * beta * gamma);
276 double N = 0.25 * alpha * (1 - k * k) / (k * k);
279 ((1 - eta) * (Nu * exp(u + gsl_sf_log_erfc(yu)) + Nv * exp(v + gsl_sf_log_erfc(yv)) +
280 Ns * exp(s + gsl_sf_log_erfc(ys)) + Nr * exp(r + gsl_sf_log_erfc(yr))) -
293 const double voigtsigmaSquared =
getParameter(
"SigmaSquared");
301 double sigmaSquared = gamma * gamma / (8.0 * M_LN2);
303 const double beta = 1 / beta0;
307 const double k = 0.05;
311 double someConst = std::numeric_limits<double>::max() / 100.0;
312 if (sigmaSquared > 0)
313 someConst = 1 / sqrt(2.0 * sigmaSquared);
314 else if (sigmaSquared < 0) {
315 g_log.
warning() <<
"sigmaSquared negative in functionLocal.\n";
321 for (
size_t i = 0; i < nData; i++) {
322 double diff = xValues[i] - X0;
325 double alpha = 1.0 / (alpha0 +
m_waveLength[i] * alpha1);
327 double a_minus = alpha * (1 - k);
328 double a_plus = alpha * (1 + k);
329 double x = a_minus - beta;
330 double y = alpha - beta;
331 double z = a_plus - beta;
333 double Nu = 1 - R * a_minus /
x;
334 double Nv = 1 - R * a_plus /
z;
335 double Ns = -2 * (1 - R * alpha /
y);
336 double Nr = 2 * R * alpha * alpha * beta * k * k / (
x *
y *
z);
338 double u = a_minus * (a_minus * sigmaSquared - 2 * diff) / 2.0;
339 double v = a_plus * (a_plus * sigmaSquared - 2 * diff) / 2.0;
340 double s = alpha * (alpha * sigmaSquared - 2 * diff) / 2.0;
341 double r = beta * (beta * sigmaSquared - 2 * diff) / 2.0;
343 double yu = (a_minus * sigmaSquared - diff) * someConst;
344 double yv = (a_plus * sigmaSquared - diff) * someConst;
345 double ys = (alpha * sigmaSquared - diff) * someConst;
346 double yr = (beta * sigmaSquared - diff) * someConst;
348 std::complex<double> zs = std::complex<double>(-alpha * diff, 0.5 * alpha * gamma);
349 std::complex<double> zu = (1 - k) * zs;
350 std::complex<double> zv = (1 + k) * zs;
351 std::complex<double> zr = std::complex<double>(-beta * diff, 0.5 * beta * gamma);
353 double N = 0.25 * alpha * (1 - k * k) / (k * k);
356 ((1 - eta) * (Nu * exp(u + gsl_sf_log_erfc(yu)) + Nv * exp(v + gsl_sf_log_erfc(yv)) +
357 Ns * exp(s + gsl_sf_log_erfc(ys)) + Nr * exp(r + gsl_sf_log_erfc(yr))) -
384 double startX,
double endX) {
391 if (scaleFactor != 0) {
#define DECLARE_FUNCTION(classname)
Macro for declaring a new type of function to be used with the FunctionFactory.
IPeaksWorkspace_sptr workspace
Base class that represents the domain of a function.
size_t m_workspaceIndex
An index to a spectrum.
void setMatrixWorkspace(std::shared_ptr< const API::MatrixWorkspace > workspace, size_t wi, double startX, double endX) override
Set MatrixWorkspace.
std::shared_ptr< const API::MatrixWorkspace > getMatrixWorkspace() const
Get shared pointer to the workspace.
bool isActive(size_t i) const
Check if an active parameter i is actually active.
virtual double getParameter(size_t i) const =0
Get i-th parameter.
double convertValue(double value, Kernel::Unit_sptr &outUnit, const std::shared_ptr< const MatrixWorkspace > &ws, size_t wsIndex) const
Convert a value from one unit (inUnit) to unit defined in workspace (ws)
void calNumericalDeriv(const FunctionDomain &domain, Jacobian &jacobian)
Calculate numerical derivatives.
virtual size_t parameterIndex(const std::string &name) const =0
Returns the index of parameter name.
virtual void addConstraint(std::unique_ptr< IConstraint > ic)
Add a constraint to function.
virtual void declareParameter(const std::string &name, double initValue=0, const std::string &description="")=0
Declare a new parameter.
void setParameter(const std::string &name, const double &value, bool explicitlySet=true) override
Override parent so that we may bust the cache when a parameter is set.
virtual std::pair< double, double > getDomainInterval(double level=DEFAULT_SEARCH_LEVEL) const
Get the interval on which the peak has all its values above a certain level.
Represents the Jacobian in IFitFunction::functionDeriv.
IntegrationResult integrate(const IPeakFunction &peakFunction, double lowerLimit, double upperLimit) const
Integration of peak function on the interval [a, b].
Provide Ikeda-Carpenter-pseudo-Voigt peak shape function interface to IPeakFunction.
void functionLocal(double *out, const double *xValues, const size_t nData) const override
Function evaluation method to be implemented in the inherited classes.
void constFunction(double *out, const double *xValues, const int &nData) const
calculate the const function
void setHeight(const double h) override
Sets the parameters such that height == h.
void setCentre(const double c) override
Sets the parameters such that centre == c.
double intensity() const override
Returns the integral intensity of the peak.
double centre() const override
overwrite IPeakFunction base class methods
void init() override
overwrite IFunction base class method, which declare function parameters
void setMatrixWorkspace(std::shared_ptr< const API::MatrixWorkspace > workspace, size_t wi, double startX, double endX) override
Set MatrixWorkspace.
void setFwhm(const double w) override
Sets the parameters such that FWHM = w.
void lowerConstraint0(const std::string ¶mName)
constrain all parameters to be non-negative
std::vector< double > m_waveLength
container for storing wavelength values for each data point
double height() const override
Returns the height of the function.
void convertVoigtToPseudo(const double &voigtSigmaSq, const double &voigtGamma, double &H, double &eta) const
convert voigt params to pseudo voigt params
void functionDerivLocal(API::Jacobian *out, const double *xValues, const size_t nData) override
Derivative evaluation method. Default is to calculate numerically.
void functionDeriv(const API::FunctionDomain &domain, API::Jacobian &jacobian) override
Derivatives of function with respect to active parameters.
double fwhm() const override
Returns the peak FWHM.
void calWavelengthAtEachDataPoint(const double *xValues, const size_t &nData) const
method for updating m_waveLength
Marks code as not implemented yet.
void debug(const std::string &msg)
Logs at debug level.
void warning(const std::string &msg)
Logs at warning level.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::complex< double > MANTID_CURVEFITTING_DLL exponentialIntegral(const std::complex< double > &z)
Compute exp(z)*E1(z) where z is complex and E1(z) is the Exponential Integral.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
std::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.