Skip to content

Commit 03ea86a

Browse files
danielbattistinialibuildmconcas
authored
ALICE 3: Add staggered staves to OT (#13910)
* Improve modularity * Add Staggered layers * Configure middle and outer layers separately * [Fix] Correct double-width staves for middle layers * Add overlap between the modules * rename config variable * Please consider the following formatting changes * Update Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx * Update Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx * Update Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx * Update Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx --------- Co-authored-by: ALICE Action Bot <alibuild@cern.ch> Co-authored-by: Matteo Concas <mconcas@cern.ch>
1 parent e24ee88 commit 03ea86a

File tree

4 files changed

+154
-37
lines changed

4 files changed

+154
-37
lines changed

Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/TRKBaseParam.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ namespace trk
2323
enum eLayout {
2424
kCylinder = 0,
2525
kTurboStaves,
26+
kStaggered,
2627
};
2728

2829
struct TRKBaseParam : public o2::conf::ConfigurableParamHelper<TRKBaseParam> {
2930
std::string configFile = "";
3031
float serviceTubeX0 = 0.02f; // X0 Al2O3
31-
eLayout layout = kCylinder; // Type of segmentation of the layers into staves
32+
eLayout layoutML = kCylinder; // Type of segmentation for the middle layers
33+
eLayout layoutOL = kCylinder; // Type of segmentation for the outer layers
3234

3335
O2ParamDef(TRKBaseParam, "TRKBase");
3436
};

Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKLayer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class TRKLayer
3939
auto getNumber() const { return mLayerNumber; }
4040
auto getName() const { return mLayerName; }
4141

42+
TGeoVolume* createSensor(std::string type, double width = -1);
43+
TGeoVolume* createChip(std::string type, double width = -1);
44+
TGeoVolume* createStave(std::string type, double width = -1);
4245
void createLayer(TGeoVolume* motherVolume);
4346

4447
private:

Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,18 @@ void Detector::buildTRKNewVacuumVessel()
116116
mLayers.emplace_back(10, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(10)}, 80.f, 258.f, 100.e-3);
117117

118118
auto& trkPars = TRKBaseParam::Instance();
119-
mLayers[8].setLayout(trkPars.layout);
120-
mLayers[9].setLayout(trkPars.layout);
121-
mLayers[10].setLayout(trkPars.layout);
119+
120+
// Middle layers
121+
mLayers[3].setLayout(trkPars.layoutML);
122+
mLayers[4].setLayout(trkPars.layoutML);
123+
mLayers[5].setLayout(trkPars.layoutML);
124+
mLayers[6].setLayout(trkPars.layoutML);
125+
126+
// Outer tracker
127+
mLayers[7].setLayout(trkPars.layoutOL);
128+
mLayers[8].setLayout(trkPars.layoutOL);
129+
mLayers[9].setLayout(trkPars.layoutOL);
130+
mLayers[10].setLayout(trkPars.layoutOL);
122131
}
123132

124133
void Detector::configFromFile(std::string fileName)

Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx

Lines changed: 136 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,108 @@ TRKLayer::TRKLayer(int layerNumber, std::string layerName, float rInn, float zLe
4141
LOGP(info, "Creating layer: id: {} rInner: {} rOuter: {} zLength: {} x2X0: {}", mLayerNumber, mInnerRadius, mOuterRadius, mZ, mX2X0);
4242
}
4343

44+
TGeoVolume* TRKLayer::createSensor(std::string type, double width)
45+
{
46+
TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
47+
std::string sensName = Form("%s%d", GeometryTGeo::getTRKSensorPattern(), this->mLayerNumber);
48+
49+
TGeoShape* sensor;
50+
51+
if (type == "cylinder") {
52+
sensor = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2);
53+
} else if (type == "flat") {
54+
if (width < 0) {
55+
LOGP(fatal, "Attempting to create sensor with invalid width");
56+
}
57+
sensor = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
58+
} else {
59+
LOGP(fatal, "Sensor of type '{}' is not implemented", type);
60+
}
61+
62+
TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi);
63+
sensVol->SetLineColor(kYellow);
64+
65+
return sensVol;
66+
};
67+
68+
TGeoVolume* TRKLayer::createChip(std::string type, double width)
69+
{
70+
TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
71+
std::string chipName = o2::trk::GeometryTGeo::getTRKChipPattern() + std::to_string(mLayerNumber);
72+
73+
TGeoShape* chip;
74+
TGeoVolume* sensVol;
75+
76+
if (type == "cylinder") {
77+
chip = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2);
78+
sensVol = createSensor("cylinder");
79+
} else if (type == "flat") {
80+
if (width < 0) {
81+
LOGP(fatal, "Attempting to create chip with invalid width");
82+
}
83+
chip = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
84+
sensVol = createSensor("flat", width);
85+
} else {
86+
LOGP(fatal, "Sensor of type '{}' is not implemented", type);
87+
}
88+
89+
TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
90+
LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
91+
chipVol->AddNode(sensVol, 1, nullptr);
92+
chipVol->SetLineColor(kYellow);
93+
94+
return chipVol;
95+
}
96+
97+
TGeoVolume* TRKLayer::createStave(std::string type, double width)
98+
{
99+
TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
100+
std::string staveName = o2::trk::GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber);
101+
102+
TGeoShape* stave;
103+
TGeoVolume* staveVol;
104+
TGeoVolume* chipVol;
105+
106+
if (type == "cylinder") {
107+
stave = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2);
108+
chipVol = createChip("cylinder");
109+
staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
110+
LOGP(info, "Inserting {} in {} ", chipVol->GetName(), staveVol->GetName());
111+
staveVol->AddNode(chipVol, 1, nullptr);
112+
} else if (type == "flat") {
113+
if (width < 0) {
114+
LOGP(fatal, "Attempting to create stave with invalid width");
115+
}
116+
stave = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
117+
chipVol = createChip("flat", width);
118+
staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
119+
LOGP(info, "Inserting {} in {} ", chipVol->GetName(), staveVol->GetName());
120+
staveVol->AddNode(chipVol, 1, nullptr);
121+
} else if (type == "staggered") {
122+
double width = mModuleWidth * 2; // Each stave has two modules (based on the LOI design)
123+
stave = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
124+
TGeoVolume* chipVolLeft = createChip("flat", mModuleWidth);
125+
TGeoVolume* chipVolRight = createChip("flat", mModuleWidth);
126+
staveVol = new TGeoVolume(staveName.c_str(), stave, medAir);
127+
128+
TGeoCombiTrans* transLeft = new TGeoCombiTrans();
129+
transLeft->SetTranslation(-mModuleWidth / 2 + 0.05, 0, 0); // 1mm overlap between the modules
130+
LOGP(info, "Inserting {} in {} ", chipVolLeft->GetName(), staveVol->GetName());
131+
staveVol->AddNode(chipVolLeft, 0, transLeft);
132+
133+
TGeoCombiTrans* transRight = new TGeoCombiTrans();
134+
transRight->SetTranslation(mModuleWidth / 2 - 0.05, 0.2, 0);
135+
LOGP(info, "Inserting {} in {} ", chipVolRight->GetName(), staveVol->GetName());
136+
staveVol->AddNode(chipVolRight, 1, transRight);
137+
} else {
138+
LOGP(fatal, "Chip of type '{}' is not implemented", type);
139+
}
140+
141+
staveVol->SetLineColor(kYellow);
142+
143+
return staveVol;
144+
}
145+
44146
void TRKLayer::createLayer(TGeoVolume* motherVolume)
45147
{
46148
TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
@@ -56,28 +158,16 @@ void TRKLayer::createLayer(TGeoVolume* motherVolume)
56158
layerVol->SetLineColor(kYellow);
57159

58160
if (mLayout == eLayout::kCylinder) {
59-
TGeoTube* stave = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2);
60-
TGeoTube* chip = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2);
61-
TGeoTube* sensor = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2);
62-
63-
TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi);
64-
sensVol->SetLineColor(kYellow);
65-
TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
66-
chipVol->SetLineColor(kYellow);
67-
TGeoVolume* staveVol = new TGeoVolume(staveName.c_str(), stave, medSi);
68-
staveVol->SetLineColor(kYellow);
69-
70-
LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
71-
chipVol->AddNode(sensVol, 1, nullptr);
72-
73-
LOGP(info, "Inserting {} in {} ", chipVol->GetName(), staveVol->GetName());
74-
staveVol->AddNode(chipVol, 1, nullptr);
75-
161+
auto staveVol = createStave("cylinder");
76162
LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
77163
layerVol->AddNode(staveVol, 1, nullptr);
78164
} else if (mLayout == eLayout::kTurboStaves) {
79165
// Compute the number of staves
80-
double width = mModuleWidth * 2; // Each stave has two modules (based on the LOI design)
166+
double width = mModuleWidth; // Each stave has two modules (based on the LOI design)
167+
if (mInnerRadius > 25) {
168+
width *= 2; // Outer layers have two modules per stave
169+
}
170+
81171
int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / width);
82172
nStaves += nStaves % 2; // Require an even number of staves
83173

@@ -91,29 +181,42 @@ void TRKLayer::createLayer(TGeoVolume* motherVolume)
91181
LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10);
92182

93183
for (int iStave = 0; iStave < nStaves; iStave++) {
94-
TGeoBBox* sensor = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
95-
TGeoBBox* chip = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
96-
TGeoBBox* stave = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2);
97-
98-
TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi);
99-
sensVol->SetLineColor(kYellow);
100-
TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
101-
chipVol->SetLineColor(kYellow);
102-
TGeoVolume* staveVol = new TGeoVolume(staveName.c_str(), stave, medSi);
103-
staveVol->SetLineColor(kYellow);
184+
TGeoVolume* staveVol = createStave("flat", width);
104185

105186
// Put the staves in the correct position and orientation
106187
TGeoCombiTrans* trans = new TGeoCombiTrans();
107188
double theta = 360. * iStave / nStaves;
108-
TGeoRotation* rot = new TGeoRotation("rot", theta + 90 + 2, 0, 0);
189+
TGeoRotation* rot = new TGeoRotation("rot", theta + 90 + 3, 0, 0);
109190
trans->SetRotation(rot);
110191
trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0);
111192

112-
LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
113-
chipVol->AddNode(sensVol, 1, nullptr);
193+
LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
194+
layerVol->AddNode(staveVol, iStave, trans);
195+
}
196+
} else if (mLayout == kStaggered) {
197+
// Compute the number of staves
198+
double width = mModuleWidth * 2; // Each stave has two modules (based on the LOI design)
199+
int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / width);
200+
nStaves += nStaves % 2; // Require an even number of staves
114201

115-
LOGP(info, "Inserting {} in {} ", chipVol->GetName(), staveVol->GetName());
116-
staveVol->AddNode(chipVol, 1, nullptr);
202+
// Compute the size of the overlap region
203+
double theta = 2 * TMath::Pi() / nStaves;
204+
double theta1 = std::atan(width / 2 / mInnerRadius);
205+
double st = std::sin(theta);
206+
double ct = std::cos(theta);
207+
double theta2 = std::atan((mInnerRadius * st - width / 2 * ct) / (mInnerRadius * ct + width / 2 * st));
208+
double overlap = (theta1 - theta2) * mInnerRadius;
209+
LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10);
210+
211+
for (int iStave = 0; iStave < nStaves; iStave++) {
212+
TGeoVolume* staveVol = createStave("staggered");
213+
214+
// Put the staves in the correct position and orientation
215+
TGeoCombiTrans* trans = new TGeoCombiTrans();
216+
double theta = 360. * iStave / nStaves;
217+
TGeoRotation* rot = new TGeoRotation("rot", theta + 90, 0, 0);
218+
trans->SetRotation(rot);
219+
trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0);
117220

118221
LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName());
119222
layerVol->AddNode(staveVol, iStave, trans);

0 commit comments

Comments
 (0)