Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Detectors/Upgrades/ALICE3/TRKFT3/TRK/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ The first 5 valid lines are parsed as `TRKMLLayer` objects. These layers **requi
**Outer Layers (OT) - Indices 5 and above**
From the 6th valid line onwards, lines are parsed as OT layer objects (`TRKOTLayer` for `kSegmented`, `TRKOTLayerRealistic` for `kSimplifiedRealistic`). These layers do **not** have a staggering offset. The optional mode parameter shifts to the 6th column.
* **Format:** `rInn` \t `thick` \t `tiltAngle` \t `nStaves` \t `nMods` \t `[optional_mode]`
* *(Note: for `kSimplifiedRealistic`, `nStaves` is recomputed internally from the average radius and stave width to guarantee the neighbour overlap; the value in the file is ignored for the OT.)*
* *(Note: for `kSimplifiedRealistic`, `nStaves` is the number of staves per ring and must be even; if it is 0 the count is derived from the radius as the smallest one giving the required neighbour overlap.)*

**Example for `kSegmented`:**

Expand Down Expand Up @@ -111,7 +111,7 @@ The geometry specification is based on [ALICE3 OT WP1 Material (26.06.2025)](htt

**End-of-stave card** — one readout PCB per stave (`constants::OT::eosCard`), mounted past the last module at the outer z end, coplanar with the two rows: a 120 × 80 mm, 1.5 mm board carrying four copper planes spread symmetrically through the thickness, the remainder FR4. The copper is what sets the card material budget: at the default 122 µm per plane the card is **4.0 % x/X₀** for a track crossing it perpendicularly (copper 3.40 %, FR4 0.60 %). It is tunable through `TRKBase.otEosCardCuThickness`, which changes only the copper/FR4 split inside the fixed 1.5 mm envelope, so the card dimensions and the layer envelopes stay put and only the radiation length moves. The cards reach |z| ≈ 141 cm, just short of the OT barrel service disk, which places them at |η| ≈ 1.84–1.88 on the innermost OT layer and |η| ≈ 1.27–1.32 on the outermost — inside the tracking acceptance, so they matter for forward-disk performance.

**Barrel** — each layer is built in **four parts**: two z-half-barrels (±η), each split azimuthally into two 180° halves. Both η half-barrels are cut on the **same vertical plane** (x = 0), so the region where the vertical beam-pipe supports run is free of staves over the whole barrel (the supports themselves are not in the geometry). Neighbouring staves overlap (≥ 1 mm active double-coverage); at the cut plane the two azimuthal halves instead leave a gap wide enough for the separation wall plus `barrelWallClearance` on each side. The stave count is the smallest even number that still meets the required overlap at the layer radius, so the OT radii (440, 615, 793 mm) are chosen at the top of a stave-count band, giving 30/42/54 staves per ring with 1.5-1.9 mm of overlap. The cooling pipe faces the larger radius on the inner two OT layers and the smaller radius on the flipped outer layer.
**Barrel** — each layer is built in **four parts**: two z-half-barrels (±η), each split azimuthally into two 180° halves. Both η half-barrels are cut on the **same vertical plane** (x = 0), so the region where the vertical beam-pipe supports run is free of staves over the whole barrel (the supports themselves are not in the geometry). Neighbouring staves overlap (≥ 1 mm active double-coverage); at the cut plane the two azimuthal halves instead leave a gap wide enough for the separation wall plus `barrelWallClearance` on each side. The default paving uses OT radii 442, 620 and 820 mm with 30, 42 and 56 staves per ring (15/21/28 per quarter barrel); L9 and L10 follow the mechanical CAD, L8 is placed as close in as the 1 mm active-overlap requirement allows for 30 staves. This gives 8.4-9.0 mm of border-to-border neighbour overlap in the stave plane. Each module's FPC extends 2.1 mm beyond the chips for wire bonding (`constants::OT::fpc::wireBondMargin`). The cooling pipe faces the larger radius on the inner two OT layers and the smaller radius on the flipped outer layer.

**Separation walls** — the quarter barrels are closed on every side but the one carrying the end-of-stave cards (`TRKServices::createOTBarrelWalls`, `kPeacockv1` + `kSimplifiedRealistic`): radially by the ML/OT and outer carbon shells, azimuthally by a rectangular carbon fibre wall in the cut plane, and at mid-rapidity by a half disk at z = 0, one per quarter barrel.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,13 @@ constexpr int nModulesPerRow{11}; // mod
constexpr double interModuleGap{0.2 * mm}; // z-gap between module FPCs

// Component dimensions of the simplified-realistic OT stave
constexpr double interChipGap{0.2 * mm}; // gap between chips within a module
namespace fpc
{
constexpr double length{116.8 * mm}; // z-extent
constexpr double width{52.2 * mm}; // phi-extent
constexpr double thickness{0.200 * mm}; // r-extent, Kapton+Cu stack
constexpr double wireBondMargin{2.1 * mm}; // FPC beyond the chips on each long side, for wire bonding
constexpr double length{116.8 * mm}; // z-extent
constexpr double width{2 * moduleMLOT::chip::width + interChipGap + 2 * wireBondMargin}; // phi-extent
constexpr double thickness{0.200 * mm}; // r-extent, Kapton+Cu stack
} // namespace fpc
namespace coldPlate
{
Expand Down Expand Up @@ -195,7 +197,6 @@ constexpr double zClearance{1.0 * mm}; // z-clearance to the nearest wall and t
} // namespace supportRing

constexpr double sensorThickness{moduleMLOT::silicon::thickness}; // pure-silicon chip (no metal stack)
constexpr double interChipGap{0.2 * mm}; // gap between chips within a module
constexpr double rowActiveOverlap{1.0 * mm}; // active overlap between the two rows of a stave
constexpr double rowRadialStagger{2.0 * mm}; // radial step between any two overlapping rows
constexpr double halfBarrelChipGap{1.0 * mm}; // gap between the two azimuthal half-barrels
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class TRKServices : public FairModule
// Carbon fibre shells bounding the OT barrel in r; the separation walls span between them.
static constexpr float sMLOTShellRMax = 39.5f; // cm, outer radius of the ML/OT separation shell
static constexpr float sMLOTShellThickness = 0.2f; // cm
static constexpr float sOTShellRMin = 82.0f; // cm, inner radius of the OT outer shell
static constexpr float sOTShellRMin = 83.0f; // cm, inner radius of the OT outer shell
static constexpr float sOTShellThickness = 0.4f; // cm, load bearing, hence thicker

// Vacuum
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,12 @@ void Detector::configMLOT()
const std::vector<int> nMods{11, 11, 11, 11, 11, 22, 22, 22};
const std::vector<float> stagOffsets{0.f, 0.f, 0.f, 1.17f, 0.89f};

// OT radii chosen at the top of a stave-count band, where the paving closes with
// ~1.5-1.9 mm of neighbour overlap; the outermost also clears TRKServices::sOTShellRMin.
// OT: L9/L10 radii from the mechanical CAD, L8 at 442 mm; staves per ring (15/21/28 per quarter barrel)
std::vector<float> rInnReal = rInn;
rInnReal[constants::ML::nLayers + 0] = 44.0f;
rInnReal[constants::ML::nLayers + 1] = 61.5f;
rInnReal[constants::ML::nLayers + 2] = 79.3f;
// OT counts are informational: TRKOTLayerRealistic derives its own from the radius.
const std::vector<int> nStaves{10, 14, 18, 26, 38, 30, 42, 54};
rInnReal[constants::ML::nLayers + 0] = 44.2f;
rInnReal[constants::ML::nLayers + 1] = 62.0f;
rInnReal[constants::ML::nLayers + 2] = 82.0f;
const std::vector<int> nStaves{10, 14, 18, 26, 38, 30, 42, 56};

LOGP(warning, "Loading simplified-realistic configuration for ALICE3 TRK");
for (int i{0}; i < constants::ML::nLayers + constants::OT::nLayers; ++i) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ TGeoVolume* TRKOTLayerRealistic::createStave()
// Two rows overlapping in phi and staggered in r. They straddle the stave origin, so the
// stave is tangent to the barrel circle at its centre and every row-to-row radial step,
// within a stave and between neighbours, is rowRadialStagger.
const double edgeDead = constants::moduleMLOT::gaps::outerEdgeLongSide + constants::moduleMLOT::chip::passiveEdgeReadOut;
const double edgeDead = constants::OT::fpc::wireBondMargin + constants::moduleMLOT::chip::passiveEdgeReadOut;
const double inStaveOverlap = 2 * edgeDead + constants::OT::rowActiveOverlap;
const double rowOffset = constants::OT::fpc::width - inStaveOverlap;

Expand All @@ -765,7 +765,7 @@ TGeoVolume* TRKOTLayerRealistic::createStave()

void TRKOTLayerRealistic::createLayer(TGeoVolume* motherVolume)
{
const double edgeDead = constants::moduleMLOT::gaps::outerEdgeLongSide + constants::moduleMLOT::chip::passiveEdgeReadOut;
const double edgeDead = constants::OT::fpc::wireBondMargin + constants::moduleMLOT::chip::passiveEdgeReadOut;
const double inStaveOverlap = 2 * edgeDead + constants::OT::rowActiveOverlap;
const double staveWidth = 2 * constants::OT::fpc::width - inStaveOverlap;

Expand Down Expand Up @@ -812,19 +812,29 @@ void TRKOTLayerRealistic::createLayer(TGeoVolume* motherVolume)
const double accGap = std::max(constants::OT::halfBarrelChipGap + 2 * constants::moduleMLOT::chip::passiveEdgeReadOut,
2 * (wallThickness / 2 + constants::OT::barrelWallClearance + edgeDead));

// Smallest even count still leaving rowActiveOverlap between neighbours: the two boundary
// staves take activeStaveWidth + accGap each, so only nStaves - 2 junctions share the rest.
// Staves per ring: configured, or else the smallest even count leaving rowActiveOverlap between
// neighbours (the two boundary staves take activeStaveWidth + accGap, nStaves - 2 junctions share the rest).
const double activeStaveWidth = staveWidth - 2 * edgeDead;
int nStavesHalfBarrel = (int)std::ceil(2. + (avgRadius * 2 * TMath::Pi() - 2 * (activeStaveWidth + accGap)) /
(activeStaveWidth - constants::OT::rowActiveOverlap));
nStavesHalfBarrel += nStavesHalfBarrel % 2;
int nStavesHalfBarrel = mNumberOfStaves;
if (nStavesHalfBarrel <= 0) {
nStavesHalfBarrel = (int)std::ceil(2. + (avgRadius * 2 * TMath::Pi() - 2 * (activeStaveWidth + accGap)) /
(activeStaveWidth - constants::OT::rowActiveOverlap));
nStavesHalfBarrel += nStavesHalfBarrel % 2;
}
if (nStavesHalfBarrel % 2) {
LOGP(fatal, "OT layer {}: {} staves per ring, must be even (two azimuthal halves)", mLayerNumber, nStavesHalfBarrel);
}

const int nHalf = nStavesHalfBarrel / 2;
const double thetaGap = (activeStaveWidth + accGap) / avgRadius;
const double thetaInt = (2. * TMath::Pi() - 2. * thetaGap) / (nStavesHalfBarrel - 2);
const double overlap = activeStaveWidth - avgRadius * thetaInt;
LOGP(info, "Creating realistic OT layer {}: {} staves/half-barrel, internal overlap {} mm, boundary gap {} mm, flipped={}",
mLayerNumber, nStavesHalfBarrel, overlap * 10, accGap * 10, mIsFlipped);
if (overlap < constants::OT::rowActiveOverlap) {
LOGP(warning, "OT layer {}: active neighbour overlap {} mm is below the required {} mm",
mLayerNumber, overlap * 10, constants::OT::rowActiveOverlap * 10);
}

const int nStaves = nStavesHalfBarrel * 2;

Expand Down
Loading