diff --git a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/TRKBaseParam.h b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/TRKBaseParam.h index 6c655571b3e4e..9ea4bd1072d91 100644 --- a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/TRKBaseParam.h +++ b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/TRKBaseParam.h @@ -23,12 +23,14 @@ namespace trk enum eLayout { kCylinder = 0, kTurboStaves, + kStaggered, }; struct TRKBaseParam : public o2::conf::ConfigurableParamHelper { std::string configFile = ""; float serviceTubeX0 = 0.02f; // X0 Al2O3 - eLayout layout = kCylinder; // Type of segmentation of the layers into staves + eLayout layoutML = kCylinder; // Type of segmentation for the middle layers + eLayout layoutOL = kCylinder; // Type of segmentation for the outer layers O2ParamDef(TRKBaseParam, "TRKBase"); }; diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKLayer.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKLayer.h index 2ddf38352ae8c..ef355ec36ce2f 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKLayer.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/TRKLayer.h @@ -39,6 +39,9 @@ class TRKLayer auto getNumber() const { return mLayerNumber; } auto getName() const { return mLayerName; } + TGeoVolume* createSensor(std::string type, double width = -1); + TGeoVolume* createChip(std::string type, double width = -1); + TGeoVolume* createStave(std::string type, double width = -1); void createLayer(TGeoVolume* motherVolume); private: diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index 9e69a3bd8a88f..b9015ce578caf 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -116,9 +116,18 @@ void Detector::buildTRKNewVacuumVessel() mLayers.emplace_back(10, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(10)}, 80.f, 258.f, 100.e-3); auto& trkPars = TRKBaseParam::Instance(); - mLayers[8].setLayout(trkPars.layout); - mLayers[9].setLayout(trkPars.layout); - mLayers[10].setLayout(trkPars.layout); + + // Middle layers + mLayers[3].setLayout(trkPars.layoutML); + mLayers[4].setLayout(trkPars.layoutML); + mLayers[5].setLayout(trkPars.layoutML); + mLayers[6].setLayout(trkPars.layoutML); + + // Outer tracker + mLayers[7].setLayout(trkPars.layoutOL); + mLayers[8].setLayout(trkPars.layoutOL); + mLayers[9].setLayout(trkPars.layoutOL); + mLayers[10].setLayout(trkPars.layoutOL); } void Detector::configFromFile(std::string fileName) diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx index 0d7930c77bb49..e6b00f6e96425 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/TRKLayer.cxx @@ -41,6 +41,108 @@ TRKLayer::TRKLayer(int layerNumber, std::string layerName, float rInn, float zLe LOGP(info, "Creating layer: id: {} rInner: {} rOuter: {} zLength: {} x2X0: {}", mLayerNumber, mInnerRadius, mOuterRadius, mZ, mX2X0); } +TGeoVolume* TRKLayer::createSensor(std::string type, double width) +{ + TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$"); + std::string sensName = Form("%s%d", GeometryTGeo::getTRKSensorPattern(), this->mLayerNumber); + + TGeoShape* sensor; + + if (type == "cylinder") { + sensor = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2); + } else if (type == "flat") { + if (width < 0) { + LOGP(fatal, "Attempting to create sensor with invalid width"); + } + sensor = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2); + } else { + LOGP(fatal, "Sensor of type '{}' is not implemented", type); + } + + TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi); + sensVol->SetLineColor(kYellow); + + return sensVol; +}; + +TGeoVolume* TRKLayer::createChip(std::string type, double width) +{ + TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$"); + std::string chipName = o2::trk::GeometryTGeo::getTRKChipPattern() + std::to_string(mLayerNumber); + + TGeoShape* chip; + TGeoVolume* sensVol; + + if (type == "cylinder") { + chip = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2); + sensVol = createSensor("cylinder"); + } else if (type == "flat") { + if (width < 0) { + LOGP(fatal, "Attempting to create chip with invalid width"); + } + chip = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2); + sensVol = createSensor("flat", width); + } else { + LOGP(fatal, "Sensor of type '{}' is not implemented", type); + } + + TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi); + LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName()); + chipVol->AddNode(sensVol, 1, nullptr); + chipVol->SetLineColor(kYellow); + + return chipVol; +} + +TGeoVolume* TRKLayer::createStave(std::string type, double width) +{ + TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$"); + std::string staveName = o2::trk::GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber); + + TGeoShape* stave; + TGeoVolume* staveVol; + TGeoVolume* chipVol; + + if (type == "cylinder") { + stave = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2); + chipVol = createChip("cylinder"); + staveVol = new TGeoVolume(staveName.c_str(), stave, medAir); + LOGP(info, "Inserting {} in {} ", chipVol->GetName(), staveVol->GetName()); + staveVol->AddNode(chipVol, 1, nullptr); + } else if (type == "flat") { + if (width < 0) { + LOGP(fatal, "Attempting to create stave with invalid width"); + } + stave = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2); + chipVol = createChip("flat", width); + staveVol = new TGeoVolume(staveName.c_str(), stave, medAir); + LOGP(info, "Inserting {} in {} ", chipVol->GetName(), staveVol->GetName()); + staveVol->AddNode(chipVol, 1, nullptr); + } else if (type == "staggered") { + double width = mModuleWidth * 2; // Each stave has two modules (based on the LOI design) + stave = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2); + TGeoVolume* chipVolLeft = createChip("flat", mModuleWidth); + TGeoVolume* chipVolRight = createChip("flat", mModuleWidth); + staveVol = new TGeoVolume(staveName.c_str(), stave, medAir); + + TGeoCombiTrans* transLeft = new TGeoCombiTrans(); + transLeft->SetTranslation(-mModuleWidth / 2 + 0.05, 0, 0); // 1mm overlap between the modules + LOGP(info, "Inserting {} in {} ", chipVolLeft->GetName(), staveVol->GetName()); + staveVol->AddNode(chipVolLeft, 0, transLeft); + + TGeoCombiTrans* transRight = new TGeoCombiTrans(); + transRight->SetTranslation(mModuleWidth / 2 - 0.05, 0.2, 0); + LOGP(info, "Inserting {} in {} ", chipVolRight->GetName(), staveVol->GetName()); + staveVol->AddNode(chipVolRight, 1, transRight); + } else { + LOGP(fatal, "Chip of type '{}' is not implemented", type); + } + + staveVol->SetLineColor(kYellow); + + return staveVol; +} + void TRKLayer::createLayer(TGeoVolume* motherVolume) { TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$"); @@ -56,28 +158,16 @@ void TRKLayer::createLayer(TGeoVolume* motherVolume) layerVol->SetLineColor(kYellow); if (mLayout == eLayout::kCylinder) { - TGeoTube* stave = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2); - TGeoTube* chip = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2); - TGeoTube* sensor = new TGeoTube(mInnerRadius, mInnerRadius + mChipThickness, mZ / 2); - - TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi); - sensVol->SetLineColor(kYellow); - TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi); - chipVol->SetLineColor(kYellow); - TGeoVolume* staveVol = new TGeoVolume(staveName.c_str(), stave, medSi); - staveVol->SetLineColor(kYellow); - - LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName()); - chipVol->AddNode(sensVol, 1, nullptr); - - LOGP(info, "Inserting {} in {} ", chipVol->GetName(), staveVol->GetName()); - staveVol->AddNode(chipVol, 1, nullptr); - + auto staveVol = createStave("cylinder"); LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName()); layerVol->AddNode(staveVol, 1, nullptr); } else if (mLayout == eLayout::kTurboStaves) { // Compute the number of staves - double width = mModuleWidth * 2; // Each stave has two modules (based on the LOI design) + double width = mModuleWidth; // Each stave has two modules (based on the LOI design) + if (mInnerRadius > 25) { + width *= 2; // Outer layers have two modules per stave + } + int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / width); nStaves += nStaves % 2; // Require an even number of staves @@ -91,29 +181,42 @@ void TRKLayer::createLayer(TGeoVolume* motherVolume) LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10); for (int iStave = 0; iStave < nStaves; iStave++) { - TGeoBBox* sensor = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2); - TGeoBBox* chip = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2); - TGeoBBox* stave = new TGeoBBox(width / 2, mChipThickness / 2, mZ / 2); - - TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi); - sensVol->SetLineColor(kYellow); - TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi); - chipVol->SetLineColor(kYellow); - TGeoVolume* staveVol = new TGeoVolume(staveName.c_str(), stave, medSi); - staveVol->SetLineColor(kYellow); + TGeoVolume* staveVol = createStave("flat", width); // Put the staves in the correct position and orientation TGeoCombiTrans* trans = new TGeoCombiTrans(); double theta = 360. * iStave / nStaves; - TGeoRotation* rot = new TGeoRotation("rot", theta + 90 + 2, 0, 0); + TGeoRotation* rot = new TGeoRotation("rot", theta + 90 + 3, 0, 0); trans->SetRotation(rot); trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0); - LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName()); - chipVol->AddNode(sensVol, 1, nullptr); + LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName()); + layerVol->AddNode(staveVol, iStave, trans); + } + } else if (mLayout == kStaggered) { + // Compute the number of staves + double width = mModuleWidth * 2; // Each stave has two modules (based on the LOI design) + int nStaves = (int)std::ceil(mInnerRadius * 2 * TMath::Pi() / width); + nStaves += nStaves % 2; // Require an even number of staves - LOGP(info, "Inserting {} in {} ", chipVol->GetName(), staveVol->GetName()); - staveVol->AddNode(chipVol, 1, nullptr); + // Compute the size of the overlap region + double theta = 2 * TMath::Pi() / nStaves; + double theta1 = std::atan(width / 2 / mInnerRadius); + double st = std::sin(theta); + double ct = std::cos(theta); + double theta2 = std::atan((mInnerRadius * st - width / 2 * ct) / (mInnerRadius * ct + width / 2 * st)); + double overlap = (theta1 - theta2) * mInnerRadius; + LOGP(info, "Creating a layer with {} staves and {} mm overlap", nStaves, overlap * 10); + + for (int iStave = 0; iStave < nStaves; iStave++) { + TGeoVolume* staveVol = createStave("staggered"); + + // Put the staves in the correct position and orientation + TGeoCombiTrans* trans = new TGeoCombiTrans(); + double theta = 360. * iStave / nStaves; + TGeoRotation* rot = new TGeoRotation("rot", theta + 90, 0, 0); + trans->SetRotation(rot); + trans->SetTranslation(mInnerRadius * std::cos(2. * TMath::Pi() * iStave / nStaves), mInnerRadius * std::sin(2 * TMath::Pi() * iStave / nStaves), 0); LOGP(info, "Inserting {} in {} ", staveVol->GetName(), layerVol->GetName()); layerVol->AddNode(staveVol, iStave, trans);