From 07719f49b99ef40c862808e027e2c463ed5cf280 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Wed, 2 Sep 2026 11:46:41 +0200 Subject: [PATCH 1/2] Let the ZEM calorimeters be built without the far beam line This adds two ZDCSimParam switches so a simulation can keep the ZEM geometry without paying for transport to the ZN/ZP calorimeters at +-113 m. - The ZDC geometry is the +-113 m beam line, its magnets, ZN, ZP and ZEM; the transport cost is the beam line, while ZEM sits at z = 7.6 m. - buildBeamLine=false skips the beam line, the magnets and ZN/ZP; buildZEM controls the ZEM calorimeters. - The ZN and ZP construction moves into createZNZP() and the ZEM construction into createZEM(), so createDetectors() shows what depends on the beam line. - The PMC and PMQ medium ids move ahead of that branch: ProcessHits compares every step against them for ZEM too, so leaving them in the ZN block gave ZEM hits with no energy loss and no light yield. - The ZN/ZP sensitive volume lookups are guarded so they no longer abort when the volumes are absent. - 20 pythia8pp events with TGeant3: 276.9 s with the full ZDC, 141.6 +- 1.1 s with --skipModules ZDC, 136.9 +- 1.9 s with buildBeamLine=false. - 50 events of 20 muons at 200 GeV into 4.6 < eta < 5.3 give 234 ZEM hits with 2167 photoelectrons at buildBeamLine=false, against 230 hits and 2097 with the full ZDC. https://its.cern.ch/jira/browse/O2-7158 Co-Authored-By: Claude Opus 5 --- .../include/ZDCSimulation/Detector.h | 2 + .../include/ZDCSimulation/ZDCSimParam.h | 5 ++ Detectors/ZDC/simulation/src/Detector.cxx | 88 +++++++++++++------ 3 files changed, 66 insertions(+), 29 deletions(-) diff --git a/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h b/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h index 40e4babe8d760..f79fedf1da235 100644 --- a/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h +++ b/Detectors/ZDC/simulation/include/ZDCSimulation/Detector.h @@ -121,6 +121,8 @@ class Detector : public o2::base::DetImpl void createCsideBeamLine(); void createMagnets(); void createDetectors(); + void createZNZP(); + void createZEM(); // determine detector; sector/tower and impact coordinates given volumename and position void getDetIDandSecID(TString const& volname, math_utils::Vector3D const& x, diff --git a/Detectors/ZDC/simulation/include/ZDCSimulation/ZDCSimParam.h b/Detectors/ZDC/simulation/include/ZDCSimulation/ZDCSimParam.h index 8d4e95533cdd7..1ac1e43af0005 100644 --- a/Detectors/ZDC/simulation/include/ZDCSimulation/ZDCSimParam.h +++ b/Detectors/ZDC/simulation/include/ZDCSimulation/ZDCSimParam.h @@ -24,6 +24,11 @@ namespace zdc struct ZDCSimParam : public o2::conf::ConfigurableParamHelper { bool continuous = true; ///< flag for continuous simulation + /// Build the +-113 m beam line, its magnets and the ZN/ZP calorimeters that sit + /// there. This is what the ZDC costs in transport time; turning it off leaves the + /// ZEM calorimeters at z ~ 7.6 m in the geometry. + bool buildBeamLine = true; + bool buildZEM = true; ///< build the ZEM calorimeters int nBCAheadCont = 1; ///< number of BC to read ahead of trigger in continuous mode int nBCAheadTrig = 3; ///< number of BC to read ahead of trigger in triggered mode bool recordSpatialResponse = false; ///< whether to record 2D spatial response showering images in proton/neutron detector diff --git a/Detectors/ZDC/simulation/src/Detector.cxx b/Detectors/ZDC/simulation/src/Detector.cxx index b8b81379a4dff..8bc527bda4dad 100644 --- a/Detectors/ZDC/simulation/src/Detector.cxx +++ b/Detectors/ZDC/simulation/src/Detector.cxx @@ -217,9 +217,13 @@ void Detector::ConstructGeometry() createMaterials(); - createAsideBeamLine(); - createCsideBeamLine(); - createMagnets(); + if (ZDCSimParam::Instance().buildBeamLine) { + createAsideBeamLine(); + createCsideBeamLine(); + createMagnets(); + } else { + LOG(info) << "ZDC: beam line, magnets and the ZN/ZP calorimeters are not built"; + } createDetectors(); } @@ -227,29 +231,32 @@ void Detector::ConstructGeometry() void Detector::defineSensitiveVolumes() { LOG(info) << "defining sensitive for ZDC"; - auto vol = gGeoManager->GetVolume("ZNENV"); - if (vol) { - AddSensitiveVolume(vol); - mZNENVVolID = vol->GetNumber(); // initialize id - - AddSensitiveVolume(gGeoManager->GetVolume("ZNF1")); - AddSensitiveVolume(gGeoManager->GetVolume("ZNF2")); - AddSensitiveVolume(gGeoManager->GetVolume("ZNF3")); - AddSensitiveVolume(gGeoManager->GetVolume("ZNF4")); - } else { - LOG(fatal) << "can't find volume ZNENV"; - } - vol = gGeoManager->GetVolume("ZPENV"); - if (vol) { - AddSensitiveVolume(vol); - mZPENVVolID = vol->GetNumber(); // initialize id - - AddSensitiveVolume(gGeoManager->GetVolume("ZPF1")); - AddSensitiveVolume(gGeoManager->GetVolume("ZPF2")); - AddSensitiveVolume(gGeoManager->GetVolume("ZPF3")); - AddSensitiveVolume(gGeoManager->GetVolume("ZPF4")); - } else { - LOG(fatal) << "can't find volume ZPENV"; + TGeoVolume* vol = nullptr; + if (ZDCSimParam::Instance().buildBeamLine) { + vol = gGeoManager->GetVolume("ZNENV"); + if (vol) { + AddSensitiveVolume(vol); + mZNENVVolID = vol->GetNumber(); // initialize id + + AddSensitiveVolume(gGeoManager->GetVolume("ZNF1")); + AddSensitiveVolume(gGeoManager->GetVolume("ZNF2")); + AddSensitiveVolume(gGeoManager->GetVolume("ZNF3")); + AddSensitiveVolume(gGeoManager->GetVolume("ZNF4")); + } else { + LOG(fatal) << "can't find volume ZNENV"; + } + vol = gGeoManager->GetVolume("ZPENV"); + if (vol) { + AddSensitiveVolume(vol); + mZPENVVolID = vol->GetNumber(); // initialize id + + AddSensitiveVolume(gGeoManager->GetVolume("ZPF1")); + AddSensitiveVolume(gGeoManager->GetVolume("ZPF2")); + AddSensitiveVolume(gGeoManager->GetVolume("ZPF3")); + AddSensitiveVolume(gGeoManager->GetVolume("ZPF4")); + } else { + LOG(fatal) << "can't find volume ZPENV"; + } } // em calorimeter vol = gGeoManager->GetVolume("ZEM "); @@ -257,7 +264,7 @@ void Detector::defineSensitiveVolumes() AddSensitiveVolume(vol); mZEMVolID = vol->GetNumber(); AddSensitiveVolume(gGeoManager->GetVolume("ZEMF")); - } else { + } else if (ZDCSimParam::Instance().buildZEM) { LOG(fatal) << "can't find volume ZEM"; } } @@ -2068,6 +2075,22 @@ void Detector::createMagnets() } //_____________________________________________________________________________ void Detector::createDetectors() +{ + // ProcessHits compares the medium of every step against these two, for ZEM as + // much as for ZN and ZP, so they have to be resolved whatever is built. + mMediumPMCid = getMediumID(kSiO2pmc); + mMediumPMQid = getMediumID(kSiO2pmq); + + // ZN and ZP sit in the ZDCA/ZDCC mother volumes that the beam line builds, so + // they stand or fall with it. ZEM is at z = 7.6 m and is built either way. + if (ZDCSimParam::Instance().buildBeamLine) { + createZNZP(); + } + createZEM(); +} + +//_____________________________________________________________________________ +void Detector::createZNZP() { // Create the ZDCs @@ -2082,8 +2105,6 @@ void Detector::createDetectors() // ------------------------------------------------------------------------------- //--> Neutron calorimeter (ZN) - mMediumPMCid = getMediumID(kSiO2pmc); - mMediumPMQid = getMediumID(kSiO2pmq); // an envelop volume for the purpose of registering particles entering the detector double eps = 0.1; // 1 mm @@ -2300,8 +2321,17 @@ void Detector::createDetectors() TVirtualMC::GetMC()->Gspos("ZPBS", 3, "ZDCA", Geometry::ZPAPOSITION[0] + Geometry::ZPDIMENSION[0] + zpSupportWallside[0], Geometry::ZPAPOSITION[1] + 0.75, Geometry::ZPAPOSITION[2] + zpSupportWallside[2], 0, "ONLY"); TVirtualMC::GetMC()->Gspos("ZPBS", 4, "ZDCA", Geometry::ZPAPOSITION[0] - Geometry::ZPDIMENSION[0] - zpSupportWallside[0], Geometry::ZPAPOSITION[1] + 0.75, Geometry::ZPAPOSITION[2] + zpSupportWallside[2], 0, "ONLY"); +} + +//_____________________________________________________________________________ +void Detector::createZEM() +{ // ------------------------------------------------------------------------------- // -> EM calorimeter (ZEM) + if (!ZDCSimParam::Instance().buildZEM) { + LOG(warning) << "ZDC: the ZEM calorimeters are not built"; + return; + } int32_t irotzem1, irotzem2; double rangzem1[6] = {0., 0., 90., 90., -90., 0.}; double rangzem2[6] = {180., 0., 90., 45. + 90., 90., 45.}; From 6b1f1fc0d7495fc162a90e6e07e1d4b035ac6a08 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Wed, 2 Sep 2026 12:31:11 +0000 Subject: [PATCH 2/2] Please consider the following formatting changes --- Detectors/ZDC/simulation/src/Detector.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Detectors/ZDC/simulation/src/Detector.cxx b/Detectors/ZDC/simulation/src/Detector.cxx index 8bc527bda4dad..6ffe0cfd7921c 100644 --- a/Detectors/ZDC/simulation/src/Detector.cxx +++ b/Detectors/ZDC/simulation/src/Detector.cxx @@ -2320,7 +2320,6 @@ void Detector::createZNZP() TVirtualMC::GetMC()->Gspos("ZPBS", 2, "ZDCC", Geometry::ZPCPOSITION[0] - Geometry::ZPDIMENSION[0] - zpSupportWallside[0], Geometry::ZPCPOSITION[1] + 0.75, Geometry::ZPCPOSITION[2] - zpSupportWallside[2], 0, "ONLY"); TVirtualMC::GetMC()->Gspos("ZPBS", 3, "ZDCA", Geometry::ZPAPOSITION[0] + Geometry::ZPDIMENSION[0] + zpSupportWallside[0], Geometry::ZPAPOSITION[1] + 0.75, Geometry::ZPAPOSITION[2] + zpSupportWallside[2], 0, "ONLY"); TVirtualMC::GetMC()->Gspos("ZPBS", 4, "ZDCA", Geometry::ZPAPOSITION[0] - Geometry::ZPDIMENSION[0] - zpSupportWallside[0], Geometry::ZPAPOSITION[1] + 0.75, Geometry::ZPAPOSITION[2] + zpSupportWallside[2], 0, "ONLY"); - } //_____________________________________________________________________________