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"
19#include "MantidHistogramData/Interpolate.h"
28#include "MantidKernel/Unit.h"
30
31namespace Mantid::Algorithms {
32
33using namespace API;
34using namespace Geometry;
35using HistogramData::interpolateLinearInplace;
36using namespace Kernel;
37using Kernel::DeltaEMode;
38using namespace Mantid::PhysicalConstants;
39using namespace Mantid::DataObjects;
41
42namespace {
43// the maximum number of elements to combine at once in the pairwise summation
44constexpr size_t MAX_INTEGRATION_LENGTH{1000};
45
46const std::string CALC_SAMPLE = "Sample";
47const std::string CALC_CONTAINER = "Container";
48const std::string CALC_ENVIRONMENT = "Environment";
49
50inline size_t findMiddle(const size_t start, const size_t stop) {
51 auto half = static_cast<size_t>(floor(.5 * (static_cast<double>(stop - start))));
52 return start + half;
53}
54
55// wavelength = 2 pi / k
56double energyToWavelength(const double energyFixed) {
57 return 2. * M_PI * std::sqrt(E_mev_toNeutronWavenumberSq / energyFixed);
58}
59
60} // namespace
61
63 : API::Algorithm(), m_inputWS(), m_sampleObject(nullptr), m_L1s(), m_elementVolumes(), m_elementPositions(),
64 m_numVolumeElements(0), m_sampleVolume(0.0), m_linearCoefTotScatt(0), m_num_lambda(0), m_xStep(0),
65 m_emode(Kernel::DeltaEMode::Undefined), m_lambdaFixed(0.), EXPONENTIAL() {}
66
68
69 // The input workspace must have an instrument and units of wavelength
70 auto wsValidator = std::make_shared<CompositeValidator>();
71 wsValidator->add<WorkspaceUnitValidator>("Wavelength");
72 wsValidator->add<InstrumentValidator>();
73
74 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input, wsValidator),
75 "The X values for the input workspace must be in units of wavelength");
76 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
77 "Output workspace name");
78
79 // AbsorbedBy
80 std::vector<std::string> scatter_options{CALC_SAMPLE, CALC_CONTAINER, CALC_ENVIRONMENT};
81 declareProperty("ScatterFrom", CALC_SAMPLE, std::make_shared<StringListValidator>(std::move(scatter_options)),
82 "The component to calculate the absorption for (default: Sample)");
83
84 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
85 mustBePositive->setLower(0.0);
86 declareProperty("AttenuationXSection", EMPTY_DBL(), mustBePositive,
87 "The ABSORPTION cross-section, at 1.8 Angstroms, for the "
88 "sample material in barns. Column 8 of a table generated "
89 "from http://www.ncnr.nist.gov/resources/n-lengths/.");
90 declareProperty("ScatteringXSection", EMPTY_DBL(), mustBePositive,
91 "The (coherent + incoherent) scattering cross-section for "
92 "the sample material in barns. Column 7 of a table generated "
93 "from http://www.ncnr.nist.gov/resources/n-lengths/.");
94 declareProperty("SampleNumberDensity", EMPTY_DBL(), mustBePositive,
95 "The number density of the sample in number of atoms per "
96 "cubic angstrom if not set with SetSampleMaterial");
97
98 auto positiveInt = std::make_shared<BoundedValidator<int64_t>>();
99 positiveInt->setLower(1);
100 declareProperty("NumberOfWavelengthPoints", static_cast<int64_t>(EMPTY_INT()), positiveInt,
101 "The number of wavelength points for which the numerical integral is\n"
102 "calculated (default: all points)");
103
104 std::vector<std::string> exp_options{"Normal", "FastApprox"};
105 declareProperty("ExpMethod", "Normal", std::make_shared<StringListValidator>(exp_options),
106 "Select the method to use to calculate exponentials, normal or a\n"
107 "fast approximation (default: Normal)");
108
109 std::vector<std::string> propOptions{"Elastic", "Direct", "Indirect"};
110 declareProperty("EMode", "Elastic", std::make_shared<StringListValidator>(propOptions),
111 "The energy mode (default: elastic)");
112 declareProperty("EFixed", 0.0, mustBePositive,
113 "The value of the initial or final energy, as appropriate, in meV.\n"
114 "Will be taken from the instrument definition file, if available.");
115
116 // Call the virtual method for concrete algorithm to define any other
117 // properties
119}
120
121std::map<std::string, std::string> AbsorptionCorrection::validateInputs() {
122 std::map<std::string, std::string> result;
123
124 // verify that the container/environment information is there if requested
125 const std::string scatterFrom = getProperty("ScatterFrom");
126 if (scatterFrom != CALC_SAMPLE) {
127 API::MatrixWorkspace_const_sptr wksp = getProperty("InputWorkspace");
128 const auto &sample = wksp->sample();
129 if (sample.hasEnvironment()) {
130 const auto numComponents = sample.getEnvironment().nelements();
131 // first element is assumed to be the container
132 if (scatterFrom == CALC_CONTAINER && numComponents == 0) {
133 result["ScatterFrom"] = "Sample does not have a container defined";
134 } else if (scatterFrom == CALC_ENVIRONMENT) {
135 if (numComponents < 2) {
136 result["ScatterFrom"] = "Sample does not have an environment defined";
137 } else if (numComponents > 2) {
138 std::stringstream msg;
139 msg << "Do not know how to calculate absorption from multiple "
140 "component sample environment. Encountered "
141 << numComponents << " components";
142 result["ScatterFrom"] = msg.str();
143 }
144 }
145 } else { // customize error message based on selection
146 if (scatterFrom == CALC_CONTAINER)
147 result["ScatterFrom"] = "Sample does not have a container defined";
148 else if (scatterFrom == CALC_ENVIRONMENT)
149 result["ScatterFrom"] = "Sample does not have an environment defined";
150 }
151 }
152
153 return result;
154}
155
157 // Retrieve the input workspace
158 m_inputWS = getProperty("InputWorkspace");
159 // Cache the beam direction
160 m_beamDirection = m_inputWS->getInstrument()->getBeamDirection();
161 // Get a reference to the parameter map (used for indirect instruments)
162 const ParameterMap &pmap = m_inputWS->constInstrumentParameters();
163
164 // Get the input parameters
166
167 // Create the output workspace
168 MatrixWorkspace_sptr correctionFactors = create<HistoWorkspace>(*m_inputWS);
169 correctionFactors->setDistribution(true); // The output of this is a distribution
170 correctionFactors->setYUnit(""); // Need to explicitly set YUnit to nothing
171 correctionFactors->setYUnitLabel("Attenuation factor");
172
173 constructSample(correctionFactors->mutableSample());
174
175 const auto numHists = static_cast<int64_t>(m_inputWS->getNumberHistograms());
176 const auto specSize = static_cast<int64_t>(m_inputWS->blocksize());
177
178 // If the number of wavelength points has not been given, use them all
180 m_num_lambda = specSize;
181 m_xStep = specSize / m_num_lambda; // Bin step between points to calculate
182
183 if (m_xStep == 0) // Number of wavelength points >number of histogram points
184 m_xStep = 1;
185
186 std::ostringstream message;
187 message << "Numerical integration performed every " << m_xStep << " wavelength points";
188 g_log.information(message.str());
189 message.str("");
190
191 // Calculate the cached values of L1, element volumes, and geometry size
193 if (m_L1s.empty()) {
194 throw std::runtime_error("Failed to define any initial scattering gauge volume for geometry");
195 }
196
197 const auto &spectrumInfo = m_inputWS->spectrumInfo();
198 Progress prog(this, 0.0, 1.0, numHists);
199 // Loop over the spectra
200 PARALLEL_FOR_IF(Kernel::threadSafe(*m_inputWS, *correctionFactors))
201 for (int64_t i = 0; i < int64_t(numHists); ++i) {
203 // Copy over bins
204 correctionFactors->setSharedX(i, m_inputWS->sharedX(i));
205
206 if (!spectrumInfo.hasDetectors(i)) {
207 g_log.information() << "Spectrum " << i << " does not have a detector defined for it\n";
208 continue;
209 }
210 const auto &det = spectrumInfo.detector(i);
211
212 std::vector<double> L2s(m_numVolumeElements);
213 calculateDistances(det, L2s);
214
215 // If an indirect instrument, see if there's an efixed in the parameter map
216 double lambdaFixed = m_lambdaFixed;
218 try {
219 Parameter_sptr par = pmap.get(&det, "Efixed");
220 if (par) {
221 lambdaFixed = energyToWavelength(par->value<double>());
222 }
223 } catch (std::runtime_error &) { /* Throws if a DetectorGroup, use single
224 provided value */
225 }
226 }
227
228 // calculate the absorption coefficient for fixed wavelength
229 const double linearCoefAbsFixed = -m_material.linearAbsorpCoef(lambdaFixed);
230 const auto wavelengths = m_inputWS->points(i);
231 // these need to have the minus sign applied still
232 const auto linearCoefAbs = m_material.linearAbsorpCoef(wavelengths.cbegin(), wavelengths.cend());
233
234 // Get a reference to the Y's in the output WS for storing the factors
235 auto &Y = correctionFactors->mutableY(i);
236
237 // Loop through the bins in the current spectrum every m_xStep
238 for (int64_t j = 0; j < specSize; j = j + m_xStep) {
240 Y[j] = this->doIntegration(-linearCoefAbs[j], L2s, 0, L2s.size());
241 } else if (m_emode == DeltaEMode::Direct) {
242 Y[j] = this->doIntegration(linearCoefAbsFixed, -linearCoefAbs[j], L2s, 0, L2s.size());
243 } else if (m_emode == DeltaEMode::Indirect) {
244 Y[j] = this->doIntegration(-linearCoefAbs[j], linearCoefAbsFixed, L2s, 0, L2s.size());
245 } else { // should never happen
246 throw std::runtime_error("AbsorptionCorrection doesn't have a known DeltaEMode defined");
247 }
248 Y[j] /= m_sampleVolume; // Divide by total volume of the shape
249
250 // Make certain that last point is calculated
251 if (m_xStep > 1 && j + m_xStep >= specSize && j + 1 != specSize) {
252 j = specSize - m_xStep - 1;
253 }
254 }
255
256 // Interpolate linearly between points separated by m_xStep,
257 // last point required
258 if (m_xStep > 1) {
259 auto histnew = correctionFactors->histogram(i);
260 interpolateLinearInplace(histnew, m_xStep);
261 correctionFactors->setHistogram(i, histnew);
262 }
263
264 prog.report();
265
267 }
269
270 g_log.information() << "Total number of elements in the integration was " << m_L1s.size() << '\n';
271 setProperty("OutputWorkspace", correctionFactors);
272
273 // Now do some cleaning-up since destructor may not be called immediately
274 m_L1s.clear();
275 m_elementVolumes.clear();
276 m_elementPositions.clear();
277}
278
281 double sigma_atten = getProperty("AttenuationXSection"); // in barns
282 double sigma_s = getProperty("ScatteringXSection"); // in barns
283 double rho = getProperty("SampleNumberDensity"); // in Angstroms-3
284 const std::string scatterFrom = getProperty("ScatterFrom");
285
286 bool createMaterial = !(isEmpty(rho) && isEmpty(sigma_s) && isEmpty(sigma_atten));
287 // get the material from the correct component
288 const auto &sampleObj = m_inputWS->sample();
289 if (scatterFrom == CALC_SAMPLE) {
290 m_material = sampleObj.getShape().material();
291 } else if (scatterFrom == CALC_CONTAINER) {
292 m_material = sampleObj.getEnvironment().getContainer().material();
293 } else if (scatterFrom == CALC_ENVIRONMENT) {
294 m_material = sampleObj.getEnvironment().getComponent(1).material();
295 }
296
297 if (createMaterial) {
298 // get values from the existing material
299 if (isEmpty(rho))
301 if (isEmpty(sigma_s))
303 if (isEmpty(sigma_atten))
305
306 // create the new material
307 NeutronAtom neutron(0, 0, 0.0, 0.0, sigma_s, 0.0, sigma_s, sigma_atten);
308
309 // Save input in Sample with wrong atomic number and name
310 auto shape = std::shared_ptr<IObject>(
311 m_inputWS->sample().getShape().cloneWithMaterial(Material("SetInAbsorptionCorrection", neutron, rho)));
312 m_inputWS->mutableSample().setShape(shape);
313
314 // get the material back
315 m_material = m_inputWS->sample().getShape().material();
316 }
317
318 // NOTE: the angstrom^-2 to barns and the angstrom^-1 to cm^-1
319 // will cancel for mu to give units: cm^-1
321
322 m_num_lambda = getProperty("NumberOfWavelengthPoints");
323
324 std::string exp_string = getProperty("ExpMethod");
325 if (exp_string == "Normal") // Use the system exp function
326 EXPONENTIAL = exp;
327 else if (exp_string == "FastApprox") // Use the compact approximation
329
330 // Get the energy mode
331 const std::string emodeStr = getProperty("EMode");
332 // Convert back to an integer representation
333 if (emodeStr == "Direct")
335 else if (emodeStr == "Indirect")
337 else if (emodeStr == "Elastic")
339 else {
340 std::stringstream msg;
341 msg << "Unknown EMode \"" << emodeStr << "\"";
342 throw std::runtime_error(msg.str());
343 }
344
345 // If inelastic, get the fixed energy and convert it to a wavelength
347 const double efixed = getProperty("Efixed");
348 m_lambdaFixed = energyToWavelength(efixed);
349 }
350
351 // Call the virtual function for any further properties
353}
354
357 const std::string xmlstring = sampleXML();
358 const std::string scatterFrom = getProperty("ScatterFrom");
359 if (xmlstring.empty()) {
360 // Get the shape from the proper object
361 if (scatterFrom == CALC_SAMPLE)
362 m_sampleObject = &sample.getShape();
363 else if (scatterFrom == CALC_CONTAINER)
365 else if (scatterFrom == CALC_ENVIRONMENT)
367 else
368 throw std::runtime_error("Somebody forgot to fill in an if/else tree");
369
370 // Check there is one, and fail if not
372 const std::string mess("No shape has been defined for the sample in the input workspace");
373 g_log.error(mess);
374 throw std::invalid_argument(mess);
375 }
376 } else if (scatterFrom != CALC_SAMPLE) { // should never be in this case
377 std::stringstream msg;
378 msg << "Cannot use geometry xml for ScatterFrom=" << scatterFrom;
379 throw std::runtime_error(msg.str());
380 } else { // create a geometry from the sample object
381 std::shared_ptr<IObject> shape = ShapeFactory().createShape(xmlstring);
382 sample.setShape(shape);
383 m_sampleObject = &sample.getShape();
384
385 g_log.information("Successfully constructed the sample object");
386 }
387}
388
393void AbsorptionCorrection::calculateDistances(const IDetector &detector, std::vector<double> &L2s) const {
394 V3D detectorPos(detector.getPos());
395 if (detector.nDets() > 1) {
396 // We need to make sure this is right for grouped detectors - should use
397 // average theta & phi
398 detectorPos.spherical(detectorPos.norm(), detector.getTwoTheta(V3D(), V3D(0, 0, 1)) * 180.0 / M_PI,
399 detector.getPhi() * 180.0 / M_PI);
400 }
401
402 for (size_t i = 0; i < m_numVolumeElements; ++i) {
403 // Create track for distance in cylinder between scattering point and
404 // detector
405 const V3D direction = normalize(detectorPos - m_elementPositions[i]);
406 Track outgoing(m_elementPositions[i], direction);
408 L2s[i] = outgoing.totalDistInsideObject();
409 }
410}
411
412// the integrations are done using pairwise summation to reduce
413// issues from adding lots of little numbers together
414// https://en.wikipedia.org/wiki/Pairwise_summation
415
418double AbsorptionCorrection::doIntegration(const double linearCoefAbs, const std::vector<double> &L2s,
419 const size_t startIndex, const size_t endIndex) const {
420 if (endIndex - startIndex > MAX_INTEGRATION_LENGTH) {
421 size_t middle = findMiddle(startIndex, endIndex);
422
423 return doIntegration(linearCoefAbs, L2s, startIndex, middle) + doIntegration(linearCoefAbs, L2s, middle, endIndex);
424 } else {
425 double integral = 0.0;
426
427 // Iterate over all the elements, summing up the integral
428 for (size_t i = startIndex; i < endIndex; ++i) {
429 const double exponent = (linearCoefAbs + m_linearCoefTotScatt) * (m_L1s[i] + L2s[i]);
430 integral += (EXPONENTIAL(exponent) * (m_elementVolumes[i]));
431 }
432
433 return integral;
434 }
435}
436
439double AbsorptionCorrection::doIntegration(const double linearCoefAbsL1, const double linearCoefAbsL2,
440 const std::vector<double> &L2s, const size_t startIndex,
441 const size_t endIndex) const {
442 if (endIndex - startIndex > MAX_INTEGRATION_LENGTH) {
443 size_t middle = findMiddle(startIndex, endIndex);
444
445 return doIntegration(linearCoefAbsL1, linearCoefAbsL2, L2s, startIndex, middle) +
446 doIntegration(linearCoefAbsL1, linearCoefAbsL2, L2s, middle, endIndex);
447 } else {
448 double integral = 0.0;
449
450 // Iterate over all the elements, summing up the integral
451 for (size_t i = startIndex; i < endIndex; ++i) {
452 double exponent = (linearCoefAbsL1 + m_linearCoefTotScatt) * m_L1s[i];
453 exponent += (linearCoefAbsL2 + m_linearCoefTotScatt) * L2s[i];
454 integral += (EXPONENTIAL(exponent) * (m_elementVolumes[i]));
455 }
456
457 return integral;
458 }
459}
460
461} // namespace Mantid::Algorithms
#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...
Definition: MultiThreaded.h:94
#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:85
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
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:33
void setShape(const Geometry::IObject_sptr &shape)
Update the shape of the object.
Definition: Sample.cpp:116
const Geometry::IObject & getShape() const
Return the sample shape.
Definition: Sample.cpp:102
const Geometry::SampleEnvironment & getEnvironment() const
Get a reference to the sample's environment.
Definition: Sample.cpp:136
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
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 calculateDistances(const Geometry::IDetector &detector, std::vector< double > &L2s) const
Calculate the distances traversed by the neutrons within the sample.
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 Kernel::V3D getPos() const =0
Get the position of the IComponent. Tree structure is traverse through the.
Interface class for detector objects.
Definition: IDetector.h:43
virtual double getPhi() const =0
Gives the phi of this detector object in radians.
virtual std::size_t nDets() const =0
Get the number of physical detectors this object represents.
virtual double getTwoTheta(const Kernel::V3D &observer, const Kernel::V3D &axis) const =0
Gives the angle of this detector object with respect to an axis.
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.
Definition: ShapeFactory.h:89
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:77
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
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:260
double numberDensityEffective() const
Get the effective number density.
Definition: Material.cpp:195
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:309
double totalScatterXSection() const
Return the total scattering cross section for a given wavelength in barns.
Definition: Material.cpp:252
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Definition: ProgressBase.h:51
Class for 3D vectors.
Definition: V3D.h:34
void spherical(const double R, const double theta, const double phi) noexcept
Sets the vector position based on spherical coordinates.
Definition: V3D.cpp:57
double norm() const noexcept
Definition: V3D.h:263
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
std::shared_ptr< Parameter > Parameter_sptr
Typedef for the shared pointer.
Definition: Parameter.h:195
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.
Definition: MultiThreaded.h:22
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
Definition: V3D.h:341
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:25
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition: EmptyValues.h:43
Generate a tableworkspace to store the calibration results.
Defines the possible energy transfer modes:
Definition: DeltaEMode.h:23
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54
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