Mantid
Loading...
Searching...
No Matches
AddAbsorptionWeightedPathLengths.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2020 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 +
9#include "MantidAPI/Sample.h"
23
24using namespace Mantid::API;
25using namespace Mantid::DataObjects;
26using namespace Mantid::Geometry;
27using namespace Mantid::Kernel;
28
29namespace Mantid::Algorithms {
30
31// Register the algorithm into the AlgorithmFactory
32DECLARE_ALGORITHM(AddAbsorptionWeightedPathLengths)
33
34//----------------------------------------------------------------------------------------------
35
36namespace {
37
38constexpr int DEFAULT_NEVENTS = 1000;
39constexpr int DEFAULT_SEED = 123456789;
40constexpr int NLAMBDA = 1;
41
42} // namespace
43
44//----------------------------------------------------------------------------------------------
49 std::make_unique<WorkspaceProperty<PeaksWorkspace_sptr::element_type>>("InputWorkspace", "", Direction::InOut),
50 "An input/output peaks workspace that the path distances will be added "
51 "to.");
52 declareProperty("UseSinglePath", false, "Use a single path with a scatter point at the sample position");
53 auto positiveInt = std::make_shared<Kernel::BoundedValidator<int>>();
54 positiveInt->setLower(1);
55 declareProperty("EventsPerPoint", DEFAULT_NEVENTS, positiveInt,
56 "The number of \"neutron\" events to generate per peak");
57 declareProperty("SeedValue", DEFAULT_SEED, positiveInt, "Seed the random number generator with this value");
58 declareProperty("MaxScatterPtAttempts", 5000, positiveInt,
59 "Maximum number of tries made to generate a scattering point "
60 "within the sample. Objects with "
61 "holes in them, e.g. a thin annulus can cause problems "
62 "if this number is too low.\n"
63 "If a scattering point cannot be generated by increasing "
64 "this value then there is most likely a problem with "
65 "the sample geometry.");
66 setPropertySettings("SeedValue",
67 std::make_unique<EnabledWhenProperty>("UseSinglePath", ePropertyCriterion::IS_DEFAULT));
68 setPropertySettings("EventsPerPoint",
69 std::make_unique<EnabledWhenProperty>("UseSinglePath", ePropertyCriterion::IS_DEFAULT));
70 setPropertySettings("MaxScatterPtAttempts",
71 std::make_unique<EnabledWhenProperty>("UseSinglePath", ePropertyCriterion::IS_DEFAULT));
72}
73
74std::map<std::string, std::string> AddAbsorptionWeightedPathLengths::validateInputs() {
75 PeaksWorkspace_sptr inputWS = getProperty("InputWorkspace");
76 std::map<std::string, std::string> issues;
77 Geometry::IComponent_const_sptr sample = inputWS->getInstrument()->getSample();
78 if (!sample) {
79 issues["InputWorkspace"] = "Input workspace does not have a Sample";
80 } else {
81 if (inputWS->sample().hasEnvironment()) {
82 issues["InputWorkspace"] = "Sample must not have a sample environment";
83 }
84
85 if (inputWS->sample().getMaterial().numberDensity() == 0) {
86 issues["InputWorkspace"] = "Sample must have a material set up with a non-zero number density";
87 }
88 }
89 return issues;
90}
91
92//----------------------------------------------------------------------------------------------
96
97 const PeaksWorkspace_sptr inputWS = getProperty("InputWorkspace");
98 const int nevents = getProperty("EventsPerPoint");
99 const int maxScatterPtAttempts = getProperty("MaxScatterPtAttempts");
100
101 auto instrument = inputWS->getInstrument();
102 auto beamProfile = BeamProfileFactory::createBeamProfile(*instrument, inputWS->sample());
103
104 const auto npeaks = inputWS->getNumberPeaks();
105
106 // Configure progress
107 Progress prog(this, 0.0, 1.0, npeaks);
108 prog.setNotifyStep(0.01);
109 const std::string reportMsg = "Computing path lengths";
110
111 // Configure strategy
112 MCInteractionVolume interactionVol(inputWS->sample(), maxScatterPtAttempts);
113 MCAbsorptionStrategy strategy(interactionVol, *beamProfile, DeltaEMode::Elastic, nevents, maxScatterPtAttempts, true);
114
115 const int seed = getProperty("SeedValue");
116
118 for (int i = 0; i < npeaks; ++i) {
120 Peak &peak = inputWS->getPeak(i);
121 auto peakWavelength = peak.getWavelength();
122
123 std::vector<double> lambdas{peakWavelength}, absFactors(NLAMBDA), absFactorErrors(NLAMBDA);
124
125 bool useSinglePath = getProperty("UseSinglePath");
126 if (useSinglePath) {
127 auto inst = inputWS->getInstrument();
128 const auto sourcePos = inst->getSource()->getPos();
129 const auto samplePos = inst->getSample()->getPos();
130 const auto reverseBeamDir = normalize(samplePos - sourcePos);
131
132 const IObject *sampleShape = &(inputWS->sample().getShape());
133
134 Track beforeScatter(samplePos, reverseBeamDir);
135 sampleShape->interceptSurface(beforeScatter);
136 const auto detDir = normalize(peak.getDetPos() - samplePos);
137 Track afterScatter(samplePos, detDir);
138 sampleShape->interceptSurface(afterScatter);
139
140 absFactors[0] = beforeScatter.calculateAttenuation(lambdas[0]) * afterScatter.calculateAttenuation(lambdas[0]);
141
142 } else {
143 MersenneTwister rng(seed + int(i));
144 MCInteractionStatistics detStatistics(peak.getDetectorID(), inputWS->sample());
145
146 strategy.calculate(rng, peak.getDetectorPosition(), lambdas, peakWavelength, absFactors, absFactorErrors,
147 detStatistics);
148
149 if (g_log.is(Kernel::Logger::Priority::PRIO_DEBUG)) {
150 g_log.debug(detStatistics.generateScatterPointStats());
151 }
152 }
153
154 double mu = inputWS->sample().getMaterial().attenuationCoefficient(peakWavelength); // m-1
155 double absWeightedPathLength = -log(absFactors[0]) / mu; // metres
156 peak.setAbsorptionWeightedPathLength(absWeightedPathLength * 100); // cm
157
158 prog.report(reportMsg);
160 }
162}
163
164} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
#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.
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
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
A property class for workspaces.
std::map< std::string, std::string > validateInputs() override
Method checking errors on ALL the inputs, before execution.
static std::unique_ptr< IBeamProfile > createBeamProfile(const Geometry::Instrument &instrument, const API::Sample &sample)
Implements the algorithm for calculating the correction factor for self-attenuation and single wavele...
virtual void calculate(Kernel::PseudoRandomNumberGenerator &rng, const Kernel::V3D &finalPos, const std::vector< double > &lambdas, const double lambdaFixed, std::vector< double > &attenuationFactors, std::vector< double > &attFactorErrors, MCInteractionStatistics &stats) override
Compute the correction for a final position of the neutron and wavelengths before and after scatterin...
Stores statistics relating to the tracks generated in MCInteractionVolume for a specific detector.
std::string generateScatterPointStats()
Log a debug string summarising which parts of the environment the simulated scatter points occurred i...
Defines a volume where interactions of Tracks and Objects can take place.
Structure describing a single-crystal peak.
Definition: Peak.h:34
double getWavelength() const override
Calculate the neutron wavelength (in angstroms) at the peak (Note for inelastic scattering - it is th...
Definition: Peak.cpp:364
IObject : Interface for geometry objects.
Definition: IObject.h:41
virtual int interceptSurface(Geometry::Track &) const =0
Defines a track as a start point and a direction.
Definition: Track.h:165
virtual double calculateAttenuation(double lambda) const
Calculate attenuation across all links.
Definition: Track.cpp:276
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
bool is(int level) const
Returns true if at least the given log level is set.
Definition: Logger.cpp:146
This implements the the Mersenne Twister 19937 pseudo-random number generator algorithm as a specialz...
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Definition: ProgressBase.h:51
void setNotifyStep(double notifyStepPct)
Override the frequency at which notifications are sent out.
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Definition: IComponent.h:161
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
@ InOut
Both an input & output workspace.
Definition: Property.h:55