Mantid
Loading...
Searching...
No Matches
AbsorptionCorrection.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 +
10#include "MantidAPI/Sample.h"
20#include "MantidHistogramData/Interpolate.h"
29#include "MantidKernel/Unit.h"
31
32namespace Mantid::Algorithms {
33
34using namespace API;
35using namespace Geometry;
36using HistogramData::interpolateLinearInplace;
37using namespace Kernel;
38using Kernel::DeltaEMode;
39using namespace Mantid::PhysicalConstants;
40using namespace Mantid::DataObjects;
42
43namespace {
44// the maximum number of elements to combine at once in the pairwise summation
45constexpr size_t MAX_INTEGRATION_LENGTH{1000};
46
47const std::string CALC_SAMPLE = "Sample";
48const std::string CALC_CONTAINER = "Container";
49const std::string CALC_ENVIRONMENT = "Environment";
50
51inline size_t findMiddle(const size_t start, const size_t stop) {
52 auto half = static_cast<size_t>(floor(.5 * (static_cast<double>(stop - start))));
53 return start + half;
54}
55
56// wavelength = 2 pi / k
57double energyToWavelength(const double energyFixed) {
58 return 2. * M_PI * std::sqrt(E_mev_toNeutronWavenumberSq / energyFixed);
59}
60
61} // namespace
62
64 : API::Algorithm(), m_inputWS(), m_sampleObject(nullptr), m_L1s(), m_elementVolumes(), m_elementPositions(),
65 m_numVolumeElements(0), m_sampleVolume(0.0), m_linearCoefTotScatt(0), m_num_lambda(0), m_xStep(0),
66 m_emode(Kernel::DeltaEMode::Undefined), m_lambdaFixed(0.), EXPONENTIAL() {}
67
69
70 // The input workspace must have an instrument and units of wavelength
71 auto wsValidator = std::make_shared<CompositeValidator>();
72 wsValidator->add<WorkspaceUnitValidator>("Wavelength");
73 wsValidator->add<InstrumentValidator>();
74
75 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input, wsValidator),
76 "The X values for the input workspace must be in units of wavelength");
77 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
78 "Output workspace name");
79
80 // AbsorbedBy
81 std::vector<std::string> scatter_options{CALC_SAMPLE, CALC_CONTAINER, CALC_ENVIRONMENT};
82 declareProperty("ScatterFrom", CALC_SAMPLE, std::make_shared<StringListValidator>(std::move(scatter_options)),
83 "The component to calculate the absorption for (default: Sample)");
84
85 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
86 mustBePositive->setLower(0.0);
87 declareProperty("AttenuationXSection", EMPTY_DBL(), mustBePositive,
88 "The ABSORPTION cross-section, at 1.8 Angstroms, for the "
89 "sample material in barns. Column 8 of a table generated "
90 "from http://www.ncnr.nist.gov/resources/n-lengths/.");
91 declareProperty("ScatteringXSection", EMPTY_DBL(), mustBePositive,
92 "The (coherent + incoherent) scattering cross-section for "
93 "the sample material in barns. Column 7 of a table generated "
94 "from http://www.ncnr.nist.gov/resources/n-lengths/.");
95 declareProperty("SampleNumberDensity", EMPTY_DBL(), mustBePositive,
96 "The number density of the sample in number of atoms per "
97 "cubic angstrom if not set with SetSampleMaterial");
98
99 auto positiveInt = std::make_shared<BoundedValidator<int64_t>>();
100 positiveInt->setLower(1);
101 declareProperty("NumberOfWavelengthPoints", static_cast<int64_t>(EMPTY_INT()), positiveInt,
102 "The number of wavelength points for which the numerical integral is\n"
103 "calculated (default: all points)");
104
105 std::vector<std::string> exp_options{"Normal", "FastApprox"};
106 declareProperty("ExpMethod", "Normal", std::make_shared<StringListValidator>(exp_options),
107 "Select the method to use to calculate exponentials, normal or a\n"
108 "fast approximation (default: Normal)");
109
110 std::vector<std::string> propOptions{"Elastic", "Direct", "Indirect"};
111 declareProperty("EMode", "Elastic", std::make_shared<StringListValidator>(propOptions),
112 "The energy mode (default: elastic)");
113 declareProperty("EFixed", 0.0, mustBePositive,
114 "The value of the initial or final energy, as appropriate, in meV.\n"
115 "Will be taken from the instrument definition file, if available.");
116
117 // Call the virtual method for concrete algorithm to define any other
118 // properties
120}
121
122std::map<std::string, std::string> AbsorptionCorrection::validateInputs() {
123 std::map<std::string, std::string> result;
124
125 // verify that the container/environment information is there if requested
126 const std::string scatterFrom = getProperty("ScatterFrom");
127 if (scatterFrom != CALC_SAMPLE) {
128 API::MatrixWorkspace_const_sptr wksp = getProperty("InputWorkspace");
129 const auto &sample = wksp->sample();
130 if (sample.hasEnvironment()) {
131 const auto numComponents = sample.getEnvironment().nelements();
132 // first element is assumed to be the container
133 if (scatterFrom == CALC_CONTAINER && numComponents == 0) {
134 result["ScatterFrom"] = "Sample does not have a container defined";
135 } else if (scatterFrom == CALC_ENVIRONMENT) {
136 if (numComponents < 2) {
137 result["ScatterFrom"] = "Sample does not have an environment defined";
138 } else if (numComponents > 2) {
139 std::stringstream msg;
140 msg << "Do not know how to calculate absorption from multiple "
141 "component sample environment. Encountered "
142 << numComponents << " components";
143 result["ScatterFrom"] = msg.str();
144 }
145 }
146 } else { // customize error message based on selection
147 if (scatterFrom == CALC_CONTAINER)
148 result["ScatterFrom"] = "Sample does not have a container defined";
149 else if (scatterFrom == CALC_ENVIRONMENT)
150 result["ScatterFrom"] = "Sample does not have an environment defined";
151 }
152 }
153
154 return result;
155}
156
158 // Retrieve the input workspace
159 m_inputWS = getProperty("InputWorkspace");
160 // Cache the beam direction
161 m_beamDirection = m_inputWS->getInstrument()->getBeamDirection();
162 // Get a reference to the parameter map (used for indirect instruments)
163 const auto &componentInfo = m_inputWS->componentInfo();
164
165 // Get the input parameters
167
168 // Create the output workspace
169 MatrixWorkspace_sptr correctionFactors = create<HistoWorkspace>(*m_inputWS);
170 correctionFactors->setDistribution(true); // The output of this is a distribution
171 correctionFactors->setYUnit(""); // Need to explicitly set YUnit to nothing
172 correctionFactors->setYUnitLabel("Attenuation factor");
173
174 constructSample(correctionFactors->mutableSample());
175
176 const auto numHists = static_cast<int64_t>(m_inputWS->getNumberHistograms());
177 const auto specSize = static_cast<int64_t>(m_inputWS->blocksize());
178
179 // If the number of wavelength points has not been given, use them all
181 m_num_lambda = specSize;
182 m_xStep = specSize / m_num_lambda; // Bin step between points to calculate
183
184 if (m_xStep == 0) // Number of wavelength points >number of histogram points
185 m_xStep = 1;
186
187 std::ostringstream message;
188 message << "Numerical integration performed every " << m_xStep << " wavelength points";
189 g_log.information(message.str());
190 message.str("");
191
192 // Calculate the cached values of L1, element volumes, and geometry size
194 if (m_L1s.empty()) {
195 throw std::runtime_error("Failed to define any initial scattering gauge volume for geometry");
196 }
197
198 const auto &spectrumInfo = m_inputWS->spectrumInfo();
199 Progress prog(this, 0.0, 1.0, numHists);
200 // Loop over the spectra
201 PARALLEL_FOR_IF(Kernel::threadSafe(*m_inputWS, *correctionFactors))
202 for (int64_t i = 0; i < int64_t(numHists); ++i) {
204 // Copy over bins
205 correctionFactors->setSharedX(i, m_inputWS->sharedX(i));
206
207 if (!spectrumInfo.hasDetectors(i)) {
208 g_log.information() << "Spectrum " << i << " does not have a detector defined for it\n";
209 continue;
210 }
211 if (spectrumInfo.isMasked(i)) {
212 continue;
213 }
214 std::vector<double> L2s(m_numVolumeElements);
215 calculateDistances(spectrumInfo, i, L2s);
216
217 // If an indirect instrument, see if there's an efixed in the parameter map
218 double lambdaFixed = m_lambdaFixed;
220 // A spectrum of several detectors has no parameters of its own, so uses the single provided value
221 if (spectrumInfo.hasUniqueDetector(i)) {
222 try {
223 const auto eFixed = componentInfo.getNumberParameter(spectrumInfo.firstDetectorIndex(i), "Efixed", false);
224 if (!eFixed.empty()) {
225 lambdaFixed = energyToWavelength(eFixed.front());
226 }
227 } catch (std::runtime_error &) { /* Not a number, use single provided value */
228 }
229 }
230 }
231
232 // calculate the absorption coefficient for fixed wavelength
233 const double linearCoefAbsFixed = -m_material.linearAbsorpCoef(lambdaFixed);
234 const auto wavelengths = m_inputWS->points(i);
235 // these need to have the minus sign applied still
236 const auto linearCoefAbs = m_material.linearAbsorpCoef(wavelengths.cbegin(), wavelengths.cend());
237
238 // Get a reference to the Y's in the output WS for storing the factors
239 auto &Y = correctionFactors->mutableY(i);
240
241 // Loop through the bins in the current spectrum every m_xStep
242 for (int64_t j = 0; j < specSize; j = j + m_xStep) {
244 Y[j] = this->doIntegration(-linearCoefAbs[j], L2s, 0, L2s.size());
245 } else if (m_emode == DeltaEMode::Direct) {
246 Y[j] = this->doIntegration(linearCoefAbsFixed, -linearCoefAbs[j], L2s, 0, L2s.size());
247 } else if (m_emode == DeltaEMode::Indirect) {
248 Y[j] = this->doIntegration(-linearCoefAbs[j], linearCoefAbsFixed, L2s, 0, L2s.size());
249 } else { // should never happen
250 throw std::runtime_error("AbsorptionCorrection doesn't have a known DeltaEMode defined");
251 }
252 Y[j] /= m_sampleVolume; // Divide by total volume of the shape
253
254 // Make certain that last point is calculated
255 if (m_xStep > 1 && j + m_xStep >= specSize && j + 1 != specSize) {
256 j = specSize - m_xStep - 1;
257 }
258 }
259
260 // Interpolate linearly between points separated by m_xStep,
261 // last point required
262 if (m_xStep > 1) {
263 auto histnew = correctionFactors->histogram(i);
264 interpolateLinearInplace(histnew, m_xStep);
265 correctionFactors->setHistogram(i, histnew);
266 }
267
268 prog.report();
269
271 }
273
274 g_log.information() << "Total number of elements in the integration was " << m_L1s.size() << '\n';
275 setProperty("OutputWorkspace", correctionFactors);
276
277 // Now do some cleaning-up since destructor may not be called immediately
278 m_L1s.clear();
279 m_elementVolumes.clear();
280 m_elementPositions.clear();
281}
282
285 double sigma_atten = getProperty("AttenuationXSection"); // in barns
286 double sigma_s = getProperty("ScatteringXSection"); // in barns
287 double rho = getProperty("SampleNumberDensity"); // in Angstroms-3
288 const std::string scatterFrom = getProperty("ScatterFrom");
289
290 bool createMaterial = !(isEmpty(rho) && isEmpty(sigma_s) && isEmpty(sigma_atten));
291 // get the material from the correct component
292 const auto &sampleObj = m_inputWS->sample();
293 if (scatterFrom == CALC_SAMPLE) {
294 m_material = sampleObj.getShape().material();
295 } else if (scatterFrom == CALC_CONTAINER) {
296 m_material = sampleObj.getEnvironment().getContainer().material();
297 } else if (scatterFrom == CALC_ENVIRONMENT) {
298 m_material = sampleObj.getEnvironment().getComponent(1).material();
299 }
300
301 if (createMaterial) {
302 // get values from the existing material
303 if (isEmpty(rho))
305 if (isEmpty(sigma_s))
307 if (isEmpty(sigma_atten))
309
310 // create the new material
311 NeutronAtom neutron(0, 0, 0.0, 0.0, sigma_s, 0.0, sigma_s, sigma_atten);
312
313 // Save input in Sample with wrong atomic number and name
314 auto shape = std::shared_ptr<IObject>(
315 m_inputWS->sample().getShape().cloneWithMaterial(Material("SetInAbsorptionCorrection", neutron, rho)));
316 m_inputWS->mutableSample().setShape(shape);
317
318 // get the material back
319 m_material = m_inputWS->sample().getShape().material();
320 }
321
322 // NOTE: the angstrom^-2 to barns and the angstrom^-1 to cm^-1
323 // will cancel for mu to give units: cm^-1
325
326 m_num_lambda = getProperty("NumberOfWavelengthPoints");
327
328 std::string exp_string = getProperty("ExpMethod");
329 if (exp_string == "Normal") // Use the system exp function
330 EXPONENTIAL = exp;
331 else if (exp_string == "FastApprox") // Use the compact approximation
333
334 // Get the energy mode
335 const std::string emodeStr = getProperty("EMode");
336 // Convert back to an integer representation
337 if (emodeStr == "Direct")
339 else if (emodeStr == "Indirect")
341 else if (emodeStr == "Elastic")
343 else {
344 std::stringstream msg;
345 msg << "Unknown EMode \"" << emodeStr << "\"";
346 throw std::runtime_error(msg.str());
347 }
348
349 // If inelastic, get the fixed energy and convert it to a wavelength
351 const double efixed = getProperty("Efixed");
352 m_lambdaFixed = energyToWavelength(efixed);
353 }
354
355 // Call the virtual function for any further properties
357}
358
361 const std::string xmlstring = sampleXML();
362 const std::string scatterFrom = getProperty("ScatterFrom");
363 if (xmlstring.empty()) {
364 // Get the shape from the proper object
365 if (scatterFrom == CALC_SAMPLE)
366 m_sampleObject = &sample.getShape();
367 else if (scatterFrom == CALC_CONTAINER)
369 else if (scatterFrom == CALC_ENVIRONMENT)
371 else
372 throw std::runtime_error("Somebody forgot to fill in an if/else tree");
373
374 // Check there is one, and fail if not
376 const std::string mess("No shape has been defined for the sample in the input workspace");
377 g_log.error(mess);
378 throw std::invalid_argument(mess);
379 }
380 } else if (scatterFrom != CALC_SAMPLE) { // should never be in this case
381 std::stringstream msg;
382 msg << "Cannot use geometry xml for ScatterFrom=" << scatterFrom;
383 throw std::runtime_error(msg.str());
384 } else { // create a geometry from the sample object
385 std::shared_ptr<IObject> shape = ShapeFactory().createShape(xmlstring);
386 sample.setShape(shape);
387 m_sampleObject = &sample.getShape();
388
389 g_log.information("Successfully constructed the sample object");
390 }
391}
392
399 std::vector<double> &L2s) const {
400 V3D detectorPos(spectrumInfo.position(index));
401 if (spectrumInfo.spectrumDefinition(index).size() > 1) {
402 // We need to make sure this is right for grouped detectors - should use
403 // average theta & phi
404 detectorPos.spherical(detectorPos.norm(), spectrumInfo.twoTheta(index, V3D(), V3D(0, 0, 1)) * 180.0 / M_PI,
405 spectrumInfo.phi(index) * 180.0 / M_PI);
406 }
407
408 for (size_t i = 0; i < m_numVolumeElements; ++i) {
409 // Create track for distance in cylinder between scattering point and
410 // detector
411 const V3D direction = normalize(detectorPos - m_elementPositions[i]);
412 Track outgoing(m_elementPositions[i], direction);
414 L2s[i] = outgoing.totalDistInsideObject();
415 }
416}
417
418// the integrations are done using pairwise summation to reduce
419// issues from adding lots of little numbers together
420// https://en.wikipedia.org/wiki/Pairwise_summation
421
424double AbsorptionCorrection::doIntegration(const double linearCoefAbs, const std::vector<double> &L2s,
425 const size_t startIndex, const size_t endIndex) const {
426 // Seems cppcheck is using the same temporary size_t to evaluate endIndex-startIndex in static analysis,
427 // so it thinks the result of the comparison is always 0<1000. Hence the suppresion.
428 // cppcheck-suppress knownConditionTrueFalse
429 if (endIndex - startIndex > MAX_INTEGRATION_LENGTH) {
430 size_t middle = findMiddle(startIndex, endIndex);
431
432 return doIntegration(linearCoefAbs, L2s, startIndex, middle) + doIntegration(linearCoefAbs, L2s, middle, endIndex);
433 } else {
434 double integral = 0.0;
435
436 // Iterate over all the elements, summing up the integral
437 for (size_t i = startIndex; i < endIndex; ++i) {
438 const double exponent = (linearCoefAbs + m_linearCoefTotScatt) * (m_L1s[i] + L2s[i]);
439 integral += (EXPONENTIAL(exponent) * (m_elementVolumes[i]));
440 }
441
442 return integral;
443 }
444}
445
448double AbsorptionCorrection::doIntegration(const double linearCoefAbsL1, const double linearCoefAbsL2,
449 const std::vector<double> &L2s, const size_t startIndex,
450 const size_t endIndex) const {
451
452 // L2s is initiliazed by m_numVolumeElements which is set to 0 in this class but it is overriden in subclasses
453 // like FlatAbsorptionCorrection
454 // Seems cppcheck is using the same temporary size_t to evaluate endIndex-startIndex in static analysis,
455 // so it thinks the result of the comparison is always 0<1000. Hence the suppresion.
456 // cppcheck-suppress knownConditionTrueFalse
457 if (endIndex - startIndex > MAX_INTEGRATION_LENGTH) {
458 size_t middle = findMiddle(startIndex, endIndex);
459
460 return doIntegration(linearCoefAbsL1, linearCoefAbsL2, L2s, startIndex, middle) +
461 doIntegration(linearCoefAbsL1, linearCoefAbsL2, L2s, middle, endIndex);
462 } else {
463 double integral = 0.0;
464
465 // Iterate over all the elements, summing up the integral
466 for (size_t i = startIndex; i < endIndex; ++i) {
467 double exponent = (linearCoefAbsL1 + m_linearCoefTotScatt) * m_L1s[i];
468 exponent += (linearCoefAbsL2 + m_linearCoefTotScatt) * L2s[i];
469 integral += (EXPONENTIAL(exponent) * (m_elementVolumes[i]));
470 }
471
472 return integral;
473 }
474}
475
476} // namespace Mantid::Algorithms
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
Base class from which all concrete algorithm classes should be derived.
Definition Algorithm.h:76
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:426
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
A validator which checks that a workspace has a valid instrument.
Helper class for reporting progress from algorithms.
Definition Progress.h:25
This class stores information about the sample used in particular run.
Definition Sample.h:35
void setShape(const Geometry::IObject_sptr &shape)
Update the shape of the object.
Definition Sample.cpp:160
const Geometry::IObject & getShape() const
Return the sample shape.
Definition Sample.cpp:146
const Geometry::SampleEnvironment & getEnvironment() const
Get a reference to the sample's environment.
Definition Sample.cpp:180
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
double twoTheta(const size_t index) const
Returns the scattering angle 2 theta in radians (angle w.r.t.
Kernel::V3D position(const size_t index) const
Returns the position of the spectrum with given index.
const SpectrumDefinition & spectrumDefinition(const size_t index) const
Returns a const reference to the SpectrumDefinition of the spectrum.
double phi(const size_t index) const
Returns the angle of the spectrum position about the lab-frame z axis, atan2(y, x),...
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
void calculateDistances(const API::SpectrumInfo &spectrumInfo, const size_t index, std::vector< double > &L2s) const
Calculate the distances traversed by the neutrons within the sample.
std::vector< double > m_elementVolumes
Cached element volumes.
std::map< std::string, std::string > validateInputs() override
Method checking errors on ALL the inputs, before execution.
void retrieveBaseProperties()
Fetch the properties and set the appropriate member variables.
virtual void retrieveProperties()
A virtual function in which additional properties should be retrieved into member variables.
virtual void defineProperties()
A virtual function in which additional properties of an algorithm should be declared.
double m_linearCoefTotScatt
The total scattering cross-section in 1/m.
double m_lambdaFixed
The wavelength corresponding to the fixed energy,.
Kernel::V3D m_beamDirection
The direction of the beam.
expfunction EXPONENTIAL
Pointer to exponential function.
double m_sampleVolume
The total volume of the sample.
double doIntegration(const double linearCoefAbs, const std::vector< double > &L2s, const size_t startIndex, const size_t endIndex) const
Carries out the numerical integration over the sample for elastic instruments.
API::MatrixWorkspace_sptr m_inputWS
A pointer to the input workspace.
const Geometry::IObject * m_sampleObject
Local cache of sample object.
size_t m_numVolumeElements
The number of volume elements.
std::vector< Kernel::V3D > m_elementPositions
Cached element positions.
std::vector< double > m_L1s
Cached L1 distances.
void constructSample(API::Sample &sample)
Create the sample object using the Geometry classes, or use the existing one.
void init() override
Initialisation code.
virtual std::string sampleXML()=0
Returns the XML string describing the sample, which can be used by the ShapeFactory.
int64_t m_num_lambda
The number of points in wavelength, the rest is.
virtual void initialiseCachedDistances()=0
Calculate the distances for L1 and element size for each element in the sample.
virtual int interceptSurface(Geometry::Track &) const =0
virtual bool hasValidShape() const =0
const Container & getContainer() const
const IObject & getComponent(const size_t index) const
Returns the requested IObject.
Class originally intended to be used with the DataHandling 'LoadInstrument' algorithm.
std::shared_ptr< CSGObject > createShape(Poco::XML::Element *pElem)
Creates a geometric object from a DOM-element-node pointing to an element whose child nodes contain t...
Defines a track as a start point and a direction.
Definition Track.h:165
double totalDistInsideObject() const
Returns the sum of all the links distInsideObject in the track.
Definition Track.cpp:254
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
Definition Material.h:50
double absorbXSection(const double lambda=PhysicalConstants::NeutronAtom::ReferenceLambda) const
Get the absorption cross section at a given wavelength in barns.
Definition Material.cpp:261
double numberDensityEffective() const
Get the effective number density.
Definition Material.cpp:196
double linearAbsorpCoef(const double lambda=PhysicalConstants::NeutronAtom::ReferenceLambda) const
Returns the linear coefficient of absorption for the material in units of cm^-1 this should match the...
Definition Material.cpp:310
double totalScatterXSection() const
Return the total scattering cross section for a given wavelength in barns.
Definition Material.cpp:253
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Class for 3D vectors.
Definition V3D.h:35
void spherical(const double R, const double theta, const double phi) noexcept
Sets the vector position based on spherical coordinates.
Definition V3D.cpp:56
double norm() const noexcept
Definition V3D.h:270
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
double fast_exp(double y)
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
Definition V3D.h:353
A namespace containing physical constants that are required by algorithms and unit routines.
Definition Atom.h:14
static constexpr double E_mev_toNeutronWavenumberSq
Transformation coefficient to transform neutron energy into neutron wavevector: K-neutron[m^-10] = sq...
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition EmptyValues.h:24
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
Defines the possible energy transfer modes:
Definition DeltaEMode.h:23
@ Input
An input workspace.
Definition Property.h:54
@ Output
An output workspace.
Definition Property.h:55
Structure to store neutronic scattering information for the various elements.
Definition NeutronAtom.h:22
static const double ReferenceLambda
The reference wavelength value for absorption cross sections.
Definition NeutronAtom.h:25