Newer
Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source
// & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
#ifndef MANTID_ALGORITHMS_MCINTERACTIONVOLUMETEST_H_
#define MANTID_ALGORITHMS_MCINTERACTIONVOLUMETEST_H_
#include <cxxtest/TestSuite.h>
#include "MantidAlgorithms/SampleCorrections/MCInteractionVolume.h"
#include "MantidKernel/MersenneTwister.h"
#include <gmock/gmock.h>
using Mantid::Algorithms::MCInteractionVolume;
class MCInteractionVolumeTest : public CxxTest::TestSuite {
public:
// This pair of boilerplate methods prevent the suite being created statically
// This means the constructor isn't called when running other tests
static MCInteractionVolumeTest *createSuite() {
return new MCInteractionVolumeTest();
}
static void destroySuite(MCInteractionVolumeTest *suite) { delete suite; }
//----------------------------------------------------------------------------
// Success cases
//----------------------------------------------------------------------------
void test_Bounding_Volume_Matches_Sample() {
using namespace MonteCarloTesting;
auto sample = createTestSample(TestSampleType::SolidSphere);
const auto sampleBox = sample.getShape().getBoundingBox();
MCInteractionVolume interactor(sample, sampleBox);
const auto interactionBox = interactor.getBoundingBox();
TS_ASSERT_EQUALS(sampleBox.minPoint(), interactionBox.minPoint());
TS_ASSERT_EQUALS(sampleBox.maxPoint(), interactionBox.maxPoint());
}
void test_Absorption_In_Solid_Sample_Gives_Expected_Answer() {
using Mantid::Kernel::V3D;
using namespace ::testing;
// Testing inputs
const V3D startPos(-2.0, 0.0, 0.0), endPos(0.7, 0.7, 1.4);
const double lambdaBefore(2.5), lambdaAfter(3.5);
MockRNG rng;
EXPECT_CALL(rng, nextValue())
.Times(Exactly(3))
.WillRepeatedly(Return(0.25));
auto sample = createTestSample(TestSampleType::SolidSphere);
MCInteractionVolume interactor(sample, sample.getShape().getBoundingBox());
const double factor = interactor.calculateAbsorption(
rng, startPos, endPos, lambdaBefore, lambdaAfter);
void test_Absorption_In_Sample_With_Hole_Container_Scatter_In_All_Segments() {
using Mantid::Kernel::V3D;
using namespace ::testing;
// Testing inputs
const V3D startPos(-2.0, 0.0, 0.0), endPos(2.0, 0.0, 0.0);
const double lambdaBefore(2.5), lambdaAfter(3.5);
auto sample = createTestSample(TestSampleType::Annulus);
MockRNG rng;
// force scatter in segment 1
EXPECT_CALL(rng, nextValue())
.Times(Exactly(3))
.WillRepeatedly(Return(0.25));
MCInteractionVolume interactor(sample, sample.getShape().getBoundingBox());
const double factorSeg1 = interactor.calculateAbsorption(
rng, startPos, endPos, lambdaBefore, lambdaAfter);
Mock::VerifyAndClearExpectations(&rng);
// force scatter in segment 2
EXPECT_CALL(rng, nextValue())
.Times(Exactly(3))
.WillRepeatedly(Return(0.75));
const double factorSeg2 = interactor.calculateAbsorption(
rng, startPos, endPos, lambdaBefore, lambdaAfter);
Mock::VerifyAndClearExpectations(&rng);
void
test_Absorption_In_Sample_And_Environment_Container_Scatter_In_All_Segments() {
using Mantid::Kernel::V3D;
using namespace ::testing;
// Testing inputs
const V3D startPos(-2.0, 0.0, 0.0), endPos(2.0, 0.0, 0.0);
const double lambdaBefore(2.5), lambdaAfter(3.5);
auto sample = createTestSample(TestSampleType::SamplePlusContainer);
MockRNG rng;
// force scatter in segment can (1)
EXPECT_CALL(rng, nextInt(0, 1))
.Times(Exactly(1))
.WillOnce(Return(1)); // MCInteractionVolume::generatePoint
.Times(Exactly(3))
.WillOnce(Return(0.02)) // RandomPoint::bounded r1
.WillOnce(Return(0.5)) // r2
.WillOnce(Return(0.5)); // r3
MCInteractionVolume interactor(sample,
sample.getEnvironment().boundingBox());
const double factorContainer = interactor.calculateAbsorption(
rng, startPos, endPos, lambdaBefore, lambdaAfter);
Mock::VerifyAndClearExpectations(&rng);
// force scatter in sample (0)
EXPECT_CALL(rng, nextInt(0, 1))
.Times(Exactly(1))
.WillOnce(Return(0)); // MCInteractionVolume::generatePoint
.Times(Exactly(3))
.WillRepeatedly(Return(0.25)); // RandomPoint::bounded r1, r2, r3
const double factorSample = interactor.calculateAbsorption(
rng, startPos, endPos, lambdaBefore, lambdaAfter);
Mock::VerifyAndClearExpectations(&rng);
}
//----------------------------------------------------------------------------
// Failure cases
//----------------------------------------------------------------------------
void test_Construction_With_Invalid_Sample_Shape_Throws_Error() {
using Mantid::API::Sample;
Sample sample;
// nothing
TS_ASSERT_THROWS(
MCInteractionVolume mcv(sample, sample.getShape().getBoundingBox()),
const std::invalid_argument &);
sample.setShape(ComponentCreationHelper::createSphere(1));
TS_ASSERT_THROWS_NOTHING(
MCInteractionVolume mcv(sample, sample.getShape().getBoundingBox()));
void test_Throws_If_Point_Cannot_Be_Generated() {
using namespace Mantid::Kernel;
using namespace MonteCarloTesting;
using namespace ::testing;
// Testing inputs
const V3D startPos(-2.0, 0.0, 0.0), endPos(2.0, 0.0, 0.0);
const double lambdaBefore(2.5), lambdaAfter(3.5);
auto sample = createTestSample(TestSampleType::ThinAnnulus);
MersenneTwister rng;
rng.setSeed(1);
const size_t maxTries(1);
MCInteractionVolume interactor(sample, sample.getShape().getBoundingBox(),
maxTries);
TS_ASSERT_THROWS(interactor.calculateAbsorption(rng, startPos, endPos,
lambdaBefore, lambdaAfter),
const std::runtime_error &);
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
void testGeneratePointConsidersAllComponents() {
using namespace ::testing;
using namespace Mantid::Kernel;
using namespace MonteCarloTesting;
auto kit = createTestKit();
size_t maxAttempts(1);
using Mantid::API::Sample;
Sample sample;
sample.setShape(ComponentCreationHelper::createSphere(1));
sample.setEnvironment(
std::make_unique<Mantid::Geometry::SampleEnvironment>(*kit));
MCInteractionVolume interactor(
sample, kit->getComponent(0).getBoundingBox(), maxAttempts);
// Generate "random" sequence
MockRNG rng;
// Selects first component
EXPECT_CALL(rng, nextInt(_, _)).Times(Exactly(1)).WillOnce(Return(1));
EXPECT_CALL(rng, nextValue())
.Times(3)
.WillOnce(Return(0.55))
.WillOnce(Return(0.65))
.WillOnce(Return(0.70));
V3D comp1Point;
TS_ASSERT_THROWS_NOTHING(comp1Point = interactor.generatePoint(rng));
TS_ASSERT(kit->isValid(comp1Point));
Mock::VerifyAndClearExpectations(&rng);
// Selects second component
MCInteractionVolume interactor2(
sample, kit->getComponent(1).getBoundingBox(), maxAttempts);
EXPECT_CALL(rng, nextInt(_, _)).Times(Exactly(1)).WillOnce(Return(2));
EXPECT_CALL(rng, nextValue())
.Times(3)
.WillOnce(Return(0.55))
.WillOnce(Return(0.65))
.WillOnce(Return(0.70));
V3D comp2Point;
TS_ASSERT_THROWS_NOTHING(comp2Point = interactor2.generatePoint(rng));
TS_ASSERT(comp2Point != comp1Point);
TS_ASSERT(kit->isValid(comp2Point));
Mock::VerifyAndClearExpectations(&rng);
// Selects third component
MCInteractionVolume interactor3(
sample, kit->getComponent(2).getBoundingBox(), maxAttempts);
EXPECT_CALL(rng, nextInt(_, _)).Times(Exactly(1)).WillOnce(Return(3));
EXPECT_CALL(rng, nextValue())
.Times(3)
.WillOnce(Return(0.55))
.WillOnce(Return(0.65))
.WillOnce(Return(0.70));
V3D comp3Point;
TS_ASSERT_THROWS_NOTHING(comp3Point = interactor3.generatePoint(rng));
TS_ASSERT(comp3Point != comp2Point);
TS_ASSERT(comp3Point != comp1Point);
TS_ASSERT(kit->isValid(comp3Point));
Mock::VerifyAndClearExpectations(&rng);
}
void testGeneratePointRespectsActiveRegion() {
using namespace MonteCarloTesting;
using namespace ::testing;
using namespace Mantid::Kernel;
auto kit = createTestKit();
size_t maxAttempts(1);
// Generate "random" sequence
MockRNG rng;
// Sequence will try to select one of the non-container pieces
EXPECT_CALL(rng, nextInt(_, _)).Times(Exactly(1)).WillOnce(Return(2));
EXPECT_CALL(rng, nextValue()).Times(3).WillRepeatedly(Return(0.5));
using Mantid::API::Sample;
Sample sample;
sample.setShape(ComponentCreationHelper::createSphere(1));
sample.setEnvironment(
std::make_unique<Mantid::Geometry::SampleEnvironment>(*kit));
MCInteractionVolume interactor(sample, kit->getContainer().getBoundingBox(),
maxAttempts);
// Restrict region to can
TS_ASSERT_THROWS(interactor.generatePoint(rng), const std::runtime_error &);
Mock::VerifyAndClearExpectations(&rng);
}
};
#endif /* MANTID_ALGORITHMS_MCINTERACTIONVOLUMETEST_H_ */