File indexing completed on 2025-01-18 09:13:10
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Material/ISurfaceMaterial.hpp"
0013 #include "Acts/Material/Material.hpp"
0014 #include "Acts/Material/MaterialSlab.hpp"
0015 #include "Acts/Plugins/Geant4/Geant4Converters.hpp"
0016 #include "Acts/Surfaces/CylinderBounds.hpp"
0017 #include "Acts/Surfaces/LineBounds.hpp"
0018 #include "Acts/Surfaces/RadialBounds.hpp"
0019 #include "Acts/Surfaces/RectangleBounds.hpp"
0020 #include "Acts/Surfaces/Surface.hpp"
0021 #include "Acts/Surfaces/TrapezoidBounds.hpp"
0022 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0023
0024 #include <array>
0025 #include <cmath>
0026 #include <memory>
0027 #include <numbers>
0028 #include <stdexcept>
0029 #include <tuple>
0030
0031 #include "G4Box.hh"
0032 #include "G4LogicalVolume.hh"
0033 #include "G4Material.hh"
0034 #include "G4PVPlacement.hh"
0035 #include "G4RotationMatrix.hh"
0036 #include "G4SystemOfUnits.hh"
0037 #include "G4ThreeVector.hh"
0038 #include "G4Trd.hh"
0039 #include "G4Tubs.hh"
0040 #include "G4VPhysicalVolume.hh"
0041
0042 double rho = 1.2345;
0043 G4Material* g4Material = new G4Material("Material", 6., 12., rho);
0044
0045 BOOST_AUTO_TEST_SUITE(Geant4Plugin)
0046
0047 BOOST_AUTO_TEST_CASE(Geant4AlgebraConversion) {
0048 G4ThreeVector g4Translation(10., 20., 30.);
0049
0050 auto translated = Acts::Geant4AlgebraConverter{}.transform(g4Translation);
0051 auto actsTranslation = translated.translation();
0052 BOOST_CHECK_EQUAL(actsTranslation[0], 10.);
0053 BOOST_CHECK_EQUAL(actsTranslation[1], 20.);
0054 BOOST_CHECK_EQUAL(actsTranslation[2], 30.);
0055
0056 auto translatedScaled =
0057 Acts::Geant4AlgebraConverter{10.}.transform(g4Translation);
0058 auto actsTranslationScaled = translatedScaled.translation();
0059 BOOST_CHECK_EQUAL(actsTranslationScaled[0], 100.);
0060 BOOST_CHECK_EQUAL(actsTranslationScaled[1], 200.);
0061 BOOST_CHECK_EQUAL(actsTranslationScaled[2], 300.);
0062 }
0063
0064 BOOST_AUTO_TEST_CASE(Geant4CylinderConversion) {
0065 G4Tubs cylinder("Cylinder", 399., 401., 800.,
0066 -std::numbers::pi * CLHEP::radian,
0067 2 * std::numbers::pi * CLHEP::radian);
0068 auto [bounds, thickness] =
0069 Acts::Geant4ShapeConverter{}.cylinderBounds(cylinder);
0070 CHECK_CLOSE_ABS(bounds->get(Acts::CylinderBounds::BoundValues::eR), 400.,
0071 10e-10);
0072 CHECK_CLOSE_ABS(bounds->get(Acts::CylinderBounds::BoundValues::eHalfLengthZ),
0073 800., 10e-10);
0074 CHECK_CLOSE_ABS(
0075 bounds->get(Acts::CylinderBounds::BoundValues::eHalfPhiSector),
0076 std::numbers::pi, 10e-10);
0077 CHECK_CLOSE_ABS(bounds->get(Acts::CylinderBounds::BoundValues::eAveragePhi),
0078 0., 10e-10);
0079 CHECK_CLOSE_ABS(thickness, 2., 10e-10);
0080 }
0081
0082 BOOST_AUTO_TEST_CASE(Geant4RadialConversion) {
0083 G4Tubs disc("disc", 40., 400., 2., -std::numbers::pi * CLHEP::radian,
0084 2 * std::numbers::pi * CLHEP::radian);
0085 auto [bounds, thickness] = Acts::Geant4ShapeConverter{}.radialBounds(disc);
0086 CHECK_CLOSE_ABS(bounds->get(Acts::RadialBounds::BoundValues::eMinR), 40.,
0087 10e-10);
0088 CHECK_CLOSE_ABS(bounds->get(Acts::RadialBounds::BoundValues::eMaxR), 400.,
0089 10e-10);
0090 CHECK_CLOSE_ABS(bounds->get(Acts::RadialBounds::BoundValues::eHalfPhiSector),
0091 std::numbers::pi, 10e-10);
0092 CHECK_CLOSE_ABS(bounds->get(Acts::RadialBounds::BoundValues::eAveragePhi), 0.,
0093 10e-10);
0094 CHECK_CLOSE_ABS(thickness, 4., 10e-10);
0095 }
0096
0097 BOOST_AUTO_TEST_CASE(Geant4LineConversion) {
0098 G4Tubs line("line", 0., 20., 400., 0., 2 * std::numbers::pi);
0099 auto bounds = Acts::Geant4ShapeConverter{}.lineBounds(line);
0100 CHECK_CLOSE_ABS(bounds->get(Acts::LineBounds::BoundValues::eR), 20., 10e-10);
0101 CHECK_CLOSE_ABS(bounds->get(Acts::LineBounds::BoundValues::eHalfLengthZ),
0102 400., 10e-10);
0103 }
0104
0105 BOOST_AUTO_TEST_CASE(Geant4BoxConversion) {
0106
0107 G4Box sensorXY("SensorXY", 23., 34., 1.);
0108 auto [boundsXY, axesXY, thicknessZ] =
0109 Acts::Geant4ShapeConverter{}.rectangleBounds(sensorXY);
0110 CHECK_CLOSE_ABS(boundsXY->halfLengthX(), 23., 10e-10);
0111 CHECK_CLOSE_ABS(boundsXY->halfLengthY(), 34., 10e-10);
0112 auto refXY = std::array<int, 2u>{0, 1};
0113 BOOST_CHECK(axesXY == refXY);
0114 CHECK_CLOSE_ABS(thicknessZ, 2., 10e-10);
0115
0116 G4Box sensorYZ("SensorYZ", 2., 45., 56.);
0117 auto [boundsYZ, axesYZ, thicknessX] =
0118 Acts::Geant4ShapeConverter{}.rectangleBounds(sensorYZ);
0119 CHECK_CLOSE_ABS(boundsYZ->halfLengthX(), 45., 10e-10);
0120 CHECK_CLOSE_ABS(boundsYZ->halfLengthY(), 56., 10e-10);
0121 auto refYZ = std::array<int, 2u>{1, 2};
0122 BOOST_CHECK(axesYZ == refYZ);
0123 CHECK_CLOSE_ABS(thicknessX, 4., 10e-10);
0124
0125 G4Box sensorZX("SensorZX", 78., 2., 67.);
0126 auto [boundsZX, axesZX, thicknessY] =
0127 Acts::Geant4ShapeConverter{}.rectangleBounds(sensorZX);
0128 CHECK_CLOSE_ABS(boundsZX->halfLengthX(), 67., 10e-10);
0129 CHECK_CLOSE_ABS(boundsZX->halfLengthY(), 78., 10e-10);
0130 auto refZX = std::array<int, 2u>{2, 0};
0131 BOOST_CHECK(axesZX == refZX);
0132 CHECK_CLOSE_ABS(thicknessY, 4., 10e-10);
0133
0134
0135 G4Box sensorXz("SensorXz", 78., 2., 67.);
0136 auto [boundsXz, axesXz, thicknessY2] =
0137 Acts::Geant4ShapeConverter{1, true}.rectangleBounds(sensorXz);
0138 CHECK_CLOSE_ABS(boundsXz->halfLengthX(), 78., 10e-10);
0139 CHECK_CLOSE_ABS(boundsXz->halfLengthY(), 67., 10e-10);
0140 auto refXz = std::array<int, 2u>{0, -2};
0141 BOOST_CHECK(axesXz == refXz);
0142 CHECK_CLOSE_ABS(thicknessY2, 4., 10e-10);
0143 }
0144
0145 BOOST_AUTO_TEST_CASE(Geant4TrapzoidConversion) {
0146
0147 G4Trd trdXY("trdXY", 100, 150, 200, 200, 2);
0148 auto [boundsXY, axesXY, thicknessZ] =
0149 Acts::Geant4ShapeConverter{}.trapezoidBounds(trdXY);
0150 CHECK_CLOSE_ABS(
0151 boundsXY->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXnegY), 100,
0152 10e-10);
0153 CHECK_CLOSE_ABS(
0154 boundsXY->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXposY), 150,
0155 10e-10);
0156 CHECK_CLOSE_ABS(
0157 boundsXY->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthY), 200,
0158 10e-10);
0159 auto refXY = std::array<int, 2u>{0, 1};
0160 BOOST_CHECK(axesXY == refXY);
0161 CHECK_CLOSE_ABS(thicknessZ, 4., 10e-10);
0162
0163
0164 G4Trd trdyX("trdyX", 200, 200, 100, 150, 2);
0165 auto [boundsyX, axesyX, thicknessZ2] =
0166 Acts::Geant4ShapeConverter{}.trapezoidBounds(trdyX);
0167 CHECK_CLOSE_ABS(
0168 boundsyX->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXnegY), 100,
0169 10e-10);
0170 CHECK_CLOSE_ABS(
0171 boundsyX->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXposY), 150,
0172 10e-10);
0173 CHECK_CLOSE_ABS(
0174 boundsyX->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthY), 200,
0175 10e-10);
0176 auto refyX = std::array<int, 2u>{-1, 0};
0177 BOOST_CHECK(axesyX == refyX);
0178 CHECK_CLOSE_ABS(thicknessZ2, 4., 10e-10);
0179
0180
0181 G4Trd trdYZ("trdYZ", 2, 2, 120, 140, 200);
0182 auto [boundsYZ, axesYZ, thicknessX] =
0183 Acts::Geant4ShapeConverter{}.trapezoidBounds(trdYZ);
0184 CHECK_CLOSE_ABS(
0185 boundsYZ->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXnegY), 120.,
0186 10e-10);
0187 CHECK_CLOSE_ABS(
0188 boundsYZ->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXposY), 140.,
0189 10e-10);
0190 CHECK_CLOSE_ABS(
0191 boundsYZ->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthY), 200.,
0192 10e-10);
0193 auto refYZ = std::array<int, 2u>{1, 2};
0194 BOOST_CHECK(axesYZ == refYZ);
0195 CHECK_CLOSE_ABS(thicknessX, 4., 10e-10);
0196
0197
0198 G4Trd trdXz("trdXz", 50, 75, 1, 1, 200);
0199 auto [boundsXz, axesXz, thicknessY] =
0200 Acts::Geant4ShapeConverter{}.trapezoidBounds(trdXz);
0201 CHECK_CLOSE_ABS(
0202 boundsXz->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXnegY), 50.,
0203 10e-10);
0204 CHECK_CLOSE_ABS(
0205 boundsXz->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXposY), 75.,
0206 10e-10);
0207 CHECK_CLOSE_ABS(
0208 boundsXz->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthY), 200.,
0209 10e-10);
0210 auto refXz = std::array<int, 2u>{0, -2};
0211 BOOST_CHECK(axesXz == refXz);
0212 CHECK_CLOSE_ABS(thicknessY, 2., 10e-10);
0213 }
0214
0215 BOOST_AUTO_TEST_CASE(Geant4PlanarConversion) {
0216 G4Box boxXY("boxXY", 23., 34., 1.);
0217 auto pBoundsBox =
0218 std::get<0u>(Acts::Geant4ShapeConverter{}.planarBounds(boxXY));
0219 auto rBounds = dynamic_cast<const Acts::RectangleBounds*>(pBoundsBox.get());
0220 BOOST_CHECK_NE(rBounds, nullptr);
0221
0222 G4Trd trdXY("trdXY", 100, 150, 200, 200, 2);
0223 auto pBoundsTrd =
0224 std::get<0u>(Acts::Geant4ShapeConverter{}.planarBounds(trdXY));
0225 auto tBounds = dynamic_cast<const Acts::TrapezoidBounds*>(pBoundsTrd.get());
0226 BOOST_CHECK_NE(tBounds, nullptr);
0227 }
0228
0229 BOOST_AUTO_TEST_CASE(Geant4BoxVPhysConversion) {
0230 double thickness = 2.;
0231
0232 G4Box* g4Box = new G4Box("Box", 23., 34., 0.5 * thickness);
0233 G4RotationMatrix* g4Rot = new G4RotationMatrix({0., 0., 1.}, 1.2);
0234 G4LogicalVolume* g4BoxLog = new G4LogicalVolume(g4Box, g4Material, "BoxLog");
0235
0236 G4ThreeVector g4Trans(0., 0., 100.);
0237 G4PVPlacement g4BoxPhys(g4Rot, g4Trans, g4BoxLog, "BoxPhys", nullptr, false,
0238 1);
0239
0240 auto planeSurface = Acts::Geant4PhysicalVolumeConverter{}.surface(
0241 g4BoxPhys, Acts::Transform3::Identity(), true, thickness);
0242 BOOST_REQUIRE_NE(planeSurface, nullptr);
0243 BOOST_CHECK_EQUAL(planeSurface->type(), Acts::Surface::SurfaceType::Plane);
0244
0245 auto material = planeSurface->surfaceMaterial();
0246 BOOST_REQUIRE_NE(material, nullptr);
0247
0248 auto materialSlab = material->materialSlab(Acts::Vector3{0., 0., 0.});
0249
0250 CHECK_CLOSE_ABS(materialSlab.material().massDensity(), rho, 0.001);
0251 CHECK_CLOSE_REL(thickness / g4Material->GetRadlen(),
0252 materialSlab.thicknessInX0(), 0.1);
0253
0254
0255 double compression = 4.;
0256 planeSurface = Acts::Geant4PhysicalVolumeConverter{}.surface(
0257 g4BoxPhys, Acts::Transform3::Identity(), true, thickness / compression);
0258 BOOST_REQUIRE_NE(planeSurface, nullptr);
0259 BOOST_CHECK_EQUAL(planeSurface->type(), Acts::Surface::SurfaceType::Plane);
0260
0261 material = planeSurface->surfaceMaterial();
0262 BOOST_REQUIRE_NE(material, nullptr);
0263 materialSlab = material->materialSlab(Acts::Vector3{0., 0., 0.});
0264
0265
0266 CHECK_CLOSE_ABS(materialSlab.material().massDensity(), compression * rho,
0267 0.001);
0268 CHECK_CLOSE_REL(thickness / g4Material->GetRadlen(),
0269 materialSlab.thicknessInX0(), 0.01);
0270
0271 CHECK_CLOSE_ABS(materialSlab.thickness(), thickness / compression, 0.01);
0272 CHECK_CLOSE_REL(materialSlab.material().X0() * compression,
0273 g4Material->GetRadlen(), 0.01);
0274
0275 delete g4Box;
0276 delete g4Rot;
0277 delete g4BoxLog;
0278 }
0279
0280 BOOST_AUTO_TEST_CASE(Geant4CylVPhysConversion) {
0281 double radius = 45.;
0282 double thickness = 1.;
0283 double halfLengthZ = 200;
0284
0285 G4Tubs* g4Tube = new G4Tubs("Tube", radius, radius + thickness, halfLengthZ,
0286 -std::numbers::pi * CLHEP::radian,
0287 2 * std::numbers::pi * CLHEP::radian);
0288
0289 G4RotationMatrix* g4Rot = new G4RotationMatrix({0., 0., 1.}, 0.);
0290 G4LogicalVolume* g4TubeLog =
0291 new G4LogicalVolume(g4Tube, g4Material, "TubeLog");
0292 G4ThreeVector g4Trans(0., 0., 100.);
0293 G4PVPlacement g4CylinderPhys(g4Rot, g4Trans, g4TubeLog, "TubePhys", nullptr,
0294 false, 1);
0295
0296 auto cylinderSurface = Acts::Geant4PhysicalVolumeConverter{}.surface(
0297 g4CylinderPhys, Acts::Transform3::Identity(), true, thickness);
0298 BOOST_REQUIRE_NE(cylinderSurface, nullptr);
0299 BOOST_CHECK_EQUAL(cylinderSurface->type(),
0300 Acts::Surface::SurfaceType::Cylinder);
0301
0302 auto material = cylinderSurface->surfaceMaterial();
0303 BOOST_REQUIRE_NE(material, nullptr);
0304
0305 auto materialSlab = material->materialSlab(Acts::Vector3{0., 0., 0.});
0306 CHECK_CLOSE_REL(thickness / g4Material->GetRadlen(),
0307 materialSlab.thicknessInX0(), 0.1);
0308
0309
0310 CHECK_CLOSE_ABS(materialSlab.material().massDensity(), rho, 0.001);
0311
0312
0313 BOOST_CHECK_THROW(
0314 Acts::Geant4PhysicalVolumeConverter{Acts::Surface::SurfaceType::Plane}
0315 .surface(g4CylinderPhys, Acts::Transform3::Identity(), true,
0316 thickness),
0317 std::runtime_error);
0318
0319 delete g4Tube;
0320 delete g4Rot;
0321 delete g4TubeLog;
0322 }
0323
0324 BOOST_AUTO_TEST_CASE(Geant4VDiscVPhysConversion) {
0325 double innerRadius = 45.;
0326 double outerRadius = 75.;
0327 double thickness = 2.;
0328
0329 G4Tubs* g4Tube = new G4Tubs("Disc", innerRadius, outerRadius, 0.5 * thickness,
0330 -std::numbers::pi * CLHEP::radian,
0331 2 * std::numbers::pi * CLHEP::radian);
0332
0333 G4RotationMatrix* g4Rot = new G4RotationMatrix({0., 0., 1.}, 0.);
0334 G4LogicalVolume* g4TubeLog =
0335 new G4LogicalVolume(g4Tube, g4Material, "TubeLog");
0336 G4ThreeVector g4Trans(0., 0., 100.);
0337 G4PVPlacement g4discPhys(g4Rot, g4Trans, g4TubeLog, "TubePhys", nullptr,
0338 false, 1);
0339
0340 auto discSurface = Acts::Geant4PhysicalVolumeConverter{}.surface(
0341 g4discPhys, Acts::Transform3::Identity(), true, thickness);
0342 BOOST_REQUIRE_NE(discSurface, nullptr);
0343 BOOST_CHECK_EQUAL(discSurface->type(), Acts::Surface::SurfaceType::Disc);
0344
0345 auto material = discSurface->surfaceMaterial();
0346 BOOST_REQUIRE_NE(material, nullptr);
0347
0348 auto materialSlab = material->materialSlab(Acts::Vector3{0., 0., 0.});
0349
0350 CHECK_CLOSE_ABS(materialSlab.material().massDensity(), rho, 0.001);
0351
0352 delete g4Tube;
0353 delete g4Rot;
0354 delete g4TubeLog;
0355 }
0356
0357 BOOST_AUTO_TEST_CASE(Geant4LineVPhysConversion) {
0358 double innerRadius = 0.;
0359 double outerRadius = 20.;
0360 double thickness = 400.;
0361
0362 G4Tubs* g4Tube = new G4Tubs("Line", innerRadius, outerRadius, 0.5 * thickness,
0363 -std::numbers::pi * CLHEP::radian,
0364 2 * std::numbers::pi * CLHEP::radian);
0365
0366 G4RotationMatrix* g4Rot = new G4RotationMatrix({0., 0., 1.}, 0.);
0367 G4LogicalVolume* g4TubeLog =
0368 new G4LogicalVolume(g4Tube, g4Material, "LineLog");
0369 G4ThreeVector g4Trans(0., 0., 100.);
0370 G4PVPlacement g4linePhys(g4Rot, g4Trans, g4TubeLog, "LinePhys", nullptr,
0371 false, 1);
0372
0373 auto lineSurface =
0374 Acts::Geant4PhysicalVolumeConverter{Acts::Surface::SurfaceType::Straw}
0375 .surface(g4linePhys, Acts::Transform3::Identity(), true, thickness);
0376 BOOST_REQUIRE_NE(lineSurface, nullptr);
0377 BOOST_CHECK_EQUAL(lineSurface->type(), Acts::Surface::SurfaceType::Straw);
0378
0379 delete g4Tube;
0380 delete g4Rot;
0381 delete g4TubeLog;
0382 }
0383
0384 BOOST_AUTO_TEST_SUITE_END()