Skip to content

Commit de48daa

Browse files
bulukutluclaude
andcommitted
ALICE 3 TRK: add simplified-realistic OT barrel layout
New kSimplifiedRealistic layoutMLOT option (TRKOTLayerRealistic): detailed OT module stack (chips, FPC, cold plate, ZIF connector, SMD capacitors, brackets, cooling pipe), two-row staves with active overlap, and a barrel built in four parts (two eta half-barrels, each split azimuthally). The ML layers and the original kSegmented OT are kept as comparison baselines. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 79fec19 commit de48daa

7 files changed

Lines changed: 487 additions & 81 deletions

File tree

Detectors/Upgrades/ALICE3/TRK/README.md

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Configurables for various sub-detectors are presented in the following Table:
1515
| Subsystem | Available options | Comments |
1616
| ------------------ | ------------------------------------------------------- | ---------------------------------------------------------------- |
1717
| `TRKBase.layoutVD` | `kIRIS4` (default), `kIRISFullCyl`, `kIRIS5`, `kIRIS4a` | [link to definitions](./base/include/TRKBase/TRKBaseParam.h) |
18-
| `TRKBase.layoutMLOT` | `kCylindrical`, `kSegmented` (default) | `kSegmented` produces a Turbo layout for ML and a Staggered layout for OT |
18+
| `TRKBase.layoutMLOT` | `kCylindrical`, `kSegmented` (default), `kSimplifiedRealistic` | `kCylindrical`: simple silicon tubes. `kSegmented`: Turbo ML + solid-module OT. `kSimplifiedRealistic`: same ML as `kSegmented`, but a detailed OT barrel (see below) |
1919
| `TRKBase.layoutSRV` | `kPeacockv1` (default), `kLOISymm` | `kLOISymm` produces radially symmetric service volumes, as used in the LoI |
2020

2121
For example, a geometry with fully cylindrical tracker barrel (for all layers in VD, ML and OT) can be obtained by
@@ -26,7 +26,7 @@ o2-sim-serial-run5 -n 1 -g pythia8hi -m A3IP TRK FT3 TF3 \
2626

2727
## Custom Geometry Configuration
2828

29-
The geometry of the ML and OT layers can be overridden by providing a custom plain-text configuration file via `TRKBase.configFile=filename.txt`. The parser interprets the file differently depending on the active `TRKBase.layoutMLOT` setting (`kCylindrical` or `kSegmented`).
29+
The geometry of the ML and OT layers can be overridden by providing a custom plain-text configuration file via `TRKBase.configFile=filename.txt`. The parser interprets the file differently depending on the active `TRKBase.layoutMLOT` setting (`kCylindrical`, or `kSegmented`/`kSimplifiedRealistic` which share the same syntax).
3030

3131
### General Syntax Rules
3232
* **Separators:** All columns **must** be separated by a single TAB (`\t`). Using spaces will result in a parsing error.
@@ -55,9 +55,9 @@ When `TRKBase.layoutMLOT=kCylindrical` is used, each layer requires a minimum of
5555
80.0 255.9 0.1
5656
```
5757

58-
### 2. Segmented Layout (`kSegmented`)
58+
### 2. Segmented / Simplified-Realistic Layout (`kSegmented`, `kSimplifiedRealistic`)
5959

60-
When `TRKBase.layoutMLOT=kSegmented` is used, each layer requires a minimum of 5 base parameters to define the geometry. The parser distinguishes between Middle Layers (ML) and Outer Layers (OT) based on the sequential layer index.
60+
Both layouts use the same configuration-file syntax (only the OT geometry implementation differs). Each layer requires a minimum of 5 base parameters to define the geometry. The parser distinguishes between Middle Layers (ML) and Outer Layers (OT) based on the sequential layer index.
6161

6262
* *(Note: The 5 base parameters map directly to: Inner Radius (`rInn`), Thickness (`thick`), Tilt Angle (`tiltAngle`), Number of Staves (`nStaves`), and Number of Modules per stave (`nMods`)).*
6363

@@ -66,8 +66,9 @@ The first 5 valid lines are parsed as `TRKMLLayer` objects. These layers **requi
6666
* **Format:** `rInn` \t `thick` \t `tiltAngle` \t `nStaves` \t `nMods` \t `stagOffset` \t `[optional_mode]`
6767

6868
**Outer Layers (OT) - Indices 5 and above**
69-
From the 6th valid line onwards, lines are parsed as `TRKOTLayer` objects. These layers do **not** have a staggering offset. The optional mode parameter shifts to the 6th column.
69+
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.
7070
* **Format:** `rInn` \t `thick` \t `tiltAngle` \t `nStaves` \t `nMods` \t `[optional_mode]`
71+
* *(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.)*
7172

7273
**Example for `kSegmented`:**
7374

@@ -89,5 +90,17 @@ From the 6th valid line onwards, lines are parsed as `TRKOTLayer` objects. These
8990
80.0 0.01 0.0 56 22 1
9091
```
9192

93+
## Simplified-Realistic OT geometry (`kSimplifiedRealistic`)
94+
95+
`kSimplifiedRealistic` keeps the ML layers identical to `kSegmented` but replaces the solid-silicon OT modules with a more detailed, but still simplified, description (`TRKOTLayerRealistic`). All tunable dimensions live in [`Specs.h`](./base/include/TRKBase/Specs.h) (`constants::OT`); values that depend on others are computed in the source.
96+
97+
**Module** — a flush stack about the chip mid-plane: cold plate (carbon fibre), 8 pure-silicon chips (2 in φ × 4 in z, dead zones facing the outer module edges), FPC (Kapton+Cu), one ZIF connector centred on a short edge, SMD capacitors over the chip footprints (skipping any under the connector), and two mounting brackets on the cold plate.
98+
99+
**Stave** — two module rows overlapping in φ (so each row's dead zone is covered by the other row's sensor) and offset in r, plus a cooling pipe between them.
100+
101+
**Barrel** — each layer is built in **four parts**: two z-half-barrels (±η), each split azimuthally into two 180° halves cut on **perpendicular planes** (one horizontal, one vertical, matching the Peacock services). Neighbouring staves overlap (≥ 1 mm active double-coverage); the two azimuthal halves meet at a ~1 mm gap instead. The stave count is fixed (the gap is absorbed into a slightly larger internal overlap). The cooling pipe faces the larger radius on the inner two OT layers (R = 45, 60 cm) and the smaller radius on the flipped outer layer (R = 80 cm).
102+
103+
The OT services (cables/cooling bundles, cold plates) are built by `TRKServices` for all layouts via `TRKBase.layoutSRV`.
104+
92105
<!-- doxy
93106
/doxy -->

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

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ namespace moduleMLOT /// same for ML and OT for the moment
7171
{ /// TODO: account for different modules in case of changes
7272
namespace silicon
7373
{
74-
constexpr double thickness{100 * mu}; // thickness of the silicon (should be 10 um epitaxial layer + 90 um substrate)?
74+
constexpr double thickness{100 * mu}; // thickness of the silicon sensor (per OT spec §2.1; previously 50 um)
7575
} // namespace silicon
7676
namespace metalstack
7777
{
@@ -114,17 +114,66 @@ namespace OT
114114
{
115115
namespace halfstave
116116
{
117-
constexpr double width{moduleMLOT::width * 1}; // width of the half stave
118-
// constexpr double length{moduleMLOT::length * 20}; // length of the halfstave
119-
constexpr double length{258 * cm}; // length of the halfstave, hardcoded to fit the implemented geometry
117+
constexpr double width{moduleMLOT::width * 1}; // width of the half stave (= one row width = FPC width = 52.2 mm)
118+
constexpr double length{258 * cm}; // legacy constant, not used directly in geometry assembly
120119
constexpr int nRows{static_cast<int>(width / moduleMLOT::chip::pitchX)}; // number of rows in the halfstave
121120
constexpr int nCols{static_cast<int>(length / moduleMLOT::chip::pitchZ)}; // number of columns in the halfstave
122121
} // namespace halfstave
123122
constexpr int nLayers{3}; // number of layers in the OT
124-
constexpr double width{halfstave::width * 2}; // width of the stave
123+
constexpr double width{halfstave::width * 2}; // width of the stave (two rows)
125124
constexpr double length{halfstave::length}; // length of the stave
126125
constexpr int nRows{static_cast<int>(width / moduleMLOT::chip::pitchX)}; // number of rows in the stave
127126
constexpr int nCols{static_cast<int>(length / moduleMLOT::chip::pitchZ)}; // number of columns in the stave
127+
constexpr int nModulesPerRow{11}; // modules along z in one row (spec §4.1)
128+
constexpr double interModuleGap{0.2 * mm}; // z-gap between consecutive module FPCs (spec §4.2)
129+
130+
// Detailed component dimensions (spec §2 and §7)
131+
namespace fpc
132+
{
133+
constexpr double length{116.8 * mm}; // z-extent (4 chips + gaps + edges)
134+
constexpr double width{52.2 * mm}; // phi-extent (2 chips + gap + edges)
135+
constexpr double thickness{0.200 * mm}; // r-extent; Kapton+Cu stack (spec §2.2)
136+
} // namespace fpc
137+
namespace coldPlate
138+
{
139+
constexpr double length{116.8 * mm}; // z-extent, same as FPC
140+
constexpr double width{47.2 * mm}; // phi-extent, narrower than FPC (chip active region only)
141+
constexpr double thickness{0.4 * mm}; // r-extent (spec §2.5)
142+
} // namespace coldPlate
143+
namespace connector
144+
{
145+
constexpr double width{25.0 * mm}; // phi-extent (long axis of ZIF connector)
146+
constexpr double length{10.0 * mm}; // z-extent
147+
constexpr double thickness{2.0 * mm}; // r-extent (spec §2.3)
148+
} // namespace connector
149+
namespace capacitor
150+
{
151+
constexpr double width{1.0 * mm}; // phi-extent
152+
constexpr double length{0.5 * mm}; // z-extent
153+
constexpr double thickness{0.3 * mm}; // r-extent (spec §2.4, unified size for 0201 and 0402)
154+
constexpr int perChip{5}; // 5 per chip → 40 per module
155+
} // namespace capacitor
156+
namespace bracket
157+
{
158+
constexpr double length{10.0 * mm}; // z-extent (spec §2.6)
159+
constexpr double width{5.0 * mm}; // phi-extent
160+
constexpr double thickness{8.0 * mm}; // r-extent, stand-off toward cooling pipe
161+
} // namespace bracket
162+
namespace coolingPipe
163+
{
164+
constexpr double rInner{0.4 * cm}; // inner radius: 4 mm
165+
constexpr double rOuter{0.5 * cm}; // outer radius: 5 mm (wall = 1 mm carbon fibre)
166+
constexpr double rLocalOffset{3.5 * cm}; // chip mid-plane → pipe axis, along local r
167+
} // namespace coolingPipe
168+
169+
// Assembly parameters for the simplified-realistic OT (tunable)
170+
constexpr double sensorThickness{moduleMLOT::silicon::thickness}; // 100 um pure-silicon chip (no metal stack)
171+
constexpr double interChipGap{0.2 * mm}; // gap between chips within a module
172+
constexpr double rowActiveOverlap{1.0 * mm}; // active double-coverage between the two rows of a stave
173+
constexpr double halfBarrelChipGap{1.0 * mm}; // chip-edge gap between the two azimuthal half-barrels
174+
constexpr double connectorZDepth{3.0 * cm}; // connector centre, inset from the module short edge in z
175+
constexpr double bracketZDepth{3.0 * cm}; // bracket centre, inset from the cold-plate short edge in z
176+
constexpr double barrelHalvesZGap{0.8 * cm}; // z-gap between the two eta half-barrels
128177
} // namespace OT
129178

130179
namespace apts /// parameters for the APTS response

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ enum eVDLayout {
3030
enum eMLOTLayout {
3131
kCylindrical = 0,
3232
kSegmented,
33+
kSimplifiedRealistic,
3334
};
3435

3536
enum eSrvLayout {

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

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#define ALICEO2_TRK_LAYER_H
1414

1515
#include "TRKBase/Specs.h"
16-
#include "TRKBase/TRKBaseParam.h"
1716
#include <TGeoManager.h>
1817

1918
#include <Rtypes.h>
@@ -77,8 +76,8 @@ class TRKSegmentedLayer : public TRKCylindricalLayer
7776
TGeoVolume* createSensor() override;
7877
TGeoVolume* createDeadzone();
7978
TGeoVolume* createMetalStack() override;
80-
TGeoVolume* createChip();
81-
TGeoVolume* createModule();
79+
virtual TGeoVolume* createChip();
80+
virtual TGeoVolume* createModule();
8281
virtual TGeoVolume* createStave() = 0;
8382
void createLayer(TGeoVolume* motherVolume) override = 0;
8483

@@ -88,7 +87,6 @@ class TRKSegmentedLayer : public TRKCylindricalLayer
8887
int mNumberOfStaves;
8988
bool mIsFlipped = false;
9089

91-
// Fixed parameters for the layer, to be set based on the specifications of the chip and module
9290
static constexpr double sChipWidth = constants::moduleMLOT::chip::width;
9391
static constexpr double sChipLength = constants::moduleMLOT::chip::length;
9492
static constexpr double sDeadzoneWidth = constants::moduleMLOT::chip::passiveEdgeReadOut;
@@ -99,10 +97,8 @@ class TRKSegmentedLayer : public TRKCylindricalLayer
9997
// TGeo objects outside logical volumes can cause errors
10098
static constexpr float sLogicalVolumeThickness = 1.3;
10199

102-
// For the segmented layers, because of tilting and staggering the bounding radii can be different
103-
// from the inner radius and inner radius + thickness.
104-
// This function calculates the bounding radii based on the geometry of the stave and the tilt angle,
105-
// to ensure that the layer volume is large enough to contain all the staves without overlaps.
100+
// Bounding radii accounting for tilt/staggering, so the layer volume contains
101+
// all staves without extrusions.
106102
virtual std::pair<float, float> getBoundingRadii(double staveWidth) const;
107103

108104
ClassDefOverride(TRKSegmentedLayer, 0);
@@ -130,6 +126,7 @@ class TRKMLLayer : public TRKSegmentedLayer
130126
ClassDefOverride(TRKMLLayer, 0);
131127
};
132128

129+
// Original (simplified) OT barrel: solid-silicon modules, cylindrically paved.
133130
class TRKOTLayer : public TRKSegmentedLayer
134131
{
135132
public:
@@ -146,15 +143,46 @@ class TRKOTLayer : public TRKSegmentedLayer
146143

147144
private:
148145
static constexpr double sHalfStaveWidth = constants::OT::halfstave::width;
149-
static constexpr double sInStaveOverlap = constants::moduleMLOT::gaps::outerEdgeLongSide + constants::moduleMLOT::chip::passiveEdgeReadOut + 0.1; // 1.5mm outer-edge + 1mm deadzone + 1mm (true) overlap
146+
static constexpr double sInStaveOverlap = constants::moduleMLOT::gaps::outerEdgeLongSide + constants::moduleMLOT::chip::passiveEdgeReadOut + 0.1;
150147
static constexpr double sStaveWidth = constants::OT::width - sInStaveOverlap;
151148

152-
// Override to account for the staggering offset present in OT layers
153149
std::pair<float, float> getBoundingRadii(double staveWidth) const override;
154150

155151
ClassDefOverride(TRKOTLayer, 0);
156152
};
157153

154+
// Simplified-realistic OT barrel: detailed module stack (FPC, cold plate, ZIF
155+
// connector, SMD capacitors, mounting brackets, cooling pipe), two-row staves
156+
// with active overlap, and a barrel paved in four parts (two eta half-barrels,
157+
// each split azimuthally into two halves cut on perpendicular planes).
158+
// All tunable dimensions live in constants::OT; everything derived is computed
159+
// in the source.
160+
class TRKOTLayerRealistic : public TRKSegmentedLayer
161+
{
162+
public:
163+
TRKOTLayerRealistic() = default;
164+
TRKOTLayerRealistic(int layerNumber, std::string layerName, float rInn, float tiltAngle, int numberOfStaves, int numberOfModules, float thickOrX2X0, MatBudgetParamMode mode);
165+
~TRKOTLayerRealistic() override = default;
166+
167+
TGeoVolume* createChip() override;
168+
TGeoVolume* createModule() override;
169+
TGeoVolume* createStave() override;
170+
TGeoVolume* createHalfStave();
171+
void createLayer(TGeoVolume* motherVolume) override;
172+
173+
private:
174+
TGeoVolume* createFPC();
175+
TGeoVolume* createColdPlate();
176+
TGeoVolume* createCoolingPipe();
177+
void addConnector(TGeoVolume* moduleVol, double rMid);
178+
void addCapacitors(TGeoVolume* moduleVol, double rMid);
179+
void addBrackets(TGeoVolume* moduleVol, double rMid);
180+
181+
std::pair<float, float> getBoundingRadii(double staveWidth) const override;
182+
183+
ClassDefOverride(TRKOTLayerRealistic, 0);
184+
};
185+
158186
} // namespace trk
159187
} // namespace o2
160188
#endif // ALICEO2_TRK_LAYER_H

0 commit comments

Comments
 (0)