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