Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:10

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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   // Test the standard orientations
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   // Test the flipped axis
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   // Standard TRD: XY are already well defined
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   // Flipped, yX are the coordinates
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   // YZ span the trapezoid
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   // Xz span the trapezoid
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   // Here it should be uncompressed material
0250   CHECK_CLOSE_ABS(materialSlab.material().massDensity(), rho, 0.001);
0251   CHECK_CLOSE_REL(thickness / g4Material->GetRadlen(),
0252                   materialSlab.thicknessInX0(), 0.1);
0253 
0254   // Convert with compression
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   // Here it should be uncompressed material
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   // Here it should be uncompressed material
0310   CHECK_CLOSE_ABS(materialSlab.material().massDensity(), rho, 0.001);
0311 
0312   /// CHECK exception throwing
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   // Here it should be uncompressed material
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()