Skip to content

Commit 59e68b2

Browse files
FT3 New Optimised OT Tiling & Clean up material writing (#15858)
* Make medium creation in FT3 defined and executed more centrally * move materials into separate header with constants, and define the getMedium file there instead for contained structure * Add basic functionality for placing exact staves and sensors: achieve by bundling existing functionalities into functions more * add the relevant constansts * add new optimised tiling to FT3ModuleConstants. Now has active coverage area of 97.25% in the nominal region * make exact stave placement default * update FT3ModuleConstants.h with original tiling again -- with 150um sensor gaps, 350um module gap. Change 2x1 sensor size with the gap as well and fix placement accordingly * make stave width explicit variable and use it to constrain its placement, rather than sensor width: this allowed for potential small ex/intrusions. * Please consider the following formatting changes * allow a bit more radius for OT than ML, so that we fit all the exceptions from the tiling that had -9, +3 as the maximum placements past the nominal radius * (maybe) temporarily move the OT services to 71cm, to make space for the air tube at 3cm extrusion, since the outermost staves extrude that far. Also make max outer radius back to 2.5cm for the ML * Please consider the following formatting changes --------- Co-authored-by: ALICE Action Bot <alibuild@cern.ch>
1 parent 0db6a66 commit 59e68b2

11 files changed

Lines changed: 670 additions & 396 deletions

File tree

‎Detectors/Upgrades/ALICE3/TRKFT3/FT3/base/include/FT3Base/FT3BaseParam.h‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,13 @@ struct FT3BaseParam : public o2::conf::ConfigurableParamHelper<FT3BaseParam> {
4646
double staveTolOTInner = 0.;
4747
double staveTolOTOuter = 0.;
4848

49-
// What to place over x=0 line in case of full outer-outer stave: Gap or Module
50-
bool placeSensorStackInMiddleOfStave = false;
49+
/*
50+
* Place the sensor stacks from the tabulated layout in FT3ModuleConstants.h
51+
* (StaveConfig::exactStaveFills) instead of filling every stave greedily
52+
* with the stack sizes in kSensorsPerStack. The tabulated layout is taken as
53+
* given: none of the radial tolerances above are applied to it.
54+
*/
55+
bool useExactStavePlacement = true;
5156

5257
// Draw reference circles at inner and outer radius of stave layer, for visualisation
5358
bool drawReferenceCircles = false;

‎Detectors/Upgrades/ALICE3/TRKFT3/FT3/simulation/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
o2_add_library(FT3Simulation
1313
SOURCES
14+
src/FT3Materials.cxx
1415
src/FT3Module.cxx
1516
src/FT3Layer.cxx
1617
src/Detector.cxx

‎Detectors/Upgrades/ALICE3/TRKFT3/FT3/simulation/include/FT3Simulation/FT3Layer.h‎

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,11 @@ class FT3Layer : public TObject
5959
/// \param motherVolume the TGeoVolume owing the volume structure
6060
virtual void createLayer(TGeoVolume* motherVolume);
6161

62-
static void initialize_mat();
63-
6462
// create layer for disk support
6563
void createSeparationLayer(TGeoVolume* motherVolume, const std::string& separationLayerName);
6664
void createSeparationLayer_waterCooling(TGeoVolume* motherVolume, const std::string& separationLayerName);
6765
void createReferenceCircles(TGeoVolume* motherVolume, const std::string& name);
6866

69-
static TGeoMaterial* carbonFiberMat;
70-
static TGeoMedium* medCarbonFiber;
71-
72-
static TGeoMixture* kaptonMat;
73-
static TGeoMedium* kaptonMed;
74-
75-
static TGeoMaterial* waterMat;
76-
static TGeoMedium* waterMed;
77-
78-
static TGeoMaterial* foamMat;
79-
static TGeoMedium* medFoam;
80-
8167
private:
8268
Int_t mLayerNumber = -1; ///< Current layer number
8369
Int_t mDirection; ///< Layer direction 0=Forward 1 = Backward
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file FT3Materials.h
13+
/// \brief Materials of the FT3 detector, and access to the media made from them
14+
15+
#ifndef FT3MATERIALS_H
16+
#define FT3MATERIALS_H
17+
18+
#include <array>
19+
#include <unordered_map>
20+
#include <TColor.h>
21+
22+
class TGeoMedium;
23+
24+
namespace o2::ft3
25+
{
26+
namespace Materials
27+
{
28+
// The name FT3 registers itself under with the MaterialManager. getMedium()
29+
// looks media up under this key, so it has to be the same name the Detector
30+
// hands to DetImpl<Detector>.
31+
constexpr const char* moduleName = "FT3";
32+
33+
/*
34+
* Materials of the FT3 detector.
35+
*
36+
* Everything the simulation needs to know about a material lives in the
37+
* materials map below, keyed by its FT3-local ID: composition, density,
38+
* transport parameters and the colour its volumes are drawn in.
39+
* Detector::createMaterials() registers the whole map with the MaterialManager,
40+
* and FT3Module/FT3Layer reach the media through getMedium() below, so no ID,
41+
* density or colour is ever written out by hand.
42+
*/
43+
enum class MaterialID : unsigned {
44+
Air = 1,
45+
Silicon,
46+
Copper,
47+
Kapton,
48+
CarbonFiber,
49+
Epoxy,
50+
Aluminum,
51+
Foam,
52+
Water
53+
};
54+
55+
// Transport parameters of a medium, in the order expected by Detector::Medium()
56+
struct TrackingParams {
57+
float tmaxfd; // maximum field-induced angular deviation per step, degrees
58+
float stemax; // maximum step length, cm
59+
float deemax; // maximum fractional energy loss per step
60+
float epsil; // tracking precision, cm
61+
float stmin; // minimum step length, cm
62+
};
63+
64+
constexpr TrackingParams sensitiveTracking = {0.1f, 0.0075f, 0.1f, 1.0e-4f, 0.0f};
65+
constexpr TrackingParams passiveTracking = {0.1f, 1.0f, 0.1f, 1.0e-4f, 0.0f};
66+
67+
// Maximum number of elements any of the mixtures below is built from
68+
constexpr unsigned maxMaterialComponents = 4;
69+
using ComponentArray = std::array<float, maxMaterialComponents>;
70+
71+
struct MaterialProperties {
72+
const char* name;
73+
int colour; // ROOT colour every volume made of this material is drawn in
74+
float density; // g/cm3
75+
// Radiation and nuclear interaction length, cm. Only single elements carry
76+
// them: Mixture() derives both from the composition and takes no such
77+
// arguments. A non-positive value lets the transport engine compute it.
78+
float radl;
79+
float absl;
80+
int nComponents; // 0: single element; > 0: mixture by weight; < 0: mixture by atom count
81+
ComponentArray a; // mass numbers; only a[0] is used for a single element
82+
ComponentArray z; // atomic numbers; only z[0] is used for a single element
83+
ComponentArray w; // weight fractions or atom counts; unused for a single element
84+
TrackingParams tracking;
85+
};
86+
87+
/*
88+
* Silicon, copper and carbon fibre are shared with TRK and are kept numerically
89+
* identical to its SILICON$, COPPER$ and CARBONFIBER$ (TRK Detector::createMaterials()),
90+
* down to the radiation lengths. Kapton, epoxy and aluminium have no TRK
91+
* counterpart: TRK models the flex as the effective FPC$ mixture instead.
92+
*/
93+
inline const std::unordered_map<MaterialID, MaterialProperties> materials = {
94+
// Air volumes get their colour set individually where they are built
95+
{MaterialID::Air, {"Air", kWhite, 1.20479e-3f, 0.0f, 0.0f, 4, {12.0107f, 14.0067f, 15.9994f, 39.948f}, {6.0f, 7.0f, 8.0f, 18.0f}, {0.000124f, 0.755267f, 0.231781f, 0.012827f}, passiveTracking}},
96+
{MaterialID::Silicon, {"Silicon", kGreen, 2.33f, 9.36f, 999.0f, 0, {28.086f}, {14.0f}, {}, sensitiveTracking}},
97+
// Copper planes of the end-of-stave cards: X0 = 1.436 cm
98+
{MaterialID::Copper, {"Copper", kOrange, 8.96f, 1.436f, 999.0f, 0, {63.546f}, {29.0f}, {}, passiveTracking}},
99+
// Kapton: C22 H10 N2 O5, by weight fraction. Also the cooling pipe material.
100+
{MaterialID::Kapton, {"Kapton", kYellow, 1.346f, 0.0f, 0.0f, 4, {12.0107f, 1.00794f, 14.0067f, 15.999f}, {6.0f, 1.0f, 7.0f, 8.0f}, {0.5641f, 0.2564f, 0.0513f, 0.1282f}, passiveTracking}},
101+
// Carbon fibre: density tuned so X0 ~ 27 cm, as in TRK
102+
// TODO: Check with Rene the exact type of carbon fiber
103+
{MaterialID::CarbonFiber, {"CarbonFiber", kGray + 1, 1.45f, 27.0f, 999.0f, 0, {12.0107f}, {6.0f}, {}, passiveTracking}},
104+
// Epoxy: C18 H19 O3, by atom count (negative nComponents)
105+
{MaterialID::Epoxy, {"Epoxy", kBlue, 2.186f, 0.0f, 0.0f, -3, {12.0107f, 1.00794f, 15.999f}, {6.0f, 1.0f, 8.0f}, {18.0f, 19.0f, 3.0f}, passiveTracking}},
106+
// No TRK counterpart; X0 and lambda are left to the transport engine
107+
{MaterialID::Aluminum, {"Aluminum", kBlack, 2.7f, 0.0f, 0.0f, 0, {26.98f}, {13.0f}, {}, passiveTracking}},
108+
// Carbon foam core of the disk separation layer
109+
{MaterialID::Foam, {"Foam", kBlack, 0.17f, 0.0f, 0.0f, 0, {12.0107f}, {6.0f}, {}, passiveTracking}},
110+
// Coolant inside the kapton pipes
111+
{MaterialID::Water, {"Water", kBlue, 1.064f, 0.0f, 0.0f, 0, {18.01528f}, {8.0f}, {}, passiveTracking}}};
112+
// The inactive rim of a sensor is made of silicon as well, but is drawn
113+
// separately so that it can be told apart from the active area.
114+
const int SiInactiveColor = kRed;
115+
} // namespace Materials
116+
117+
/// Retrieve one of the media registered by Detector::createMaterials().
118+
///
119+
/// A free function rather than a member of Detector: the media live in the
120+
/// MaterialManager singleton keyed by Materials::moduleName, not in the
121+
/// detector object, so the lookup needs no Detector instance.
122+
TGeoMedium* getMedium(Materials::MaterialID id);
123+
} // namespace o2::ft3
124+
125+
#endif // FT3MATERIALS_H

‎Detectors/Upgrades/ALICE3/TRKFT3/FT3/simulation/include/FT3Simulation/FT3Module.h‎

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
#ifndef FT3MODULE_H
1616
#define FT3MODULE_H
1717

18+
#include <TGeoMedium.h>
1819
#include <TGeoVolume.h>
1920
#include <string>
2021
#include <vector>
2122

23+
#include "FT3Simulation/FT3Materials.h"
2224
#include "FT3Simulation/FT3ModuleConstants.h"
2325

2426
// define types for y positions, second element is the stack height
@@ -28,25 +30,12 @@ using PosNegPositionTypes = std::pair<PositionTypes, PositionTypes>;
2830
// define type of the y position range: First pair is (min, max) for positive y
2931
using PositionRangeType = std::pair<std::pair<double, double>, std::pair<double, double>>;
3032
namespace Constants = o2::ft3::ModuleConstants;
33+
namespace Materials = o2::ft3::Materials;
3134

3235
class FT3Module
3336
{
3437

3538
public:
36-
static void initialize_materials();
37-
static TGeoMaterial* siliconMat;
38-
static TGeoMedium* siliconMed;
39-
static TGeoMaterial* copperMat;
40-
static TGeoMedium* copperMed;
41-
static TGeoMixture* kaptonMat;
42-
static TGeoMedium* kaptonMed;
43-
static TGeoMaterial* epoxyMat;
44-
static TGeoMedium* epoxyMed;
45-
static TGeoMaterial* AluminumMat;
46-
static TGeoMedium* AluminumMed;
47-
static TGeoMaterial* carbonFiberMat;
48-
static TGeoMedium* carbonFiberMed;
49-
5039
const char* mDetName;
5140

5241
static void createModule(
@@ -70,10 +59,39 @@ class FT3Module
7059
double Rout, double z_offset_local, const Constants::StaveConfig& staveConfig,
7160
TGeoVolume* motherVolume);
7261

62+
// Walk every stave of a layer, create its volumes and work out where its
63+
// modules go, leaving the positions in y_positionsPosNeg
64+
void build_staves_exact(
65+
TGeoVolume* motherVolume, int layerNumber, int direction,
66+
const Constants::StaveConfig& staveConfig,
67+
const std::array<std::array<double, 3>, 4>& staveTriangles,
68+
double z_offset_to_carbon_face,
69+
std::vector<PosNegPositionTypes>& y_positionsPosNeg,
70+
unsigned& staveVolumeCount);
71+
72+
void build_staves_greedy(
73+
TGeoVolume* motherVolume, int layerNumber, int direction, double Rin, double Rout,
74+
const Constants::StaveConfig& staveConfig,
75+
const std::array<std::array<double, 3>, 4>& staveTriangles,
76+
double z_offset_to_carbon_face,
77+
std::vector<PosNegPositionTypes>& y_positionsPosNeg, unsigned& staveVolumeCount);
78+
79+
// Shared by both: one stave's carbon shell, plus its mirror where needed
80+
void add_stave_volumes(
81+
TGeoVolume* motherVolume, int layerNumber, int direction,
82+
const Constants::StaveConfig& staveConfig, unsigned i_stave,
83+
const std::array<std::array<double, 3>, 4>& staveTriangles,
84+
double z_offset_to_carbon_face, std::pair<double, double>& absAllowedYRange,
85+
double y_midpoint, bool mirrorStaveAroundX, unsigned* staveVolumeCount);
86+
7387
// Helper functions
74-
void fill_stave(PosNegPositionTypes& y_positions, double Rin, double Rout,
75-
double x_left, unsigned kSensorStack, PositionRangeType y_range,
76-
std::pair<double, double>& absAllowedYRange);
88+
void fill_stave_greedy(
89+
PosNegPositionTypes& y_positions, unsigned kSensorStack,
90+
PositionRangeType y_range,
91+
std::pair<double, double>& absAllowedYRange);
92+
93+
PositionTypes fill_stave_exact(const std::vector<Constants::StaveFill>& fills);
94+
7795
void addStaveVolume(
7896
TGeoVolume* motherVolume, std::string volumeName, int direction,
7997
unsigned* volume_count, double staveLength,

0 commit comments

Comments
 (0)