33 const size_t nevents,
const size_t maxScatterPtAttempts,
34 const bool regenerateTracksForEachLambda)
35 : m_scatterVol(
std::move(interactionVolume)), m_beamProfile(beamProfile), m_nevents(nevents),
36 m_maxScatterAttempts(maxScatterPtAttempts), m_EMode(EMode),
37 m_regenerateTracksForEachLambda(regenerateTracksForEachLambda) {
69 const std::vector<double> &lambdas,
const double lambdaFixed,
70 std::vector<double> &attenuationFactors, std::vector<double> &attFactorErrors,
72 const auto scatterBounds =
m_scatterVol->getFullBoundingBox();
73 const auto nbins =
static_cast<int>(lambdas.size());
76 std::vector<double> wgtMean(attenuationFactors.size()), wgtM2(attenuationFactors.size());
79 std::shared_ptr<Geometry::Track> beforeScatter;
80 std::shared_ptr<Geometry::Track> afterScatter;
81 for (
int j = 0; j < nbins; ++j) {
87 std::tie(success, beforeScatter, afterScatter) =
88 m_scatterVol->calculateBeforeAfterTrack(rng, neutron.startPos, finalPos, stats);
95 const double lambdaStep = lambdas[j];
96 double lambdaIn(lambdaStep), lambdaOut(lambdaStep);
98 lambdaIn = lambdaFixed;
100 lambdaOut = lambdaFixed;
105 beforeScatter->calculateAttenuation(lambdaIn) * afterScatter->calculateAttenuation(lambdaOut);
106 attenuationFactors[j] += wgt;
108 double delta = wgt - wgtMean[j];
109 wgtMean[j] +=
delta /
static_cast<double>(i + 1);
110 wgtM2[j] +=
delta * (wgt - wgtMean[j]);
113 attFactorErrors[j] = sqrt(wgtM2[j] /
static_cast<double>(i));
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 and, "
124 "if defined, the gauge volume (both its shape "
125 "and its intersection with the defined sample shape).");
131 std::transform(attenuationFactors.begin(), attenuationFactors.end(), attenuationFactors.begin(),
132 std::bind(std::divides<double>(), std::placeholders::_1,
static_cast<double>(
m_nevents)));
135 std::transform(attFactorErrors.begin(), attFactorErrors.end(), attFactorErrors.begin(),
136 [
this](
double v) ->
double { return v / sqrt(static_cast<double>(m_nevents)); });
MCAbsorptionStrategy(std::shared_ptr< IMCInteractionVolume > interactionVolume, const IBeamProfile &beamProfile, Kernel::DeltaEMode::Type EMode, const size_t nevents, const size_t maxScatterPtAttempts, const bool regenerateTracksForEachLambda)
Constructor.
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...