Project
Loading...
Searching...
No Matches
Geometry.cxx
Go to the documentation of this file.
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
16
18
19#include <sstream>
20
21#include "Materials.h"
24
25#include <TGeoVolume.h>
26#include <TGeoManager.h>
27#include <TGeoShape.h>
28#include <TGeoCompositeShape.h>
29
30namespace o2
31{
32namespace mid
33{
34
36
37// Gas gap (gas enclosed by bakelite electrodes + graphite and spacers)
38const float kGasHalfThickness = 0.2 / 2.;
39const float kSpacerHalfThickness = 0.2 / 2.;
40const float kElectrodHalfThickness = 0.2 / 2.;
41
42// Insulating material (PET foil) between the gas gap and the strip plane
43const float kInsulatorHalfThickness = 0.01 / 2.;
44
45// Strip plane (styrofoam + mylar/copper foils)
46const float kStyrofoamHalfThickness = 0.3 / 2.;
47const float kMylarHalfThickness = 0.019 / 2.;
48const float kCopperHalfThickness = 0.002 / 2.;
49
50// Stiffener plane (nomex enclosed between aluminium sheets)
51const float kNomexHalfThickness = 0.88 / 2.;
52const float kAluminiumHalfThickness = 0.06 / 2.;
53
55// vertical support
56const float kVerticalSupportHalfExtDim[] = {1.5, 311., 1.5};
57const float kVerticalSupportHalfIntDim[] = {1.2, 311., 1.2};
58const float kVerticalSupportXPos[] = {61.45, 122.45, 192.95, 236.95};
59
60// horizontal support
61const float kHorizontalSupportHalfExtDim[] = {96.775, 2., 3.};
62const float kHorizontalSupportHalfIntDim[] = {96.775, 1.9, 2.8};
64
65TGeoVolume* createVerticalSupport(int iChamber)
66{
68
69 auto supp = new TGeoVolume(Form("Vertical support chamber %d", iChamber), new TGeoBBox(Form("VertSuppBox%d", iChamber), kVerticalSupportHalfExtDim[0], kVerticalSupportHalfExtDim[1] * geoparams::ChamberScaleFactors[iChamber], kVerticalSupportHalfExtDim[2]), assertMedium(Medium::Aluminium));
70
71 new TGeoBBox(Form("VertSuppCut%d", iChamber), kVerticalSupportHalfIntDim[0], kVerticalSupportHalfIntDim[1] * geoparams::ChamberScaleFactors[iChamber], kVerticalSupportHalfIntDim[2]);
72
73 supp->SetShape(new TGeoCompositeShape(Form("VertSuppCut%d", iChamber), Form("VertSuppBox%d-VertSuppCut%d", iChamber, iChamber)));
74
75 return supp;
76}
77
78TGeoVolume* createHorizontalSupport(int iChamber)
79{
81
82 auto supp = new TGeoVolume(Form("Horizontal support chamber %d", iChamber), new TGeoBBox(Form("HoriSuppBox%d", iChamber), kHorizontalSupportHalfExtDim[0] * geoparams::ChamberScaleFactors[iChamber], kHorizontalSupportHalfExtDim[1], kHorizontalSupportHalfExtDim[2]), assertMedium(Medium::Aluminium));
83
84 new TGeoBBox(Form("HoriSuppCut%d", iChamber), kHorizontalSupportHalfIntDim[0] * geoparams::ChamberScaleFactors[iChamber], kHorizontalSupportHalfIntDim[1], kHorizontalSupportHalfIntDim[2]);
85
86 supp->SetShape(new TGeoCompositeShape(Form("HoriSuppCut%d", iChamber), Form("HoriSuppBox%d-HoriSuppCut%d", iChamber, iChamber)));
87
88 return supp;
89}
90
91TGeoVolume* createRPC(geoparams::RPCtype type, int iChamber)
92{
94
95 auto sname = getRPCVolumeName(type, iChamber);
96 auto name = sname.c_str();
97
98 auto rpc = new TGeoVolumeAssembly(name);
99
100 // get the dimensions from MIDBase/Constants
102 halfLength *= geoparams::ChamberScaleFactors[iChamber];
103 double halfHeight = geoparams::getRPCHalfHeight(iChamber);
104
106
108 // trigger gas
109 auto gas = new TGeoVolume(Form("Gas %s", name),
110 new TGeoBBox(Form("%sGasBox", name), halfLength, halfHeight, kGasHalfThickness),
112
113 // resisitive electrod plate
114 auto electrod = new TGeoVolume(Form("Electrod %s", name),
115 new TGeoBBox(Form("%sElecBox", name), halfLength, halfHeight, kElectrodHalfThickness),
117
119 auto insu = new TGeoVolume(Form("Insulator %s", name),
120 new TGeoBBox(Form("%sInsuBox", name), halfLength, halfHeight, kInsulatorHalfThickness),
122
124 // cooper foil
125 auto copper = new TGeoVolume(Form("Copper %s", name),
126 new TGeoBBox(Form("%sCopperBox", name), halfLength, halfHeight, kCopperHalfThickness),
128
129 // mylar foil
130 auto mylar = new TGeoVolume(Form("Mylar %s", name),
131 new TGeoBBox(Form("%sMylarBox", name), halfLength, halfHeight, kMylarHalfThickness),
133
134 // styrofoam plane
135 auto styro = new TGeoVolume(Form("Styrofoam %s", name),
136 new TGeoBBox(Form("%sStyroBox", name), halfLength, halfHeight, kStyrofoamHalfThickness),
138
140 // aluminium foil
141 auto alu = new TGeoVolume(Form("Aluminium %s", name),
142 new TGeoBBox(Form("%sAluBox", name), halfLength, halfHeight, kAluminiumHalfThickness),
144
145 // nomex
146 auto nomex = new TGeoVolume(Form("Nomex %s", name),
147 new TGeoBBox(Form("%sNomexBox", name), halfLength, halfHeight, kNomexHalfThickness),
149
150 // change the volume shape if we are creating a "cut" RPC
152 // dimensions of the cut
153 double cutHalfLength = geoparams::getLocalBoardWidth(iChamber) / 2.;
154 double cutHalfHeight = geoparams::getLocalBoardHeight(iChamber) / 2.;
155
156 bool isTopCut = (type == geoparams::RPCtype::TopCut);
157 const char* cutName = Form("%sCut%s", (isTopCut) ? "top" : "bottom", name);
158
159 // position of the cut w.r.t the center of the RPC
160 auto cutPos = new TGeoTranslation(Form("%sPos", cutName), cutHalfLength - halfLength, (isTopCut) ? halfHeight - cutHalfHeight : cutHalfHeight - halfHeight, 0.);
161 cutPos->RegisterYourself();
162
163 // for each volume, create a box and change the volume shape by extracting the cut shape
164 new TGeoBBox(Form("%sGasCut", name), cutHalfLength, cutHalfHeight, 2 * kGasHalfThickness);
165 gas->SetShape(new TGeoCompositeShape(Form("%sGasShape", name), Form("%sGasBox-%sGasCut:%sPos", name, name, cutName)));
166
167 new TGeoBBox(Form("%sElecCut", name), cutHalfLength, cutHalfHeight, 2 * kElectrodHalfThickness);
168 electrod->SetShape(new TGeoCompositeShape(Form("%sElecShape", name), Form("%sElecBox-%sElecCut:%sPos", name, name, cutName)));
169
170 new TGeoBBox(Form("%sInsuCut", name), cutHalfLength, cutHalfHeight, 2 * kInsulatorHalfThickness);
171 insu->SetShape(new TGeoCompositeShape(Form("%sInsuShape", name), Form("%sInsuBox-%sInsuCut:%sPos", name, name, cutName)));
172
173 new TGeoBBox(Form("%sCopperCut", name), cutHalfLength, cutHalfHeight, 2 * kCopperHalfThickness);
174 copper->SetShape(new TGeoCompositeShape(Form("%sCopperShape", name), Form("%sCopperBox-%sCopperCut:%sPos", name, name, cutName)));
175
176 new TGeoBBox(Form("%sMylarCut", name), cutHalfLength, cutHalfHeight, 2 * kMylarHalfThickness);
177 mylar->SetShape(new TGeoCompositeShape(Form("%sMylarShape", name), Form("%sMylarBox-%sMylarCut:%sPos", name, name, cutName)));
178
179 new TGeoBBox(Form("%sStyroCut", name), cutHalfLength, cutHalfHeight, 2 * kStyrofoamHalfThickness);
180 styro->SetShape(new TGeoCompositeShape(Form("%sStyroShape", name), Form("%sStyroBox-%sStyroCut:%sPos", name, name, cutName)));
181
182 new TGeoBBox(Form("%sAluCut", name), cutHalfLength, cutHalfHeight, 2 * kAluminiumHalfThickness);
183 alu->SetShape(new TGeoCompositeShape(Form("%sAluShape", name), Form("%sAluBox-%sAluCut:%sPos", name, name, cutName)));
184
185 new TGeoBBox(Form("%sNomexCut", name), cutHalfLength, cutHalfHeight, 2 * kNomexHalfThickness);
186 nomex->SetShape(new TGeoCompositeShape(Form("%sNomexShape", name), Form("%sNomexBox-%sNomexCut:%sPos", name, name, cutName)));
187 }
188
190 double halfThickness = kGasHalfThickness;
191 rpc->AddNode(gas, 1);
192 double z = halfThickness; // increment this value when adding a new layer
193
194 halfThickness = kElectrodHalfThickness;
195 z += halfThickness;
196 rpc->AddNode(electrod, 1, new TGeoTranslation(0., 0., z));
197 rpc->AddNode(electrod, 2, new TGeoTranslation(0., 0., -z));
198 z += halfThickness;
199
200 halfThickness = kInsulatorHalfThickness;
201 z += halfThickness;
202 rpc->AddNode(insu, 1, new TGeoTranslation(0., 0., z));
203 rpc->AddNode(insu, 2, new TGeoTranslation(0., 0., -z));
204 z += halfThickness;
205
206 halfThickness = kCopperHalfThickness;
207 z += halfThickness;
208 rpc->AddNode(copper, 1, new TGeoTranslation(0., 0., z));
209 rpc->AddNode(copper, 2, new TGeoTranslation(0., 0., -z));
210 z += halfThickness;
211
212 halfThickness = kMylarHalfThickness;
213 z += halfThickness;
214 rpc->AddNode(mylar, 1, new TGeoTranslation(0., 0., z));
215 rpc->AddNode(mylar, 2, new TGeoTranslation(0., 0., -z));
216 z += halfThickness;
217
218 halfThickness = kStyrofoamHalfThickness;
219 z += halfThickness;
220 rpc->AddNode(styro, 1, new TGeoTranslation(0., 0., z));
221 rpc->AddNode(styro, 2, new TGeoTranslation(0., 0., -z));
222 z += halfThickness;
223
224 halfThickness = kMylarHalfThickness;
225 z += halfThickness;
226 rpc->AddNode(mylar, 3, new TGeoTranslation(0., 0., z));
227 rpc->AddNode(mylar, 4, new TGeoTranslation(0., 0., -z));
228 z += halfThickness;
229
230 halfThickness = kCopperHalfThickness;
231 z += halfThickness;
232 rpc->AddNode(copper, 3, new TGeoTranslation(0., 0., z));
233 rpc->AddNode(copper, 4, new TGeoTranslation(0., 0., -z));
234 z += halfThickness;
235
236 halfThickness = kAluminiumHalfThickness;
237 z += halfThickness;
238 rpc->AddNode(alu, 1, new TGeoTranslation(0., 0., z));
239 rpc->AddNode(alu, 2, new TGeoTranslation(0., 0., -z));
240 z += halfThickness;
241
242 halfThickness = kNomexHalfThickness;
243 z += halfThickness;
244 rpc->AddNode(nomex, 1, new TGeoTranslation(0., 0., z));
245 rpc->AddNode(nomex, 2, new TGeoTranslation(0., 0., -z));
246 z += halfThickness;
247
248 halfThickness = kAluminiumHalfThickness;
249 z += halfThickness;
250 rpc->AddNode(alu, 3, new TGeoTranslation(0., 0., z));
251 rpc->AddNode(alu, 4, new TGeoTranslation(0., 0., -z));
252
253 return rpc;
254}
255
257{
259 double xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz;
260 matrix.GetComponents(xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz);
261 double vect[3] = {dx, dy, dz};
262 double rotMatrix[9] = {xx, xy, xz, yx, yy, yz, zx, zy, zz};
263 TGeoHMatrix* geoMatrix = new TGeoHMatrix("Transformation");
264 geoMatrix->SetTranslation(vect);
265 geoMatrix->SetRotation(rotMatrix);
266 return geoMatrix;
267}
268
269TGeoVolume* createChamber(int iChamber)
270{
272
273 auto chamber = new TGeoVolumeAssembly(geoparams::getChamberVolumeName(iChamber).c_str());
274
275 double scale = geoparams::ChamberScaleFactors[iChamber];
276
277 // create the service volumes
278 auto vertSupp = createVerticalSupport(iChamber);
279 auto horiSupp = createHorizontalSupport(iChamber);
280
281 // create the 4 types of RPC
282 auto longRPC = createRPC(geoparams::RPCtype::Long, iChamber);
283 auto bottomCutRPC = createRPC(geoparams::RPCtype::BottomCut, iChamber);
284 auto topCutRPC = createRPC(geoparams::RPCtype::TopCut, iChamber);
285 auto shortRPC = createRPC(geoparams::RPCtype::Short, iChamber);
286
287 // for node counting
288 int iHoriSuppNode = 0, iVertSuppNode = 0;
289
290 // place the volumes on both side of the chamber
291 for (int iside = 0; iside < 2; iside++) {
292
293 bool isRight = (iside == 0);
294 double xSign = (isRight) ? 1. : -1.;
295
296 // place 4 vertical supports per side
297 for (int i = 0; i < 4; i++) {
298 chamber->AddNode(vertSupp, iVertSuppNode++, new TGeoTranslation(xSign * kVerticalSupportXPos[i] * scale, 0., 0.));
299 }
300
301 // place the RPCs
302 for (int iRPC = 0; iRPC < detparams::NRPCLines; iRPC++) {
303
304 double x = xSign * geoparams::getRPCCenterPosX(iChamber, iRPC);
305 double zSign = (iRPC % 2 == 0) ? 1. : -1.;
306
307 if (!isRight) {
308 zSign *= -1.;
309 }
310 double z = zSign * geoparams::RPCZShift;
311 double y = 2 * geoparams::getRPCHalfHeight(iChamber) * (iRPC - 4) / (1 - (z / geoparams::DefaultChamberZ[0]));
312
313 // ID convention (from bottom to top of the chamber) : long, long, long, cut, short, cut, long, long, long
314 TGeoVolume* rpc = nullptr;
315 switch (iRPC) {
316 case 4: // short
317 rpc = shortRPC;
318 break;
319 case 5: // cut (bottom)
320 rpc = bottomCutRPC;
321 break;
322 case 3: // cut (top)
323 rpc = topCutRPC;
324 break;
325 default: // long
326 rpc = longRPC;
327 break;
328 }
329
330 int deId = detparams::getDEId(isRight, iChamber, iRPC);
331 chamber->AddNode(rpc, deId, getTransformation(getDefaultRPCTransform(isRight, iChamber, iRPC)));
332
333 // place 3 horizontal supports behind the RPC (and the vertical rods)
334 x = xSign * kHorizontalSupportPos[0] * scale;
335 z = -zSign * kHorizontalSupportPos[2];
336 for (int i = 0; i < 3; i++) {
337 chamber->AddNode(horiSupp, iHoriSuppNode++, new TGeoTranslation(x, y + (i - 1) * kHorizontalSupportPos[1] * scale, z));
338 }
339
340 } // end of the loop over the number of RPC lines
341
342 } // end of the side loop
343
344 return chamber;
345}
346
347void createGeometry(TGeoVolume& topVolume)
348{
350
351 // create and place the trigger chambers
352 for (int iCh = 0; iCh < detparams::NChambers; iCh++) {
353
354 topVolume.AddNode(createChamber(iCh), 1, getTransformation(getDefaultChamberTransform(iCh)));
355 }
356}
357
358//______________________________________________________________________________
359std::vector<TGeoVolume*> getSensitiveVolumes()
360{
362
363 std::vector<TGeoVolume*> sensitiveVolumeNames;
365 for (int ich = 0; ich < detparams::NChambers; ++ich) {
366 for (auto& type : types) {
367
368 auto name = Form("Gas %s", getRPCVolumeName(type, ich).c_str());
369 auto vol = gGeoManager->GetVolume(name);
370
371 if (!vol) {
372 throw std::runtime_error(Form("could not get expected volume %s", name));
373 } else {
374 sensitiveVolumeNames.push_back(vol);
375 }
376 }
377 }
378 return sensitiveVolumeNames;
379}
380
381} // namespace mid
382} // namespace o2
Useful detector parameters for MID.
int32_t i
Useful geometrical parameters for MID.
Implementation of the MID materials definitions.
Implementation of the trigger-stations geometry.
GLint GLenum GLint x
Definition glcorearb.h:403
GLsizei GLenum GLenum * types
Definition glcorearb.h:2516
GLuint const GLchar * name
Definition glcorearb.h:781
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
constexpr int NChambers
Number of chambers.
constexpr int NRPCLines
Number of RPC lines.
int getDEId(bool isRight, int chamber, int rpc)
double getLocalBoardWidth(int chamber)
std::string getChamberVolumeName(int chamber)
constexpr double RPCCenterPos
Position of most RPCs in the right side of the first chamber.
double getLocalBoardHeight(int chamber)
constexpr double RPCZShift
Default shift of the RPC z position with respect to the average chamber position.
constexpr std::array< const double, 4 > DefaultChamberZ
Array of default z position of the chamber.
constexpr double RPCShortHalfLength
Half length of the short RPC in the first chamber.
constexpr double RPCHalfLength
Half length of most RPCs in the first chamber.
double getRPCHalfHeight(int chamber)
constexpr std::array< const double, 4 > ChamberScaleFactors
Array of scale factors for projective geometry.
double getRPCCenterPosX(int chamber, int rpc)
const float kHorizontalSupportHalfExtDim[]
Definition Geometry.cxx:61
const double kHorizontalSupportPos[]
Definition Geometry.cxx:63
const float kHorizontalSupportHalfIntDim[]
Definition Geometry.cxx:62
const float kAluminiumHalfThickness
Definition Geometry.cxx:52
std::vector< TGeoVolume * > getSensitiveVolumes()
get a list of MID sensitive volumes
Definition Geometry.cxx:359
void createMaterials()
Definition Materials.cxx:88
TGeoMedium * assertMedium(int imed)
@ Styrofoam
Definition Materials.h:35
@ Bakelite
Definition Materials.h:30
@ Aluminium
Definition Materials.h:32
const float kVerticalSupportHalfIntDim[]
Definition Geometry.cxx:57
const float kMylarHalfThickness
Definition Geometry.cxx:47
TGeoMatrix * getTransformation(const ROOT::Math::Transform3D &matrix)
Definition Geometry.cxx:256
const float kVerticalSupportHalfExtDim[]
Service parameters.
Definition Geometry.cxx:56
ROOT::Math::Transform3D getDefaultChamberTransform(int ichamber)
const float kSpacerHalfThickness
Definition Geometry.cxx:39
TGeoVolume * createRPC(geoparams::RPCtype type, int iChamber)
Definition Geometry.cxx:91
TGeoVolume * createHorizontalSupport(int iChamber)
Definition Geometry.cxx:78
void createGeometry(TGeoVolume &topVolume)
create MID geometry and attach it to existing topVolume
Definition Geometry.cxx:347
const float kElectrodHalfThickness
Definition Geometry.cxx:40
ROOT::Math::Transform3D getDefaultRPCTransform(bool isRight, int chamber, int rpc)
const float kStyrofoamHalfThickness
Definition Geometry.cxx:46
const float kVerticalSupportXPos[]
Definition Geometry.cxx:58
const float kCopperHalfThickness
Definition Geometry.cxx:48
const float kNomexHalfThickness
Definition Geometry.cxx:51
TGeoVolume * createVerticalSupport(int iChamber)
Definition Geometry.cxx:65
const float kGasHalfThickness
RPC thickness.
Definition Geometry.cxx:38
TGeoVolume * createChamber(int iChamber)
Definition Geometry.cxx:269
const float kInsulatorHalfThickness
Definition Geometry.cxx:43
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...