Project
Loading...
Searching...
No Matches
Detector.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
14#include "TPCSimulation/Point.h"
17
18#include "DetectorsBase/Stack.h"
21#include "SimConfig/G4Params.h"
22
23#include "FairVolume.h" // for FairVolume
24
25#include "TVirtualMC.h" // for TVirtualMC, gMC
26
27#include <cstddef> // for NULL
28
29#include "FairRun.h"
30#include <fairlogger/Logger.h>
31#include "FairRootManager.h"
32
33#include "TSystem.h"
34#include "TVirtualMC.h"
35
36#include "TFile.h"
37
38// geo stuff
39#include "TGeoManager.h"
40#include "TGeoVolume.h"
41#include "TGeoPcon.h"
42#include "TGeoTube.h"
43#include "TGeoCone.h"
44#include "TGeoPgon.h"
45#include "TGeoTrd1.h"
46#include "TGeoCompositeShape.h"
47#include "TGeoPara.h"
48#include "TGeoPhysicalNode.h"
49#include "TGeoArb8.h"
50#include "TGeoMatrix.h"
51
53
54#include <iostream>
55#include <cmath>
57
58using std::cout;
59using std::endl;
60using std::ifstream;
61using std::ios_base;
62using namespace o2::tpc;
63
64namespace
65{
66// Half-size of the boxes standing in for the half-space cuts of the TPC support structures.
67// Ten times the largest solid any of them is subtracted from, and small compared to the TPC.
68constexpr double kHalfSpaceReach = 100.;
69} // namespace
70
71Detector::Detector(Bool_t active) : o2::base::DetImpl<Detector>("TPC", active), mGeoFileName()
72{
73 for (int i = 0; i < Sector::MAXSECTOR; ++i) {
74 mHitsPerSectorCollection[i] = o2::utils::createSimVector<o2::tpc::HitGroup>(); // new std::vector<o2::tpc::HitGroup>;
75 }
76}
77
78// forward default constructor
79Detector::Detector() : o2::tpc::Detector(kTRUE) {}
80
82 : o2::base::DetImpl<Detector>(rhs),
83 mHitCounter(0),
84 mElectronCounter(0),
85 mStepCounter(0),
86 mGeoFileName(rhs.mGeoFileName)
87{
88 for (int i = 0; i < Sector::MAXSECTOR; ++i) {
89 mHitsPerSectorCollection[i] = o2::utils::createSimVector<o2::tpc::HitGroup>(); // new std::vector<o2::tpc::HitGroup>;new std::vector<o2::tpc::HitGroup>;
90 }
91}
92
94{
95 for (int i = 0; i < Sector::MAXSECTOR; ++i) {
96 // mHitsPerSectorCollection[i]->clear();
97 o2::utils::freeSimVector(mHitsPerSectorCollection[i]);
98 }
99 std::cout << "Produced hits " << mHitCounter << "\n";
100 std::cout << "Produced electrons " << mElectronCounter << "\n";
101 std::cout << "Stepping called " << mStepCounter << "\n";
102}
103
105{
106 // Define the list of sensitive volumes
107 defineSensitiveVolumes();
108}
109
111{
112 mStepCounter++;
113 auto& gasParam = ParameterGas::Instance();
114 auto& detParam = ParameterDetector::Instance();
115 const Int_t kMaxDistRef = 15; // maximal difference between 2 stored references - the parameter should be 15 cm as default
116
117 /* This method is called from the MC stepping for the sensitive volume only */
118 // LOG(info) << "tpc::ProcessHits";
119 const double trackCharge = fMC->TrackCharge();
120 // Magnetic monopoles have zero electric charge but ionise the gas through
121 // their magnetic charge energy loss (G4mplIonisation), so they must not be
122 // rejected by the electric-charge gate. The PDG lookup is only worth doing for neutral particle
123 // To-do: add dyons case
124 bool isMonopole = false;
125 if (static_cast<int>(trackCharge) == 0) {
126 static const bool sMonopoleIonisation = o2::conf::G4Params::Instance().monopole;
127 isMonopole = sMonopoleIonisation && o2::sim::isMonopole(fMC->TrackPid());
128 if (!isMonopole) {
129 // set a very large step size for neutral particles
130 fMC->SetMaxStep(1.e10);
131 return kFALSE; // take only charged particles
132 }
133 if (fMC->Edep() <= 0.) {
134 // An ionising monopole depositing nothing on this step: there
135 // is no hit to create, and the step limit is deliberately left alone
136 return kFALSE;
137 }
138 }
139
140 // ===| SET THE LENGTH OF THE NEXT ENERGY LOSS STEP |=========================
141 // (We do this first so we can skip out of the method in the following
142 // Eloss->Ionization part.)
143 //
144 // In all cases we have multiple collisions and we use 2mm (+ some
145 // random shift to avoid binning effects), which was tuned for GEANT4, see
146 // https://indico.cern.ch/event/316891/contributions/732168/
147
148 const double rnd = o2::base::simRandom()->Rndm();
149 fMC->SetMaxStep(0.2 + (2. * rnd - 1.) * 0.05); // 2 mm +- rndm*0.5mm step
150
151 // ===| check active sector |=================================================
152 //
153 // Get the sector ID and check if the sector is active
154 static thread_local TLorentzVector position;
155 fMC->TrackPosition(position);
156 // for processing reasons in the digitizer, the sectors are shifted by -10deg, so sector 0 will be
157 // from -10 - +10 deg instead of 0-20 and so on
158 const int sectorID = static_cast<int>(Sector::ToShiftedSector(position.X(), position.Y(), position.Z()));
159 // const int sectorID = static_cast<int>(Sector::ToSector(position.X(), position.Y(), position.Z()));
160 // TODO: Temporary hack to process only one sector
161 // if (sectorID != 0) return kFALSE;
162
163 // ---| momentum and beta gamma |---
164 TLorentzVector momentum;
165 fMC->TrackMomentum(momentum);
166
167 const float time = fMC->TrackTime() * 1.0e9;
168 const int trackID = fMC->GetStack()->GetCurrentTrackNumber();
169 o2::data::Stack* stack = (o2::data::Stack*)fMC->GetStack();
170 if (fMC->IsTrackEntering() || fMC->IsTrackExiting()) {
171 stack->addTrackReference(o2::TrackReference(position.X(), position.Y(), position.Z(), momentum.X(), momentum.Y(),
172 momentum.Z(), fMC->TrackLength(), time, trackID, GetDetId()));
173 mLastReferenceR = fMC->TrackLength();
174 }
175 if (TMath::Abs(mLastReferenceR - fMC->TrackLength()) > kMaxDistRef) {
176 stack->addTrackReference(o2::TrackReference(position.X(), position.Y(), position.Z(), momentum.X(), momentum.Y(),
177 momentum.Z(), fMC->TrackLength(), time, trackID, GetDetId()));
178 mLastReferenceR = fMC->TrackLength();
179 }
180
181 // ---| remove clusters between the IFC and the FC strips |---
182 // those should not enter the active readout area
183 // do coarse selection before, to limit number of transformations
184 if (detParam.ExcludeFCGap) {
185 const auto rCluster = std::sqrt(position.X() * position.X() + position.Y() * position.Y());
186 const float rodRin = 81.5 + 2.2; // radial position of the inner field cage rods + radial size of the field cage rods
187 const float rodRout = 254.25 + 2.2; // radial position of the outer field cage rods + radial size of the field cage rods
188 const float fcLxIn = 82.428409; // position of the inner FC strips in local x = cos(10 deg) * rodRin;
189 const float fcLxOut = 252.55395; // position of the outer FC strips in local x = cos(10 deg) * rodRin;
190
191 if (rCluster < rodRin || rCluster > fcLxOut) {
192 const int sectorIDnonShift = static_cast<int>(Sector::ToSector(position.X(), position.Y(), position.Z()));
193 const double alpha = TMath::DegToRad() * (10. + sectorIDnonShift * 20.);
194 const double cs = std::cos(-alpha), sn = std::sin(-alpha);
195 const auto localX = position.X() * cs - position.Y() * sn;
196 // fine cut
197 if (localX < fcLxIn || localX > fcLxOut) {
198 return kFALSE;
199 }
200 }
201 }
202
203 // ===| CONVERT THE ENERGY LOSS TO IONIZATION ELECTRONS |=====================
204 //
205 // The energy loss is implemented directly below and taken GEANT3,
206 // ILOSS model 5 (in gfluct.F), which gives
207 // the energy loss in a single collision (NA49 model).
208 // TODO: Add discussion about drawback
209
210 Int_t numberOfElectrons = 0;
211 // I.H. - the type expected in addHit is float
212
213 // use Geant4 energy deposit directly for ionisation (Kr-83m calibration simulations)
214 if (detParam.UseGeant4Edep) {
215 // We have multiple collisions and add fluctuations: smear nel using
216 // gamma distr with mean = meanIon and variance = meanIon*FanoFactorG4.
217 // These parameters were tuned for GEANT4.
218 const double meanIon = fMC->Edep() / (gasParam.Wion * gasParam.ScaleFactorG4);
219 if (meanIon > 0.) {
220 numberOfElectrons = static_cast<int>(gasParam.FanoFactorG4 * Gamma(meanIon / gasParam.FanoFactorG4));
221 }
222 } else if (isMonopole) {
223 // ---| MONOPOLE IONISATION |--------
224 // A magnetic monopole ionises the gas via G4mplIonisation (Ahlen stopping
225 // power), which is not described by the electric-charge model (no e-charge)
226 // Ionisation electrons calculated directly from the energy deposited in this step: Nel = Edep / Wion.
227 // To check by TPC experts if this is actually the best way...
228 numberOfElectrons = static_cast<int>(fMC->Edep() / static_cast<double>(gasParam.Wion));
229 // The number of electrons is stored as a float in the HitGroup: maximum cap at
230 // 2^24 (16777216) ==> largest integer a IEEE-754 float can represent exactly
231 numberOfElectrons = TMath::Min(numberOfElectrons, 16777216);
232 } else {
233 // ---| Stepsize in cm |---
234 const double stepSize = fMC->TrackStep();
235
236 double betaGamma = momentum.P() / fMC->TrackMass();
237 betaGamma = TMath::Max(betaGamma, 7.e-3); // protection against too small bg
238
239 // ---| number of primary ionisations per cm |---
240 const double primaryElectronsPerCM =
241 gasParam.Nprim * BetheBlochAleph(static_cast<float>(betaGamma), gasParam.BetheBlochParam[0],
242 gasParam.BetheBlochParam[1], gasParam.BetheBlochParam[2],
243 gasParam.BetheBlochParam[3], gasParam.BetheBlochParam[4]);
245 // ---| mean number of collisions and random for this event |---
246 const double meanNcoll = stepSize * trackCharge * trackCharge * primaryElectronsPerCM;
247 const int nColl = static_cast<int>(o2::base::simRandom()->Poisson(meanNcoll));
248
249 // Variables needed to generate random powerlaw distributed energy loss
250 const double alpha_p1 = 1. - gasParam.Exp; // NA49/G3 value
251 const double oneOverAlpha_p1 = 1. / alpha_p1;
252 const double eMin = gasParam.Ipot;
253 const double eMax = gasParam.Eend;
254 const double kMin = TMath::Power(eMin, alpha_p1);
255 const double kMax = TMath::Power(eMax, alpha_p1);
256 const double wIon = gasParam.Wion;
257
258 for (Int_t n = 0; n < nColl; n++) {
259 // Use GEANT3 / NA49 expression:
260 // P(eDep) ~ k * edep^-gasParam.getExp()
261 // eMin(~I) < eDep < eMax(300 electrons)
262 // k fixed so that Int_Emin^EMax P(Edep) = 1.
263 const double rndm = o2::base::simRandom()->Rndm();
264 const double eDep = TMath::Power((kMax - kMin) * rndm + kMin, oneOverAlpha_p1);
265 int nel_step = static_cast<int>(((eDep - eMin) / wIon) + 1);
266 nel_step = TMath::Min(nel_step, gasParam.MaxElePerStep); // 300 electrons corresponds to 10 keV
267 numberOfElectrons += nel_step;
268 }
269 }
270
271 // LOG(info) << "tpc::AddHit" << FairLogger::endl << "Eloss: "
272 //<< fMC->Edep() << ", Nelectrons: "
273 //<< numberOfElectrons;
274
275 if (numberOfElectrons <= 0) { // Could maybe be smaller than 0 due to the Gamma function
276 return kFALSE;
277 }
278
279 // ADD HIT
280 // the first hit of an event starts the grouping afresh
281 if (!mCurrentGroup) {
282 mOldTrackId = trackID;
283 mOldSectorId = sectorID;
284 mGroupCounter = 0;
285 }
286
287 // a new group is starting -> put it into the container
288 if (mGroupCounter == 0) {
289 mHitsPerSectorCollection[sectorID]->emplace_back(trackID);
290 mCurrentGroup = &(mHitsPerSectorCollection[sectorID]->back());
291 }
292 if (trackID == mOldTrackId && mOldSectorId == sectorID) {
293 mGroupCounter++;
294 mHitCounter++;
295 mElectronCounter += numberOfElectrons;
296 mCurrentGroup->addHit(position.X(), position.Y(), position.Z(), time, numberOfElectrons);
297
298 // add last buffered hit, which was not yet added to the current group
299 if (mHitLast.GetEnergyLoss() >= 0) {
300 mCurrentGroup->addHit(mHitLast.GetX(), mHitLast.GetY(), mHitLast.GetZ(), mHitLast.GetTime(), mHitLast.GetEnergyLoss());
301 mGroupCounter++;
302 mHitCounter++;
303 mElectronCounter += mHitLast.GetEnergyLoss();
304 mHitLast.mELoss = -1;
305 }
306 }
307 // finish group
308 else {
309 mOldTrackId = trackID;
310 mOldSectorId = sectorID;
311 mGroupCounter = 0;
312
313 // buffer this hit, otherwise it wouldnt be stored in the HitGroup
314 mHitLast = ElementalHit(position.X(), position.Y(), position.Z(), time, numberOfElectrons);
315 }
316
317 // LOG(info) << "tpc::AddHit" << FairLogger::endl
318 //<< " -- " << trackNumberID <<"," << volumeID << " " << vol->GetName()
319 //<< ", Pos: (" << position.X() << ", " << position.Y() <<", "<< position.Z()<< ", " << r << ") "
320 //<< ", Mom: (" << momentum.Px() << ", " << momentum.Py() << ", " << momentum.Pz() << ") "
321 //<< " Time: "<< time <<", Len: " << length << ", Nelectrons: " <<
322 // numberOfElectrons;
323 // I.H. - the code above does not compile if uncommented
324
325 // Increment number of Detector det points in TParticle
326 stack->addHit(GetDetId());
327
328 return kTRUE;
329}
330
332{
333 // the hit grouping must not carry over into the next event
334 mCurrentGroup = nullptr;
335 mHitLast.mELoss = -1;
336 if (!o2::utils::ShmManager::Instance().isOperational()) {
337 for (int i = 0; i < Sector::MAXSECTOR; ++i) {
338 mHitsPerSectorCollection[i]->clear();
339 }
340 }
341}
342
344{
351 auto* mgr = FairRootManager::Instance();
352 for (int i = 0; i < Sector::MAXSECTOR; ++i) {
353 mgr->RegisterAny(getHitBranchNames(i).c_str(), mHitsPerSectorCollection[i], kTRUE);
354 }
355}
356
358{
359 for (int i = 0; i < Sector::MAXSECTOR; ++i) {
360 // cout << "CLEARED (reset) hitsCollection " << i << " " << mHitsPerSectorCollection[i] << endl;
361 mHitsPerSectorCollection[i]->clear();
362 }
363}
364
366{
367 // Create the detector materials
368 CreateMaterials();
369
370 // Load geometry
371 // LoadGeometryFromFile();
372 ConstructTPCGeometry();
373}
374
375void Detector::CreateMaterials()
376{
377 //-----------------------------------------------
378 // Create Materials for for TPC simulations
379 //-----------------------------------------------
380
381 //-----------------------------------------------------------------
382 // Origin: Marek Kowalski IFJ, Krakow, Marek.Kowalski@ifj.edu.pl
383 //-----------------------------------------------------------------
384
385 const auto& gasParam = ParameterGas::Instance();
386
387 Int_t iSXFLD = 2;
388 Float_t sXMGMX = 10.0;
389 // init the field tracking params
391
392 Float_t amat[7]; // atomic numbers
393 Float_t zmat[7]; // z
394 Float_t wmat[7]; // proportions
395
396 Float_t density;
397
398 // TODO: load pressure and temperature values from CCDB
399 const Double_t pressure = gasParam.Pressure; // in mbar
400 const Double_t temperature = gasParam.Temperature + 273.15; // in K
401
402 // densities were taken for these values
403 const Double_t t1 = 293.15; // 20°C in K
404 const Double_t p1 = 1013.25; // 1 atm in mbars
405
406 // sanity check - temperature between 10 and 30 deg, pressure between 800 and 1200 mbar
407 Double_t ptCorr = 1.;
408 if (TMath::Abs(temperature - 293.15) > 10. || TMath::Abs(pressure - 1000.) > 200.) {
409 ptCorr = 1.;
410 } else {
411 ptCorr = (pressure * t1) / (p1 * temperature);
412 }
413 LOG(info) << "Setting gas density correction to: " << ptCorr;
414
415 //***************** Gases *************************
416
417 //--------------------------------------------------------------
418 // gases - air and CO2
419 //--------------------------------------------------------------
420
421 // CO2
422
423 amat[0] = 12.011;
424 amat[1] = 15.9994;
425
426 zmat[0] = 6.;
427 zmat[1] = 8.;
428
429 wmat[0] = 0.2729;
430 wmat[1] = 0.7271;
431
432 density = 1.842e-3;
433
434 o2::base::Detector::Mixture(10, "CO2", amat, zmat, density * ptCorr, 2, wmat);
435 //
436 // Air
437 //
438 amat[0] = 15.9994;
439 amat[1] = 14.007;
440 //
441 zmat[0] = 8.;
442 zmat[1] = 7.;
443 //
444 wmat[0] = 0.233;
445 wmat[1] = 0.767;
446 //
447 density = 0.001205;
448
449 o2::base::Detector::Mixture(11, "Air", amat, zmat, density * ptCorr, 2, wmat);
450
451 //----------------------------------------------------------------
452 // drift gases 5 mixtures, 5 materials
453 //----------------------------------------------------------------
454 //
455 // Drift gases 1 - nonsensitive, 2 - sensitive, 3 - for Kr
456 // Composition by % of volume, values at 20deg and 1 atm.
457 //
458 // get the geometry title - defined in Config.C
459 //
460 //--------------------------------------------------------------
461 // predefined gases, composition taken from param file
462 //--------------------------------------------------------------
463 TString names[6] = {"Ne", "Ar", "CO2", "N", "CF4", "CH4"};
464 TString gname;
465
467 // container in the future
468 Float_t comp[6] = {90. / 105., 0., 10. / 105., 5. / 105., 0., 0.};
469 // indices:
470 // 0-Ne, 1-Ar, 2-CO2, 3-N, 4-CF4, 5-CH4
471 //
472 // elements' masses
473 //
474 amat[0] = 20.18; // Ne
475 amat[1] = 39.95; // Ar
476 amat[2] = 12.011; // C
477 amat[3] = 15.9994; // O
478 amat[4] = 14.007; // N
479 amat[5] = 18.998; // F
480 amat[6] = 1.; // H
481 //
482 // elements' atomic numbers
483 //
484 //
485 zmat[0] = 10.; // Ne
486 zmat[1] = 18.; // Ar
487 zmat[2] = 6.; // C
488 zmat[3] = 8.; // O
489 zmat[4] = 7.; // N
490 zmat[5] = 9.; // F
491 zmat[6] = 1.; // H
492 //
493 // Mol masses
494 //
495 Float_t wmol[6];
496 wmol[0] = 20.18; // Ne
497 wmol[1] = 39.948; // Ar
498 wmol[2] = 44.0098; // CO2
499 wmol[3] = 2. * 14.0067; // N2
500 wmol[4] = 88.0046; // CF4
501 wmol[5] = 16.011; // CH4
502 //
503 Float_t wtot = 0.; // total mass of the mixture
504 for (Int_t i = 0; i < 6; i++) {
505 wtot += *(comp + i) * wmol[i];
506 }
507 wmat[0] = comp[0] * amat[0] / wtot; // Ne
508 wmat[1] = comp[1] * amat[1] / wtot; // Ar
509 wmat[2] = (comp[2] * amat[2] + comp[4] * amat[2] + comp[5] * amat[2]) / wtot; // C
510 wmat[3] = comp[2] * amat[3] * 2. / wtot; // O
511 wmat[4] = comp[3] * amat[4] * 2. / wtot; // N
512 wmat[5] = comp[4] * amat[5] * 4. / wtot; // F
513 wmat[6] = comp[5] * amat[6] * 4. / wtot; // H
514 //
515 // densities (NTP)
516 //
517 Float_t dens[6] = {0.839e-3, 1.661e-3, 1.842e-3, 1.165e-3, 3.466e-3, 0.668e-3};
518 //
519 density = 0.;
520 for (Int_t i = 0; i < 6; i++) {
521 density += comp[i] * dens[i];
522 }
523 //
524 // names
525 //
526 Int_t cnt = 0;
527 for (Int_t i = 0; i < 6; i++) {
528 if (comp[i]) {
529 if (cnt) {
530 gname += "-";
531 }
532 gname += names[i];
533 cnt++;
534 }
535 }
536 TString gname1, gname2, gname3;
537 gname1 = gname + "-1";
538 gname2 = gname + "-2";
539 gname3 = gname + "-3";
540 //
541 // take only elements with nonzero weights
542 //
543 Float_t amat1[6], zmat1[6], wmat1[6];
544 cnt = 0;
545 for (Int_t i = 0; i < 7; i++) {
546 if (wmat[i]) {
547 zmat1[cnt] = zmat[i];
548 amat1[cnt] = amat[i];
549 wmat1[cnt] = wmat[i];
550 cnt++;
551 }
552 }
553
554 //
555 o2::base::Detector::Mixture(12, gname1.Data(), amat1, zmat1, density * ptCorr, cnt, wmat1); // nonsensitive
556 o2::base::Detector::Mixture(13, gname2.Data(), amat1, zmat1, density * ptCorr, cnt, wmat1); // sensitive
557 o2::base::Detector::Mixture(40, gname3.Data(), amat1, zmat1, density * ptCorr, cnt, wmat1); // sensitive Kr
558
559 //----------------------------------------------------------------------
560 // solid materials
561 //----------------------------------------------------------------------
562
563 // Kevlar C14H22O2N2
564
565 amat[0] = 12.011;
566 amat[1] = 1.;
567 amat[2] = 15.999;
568 amat[3] = 14.006;
569
570 zmat[0] = 6.;
571 zmat[1] = 1.;
572 zmat[2] = 8.;
573 zmat[3] = 7.;
574
575 wmat[0] = 14.;
576 wmat[1] = 22.;
577 wmat[2] = 2.;
578 wmat[3] = 2.;
579
580 density = 1.45;
581
582 o2::base::Detector::Mixture(14, "Kevlar", amat, zmat, density, -4, wmat);
583
584 // NOMEX
585
586 amat[0] = 12.011;
587 amat[1] = 1.;
588 amat[2] = 15.999;
589 amat[3] = 14.006;
590
591 zmat[0] = 6.;
592 zmat[1] = 1.;
593 zmat[2] = 8.;
594 zmat[3] = 7.;
595
596 wmat[0] = 14.;
597 wmat[1] = 22.;
598 wmat[2] = 2.;
599 wmat[3] = 2.;
600
601 density = 0.029;
602
603 o2::base::Detector::Mixture(15, "NOMEX", amat, zmat, density, -4, wmat);
604
605 // Makrolon C16H18O3
606
607 amat[0] = 12.011;
608 amat[1] = 1.;
609 amat[2] = 15.999;
610
611 zmat[0] = 6.;
612 zmat[1] = 1.;
613 zmat[2] = 8.;
614
615 wmat[0] = 16.;
616 wmat[1] = 18.;
617 wmat[2] = 3.;
618
619 density = 1.2;
620
621 o2::base::Detector::Mixture(16, "Makrolon", amat, zmat, density, -3, wmat);
622
623 // Tedlar C2H3F
624
625 amat[0] = 12.011;
626 amat[1] = 1.;
627 amat[2] = 18.998;
628
629 zmat[0] = 6.;
630 zmat[1] = 1.;
631 zmat[2] = 9.;
632
633 wmat[0] = 2.;
634 wmat[1] = 3.;
635 wmat[2] = 1.;
636
637 density = 1.71;
638
639 o2::base::Detector::Mixture(17, "Tedlar", amat, zmat, density, -3, wmat);
640
641 // Mylar C5H4O2
642
643 amat[0] = 12.011;
644 amat[1] = 1.;
645 amat[2] = 15.9994;
646
647 zmat[0] = 6.;
648 zmat[1] = 1.;
649 zmat[2] = 8.;
650
651 wmat[0] = 5.;
652 wmat[1] = 4.;
653 wmat[2] = 2.;
654
655 density = 1.39;
656
657 o2::base::Detector::Mixture(18, "Mylar", amat, zmat, density, -3, wmat);
658 // material for "prepregs"
659 // Epoxy - C14 H20 O3
660 // Quartz SiO2
661 // Carbon C
662 // prepreg1 60% C-fiber, 40% epoxy (vol)
663 amat[0] = 12.011;
664 amat[1] = 1.;
665 amat[2] = 15.994;
666
667 zmat[0] = 6.;
668 zmat[1] = 1.;
669 zmat[2] = 8.;
670
671 wmat[0] = 0.923;
672 wmat[1] = 0.023;
673 wmat[2] = 0.054;
674
675 density = 1.859;
676
677 o2::base::Detector::Mixture(19, "Prepreg1", amat, zmat, density, 3, wmat);
678
679 // prepreg2 60% glass-fiber, 40% epoxy
680
681 amat[0] = 12.01;
682 amat[1] = 1.;
683 amat[2] = 15.994;
684 amat[3] = 28.086;
685
686 zmat[0] = 6.;
687 zmat[1] = 1.;
688 zmat[2] = 8.;
689 zmat[3] = 14.;
690
691 wmat[0] = 0.194;
692 wmat[1] = 0.023;
693 wmat[2] = 0.443;
694 wmat[3] = 0.34;
695
696 density = 1.82;
697
698 o2::base::Detector::Mixture(20, "Prepreg2", amat, zmat, density, 4, wmat);
699
700 // prepreg3 50% glass-fiber, 50% epoxy
701
702 amat[0] = 12.01;
703 amat[1] = 1.;
704 amat[2] = 15.994;
705 amat[3] = 28.086;
706
707 zmat[0] = 6.;
708 zmat[1] = 1.;
709 zmat[2] = 8.;
710 zmat[3] = 14.;
711
712 wmat[0] = 0.257;
713 wmat[1] = 0.03;
714 wmat[2] = 0.412;
715 wmat[3] = 0.3;
716
717 density = 1.725;
718
719 o2::base::Detector::Mixture(21, "Prepreg3", amat, zmat, density, 4, wmat);
720
721 // G10 60% SiO2 40% epoxy
722
723 amat[0] = 12.01;
724 amat[1] = 1.;
725 amat[2] = 15.994;
726 amat[3] = 28.086;
727
728 zmat[0] = 6.;
729 zmat[1] = 1.;
730 zmat[2] = 8.;
731 zmat[3] = 14.;
732
733 wmat[0] = 0.194;
734 wmat[1] = 0.023;
735 wmat[2] = 0.443;
736 wmat[3] = 0.340;
737
738 density = 1.7;
739
740 o2::base::Detector::Mixture(22, "G10", amat, zmat, density, 4, wmat);
741
742 // Al
743
744 amat[0] = 26.98;
745 zmat[0] = 13.;
746
747 density = 2.7;
748
749 o2::base::Detector::Material(23, "Al", amat[0], zmat[0], density, 999., 999.);
750
751 // Si (for electronics
752
753 amat[0] = 28.086;
754 zmat[0] = 14.;
755
756 density = 2.33;
757
758 o2::base::Detector::Material(24, "Si", amat[0], zmat[0], density, 999., 999.);
759
760 // Cu
761
762 amat[0] = 63.546;
763 zmat[0] = 29.;
764
765 density = 8.96;
766
767 o2::base::Detector::Material(25, "Cu", amat[0], zmat[0], density, 999., 999.);
768
769 // brass
770
771 amat[0] = 63.546;
772 zmat[0] = 29.;
773 //
774 amat[1] = 65.409;
775 zmat[1] = 30.;
776 //
777 wmat[0] = 0.6;
778 wmat[1] = 0.4;
779
780 //
781 density = 8.23;
782
783 //
784 o2::base::Detector::Mixture(33, "Brass", amat, zmat, density, 2, wmat);
785
786 // Epoxy - C14 H20 O3
787
788 amat[0] = 12.011;
789 amat[1] = 1.;
790 amat[2] = 15.9994;
791
792 zmat[0] = 6.;
793 zmat[1] = 1.;
794 zmat[2] = 8.;
795
796 wmat[0] = 14.;
797 wmat[1] = 20.;
798 wmat[2] = 3.;
799
800 density = 1.25;
801
802 o2::base::Detector::Mixture(26, "Epoxy", amat, zmat, density, -3, wmat);
803
804 // Epoxy - C14 H20 O3 for glue
805
806 amat[0] = 12.011;
807 amat[1] = 1.;
808 amat[2] = 15.9994;
809
810 zmat[0] = 6.;
811 zmat[1] = 1.;
812 zmat[2] = 8.;
813
814 wmat[0] = 14.;
815 wmat[1] = 20.;
816 wmat[2] = 3.;
817
818 density = 1.25;
819
820 density *= 1.25;
821
822 o2::base::Detector::Mixture(35, "Epoxy1", amat, zmat, density, -3, wmat);
823 //
824 // epoxy film - 90% epoxy, 10% glass fiber
825 //
826 amat[0] = 12.01;
827 amat[1] = 1.;
828 amat[2] = 15.994;
829 amat[3] = 28.086;
830
831 zmat[0] = 6.;
832 zmat[1] = 1.;
833 zmat[2] = 8.;
834 zmat[3] = 14.;
835
836 wmat[0] = 0.596;
837 wmat[1] = 0.071;
838 wmat[2] = 0.257;
839 wmat[3] = 0.076;
840
841 density = 1.345;
842
843 o2::base::Detector::Mixture(34, "Epoxy-film", amat, zmat, density, 4, wmat);
844
845 // Plexiglas C5H8O2
846
847 amat[0] = 12.011;
848 amat[1] = 1.;
849 amat[2] = 15.9994;
850
851 zmat[0] = 6.;
852 zmat[1] = 1.;
853 zmat[2] = 8.;
854
855 wmat[0] = 5.;
856 wmat[1] = 8.;
857 wmat[2] = 2.;
858
859 density = 1.18;
860
861 o2::base::Detector::Mixture(27, "Plexiglas", amat, zmat, density, -3, wmat);
862
863 // Carbon
864
865 amat[0] = 12.011;
866 zmat[0] = 6.;
867 density = 2.265;
868
869 o2::base::Detector::Material(28, "C", amat[0], zmat[0], density, 999., 999.);
870
871 // Fe (steel for the inner heat screen)
872
873 amat[0] = 55.845;
874
875 zmat[0] = 26.;
876
877 density = 7.87;
878
879 o2::base::Detector::Material(29, "Fe", amat[0], zmat[0], density, 999., 999.);
880 //
881 // Peek - (C6H4-O-OC6H4-O-C6H4-CO)n
882 amat[0] = 12.011;
883 amat[1] = 1.;
884 amat[2] = 15.9994;
885
886 zmat[0] = 6.;
887 zmat[1] = 1.;
888 zmat[2] = 8.;
889
890 wmat[0] = 19.;
891 wmat[1] = 12.;
892 wmat[2] = 3.;
893 //
894 density = 1.3;
895 //
896 o2::base::Detector::Mixture(30, "Peek", amat, zmat, density, -3, wmat);
897 //
898 // Ceramics - Al2O3
899 //
900 amat[0] = 26.98;
901 amat[1] = 15.9994;
902
903 zmat[0] = 13.;
904 zmat[1] = 8.;
905
906 wmat[0] = 2.;
907 wmat[1] = 3.;
908
909 density = 3.97;
910
911 o2::base::Detector::Mixture(31, "Alumina", amat, zmat, density, -2, wmat);
912 //
913 // Ceramics for resistors
914 //
915 amat[0] = 26.98;
916 amat[1] = 15.9994;
917
918 zmat[0] = 13.;
919 zmat[1] = 8.;
920
921 wmat[0] = 2.;
922 wmat[1] = 3.;
923
924 density = 3.97;
925 //
926 density *= 1.25;
927
928 o2::base::Detector::Mixture(36, "Alumina1", amat, zmat, density, -2, wmat);
929 //
930 // liquids
931 //
932
933 // water
934
935 amat[0] = 1.;
936 amat[1] = 15.9994;
937
938 zmat[0] = 1.;
939 zmat[1] = 8.;
940
941 wmat[0] = 2.;
942 wmat[1] = 1.;
943
944 density = 1.;
945
946 o2::base::Detector::Mixture(32, "Water", amat, zmat, density, -2, wmat);
947
948 //----------------------------------------------------------
949 // tracking media for gases
950 //----------------------------------------------------------
951
952 o2::base::Detector::Medium(kAir, "Air", 11, 0, iSXFLD, sXMGMX, 10., 999., .1, .01, .1);
953 o2::base::Detector::Medium(kDriftGas1, "DriftGas1", 12, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
954 o2::base::Detector::Medium(kDriftGas2, "DriftGas2", 13, 1, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
955 o2::base::Detector::Medium(kCO2, "CO2", 10, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
956 o2::base::Detector::Medium(kDriftGas3, "DriftGas3", 40, 1, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
957 //-----------------------------------------------------------
958 // tracking media for solids
959 //-----------------------------------------------------------
960
961 o2::base::Detector::Medium(kAl, "Al", 23, 0, iSXFLD, sXMGMX, 10., 999., .1, .0005, .001);
962 o2::base::Detector::Medium(kKevlar, "Kevlar", 14, 0, iSXFLD, sXMGMX, 10., 999., .1, .0005, .001);
963 o2::base::Detector::Medium(kNomex, "Nomex", 15, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
964 o2::base::Detector::Medium(kMakrolon, "Makrolon", 16, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
965 o2::base::Detector::Medium(kMylar, "Mylar", 18, 0, iSXFLD, sXMGMX, 10., 999., .1, .0005, .001);
966 o2::base::Detector::Medium(kTedlar, "Tedlar", 17, 0, iSXFLD, sXMGMX, 10., 999., .1, .0005, .001);
967 //
968 o2::base::Detector::Medium(kPrepreg1, "Prepreg1", 19, 0, iSXFLD, sXMGMX, 10., 999., .1, .0005, .001);
969 o2::base::Detector::Medium(kPrepreg2, "Prepreg2", 20, 0, iSXFLD, sXMGMX, 10., 999., .1, .0005, .001);
970 o2::base::Detector::Medium(kPrepreg3, "Prepreg3", 21, 0, iSXFLD, sXMGMX, 10., 999., .1, .0005, .001);
971 o2::base::Detector::Medium(kEpoxy, "Epoxy", 26, 0, iSXFLD, sXMGMX, 10., 999., .1, .0005, .001);
972
973 o2::base::Detector::Medium(kCu, "Cu", 25, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
974 o2::base::Detector::Medium(kSi, "Si", 24, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
975 o2::base::Detector::Medium(kG10, "G10", 22, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
976 o2::base::Detector::Medium(kPlexiglas, "Plexiglas", 27, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
977 o2::base::Detector::Medium(kSteel, "Steel", 29, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
978 o2::base::Detector::Medium(kPeek, "Peek", 30, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
979 o2::base::Detector::Medium(kAlumina, "Alumina", 31, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
980 o2::base::Detector::Medium(kWater, "Water", 32, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
981 o2::base::Detector::Medium(kBrass, "Brass", 33, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
982 o2::base::Detector::Medium(kEpoxyfm, "Epoxyfm", 34, 0, iSXFLD, sXMGMX, 10., 999., .1, .0005, .001);
983 o2::base::Detector::Medium(kEpoxy1, "Epoxy1", 35, 0, iSXFLD, sXMGMX, 10., 999., .1, .0005, .001);
984 o2::base::Detector::Medium(kAlumina1, "Alumina1", 36, 0, iSXFLD, sXMGMX, 10., 999., .1, .001, .001);
985}
986
987void Detector::ConstructTPCGeometry()
988{
989 //
990 // Create the geometry of Time Projection Chamber version 2
991 //
992 // Begin_Html
993 /*
994 * <img src="picts/AliTPC.gif">
995 */
996 // End_Html
997 // Begin_Html
998 /*
999 * <img src="picts/AliTPCv2Tree.gif">
1000 */
1001 // End_Html
1002
1003 //----------------------------------------------------------
1004 // This geometry is written using TGeo class
1005 // Firstly the shapes are defined, and only then the volumes
1006 // What is recognized by the MC are volumes
1007 //----------------------------------------------------------
1008 //
1009 // tpc - this will be the mother volume
1010 //
1011
1012 // if (!mParam) {
1013 // LOG(error) << "TPC Parameters not available, cannot create Geometry";
1014 // return;
1015 // }
1016
1017 //
1018 // here I define a volume TPC
1019 // retrive the medium name with "TPC_" as a leading string
1020 //
1021 auto* tpc = new TGeoPcon(0., 360., 30); // 30 sections
1022 //
1023 tpc->DefineSection(0, -289.6, 77., 278.);
1024 tpc->DefineSection(1, -262.1, 77., 278.);
1025 //
1026 tpc->DefineSection(2, -262.1, 83.1, 278.);
1027 tpc->DefineSection(3, -260., 83.1, 278.);
1028 //
1029 tpc->DefineSection(4, -260., 70., 278.);
1030 tpc->DefineSection(5, -259.6, 70., 278.);
1031 //
1032 tpc->DefineSection(6, -259.6, 68.1, 278.);
1033 tpc->DefineSection(7, -253.6, 68.1, 278.);
1034 //
1035 tpc->DefineSection(8, -253.6, 67.88, 278.); // hs
1036 tpc->DefineSection(9, -74.0, 60.68, 278.); // hs
1037 //
1038 tpc->DefineSection(10, -74.0, 60.1, 278.);
1039 tpc->DefineSection(11, -73.3, 60.1, 278.);
1040 //
1041 tpc->DefineSection(12, -73.3, 56.9, 278.);
1042 tpc->DefineSection(13, -68.5, 56.9, 278.);
1043 //
1044 tpc->DefineSection(14, -68.5, 60., 278.);
1045 tpc->DefineSection(15, -64.7, 60., 278.);
1046 //
1047 tpc->DefineSection(16, -64.7, 56.9, 278.);
1048 tpc->DefineSection(17, 73.3, 56.9, 278.);
1049 //
1050 tpc->DefineSection(18, 73.3, 60.1, 278.);
1051 tpc->DefineSection(19, 74.0, 60.1, 278.);
1052 //
1053 tpc->DefineSection(20, 74.0, 60.68, 278.); // hs
1054 tpc->DefineSection(21, 253.6, 65.38, 278.); // hs
1055 //
1056 tpc->DefineSection(22, 253.6, 65.6, 278.);
1057 tpc->DefineSection(23, 259.6, 65.6, 278.);
1058 //
1059 tpc->DefineSection(24, 259.6, 70.0, 278.);
1060 tpc->DefineSection(25, 260., 70.0, 278.);
1061 //
1062 tpc->DefineSection(26, 260., 83.1, 278.);
1063 tpc->DefineSection(27, 262.1, 83.1, 278.);
1064 //
1065 tpc->DefineSection(28, 262.1, 77., 278);
1066 tpc->DefineSection(29, 289.6, 77., 278.);
1067 //
1068 TGeoMedium* m1 = gGeoManager->GetMedium("TPC_Air");
1069 auto* v1 = new TGeoVolume("TPC_M", tpc, m1);
1070 //
1071 // drift volume - sensitive volume, extended beyond the
1072 // endcaps, because of the alignment
1073 //
1074 auto* dvol = new TGeoPcon(0., 360., 6);
1075 dvol->DefineSection(0, -260., 74.5, 264.4);
1076 dvol->DefineSection(1, -253.6, 74.5, 264.4);
1077 //
1078 dvol->DefineSection(2, -253.6, 76.6774, 258.);
1079 dvol->DefineSection(3, 253.6, 76.6774, 258.);
1080 //
1081 dvol->DefineSection(4, 253.6, 74.5, 264.4);
1082 dvol->DefineSection(5, 260., 74.5, 264.4);
1083 //
1084 TGeoMedium* m5 = gGeoManager->GetMedium("TPC_DriftGas2");
1085 auto* v9 = new TGeoVolume("TPC_Drift", dvol, m5);
1086 //
1087 v1->AddNode(v9, 1);
1088 //
1089 // outer insulator
1090 //
1091 auto* tpco = new TGeoPcon(0., 360., 6); // insulator
1092 //
1093 tpco->DefineSection(0, -256.6, 264.8, 278.);
1094 tpco->DefineSection(1, -253.6, 264.8, 278.);
1095 //
1096 tpco->DefineSection(2, -253.6, 258., 278.);
1097 tpco->DefineSection(3, 250.6, 258., 278.);
1098 //
1099 tpco->DefineSection(4, 250.6, 258., 275.5);
1100 tpco->DefineSection(5, 253.6, 258., 275.5);
1101 //
1102 TGeoMedium* m2 = gGeoManager->GetMedium("TPC_CO2");
1103 auto* v2 = new TGeoVolume("TPC_OI", tpco, m2);
1104 //
1105 TGeoRotation* segrot; // segment rotations
1106 //
1107 // outer containment vessel
1108 //
1109 auto* tocv = new TGeoPcon(0., 360., 6); // containment vessel
1110 //
1111 tocv->DefineSection(0, -256.6, 264.8, 278.);
1112 tocv->DefineSection(1, -253.6, 264.8, 278.);
1113 //
1114 tocv->DefineSection(2, -253.6, 274.8124, 278.);
1115 tocv->DefineSection(3, 247.6, 274.8124, 278.);
1116 //
1117 tocv->DefineSection(4, 247.6, 270.4, 278.);
1118 tocv->DefineSection(5, 250.6, 270.4, 278.);
1119 //
1120 TGeoMedium* m3 = gGeoManager->GetMedium("TPC_Al");
1121 auto* v3 = new TGeoVolume("TPC_OCV", tocv, m3);
1122 //
1123 auto* to1 = new TGeoTubeSeg(274.8174, 277.995, 252.1, 0., 59.9); // epoxy
1124 auto* to2 = new TGeoTubeSeg(274.8274, 277.985, 252.1, 0., 59.9); // tedlar
1125 auto* to3 = new TGeoTubeSeg(274.8312, 277.9812, 252.1, 0., 59.9); // prepreg2
1126 auto* to4 = new TGeoTubeSeg(274.9062, 277.9062, 252.1, 0., 59.9); // nomex
1127 auto* tog5 = new TGeoTubeSeg(274.8174, 277.995, 252.1, 59.9, 60.); // epoxy
1128 //
1129 TGeoMedium* sm1 = gGeoManager->GetMedium("TPC_Epoxy");
1130 TGeoMedium* sm2 = gGeoManager->GetMedium("TPC_Tedlar");
1131 TGeoMedium* sm3 = gGeoManager->GetMedium("TPC_Prepreg2");
1132 TGeoMedium* sm4 = gGeoManager->GetMedium("TPC_Nomex");
1133 //
1134 TGeoMedium* smep = gGeoManager->GetMedium("TPC_Epoxy1");
1135 //
1136 auto* tov1 = new TGeoVolume("TPC_OCV1", to1, sm1);
1137 auto* tov2 = new TGeoVolume("TPC_OCV2", to2, sm2);
1138 auto* tov3 = new TGeoVolume("TPC_OCV3", to3, sm3);
1139 auto* tov4 = new TGeoVolume("TPC_OCV4", to4, sm4);
1140 auto* togv5 = new TGeoVolume("TPC_OCVG5", tog5, sm1);
1141 //
1142 TGeoMedium* mhs = gGeoManager->GetMedium("TPC_Steel");
1143 TGeoMedium* m12 = gGeoManager->GetMedium("TPC_Water");
1144 //-------------------------------------------------------
1145 // Tpc Outer Field Cage
1146 // daughters - composite (sandwich)
1147 //-------------------------------------------------------
1148
1149 auto* tofc = new TGeoPcon(0., 360., 6);
1150 //
1151 tofc->DefineSection(0, -253.6, 258., 269.6);
1152 tofc->DefineSection(1, -250.6, 258., 269.6);
1153 //
1154 tofc->DefineSection(2, -250.6, 258., 260.0676);
1155 tofc->DefineSection(3, 250.6, 258., 260.0676);
1156 //
1157 tofc->DefineSection(4, 250.6, 258., 275.5);
1158 tofc->DefineSection(5, 253.6, 258., 275.5);
1159 //
1160 auto* v4 = new TGeoVolume("TPC_TOFC", tofc, m3);
1161 // sandwich
1162 auto* tf1 = new TGeoTubeSeg(258.0, 260.0676, 252.1, 0., 59.9); // tedlar
1163 auto* tf2 = new TGeoTubeSeg(258.0038, 260.0638, 252.1, 0., 59.9); // prepreg3
1164 auto* tf3 = new TGeoTubeSeg(258.0338, 260.0338, 252.1, 0., 59.9); // nomex
1165 auto* tfg4 = new TGeoTubeSeg(258.0, 260.0676, 252.1, 59.9, 60.); // epoxy glue
1166 //
1167 TGeoMedium* sm5 = gGeoManager->GetMedium("TPC_Prepreg3");
1168 //
1169 auto* tf1v = new TGeoVolume("TPC_OFC1", tf1, sm2);
1170 auto* tf2v = new TGeoVolume("TPC_OFC2", tf2, sm5);
1171 auto* tf3v = new TGeoVolume("TPC_OFC3", tf3, sm4);
1172 auto* tfg4v = new TGeoVolume("TPC_OFCG4", tfg4, smep);
1173 //
1174 // outer part - positioning
1175 //
1176 tov1->AddNode(tov2, 1);
1177 tov2->AddNode(tov3, 1);
1178 tov3->AddNode(tov4, 1); // ocv
1179 //
1180 tf1v->AddNode(tf2v, 1);
1181 tf2v->AddNode(tf3v, 1); // ofc
1182 //
1183 auto* t200 = new TGeoVolumeAssembly("TPC_OCVSEG");
1184 auto* t300 = new TGeoVolumeAssembly("TPC_OFCSEG");
1185 //
1186 // assembly OCV and OFC
1187 //
1188 // 1st - no rotation
1189 t200->AddNode(tov1, 1);
1190 t200->AddNode(togv5, 1);
1191 t300->AddNode(tf1v, 1);
1192 t300->AddNode(tfg4v, 1);
1193 // 2nd - rotation 60 deg
1194 segrot = new TGeoRotation();
1195 segrot->RotateZ(60.);
1196 t200->AddNode(tov1, 2, segrot);
1197 t200->AddNode(togv5, 2, segrot);
1198 t300->AddNode(tf1v, 2, segrot);
1199 t300->AddNode(tfg4v, 2, segrot);
1200 // 3rd rotation 120 deg
1201 segrot = new TGeoRotation();
1202 segrot->RotateZ(120.);
1203 t200->AddNode(tov1, 3, segrot);
1204 t200->AddNode(togv5, 3, segrot);
1205 t300->AddNode(tf1v, 3, segrot);
1206 t300->AddNode(tfg4v, 3, segrot);
1207 // 4th rotation 180 deg
1208 segrot = new TGeoRotation();
1209 segrot->RotateZ(180.);
1210 t200->AddNode(tov1, 4, segrot);
1211 t200->AddNode(togv5, 4, segrot);
1212 t300->AddNode(tf1v, 4, segrot);
1213 t300->AddNode(tfg4v, 4, segrot);
1214 // 5th rotation 240 deg
1215 segrot = new TGeoRotation();
1216 segrot->RotateZ(240.);
1217 t200->AddNode(tov1, 5, segrot);
1218 t200->AddNode(togv5, 5, segrot);
1219 t300->AddNode(tf1v, 5, segrot);
1220 t300->AddNode(tfg4v, 5, segrot);
1221 // 6th rotation 300 deg
1222 segrot = new TGeoRotation();
1223 segrot->RotateZ(300.);
1224 t200->AddNode(tov1, 6, segrot);
1225 t200->AddNode(togv5, 6, segrot);
1226 t300->AddNode(tf1v, 6, segrot);
1227 t300->AddNode(tfg4v, 6, segrot);
1228 //
1229 v3->AddNode(t200, 1, new TGeoTranslation(0., 0., -1.5));
1230 v4->AddNode(t300, 1);
1231 //
1232 v2->AddNode(v3, 1);
1233 v2->AddNode(v4, 1);
1234 //
1235 v1->AddNode(v2, 1);
1236 //
1237 // Outer field cage guard rings. Inner placed in the drift gas, outer placed in the outer insulator (CO2)
1238 //
1239 auto* ogri = new TGeoTube(257.985, 258., 0.6); // placed in the drift volume
1240 auto* ogro = new TGeoTube(260.0676, 260.0826, 0.6); // placed in the outer insulator
1241 //
1242 auto* ogriv = new TGeoVolume("TPC_OGRI", ogri, m3);
1243 auto* ogrov = new TGeoVolume("TPC_OGRO", ogro, m3);
1244 //
1245 for (Int_t i = 0; i < 24; i++) {
1246 v9->AddNode(ogriv, (i + 1), new TGeoTranslation(0., 0., (i + 1) * 10));
1247 v9->AddNode(ogriv, (i + 25), new TGeoTranslation(0., 0., -(i + 1) * 10));
1248 v2->AddNode(ogrov, (i + 1), new TGeoTranslation(0., 0., (i + 1) * 10));
1249 v2->AddNode(ogrov, (i + 25), new TGeoTranslation(0., 0., -(i + 1) * 10));
1250 }
1251 //--------------------------------------------------------------------
1252 // Tpc Inner INsulator (CO2)
1253 // the cones, the central drum and the inner f.c. sandwich with a piece
1254 // of the flane will be placed in the TPC
1255 //--------------------------------------------------------------------
1256 auto* tpci = new TGeoPcon(0., 360., 4);
1257 //
1258 tpci->DefineSection(0, -253.6, 68.4, 76.6774);
1259 tpci->DefineSection(1, -74.0, 61.2, 76.6774);
1260 //
1261 tpci->DefineSection(2, 74.0, 61.2, 76.6774);
1262 //
1263 tpci->DefineSection(3, 253.6, 65.9, 76.6774);
1264 //
1265 auto* v5 = new TGeoVolume("TPC_INI", tpci, m2);
1266 //
1267 // now the inner field cage - only part of flanges (2 copies)
1268 //
1269 auto* tif1 = new TGeoTube(69.9, 76.6774, 1.5);
1270 auto* v6 = new TGeoVolume("TPC_IFC1", tif1, m3);
1271 //
1272 //---------------------------------------------------------
1273 // Tpc Inner Containment vessel - Muon side
1274 //---------------------------------------------------------
1275 auto* tcms = new TGeoPcon(0., 360., 10);
1276 //
1277 tcms->DefineSection(0, -259.1, 68.1, 74.2);
1278 tcms->DefineSection(1, -253.6, 68.1, 74.2);
1279 //
1280 tcms->DefineSection(2, -253.6, 68.1, 68.4);
1281 tcms->DefineSection(3, -74.0, 60.9, 61.2);
1282 //
1283 tcms->DefineSection(4, -74.0, 60.1, 61.2);
1284 tcms->DefineSection(5, -73.3, 60.1, 61.2);
1285 //
1286 tcms->DefineSection(6, -73.3, 56.9, 61.2);
1287 tcms->DefineSection(7, -73.0, 56.9, 61.2);
1288 //
1289 tcms->DefineSection(8, -73.0, 56.9, 58.8);
1290 tcms->DefineSection(9, -71.3, 56.9, 58.8);
1291 //
1292 auto* v7 = new TGeoVolume("TPC_ICVM", tcms, m3);
1293 //------------------------------------------------
1294 // Heat screen muon side
1295 //------------------------------------------------
1296
1297 auto* thsm = new TGeoCone(89.8, 67.88, 68.1, 60.68, 60.9);
1298 auto* thsmw = new TGeoCone(89.8, 67.94, 68.04, 60.74, 60.84);
1299 auto* hvsm = new TGeoVolume("TPC_HSM", thsm, mhs); // steel
1300 auto* hvsmw = new TGeoVolume("TPC_HSMW", thsmw, m12); // water
1301 // assembly heat screen muon
1302 hvsm->AddNode(hvsmw, 1);
1303 //-----------------------------------------------
1304 // inner containment vessel - shaft side
1305 //-----------------------------------------------
1306 auto* tcss = new TGeoPcon(0., 360., 10);
1307 //
1308 tcss->DefineSection(0, 71.3, 56.9, 58.8);
1309 tcss->DefineSection(1, 73.0, 56.9, 58.8);
1310 //
1311 tcss->DefineSection(2, 73.0, 56.9, 61.2);
1312 tcss->DefineSection(3, 73.3, 56.9, 61.2);
1313 //
1314 tcss->DefineSection(4, 73.3, 60.1, 61.2);
1315 tcss->DefineSection(5, 74.0, 60.1, 61.2);
1316 //
1317 tcss->DefineSection(6, 74.0, 60.9, 61.2);
1318 tcss->DefineSection(7, 253.6, 65.6, 65.9);
1319 //
1320 tcss->DefineSection(8, 253.6, 65.6, 74.2);
1321 tcss->DefineSection(9, 258.1, 65.6, 74.2);
1322 //
1323 auto* v8 = new TGeoVolume("TPC_ICVS", tcss, m3);
1324 //-------------------------------------------------
1325 // Heat screen shaft side
1326 //--------------------------------------------------
1327 auto* thss = new TGeoCone(89.8, 60.68, 60.9, 65.38, 65.6);
1328 auto* thssw = new TGeoCone(89.8, 60.74, 60.84, 65.44, 65.54);
1329 auto* hvss = new TGeoVolume("TPC_HSS", thss, mhs); // steel
1330 auto* hvssw = new TGeoVolume("TPC_HSSW", thssw, m12); // water
1331 // assembly heat screen shaft
1332 hvss->AddNode(hvssw, 1);
1333 //-----------------------------------------------
1334 // Inner field cage
1335 // define 4 parts and make an assembly
1336 //-----------------------------------------------
1337 // part1 - Al - 2 copies
1338 auto* t1 = new TGeoTube(76.6774, 78.845, 0.75);
1339 auto* tv1 = new TGeoVolume("TPC_IFC2", t1, m3);
1340 // sandwich - outermost parts - 2 copies
1341 //
1342 // segment outermost
1343 //
1344 auto* t2 = new TGeoTubeSeg(76.6774, 78.845, 74.175, 350., 109.4); // tedlar 38 microns
1345 auto* t3 = new TGeoTubeSeg(76.6812, 78.8412, 74.175, 350., 109.4); // prepreg2 500 microns
1346 auto* t4 = new TGeoTubeSeg(76.7312, 78.7912, 74.175, 350., 109.4); // prepreg3 300 microns
1347 auto* t5 = new TGeoTubeSeg(76.7612, 78.7612, 74.175, 350., 109.4); // nomex 2 cm
1348 auto* tepox1 = new TGeoTubeSeg(76.6774, 78.845, 74.175, 109.4, 110.); // epoxy
1349 auto* tpr1 = new TGeoTubeSeg(78.845, 78.885, 74.175, 109., 111.);
1350
1351 // volumes for the outer part
1352 auto* tv2 = new TGeoVolume("TPC_IFC3", t2, sm2);
1353 auto* tv3 = new TGeoVolume("TPC_IFC4", t3, sm3);
1354 auto* tv4 = new TGeoVolume("TPC_IFC5", t4, sm5);
1355 auto* tv5 = new TGeoVolume("TPC_IFC6", t5, sm4);
1356 auto* tvep1 = new TGeoVolume("TPC_IFEPOX1", tepox1, smep);
1357 auto* tvpr1 = new TGeoVolume("TPC_PRSTR1", tpr1, sm2);
1358 //
1359 // middle parts - 2 copies
1360 //
1361 // segment middle
1362 //
1363 auto* t6 = new TGeoTubeSeg(76.6774, 78.795, 5., 350., 109.4); // tedlar 38 microns
1364 auto* t7 = new TGeoTubeSeg(76.6812, 78.7912, 5., 350., 109.4); // prepreg2 250 microns
1365 auto* t8 = new TGeoTubeSeg(76.7062, 78.7662, 5., 350., 109.4); // prepreg3 300 microns
1366 auto* t9 = new TGeoTubeSeg(76.7362, 78.7362, 5., 350., 109.4); // nomex 2 cm
1367 auto* tepox2 = new TGeoTubeSeg(76.6774, 78.795, 5., 109.4, 110.); // epoxy
1368 auto* tpr2 = new TGeoTubeSeg(78.795, 78.835, 5., 109., 111.);
1369 // volumes for the middle part
1370 auto* tv6 = new TGeoVolume("TPC_IFC7", t6, sm2);
1371 auto* tv7 = new TGeoVolume("TPC_IFC8", t7, sm3);
1372 auto* tv8 = new TGeoVolume("TPC_IFC9", t8, sm5);
1373 auto* tv9 = new TGeoVolume("TPC_IFC10", t9, sm4);
1374 auto* tvep2 = new TGeoVolume("TPC_IFEPOX2", tepox2, smep);
1375 auto* tvpr2 = new TGeoVolume("TPC_PRSTR2", tpr2, sm2);
1376 // central part - 1 copy
1377 //
1378 // segment central part
1379 //
1380 auto* t10 = new TGeoTubeSeg(76.6774, 78.785, 93.75, 350., 109.4); // tedlar 38 microns
1381 auto* t11 = new TGeoTubeSeg(76.6812, 78.7812, 93.75, 350., 109.4); // prepreg3 500 microns
1382 auto* t12 = new TGeoTubeSeg(76.7312, 78.7312, 93.75, 350., 109.4); // nomex 2 cm
1383 auto* tepox3 = new TGeoTubeSeg(76.6774, 78.785, 93.75, 109.4, 110.); // epoxy
1384 auto* tpr3 = new TGeoTubeSeg(78.785, 78.825, 93.75, 109., 111.);
1385 // volumes for the central part
1386 auto* tv10 = new TGeoVolume("TPC_IFC11", t10, sm2);
1387 auto* tv11 = new TGeoVolume("TPC_IFC12", t11, sm5);
1388 auto* tv12 = new TGeoVolume("TPC_IFC13", t12, sm4);
1389 auto* tvep3 = new TGeoVolume("TPC_IFEPOX3", tepox3, smep);
1390 auto* tvpr3 = new TGeoVolume("TPC_PRSTR3", tpr3, sm2);
1391 //
1392 // creating a sandwich for the outer par,t tv2 is the mother
1393 //
1394 tv2->AddNode(tv3, 1);
1395 tv3->AddNode(tv4, 1);
1396 tv4->AddNode(tv5, 1);
1397 //
1398 // creating a sandwich for the middle part, tv6 is the mother
1399 //
1400 tv6->AddNode(tv7, 1);
1401 tv7->AddNode(tv8, 1);
1402 tv8->AddNode(tv9, 1);
1403 //
1404 // creating a sandwich for the central part, tv10 is the mother
1405 //
1406 tv10->AddNode(tv11, 1);
1407 tv11->AddNode(tv12, 1);
1408 //
1409 auto* tv100 = new TGeoVolumeAssembly("TPC_IFC"); // ifc itself - 3 segments
1410
1411 //
1412 // first segment - no rotation
1413 //
1414 // central
1415 tv100->AddNode(tv10, 1); // sandwich
1416 tv100->AddNode(tvep3, 1); // epoxy
1417 tv100->AddNode(tvpr3, 1); // prepreg strip
1418 // middle
1419 tv100->AddNode(tv6, 1, new TGeoTranslation(0., 0., -98.75)); // sandwich1
1420 tv100->AddNode(tv6, 2, new TGeoTranslation(0., 0., 98.75)); // sandwich2
1421 tv100->AddNode(tvep2, 1, new TGeoTranslation(0., 0., -98.75)); // epoxy
1422 tv100->AddNode(tvep2, 2, new TGeoTranslation(0., 0., 98.75)); // epoxy
1423 tv100->AddNode(tvpr2, 1, new TGeoTranslation(0., 0., -98.75)); // prepreg strip
1424 tv100->AddNode(tvpr2, 2, new TGeoTranslation(0., 0., 98.75));
1425 // outer
1426 tv100->AddNode(tv2, 1, new TGeoTranslation(0., 0., -177.925)); // sandwich
1427 tv100->AddNode(tv2, 2, new TGeoTranslation(0., 0., 177.925));
1428 tv100->AddNode(tvep1, 1, new TGeoTranslation(0., 0., -177.925)); // epoxy
1429 tv100->AddNode(tvep1, 2, new TGeoTranslation(0., 0., 177.925));
1430 tv100->AddNode(tvpr1, 1, new TGeoTranslation(0., 0., -177.925)); // prepreg strip
1431 tv100->AddNode(tvpr1, 2, new TGeoTranslation(0., 0., 177.925));
1432 //
1433 // second segment - rotation 120 deg.
1434 //
1435 segrot = new TGeoRotation();
1436 segrot->RotateZ(120.);
1437 //
1438 // central
1439 tv100->AddNode(tv10, 2, segrot); // sandwich
1440 tv100->AddNode(tvep3, 2, segrot); // epoxy
1441 tv100->AddNode(tvpr3, 2, segrot); // prepreg strip
1442 // middle
1443 tv100->AddNode(tv6, 3, new TGeoCombiTrans(0., 0., -98.75, segrot)); // sandwich1
1444 tv100->AddNode(tv6, 4, new TGeoCombiTrans(0., 0., 98.75, segrot)); // sandwich2
1445 tv100->AddNode(tvep2, 3, new TGeoCombiTrans(0., 0., -98.75, segrot)); // epoxy
1446 tv100->AddNode(tvep2, 4, new TGeoCombiTrans(0., 0., 98.75, segrot)); // epoxy
1447 tv100->AddNode(tvpr2, 3, new TGeoCombiTrans(0., 0., -98.75, segrot)); // prepreg strip
1448 tv100->AddNode(tvpr2, 4, new TGeoCombiTrans(0., 0., 98.75, segrot));
1449 // outer
1450 tv100->AddNode(tv2, 3, new TGeoCombiTrans(0., 0., -177.925, segrot)); // sandwich
1451 tv100->AddNode(tv2, 4, new TGeoCombiTrans(0., 0., 177.925, segrot));
1452 tv100->AddNode(tvep1, 3, new TGeoCombiTrans(0., 0., -177.925, segrot)); // epoxy
1453 tv100->AddNode(tvep1, 4, new TGeoCombiTrans(0., 0., 177.925, segrot));
1454 tv100->AddNode(tvpr1, 3, new TGeoCombiTrans(0., 0., -177.925, segrot)); // prepreg strip
1455 tv100->AddNode(tvpr1, 4, new TGeoCombiTrans(0., 0., 177.925, segrot));
1456 //
1457 // third segment - rotation 240 deg.
1458 //
1459 segrot = new TGeoRotation();
1460 segrot->RotateZ(240.);
1461 //
1462 // central
1463 tv100->AddNode(tv10, 3, segrot); // sandwich
1464 tv100->AddNode(tvep3, 3, segrot); // epoxy
1465 tv100->AddNode(tvpr3, 3, segrot); // prepreg strip
1466 // middle
1467 tv100->AddNode(tv6, 5, new TGeoCombiTrans(0., 0., -98.75, segrot)); // sandwich1
1468 tv100->AddNode(tv6, 6, new TGeoCombiTrans(0., 0., 98.75, segrot)); // sandwich2
1469 tv100->AddNode(tvep2, 5, new TGeoCombiTrans(0., 0., -98.75, segrot)); // epoxy
1470 tv100->AddNode(tvep2, 6, new TGeoCombiTrans(0., 0., 98.75, segrot)); // epoxy
1471 tv100->AddNode(tvpr2, 5, new TGeoCombiTrans(0., 0., -98.75, segrot)); // prepreg strip
1472 tv100->AddNode(tvpr2, 6, new TGeoCombiTrans(0., 0., 98.75, segrot));
1473 // outer
1474 tv100->AddNode(tv2, 5, new TGeoCombiTrans(0., 0., -177.925, segrot)); // sandwich
1475 tv100->AddNode(tv2, 6, new TGeoCombiTrans(0., 0., 177.925, segrot));
1476 tv100->AddNode(tvep1, 5, new TGeoCombiTrans(0., 0., -177.925, segrot)); // epoxy
1477 tv100->AddNode(tvep1, 6, new TGeoCombiTrans(0., 0., 177.925, segrot));
1478 tv100->AddNode(tvpr1, 5, new TGeoCombiTrans(0., 0., -177.925, segrot)); // prepreg strip
1479 tv100->AddNode(tvpr1, 6, new TGeoCombiTrans(0., 0., 177.925, segrot));
1480 // Al parts - rings
1481 tv100->AddNode(tv1, 1, new TGeoTranslation(0., 0., -252.85));
1482 tv100->AddNode(tv1, 2, new TGeoTranslation(0., 0., 252.85));
1483 //
1484 v5->AddNode(v6, 1, new TGeoTranslation(0., 0., -252.1));
1485 v5->AddNode(v6, 2, new TGeoTranslation(0., 0., 252.1));
1486 v1->AddNode(v5, 1);
1487 v1->AddNode(v7, 1);
1488 v1->AddNode(v8, 1);
1489 v1->AddNode(hvsm, 1, new TGeoTranslation(0., 0., -163.8));
1490 v1->AddNode(hvss, 1, new TGeoTranslation(0., 0., 163.8));
1491 v9->AddNode(tv100, 1);
1492 //
1493 // guard rings for IFC - outer placed in inner insulator, inner placed in the drift gas (3 different radii)
1494 // AL, 1.2 cm wide, 0.015 cm thick, volumes TPC_IGR1 - outer, TPC_IGR2-4 - inner
1495 //
1496 auto* igro = new TGeoTube(76.6624, 76.6774, 0.6); // inner part, ends at inner radius of the IFC
1497 auto* igrio = new TGeoTube(78.845, 78.86, 0.6); // outer part
1498 auto* igrim = new TGeoTube(78.795, 78.81, 0.6);
1499 auto* igric = new TGeoTube(78.785, 78.8, 0.6);
1500 //
1501 // volumes
1502 //
1503 auto* igrov = new TGeoVolume("TPC_IGR1", igro, m3);
1504 auto* igriov = new TGeoVolume("TPC_IGR2", igrio, m3);
1505 auto* igrimv = new TGeoVolume("TPC_IGR3", igrim, m3);
1506 auto* igricv = new TGeoVolume("TPC_IGR4", igric, m3);
1507 //
1508 // outer guard rings for IFC placement - every 10 cm
1509 //
1510 for (Int_t i = 0; i < 24; i++) {
1511 v5->AddNode(igrov, (i + 1), new TGeoTranslation(0., 0., (i + 1) * 10));
1512 v5->AddNode(igrov, (i + 25), new TGeoTranslation(0., 0., -(i + 1) * 10));
1513 }
1514 //
1515 // inner guard rings for IFC placement
1516 //
1517 for (Int_t i = 0; i < 9; i++) {
1518 v9->AddNode(igricv, (i + 1), new TGeoTranslation(0., 0., (i + 1) * 10));
1519 v9->AddNode(igricv, (i + 10), new TGeoTranslation(0., 0., -(i + 1) * 10));
1520 }
1521 v9->AddNode(igrimv, 1, new TGeoTranslation(0., 0., 100.));
1522 v9->AddNode(igrimv, 2, new TGeoTranslation(0., 0., -100.));
1523 //
1524 for (Int_t i = 0; i < 13; i++) {
1525 v9->AddNode(igriov, i + 1, new TGeoTranslation(0., 0., 100 + (i + 1) * 10));
1526 v9->AddNode(igriov, i + 14, new TGeoTranslation(0., 0., -(100 + (i + 1) * 10)));
1527 }
1528 //
1529 // central drum
1530 //
1531 // flange + sandwich
1532 //
1533 auto* cfl = new TGeoPcon(0., 360., 6);
1534 cfl->DefineSection(0, -71.1, 59.7, 61.2);
1535 cfl->DefineSection(1, -68.6, 59.7, 61.2);
1536 //
1537 cfl->DefineSection(2, -68.6, 60.6124, 61.2);
1538 cfl->DefineSection(3, 68.6, 60.6124, 61.2);
1539 //
1540 cfl->DefineSection(4, 68.6, 59.7, 61.2);
1541 cfl->DefineSection(5, 71.1, 59.7, 61.2);
1542 //
1543 auto* cflv = new TGeoVolume("TPC_CDR", cfl, m3);
1544 // sandwich
1545 auto* cd1 = new TGeoTubeSeg(60.6224, 61.19, 69.8, 0.05, 119.95);
1546 auto* cd2 = new TGeoTubeSeg(60.6262, 61.1862, 69.8, 0.05, 119.95);
1547 auto* cd3 = new TGeoTubeSeg(60.6462, 61.1662, 69.8, 0.05, 119.95);
1548 auto* cd4 = new TGeoTubeSeg(60.6562, 61.1562, 69.8, 0.05, 119.95);
1549 auto* tepox4 = new TGeoTubeSeg(60.6224, 61.19, 69.8, 359.95, 0.05); // epoxy glue 0.01 deg
1550 //
1551 TGeoMedium* sm6 = gGeoManager->GetMedium("TPC_Prepreg1");
1552 TGeoMedium* sm8 = gGeoManager->GetMedium("TPC_Epoxyfm");
1553 auto* cd1v = new TGeoVolume("TPC_CDR1", cd1, sm2); // tedlar
1554 auto* cd2v = new TGeoVolume("TPC_CDR2", cd2, sm6); // prepreg1
1555 auto* cd3v = new TGeoVolume("TPC_CDR3", cd3, sm8); // epoxy film
1556 auto* cd4v = new TGeoVolume("TPC_CDR4", cd4, sm4); // nomex
1557 auto* tvep4 = new TGeoVolume("TPC_IFEPOX4", tepox4, smep); // epoxy glue
1558 //
1559 // joints between sections 1 deg prepreg1 placed in nomex at lower and upper radius + 0.1 deg of glue (epoxy)
1560 //
1561 auto* cdjl = new TGeoTubeSeg(60.6562, 60.6762, 69.8, 0., 1.0); // lower, to be rotated when positioned
1562 auto* cdju = new TGeoTubeSeg(61.1362, 61.1562, 69.8, 0., 1.0); // upper, to be rotated when positioned
1563 //
1564 auto* cdjlv = new TGeoVolume("TPC_CDJL", cdjl, sm6);
1565 auto* cdjuv = new TGeoVolume("TPC_CDJU", cdju, sm6);
1566 //
1567 // seals for central drum 2 copies
1568 //
1569 auto* cs = new TGeoTube(56.9, 61.2, 0.1);
1570 TGeoMedium* sm7 = gGeoManager->GetMedium("TPC_Mylar");
1571 auto* csv = new TGeoVolume("TPC_CDRS", cs, sm7);
1572 v1->AddNode(csv, 1, new TGeoTranslation(0., 0., -71.2));
1573 v1->AddNode(csv, 2, new TGeoTranslation(0., 0., 71.2));
1574 //
1575 // seal collars
1576 auto* se = new TGeoPcon(0., 360., 6);
1577 se->DefineSection(0, -72.8, 59.7, 61.2);
1578 se->DefineSection(1, -72.3, 59.7, 61.2);
1579 //
1580 se->DefineSection(2, -72.3, 58.85, 61.2);
1581 se->DefineSection(3, -71.6, 58.85, 61.2);
1582 //
1583 se->DefineSection(4, -71.6, 59.7, 61.2);
1584 se->DefineSection(5, -71.3, 59.7, 61.2);
1585 //
1586 auto* sev = new TGeoVolume("TPC_CDCE", se, m3);
1587 //
1588 auto* si = new TGeoTube(56.9, 58.8, 1.);
1589 auto* siv = new TGeoVolume("TPC_CDCI", si, m3);
1590 //
1591 // define reflection matrix
1592 //
1593 auto* ref = new TGeoRotation("ref", 90., 0., 90., 90., 180., 0.);
1594 //
1595 cd1v->AddNode(cd2v, 1);
1596 cd2v->AddNode(cd3v, 1);
1597 cd3v->AddNode(cd4v, 1); // sandwich
1598 //
1599 // joints, lower part and upper parts, placed in nomex
1600 //
1601 segrot = new TGeoRotation();
1602 segrot->RotateZ(0.05);
1603 cd4v->AddNode(cdjlv, 1, segrot);
1604 cd4v->AddNode(cdjuv, 1, segrot);
1605 segrot = new TGeoRotation();
1606 segrot->RotateZ(118.95);
1607 cd4v->AddNode(cdjlv, 2, segrot);
1608 cd4v->AddNode(cdjuv, 2, segrot);
1609 //
1610 // according to the conversion data, segments have an additionaly rotated by 4.6 deg
1611 //
1612 // first segment
1613 segrot = new TGeoRotation();
1614 segrot->RotateZ(4.6);
1615 cflv->AddNode(cd1v, 1, segrot);
1616 cflv->AddNode(tvep4, 1, segrot);
1617 // second segment
1618 segrot = new TGeoRotation();
1619 segrot->RotateZ(124.6);
1620 cflv->AddNode(cd1v, 2, segrot);
1621 cflv->AddNode(tvep4, 2, segrot);
1622 // third segment
1623 segrot = new TGeoRotation();
1624 segrot->RotateZ(244.6);
1625 cflv->AddNode(cd1v, 3, segrot);
1626 cflv->AddNode(tvep4, 3, segrot);
1627 //
1628 // heating strips
1629 //
1630 auto* hstr = new TGeoTubeSeg(60.6124, 60.6224, 68.5, 0., 1.25);
1631 auto* hstrv = new TGeoVolume("TPC_HSTR", hstr, m1); // air, caved out from cflv, first strip starts at 0 deg
1632 for (Int_t i = 0; i < 144; i++) {
1633 Double_t alpha = 1.25 + i * 2.5;
1634 segrot = new TGeoRotation();
1635 segrot->RotateZ(alpha);
1636 cflv->AddNode(hstrv, i + 1, segrot);
1637 }
1638 //
1639 v1->AddNode(siv, 1, new TGeoTranslation(0., 0., -69.9));
1640 v1->AddNode(siv, 2, new TGeoTranslation(0., 0., 69.9));
1641 v1->AddNode(sev, 1);
1642 v1->AddNode(sev, 2, ref);
1643 v1->AddNode(cflv, 1);
1644 //
1645 // central membrane - 2 rings and a mylar membrane - assembly
1646 //
1647 auto* ih = new TGeoTube(81.05, 84.05, 0.3);
1648 auto* oh = new TGeoTube(250., 256., 0.5);
1649 auto* mem = new TGeoTube(84.05, 250., 0.00115);
1650
1651 //
1652 TGeoMedium* m4 = gGeoManager->GetMedium("TPC_G10");
1653 //
1654 auto* ihv = new TGeoVolume("TPC_IHVH", ih, m3);
1655 auto* ohv = new TGeoVolume("TPC_OHVH", oh, m3);
1656
1657 auto* memv = new TGeoVolume("TPC_HV", mem, sm7);
1658 //
1659 auto* cm = new TGeoVolumeAssembly("TPC_HVMEM");
1660 cm->AddNode(ihv, 1);
1661 cm->AddNode(ohv, 1);
1662 cm->AddNode(memv, 1);
1663
1664 v9->AddNode(cm, 1);
1665 //
1666 // end caps - they are make as an assembly of single segments
1667 // containing both readout chambers
1668 //
1669 Double_t openingAngle = 10. * TMath::DegToRad();
1670 Double_t thick = 1.5; // rib
1671 Double_t shift = thick / TMath::Sin(openingAngle);
1672 //
1673 Double_t lowEdge = 86.3; // hole in the wheel
1674 Double_t upEdge = 240.4; // hole in the wheel
1675 //
1676 new TGeoTubeSeg("tpc_ssec", 74.5, 264.4, 3., 0., 20.);
1677 //
1678 auto* tpc_hole = new TGeoPgon("tpc_hole", 0., 20., 1, 4);
1679 //
1680 tpc_hole->DefineSection(0, -3.5, lowEdge - shift, upEdge - shift);
1681 tpc_hole->DefineSection(1, -1.5, lowEdge - shift, upEdge - shift);
1682 //
1683 tpc_hole->DefineSection(2, -1.5, lowEdge - shift, upEdge + 3. - shift);
1684 tpc_hole->DefineSection(3, 3.5, lowEdge - shift, upEdge + 3. - shift);
1685 //
1686 Double_t ys = shift * TMath::Sin(openingAngle);
1687 Double_t xs = shift * TMath::Cos(openingAngle);
1688 auto* tr = new TGeoTranslation("tr", xs, ys, 0.);
1689 tr->RegisterYourself();
1690 auto* chamber = new TGeoCompositeShape("tpc_ssec-tpc_hole:tr");
1691 auto* sv = new TGeoVolume("TPC_WSEG", chamber, m3);
1692 auto* bar = new TGeoPgon("bar", 0., 20., 1, 2);
1693 bar->DefineSection(0, -3., 131.5 - shift, 136.5 - shift);
1694 bar->DefineSection(1, 1.5, 131.5 - shift, 136.5 - shift);
1695 auto* barv = new TGeoVolume("TPC_WBAR", bar, m3);
1696 auto* ch = new TGeoVolumeAssembly("TPC_WCH"); // empty segment
1697 //
1698 ch->AddNode(sv, 1);
1699 ch->AddNode(barv, 1, tr);
1700 //
1701 // readout chambers
1702 //
1703 // IROC first
1704 //
1705 TGeoMedium* m6 = gGeoManager->GetMedium("TPC_Makrolon");
1706 //
1707 auto* ibody = new TGeoTrd1(13.8742, 21.3328, 4.29, 21.15);
1708 auto* ibdv = new TGeoVolume("TPC_IROCB", ibody, m3);
1709 // empty space
1710 auto* emp = new TGeoTrd1(12.3742, 19.8328, 4.05, 19.65);
1711 auto* empv = new TGeoVolume("TPC_IROCE", emp, m1);
1712 ibdv->AddNode(empv, 1, new TGeoTranslation(0., -0.24, 0.));
1713 // bars
1714 Double_t tga = (19.8328 - 12.3742) / 39.3;
1715 Double_t xmin, xmax;
1716 // 1
1717 xmin = 9.65 * tga + 12.3742;
1718 xmax = 10.05 * tga + 12.3742;
1719 //
1720 auto* ib1 = new TGeoTrd1(xmin, xmax, 2.06, 0.2);
1721 auto* ib1v = new TGeoVolume("TPC_IRB1", ib1, m3);
1722 empv->AddNode(ib1v, 1, new TGeoTranslation("tt1", 0., 1.99, -9.8));
1723 // 2
1724 xmin = 19.5 * tga + 12.3742;
1725 xmax = 19.9 * tga + 12.3742;
1726 //
1727 auto* ib2 = new TGeoTrd1(xmin, xmax, 2.06, 0.2);
1728 auto* ib2v = new TGeoVolume("TPC_TRB2", ib2, m3);
1729 empv->AddNode(ib2v, 1, new TGeoTranslation(0., 1.99, 0.05));
1730 // 3
1731 xmin = 29.35 * tga + 12.3742;
1732 xmax = 29.75 * tga + 12.3742;
1733 //
1734 auto* ib3 = new TGeoTrd1(xmin, xmax, 2.06, 0.2);
1735 auto* ib3v = new TGeoVolume("TPC_IRB3", ib3, m3);
1736 empv->AddNode(ib3v, 1, new TGeoTranslation(0., 1.99, 9.9));
1737 //
1738 // connectors alu body & strong back
1739 //
1740 auto* conn = new TGeoBBox(0.4, 0.24, 1.937); // connectors alu body
1741 auto* connv = new TGeoVolume("TPC_RCCON", conn, m6); // makrolon
1742 //
1743 auto* connb = new TGeoBBox(0.5, 0.25, 2.375); // connectors strong back
1744 auto* connbv = new TGeoVolume("TPC_RCCONB", connb, m6);
1745 //
1746 // strong back
1747 //
1748 auto* icsb = new TGeoTrd1(14.5974, 23.3521, 0.25, 24.825);
1749 auto* icsbv = new TGeoVolume("TPC_ISB", icsb, m4);
1750 //
1751 // file with positions of connectors
1752 //
1753 TString fileName(gSystem->Getenv("VMCWORKDIR"));
1754 fileName += "/Detectors/Geometry/TPC/conn_iroc.dat";
1755 ifstream in;
1756 in.open(fileName.Data(), ios_base::in); // asci file
1757 if (!in.is_open()) {
1758 LOG(fatal) << "Cannot open input file : " << fileName.Data();
1759 }
1760 for (Int_t i = 0; i < 132; i++) {
1761 Double_t x, z, ang;
1762 in >> ang >> x >> z;
1763 //
1764 ang = -ang;
1765 z -= 1102.; // changing the reference frame from the beam to the volume
1766 z *= 0.1;
1767 x *= 0.1;
1768 //
1769 auto* rrr = new TGeoRotation();
1770 rrr->RotateY(ang);
1771 //
1772 ibdv->AddNode(connv, i + 1, new TGeoCombiTrans(x, 4.05, z, rrr)); // connectors alu body
1773 icsbv->AddNode(connbv, i + 1, new TGeoCombiTrans(x, 0., z + 1.725, rrr)); // connectors strong back
1774 }
1775 in.close();
1776 //
1777 // "cap"
1778 new TGeoTrd1("icap", 14.5974, 23.3521, 1.19, 24.825);
1779 // "hole"
1780 new TGeoTrd1("ihole", 13.8742, 21.3328, 1.2, 21.15);
1781 auto* tr1 = new TGeoTranslation("tr1", 0., 0., 1.725);
1782 tr1->RegisterYourself();
1783 auto* ic = new TGeoCompositeShape("icap-ihole:tr1");
1784 auto* icv = new TGeoVolume("TPC_IRCAP", ic, m3);
1785 //
1786 // pad plane G10 3.2 mm thick
1787 //
1788 auto* icpp = new TGeoTrd1(14.5974, 23.3521, 0.16, 24.825);
1789 auto* icppv = new TGeoVolume("TPC_IPP", icpp, m4); // pad plane
1790 //
1791 // gem
1792 //
1793 new TGeoTrd1("igem", 14.5974, 23.3521, 0.1, 24.825);
1794 new TGeoTrd1("igemh", 14.5974 - .5, 23.3521 - .5, 0.11, 24.825 - .5);
1795 auto* icgem = new TGeoCompositeShape("igem-igemh");
1796 auto* icgemv = new TGeoVolume("TPC_ICGEM", icgem, m4);
1797 //
1798 // assembly of the iroc
1799 //
1800 auto* iroc = new TGeoVolumeAssembly("TPC_IROC");
1801 //
1802 iroc->AddNode(ibdv, 1); // main body
1803 iroc->AddNode(icv, 1, new TGeoTranslation(0., 3.1, -1.725)); // cap
1804 iroc->AddNode(icsbv, 1, new TGeoTranslation(0., 4.54, -1.725)); // strong back
1805 iroc->AddNode(icppv, 1, new TGeoTranslation(0., 4.95, -1.725)); // pad plane
1806 iroc->AddNode(icgemv, 1, new TGeoTranslation(0., 5.21, -1.725)); // gem
1807 //
1808 // OROC
1809 //
1810 auto* obody = new TGeoTrd1(22.2938, 40.5084, 4.29, 51.65);
1811 auto* obdv = new TGeoVolume("TPC_OROCB", obody, m3);
1812 auto* oemp = new TGeoTrd1(20.7938, 39.0084, 3.89, 50.15);
1813 auto* oempv = new TGeoVolume("TPC_OROCE", oemp, m1);
1814 obdv->AddNode(oempv, 1, new TGeoTranslation(0., -0.4, 0.));
1815 //
1816 // horizontal bars
1817 //
1818 tga = (39.0084 - 20.7938) / 100.3;
1819 xmin = tga * 14.2 + 20.7938;
1820 xmax = tga * 14.6 + 20.7938;
1821 auto* ob1 = new TGeoTrd1(xmin, xmax, 2.94, 0.2);
1822 auto* ob1v = new TGeoVolume("TPC_ORB1", ob1, m3);
1823 //
1824 xmin = 30.4 * tga + 20.7938;
1825 xmax = 32.1 * tga + 20.7938;
1826 auto* ob2 = new TGeoTrd1(xmin, xmax, 2.94, 1.05);
1827 auto* ob2v = new TGeoVolume("TPC_ORB2", ob2, m3);
1828 //
1829 xmin = 51.5 * tga + 20.7938;
1830 xmax = 51.9 * tga + 20.7938;
1831 auto* ob3 = new TGeoTrd1(xmin, xmax, 2.94, 0.2);
1832 auto* ob3v = new TGeoVolume("TPC_ORB3", ob3, m3);
1833 //
1834 xmin = 68.5 * tga + 20.7938;
1835 xmax = 70.6 * tga + 20.7938;
1836 auto* ob4 = new TGeoTrd1(xmin, xmax, 2.94, 1.05);
1837 auto* ob4v = new TGeoVolume("TPC_ORB4", ob4, m3);
1838 //
1839 xmin = 89.9 * tga + 20.7938;
1840 xmax = 90.3 * tga + 20.7938;
1841 auto* ob5 = new TGeoTrd1(xmin, xmax, 2.94, 0.2);
1842 auto* ob5v = new TGeoVolume("TPC_ORB5", ob5, m3);
1843 //
1844 oempv->AddNode(ob1v, 1, new TGeoTranslation(0., 0.59, -35.75));
1845 oempv->AddNode(ob2v, 1, new TGeoTranslation(0., 0.59, -18.7));
1846 oempv->AddNode(ob3v, 1, new TGeoTranslation(0., 0.59, 1.55));
1847 oempv->AddNode(ob4v, 1, new TGeoTranslation(0., 0.59, 19.4));
1848 oempv->AddNode(ob5v, 1, new TGeoTranslation(0., 0.59, 39.95));
1849 //
1850 // connectors, identical as for iroc, but I prefer to have separate volumes for better control
1851 //
1852 auto* conno = new TGeoBBox(0.4, 0.4, 1.937); // alu body
1853 auto* connov = new TGeoVolume("TPC_RCCONO", conno, m6); // makrolon
1854 //
1855 auto* connob = new TGeoBBox(0.5, 0.25, 2.375);
1856 auto* connobv = new TGeoVolume("TPC_RCCONOB", connob, m6); // strong back
1857 //
1858 // cap
1859 //
1860 new TGeoTrd1("ocap", 23.3875, 43.524, 1.19, 57.1);
1861 new TGeoTrd1("ohole", 22.2938, 40.5084, 1.19, 51.65);
1862 auto* tr5 = new TGeoTranslation("tr5", 0., 0., -2.15);
1863 tr5->RegisterYourself();
1864 auto* oc = new TGeoCompositeShape("ocap-ohole:tr5");
1865 auto* ocv = new TGeoVolume("TPC_ORCAP", oc, m3);
1866 //
1867 // stron back 5 mm
1868 //
1869 auto* osb = new TGeoTrd1(23.3874, 43.524, 0.25, 57.1);
1870 auto* osbv = new TGeoVolume("TPC_OSB", osb, m4);
1871 //
1872 // pad plane 3.2 mm
1873 //
1874 auto* opp = new TGeoTrd1(23.3874, 43.524, 0.16, 57.1);
1875 auto* oppv = new TGeoVolume("TPC_OPP", opp, m4);
1876 //
1877 // gem
1878 //
1879 new TGeoTrd1("ogem", 23.3874, 43.524, 0.1, 57.1);
1880 //
1881 // ogemh1 - first "hole" ends at z = 36.25, ogemh2 - second "hole" starts at z = 74.15
1882 //
1883 new TGeoTrd1("ogemh1", 22.548, 28.579, 0.1, 17.625); // ogemh1 - lower hole
1884 new TGeoTrd1("ogemh2", 28.949, 35.297, 0.1, 18.45); // ogemh2 - middle hole
1885 new TGeoTrd1("ogemh3", 35.667, 42.332, 0.1, 19.425); // ogemh3 - upper hole
1886 //
1887 auto* tr2 = new TGeoTranslation("tr2", 0., 0., 18.125 - 57.1);
1888 auto* tr3 = new TGeoTranslation("tr3", 0., 0., 55.2 - 57.1);
1889 auto* tr4 = new TGeoTranslation("tr4", 0., 0., 94.175 - 57.1);
1890 tr2->RegisterYourself();
1891 tr3->RegisterYourself();
1892 tr4->RegisterYourself();
1893 auto* ocgem = new TGeoCompositeShape("ogem-ogemh1:tr2-ogemh2:tr3-ogemh3:tr4");
1894 auto* ocgemv = new TGeoVolume("TPC_OCGEM", ocgem, m4);
1895 //
1896 // holes for connectors
1897 //
1898 fileName = gSystem->Getenv("VMCWORKDIR");
1899 fileName += "/Detectors/Geometry/TPC/conn_oroc.dat";
1900 in.open(fileName.Data(), ios_base::in); // asci file
1901 if (!in.is_open()) {
1902 LOG(fatal) << "Cannot open input file : " << fileName.Data();
1903 }
1904 for (Int_t i = 0; i < 232; i++) {
1905 Double_t x, z, ang;
1906 in >> ang >> x >> z;
1907 ang = -ang;
1908 z -= 1884.5;
1909 z *= 0.1;
1910 x *= 0.1;
1911 //
1912 auto* rrr = new TGeoRotation();
1913 rrr->RotateY(ang);
1914 obdv->AddNode(connov, i + 1, new TGeoCombiTrans(x, 3.89, z, rrr));
1915 osbv->AddNode(connobv, i + 1, new TGeoCombiTrans(x, 0., z - 2.15, rrr));
1916 }
1917 in.close();
1918 //
1919 auto* oroc = new TGeoVolumeAssembly("TPC_OROC");
1920 //
1921 oroc->AddNode(obdv, 1);
1922 oroc->AddNode(ocv, 1, new TGeoTranslation(0., 3.1, 2.15));
1923 oroc->AddNode(osbv, 1, new TGeoTranslation(0., 4.54, 2.15));
1924 oroc->AddNode(oppv, 1, new TGeoTranslation(0., 4.95, 2.15));
1925 oroc->AddNode(ocgemv, 1, new TGeoTranslation(0., 5.21, 2.15));
1926 //
1927 // now iroc and oroc are placed into a sector...
1928 //
1929 auto* secta = new TGeoVolumeAssembly("TPC_SECT"); // a-side
1930 auto* sectc = new TGeoVolumeAssembly("TPC_SECT"); // c-side
1931 TGeoRotation rot1("rot1", 90., 90., 0.);
1932 TGeoRotation rot2("rot2");
1933 rot2.RotateY(10.);
1934 auto* rot = new TGeoRotation("rot");
1935 *rot = rot1 * rot2;
1936 //
1937 Double_t x0, y0;
1938 //
1939 // a and c sides separately because of possible different z-coordinate of first gem
1940 //
1941 x0 = 110.2 * TMath::Cos(openingAngle);
1942 y0 = 110.2 * TMath::Sin(openingAngle);
1943 auto* combi1a = new TGeoCombiTrans("combi1", x0, y0, 1.09, rot); // a-side
1944 auto* combi1c = new TGeoCombiTrans("combi1", x0, y0, 1.09, rot); // c-side
1945 x0 = 188.45 * TMath::Cos(openingAngle);
1946 y0 = 188.45 * TMath::Sin(openingAngle);
1947 auto* combi2a = new TGeoCombiTrans("combi2", x0, y0, 1.09, rot); // a-side
1948 auto* combi2c = new TGeoCombiTrans("combi2", x0, y0, 1.09, rot); // c-side
1949 //
1950 //
1951 // A-side
1952 //
1953 secta->AddNode(ch, 1);
1954 secta->AddNode(iroc, 1, combi1a);
1955 secta->AddNode(oroc, 1, combi2a);
1956 //
1957 // C-side
1958 //
1959 sectc->AddNode(ch, 1);
1960 sectc->AddNode(iroc, 1, combi1c);
1961 sectc->AddNode(oroc, 1, combi2c);
1962 //
1963 // now I try to make wheels...
1964 //
1965 auto* wheela = new TGeoVolumeAssembly("TPC_ENDCAP");
1966 auto* wheelc = new TGeoVolumeAssembly("TPC_ENDCAP");
1967 //
1968 for (Int_t i = 0; i < 18; i++) {
1969 Double_t phi = (20. * i);
1970 auto* rwh = new TGeoRotation();
1971 rwh->RotateZ(phi);
1972 wheela->AddNode(secta, i + 1, rwh);
1973 wheelc->AddNode(sectc, i + 1, rwh);
1974 }
1975 // wheels in the drift volume!
1976
1977 auto* combi3 = new TGeoCombiTrans("combi3", 0., 0., 256.6, ref);
1978 v9->AddNode(wheela, 1, combi3);
1979 v9->AddNode(wheelc, 2, new TGeoTranslation(0., 0., -256.6));
1980 //_____________________________________________________________
1981 // service support wheel
1982 //_____________________________________________________________
1983 auto* sw = new TGeoPgon(0., 20., 1, 2);
1984 sw->DefineSection(0, -4., 80.5, 251.75);
1985 sw->DefineSection(1, 4., 80.5, 251.75);
1986 auto* swv = new TGeoVolume("TPC_SWSEG", sw, m3); // Al
1987 //
1988 thick = 1.;
1989 shift = thick / TMath::Sin(openingAngle);
1990 auto* sh = new TGeoPgon(0., 20., 1, 2);
1991 sh->DefineSection(0, -4., 81.5 - shift, 250.75 - shift);
1992 sh->DefineSection(1, 4., 81.5 - shift, 250.75 - shift);
1993 auto* shv = new TGeoVolume("TPC_SWS1", sh, m1); // Air
1994 //
1995 TGeoMedium* m9 = gGeoManager->GetMedium("TPC_Si");
1996 auto* el = new TGeoPgon(0., 20., 1, 2);
1997 el->DefineSection(0, -1.872, 81.5 - shift, 250.75 - shift);
1998 el->DefineSection(1, 1.872, 81.5 - shift, 250.75 - shift);
1999 auto* elv = new TGeoVolume("TPC_ELEC", el, m9); // Si
2000 //
2001 shv->AddNode(elv, 1);
2002 //
2003 //
2004 ys = shift * TMath::Sin(openingAngle);
2005 xs = shift * TMath::Cos(openingAngle);
2006 swv->AddNode(shv, 1, new TGeoTranslation(xs, ys, 0.));
2007 // cover
2008 auto* co = new TGeoPgon(0., 20., 1, 2);
2009 co->DefineSection(0, -0.5, 77., 255.25);
2010 co->DefineSection(1, 0.5, 77., 255.25);
2011 auto* cov = new TGeoVolume("TPC_SWC1", co, m3); // Al
2012 // hole in a cover
2013 auto* coh = new TGeoPgon(0., 20., 1, 2);
2014 shift = 4. / TMath::Sin(openingAngle);
2015 coh->DefineSection(0, -0.5, 85. - shift, 247.25 - shift);
2016 coh->DefineSection(1, 0.5, 85. - shift, 247.25 - shift);
2017 //
2018 auto* cohv = new TGeoVolume("TPC_SWC2", coh, m1);
2019 //
2020 ys = shift * TMath::Sin(openingAngle);
2021 xs = shift * TMath::Cos(openingAngle);
2022 cov->AddNode(cohv, 1, new TGeoTranslation(xs, ys, 0.));
2023 //
2024 // Sector as an Assembly
2025 //
2026 auto* swhs = new TGeoVolumeAssembly("TPC_SSWSEC");
2027 swhs->AddNode(swv, 1);
2028 swhs->AddNode(cov, 1, new TGeoTranslation(0., 0., -4.5));
2029 swhs->AddNode(cov, 2, new TGeoTranslation(0., 0., 4.5));
2030 //
2031 // SSW as an Assembly of sectors
2032 //
2033 TGeoRotation* rsw[18];
2034 auto* swheel = new TGeoVolumeAssembly("TPC_SSWHEEL");
2035 for (Int_t i = 0; i < 18; i++) {
2036 Double_t phi = (20. * i);
2037 rsw[i] = new TGeoRotation();
2038 rsw[i]->RotateZ(phi);
2039 swheel->AddNode(swhs, i + 1, rsw[i]);
2040 }
2041 v1->AddNode(swheel, 1, new TGeoTranslation(0., 0., -284.6));
2042 v1->AddNode(swheel, 2, new TGeoTranslation(0., 0., 284.6));
2043
2044 // sensitive strips - strip "0" is always set
2045 // conditional
2047 Int_t totrows = 159;
2048 // totrows = mParam->GetNRowLow() + mParam->GetNRowUp();
2049 Double_t* upar;
2050 upar = nullptr;
2051 gGeoManager->Volume("TPC_Strip", "PGON", m5->GetId(), upar);
2052 upar = new Double_t[10];
2053 upar[0] = 0.;
2054 upar[1] = 360.;
2055 upar[2] = 18.;
2056 upar[3] = 2.;
2057 //
2058 upar[4] = -124.8;
2059 upar[7] = 124.8;
2060
2062 // Double_t rlow=mParam->GetPadRowRadiiLow(0);
2063 Double_t rlow = 85.225; // cm
2064
2065 upar[5] = rlow;
2066 upar[6] = rlow + .01;
2067 upar[8] = upar[5];
2068 upar[9] = upar[6];
2069 //
2070 gGeoManager->Node("TPC_Strip", 1, "TPC_Drift", 0., 0., 124.82, 0, kTRUE, upar, 10);
2071 gGeoManager->Node("TPC_Strip", totrows + 1, "TPC_Drift", 0., 0., -124.82, 0, kTRUE, upar, 10);
2072 //
2073 // now, strips optionally
2074 //
2075 // if(mSens){
2076 // //lower sectors
2077 // for(Int_t i=2;i<mParam->GetNRowLow()+1;i++){
2078 // rlow=mParam->GetPadRowRadiiLow(i-1);
2079 // upar[5]=rlow;
2080 // upar[6]=rlow+.01;
2081 // upar[8]=upar[5];
2082 // upar[9]=upar[6];
2083 // gGeoManager->Node("TPC_Strip",i,
2084 // "TPC_Drift",0.,0.,124.82,0,kTRUE,upar,10);
2085 // gGeoManager->Node("TPC_Strip",totrows+i,
2086 // "TPC_Drift",0.,0.,-124.82,0,kTRUE,upar,10);
2087 // }
2088 // //upper sectors
2089 // for(Int_t i=1;i<mParam->GetNRowUp()+1;i++){
2090 // rlow=mParam->GetPadRowRadiiUp(i-1);
2091 // upar[5]=rlow;
2092 // upar[6]=rlow+.01;
2093 // upar[8]=upar[5];
2094 // upar[9]=upar[6];
2095 // gGeoManager->Node("TPC_Strip",i+mParam->GetNRowLow(),
2096 // "TPC_Drift",0.,0.,124.82,0,kTRUE,upar,10);
2097 // gGeoManager->Node("TPC_Strip",totrows+i+mParam->GetNRowLow(),
2098 // "TPC_Drift",0.,0.,-124.82,0,kTRUE,upar,10);
2099 // }
2100 // }//strips
2101 //----------------------------------------------------------
2102 // TPC Support Rods - MAKROLON
2103 //----------------------------------------------------------
2104 //
2105 TGeoMedium* m7 = gGeoManager->GetMedium("TPC_Cu");
2106 TGeoMedium* m10 = gGeoManager->GetMedium("TPC_Alumina");
2107 TGeoMedium* m11 = gGeoManager->GetMedium("TPC_Peek");
2108 TGeoMedium* m13 = gGeoManager->GetMedium("TPC_Brass");
2109 TGeoMedium* m14 = gGeoManager->GetMedium("TPC_Alumina1");
2110 //
2111 // tpc rod is an assembly of 10 long parts and 2 short parts
2112 // connected with alu rings and plagged on both sides.
2113 //
2114 //
2115 // tpc rod long
2116 //
2117 auto* rod = new TGeoPcon("rod", 0., 360., 6);
2118 rod->DefineSection(0, -10.43, 1.92, 2.08);
2119 rod->DefineSection(1, -9.75, 1.92, 2.08);
2120
2121 rod->DefineSection(2, -9.75, 1.8, 2.2);
2122 rod->DefineSection(3, 9.75, 1.8, 2.2);
2123
2124 rod->DefineSection(4, 9.75, 1.92, 2.08);
2125 rod->DefineSection(5, 10.43, 1.92, 2.08);
2126 //
2127 auto* mrodl = new TGeoVolume("TPC_mrodl", rod, m6);
2128 //
2129 // tpc rod short
2130 //
2131 auto* rod1 = new TGeoPcon("rod1", 0., 360., 6);
2132 rod1->DefineSection(0, -8.93, 1.92, 2.08);
2133 rod1->DefineSection(1, -8.25, 1.92, 2.08);
2134
2135 rod1->DefineSection(2, -8.25, 1.8, 2.2);
2136 rod1->DefineSection(3, 8.25, 1.8, 2.2);
2137
2138 rod1->DefineSection(4, 8.25, 1.92, 2.08);
2139 rod1->DefineSection(5, 8.93, 1.92, 2.08);
2140 //
2141 auto* mrods = new TGeoVolume("TPC_mrods", rod1, m6);
2142 //
2143 // below is for the resistor rod
2144 //
2145 // hole for the brass connectors
2146 //
2147
2148 new TGeoTube("hhole", 0., 0.3, 0.3);
2149 //
2150 // transformations for holes - initialy they
2151 // are placed at x=0 and negative y
2152 //
2153 auto* rhole = new TGeoRotation();
2154 rhole->RotateX(90.);
2155 TGeoCombiTrans* transf[13];
2156 Char_t name[30];
2157 for (Int_t i = 0; i < 13; i++) {
2158 snprintf(name, 30, "transf%d", i);
2159 transf[i] = new TGeoCombiTrans(name, 0., -2., -9. + i * 1.5, rhole);
2160 transf[i]->RegisterYourself();
2161 }
2162 // union expression for holes
2163 TString operl("hhole:transf0");
2164 for (Int_t i = 1; i < 13; i++) {
2165 snprintf(name, 30, "+hhole:transf%d", i);
2166 operl.Append(name);
2167 }
2168 //
2169 TString opers("hhole:transf1");
2170 for (Int_t i = 2; i < 12; i++) {
2171 snprintf(name, 30, "+hhole:transf%d", i);
2172 opers.Append(name);
2173 }
2174 // union of holes
2175 new TGeoCompositeShape("hlv", operl.Data());
2176 new TGeoCompositeShape("hsv", opers.Data());
2177 //
2178 auto* rodl = new TGeoCompositeShape("rodl", "rod-hlv");
2179 auto* rods = new TGeoCompositeShape("rods", "rod1-hsv");
2180 // rods - volumes - makrolon rods with holes
2181 auto* rodlv = new TGeoVolume("TPC_rodl", rodl, m6);
2182 auto* rodsv = new TGeoVolume("TPC_rods", rods, m6);
2183 // brass connectors
2184 // connectors
2185 auto* bcon = new TGeoTube(0., 0.3, 0.3); // connectors
2186 auto* bconv = new TGeoVolume("TPC_bcon", bcon, m13);
2187 //
2188 // hooks holding strips
2189 //
2190 new TGeoBBox("hk1", 0.625, 0.015, 0.75);
2191 new TGeoBBox("hk2", 0.625, 0.015, 0.15);
2192 auto* tr21 = new TGeoTranslation("tr21", 0., -0.03, -0.6);
2193 auto* tr12 = new TGeoTranslation("tr12", 0., -0.03, 0.6);
2194 tr21->RegisterYourself();
2195 tr12->RegisterYourself();
2196
2197 auto* hook = new TGeoCompositeShape("hook", "hk1+hk2:tr21+hk2:tr12");
2198 auto* hookv = new TGeoVolume("TPC_hook", hook, m13);
2199 //
2200 // assembly of the short rod with connectors and hooks
2201 //
2202 //
2203 // short rod
2204 //
2205 auto* spart = new TGeoVolumeAssembly("TPC_spart");
2206 //
2207 spart->AddNode(rodsv, 1);
2208 for (Int_t i = 1; i < 12; i++) {
2209 spart->AddNode(bconv, i, transf[i]);
2210 }
2211 for (Int_t i = 0; i < 11; i++) {
2212 spart->AddNode(hookv, i + 1, new TGeoTranslation(0., -2.315, -7.5 + i * 1.5));
2213 }
2214 //
2215 // long rod
2216 //
2217 auto* lpart = new TGeoVolumeAssembly("TPC_lpart");
2218 //
2219 lpart->AddNode(rodlv, 1);
2220 for (Int_t i = 0; i < 13; i++) {
2221 lpart->AddNode(bconv, i + 12, transf[i]);
2222 }
2223 for (Int_t i = 0; i < 13; i++) {
2224 lpart->AddNode(hookv, i + 12, new TGeoTranslation(0., -2.315, -9. + i * 1.5));
2225 }
2226 //
2227 // alu ring
2228 //
2229 new TGeoTube("ring1", 2.1075, 2.235, 0.53);
2230 new TGeoTube("ring2", 1.7925, 1.89, 0.43);
2231 new TGeoTube("ring3", 1.89, 2.1075, 0.05);
2232 auto* ring = new TGeoCompositeShape("ring", "ring1+ring2+ring3");
2233 auto* ringv = new TGeoVolume("TPC_ring", ring, m3);
2234 //
2235 // rod assembly
2236 //
2237 auto* tpcrrod = new TGeoVolumeAssembly("TPC_rrod"); // rrod
2238 auto* tpcmrod = new TGeoVolumeAssembly("TPC_mrod"); // makrolon rod
2239 // long pieces
2240 for (Int_t i = 0; i < 11; i++) {
2241 tpcrrod->AddNode(ringv, i + 1, new TGeoTranslation(0., 0., -105. + i * 21));
2242 tpcmrod->AddNode(ringv, i + 12, new TGeoTranslation(0., 0., -105. + i * 21));
2243 }
2244 for (Int_t i = 0; i < 10; i++) {
2245 tpcrrod->AddNode(lpart, i + 1, new TGeoTranslation(0., 0., -94.5 + i * 21)); // resistor rod
2246 tpcmrod->AddNode(mrodl, i + 1, new TGeoTranslation(0., 0., -94.5 + i * 21)); // makrolon rod
2247 }
2248 //
2249 // right plug - identical for all rods
2250 //
2251 auto* tpcrp = new TGeoPcon(0., 360., 6);
2252 //
2253 tpcrp->DefineSection(0, 123.05, 1.89, 2.1075);
2254 tpcrp->DefineSection(1, 123.59, 1.89, 2.1075);
2255 //
2256 tpcrp->DefineSection(2, 123.59, 1.8, 2.2);
2257 tpcrp->DefineSection(3, 127., 1.8, 2.2);
2258 //
2259 tpcrp->DefineSection(4, 127., 0., 2.2);
2260 tpcrp->DefineSection(5, 127.5, 0., 2.2);
2261 //
2262 auto* tpcrpv = new TGeoVolume("TPC_RP", tpcrp, m6);
2263 //
2264 // adding short pieces and right plug
2265 //
2266 tpcrrod->AddNode(spart, 1, new TGeoTranslation(0., 0., -114.));
2267 tpcrrod->AddNode(spart, 2, new TGeoTranslation(0., 0., 114.));
2268 tpcrrod->AddNode(ringv, 23, new TGeoTranslation(0., 0., -123.));
2269 tpcrrod->AddNode(ringv, 24, new TGeoTranslation(0., 0., 123.));
2270 tpcrrod->AddNode(tpcrpv, 1);
2271 //
2272 tpcmrod->AddNode(mrods, 1, new TGeoTranslation(0., 0., -114.));
2273 tpcmrod->AddNode(mrods, 2, new TGeoTranslation(0., 0., 114.));
2274 tpcmrod->AddNode(ringv, 25, new TGeoTranslation(0., 0., -123.));
2275 tpcmrod->AddNode(ringv, 26, new TGeoTranslation(0., 0., 123.));
2276 tpcmrod->AddNode(tpcrpv, 2);
2277 //
2278 // from the ringv position to the CM is 3.0 cm!
2279 //----------------------------------------
2280 //
2281 //
2282 // HV rods - makrolon + 0.58cm (diameter) Cu ->check the length
2283 auto* hvr = new TGeoTube(0., 1.465, 123.);
2284 auto* hvc = new TGeoTube(0., 0.29, 123.);
2285 //
2286 auto* hvrv = new TGeoVolume("TPC_HV_Rod", hvr, m6);
2287 auto* hvcv = new TGeoVolume("TPC_HV_Cable", hvc, m7);
2288 hvrv->AddNode(hvcv, 1);
2289 //
2290 // resistor rod
2291 //
2292 auto* cr = new TGeoTube(0., 0.45, 123.);
2293 auto* cw = new TGeoTube(0., 0.15, 123.);
2294 auto* crv = new TGeoVolume("TPC_CR", cr, m10);
2295 auto* cwv = new TGeoVolume("TPC_W", cw, m12);
2296 //
2297 // ceramic rod with water
2298 //
2299 crv->AddNode(cwv, 1);
2300 //
2301 // peek rod
2302 //
2303 auto* pr = new TGeoTube(0.2, 0.35, 123.);
2304 auto* prv = new TGeoVolume("TPC_PR", pr, m11);
2305 //
2306 // copper plates with connectors
2307 //
2308 new TGeoTube("tub", 0., 1.7, 0.025);
2309 //
2310 // half space - points on the plane and a normal vector
2311 //
2312 Double_t n[3], p[3];
2313 Double_t slope = TMath::Tan(22. * TMath::DegToRad());
2314 Double_t intp = 1.245;
2315 //
2316 Double_t b = slope * slope + 1.;
2317 p[0] = intp * slope / b;
2318 p[1] = -intp / b;
2319 p[2] = 0.;
2320 //
2321 n[0] = -p[0];
2322 n[1] = -p[1];
2323 n[2] = 0.;
2324 Double_t norm;
2325 norm = TMath::Sqrt(n[0] * n[0] + n[1] * n[1]);
2326 n[0] /= norm;
2327 n[1] /= norm;
2328 //
2329 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("sp1", p, n, kHalfSpaceReach);
2330 //
2331 slope = -slope;
2332 //
2333 p[0] = intp * slope / b;
2334 p[1] = -intp / b;
2335 //
2336 n[0] = -p[0];
2337 n[1] = -p[1];
2338 norm = TMath::Sqrt(n[0] * n[0] + n[1] * n[1]);
2339 n[0] /= norm;
2340 n[1] /= norm;
2341 //
2342 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("sp2", p, n, kHalfSpaceReach);
2343 // holes for rods
2344 // holes
2345 new TGeoTube("h1", 0., 0.5, 0.025);
2346 new TGeoTube("h2", 0., 0.35, 0.025);
2347 // translations:
2348 auto* ttr11 = new TGeoTranslation("ttr11", -0.866, 0.5, 0.);
2349 auto* ttr22 = new TGeoTranslation("ttr22", 0.866, 0.5, 0.);
2350 ttr11->RegisterYourself();
2351 ttr22->RegisterYourself();
2352 // elastic connector
2353 new TGeoBBox("elcon", 0.72, 0.005, 0.3);
2354 auto* crr1 = new TGeoRotation();
2355 crr1->RotateZ(-22.);
2356 auto* ctr1 = new TGeoCombiTrans("ctr1", -0.36011, -1.09951, -0.325, crr1);
2357 ctr1->RegisterYourself();
2358 auto* cs1 = new TGeoCompositeShape("cs1", "(((((tub-h1:ttr11)-h1:ttr22)-(sp1:sp1_tr))-(sp2:sp2_tr))-h2)+elcon:ctr1");
2359 //
2360 auto* csvv = new TGeoVolume("TPC_RR_CU", cs1, m7);
2361 //
2362 // resistor rod assembly 2 ceramic rods, peak rod, Cu plates
2363 // and resistors
2364 //
2365 auto* rrod = new TGeoVolumeAssembly("TPC_RRIN");
2366 // rods
2367 rrod->AddNode(crv, 1, ttr11);
2368 rrod->AddNode(crv, 2, ttr22);
2369 rrod->AddNode(prv, 1);
2370 // Cu plates
2371 for (Int_t i = 0; i < 165; i++) {
2372 rrod->AddNode(csvv, i + 1, new TGeoTranslation(0., 0., -122.675 + i * 1.5));
2373 }
2374 // resistors
2375 auto* res = new TGeoTube(0., 0.15, 0.5);
2376 auto* resv = new TGeoVolume("TPC_RES", res, m14);
2377 auto* ress = new TGeoVolumeAssembly("TPC_RES_CH");
2378 ress->AddNode(resv, 1, new TGeoTranslation(0.2, 0., 0.));
2379 ress->AddNode(resv, 2, new TGeoTranslation(-0.2, 0., 0.));
2380 //
2381 auto* crr2 = new TGeoRotation();
2382 crr2->RotateY(30.);
2383 auto* crr3 = new TGeoRotation();
2384 crr3->RotateY(-30.);
2385 //
2386 for (Int_t i = 0; i < 164; i += 2) {
2387 rrod->AddNode(ress, i + 1, new TGeoCombiTrans(0., 1.2, -121.925 + i * 1.5, crr2));
2388 rrod->AddNode(ress, i + 2, new TGeoCombiTrans(0., 1.2, -121.925 + (i + 1) * 1.5, crr3));
2389 }
2390
2391 tpcrrod->AddNode(rrod, 1, new TGeoCombiTrans(0., 0., 0.5, crr1));
2392 //
2393 // rod left head with holders - inner
2394 //
2395 // first element - support for inner holder TPC_IHS
2396 Double_t shift1[3] = {0.0, -0.175, 0.0};
2397
2398 new TGeoBBox("tpcihs1", 4.7, 0.66, 2.35);
2399 new TGeoBBox("tpcihs2", 4.7, 0.485, 1.0, shift1);
2400 new TGeoBBox("tpcihs3", 1.5, 0.485, 2.35, shift1);
2401 new TGeoTube("tpcihs4", 0.0, 2.38, 0.1);
2402 //
2403 Double_t pointstrap[16];
2404 pointstrap[0] = 0.0;
2405 pointstrap[1] = 0.0;
2406 pointstrap[2] = 0.0;
2407 pointstrap[3] = 1.08;
2408 pointstrap[4] = 2.3;
2409 pointstrap[5] = 1.08;
2410 pointstrap[6] = 3.38;
2411 pointstrap[7] = 0.0;
2412 pointstrap[8] = 0.0;
2413 pointstrap[9] = 0.0;
2414 pointstrap[10] = 0.0;
2415 pointstrap[11] = 1.08;
2416 pointstrap[12] = 2.3;
2417 pointstrap[13] = 1.08;
2418 pointstrap[14] = 3.38;
2419 pointstrap[15] = 0.0;
2420 //
2421 auto* tpcihs5 = new TGeoArb8("tpcihs5", 0.6, pointstrap);
2422 //
2423 // half space - cutting "legs"
2424 //
2425 p[0] = 0.0;
2426 p[1] = 0.105;
2427 p[2] = 0.0;
2428 //
2429 n[0] = 0.0;
2430 n[1] = 1.0;
2431 n[2] = 0.0;
2432
2433 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutil1", p, n, kHalfSpaceReach);
2434
2435 //
2436 // transformations
2437 //
2438 auto* trans2 = new TGeoTranslation("trans2", 0.0, 2.84, 2.25);
2439 trans2->RegisterYourself();
2440 auto* trans3 = new TGeoTranslation("trans3", 0.0, 2.84, -2.25);
2441 trans3->RegisterYourself();
2442 // support - composite volume
2443 //
2444 auto* tpcihs6 =
2445 new TGeoCompositeShape("tpcihs6", "tpcihs1-(tpcihs2+tpcihs3)-(tpcihs4:trans2)-(tpcihs4:trans3)-(cutil1:cutil1_tr)");
2446 //
2447 // volumes - all makrolon
2448 //
2449 auto* tpcihss = new TGeoVolume("TPC_IHSS", tpcihs6, m6); // support
2450 auto* tpcihst = new TGeoVolume("TPC_IHSTR", tpcihs5, m6); // trapesoid
2451 // now assembly
2452 auto* rot111 = new TGeoRotation();
2453 rot111->RotateY(180.0);
2454 //
2455 auto* tpcihs = new TGeoVolumeAssembly("TPC_IHS"); // assembly of the support
2456 tpcihs->AddNode(tpcihss, 1);
2457 tpcihs->AddNode(tpcihst, 1, new TGeoTranslation(-4.7, 0.66, 0.0));
2458 tpcihs->AddNode(tpcihst, 2, new TGeoCombiTrans(4.7, 0.66, 0.0, rot111));
2459 //
2460 // two rod holders (TPC_IRH) assembled with the support
2461 //
2462 new TGeoBBox("tpcirh1", 4.7, 1.33, 0.5);
2463 shift1[0] = -3.65;
2464 shift1[1] = 0.53;
2465 shift1[2] = 0.;
2466 new TGeoBBox("tpcirh2", 1.05, 0.8, 0.5, shift1);
2467 shift1[0] = 3.65;
2468 shift1[1] = 0.53;
2469 shift1[2] = 0.;
2470 new TGeoBBox("tpcirh3", 1.05, 0.8, 0.5, shift1);
2471 shift1[0] = 0.0;
2472 shift1[1] = 1.08;
2473 shift1[2] = 0.;
2474 new TGeoBBox("tpcirh4", 1.9, 0.25, 0.5, shift1);
2475 new TGeoTube("tpcirh5", 0, 1.9, 5);
2476 //
2477 auto* trans4 = new TGeoTranslation("trans4", 0, 0.83, 0.0);
2478 trans4->RegisterYourself();
2479 //
2480 auto* tpcirh6 = new TGeoCompositeShape("tpcirh6", "tpcirh1-tpcirh2-tpcirh3-(tpcirh5:trans4)-tpcirh4");
2481 //
2482 // now volume
2483 //
2484 auto* tpcirh = new TGeoVolume("TPC_IRH", tpcirh6, m6);
2485 //
2486 // and all together...
2487 //
2488 TGeoVolume* tpciclamp = new TGeoVolumeAssembly("TPC_ICLP");
2489 tpciclamp->AddNode(tpcihs, 1);
2490 tpciclamp->AddNode(tpcirh, 1, new TGeoTranslation(0, 1.99, 1.1));
2491 tpciclamp->AddNode(tpcirh, 2, new TGeoTranslation(0, 1.99, -1.1));
2492 //
2493 // and now left inner "head"
2494 //
2495 auto* inplug = new TGeoPcon("inplug", 0.0, 360.0, 13);
2496
2497 inplug->DefineSection(0, 0.3, 0.0, 2.2);
2498 inplug->DefineSection(1, 0.6, 0.0, 2.2);
2499
2500 inplug->DefineSection(2, 0.6, 0.0, 1.75);
2501 inplug->DefineSection(3, 0.7, 0.0, 1.75);
2502
2503 inplug->DefineSection(4, 0.7, 1.55, 1.75);
2504 inplug->DefineSection(5, 1.6, 1.55, 1.75);
2505
2506 inplug->DefineSection(6, 1.6, 1.55, 2.2);
2507 inplug->DefineSection(7, 1.875, 1.55, 2.2);
2508
2509 inplug->DefineSection(8, 2.47, 1.75, 2.2);
2510
2511 inplug->DefineSection(9, 2.47, 1.75, 2.08);
2512 inplug->DefineSection(10, 2.57, 1.8, 2.08);
2513
2514 inplug->DefineSection(11, 2.57, 1.92, 2.08);
2515 inplug->DefineSection(12, 2.95, 1.92, 2.08);
2516 //
2517 shift1[0] = 0.0;
2518 shift1[1] = -2.09;
2519 shift1[2] = 1.075;
2520 //
2521 new TGeoBBox("pcuti", 1.5, 0.11, 1.075, shift1);
2522 //
2523 auto* inplleft = new TGeoCompositeShape("inplleft", "inplug-pcuti");
2524 auto* tpcinlplug = new TGeoVolume("TPC_INPLL", inplleft, m6);
2525 //
2526 // holder + plugs
2527 //
2528 TGeoVolume* tpcihpl = new TGeoVolumeAssembly("TPC_IHPL"); // holder+2 plugs (reflected)
2529 tpcihpl->AddNode(tpcinlplug, 1);
2530 tpcihpl->AddNode(tpcinlplug, 2, ref);
2531 tpcihpl->AddNode(tpciclamp, 1, new TGeoTranslation(0.0, -2.765, 0.0));
2532 //
2533 // outer holders and clamps
2534 //
2535
2536 // outer membrane holder (between rods)
2537 pointstrap[0] = 0.0;
2538 pointstrap[1] = 0.0;
2539 pointstrap[2] = 0.0;
2540 pointstrap[3] = 2.8;
2541 pointstrap[4] = 3.1;
2542 pointstrap[5] = 2.8 - 3.1 * TMath::Tan(15. * TMath::DegToRad());
2543 pointstrap[6] = 3.1;
2544 pointstrap[7] = 0.0;
2545 pointstrap[8] = 0.0;
2546 pointstrap[9] = 0.0;
2547 pointstrap[10] = 0.0;
2548 pointstrap[11] = 2.8;
2549 pointstrap[12] = 3.1;
2550 pointstrap[13] = 2.8 - 3.1 * TMath::Tan(15. * TMath::DegToRad());
2551 pointstrap[14] = 3.1;
2552 pointstrap[15] = 0.0;
2553 //
2554 auto* tpcomh1 = new TGeoArb8("tpcomh1", 1.05, pointstrap);
2555 auto* tpcomh2 = new TGeoBBox("tpcomh2", 0.8, 1.4, 6);
2556 //
2557 auto* tpcomh1v = new TGeoVolume("TPC_OMH1", tpcomh1, m7);
2558 auto* tpcomh2v = new TGeoVolume("TPC_OMH2", tpcomh2, m7);
2559 //
2560 TGeoVolume* tpcomh3v = new TGeoVolumeAssembly("TPC_OMH3"); // assembly1
2561 tpcomh3v->AddNode(tpcomh1v, 1, new TGeoTranslation(0.8, -1.4, 4.95));
2562 tpcomh3v->AddNode(tpcomh1v, 2, new TGeoTranslation(0.8, -1.4, -4.95));
2563 tpcomh3v->AddNode(tpcomh2v, 1);
2564 //
2565 shift1[0] = 0.9;
2566 shift1[1] = -1.85;
2567 shift1[2] = 0.0;
2568 //
2569 new TGeoBBox("tpcomh3", 1.65, 1.15, 3.4);
2570 auto* tpcomh4 = new TGeoBBox("tpcomh4", 0.75, 0.7, 3.4, shift1);
2571 //
2572 // halfspace 1
2573 //
2574 p[0] = 0.0;
2575 p[1] = -1.05;
2576 p[2] = -3.4;
2577 //
2578 n[0] = 0.0;
2579 n[1] = -1.0 * TMath::Tan(30. * TMath::DegToRad());
2580 n[2] = 1.0;
2581 //
2582 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutomh1", p, n, kHalfSpaceReach);
2583 //
2584 // halfspace 2
2585 //
2586 p[0] = 0.0;
2587 p[1] = -1.05;
2588 p[2] = 3.4;
2589 //
2590 n[0] = 0.0;
2591 n[1] = -1.0 * TMath::Tan(30. * TMath::DegToRad());
2592 n[2] = -1.0;
2593 //
2594 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutomh2", p, n, kHalfSpaceReach);
2595 //
2596 // halfspace 3
2597 //
2598 p[0] = -1.65;
2599 p[1] = 0.0;
2600 p[2] = -0.9;
2601 //
2602 n[0] = 1.0 * TMath::Tan(75. * TMath::DegToRad());
2603 n[1] = 0.0;
2604 n[2] = 1.0;
2605 //
2606 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutomh3", p, n, kHalfSpaceReach);
2607 //
2608 // halfspace 4
2609 //
2610 p[0] = -1.65;
2611 p[1] = 0.0;
2612 p[2] = 0.9;
2613 //
2614 n[0] = 1.0 * TMath::Tan(75 * TMath::DegToRad());
2615 n[1] = 0.0;
2616 n[2] = -1.0;
2617 //
2618 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutomh4", p, n, kHalfSpaceReach);
2619 //
2620 // halsfspace 5
2621 //
2622 p[0] = 1.65;
2623 p[1] = -1.05;
2624 p[2] = 0.0;
2625 //
2626 n[0] = -1.0;
2627 n[1] = -1.0 * TMath::Tan(20. * TMath::DegToRad());
2628 n[2] = 0.0;
2629 //
2630 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutomh5", p, n, kHalfSpaceReach);
2631 //
2632 auto* tpcomh5 = new TGeoCompositeShape("tpcomh5", "tpcomh3-(cutomh1:cutomh1_tr)-(cutomh2:cutomh2_tr)-(cutomh3:cutomh3_tr)-(cutomh4:cutomh4_tr)-(cutomh5:cutomh5_tr)");
2633 //
2634 auto* tpcomh5v = new TGeoVolume("TPC_OMH5", tpcomh5, m6);
2635 auto* tpcomh4v = new TGeoVolume("TPC_OMH6", tpcomh4, m6);
2636 //
2637 auto* tpcomh7v = new TGeoVolumeAssembly("TPC_OMH7");
2638 tpcomh7v->AddNode(tpcomh5v, 1);
2639 tpcomh7v->AddNode(tpcomh4v, 1);
2640 //
2641 // full membrane holder - tpcomh3v + tpcomh7v
2642 //
2643 auto* tpcomh = new TGeoVolumeAssembly("TPC_OMH");
2644 tpcomh->AddNode(tpcomh3v, 1, new TGeoTranslation(1.5, 0., 0.));
2645 tpcomh->AddNode(tpcomh3v, 2, new TGeoCombiTrans(-1.5, 0., 0., rot111));
2646 tpcomh->AddNode(tpcomh7v, 1, new TGeoTranslation(0.65 + 1.5, 2.55, 0.0));
2647 tpcomh->AddNode(tpcomh7v, 2, new TGeoCombiTrans(-0.65 - 1.5, 2.55, 0.0, rot111));
2648 //
2649 // outer rod holder support
2650 //
2651 new TGeoBBox("tpcohs1", 3.8, 0.675, 2.35);
2652 //
2653 shift1[0] = 0.0;
2654 shift1[1] = 0.175;
2655 shift1[2] = 0.0;
2656 //
2657 new TGeoBBox("tpcohs2", 1.5, 0.5, 2.35, shift1);
2658 new TGeoBBox("tpcohs3", 3.8, 0.5, 0.85, shift1);
2659 //
2660 shift1[0] = 0.0;
2661 shift1[1] = -1.175;
2662 shift1[2] = 0.0;
2663 //
2664 auto* tpcohs4 = new TGeoBBox("tpsohs4", 3.1, 0.5, 0.7, shift1);
2665 //
2666 auto* tpcohs4v = new TGeoVolume("TPC_OHS4", tpcohs4, m6);
2667 //
2668 p[0] = 0.0;
2669 p[1] = -0.186;
2670 p[2] = 0.0;
2671 //
2672 n[0] = 0.0;
2673 n[1] = -1.0;
2674 n[2] = 0.0;
2675 //
2676 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutohs1", p, n, kHalfSpaceReach);
2677 //
2678 auto* tpcohs5 = new TGeoCompositeShape("tpcohs5", "tpcohs1-tpcohs2-tpcohs3-(cutohs1:cutohs1_tr)");
2679 auto* tpcohs5v = new TGeoVolume("TPC_OHS5", tpcohs5, m6);
2680 //
2681 auto* tpcohs = new TGeoVolumeAssembly("TPC_OHS");
2682 tpcohs->AddNode(tpcohs5v, 1);
2683 tpcohs->AddNode(tpcohs4v, 1);
2684 //
2685 // outer rod holder itself
2686 //
2687 shift1[0] = 0.0;
2688 shift1[1] = 1.325;
2689 shift1[2] = 0.0;
2690 new TGeoBBox("tpcorh1", 3.1, 1.825, 0.55); // from this box we cut pieces...
2691 //
2692 shift1[0] = -3.1;
2693 shift1[1] = -0.5;
2694 shift1[2] = 0.0;
2695 //
2696 new TGeoBBox("tpcorh2", 0.5, 2.75, 1.1, shift1);
2697 //
2698 shift1[0] = 3.1;
2699 shift1[1] = -0.5;
2700 shift1[2] = 0.0;
2701 //
2702 new TGeoBBox("tpcorh3", 0.5, 2.75, 1.1, shift1);
2703 //
2704 shift1[0] = 0.0;
2705 shift1[1] = -0.5;
2706 shift1[2] = -0.95;
2707 //
2708 new TGeoBBox("tpcorh4", 3.9, 2.75, 0.5, shift1);
2709 //
2710 shift1[0] = 0.0;
2711 shift1[1] = -0.5;
2712 shift1[2] = 0.0;
2713 //
2714 new TGeoBBox("tpcorh5", 1.95, 0.5, 1.1, shift1);
2715 //
2716 shift1[0] = 0.0;
2717 shift1[1] = -0.5;
2718 shift1[2] = 0.55;
2719 //
2720 new TGeoBBox("tpcorh6", 2.4, 0.5, 0.6, shift1);
2721 //
2722 new TGeoTube("tpcorh7", 0, 1.95, 0.85);
2723 new TGeoTube("tpcorh8", 0, 2.4, 0.6);
2724 //
2725 auto* trans33 = new TGeoTranslation("trans33", 0.0, 0.0, 0.55);
2726 trans33->RegisterYourself();
2727 //
2728 auto* tpcorh9 =
2729 new TGeoCompositeShape("tpcorh9", "tpcorh1-tpcorh2-tpcorh3-tpcorh4-tpcorh5-tpcorh6-(tpcorh8:trans33)-tpcorh7");
2730 //
2731 auto* tpcorh9v = new TGeoVolume("TPC_ORH", tpcorh9, m6); // outer rod holder
2732 //
2733 // now 2 holders together
2734 //
2735 auto* tpcorh = new TGeoVolumeAssembly("TPC_ORH2");
2736 //
2737 tpcorh->AddNode(tpcorh9v, 1, new TGeoTranslation(0.0, 0.0, 1.25));
2738 tpcorh->AddNode(tpcorh9v, 2, new TGeoCombiTrans(0.0, 0.0, -1.25, rot111));
2739 //
2740 // outer rod plug left
2741 //
2742 auto* outplug = new TGeoPcon("outplug", 0.0, 360.0, 13);
2743
2744 outplug->DefineSection(0, 0.5, 0.0, 2.2);
2745 outplug->DefineSection(1, 0.7, 0.0, 2.2);
2746 outplug->DefineSection(2, 0.7, 1.55, 2.2);
2747 outplug->DefineSection(3, 0.8, 1.55, 2.2);
2748 outplug->DefineSection(4, 0.8, 1.55, 1.75);
2749 outplug->DefineSection(5, 1.2, 1.55, 1.75);
2750 outplug->DefineSection(6, 1.2, 1.55, 2.2);
2751 outplug->DefineSection(7, 1.875, 1.55, 2.2);
2752 outplug->DefineSection(8, 2.47, 1.75, 2.2);
2753 outplug->DefineSection(9, 2.47, 1.75, 2.08);
2754 outplug->DefineSection(10, 2.57, 1.8, 2.08);
2755 outplug->DefineSection(11, 2.57, 1.92, 2.08);
2756 outplug->DefineSection(12, 2.95, 1.92, 2.08);
2757 //
2758 shift1[0] = 0.0;
2759 shift1[1] = 2.09;
2760 shift1[2] = 1.01;
2761
2762 new TGeoBBox("cutout", 2.5, 0.11, 1.01, shift1);
2763 //
2764
2765 auto* outplleft = new TGeoCompositeShape("outplleft", "outplug-cutout");
2766 auto* outplleftv = new TGeoVolume("TPC_OPLL", outplleft, m6);
2767 //
2768 // support + holder + plug
2769 //
2770
2771 auto* tpcohpl = new TGeoVolumeAssembly("TPC_OHPL");
2772 //
2773 tpcohpl->AddNode(outplleftv, 1); // plug
2774 tpcohpl->AddNode(outplleftv, 2, ref); // plug reflected
2775 tpcohpl->AddNode(tpcorh, 1); // rod holder
2776 tpcohpl->AddNode(tpcohs, 1, new TGeoTranslation(0.0, 3.925, 0)); // support
2777 //
2778
2779 //
2780 // main membrane holder
2781 //
2782 pointstrap[0] = 0.0;
2783 pointstrap[1] = 0.0;
2784 pointstrap[2] = 0.0;
2785 pointstrap[3] = 2.8;
2786 pointstrap[4] = 3.1;
2787 pointstrap[5] = 1.96;
2788 pointstrap[6] = 3.1;
2789 pointstrap[7] = 0.0;
2790 pointstrap[8] = 0.0;
2791 pointstrap[9] = 0.0;
2792 pointstrap[10] = 0.0;
2793 pointstrap[11] = 2.8;
2794 pointstrap[12] = 3.1;
2795 pointstrap[13] = 1.96;
2796 pointstrap[14] = 3.1;
2797 pointstrap[15] = 0.0;
2798 //
2799 auto* tpcmmh1 = new TGeoArb8("tpcmmh1", 1.75, pointstrap);
2800 auto* tpcmmh2 = new TGeoBBox("tpcmmh2", 0.8, 1.4, 12.5);
2801 //
2802 auto* tpcmmh1v = new TGeoVolume("TPC_MMH1", tpcmmh1, m6);
2803 auto* tpcmmh2v = new TGeoVolume("TPC_MMH2", tpcmmh2, m6);
2804 //
2805 auto* tpcmmhs = new TGeoVolumeAssembly("TPC_MMHS");
2806 tpcmmhs->AddNode(tpcmmh1v, 1, new TGeoTranslation(0.8, -1.4, 10.75));
2807 tpcmmhs->AddNode(tpcmmh1v, 2, new TGeoTranslation(0.8, -1.4, -10.75));
2808 tpcmmhs->AddNode(tpcmmh2v, 1);
2809 //
2810 // main membrahe holder clamp
2811 //
2812 shift1[0] = -0.75;
2813 shift1[1] = -1.15;
2814 shift1[2] = 0.0;
2815 //
2816 new TGeoBBox("tpcmmhc1", 1.65, 1.85, 8.9);
2817 new TGeoBBox("tpcmmhc2", 0.9, 0.7, 8.9, shift1);
2818 //
2819 // half spaces - cuts
2820 //
2821 p[0] = -1.65;
2822 p[1] = 0.0;
2823 p[2] = -0.9;
2824 //
2825 n[0] = 8.0;
2826 n[1] = 0.0;
2827 n[2] = 8.0 * TMath::Tan(13. * TMath::DegToRad());
2828 //
2829 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutmmh1", p, n, kHalfSpaceReach);
2830 //
2831 p[0] = -1.65;
2832 p[1] = 0.0;
2833 p[2] = 0.9;
2834 //
2835 n[0] = 8.0;
2836 n[1] = 0.0;
2837 n[2] = -8.0 * TMath::Tan(13. * TMath::DegToRad());
2838 //
2839 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutmmh2", p, n, kHalfSpaceReach);
2840 //
2841 p[0] = 0.0;
2842 p[1] = 1.85;
2843 p[2] = -2.8;
2844 //
2845 n[0] = 0.0;
2846 n[1] = -6.1;
2847 n[2] = 6.1 * TMath::Tan(20. * TMath::DegToRad());
2848 //
2849 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutmmh3", p, n, kHalfSpaceReach);
2850 //
2851 p[0] = 0.0;
2852 p[1] = 1.85;
2853 p[2] = 2.8;
2854 //
2855 n[0] = 0.0;
2856 n[1] = -6.1;
2857 n[2] = -6.1 * TMath::Tan(20 * TMath::DegToRad());
2858 //
2859 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutmmh4", p, n, kHalfSpaceReach);
2860 //
2861 p[0] = 0.75;
2862 p[1] = 0.0;
2863 p[2] = -8.9;
2864 //
2865 n[0] = 2.4 * TMath::Tan(30 * TMath::DegToRad());
2866 n[1] = 0.0;
2867 n[2] = 2.4;
2868 //
2869 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutmmh5", p, n, kHalfSpaceReach);
2870 //
2871 p[0] = 0.75;
2872 p[1] = 0.0;
2873 p[2] = 8.9;
2874 //
2875 n[0] = 2.4 * TMath::Tan(30 * TMath::DegToRad());
2876 n[1] = 0.0;
2877 n[2] = -2.4;
2878 //
2879 o2::base::TGeoGeometryUtils::makeHalfSpaceBox("cutmmh6", p, n, kHalfSpaceReach);
2880
2881 auto* tpcmmhc =
2882 new TGeoCompositeShape("TPC_MMHC", "tpcmmhc1-tpcmmhc2-(cutmmh1:cutmmh1_tr)-(cutmmh2:cutmmh2_tr)-(cutmmh3:cutmmh3_tr)-(cutmmh4:cutmmh4_tr)-(cutmmh5:cutmmh5_tr)-(cutmmh6:cutmmh6_tr)");
2883
2884 auto* tpcmmhcv = new TGeoVolume("TPC_MMHC", tpcmmhc, m6);
2885 //
2886 TGeoVolume* tpcmmh = new TGeoVolumeAssembly("TPC_MMH");
2887 //
2888 tpcmmh->AddNode(tpcmmhcv, 1, new TGeoTranslation(0.65 + 1.5, 1.85, 0.0));
2889 tpcmmh->AddNode(tpcmmhcv, 2, new TGeoCombiTrans(-0.65 - 1.5, 1.85, 0.0, rot111));
2890 tpcmmh->AddNode(tpcmmhs, 1, new TGeoTranslation(1.5, 0.0, 0.0));
2891 tpcmmh->AddNode(tpcmmhs, 2, new TGeoCombiTrans(-1.5, 0.0, 0.0, rot111));
2892 //
2893
2894 //
2895
2896 //--------------------------------------------
2897 //
2898 // guard ring resistor chain
2899 //
2900
2901 auto* gres1 = new TGeoTube(0., 0.375, 125.); // inside ifc
2902 //
2903 auto* vgres1 = new TGeoVolume("TPC_GRES1", gres1, m14);
2904
2905 //
2906 Double_t xrc, yrc;
2907 //
2908 xrc = 79.3 * TMath::Cos(350. * TMath::DegToRad());
2909 yrc = 79.3 * TMath::Sin(350. * TMath::DegToRad());
2910 //
2911 v9->AddNode(vgres1, 1, new TGeoTranslation(xrc, yrc, 126.9));
2912 v9->AddNode(vgres1, 2, new TGeoTranslation(xrc, yrc, -126.9));
2913 //
2914 xrc = 79.3 * TMath::Cos(190. * TMath::DegToRad());
2915 yrc = 79.3 * TMath::Sin(190. * TMath::DegToRad());
2916 //
2917 v9->AddNode(vgres1, 3, new TGeoTranslation(xrc, yrc, 126.9));
2918 v9->AddNode(vgres1, 4, new TGeoTranslation(xrc, yrc, -126.9));
2919 //------------------------------------------------------------------
2920 TGeoRotation refl("refl", 90., 0., 90., 90., 180., 0.);
2921 TGeoRotation rotrod("rotrod");
2922 //
2923 TGeoRotation* rotpos[2];
2924 //
2925 TGeoRotation* rotrod1[2];
2926 //
2927 // clamps holding rods
2928 //
2929 auto* clampi1 = new TGeoBBox("clampi1", 0.2, 3.1, 0.8);
2930 auto* clampi1v = new TGeoVolume("TPC_clampi1v", clampi1, m6);
2931 //
2932 pointstrap[0] = 0.49;
2933 pointstrap[1] = 0.375;
2934 //
2935 pointstrap[2] = 0.49;
2936 pointstrap[3] = -0.375;
2937 //
2938 pointstrap[4] = -0.49;
2939 pointstrap[5] = -0.375;
2940 //
2941 pointstrap[6] = -0.49;
2942 pointstrap[7] = 1.225;
2943 //
2944 pointstrap[8] = 0.49;
2945 pointstrap[9] = 0.375;
2946 //
2947 pointstrap[10] = 0.49;
2948 pointstrap[11] = -0.375;
2949 //
2950 pointstrap[12] = -0.49;
2951 pointstrap[13] = -0.375;
2952 //
2953 pointstrap[14] = -0.49;
2954 pointstrap[15] = 1.225;
2955 //
2956 auto* clitrap = new TGeoArb8("clitrap", 0.25, pointstrap);
2957 auto* clitrapv = new TGeoVolume("TPC_clitrapv", clitrap, m6);
2958 //
2959 auto* clamprot = new TGeoRotation();
2960 clamprot->RotateX(180.);
2961 //
2962 new TGeoBBox("clibox", 1.125, 3.1, .1);
2963 new TGeoTube("clitub", 0., 2.2, 0.1);
2964 //
2965 // copmisite shape for the clamp holder
2966 //
2967 auto* clitr1 = new TGeoTranslation("clitr1", 1.125, 0., 0.);
2968 clitr1->RegisterYourself();
2969 auto* clihold = new TGeoCompositeShape("clihold", "clibox-clitub:clitr1");
2970 auto* cliholdv = new TGeoVolume("TPC_cliholdv", clihold, m6);
2971 //
2972 // now assembly the whole inner clamp
2973 //
2974 TGeoVolume* iclamp = new TGeoVolumeAssembly("TPC_iclamp");
2975 //
2976 iclamp->AddNode(clampi1v, 1); // main box
2977 iclamp->AddNode(clitrapv, 1, new TGeoTranslation(0.69, -2.725, 0.35)); // trapezoids
2978 iclamp->AddNode(clitrapv, 2, new TGeoTranslation(0.69, -2.725, -0.35));
2979 iclamp->AddNode(clitrapv, 3, new TGeoCombiTrans(0.69, 2.725, 0.35, clamprot));
2980 iclamp->AddNode(clitrapv, 4, new TGeoCombiTrans(0.69, 2.725, -0.35, clamprot));
2981 iclamp->AddNode(cliholdv, 1, new TGeoTranslation(1.325, 0., 0.)); // holder
2982 //
2983 // outer clamps
2984 //
2985 auto* clampo1 = new TGeoBBox("clampo1", 0.25, 3.1, 1.);
2986 auto* clampo2 = new TGeoBBox("clampo2", 0.4, 0.85, 1.);
2987 //
2988 auto* clampo1v = new TGeoVolume("TPC_clampo1v", clampo1, m6);
2989 auto* clampo2v = new TGeoVolume("TPC_clampo2v", clampo2, m6);
2990 //
2991 auto* oclamp = new TGeoVolumeAssembly("TPC_oclamp");
2992 //
2993 oclamp->AddNode(clampo1v, 1);
2994 //
2995 oclamp->AddNode(clampo2v, 1, new TGeoTranslation(0.65, -2.25, 0));
2996 oclamp->AddNode(clampo2v, 2, new TGeoTranslation(0.65, 2.25, 0));
2997
2998 //
2999 pointstrap[0] = 0.375;
3000 pointstrap[1] = 0.75;
3001 pointstrap[2] = 0.375;
3002 pointstrap[3] = -0.35;
3003 pointstrap[4] = -0.375;
3004 pointstrap[5] = -0.35;
3005 pointstrap[6] = -0.375;
3006 pointstrap[7] = 0.35;
3007 //
3008 pointstrap[8] = 0.375;
3009 pointstrap[9] = 0.75;
3010 pointstrap[10] = 0.375;
3011 pointstrap[11] = -0.35;
3012 pointstrap[12] = -0.375;
3013 pointstrap[13] = -0.35;
3014 pointstrap[14] = -0.375;
3015 pointstrap[15] = 0.35;
3016 //
3017 auto* clotrap = new TGeoArb8("clotrap", 0.25, pointstrap);
3018 auto* clotrapv = new TGeoVolume("TPC_clotrapv", clotrap, m6);
3019 //
3020 oclamp->AddNode(clotrapv, 1, new TGeoTranslation(-0.625, -2.75, 0.35));
3021 oclamp->AddNode(clotrapv, 2, new TGeoTranslation(-0.625, -2.75, -0.35));
3022 oclamp->AddNode(clotrapv, 3, new TGeoCombiTrans(-0.625, 2.75, 0.35, clamprot));
3023 oclamp->AddNode(clotrapv, 4, new TGeoCombiTrans(-0.625, 2.75, -0.35, clamprot));
3024 //
3025 auto* clampo3 = new TGeoBBox("clampo3", 1.6, 0.45, .1);
3026 auto* clampo3v = new TGeoVolume("TPC_clampo3v", clampo3, m6);
3027 //
3028 oclamp->AddNode(clampo3v, 1, new TGeoTranslation(-1.85, 2.625, 0.));
3029 oclamp->AddNode(clampo3v, 2, new TGeoTranslation(-1.85, -2.625, 0));
3030 //
3031 auto* clampo4 = new TGeoTubeSeg("clampo4", 2.2, 3.1, 0.1, 90., 270.);
3032 auto* clampo4v = new TGeoVolume("TPC_clampo4v", clampo4, m6);
3033 //
3034 oclamp->AddNode(clampo4v, 1, new TGeoTranslation(-3.45, 0., 0.));
3035
3036 // v9 - drift gas
3037
3038 TGeoRotation rot102("rot102");
3039 rot102.RotateY(-90.);
3040
3041 for (Int_t i = 0; i < 18; i++) {
3042 Double_t angle, x, y;
3043 Double_t z, r;
3044 angle = TMath::DegToRad() * 20. * (Double_t)i;
3045 // inner rods
3046 r = 81.5;
3047 x = r * TMath::Cos(angle);
3048 y = r * TMath::Sin(angle);
3049 z = 126.;
3050 auto* rot12 = new TGeoRotation();
3051 rot12->RotateZ(-90.0 + i * 20.);
3052 v9->AddNode(tpcihpl, i + 1, new TGeoCombiTrans(x, y, 0., rot12));
3053 //
3054 if (i == 11) { // resistor rod inner
3055 rotrod.RotateZ(-90. + i * 20.);
3056 rotrod1[0] = new TGeoRotation();
3057 rotpos[0] = new TGeoRotation();
3058 //
3059 rotrod1[0]->RotateZ(90. + i * 20.);
3060 *rotpos[0] = refl * rotrod; // rotation+reflection
3061 v9->AddNode(tpcrrod, 1, new TGeoCombiTrans(x, y, z, rotrod1[0])); // A
3062 v9->AddNode(tpcrrod, 2, new TGeoCombiTrans(x, y, -z, rotpos[0])); // C
3063 } else {
3064 v9->AddNode(tpcmrod, i + 1, new TGeoTranslation(x, y, z)); // shaft
3065 v9->AddNode(tpcmrod, i + 19, new TGeoCombiTrans(x, y, -z, ref)); // muon
3066 }
3067 //
3068 // inner clamps positioning
3069 //
3070 r = 79.05;
3071 x = r * TMath::Cos(angle);
3072 y = r * TMath::Sin(angle);
3073 rot12 = new TGeoRotation();
3074 rot12->RotateZ(i * 20.);
3075 //
3076 // A-side
3077 v9->AddNode(iclamp, 7 * i + 1, new TGeoCombiTrans(x, y, 5.25, rot12));
3078 v9->AddNode(iclamp, 7 * i + 2, new TGeoCombiTrans(x, y, 38.25, rot12));
3079 v9->AddNode(iclamp, 7 * i + 3, new TGeoCombiTrans(x, y, 80.25, rot12));
3080 v9->AddNode(iclamp, 7 * i + 4, new TGeoCombiTrans(x, y, 122.25, rot12));
3081 v9->AddNode(iclamp, 7 * i + 5, new TGeoCombiTrans(x, y, 164.25, rot12));
3082 v9->AddNode(iclamp, 7 * i + 6, new TGeoCombiTrans(x, y, 206.25, rot12));
3083 v9->AddNode(iclamp, 7 * i + 7, new TGeoCombiTrans(x, y, 246.75, rot12));
3084 // C-side
3085 v9->AddNode(iclamp, 7 * i + 127, new TGeoCombiTrans(x, y, -5.25, rot12));
3086 v9->AddNode(iclamp, 7 * i + 128, new TGeoCombiTrans(x, y, -38.25, rot12));
3087 v9->AddNode(iclamp, 7 * i + 129, new TGeoCombiTrans(x, y, -80.25, rot12));
3088 v9->AddNode(iclamp, 7 * i + 130, new TGeoCombiTrans(x, y, -122.25, rot12));
3089 v9->AddNode(iclamp, 7 * i + 131, new TGeoCombiTrans(x, y, -164.25, rot12));
3090 v9->AddNode(iclamp, 7 * i + 132, new TGeoCombiTrans(x, y, -206.25, rot12));
3091 v9->AddNode(iclamp, 7 * i + 133, new TGeoCombiTrans(x, y, -246.75, rot12));
3092 //
3093 //--------------------------
3094 // outer rods
3095 r = 254.25;
3096 x = r * TMath::Cos(angle);
3097 y = r * TMath::Sin(angle);
3098 z = 126.;
3099 //
3100 // outer rod holder + outer left plug
3101 //
3102
3103 auto* rot33 = new TGeoRotation();
3104 rot33->RotateZ(-90 + i * 20.);
3105 //
3106 v9->AddNode(tpcohpl, i + 1, new TGeoCombiTrans(x, y, 0., rot33));
3107 //
3108 Double_t xxx = 256.297 * TMath::Cos((i * 20. + 10.) * TMath::DegToRad());
3109 Double_t yyy = 256.297 * TMath::Sin((i * 20. + 10.) * TMath::DegToRad());
3110 //
3111 TGeoRotation rot101("rot101");
3112 rot101.RotateZ(90. + i * 20. + 10.);
3113 auto* rot103 = new TGeoRotation("rot103");
3114 *rot103 = rot101 * rot102;
3115 //
3116 auto* trh100 = new TGeoCombiTrans(xxx, yyy, 0., rot103);
3117 //
3118 if (i == 2) {
3119 // main membrane holder
3120 v9->AddNode(tpcmmh, 1, trh100);
3121 } else {
3122 // "normal" membrane holder
3123 v9->AddNode(tpcomh, i + 1, trh100);
3124 }
3125
3126 //
3127 if (i == 3) { // resistor rod outer
3128 rotrod.RotateZ(90. + i * 20.);
3129 rotrod1[1] = new TGeoRotation();
3130 rotpos[1] = new TGeoRotation();
3131 rotrod1[1]->RotateZ(90. + i * 20.);
3132 *rotpos[1] = refl * rotrod; // rotation+reflection
3133 v9->AddNode(tpcrrod, 3, new TGeoCombiTrans(x, y, z, rotrod1[1])); // A
3134 v9->AddNode(tpcrrod, 4, new TGeoCombiTrans(x, y, -z, rotpos[1])); // C
3135 } else {
3136 v9->AddNode(tpcmrod, i + 37, new TGeoTranslation(x, y, z)); // shaft
3137 v9->AddNode(tpcmrod, i + 55, new TGeoCombiTrans(x, y, -z, ref)); // muon
3138 }
3139 if (i == 15) {
3140 v9->AddNode(hvrv, 1, new TGeoTranslation(x, y, z + 0.7)); // hv->A-side only
3141 }
3142 //
3143 // outer clamps
3144 //
3145 r = 256.9;
3146 x = r * TMath::Cos(angle);
3147 y = r * TMath::Sin(angle);
3148 rot12 = new TGeoRotation();
3149 rot12->RotateZ(i * 20.);
3150 //
3151 // A-side
3152 v9->AddNode(oclamp, 7 * i + 1, new TGeoCombiTrans(x, y, 5.25, rot12));
3153 v9->AddNode(oclamp, 7 * i + 2, new TGeoCombiTrans(x, y, 38.25, rot12));
3154 v9->AddNode(oclamp, 7 * i + 3, new TGeoCombiTrans(x, y, 80.25, rot12));
3155 v9->AddNode(oclamp, 7 * i + 4, new TGeoCombiTrans(x, y, 122.25, rot12));
3156 v9->AddNode(oclamp, 7 * i + 5, new TGeoCombiTrans(x, y, 164.25, rot12));
3157 v9->AddNode(oclamp, 7 * i + 6, new TGeoCombiTrans(x, y, 206.25, rot12));
3158 v9->AddNode(oclamp, 7 * i + 7, new TGeoCombiTrans(x, y, 246.75, rot12));
3159 // C-side
3160 v9->AddNode(oclamp, 7 * i + 127, new TGeoCombiTrans(x, y, -5.25, rot12));
3161 v9->AddNode(oclamp, 7 * i + 128, new TGeoCombiTrans(x, y, -38.25, rot12));
3162 v9->AddNode(oclamp, 7 * i + 129, new TGeoCombiTrans(x, y, -80.25, rot12));
3163 v9->AddNode(oclamp, 7 * i + 130, new TGeoCombiTrans(x, y, -122.25, rot12));
3164 v9->AddNode(oclamp, 7 * i + 131, new TGeoCombiTrans(x, y, -164.25, rot12));
3165 v9->AddNode(oclamp, 7 * i + 132, new TGeoCombiTrans(x, y, -206.25, rot12));
3166 v9->AddNode(oclamp, 7 * i + 133, new TGeoCombiTrans(x, y, -246.75, rot12));
3167
3168 } // end of rods positioning
3169
3170 TGeoVolume* alice = gGeoManager->GetVolume("barrel");
3171 alice->AddNode(v1, 1, new TGeoTranslation(0., 30., 0.));
3172
3173} // end of function
3174
3175void Detector::LoadGeometryFromFile()
3176{
3177 // ===| Read the TPC geometry from file |=====================================
3178 if (mGeoFileName.IsNull()) {
3179 LOG(fatal) << "TPC geometry file name not set";
3180 return;
3181 }
3182
3183 TFile* fGeoFile = TFile::Open(mGeoFileName);
3184 if (!fGeoFile || !fGeoFile->IsOpen() || fGeoFile->IsZombie()) {
3185 LOG(fatal) << "Could not open TPC geometry file '" << mGeoFileName << "'";
3186 return;
3187 }
3188
3189 TGeoVolume* tpcVolume = dynamic_cast<TGeoVolume*>(fGeoFile->Get("TPC_M"));
3190 if (!tpcVolume) {
3191 LOG(fatal) << "Could not retrieve TPC geometry from file '" << mGeoFileName << "'";
3192 return;
3193 }
3194
3195 LOG(info) << "Loaded TPC geometry from file '" << mGeoFileName << "'";
3196 TGeoVolume* alice = gGeoManager->GetVolume("barrel");
3197 alice->AddNode(tpcVolume, 1, new TGeoTranslation(0., 30., 0.));
3198}
3199
3200void Detector::defineSensitiveVolumes()
3201{
3202 TGeoManager* geoManager = gGeoManager;
3203 TGeoVolume* v = nullptr;
3204
3205 // const Int_t nSensitive=2;
3206 // const char* volumeNames[nSensitive]={"TPC_Drift","TPC_Strip"};
3207 const Int_t nSensitive = 1;
3208 const char* volumeNames[nSensitive] = {"TPC_Drift"};
3209
3210 // The names of the ITS sensitive volumes have the format: ITSUSensor(0...mNumberLayers-1)
3211 for (Int_t ivol = 0; ivol < nSensitive; ++ivol) {
3212 TString volumeName = volumeNames[ivol];
3213 v = geoManager->GetVolume(volumeName.Data());
3214 if (!v) {
3215 LOG(error) << "Could not find volume '" << volumeName << "'";
3216 continue;
3217 }
3218
3219 // set volume sentive
3221 }
3222
3223 // Special sensitive volume parameters in case FLUKA is used as transport engine
3224 auto vmc = TVirtualMC::GetMC();
3225 if (strcmp(vmc->GetName(), "TFluka") == 0) {
3226 LOG(info) << "Setting special FLUKA parameters for TPC Driftgas";
3228 Int_t index = mgr.getMediumID("TPC", kDriftGas2);
3229 vmc->Gstpar(index, "PRIMIO_E", 20.77);
3230 vmc->Gstpar(index, "PRIMIO_N", 14.35);
3231 vmc->Gstpar(index, "LOSS", 14);
3232 vmc->Gstpar(index, "STRA", 4);
3233 }
3234}
3235
3236Double_t Detector::Gamma(Double_t k)
3237{
3238 static thread_local Double_t n = 0;
3239 static thread_local Double_t c1 = 0;
3240 static thread_local Double_t c2 = 0;
3241 static thread_local Double_t b1 = 0;
3242 static thread_local Double_t b2 = 0;
3243 if (k > 0) {
3244 if (k < 0.4) {
3245 n = 1. / k;
3246 } else if (k >= 0.4 && k < 4) {
3247 n = 1. / k + (k - 0.4) / k / 3.6;
3248 } else if (k >= 4.) {
3249 n = 1. / TMath::Sqrt(k);
3250 }
3251 b1 = k - 1. / n;
3252 b2 = k + 1. / n;
3253 c1 = (k < 0.4) ? 0 : b1 * (TMath::Log(b1) - 1.) / 2.;
3254 c2 = b2 * (TMath::Log(b2) - 1.) / 2.;
3255 }
3256 Double_t x;
3257 Double_t y = -1.;
3258 while (1) {
3259 Double_t nu1 = o2::base::simRandom()->Rndm();
3260 Double_t nu2 = o2::base::simRandom()->Rndm();
3261 Double_t w1 = c1 + TMath::Log(nu1);
3262 Double_t w2 = c2 + TMath::Log(nu2);
3263 y = n * (b1 * w2 - b2 * w1);
3264 if (y < 0) {
3265 continue;
3266 }
3267 x = n * (w2 - w1);
3268 if (TMath::Log(y) >= x) {
3269 break;
3270 }
3271 }
3272 return TMath::Exp(x);
3273}
3274
3275std::string Detector::getHitBranchNames(int probe) const
3276{
3277 if (probe >= 0 && probe < Sector::MAXSECTOR) {
3278 TString name;
3279 name.Form("%sHitsShiftedSector%d", GetName(), probe);
3280 return std::string(name.Data());
3281 }
3282 return std::string();
3283}
3284
3286{
3287 // lower energy threshold to track low-energy electrons for Kr-83m calibration
3288 auto const& detParam = ParameterDetector::Instance();
3289 LOG(info) << "TPC SetSpecialPhysicsCuts: UseGeant4Edep=" << detParam.UseGeant4Edep;
3290 if (detParam.UseGeant4Edep) {
3291 auto& matmgr = o2::base::MaterialManager::Instance();
3292 const float specialCut = detParam.SpecialCutsGeV;
3293 for (int med : {(int)kDriftGas1, (int)kDriftGas2, (int)kCO2}) {
3294 matmgr.SpecialCut(GetName(), med, o2::base::ECut::kCUTELE, specialCut);
3295 matmgr.SpecialCut(GetName(), med, o2::base::ECut::kCUTGAM, specialCut);
3296 matmgr.SpecialCut(GetName(), med, o2::base::ECut::kDCUTE, specialCut);
3297 matmgr.SpecialCut(GetName(), med, o2::base::ECut::kBCUTE, specialCut);
3298 }
3299 }
3301}
3302
3304
3305// Define Factory method for calling from the outside
3306extern "C" {
3311}
Definition of the Stack class.
int16_t time
Definition RawEventData.h:4
int32_t i
constexpr int p1()
constexpr to accelerate the coordinates changing
char error[CURL_ERROR_SIZE]
ClassImp(IdPath)
Identification of the BSM magnetic monopoles across the simulation.
Definition of the parameter class for the detector.
Definition of the parameter class for the detector gas.
Class for TPC Point.
uint16_t slope
Definition RawData.h:1
uint32_t res
Definition RawData.h:0
uint32_t stack
Definition RawData.h:1
Acts::Vector3 position
Collection of utility functions for TGeo.
o2::base::Detector * create_detector_tpc(bool active)
virtual void Register()=0
virtual Bool_t ProcessHits(FairVolume *v=0)=0
virtual void EndOfEvent()
virtual void Reset()=0
Int_t GetDetId()
void AddSensitiveVolume(TGeoVolume *v)
TVirtualMC * fMC
flag for initialisation
Definition FairModule.h:160
virtual void ConstructGeometry()
static FairRootManager * Instance()
virtual std::string getHitBranchNames(int probe) const =0
~Detector() override
Default Destructor.
Definition Detector.cxx:93
Detector()
Default Constructor.
Definition Detector.cxx:36
void Mixture(Int_t imat, const char *name, Float_t *a, Float_t *z, Float_t dens, Int_t nlmat, Float_t *wmat)
Definition Detector.cxx:66
void Medium(Int_t numed, const char *name, Int_t nmat, Int_t isvol, Int_t ifield, Float_t fieldm, Float_t tmaxfd, Float_t stemax, Float_t deemax, Float_t epsil, Float_t stmin, Float_t *ubuf=nullptr, Int_t nbuf=0)
Definition Detector.cxx:72
void SetSpecialPhysicsCuts() override
Definition Detector.cxx:122
static void initFieldTrackingParams(int &mode, float &maxfield)
Definition Detector.cxx:143
void Material(Int_t imat, const char *name, Float_t a, Float_t z, Float_t dens, Float_t radl, Float_t absl, Float_t *buf=nullptr, Int_t nwbuf=0)
Definition Detector.cxx:59
virtual void InitializeO2Detector()=0
Definition Detector.cxx:104
static MaterialManager & Instance()
static void makeHalfSpaceBox(const char *name, const double p[3], const double n[3], double reach)
Double_t Gamma(Double_t k)
static o2::base::Detector * create(bool active)
Definition Detector.h:72
static int ToShiftedSector(T x, T y, T z)
Definition Sector.h:126
static int ToSector(T x, T y, T z)
Definition Sector.h:107
static constexpr int MAXSECTOR
Definition Sector.h:44
static ShmManager & Instance()
Definition ShmManager.h:61
GLdouble n
Definition glcorearb.h:1982
GLfloat GLfloat GLfloat alpha
Definition glcorearb.h:279
GLint GLenum GLint x
Definition glcorearb.h:403
const GLdouble * v
Definition glcorearb.h:832
GLuint const GLchar * name
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint y
Definition glcorearb.h:270
GLuint GLfloat x0
Definition glcorearb.h:5034
GLfloat angle
Definition glcorearb.h:4071
GLfloat GLfloat v1
Definition glcorearb.h:812
GLboolean r
Definition glcorearb.h:1233
GLfloat GLfloat GLfloat GLfloat v3
Definition glcorearb.h:814
GLint ref
Definition glcorearb.h:291
GLfloat GLfloat GLfloat v2
Definition glcorearb.h:813
GLuint GLfloat GLfloat y0
Definition glcorearb.h:5034
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition glcorearb.h:5034
TRandom * simRandom()
Definition SimRandom.cxx:22
double norm(const Vec3 &vector)
std::optional< Chamber > chamber(int chamberId)
Definition Chamber.cxx:17
std::array< uint64_t, 23 > m2
std::array< uint64_t, 17 > m5
std::array< uint64_t, 17 > m4
std::array< uint64_t, 23 > m3
std::array< uint64_t, 23 > m1
constexpr bool isMonopole(int pdg) noexcept
true for the monopole and antimonopole of both species
Global TPC definitions and constants.
constexpr double cm
Definition Specs.h:31
void freeSimVector(std::vector< T > *ptr)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
TStopwatch sw