Mantid
Loading...
Searching...
No Matches
ComptonProfile.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 +
14
15#include <gsl/gsl_poly.h>
16
18
19using namespace CurveFitting;
20using namespace CurveFitting::Algorithms;
21using namespace Mantid::API;
22
23namespace {
25// const char * WSINDEX_NAME = "WorkspaceIndex";
26const char *MASS_NAME = "Mass";
28} // namespace
29
31 : API::ParamFunction(), API::IFunction1D(), m_log("ComptonProfile"), m_wsIndex(0), m_startX(0.0), m_endX(0.0),
32 m_voigt(), m_resolutionFunction(std::dynamic_pointer_cast<VesuvioResolution>(
33 FunctionFactory::Instance().createFunction("VesuvioResolution"))),
34 m_yspace(), m_modQ(), m_e0(), m_mass(0.0) {}
35
36//-------------------------------------- Function evaluation
37//-----------------------------------------
38
47void ComptonProfile::function1D(double *out, const double *xValues, const size_t nData) const {
48 UNUSED_ARG(xValues); // Y-space values have already been pre-cached
49
50 this->massProfile(out, nData);
51
52 m_log.setEnabled(false);
53}
54
55/*
56 * Creates the internal caches
57 */
59
60 using namespace Mantid::API;
61 m_voigt = std::dynamic_pointer_cast<IPeakFunction>(FunctionFactory::Instance().createFunction("Voigt"));
62 m_resolutionFunction->setUpForFit();
63}
64
72void ComptonProfile::setMatrixWorkspace(std::shared_ptr<const API::MatrixWorkspace> workspace, size_t wsIndex,
73 double startX, double endX) {
74 auto inst = workspace->getInstrument();
75 auto sample = inst->getSample();
76 auto source = inst->getSource();
77 if (!sample || !source) {
78 throw std::invalid_argument("ComptonProfile - Workspace has no source/sample.");
79 }
81 m_wsIndex = wsIndex;
82 m_startX = startX;
83 m_endX = endX;
84
86}
87
89 const auto &spectrumInfo = m_workspace->spectrumInfo();
90 if (!spectrumInfo.hasDetectors(m_wsIndex)) {
91 throw std::invalid_argument("ComptonProfile - Workspace has no detector "
92 "attached to histogram at index " +
94 }
95
96 m_resolutionFunction->setAttributeValue("Mass", m_mass);
98
100 this->cacheYSpaceValues(m_workspace->points(m_wsIndex), detpar);
101}
102
103void ComptonProfile::cacheYSpaceValues(const HistogramData::Points &tseconds, const Algorithms::DetectorParams &detpar,
104 const ResolutionParams &respar) {
105 m_resolutionFunction->setAttributeValue("Mass", m_mass);
106 m_resolutionFunction->cacheResolutionComponents(detpar, respar);
107 this->cacheYSpaceValues(tseconds, detpar);
108}
109
114void ComptonProfile::cacheYSpaceValues(const HistogramData::Points &tseconds,
115 const Algorithms::DetectorParams &detpar) {
116
117 // ------ Fixed coefficients related to resolution & Y-space transforms
118 // ------------------
120 const double massToMeV = 0.5 * PhysicalConstants::NeutronMass / PhysicalConstants::meV; // Includes factor of 1/2
121
122 const double v1 = std::sqrt(detpar.efixed / massToMeV);
123 const double k1 = std::sqrt(detpar.efixed / mevToK);
124
125 // Calculate energy dependent factors and transform q to Y-space
126 const size_t nData = tseconds.size();
127
128 m_e0.resize(nData);
129 m_modQ.resize(nData);
130 m_yspace.resize(nData);
131 for (size_t i = 0; i < nData; ++i) {
132 const double tsec = tseconds[i];
133 ConvertToYSpace::calculateY(m_yspace[i], m_modQ[i], m_e0[i], m_mass, tsec, k1, v1, detpar);
134 }
135}
136
137void ComptonProfile::declareParameters() { declareParameter(MASS_NAME, 0.0, "Atomic mass (amu)"); }
138
139void ComptonProfile::setParameter(size_t i, const double &value, bool explicitlySet) {
140 ParamFunction::setParameter(i, value, explicitlySet);
141
142 // Mass parameter has changed, need to rebuild Y-space cache
143 if (i == parameterIndex(MASS_NAME) && m_mass != value) {
144 m_mass = value;
145 m_resolutionFunction->setAttributeValue("Mass", m_mass);
146
147 if (m_workspace)
148 buildCaches();
149 }
150}
151
163void ComptonProfile::voigtApproxDiff(std::vector<double> &voigtDiff, const std::vector<double> &yspace,
164 const double lorentzPos, const double lorentzAmp, const double lorentzWidth,
165 const double gaussWidth) const {
166 double miny(DBL_MAX), maxy(-DBL_MAX);
167 auto iend = yspace.end();
168 for (auto itr = yspace.begin(); itr != iend; ++itr) {
169 const double absy = std::abs(*itr);
170 if (absy < miny)
171 miny = absy;
172 else if (absy > maxy)
173 maxy = absy;
174 }
175 const double epsilon = (maxy - miny) / 1000.0;
176
177 // Compute: V = (voigt(y+2eps,...) - voigt(y-2eps,...) - 2*voigt(y+eps,...) +
178 // 2*(voigt(y-eps,...))/(2eps^3)
179
180 std::vector<double> ypmEps(yspace.size());
181 // y+2eps
182 using std::placeholders::_1;
183 std::transform(yspace.begin(), yspace.end(), ypmEps.begin(),
184 std::bind(std::plus<double>(), _1, 2.0 * epsilon)); // Add 2 epsilon
185 m_resolutionFunction->voigtApprox(voigtDiff, ypmEps, lorentzPos, lorentzAmp, lorentzWidth, gaussWidth);
186 // y-2eps
187 std::transform(yspace.begin(), yspace.end(), ypmEps.begin(),
188 std::bind(std::minus<double>(), _1, 2.0 * epsilon)); // Subtract 2 epsilon
189 std::vector<double> tmpResult(yspace.size());
190 m_resolutionFunction->voigtApprox(tmpResult, ypmEps, lorentzPos, lorentzAmp, lorentzWidth, gaussWidth);
191 // Difference of first two terms - result is put back in voigtDiff
192 std::transform(voigtDiff.begin(), voigtDiff.end(), tmpResult.begin(), voigtDiff.begin(), std::minus<double>());
193
194 // y+eps
195 std::transform(yspace.begin(), yspace.end(), ypmEps.begin(),
196 std::bind(std::plus<double>(), _1, epsilon)); // Add epsilon
197 m_resolutionFunction->voigtApprox(tmpResult, ypmEps, lorentzPos, lorentzAmp, lorentzWidth, gaussWidth);
198 std::transform(tmpResult.begin(), tmpResult.end(), tmpResult.begin(),
199 std::bind(std::multiplies<double>(), _1, 2.0)); // times 2
200 // Difference with 3rd term - result is put back in voigtDiff
201 std::transform(voigtDiff.begin(), voigtDiff.end(), tmpResult.begin(), voigtDiff.begin(), std::minus<double>());
202
203 // y-eps
204 std::transform(yspace.begin(), yspace.end(), ypmEps.begin(),
205 std::bind(std::minus<double>(), _1, epsilon)); // Subtract epsilon
206 m_resolutionFunction->voigtApprox(tmpResult, ypmEps, lorentzPos, lorentzAmp, lorentzWidth, gaussWidth);
207 std::transform(tmpResult.begin(), tmpResult.end(), tmpResult.begin(),
208 std::bind(std::multiplies<double>(), _1, 2.0)); // times 2
209 // Sum final term
210 std::transform(voigtDiff.begin(), voigtDiff.end(), tmpResult.begin(), voigtDiff.begin(), std::plus<double>());
211
212 // Finally divide by 2*eps^3
213 std::transform(voigtDiff.begin(), voigtDiff.end(), voigtDiff.begin(),
214 std::bind(std::divides<double>(), _1, 2.0 * std::pow(epsilon, 3)));
215}
216
217} // namespace Mantid::CurveFitting::Functions
double value
The value of the point.
Definition: FitMW.cpp:51
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition: System.h:64
This is a specialization of IFunction for functions of one real argument.
Definition: IFunction1D.h:43
Implements the part of IFunction interface dealing with parameters.
Definition: ParamFunction.h:33
void setParameter(size_t, const double &value, bool explicitlySet=true) override
Set i-th parameter.
size_t parameterIndex(const std::string &name) const override
Returns the index of parameter name.
void declareParameter(const std::string &name, double initValue=0, const std::string &description="") override
Declare a new parameter.
static DetectorParams getDetectorParameters(const API::MatrixWorkspace_const_sptr &ws, const size_t index)
Creates a POD struct containing the required detector parameters for this spectrum.
static void calculateY(double &yspace, double &qspace, double &ei, const double mass, const double tsec, const double k1, const double v1, const DetectorParams &detpar)
Convert single time value to Y,Q & Ei values.
virtual void massProfile(double *result, const size_t nData) const =0
Override to calculate the value of the profile for this mass and store in the given array.
std::vector< double > m_e0
Incident energies.
std::shared_ptr< const API::MatrixWorkspace > m_workspace
Current workspace.
void declareParameters() override
Declare parameters that will never participate in the fit.
std::shared_ptr< VesuvioResolution > m_resolutionFunction
Vesuvio resolution function.
ComptonProfile()
Default constructor required for factory.
void voigtApproxDiff(std::vector< double > &voigtDiff, const std::vector< double > &yspace, const double lorentzPos, const double lorentzAmp, const double lorentzWidth, const double gaussWidth) const
Compute Voigt function interpolated around the given values.
void setParameter(size_t i, const double &value, bool explicitlySet=true) override
Set i-th parameter.
void setMatrixWorkspace(std::shared_ptr< const API::MatrixWorkspace > workspace, size_t wsIndex, double startX, double endX) override
Cache a copy of the workspace pointer and pull out the parameters.
void buildCaches()
Initiate a Y-space value chache rebuild when workspace of mass are changed.
std::shared_ptr< API::IPeakFunction > m_voigt
Voigt function.
void function1D(double *out, const double *xValues, const size_t nData) const override
Calculates the value of the function for each x value and stores in the given output array.
void cacheYSpaceValues(const HistogramData::Points &tseconds, const Algorithms::DetectorParams &detpar, const ResolutionParams &respar)
Pre-calculate the Y-space values with specified resolution parameters.
size_t m_wsIndex
Current workspace index, required to access instrument parameters.
void setUpForFit() override
Ensure the object is ready to be fitted.
Calculate the resolution from a workspace of Vesuvio data using the mass & instrument definition.
void setEnabled(const bool enabled)
set if the logging is enabled
Definition: Logger.cpp:59
Manage the lifetime of a class intended to be a singleton.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
static constexpr double E_mev_toNeutronWavenumberSq
Transformation coefficient to transform neutron energy into neutron wavevector: K-neutron[m^-10] = sq...
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double meV
1 meV in Joules.
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
Simple data structure to store nominal detector values It avoids some functions taking a huge number ...
Simple data structure to store resolution parameter values It avoids some functions taking a huge num...