Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ZDC_RPDModule.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "ZDC_RPDModule.h"
6 
7 #include "GeoModelKernel/GeoShape.h"
8 #include "GeoModelKernel/GeoBox.h"
9 #include "GeoModelKernel/GeoTube.h"
10 #include "GeoModelKernel/GeoLogVol.h"
11 #include "GeoModelKernel/GeoNameTag.h"
12 #include "GeoModelKernel/GeoPhysVol.h"
13 #include "GeoModelKernel/GeoFullPhysVol.h"
14 #include "GeoModelKernel/GeoTransform.h"
15 #include "GeoModelKernel/GeoIdentifierTag.h"
16 #include "GeoModelKernel/GeoAlignableTransform.h"
17 #include "GeoModelKernel/GeoDefinitions.h"
18 #include "GeoModelKernel/Units.h"
20 #include "GeoModelKernel/GeoMaterial.h"
21 #include "GaudiKernel/SystemOfUnits.h"
22 #include "GaudiKernel/MsgStream.h"
24 #include "ZdcIdentifier/ZdcID.h"
25 #include "CLHEP/Geometry/Transform3D.h"
26 #include <stdexcept>
27 
28 void ZDC_RPDModule::create(GeoFullPhysVol* mother, StoredMaterialManager *materialManager, const ZdcID *zdcID){
29 
30  MsgStream LogStream(Athena::getMessageSvc(), "ZDC_RPDModule::create");
31 
32  const GeoMaterial *Aluminum = materialManager->getMaterial("std::Aluminium");
33  const GeoMaterial *OpAir = materialManager->getMaterial("ZDC::opticalAir");
34  const GeoMaterial *OpSilicaCore = materialManager->getMaterial("ZDC::opticalSilica");
35  const GeoMaterial *OpSilicaClad = materialManager->getMaterial("ZDC::opticalSilicaClad");
36  const GeoMaterial *OpKapton = materialManager->getMaterial("ZDC::opticalKapton");
37 
38  // All parameters are either in mm or are unitless
39  const int nRows = 4;
40  const int nCols = 4;
41  const float coreDia = 0.60; // Fiber core diameter
42  const float cladDia = 0.66; // Fiber cladding diameter
43  const float buffDia = 0.71; // Fiber buffer diameter
44  const float fiberPitchX = 1.425; // Spacing between fibers in X
45  const float fiberPitchZ = 1.63; // Spacing between fibers in Z
46  const float tileSize = 11.4; // Size of a square "tile"
47  const float housingThickness = 5; // Thickness of aluminum housing
48  const float detectorInnerWidth = 4 * tileSize; // Width (x) of the detector cavity which contains the fibers
49  const float detectorInnerDepth = 8 * fiberPitchZ + buffDia; // Depth (z) of the detector cavity which contains the fibers
50  const float footWidth = 91; // Width of the foot of the module
51  const float footDepth = 75; // Depth of the foot of the module
52  const float footHeight = 10; // Height of the foot of the module
53  const float posY = m_trf.translation().y(); // Y position of center of the tiles
54 
55  const GeoBox* motherBox = dynamic_cast<const GeoBox*>(mother->getLogVol()->getShape());
56  if (not motherBox){
57  throw (std::runtime_error("ZDC_RPDModule::create: motherBox is a nullptr"));
58  }
59  const float halfY = motherBox->getYHalfLength();
60 
61  // Height of the extension between the main RPD body and the foot
62  const float detectorHeight = 2*halfY - footHeight; // Height of the detector minus the foot
63  const float readoutFiberLength = halfY - posY - 2*tileSize; // Length of the "readout" section of the fibers, not including the active area extension
64 
65  // Build the main transforms here
66  //The foot has to be placed at the bottom of the TAN/TAXN slot
67  const GeoTrf::Transform3D footTrf = GeoTrf::TranslateY3D((-halfY - posY + footHeight * 0.5) * Gaudi::Units::mm) * m_trf;
68 
69  //The main housing is shifted up by half the foot height
70  const GeoTrf::Transform3D moduleTrf = GeoTrf::TranslateY3D((0.5 * footHeight - posY) * Gaudi::Units::mm) * m_trf;
71 
72  char volName[64];
73 
74  // Aluminum housing (case)
75  GeoBox *Housing_Box = new GeoBox((detectorInnerWidth + 2 * housingThickness) * Gaudi::Units::mm * 0.5,
76  detectorHeight * Gaudi::Units::mm * 0.5,
77  (detectorInnerDepth + 2 * housingThickness) * Gaudi::Units::mm * 0.5);
78 
79  GeoLogVol *Housing_Logical = new GeoLogVol("RPD_Housing_Logical", Housing_Box, Aluminum);
80  GeoFullPhysVol *Housing_Physical = new GeoFullPhysVol(Housing_Logical);
81 
82  // Detector inner volume
83  GeoBox *Module_Box = new GeoBox(detectorInnerWidth * Gaudi::Units::mm * 0.5,
84  readoutFiberLength * Gaudi::Units::mm * 0.5,
85  detectorInnerDepth * Gaudi::Units::mm * 0.5);
86 
87  GeoLogVol *Module_Logical = new GeoLogVol("RPD_Module_Logical", Module_Box, OpAir);
88  GeoPhysVol *Module_Physical = new GeoPhysVol(Module_Logical);
89 
90  // Foot
91  GeoBox *Foot_Box = new GeoBox(footWidth * Gaudi::Units::mm * 0.5,
92  footHeight * Gaudi::Units::mm * 0.5,
93  footDepth * Gaudi::Units::mm * 0.5);
94 
95  GeoLogVol *Foot_Logical = new GeoLogVol("RPD_Foot_Logical", Foot_Box, Aluminum);
96  GeoPhysVol *Foot_Physical = new GeoPhysVol(Foot_Logical);
97 
98  // Readout fiber volumes are made here because they're all the same length
99  // Core
100  GeoTube *Readout_Core_Tube = new GeoTube(0.0 * Gaudi::Units::mm, coreDia * Gaudi::Units::mm * 0.5, readoutFiberLength * Gaudi::Units::mm * 0.5);
101  GeoLogVol *Readout_Core_Logical = new GeoLogVol("RPD_Core_Readout_Logical", Readout_Core_Tube, OpSilicaCore);
102  GeoPhysVol *Readout_Core_Physical = new GeoPhysVol(Readout_Core_Logical);
103 
104  // Cladding
105  GeoTube *Readout_Clad_Tube = new GeoTube(coreDia * Gaudi::Units::mm * 0.5, cladDia * Gaudi::Units::mm * 0.5, readoutFiberLength * Gaudi::Units::mm * 0.5);
106  GeoLogVol *Readout_Clad_Logical = new GeoLogVol("RPD_Clad_Readout_Logical", Readout_Clad_Tube, OpSilicaClad);
107  GeoPhysVol *Readout_Clad_Physical = new GeoPhysVol(Readout_Clad_Logical);
108 
109  // Buffer
110  GeoTube *Readout_Buffer_Tube = new GeoTube(cladDia * Gaudi::Units::mm * 0.5, buffDia * Gaudi::Units::mm * 0.5, readoutFiberLength * Gaudi::Units::mm * 0.5);
111  GeoLogVol *Readout_Buffer_Logical = new GeoLogVol("RPD_Buff_Readout_Logical", Readout_Buffer_Tube, OpKapton);
112  GeoPhysVol *Readout_Buffer_Physical = new GeoPhysVol(Readout_Buffer_Logical);
113 
114  /***************************************************
115  *
116  * The fibers are positioned in a way that distributes of all channels in a given column evenly in z
117  * This is done by offsetting each fiber in x and z. For example, fibers for a single channel would look like this
118  *
119  * -0-------0--------
120  * ---0-------0------
121  * -----0-------0----
122  * -------0--------0-
123  *
124  * The cycle has been repeated twice in order to achieve a "tile" size of approximately 10mm (11.4) while maintaining maximum density of fibers
125  * Additionally this pattern is mirrored in z and interlaced with the first pattern. This is done to have uniformity in z for a given channel
126  *
127  * Pattern1 Pattern2 Sum
128  * -0-------0-------- -------0--------0- -0-----0-0------0-
129  * so ---0-------0------ + -----0-------0---- = ---0-0-----0-0----
130  * -----0-------0---- ---0-------0------ ---0-0-----0-0----
131  * -------0--------0- -0-------0-------- -0-----0-0------0-
132  *
133  * Everything above was for a single channel in row 0. Each row in a given colum starts the same pattern, just offset by fiberPitchZ
134  * So that looks like this, where the number represents the row
135  *
136  * -0--1--2--3--0--1--2--3--
137  * -3--0--1--2--3--0--1--2--
138  * -2--3--0--1--2--3--0--1--
139  * -1--2--3--0--1--2--3--0-
140  *
141  ****************************************************/
142 
143  float startX = tileSize * nCols * 0.5 - fiberPitchX / 4;
144  float startZ = -fiberPitchZ * (nCols - 0.5) * 0.5;
145  const unsigned int NFIBERS = 64; // Per row
146  for (int row = 0; row < nRows; ++row)
147  {
148  float fiberLength = (1 + row) * tileSize;
149  // float y = (-detectorHeight * 0.5 + housingThickness + tileSize * nRows - fiberLength * 0.5) * Gaudi::Units::mm;
150  float y = (posY - 0.5 * footHeight + 0.5 * tileSize * nRows - fiberLength * 0.5) * Gaudi::Units::mm;
151 
152  // Core
153  sprintf(volName, "RPD_Core_Active_Logical %d", row);
154  GeoTube *Active_Core_Tube = new GeoTube(0.0 * Gaudi::Units::mm, coreDia * Gaudi::Units::mm * 0.5, fiberLength * Gaudi::Units::mm * 0.5);
155  GeoLogVol *Active_Core_Logical= new GeoLogVol(volName, Active_Core_Tube, OpSilicaCore);
156  GeoPhysVol *Active_Core_Physical = new GeoPhysVol(Active_Core_Logical);
157 
158  // Cladding
159  sprintf(volName, "RPD_Clad_Active_Logical %d", row);
160  GeoTube *Active_Clad_Tube = new GeoTube(coreDia * Gaudi::Units::mm * 0.5, cladDia * Gaudi::Units::mm * 0.5, fiberLength * Gaudi::Units::mm * 0.5);
161  GeoLogVol *Active_Clad_Logical = new GeoLogVol(volName, Active_Clad_Tube, OpSilicaClad);
162  GeoPhysVol *Active_Clad_Physical = new GeoPhysVol(Active_Clad_Logical);
163 
164  // Buffer
165  sprintf(volName, "RPD_Buff_Active_Logical %d", row);
166  GeoTube *Active_Buffer_Tube = new GeoTube(cladDia * Gaudi::Units::mm * 0.5, buffDia * Gaudi::Units::mm * 0.5, fiberLength * Gaudi::Units::mm * 0.5);
167  GeoLogVol *Active_Buffer_Logical = new GeoLogVol(volName, Active_Buffer_Tube, OpKapton);
168  GeoPhysVol *Active_Buffer_Physical = new GeoPhysVol(Active_Buffer_Logical);
169 
170  for (uint fiber = 0; fiber < NFIBERS; ++fiber)
171  {
172 
173  // functions
174  int index = fiber * 0.5;
175  int pattern = fiber % 2;
176  int cycle = fiber / (2 * nCols) % 2;
177  int col = 2 * index / (nRows * nCols);
178  float cycleOffset = cycle * nCols * fiberPitchX;
179  float patternOffsetX = -pattern * fiberPitchX * 0.5;
180  float patternOffsetZ = pattern * fiberPitchZ * 0.5;
181 
182  float x = startX - tileSize * col - cycleOffset + patternOffsetX - index % 4 * fiberPitchX;
183  float z = startZ + fiberPitchZ * ((row + index % 4 + 2 * pattern) % 4) + patternOffsetZ;
184 
185  int channel = 4*row + col;
186 
187  std::string channelHashStr = zdcID->channel_id(m_side,m_module,ZdcIDType::ACTIVE,channel).getString();
189 
190 
191  /*******************************************
192  * Core
193  ********************************************/
194 
195  // Active region core get placed in aluminum
196 
197  // Active area
198  sprintf(volName, "ZDC::RPD_Core_Active %s", channelHashStr.c_str());
199  Housing_Physical->add(new GeoNameTag(volName));
200  Housing_Physical->add(new GeoIdentifierTag(channelHash));
201  Housing_Physical->add(new GeoAlignableTransform(GeoTrf::Translate3D(x * Gaudi::Units::mm, y * Gaudi::Units::mm, z * Gaudi::Units::mm)));
202  Housing_Physical->add(new GeoAlignableTransform(GeoTrf::RotateX3D(90 * Gaudi::Units::deg)));
203  Housing_Physical->add(Active_Core_Physical);
204 
205  // Readout Fiber
206  sprintf(volName, "ZDC::RPD_Core_Readout %s", channelHashStr.c_str());
207  Module_Physical->add(new GeoNameTag(volName));
208  Module_Physical->add(new GeoIdentifierTag(channelHash));
209  Module_Physical->add(new GeoAlignableTransform(GeoTrf::Translate3D(x * Gaudi::Units::mm, 0.0, z * Gaudi::Units::mm)));
210  Module_Physical->add(new GeoAlignableTransform(GeoTrf::RotateX3D(90 * Gaudi::Units::deg)));
211  Module_Physical->add(Readout_Core_Physical);
212 
213  /*******************************************
214  * Cladding
215  ********************************************/
216 
217  // Active area
218  sprintf(volName, "ZDC::RPD_Clad_Active %s", channelHashStr.c_str());
219  Housing_Physical->add(new GeoNameTag(volName));
220  Housing_Physical->add(new GeoIdentifierTag(channelHash));
221  Housing_Physical->add(new GeoAlignableTransform(GeoTrf::Translate3D(x * Gaudi::Units::mm, y * Gaudi::Units::mm, z * Gaudi::Units::mm)));
222  Housing_Physical->add(new GeoAlignableTransform(GeoTrf::RotateX3D(90 * Gaudi::Units::deg)));
223  Housing_Physical->add(Active_Clad_Physical);
224 
225  // Readout
226  sprintf(volName, "ZDC::RPD_Clad_Readout %s", channelHashStr.c_str());
227  Module_Physical->add(new GeoNameTag(volName));
228  Module_Physical->add(new GeoAlignableTransform(GeoTrf::Translate3D(x * Gaudi::Units::mm, 0.0, z * Gaudi::Units::mm)));
229  Module_Physical->add(new GeoIdentifierTag(channelHash));
230  Module_Physical->add(new GeoAlignableTransform(GeoTrf::RotateX3D(90 * Gaudi::Units::deg)));
231  Module_Physical->add(Readout_Clad_Physical);
232 
233  /*******************************************
234  * Buffer
235  ********************************************/
236 
237  // Active area
238  sprintf(volName, "ZDC::RPD_Buffer_Active %s", channelHashStr.c_str());
239  Housing_Physical->add(new GeoNameTag(volName));
240  Housing_Physical->add(new GeoIdentifierTag(channelHash));
241  Housing_Physical->add(new GeoAlignableTransform(GeoTrf::Translate3D(x * Gaudi::Units::mm, y * Gaudi::Units::mm, z * Gaudi::Units::mm)));
242  Housing_Physical->add(new GeoAlignableTransform(GeoTrf::RotateX3D(90 * Gaudi::Units::deg)));
243  Housing_Physical->add(Active_Buffer_Physical);
244 
245  // Readout Fiber
246  sprintf(volName, "ZDC::RPD_Buffer_Readout %s", channelHashStr.c_str());
247  Module_Physical->add(new GeoNameTag(volName));
248  Module_Physical->add(new GeoAlignableTransform(GeoTrf::Translate3D(x * Gaudi::Units::mm, 0.0, z * Gaudi::Units::mm)));
249  Module_Physical->add(new GeoAlignableTransform(GeoTrf::RotateX3D(90 * Gaudi::Units::deg)));
250  Module_Physical->add(new GeoIdentifierTag(channelHash));
251  Module_Physical->add(Readout_Buffer_Physical);
252 
253  } // end loop over fibers
254  }// end loop over rows
255 
256  Identifier id;
257 
258  // Place the fiber routing volume
260  sprintf(volName, "ZDC::RPD_Air_Cavity %s", id.getString().c_str());
261  Housing_Physical->add(new GeoNameTag(volName));
262  Housing_Physical->add(new GeoIdentifierTag( id.get_identifier32().get_compact()));
263  Housing_Physical->add(new GeoAlignableTransform(GeoTrf::TranslateY3D( 0.5 * (detectorHeight - readoutFiberLength) * Gaudi::Units::mm)));
264  Housing_Physical->add(Module_Physical);
265 
266  // Place the foot in the mother volume
268  sprintf(volName, "ZDC::RPD_Foot %s",id.getString().c_str());
269  mother->add(new GeoNameTag(volName));
270  mother->add(new GeoIdentifierTag(id.get_identifier32().get_compact()));
271  mother->add(new GeoAlignableTransform( footTrf ));
272  mother->add(Foot_Physical);
273 
274  // Place the module in the mother volume
276  sprintf(volName, "Zdc::RPD_Mod %s", id.getString().c_str());
277  mother->add(new GeoNameTag(volName));
278  mother->add(new GeoIdentifierTag(id.get_identifier32().get_compact()));
279  mother->add(new GeoAlignableTransform( moduleTrf));
280  mother->add(Housing_Physical);
281 
282 }
mergePhysValFiles.pattern
pattern
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:26
query_example.row
row
Definition: query_example.py:24
HOUSING
@ HOUSING
Definition: ZdcID.h:22
plotting.yearwise_efficiency.channel
channel
Definition: yearwise_efficiency.py:24
getMessageSvc.h
singleton-like access to IMessageSvc via open function and helper
ZDC_ModuleBase::m_module
int m_module
Definition: ZDC_ModuleBase.h:48
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
index
Definition: index.py:1
cycle
double cycle(double a, double b)
Definition: SiHitCollectionCnv_p2.cxx:38
Identifier::get_identifier32
Identifier32 get_identifier32() const
Get the 32-bit version Identifier, will be invalid if >32 bits needed.
deg
#define deg
Definition: SbPolyhedron.cxx:17
AIR
@ AIR
Definition: ZdcID.h:22
ZDC_ModuleBase::m_trf
GeoTrf::Transform3D m_trf
Definition: ZDC_ModuleBase.h:50
x
#define x
Identifier32::get_compact
value_type get_compact() const
Get the compact id.
Definition: Identifier32.h:44
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
ZDC_RPDModule.h
NFIBERS
#define NFIBERS
Definition: TileLaserDefaultCalibTool.h:40
ZdcID::channel_id
Identifier channel_id(int side, int module, int type, int channel) const
Definition: ZdcID.h:205
uint
unsigned int uint
Definition: LArOFPhaseFill.cxx:20
z
#define z
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
RPDUtils::nCols
unsigned constexpr int nCols
Definition: RPDUtils.h:25
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:239
StoredMaterialManager.h
query_example.col
col
Definition: query_example.py:7
ZDC_ModuleBase::m_side
int m_side
Definition: ZDC_ModuleBase.h:47
beamspotman.posY
posY
Definition: beamspotman.py:1624
python.SystemOfUnits.mm
int mm
Definition: SystemOfUnits.py:83
ZDC_RPDModule::create
virtual void create(GeoFullPhysVol *mother, StoredMaterialManager *materialManager, const ZdcID *zdcID) override
Definition: ZDC_RPDModule.cxx:28
ZdcID.h
Identifier::getString
std::string getString() const
Provide a string form of the identifier - hexadecimal.
Definition: Identifier.cxx:25
y
#define y
StoredMaterialManager::getMaterial
virtual const GeoMaterial * getMaterial(const std::string &name)=0
StoredMaterialManager
This class holds one or more material managers and makes them storeable, under StoreGate.
Definition: StoredMaterialManager.h:28
ACTIVE
@ ACTIVE
Definition: ZdcID.h:21
RPDUtils::nRows
unsigned constexpr int nRows
Definition: RPDUtils.h:24
INACTIVE
@ INACTIVE
Definition: ZdcID.h:21
ZdcID
Definition: ZdcID.h:25
Identifier
Definition: IdentifierFieldParser.cxx:14