13#include <TGeoVolume.h>
14#include <TGeoMatrix.h>
18#include <TGeoCompositeShape.h>
21#include "TGeoManager.h"
32static std::vector<VDSensorDesc> gVDSensors;
39 gVDSensors.push_back({volName, petal, region,
type, idx});
42static inline std::string makeSensorName(
const std::string& layerName,
int layerNumber)
51inline bool isSolidToCut(
const TGeoVolume*
v)
53 const char* nm =
v->GetName();
54 const char* med =
v->GetMedium() ?
v->GetMedium()->GetName() :
"";
56 if (med && strcmp(med,
"TRK_SILICON$") == 0) {
60 if (TString(nm).BeginsWith(
"VD_InnerWallArc")) {
63 if (TString(nm).BeginsWith(
"VD_OuterWallArc")) {
66 if (TString(nm).BeginsWith(
"VD_SideWall")) {
69 if (TString(nm).BeginsWith(
"VD_InnerWallCyl")) {
72 if (TString(nm).BeginsWith(
"VD_OuterWallCyl")) {
75 if (TString(nm).Contains(
"_Coldplate")) {
78 if (TString(nm).BeginsWith(
"IRIS_Service_Neg")) {
81 if (TString(nm).BeginsWith(
"IRIS_Service_Pos_InVac")) {
84 if (TString(nm).BeginsWith(
"VD_InclinedWall")) {
87 if (TString(nm).Contains(
"_ZCap")) {
94inline const char* ensureShapeName(TGeoVolume*
v)
96 auto* sh =
v->GetShape();
97 TString nm = sh->GetName();
98 if (nm.IsNull() || nm.BeginsWith(
"TGeo")) {
99 TString wanted = TString(
v->GetName()) +
"_sh";
102 TString cand = wanted;
103 auto* shapes = gGeoManager ? gGeoManager->GetListOfShapes() :
nullptr;
104 while (shapes && shapes->FindObject(cand)) {
105 cand = Form(
"%s_%d", wanted.Data(), ++k);
108 if (shapes && !shapes->FindObject(cand)) {
112 return sh->GetName();
116static TString gPetalSolidsFormula;
117static int gLocalTrIdx = 0;
120inline void appendLocalTerm(
const char* shapeName,
const TGeoHMatrix& H)
122 auto* ct =
new TGeoCombiTrans(H);
123 ct->SetName(Form(
"IRIS_LOC_TR_%d", gLocalTrIdx++));
124 ct->RegisterYourself();
125 if (!gPetalSolidsFormula.IsNull()) {
126 gPetalSolidsFormula +=
"+";
128 gPetalSolidsFormula += TString::Format(
"%s:%s", shapeName, ct->GetName());
132void traversePetalLocal(TGeoVolume* vol,
const TGeoHMatrix& prefix)
134 auto*
nodes = vol->GetNodes();
138 for (
int i = 0;
i <
nodes->GetEntriesFast(); ++
i) {
140 auto* childV =
node->GetVolume();
141 TGeoHMatrix H(prefix);
142 if (
auto*
m =
node->GetMatrix()) {
146 if (isSolidToCut(childV)) {
147 const char* shapeName = ensureShapeName(childV);
148 appendLocalTerm(shapeName, H);
150 traversePetalLocal(childV, H);
155inline void buildPetalSolidsComposite(TGeoVolume* petalAsm)
158 if (gGeoManager && gGeoManager->GetListOfShapes() && gGeoManager->GetListOfShapes()->FindObject(
"IRIS_PETAL_SOLIDSsh")) {
162 gPetalSolidsFormula.Clear();
166 traversePetalLocal(petalAsm, I);
168 if (gPetalSolidsFormula.IsNull()) {
169 LOGP(error,
"IRIS_PETAL_SOLIDSsh formula is empty; did not find solids in petal.");
173 LOGP(info,
"IRIS_PETAL_SOLIDSsh formula: {}", gPetalSolidsFormula.Data());
174 new TGeoCompositeShape(
"IRIS_PETAL_SOLIDSsh", gPetalSolidsFormula.Data());
178inline void buildIrisCutoutFromPetalSolid(
int nPetals)
180 auto* shps = gGeoManager->GetListOfShapes();
181 auto* base = shps ?
dynamic_cast<TGeoShape*
>(shps->FindObject(
"IRIS_PETAL_SOLIDSsh")) : nullptr;
183 LOGP(error,
"IRIS cutout: shape 'IRIS_PETAL_SOLIDSsh' not found.");
191 if (shps->FindObject(
"IRIS_CUTOUTsh")) {
194 LOGP(warning,
"IRIS cutout: 'IRIS_CUTOUTsh' already exists; overwriting by clone name reuse may be unsafe.");
197 auto* cut =
dynamic_cast<TGeoShape*
>(base->Clone(
"IRIS_CUTOUTsh"));
199 LOGP(error,
"IRIS cutout: failed to clone 'IRIS_PETAL_SOLIDSsh' to 'IRIS_CUTOUTsh'.");
203 LOGP(info,
"IRIS_CUTOUTsh created as clone of IRIS_PETAL_SOLIDSsh (nPetals=1).");
209 for (
int p = 0;
p < nPetals; ++
p) {
210 const double phi = (360.0 / nPetals) * (p + 0.5);
211 auto*
R =
new TGeoRotation();
213 auto*
RT =
new TGeoCombiTrans(0, 0, 0,
R);
214 RT->SetName(Form(
"IRIS_PETAL_ROT_%d", p));
215 RT->RegisterYourself();
220 cutFormula += Form(
"IRIS_PETAL_SOLIDSsh:%s",
RT->GetName());
223 LOGP(info,
"IRIS_CUTOUTsh formula: {}", cutFormula.Data());
224 auto* cut =
new TGeoCompositeShape(
"IRIS_CUTOUTsh", cutFormula.Data());
228 auto* cutCheck =
dynamic_cast<TGeoCompositeShape*
>(shps->FindObject(
"IRIS_CUTOUTsh"));
229 if (!cutCheck || !cutCheck->GetBoolNode()) {
230 LOGP(error,
"IRIS cutout sanity: IRIS_CUTOUTsh exists but parsing failed (no BoolNode).");
232 LOGP(info,
"IRIS cutout sanity: OK ({} petals).", nPetals);
239static constexpr double kX2X0 = 0.001f;
240static constexpr double kLenZ_cm = 50.0f;
243static constexpr double rL0_cm = 0.5f;
244static constexpr double rL1_cm = 1.2f;
245static constexpr double rL2_cm = 2.5f;
248static constexpr double kL0RectHeight_cm = 0.5f;
249static constexpr double kL0RectWidth_cm = 0.83f;
252static constexpr double diskRin_cm = 0.5f;
253static constexpr double diskRout_cm = 2.5f;
254static const double diskZ_cm[6] = {-34.0f, -30.0f, -26.0f, 26.0f, 30.0f, 34.0f};
257static constexpr double kPetalZ_cm = 70.0f;
258static constexpr double kWallThick_cm = 0.02f;
259static constexpr double kInnerWallRadius_cm = 0.48f;
260static constexpr double kOuterWallRadius_cm = 4.8f;
261static constexpr double kEps_cm = 2.5e-4f;
262static constexpr double kEps_100um = 0.01f;
266static constexpr double kInclinedWallThick_cm = 0.04f;
268static constexpr double kSiLayerThick_cm = 0.01f;
271static constexpr double kInclinedWallPhi0_deg = 27.799f;
272static constexpr double kInclinedWallRmax_cm = 4.75f;
275static constexpr double kColdplateRadius_cm = 2.6f;
276static constexpr double kColdplateThickness_cm = 0.15f;
277static constexpr double kColdplateZ_cm = 50.0f;
284inline double degFromArc(
double arc,
double radius)
287 return (radius > 0.f) ? (arc / radius) * TMath::RadToDeg() : 0.f;
297inline double phiSpanFromGap(
int nPetals,
double gap,
double radius)
299 if (nPetals <= 0 || radius <= 0.f) {
302 const double petalPhiDeg = 360.f / nPetals;
303 const double phi = petalPhiDeg - degFromArc(gap, radius);
304 return phi > 0.f ?
phi : 0.f;
311inline double phiSpanFromArc(
double arcLen,
double radius)
313 return (arcLen > 0.f && radius > 0.f) ? degFromArc(arcLen, radius) : 0.f;
316inline TGeoCombiTrans rotZ(
double phiDeg)
318 auto*
r =
new TGeoRotation();
319 r->RotateZ(
static_cast<Double_t
>(phiDeg));
320 return TGeoCombiTrans(0., 0., 0.,
r);
327static void addPetalWalls(TGeoVolume* petalAsm,
329 double outerRadius_cm = kOuterWallRadius_cm,
330 bool withSideWalls =
true,
331 bool fullCylindricalRadialWalls =
false)
334 LOGP(error,
"addPetalWalls: petalAsm is null");
339 const TGeoMedium* med = matmgr.getTGeoMedium(
"ALICE3_TRKSERVICES_ALUMINIUM5083");
342 LOGP(warning,
"Petal walls: ALICE3_TRKSERVICES_ALUMINIUM5083$ not found, walls not created.");
346 const double halfZ = 0.5 * kPetalZ_cm;
349 const double halfPhi = fullCylindricalRadialWalls ? 180.0 : 0.5 * (360.0 /
static_cast<double>(nPetals));
352 if (fullCylindricalRadialWalls) {
353 auto*
s =
new TGeoTube(
static_cast<Double_t
>(kInnerWallRadius_cm),
354 static_cast<Double_t
>(kInnerWallRadius_cm + kWallThick_cm),
355 static_cast<Double_t
>(halfZ));
356 auto*
v =
new TGeoVolume(
"VD_InnerWallCyl", s, med);
357 v->SetLineColor(kGray + 2);
358 v->SetTransparency(70);
359 petalAsm->AddNode(
v, 1);
361 auto*
s =
new TGeoTubeSeg(
static_cast<Double_t
>(kInnerWallRadius_cm),
362 static_cast<Double_t
>(kInnerWallRadius_cm + kWallThick_cm),
363 static_cast<Double_t
>(halfZ),
364 static_cast<Double_t
>(-halfPhi),
365 static_cast<Double_t
>(+halfPhi));
366 auto*
v =
new TGeoVolume(
"VD_InnerWallArc", s, med);
367 v->SetLineColor(kGray + 2);
368 v->SetTransparency(70);
369 petalAsm->AddNode(
v, 1);
373 if (fullCylindricalRadialWalls) {
374 auto*
s =
new TGeoTube(
static_cast<Double_t
>(outerRadius_cm),
375 static_cast<Double_t
>(outerRadius_cm + kWallThick_cm),
376 static_cast<Double_t
>(halfZ));
377 auto*
v =
new TGeoVolume(
"VD_OuterWallCyl", s, med);
378 v->SetLineColor(kGray + 2);
379 v->SetTransparency(70);
380 petalAsm->AddNode(
v, 1);
382 auto*
s =
new TGeoTubeSeg(
static_cast<Double_t
>(outerRadius_cm),
383 static_cast<Double_t
>(outerRadius_cm + kWallThick_cm),
384 static_cast<Double_t
>(halfZ),
385 static_cast<Double_t
>(-halfPhi),
386 static_cast<Double_t
>(+halfPhi));
387 auto*
v =
new TGeoVolume(
"VD_OuterWallArc", s, med);
388 v->SetLineColor(kGray + 2);
389 v->SetTransparency(70);
390 petalAsm->AddNode(
v, 1);
394 if (!withSideWalls) {
399 const double radialLen = (outerRadius_cm - (kInnerWallRadius_cm + kWallThick_cm));
400 auto* sideS =
new TGeoBBox(
static_cast<Double_t
>(0.5f * radialLen),
401 static_cast<Double_t
>(0.5f * kWallThick_cm),
402 static_cast<Double_t
>(halfZ));
403 auto* sideV =
new TGeoVolume(
"VD_SideWall", sideS, med);
404 sideV->SetLineColor(kGray + 2);
405 sideV->SetTransparency(70);
407 for (
int sgn : {-1, +1}) {
408 const double phi = sgn * halfPhi;
409 const double rMid = kInnerWallRadius_cm + kWallThick_cm + 0.5f * radialLen;
410 const double rad =
static_cast<double>(TMath::DegToRad());
411 const double x = rMid * std::cos(phi * rad);
412 const double y = rMid * std::sin(phi * rad);
413 auto* rot =
new TGeoRotation();
414 rot->RotateZ(
static_cast<Double_t
>(phi));
415 auto* tr =
new TGeoCombiTrans(
static_cast<Double_t
>(
x),
416 static_cast<Double_t
>(
y),
418 petalAsm->AddNode(sideV, (sgn < 0 ? 1 : 2), tr);
424static void addBarrelLayers(TGeoVolume* petalAsm,
int nPetals,
int petalID,
bool rectangularL0,
bool fullCylinders)
427 LOGP(error,
"addBarrelLayers: petalAsm is null");
432 constexpr double gapL0_cm = 0.163f;
433 constexpr double gapL1L2_cm = 0.12f;
434 constexpr double arcL0_cm = 0.6247f;
437 const double phiL0_deg = fullCylinders ? 360.0 : phiSpanFromGap(nPetals, gapL0_cm, rL0_cm);
438 const double phiL1_deg = fullCylinders ? 360.0 : phiSpanFromGap(nPetals, gapL1L2_cm, rL1_cm);
439 const double phiL2_deg = fullCylinders ? 360.0 : phiSpanFromGap(nPetals, gapL1L2_cm, rL2_cm);
441 const std::string nameL0 =
445 if (!fullCylinders && rectangularL0) {
446 VDRectangularLayer L0(0,
448 kX2X0, kL0RectWidth_cm, kLenZ_cm, kLenZ_cm);
451 double x = kL0RectHeight_cm + L0.getChipThickness() / 2.;
452 LOGP(info,
"Placing rectangular L0 at r={:.3f} cm (half-width={:.3f} cm)",
x, 0.5f * kL0RectWidth_cm);
457 auto* rot =
new TGeoRotation();
460 auto* tr =
new TGeoCombiTrans(
x,
y,
z, rot);
461 L0.createLayer(petalAsm, tr);
464 VDCylindricalLayer L0(0,
466 kX2X0, rL0_cm, phiL0_deg, kLenZ_cm, kLenZ_cm);
467 L0.createLayer(petalAsm,
nullptr);
471 const std::string nameL1 =
475 VDCylindricalLayer L1(1,
477 kX2X0, rL1_cm, phiL1_deg, kLenZ_cm, kLenZ_cm);
478 L1.createLayer(petalAsm,
nullptr);
481 const std::string nameL2 =
485 VDCylindricalLayer L2(2,
487 kX2X0, rL2_cm, phiL2_deg, kLenZ_cm, kLenZ_cm);
488 L2.createLayer(petalAsm,
nullptr);
493static void addColdPlate(TGeoVolume* petalAsm,
int nPetals,
int petalId,
bool fullCylinders =
false)
496 LOGP(error,
"addColdPlate: petalAsm is null");
501 const TGeoMedium* med = gGeoManager->GetMedium(
"ALICE3_TRKSERVICES_CERAMIC");
503 LOGP(error,
"addColdPlate: can't find the medium.");
507 constexpr double gapL1L2_cm = 0.12f;
510 const double phiSpanColdplate_deg =
511 fullCylinders ? 360.0 : phiSpanFromGap(nPetals, gapL1L2_cm, rL2_cm);
512 const double halfPhiDeg = 0.5 * phiSpanColdplate_deg;
513 const double startPhi = -halfPhiDeg;
514 const double endPhi = +halfPhiDeg;
517 auto* shape =
new TGeoTubeSeg(
static_cast<Double_t
>(kColdplateRadius_cm),
518 static_cast<Double_t
>(kColdplateRadius_cm + kColdplateThickness_cm),
519 static_cast<Double_t
>(0.5 * kColdplateZ_cm),
520 static_cast<Double_t
>(startPhi),
521 static_cast<Double_t
>(endPhi));
523 TString volName = TString::Format(
"Petal%d_Coldplate", petalId);
524 auto* coldVol =
new TGeoVolume(volName, shape, med);
525 coldVol->SetLineColor(kAzure - 3);
526 coldVol->SetTransparency(10);
529 petalAsm->AddNode(coldVol, 1);
531 LOGP(info,
"Adding cold plate {} r={:.3f} cm t={:.3f} cm Lz={:.3f} cm φ=[{:.3f}, {:.3f}]",
532 volName.Data(), kColdplateRadius_cm, kColdplateThickness_cm, kColdplateZ_cm, startPhi, endPhi);
537static void addIRISServiceModules(TGeoVolume* petalAsm,
int nPetals)
540 LOGP(error,
"addIRISServiceModules: petalAsm is null");
544 auto* matAl =
new TGeoMaterial(
"ALUMINUM", 26.9815, 13, 2.70);
545 const TGeoMedium* med =
new TGeoMedium(
"ALUMINUM", 4, matAl);
548 LOGP(error,
"addIRISServiceModules: ALUMINUM medium not found.");
552 constexpr double radius = 3.2;
554 constexpr double halfLength = 19.5;
555 const double rIn = radius;
559 const double halfPhi_deg = 0.5 * (360.0 / double(nPetals));
562 auto* segSh =
new TGeoTubeSeg(
563 "IRIS_SERVICE_SEGsh",
566 -halfPhi_deg, halfPhi_deg);
569 TString namePos =
"IRIS_Service_Pos";
570 auto* volPos =
new TGeoVolume(namePos, segSh, med);
571 volPos->SetLineColor(kRed + 2);
572 volPos->SetTransparency(50);
575 TString nameNeg =
"IRIS_Service_Neg";
576 auto* volNeg =
new TGeoVolume(nameNeg, segSh, med);
577 volNeg->SetLineColor(kRed + 2);
578 volNeg->SetTransparency(50);
581 const double zpos = 36.0 + halfLength;
582 auto* transPos =
new TGeoTranslation(0.0, 0.0,
static_cast<Double_t
>(zpos));
583 auto* transNeg =
new TGeoTranslation(0.0, 0.0,
static_cast<Double_t
>(-zpos));
586 petalAsm->AddNode(volPos, 1, transPos);
587 petalAsm->AddNode(volNeg, 2, transNeg);
589 LOGP(info,
"Added IRIS service modules at z = ±{} cm, r=[{}, {}] cm", zpos, rIn, rOut);
593static void addIRISServiceModulesSegmented(TGeoVolume* petalAsm,
int nPetals)
596 LOGP(error,
"addIRISServiceModulesSegmented: petalAsm is null");
601 constexpr double rIn = 3.2;
604 constexpr double halfLen = 19.5;
605 constexpr double z0 = 36.0 + halfLen;
606 const double zMinA = z0 - halfLen;
607 const double zMaxA = z0 + halfLen;
611 constexpr double vacuumVesselLength = kPetalZ_cm;
612 constexpr double vacuumVesselThickness = kWallThick_cm;
613 const double halfVess = 0.5 * vacuumVesselLength;
614 const double gapStart = halfVess;
615 const double gapEnd = halfVess + vacuumVesselThickness;
618 const double halfPhi = 0.5 * (360.0 / double(nPetals));
620 auto* matAl =
new TGeoMaterial(
"ALUMINUM", 26.9815, 13, 2.70);
621 const TGeoMedium* med =
new TGeoMedium(
"ALUMINUM", 4, matAl);
624 LOGP(error,
"addIRISServiceModules: ALUMINUM medium not found.");
632 auto* sh =
new TGeoTubeSeg(rIn, rOut, halfLen, -halfPhi, +halfPhi);
633 auto* vN =
new TGeoVolume(
"IRIS_Service_Neg", sh, med);
634 vN->SetLineColor(kRed + 2);
635 vN->SetTransparency(55);
636 petalAsm->AddNode(vN, 1,
new TGeoTranslation(0., 0., -(z0)));
643 const double L_inVac = std::max(0.0, std::min(zMaxA, gapStart) - zMinA);
645 const double dz = 0.5 * L_inVac;
646 const double zc = zMinA + dz;
647 auto* sh =
new TGeoTubeSeg(rIn, rOut, dz, -halfPhi, halfPhi);
648 sh->SetName(
"IRIS_SERVICE_POS_INVACsh");
649 auto* vP =
new TGeoVolume(
"IRIS_Service_Pos_InVac", sh, med);
650 vP->SetLineColor(kRed + 2);
651 vP->SetTransparency(55);
652 petalAsm->AddNode(vP, 1,
new TGeoTranslation(0., 0., zc));
653 LOGP(info,
"IRIS A-side (InVac): z=[{:.3f},{:.3f}] cm, len={:.3f} cm",
654 zc - dz, zc + dz, 2 * dz);
656 LOGP(warning,
"IRIS A-side (InVac): no overlap with vacuum (L_inVac<=0)");
662 const double L_outVac = std::max(0.0, zMaxA - std::max(zMinA, gapEnd));
664 const double dz = 0.5 * L_outVac;
665 const double zc = std::max(zMinA, gapEnd) + dz;
666 auto* sh =
new TGeoTubeSeg(rIn, rOut, dz, -halfPhi, +halfPhi);
667 sh->SetName(
"IRIS_SERVICE_POS_OUTVACsh");
668 auto* vP =
new TGeoVolume(
"IRIS_Service_Pos_OutVac", sh, med);
669 vP->SetLineColor(kRed + 1);
670 vP->SetTransparency(70);
671 petalAsm->AddNode(vP, 2,
new TGeoTranslation(0., 0., +zc));
672 LOGP(info,
"IRIS A-side (OutVac): z=[{:.3f},{:.3f}] cm, len={:.3f} cm",
673 zc - dz, zc + dz, 2 * dz);
675 LOGP(warning,
"IRIS A-side (OutVac): no upper piece (L_outVac<=0)");
681static void addDisks(TGeoVolume* petalAsm,
int nPetals,
int petalID,
bool fullCylinders)
685 LOGP(error,
"addDisks: petalAsm is null");
689 const double phiDisk_deg = fullCylinders ? 360.0 : phiSpanFromGap(nPetals, 2 * kWallThick_cm, diskRin_cm);
691 for (
int i = 0;
i < 6; ++
i) {
692 const std::string nameD =
698 kX2X0, diskRin_cm, diskRout_cm, phiDisk_deg, diskZ_cm[
i]);
701 auto* tr =
new TGeoTranslation(0.0, 0.0,
static_cast<Double_t
>(disk.getZPosition()));
702 disk.createLayer(petalAsm, tr);
710static void addPetalEndCaps(TGeoVolume* petalAsm,
719 LOGP(error,
"addPetalEndCaps: petalAsm is null");
724 const TGeoMedium* med =
725 matmgr.getTGeoMedium(
"ALICE3_TRKSERVICES_ALUMINIUM5083");
729 "addPetalEndCaps: ALICE3_TRKSERVICES_ALUMINIUM5083 not found, caps not created.");
733 const double halfT = 0.5 * capThick_cm;
735 auto* sh =
new TGeoTube(
static_cast<Double_t
>(rIn_cm),
736 static_cast<Double_t
>(rOut_cm),
737 static_cast<Double_t
>(halfT));
739 TString vname = Form(
"Petal%d_ZCap", petalId);
740 auto*
v =
new TGeoVolume(vname, sh, med);
741 v->SetLineColor(kGray + 2);
742 v->SetTransparency(70);
744 auto* trMin =
new TGeoTranslation(0.0, 0.0,
745 static_cast<Double_t
>(zMin_cm + halfT));
746 auto* trMax =
new TGeoTranslation(0.0, 0.0,
747 static_cast<Double_t
>(zMax_cm - halfT));
749 petalAsm->AddNode(
v, 1, trMin);
750 petalAsm->AddNode(
v, 2, trMax);
754static TGeoVolume* buildPetalAssembly(
int nPetals,
760 auto* petalAsm =
new TGeoVolumeAssembly(Form(
"PETAL_%d", petalID));
763 addPetalWalls(petalAsm, nPetals, kOuterWallRadius_cm,
767 addBarrelLayers(petalAsm, nPetals, petalID, rectangularL0, fullCylinders);
770 addColdPlate(petalAsm, nPetals, petalID,
false);
771 addIRISServiceModulesSegmented(petalAsm, nPetals);
776static TGeoVolume* buildFullCylAssembly(
int petalID,
bool withDisks)
779 auto* petalAsm =
new TGeoVolumeAssembly(Form(
"PETAL_%d", petalID));
782 addPetalWalls(petalAsm,
790 const double zMin = -0.5 * kPetalZ_cm - 2 * kWallThick_cm;
791 const double zMax = +0.5 * kPetalZ_cm + 2 * kWallThick_cm;
792 const double rIn = kInnerWallRadius_cm;
793 const double rOut = kOuterWallRadius_cm + kWallThick_cm;
795 addPetalEndCaps(petalAsm,
805 addBarrelLayers(petalAsm,
811 addColdPlate(petalAsm, 1, petalID,
true);
812 addIRISServiceModulesSegmented(petalAsm, 1);
830static void addInclinedWalls3FullCyl(TGeoVolume* petalAsm,
double phi0_deg = kInclinedWallPhi0_deg)
833 LOGP(error,
"addInclinedWalls3FullCyl: petalAsm is null");
838 const TGeoMedium* med = matmgr.getTGeoMedium(
"ALICE3_TRKSERVICES_ALUMINIUM5083");
840 LOGP(warning,
"addInclinedWalls3FullCyl: ALICE3_TRKSERVICES_ALUMINIUM5083 not found, walls not created.");
845 constexpr double clearanceMargin = 0.010;
848 constexpr double R0 = rL0_cm;
849 constexpr double R1 = rL1_cm;
850 constexpr double R2 = rL2_cm;
851 constexpr double Rmax = kInclinedWallRmax_cm;
853 const double wallDy = 0.5 * kInclinedWallThick_cm;
854 const double shellTh = kSiLayerThick_cm;
855 const double h = 0.5 * shellTh;
856 const double dz = 0.5 * kPetalZ_cm;
858 constexpr int nWalls = 3;
859 constexpr double dPhi = 360.0 / double(nWalls);
862 const double R0_out = R0 +
h;
863 const double R1_in =
R1 -
h;
864 const double R1_out =
R1 +
h;
865 const double R2_in = R2 -
h;
866 const double R2_out = R2 +
h;
869 const double Rcold_out = kColdplateRadius_cm + kColdplateThickness_cm;
872 const double Rtan = R0_out + wallDy + clearanceMargin;
876 const double Reff_plus = Rtan + wallDy + clearanceMargin;
877 const double Reff_minus = std::max(0.0, Rtan - wallDy - clearanceMargin);
879 auto sAt = [](
double R,
double Reff) ->
double {
880 const double v =
R *
R - Reff * Reff;
881 return (
v > 0.0) ? std::sqrt(
v) : 0.0;
886 const double sa01 = 0.0;
887 const double sb01 = sAt(R1_in, Reff_plus);
890 const double sa12 = sAt(R1_out, Reff_minus);
891 const double sb12 = sAt(R2_in, Reff_plus);
894 const double R23_start = std::max(R2_out, Rcold_out) + clearanceMargin;
895 const double sa23 = sAt(R23_start, Reff_minus);
896 const double sb23 = sAt(Rmax, Reff_plus);
898 if (!((sb01 > sa01) && (sb12 > sa12) && (sb23 > sa23))) {
900 "addInclinedWalls3FullCyl: invalid bounds. 01:[{},{}] 12:[{},{}] 23:[{},{}] "
901 "Rtan={} Reff-={} Reff+={} R23_start={}",
902 sa01, sb01, sa12, sb12, sa23, sb23,
903 Rtan, Reff_minus, Reff_plus, R23_start);
908 const double dx01 = 0.5 * (sb01 - sa01);
909 const double dx12 = 0.5 * (sb12 - sa12);
910 const double dx23 = 0.5 * (sb23 - sa23);
912 const double sc01 = 0.5 * (sa01 + sb01);
913 const double sc12 = 0.5 * (sa12 + sb12);
914 const double sc23 = 0.5 * (sa23 + sb23);
917 auto* sh01 =
new TGeoBBox(dx01, wallDy, dz);
918 auto* sh12 =
new TGeoBBox(dx12, wallDy, dz);
919 auto* sh23 =
new TGeoBBox(dx23, wallDy, dz);
920 sh01->SetName(
"VD_InclinedWall01_sh");
921 sh12->SetName(
"VD_InclinedWall12_sh");
922 sh23->SetName(
"VD_InclinedWall23_sh");
924 const double phi0_rad = phi0_deg * TMath::DegToRad();
926 for (
int i = 0;
i < nWalls; ++
i) {
927 const double phi = phi0_rad +
i * (dPhi * TMath::DegToRad());
928 const double cosPhi = std::cos(phi);
929 const double sinPhi = std::sin(phi);
932 const double xT = Rtan * cosPhi;
933 const double yT = Rtan * sinPhi;
936 const double ux = -sinPhi;
937 const double uy = cosPhi;
940 const double cx01 = xT + sc01 * ux;
941 const double cy01 = yT + sc01 * uy;
942 const double cx12 = xT + sc12 * ux;
943 const double cy12 = yT + sc12 * uy;
944 const double cx23 = xT + sc23 * ux;
945 const double cy23 = yT + sc23 * uy;
948 const double alpha_deg = phi0_deg +
i * dPhi + 90.0;
949 auto* rot =
new TGeoRotation();
950 rot->RotateZ(alpha_deg);
953 auto* v01 =
new TGeoVolume(Form(
"VD_InclinedWall01_%d",
i), sh01, med);
954 auto* v12 =
new TGeoVolume(Form(
"VD_InclinedWall12_%d",
i), sh12, med);
955 auto* v23 =
new TGeoVolume(Form(
"VD_InclinedWall23_%d",
i), sh23, med);
956 v01->SetLineColor(kOrange + 7);
957 v12->SetLineColor(kOrange + 7);
958 v23->SetLineColor(kOrange + 7);
959 v01->SetTransparency(70);
960 v12->SetTransparency(70);
961 v23->SetTransparency(70);
963 auto* T01 =
new TGeoCombiTrans(cx01, cy01, 0.0, rot);
964 auto* T12 =
new TGeoCombiTrans(cx12, cy12, 0.0,
new TGeoRotation(*rot));
965 auto* T23 =
new TGeoCombiTrans(cx23, cy23, 0.0,
new TGeoRotation(*rot));
967 petalAsm->AddNode(v01, 1, T01);
968 petalAsm->AddNode(v12, 1, T12);
969 petalAsm->AddNode(v23, 1, T23);
972 "InclinedWall {}: 01({:.3f},{:.3f}) 12({:.3f},{:.3f}) 23({:.3f},{:.3f}) angle={:.2f}°",
973 i, cx01, cy01, cx12, cy12, cx23, cy23, alpha_deg);
982 LOGP(error,
"createIRIS4Geometry: motherVolume is null");
988 constexpr int nPetals = 4;
989 for (
int p = 0; p < nPetals; ++p) {
990 auto* petal = buildPetalAssembly(nPetals, p,
false,
995 buildPetalSolidsComposite(petal);
997 const double phiDeg = (360.0 / double(nPetals)) * (
double(p) + 0.5);
998 auto*
R =
new TGeoRotation();
1000 auto* T =
new TGeoCombiTrans(0, 0, 0,
R);
1001 motherVolume->AddNode(petal, p + 1, T);
1003 buildIrisCutoutFromPetalSolid(nPetals);
1008 if (!motherVolume) {
1009 LOGP(error,
"createIRIS5Geometry: motherVolume is null");
1015 constexpr int nPetals = 4;
1016 for (
int p = 0; p < nPetals; ++p) {
1017 auto* petal = buildPetalAssembly(nPetals, p,
true,
1022 buildPetalSolidsComposite(petal);
1024 const double phiDeg = (360.0 / double(nPetals)) * (
double(p) + 0.5);
1025 auto*
R =
new TGeoRotation();
1027 auto* T =
new TGeoCombiTrans(0, 0, 0,
R);
1028 motherVolume->AddNode(petal, p + 1, T);
1030 buildIrisCutoutFromPetalSolid(nPetals);
1035 if (!motherVolume) {
1036 LOGP(error,
"createIRIS4aGeometry: motherVolume is null");
1042 constexpr int nPetals = 3;
1043 for (
int p = 0; p < nPetals; ++p) {
1044 auto* petal = buildPetalAssembly(nPetals, p,
false,
1049 buildPetalSolidsComposite(petal);
1051 const double phiDeg = (360.0 / double(nPetals)) * (
double(p) + 0.5);
1052 auto*
R =
new TGeoRotation();
1054 auto* T =
new TGeoCombiTrans(0, 0, 0,
R);
1055 motherVolume->AddNode(petal, p + 1, T);
1057 buildIrisCutoutFromPetalSolid(nPetals);
1062 if (!motherVolume) {
1063 LOGP(error,
"createIRISGeometryFullCyl: motherVolume is null");
1069 constexpr int nPetals = 1;
1070 constexpr int petalID = 0;
1072 auto* petal = buildFullCylAssembly(petalID,
false);
1073 motherVolume->AddNode(petal, 1,
nullptr);
1075 buildPetalSolidsComposite(petal);
1076 buildIrisCutoutFromPetalSolid(nPetals);
1081 if (!motherVolume) {
1082 LOGP(error,
"createIRISGeometry3InclinedWalls: motherVolume is null");
1088 constexpr int nPetals = 1;
1089 constexpr int petalID = 0;
1092 auto* petal = buildFullCylAssembly(petalID,
false);
1095 addInclinedWalls3FullCyl(petal, kInclinedWallPhi0_deg);
1097 motherVolume->AddNode(petal, 1,
nullptr);
1100 buildPetalSolidsComposite(petal);
1101 buildIrisCutoutFromPetalSolid(nPetals);
1106 if (!motherVolume) {
1107 LOGP(error,
"createIRISGeometryFullCylDisks: motherVolume is null");
1113 constexpr int nPetals = 1;
1114 constexpr int petalID = 0;
1116 auto* petal = buildFullCylAssembly(petalID,
true);
1117 motherVolume->AddNode(petal, 1,
nullptr);
1120 buildPetalSolidsComposite(petal);
1121 buildIrisCutoutFromPetalSolid(nPetals);
1126 auto* petal = buildPetalAssembly(nPetals, petalID, rectangularL0,
false,
true);
1129 const double phiDeg = (360.f /
static_cast<double>(nPetals)) * (
static_cast<double>(petalID) + 0.5f);
1130 auto*
R =
new TGeoCombiTrans(0, 0, 0,
new TGeoRotation(
"", phiDeg, 0, 0));
1131 motherVolume->AddNode(petal, 1,
R);
1133 LOGP(info,
"Debug: Added Petal{} to {}", petalID, motherVolume->GetName());
std::unique_ptr< expressions::Node > node
Class for time synchronization of RawReader instances.
static MaterialManager & Instance()
static const char * getTRKPetalDiskPattern()
static const char * getTRKSensorPattern()
static const char * getTRKPetalLayerPattern()
static const char * getTRKPetalPattern()
GLint GLint GLsizei GLint GLenum GLenum type
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLdouble GLdouble GLdouble z
constexpr double thickness
std::vector< VDSensorDesc > & vdSensorRegistry()
void createIRISGeometry3InclinedWalls(TGeoVolume *motherVolume)
void createSinglePetalDebug(TGeoVolume *motherVolume, int petalID=0, int nPetals=4, bool rectangularL0=false)
void createIRISGeometryFullCyl(TGeoVolume *motherVolume)
void createIRIS4aGeometry(TGeoVolume *motherVolume)
void createIRIS4Geometry(TGeoVolume *motherVolume)
void createIRISGeometryFullCylwithDisks(TGeoVolume *motherVolume)
void registerSensor(const std::string &volName, int petal, VDSensorDesc::Region region, VDSensorDesc::Type type, int idx)
void createIRIS5Geometry(TGeoVolume *motherVolume)
void clearVDSensorRegistry()
std::string to_string(gsl::span< T, Size > span)