Mantid
Loading...
Searching...
No Matches
MCAbsorptionStrategy.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 "MantidKernel/V3D.h"
11
13
14namespace Mantid {
15using Kernel::DeltaEMode;
16using Kernel::PseudoRandomNumberGenerator;
17
18namespace Algorithms {
19
32 DeltaEMode::Type EMode, const size_t nevents,
33 const size_t maxScatterPtAttempts, const bool regenerateTracksForEachLambda)
34 : m_beamProfile(beamProfile), m_scatterVol(setActiveRegion(interactionVolume, beamProfile)), m_nevents(nevents),
35 m_maxScatterAttempts(maxScatterPtAttempts), m_EMode(EMode),
36 m_regenerateTracksForEachLambda(regenerateTracksForEachLambda) {}
37
47 const IBeamProfile &beamProfile) {
48 interactionVolume.setActiveRegion(beamProfile.defineActiveRegion(interactionVolume.getFullBoundingBox()));
49 return interactionVolume;
50}
51
70 const std::vector<double> &lambdas, const double lambdaFixed,
71 std::vector<double> &attenuationFactors, std::vector<double> &attFactorErrors,
73 const auto scatterBounds = m_scatterVol.getFullBoundingBox();
74 const auto nbins = static_cast<int>(lambdas.size());
75
76 std::vector<double> wgtMean(attenuationFactors.size()), wgtM2(attenuationFactors.size());
77
78 for (size_t i = 0; i < m_nevents; ++i) {
79 std::shared_ptr<Geometry::Track> beforeScatter;
80 std::shared_ptr<Geometry::Track> afterScatter;
81 for (int j = 0; j < nbins; ++j) {
82 size_t attempts(0);
83 do {
84 bool success = false;
85 if (m_regenerateTracksForEachLambda || j == 0) {
86 const auto neutron = m_beamProfile.generatePoint(rng, scatterBounds);
87 std::tie(success, beforeScatter, afterScatter) =
88 m_scatterVol.calculateBeforeAfterTrack(rng, neutron.startPos, finalPos, stats);
89 } else {
90 success = true;
91 }
92 if (!success) {
93 ++attempts;
94 } else {
95 const double lambdaStep = lambdas[j];
96 double lambdaIn(lambdaStep), lambdaOut(lambdaStep);
98 lambdaIn = lambdaFixed;
99 } else if (m_EMode == DeltaEMode::Indirect) {
100 lambdaOut = lambdaFixed;
101 } else {
102 // elastic case already initialized
103 }
104 const double wgt =
105 beforeScatter->calculateAttenuation(lambdaIn) * afterScatter->calculateAttenuation(lambdaOut);
106 attenuationFactors[j] += wgt;
107 // increment standard deviation using Welford algorithm
108 double delta = wgt - wgtMean[j];
109 wgtMean[j] += delta / static_cast<double>(i + 1);
110 wgtM2[j] += delta * (wgt - wgtMean[j]);
111 // calculate sample SD (M2/n-1)
112 // will give NaN for m_events=1, but that's correct
113 attFactorErrors[j] = sqrt(wgtM2[j] / static_cast<double>(i));
114
115 break;
116 }
117 if (attempts == m_maxScatterAttempts) {
118 throw std::runtime_error("Unable to generate valid track through "
119 "sample interaction volume after " +
121 " attempts. Try increasing the maximum "
122 "threshold or if this does not help then "
123 "please check the defined shape.");
124 }
125 } while (true);
126 }
127 }
128
129 std::transform(attenuationFactors.begin(), attenuationFactors.end(), attenuationFactors.begin(),
130 std::bind(std::divides<double>(), std::placeholders::_1, static_cast<double>(m_nevents)));
131
132 // calculate standard deviation of mean from sample mean
133 std::transform(attFactorErrors.begin(), attFactorErrors.end(), attFactorErrors.begin(),
134 [this](double v) -> double { return v / sqrt(static_cast<double>(m_nevents)); });
135}
136
137} // namespace Algorithms
138} // namespace Mantid
Base class for all classes defining a beam profile.
Definition: IBeamProfile.h:26
virtual Ray generatePoint(Kernel::PseudoRandomNumberGenerator &rng) const =0
virtual Geometry::BoundingBox defineActiveRegion(const Geometry::BoundingBox &) const =0
Defines a base class for objects describing a volume where interactions of Tracks and Objects can tak...
virtual void setActiveRegion(const Geometry::BoundingBox &region)=0
virtual TrackPair calculateBeforeAfterTrack(Kernel::PseudoRandomNumberGenerator &rng, const Kernel::V3D &startPos, const Kernel::V3D &endPos, MCInteractionStatistics &stats) const =0
virtual const Geometry::BoundingBox getFullBoundingBox() const =0
MCAbsorptionStrategy(IMCInteractionVolume &interactionVolume, const IBeamProfile &beamProfile, Kernel::DeltaEMode::Type EMode, const size_t nevents, const size_t maxScatterPtAttempts, const bool regenerateTracksForEachLambda)
Constructor.
const IMCInteractionVolume & m_scatterVol
IMCInteractionVolume & setActiveRegion(IMCInteractionVolume &interactionVolume, const IBeamProfile &beamProfile)
Set the active region on the interaction volume as smaller of the sample bounding box and the beam cr...
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...
const Kernel::DeltaEMode::Type m_EMode
Stores statistics relating to the tracks generated in MCInteractionVolume for a specific detector.
Defines a 1D pseudo-random number generator, i.e.
Class for 3D vectors.
Definition: V3D.h:34
Helper class which provides the Collimation Length for SANS instruments.
std::string to_string(const wide_integer< Bits, Signed > &n)
Type
Define the available energy transfer modes It is important to assign enums proper numbers,...
Definition: DeltaEMode.h:29