diff --git a/Detectors/Upgrades/ALICE3/IOTOF/README.md b/Detectors/Upgrades/ALICE3/IOTOF/README.md index e52b5e2379e9c..b248d0ceeac76 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/README.md +++ b/Detectors/Upgrades/ALICE3/IOTOF/README.md @@ -18,10 +18,10 @@ Configurables for various sub-detectors are presented in the following Table: | ----------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------- | | `IOTOFBase.enableInnerTOF` | `true` (default), `false` | Enable inner TOF barrel layer | | `IOTOFBase.enableOuterTOF` | `true` (default), `false` | Enable outer TOF barrel layer | -| `IOTOFBase.enableForwardTOF` | `true` (default), `false` | Enable forward TOF endcap | -| `IOTOFBase.enableBackwardTOF` | `true` (default), `false` | Enable backward TOF endcap | -| `IOTOFBase.segmentedInnerTOF` | `false` (default), `true` | Use segmented geometry for inner TOF | -| `IOTOFBase.segmentedOuterTOF` | `false` (default), `true` | Use segmented geometry for outer TOF | +| `IOTOFBase.enableForwardTOF` | `false` (default), `true` | Enable forward TOF endcap | +| `IOTOFBase.enableBackwardTOF` | `false` (default), `true` | Enable backward TOF endcap | +| `IOTOFBase.segmentedInnerTOF` | `true` (default), `false` | Use segmented geometry for inner TOF | +| `IOTOFBase.segmentedOuterTOF` | `true` (default), `false` | Use segmented geometry for outer TOF | | `IOTOFBase.detectorPattern` | ` ` (default), `v3b`, `v3b1a`, `v3b1b`, `v3b2a`, `v3b2b`, `v3b3` | Optional layout pattern | | `IOTOFBase.x2x0` | `0.02` (default) | Chip thickness in fractions of the rad. lenght | | `IOTOFBase.sensorThickness` | `0.0050` (default) | Sensor thickness in cm, can be at maximum equivalent to the chip thickness | diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h index 3364fd59d2165..f3fd9109b839b 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h @@ -47,11 +47,11 @@ struct ChipSpecificsParam : public o2::conf::ConfigurableParamPromoter { bool enableInnerTOF = true; // Enable Inner TOF layer bool enableOuterTOF = true; // Enable Outer TOF layer - bool enableForwardTOF = true; // Enable Forward TOF layer - bool enableBackwardTOF = true; // Enable Backward TOF layer + bool enableForwardTOF = false; // Enable Forward TOF layer + bool enableBackwardTOF = false; // Enable Backward TOF layer std::string detectorPattern = ""; // Layouts of the detector - bool segmentedInnerTOF = false; // If the inner TOF layer is segmented - bool segmentedOuterTOF = false; // If the outer TOF layer is segmented + bool segmentedInnerTOF = true; // If the inner TOF layer is segmented + bool segmentedOuterTOF = true; // If the outer TOF layer is segmented float x2x0 = 0.02f; // thickness expressed in radiation length, for all layers for the moment float sensorThickness = 0.0050f; // thickness of the sensor in cm, for all layers for the moment, the default is set to 50 microns diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/TRK/base/include/TRKBase/Specs.h b/Detectors/Upgrades/ALICE3/TRKFT3/TRK/base/include/TRKBase/Specs.h index 1459272a8fec7..0042654f92904 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/TRK/base/include/TRKBase/Specs.h +++ b/Detectors/Upgrades/ALICE3/TRKFT3/TRK/base/include/TRKBase/Specs.h @@ -108,6 +108,16 @@ constexpr double width{constants::moduleMLOT::width * 1}; // width of the stave constexpr double length{124 * cm}; // length of the stave, hardcoded to fit the implemented geometry constexpr int nRows{static_cast(width / constants::moduleMLOT::chip::pitchX)}; // number of rows in the stave constexpr int nCols{static_cast(length / constants::moduleMLOT::chip::pitchZ)}; // number of columns in the stave + +namespace eosCard // end-of-stave readout card, one per ML stave, A-side (+z) only, +{ // placed in front of the TRK_MIDBARCONN_DISK (fibre, power, ...) +constexpr double length{90 * mm}; // z-extent (fits the gap to the conn disk) +constexpr double width{50 * mm}; // phi-extent +constexpr double thickness{1.5 * mm}; // r-extent, FR4 + copper planes +constexpr int nCopperLayers{4}; // copper planes, spread over the thickness +constexpr double copperThickness{122 * mu}; // per copper plane; default of TRKBase.mlEosCardCuThickness +constexpr double zGap{0.1 * mm}; // z-clearance from the last module / stave end +} // namespace eosCard } // namespace ML namespace OT diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/TRK/base/include/TRKBase/TRKBaseParam.h b/Detectors/Upgrades/ALICE3/TRKFT3/TRK/base/include/TRKBase/TRKBaseParam.h index 22e2b7d683939..76a6be0d4442a 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/TRK/base/include/TRKBase/TRKBaseParam.h +++ b/Detectors/Upgrades/ALICE3/TRKFT3/TRK/base/include/TRKBase/TRKBaseParam.h @@ -45,6 +45,7 @@ struct TRKBaseParam : public o2::conf::ConfigurableParamHelper { float serviceTubeX0 = 0.02f; // X0 Al2O3 float otBarrelWallThickness = 0.2f; // cm, carbon fibre separation walls of the OT quarter barrels, 0 disables them float otEosCardCuThickness = constants::OT::eosCard::copperThickness; // cm, copper per plane in the OT end-of-stave card; drives the card x/X0 + float mlEosCardCuThickness = constants::ML::eosCard::copperThickness; // cm, copper per plane in the ML end-of-stave card; drives the card x/X0 bool irisOpen = false; bool includeLowServices = false; @@ -76,4 +77,4 @@ struct TRKBaseParam : public o2::conf::ConfigurableParamHelper { } // end namespace trk } // end namespace o2 -#endif \ No newline at end of file +#endif diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/include/TRKSimulation/TRKLayer.h b/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/include/TRKSimulation/TRKLayer.h index 2839e2db9307d..a533bd1066b41 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/include/TRKSimulation/TRKLayer.h +++ b/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/include/TRKSimulation/TRKLayer.h @@ -118,6 +118,8 @@ class TRKMLLayer : public TRKSegmentedLayer void createLayer(TGeoVolume* motherVolume) override; private: + TGeoVolume* createEndOfStaveCard(); // A-side (+z) end-of-stave card, in front of the conn disk + float mStaggerOffset; static constexpr double sStaveWidth = constants::ML::width; diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/src/TRKLayer.cxx b/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/src/TRKLayer.cxx index 15b04ffe54098..eb33616f8e0db 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/src/TRKLayer.cxx +++ b/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/src/TRKLayer.cxx @@ -247,10 +247,9 @@ TRKMLLayer::TRKMLLayer(int layerNumber, std::string layerName, float rInn, float TGeoVolume* TRKMLLayer::createStave() { - TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$"); + // Assembly (not a solid box) so the end-of-stave card can extend past the module envelope. std::string staveName = GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber); - TGeoShape* stave = new TGeoBBox(sStaveWidth / 2, mChipThickness / 2, mLength / 2); - TGeoVolume* staveVol = new TGeoVolume(staveName.c_str(), stave, medAir); + TGeoVolume* staveVol = new TGeoVolumeAssembly(staveName.c_str()); staveVol->SetLineColor(kYellow); for (int iModule = 0; iModule < mNumberOfModules; iModule++) { @@ -262,9 +261,48 @@ TGeoVolume* TRKMLLayer::createStave() staveVol->AddNode(moduleVol, iModule, trans); } + // End-of-stave card on the A-side (+z) only, just past the stave end and in front of the + // TRK_MIDBARCONN_DISK. Local frame: x = phi (width), y = radial (thickness), z = length. + TGeoCombiTrans* tCard = new TGeoCombiTrans(); + tCard->SetTranslation(0, 0, mLength / 2 + constants::ML::eosCard::zGap + constants::ML::eosCard::length / 2); + staveVol->AddNode(createEndOfStaveCard(), 0, tCard); + return staveVol; } +TGeoVolume* TRKMLLayer::createEndOfStaveCard() +{ + // FR4 board carrying evenly spaced copper planes; same construction as the OT card, with its + // own constants::ML::eosCard dimensions and a configurable copper thickness (TRKBase.mlEosCardCuThickness), + // which displaces FR4 inside the fixed envelope and sets the card x/X0. + TGeoMedium* medFR4 = gGeoManager->GetMedium("TRK_FR4$"); + TGeoMedium* medCu = gGeoManager->GetMedium("TRK_COPPER$"); + const std::string name = GeometryTGeo::getTRKStavePattern() + std::to_string(mLayerNumber) + "_EOSCard"; + + TGeoShape* board = new TGeoBBox(constants::ML::eosCard::width / 2, constants::ML::eosCard::thickness / 2, constants::ML::eosCard::length / 2); + TGeoVolume* cardVol = new TGeoVolume(name.c_str(), board, medFR4); + cardVol->SetLineColor(kGreen + 3); + + const double cuThickness = TRKBaseParam::Instance().mlEosCardCuThickness; + const int nPlanes = constants::ML::eosCard::nCopperLayers; + if (cuThickness * nPlanes >= constants::ML::eosCard::thickness) { + LOGP(fatal, "TRKBase.mlEosCardCuThickness = {} cm x {} planes does not fit in the {} cm ML end-of-stave card", + cuThickness, nPlanes, constants::ML::eosCard::thickness); + } + TGeoShape* plane = new TGeoBBox(constants::ML::eosCard::width / 2, cuThickness / 2, constants::ML::eosCard::length / 2); + TGeoVolume* planeVol = new TGeoVolume((name + "_Cu").c_str(), plane, medCu); + planeVol->SetLineColor(kOrange + 7); + + // Evenly spaced, the outermost two flush with the board surfaces. + const double span = constants::ML::eosCard::thickness - cuThickness; + for (int iPlane = 0; iPlane < nPlanes; iPlane++) { + const double y = (nPlanes > 1) ? -span / 2 + iPlane * span / (nPlanes - 1) : 0.; + cardVol->AddNode(planeVol, iPlane, new TGeoTranslation(0, y, 0)); + } + + return cardVol; +} + void TRKMLLayer::createLayer(TGeoVolume* motherVolume) { // Retrieve exact bounding boundaries and create the logical container volume @@ -272,7 +310,9 @@ void TRKMLLayer::createLayer(TGeoVolume* motherVolume) TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$"); // TGeoTube* layer = new TGeoTube(mInnerRadius - 0.333 * sLogicalVolumeThickness, mInnerRadius + 0.667 * sLogicalVolumeThickness, mLength / 2); - TGeoTube* layer = new TGeoTube(rMin, rMax, mLength / 2); + // Extend the z half-length so the A-side end-of-stave card (past mLength/2) stays inside the layer. + const double halfLengthZ = mLength / 2 + constants::ML::eosCard::zGap + constants::ML::eosCard::length; + TGeoTube* layer = new TGeoTube(rMin, rMax, halfLengthZ); TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir); layerVol->SetLineColor(kYellow); diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/src/TRKServices.cxx b/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/src/TRKServices.cxx index a5f897ec9ef4f..ec028c16086e7 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/src/TRKServices.cxx +++ b/Detectors/Upgrades/ALICE3/TRKFT3/TRK/simulation/src/TRKServices.cxx @@ -630,7 +630,7 @@ void TRKServices::createMLServicesPeacock(TGeoVolume* motherVolume) // Get geometry information from TRK which is already present float rMinMiddleServices = 38.0f; // cm, start radius of the ML services = maximum radius allowed for sensors (35 cm), plus some margin for disk paving with modules - const float zMiddleServicesBarrel = 64.5f; // cm, z position of the first barrel ML service disk + const float zMiddleServicesBarrel = 74.0f; // cm, z position of the first barrel ML service disk const float zMiddleServicesBarrelFwdConnection = 143.f; // cm, z position of barrel to forward connection services const float zLengthCylinderMiddleServicesBarrel = zMiddleServicesBarrelFwdConnection - zMiddleServicesBarrel;