Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:22:09

0001 #include "PHG4MvtxSupport.h"
0002 
0003 #include "PHG4MvtxCable.h"
0004 #include "PHG4MvtxDetector.h"
0005 #include "PHG4MvtxDisplayAction.h"
0006 
0007 #include <g4main/PHG4Detector.h>
0008 
0009 #include <Geant4/G4AssemblyVolume.hh>
0010 #include <Geant4/G4Box.hh>
0011 #include <Geant4/G4LogicalVolume.hh>
0012 #include <Geant4/G4Material.hh>
0013 #include <Geant4/G4Polycone.hh>
0014 #include <Geant4/G4RotationMatrix.hh>  // for G4RotationMatrix
0015 #include <Geant4/G4String.hh>
0016 #include <Geant4/G4SubtractionSolid.hh>
0017 #include <Geant4/G4SystemOfUnits.hh>
0018 #include <Geant4/G4ThreeVector.hh>  // for G4ThreeVector
0019 #include <Geant4/G4Transform3D.hh>
0020 #include <Geant4/G4Tubs.hh>
0021 #include <Geant4/G4Types.hh>
0022 #include <Geant4/G4UserLimits.hh>
0023 
0024 #include <algorithm>  // for max
0025 #include <cmath>      // for M_PI, atan, cos, sin
0026 #include <format>
0027 #include <iostream>   // for operator<<, basic_...
0028 #include <regex>      // for regex
0029 #include <utility>    // for pair, make_pair
0030 #include <vector>
0031 
0032 class G4VSolid;
0033 
0034 namespace ServiceProperties
0035 {
0036   //  std::string materials[] = {"G4_Cu", "MVTX_CarbonFiber$", "G4_POLYETHYLENE"};
0037   //  const int nMaterials = sizeof(materials) / sizeof(materials[0]);
0038 
0039   const double sEndWheelSNHolesZdist = 308.0 * mm;  // ALIITSUP0187,0177,0143
0040   const double sEndWStepHoleZpos = 4. * mm;
0041   const double sEndWStepHoleZdist = 4. * mm;
0042   const double sEndWheelNLen = 30. * mm;
0043 
0044   const double sCYSSFlgSsfFlgNsf = 606.59 * mm;  // sf -> south face
0045   const double sCYSSFlgSsfCylsf = 181. * mm;
0046   const double sCYSSFlgSsfConesf = 7. * mm;
0047   const double sCYSSFlgSsfRibsf = 50. * mm;
0048   const double sPP2sfSBsf = 791.77 * mm;
0049   const double sPP2Len = 80 * mm;
0050 
0051   double ServiceEnd = -7.21 * cm;
0052   double ServiceOffset = -16.0 * cm;
0053   double BarrelOffset = 18.679 * cm;
0054   double BarrelRadius = 10.33 * cm;     // Inner radious of service barrel
0055   double BarrelThickness = 0.436 * cm;  // Thickness in cm
0056   double BarrelLength = 1214.4 * mm;    // Length of cylinder in cm
0057   double BarrelCableStart = sEndWheelSNHolesZdist / 2 - (sEndWStepHoleZpos + sEndWStepHoleZdist) + sEndWheelNLen - sCYSSFlgSsfFlgNsf - BarrelLength + sPP2sfSBsf + sPP2Len / 2;
0058   double BarrelCableEnd = BarrelCableStart - (sPP2sfSBsf + sPP2Len / 2);
0059   double LayerThickness = 0.1 * cm;  //
0060   double CYSSConeThickness = 0.216 * cm;
0061   double CYSSRibThickness = 0.170 * cm;
0062   double cableRotate[3] = {10., 5., 5.};  // Rotate the cables to line up with the staves in deg
0063 }  // namespace ServiceProperties
0064 
0065 //________________________________________________________________________________
0066 PHG4MvtxSupport::PHG4MvtxSupport(PHG4MvtxDetector *detector, PHG4MvtxDisplayAction *dispAct, bool overlapCheck)
0067   : m_Detector(detector)
0068   , m_DisplayAction(dispAct)
0069   , m_overlapCheck(overlapCheck)
0070 {
0071 }
0072 
0073 //________________________________________________________________________________
0074 PHG4MvtxSupport::~PHG4MvtxSupport()
0075 {
0076     delete m_avSupport;
0077     delete m_avBarrelCable;
0078   for (auto *av : m_avLayerCable)
0079   {
0080       delete av;
0081   }
0082 }
0083 
0084 //________________________________________________________________________________
0085 void PHG4MvtxSupport::CreateMvtxSupportMaterials()
0086 {
0087   G4double density;
0088   G4int natoms;
0089   G4String symbol;
0090   G4String material = "MVTX_EW_Al$";
0091   if (!PHG4Detector::GetDetectorMaterial(material, false))
0092   {
0093     auto *MVTX_Al = new G4Material(material, density = 2.7 * g / cm3,
0094                                   natoms = 1, kStateSolid);
0095     MVTX_Al->AddMaterial(PHG4Detector::GetDetectorMaterial("G4_Al"), 100 * perCent);
0096   }
0097 
0098   material = "MVTX_Epoxy$";
0099   if (!PHG4Detector::GetDetectorMaterial(material, false))
0100   {
0101     auto *MVTX_Epoxy = new G4Material(material, density = 1.56 * g / cm3, natoms = 4);
0102     MVTX_Epoxy->AddElement(PHG4Detector::GetDetectorElement("H", true), 32);  // Hydrogen
0103     MVTX_Epoxy->AddElement(PHG4Detector::GetDetectorElement("C", true), 2);   // Nitrogen
0104     MVTX_Epoxy->AddElement(PHG4Detector::GetDetectorElement("N", true), 4);   // Oxygen
0105     MVTX_Epoxy->AddElement(PHG4Detector::GetDetectorElement("O", true), 15);  // Carbon
0106   }
0107 
0108   material = "MVTX_CarbonFiber$";
0109   if (!PHG4Detector::GetDetectorMaterial(material, false))
0110   {
0111     auto *MVTX_CF = new G4Material(material, density = 1.987 * g / cm3,
0112                                   natoms = 2);
0113     MVTX_CF->AddMaterial(PHG4Detector::GetDetectorMaterial("G4_C"), 70 * perCent);         // Carbon (NX-80-240)
0114     MVTX_CF->AddMaterial(PHG4Detector::GetDetectorMaterial("MVTX_Epoxy$"), 30 * perCent);  // Epoxy (EX-1515)
0115   }
0116 }
0117 
0118 //________________________________________________________________________________
0119 void PHG4MvtxSupport::CreateEndWheelsSideN(G4AssemblyVolume *&av)
0120 {
0121   for (unsigned int iLay = 0; iLay < PHG4MvtxDefs::kNLayers; iLay++)
0122   {
0123     GetEndWheelSideN(iLay, av);
0124   }
0125 }
0126 
0127 //________________________________________________________________________________
0128 void PHG4MvtxSupport::GetEndWheelSideN(const int lay, G4AssemblyVolume *&endWheel)
0129 {
0130   //
0131   // Creates the single End Wheel on Side North
0132   // for a given layer of the MVTX detector
0133   // (Layer 0: MVTX-2-S-00001)
0134   // (Layer 1: MVTX-2-S-00016)
0135   // (Layer 2: MVTX-2-S-00023)
0136   //
0137   // Input:
0138   //         iLay : the layer number
0139   //         endWheel : the whole end wheel volume
0140   //                    where to place the current created wheel
0141   // Output:
0142   //
0143   // Return:
0144   //
0145   // Created:      10 Jan 2023 Yasser Corrales Morales
0146   //               (partially based on M. Sitta implementation in ITS2)
0147   //
0148 
0149   // The Basis Cone North Side is two halves,
0150   // but for sake of simplicity, so here they are made as a single cone.
0151   const double sEndWheelNRmax[3] = {30.57 * mm, 38.59 * mm, 46.30 * mm};
0152   const double sEndWheelNRmin[3] = {22.83 * mm, 30.67 * mm, 38.70 * mm};
0153   const double sEndWheelNWallR[3] = {29.57 * mm, 37.59 * mm, 45.30 * mm};
0154   const double sEndWheelNThick = 2.8 * mm;
0155 
0156   const int sEndWNBaseNBigHoles = 6;
0157   const int sEndWNBaseNSmallHoles = 5;
0158   const double sEndWNBaseBigHoleD = 4 * mm;
0159   const double sEndWNBaseSmallHoleD = 1.6 * mm;
0160   const double sEndWNBaseHolesR[3] = {27. * mm, 35. * mm, 42.7 * mm};
0161   const double sEndWNBaseHolesPhi = 15.;  // Deg
0162 
0163   const int sEndWNWallNHoles[3] = {6, 8, 10};
0164   const double sEndWNWallHoleD = 4.5 * mm;
0165 
0166   // The End Wheel Steps
0167   const double sEndWNStepXlen[3] = {9.88 * mm, 11.2 * mm, 8.38 * mm};
0168   const double sEndWNStepYdispl[3] = {26.521 * mm, 33.891 * mm, 41.64 * mm};
0169   const double sEndWNStepHolePhi[3] = {30.0, 22.5, 18.0};   // Deg
0170   const double sEndWNStepHoleTilt[3] = {0., 0.295, 0.297};  // Rad
0171 
0172   const double sEndWNStepZlen = ServiceProperties::sEndWheelNLen - sEndWheelNThick;
0173 
0174   // local varianbles
0175   double rmin;
0176   double rmax;
0177   double phimin;
0178   double dphi;
0179   double xpos;
0180   double ypos;
0181   double zpos;
0182   double rpos;
0183   double xlen;
0184   double ylen;
0185 
0186   auto Ta = G4ThreeVector();
0187   auto Ra = G4RotationMatrix();
0188 
0189   const unsigned short nZplanes = 4;
0190   const double zPlane[nZplanes] = {0. * mm,
0191                                    ServiceProperties::sEndWheelNLen - sEndWheelNThick,
0192                                    ServiceProperties::sEndWheelNLen - sEndWheelNThick,
0193                                    ServiceProperties::sEndWheelNLen};
0194 
0195   const double rInner[nZplanes] = {sEndWheelNWallR[lay], sEndWheelNWallR[lay],
0196                                    sEndWheelNRmin[lay], sEndWheelNRmin[lay]};
0197 
0198   const double rOuter[nZplanes] = {sEndWheelNRmax[lay], sEndWheelNRmax[lay],
0199                                    sEndWheelNRmax[lay], sEndWheelNRmax[lay]};
0200 
0201   G4VSolid *endWNBasis = new G4Polycone(std::string("endwnbasis" + std::to_string(lay)), 0., 2. * M_PI * rad,
0202                                         nZplanes, zPlane, rInner, rOuter);
0203 
0204   // The holes in the veritcal wall
0205   auto *endwnwalhol = new G4Tubs(std::string("endwnwalhol" + std::to_string(lay)), 0, sEndWNWallHoleD / 2,
0206                                 1.5 * (sEndWheelNRmax[lay] - sEndWheelNWallR[lay]),
0207                                 0, 2 * M_PI * rad);
0208 
0209   rmin = (sEndWheelNRmax[lay] + sEndWheelNWallR[lay]) / 2;
0210   zpos = ServiceProperties::sEndWStepHoleZpos;
0211   dphi = 180. / sEndWNWallNHoles[lay];
0212   phimin = dphi / 2;
0213   for (int ihole = 0; ihole < 2 * sEndWNWallNHoles[lay]; ihole++)
0214   {
0215     double phi = phimin + ihole * dphi;
0216     xpos = rmin * sin(phi * deg);
0217     ypos = rmin * cos(phi * deg);
0218     Ra.set(-phi * deg, 90 * deg, 0.);
0219     Ta.set(xpos, ypos, zpos);
0220     endWNBasis = new G4SubtractionSolid(std::string("endwnbasis-endwnwalhol" + std::to_string(ihole) + "l" + std::to_string(lay)),
0221                                         endWNBasis, endwnwalhol, &Ra, Ta);
0222   }
0223 
0224   // The holes in the base
0225   auto *endwnbasBhol = new G4Tubs(std::string("endwnbasBhol" + std::to_string(lay)), 0, sEndWNBaseBigHoleD / 2,
0226                                  1.5 * sEndWheelNThick, 0, 2 * M_PI * rad);
0227 
0228   auto *endwnbasShol = new G4Tubs(std::string("endwnbasShol" + std::to_string(lay)), 0, sEndWNBaseSmallHoleD / 2,
0229                                  1.5 * sEndWheelNThick, 0, 2 * M_PI * rad);
0230 
0231   rmin = sEndWNBaseHolesR[lay];
0232   zpos = ServiceProperties::sEndWheelNLen - (sEndWheelNThick / 2);
0233   phimin = 0.;
0234   for (int ihole = 0; ihole < (sEndWNBaseNBigHoles + sEndWNBaseNSmallHoles); ihole++)
0235   {
0236     phimin += sEndWNBaseHolesPhi;
0237     xpos = rmin * cos(phimin * deg);
0238     ypos = rmin * sin(phimin * deg);
0239     Ra.set(0., 0., 0.);
0240     Ta.set(xpos, ypos, zpos);
0241     auto *endwnbashol = (ihole < 2 || ihole == 5 || ihole > 8) ? endwnbasShol : endwnbasBhol;
0242     endWNBasis = new G4SubtractionSolid(std::string("endwnbasis-endwnwalhol" + std::to_string(ihole) + "l" + std::to_string(lay) + "a"),
0243                                         endWNBasis, endwnbashol, &Ra, Ta);
0244     Ta = G4ThreeVector(-xpos, -ypos, zpos);
0245     endWNBasis = new G4SubtractionSolid(std::string("endwnbasis-endwnwalhol" + std::to_string(ihole) + "l" + std::to_string(lay) + "b"),
0246                                         endWNBasis, endwnbashol, &Ra, Ta);
0247   }
0248 
0249   // Now the Step as a Composite Shape (subtraction of a Pcon from a BBox)
0250   // (cutting volume should be slightly larger than desired region)
0251   rmin = sEndWheelNWallR[lay];
0252   xlen = sEndWNStepXlen[lay] - ((lay == 1) ? 0.01 * mm : 0. * mm);
0253   double xDispl = sqrt(rmin * rmin - sEndWNStepYdispl[lay] * sEndWNStepYdispl[lay]) - xlen;
0254   ylen = sqrt(rmin * rmin - xDispl * xDispl) - sEndWNStepYdispl[lay];
0255 
0256   auto *stepBoxNSh = new G4Box(std::string("stepBoxNSh" + std::to_string(lay)), xlen / 2, ylen / 2,
0257                               (sEndWNStepZlen / 2) - 0.05 * mm);
0258 
0259   xpos = xDispl + stepBoxNSh->GetXHalfLength();
0260   ypos = sEndWNStepYdispl[lay] + stepBoxNSh->GetYHalfLength();
0261   rpos = std::sqrt(xpos * xpos + ypos * ypos);
0262 
0263   phimin = (90. * deg) - acos(sEndWNStepYdispl[lay] / rmin) * rad - 5 * deg;
0264   dphi = (90. * deg) - asin(xDispl / rmin) * rad - phimin + 5 * deg;
0265   rmax = rmin + 2 * stepBoxNSh->GetYHalfLength();
0266 
0267   auto *stepTubNSh = new G4Tubs(std::string("stepTubNSh" + std::to_string(lay)), rmin, rmax,
0268                                1.5 * sEndWNStepZlen / 2, phimin, dphi);
0269   Ra.set(0., 0., 0.);
0270   Ta.set(-xpos, -ypos, 0);
0271   auto *stepNSh = new G4SubtractionSolid(std::string("stepNSh" + std::to_string(lay)),
0272                                         stepBoxNSh, stepTubNSh, &Ra, Ta);
0273 
0274   auto *matAl = PHG4Detector::GetDetectorMaterial("MVTX_EW_Al$");
0275 
0276   auto *endWheelNvol = new G4LogicalVolume(endWNBasis, matAl, std::string("EndWheelNBasis" + std::to_string(lay)));
0277   m_DisplayAction->AddVolume(endWheelNvol, "red");
0278   m_Detector->FillSupportLVArray(endWheelNvol);
0279 
0280   auto *stepNShLogVol = new G4LogicalVolume(stepNSh, matAl, std::string("StepNL" + std::to_string(lay) + "_LOGIC"));
0281   m_DisplayAction->AddVolume(stepNShLogVol, "red");
0282   m_Detector->FillSupportLVArray(stepNShLogVol);
0283 
0284   // Finally put everything in the mother volume
0285   zpos = (ServiceProperties::sEndWheelSNHolesZdist / 2) - (ServiceProperties::sEndWStepHoleZpos + ServiceProperties::sEndWStepHoleZdist);
0286   Ra.set(0., 0., 0.);
0287   Ta.set(0, 0, zpos);
0288   endWheel->AddPlacedVolume(endWheelNvol, Ta, &Ra);
0289 
0290   dphi = std::atan(ypos / xpos);
0291   double phi0 = PHG4MvtxDefs::mvtxdat[lay][PHG4MvtxDefs::kPhi0];
0292   const int numberOfStaves = PHG4MvtxDefs::mvtxdat[lay][PHG4MvtxDefs::kNStave];
0293   zpos += (stepBoxNSh->GetZHalfLength());
0294   for (int j = 0; j < numberOfStaves; j++)
0295   {
0296     double phi = phi0 * rad;
0297     phi += j * sEndWNStepHolePhi[lay] * deg;
0298     phi -= sEndWNStepHoleTilt[lay];
0299     xpos = rpos * cos(phi);
0300     ypos = rpos * sin(phi);
0301     Ra.set(0., 0., dphi - phi);
0302     Ta.set(xpos, ypos, zpos);
0303     endWheel->AddPlacedVolume(stepNShLogVol, Ta, &Ra);
0304   }
0305 
0306   return;
0307 }
0308 
0309 //________________________________________________________________________________
0310 void PHG4MvtxSupport::CreateEndWheelsSideS(G4AssemblyVolume *&av)
0311 {
0312   for (unsigned int iLay = 0; iLay < PHG4MvtxDefs::kNLayers; iLay++)
0313   {
0314     GetEndWheelSideS(iLay, av);
0315   }
0316 }
0317 
0318 //________________________________________________________________________________
0319 void PHG4MvtxSupport::GetEndWheelSideS(const int lay, G4AssemblyVolume *&endWheel)
0320 {
0321   //
0322   // Creates the single End Wheel on Side South
0323   // for a given layer of the MVTX detector
0324   // (Layer 0: MVTX-2-S-00002)
0325   // (Layer 1: MVTX-2-S-00017)
0326   // (Layer 2: MVTX-2-S-00024)
0327   //
0328   // Input:
0329   //         iLay : the layer number
0330   //         endWheel : the whole end wheel volume
0331   //                    where to place the current created wheel
0332   // Output:
0333   //
0334   // Return:
0335   //
0336   // Created:      17 Jan 2023 Yasser Corrales Morales
0337   //               (partially based on M. Sitta implementation in ITS2)
0338   //
0339 
0340   // The Basis Cone South Side is two halves,
0341   // but for sake of simplicity, so here they are made as a single cone.
0342   const double sEWSExtSectRmax[3] = {30.97 * mm, 38.99 * mm, 46.74 * mm};
0343   const double sEWSExtSectThick[3] = {0.97 * mm, 1.20 * mm, 1.01 * mm};
0344 
0345   const double sEWSIntSectRmax[3] = {29.77 * mm, 37.79 * mm, 45.54 * mm};
0346   const double sEWSIntSectRmin[3] = {28.80 * mm, 36.80 * mm, 44.50 * mm};
0347   const double sEWSIntSectLongLen = 26 * mm;
0348   const double sEWSIntSectShortLen = 25 * mm;
0349 
0350   const double sEWSTotalLen = 42. * mm;
0351 
0352   const int sEndWSWallNHoles[3] = {6, 8, 10};
0353   const double sEndWSWallHoleD = 4.5 * mm;
0354 
0355   const double sEndWSStepXlen[3] = {10.80 * mm, 10.05 * mm, 9.45 * mm};
0356   const double sEndWSStepYdispl[3] = {26.52 * mm, 33.89 * mm, 41.64 * mm};
0357   const double sEndWSStepHolePhi[3] = {30.0, 22.5, 18.0};   // Deg
0358   const double sEndWSStepHoleTilt[3] = {0., 0.295, 0.297};  // Rad
0359 
0360   const double sEndWSStepZlen = sEWSTotalLen - sEWSIntSectLongLen;
0361   const double sEndWheelNWallR = sEWSExtSectRmax[lay] - sEWSExtSectThick[lay] + 0.05 * mm;
0362 
0363   // local varianbles
0364   double rmin;
0365   double rmax;
0366   double phimin;
0367   double dphi;
0368   double xpos;
0369   double ypos;
0370   double zpos;
0371   double rpos;
0372   double xlen;
0373   double ylen;
0374 
0375   auto Ta = G4ThreeVector();
0376   auto Ra = G4RotationMatrix();
0377 
0378   const unsigned short nZplanes = 6;
0379   const double zPlane[nZplanes] = {0. * mm,
0380                                    sEWSTotalLen - sEWSIntSectLongLen,
0381                                    sEWSTotalLen - sEWSIntSectLongLen,
0382                                    sEWSTotalLen - sEWSIntSectShortLen,
0383                                    sEWSTotalLen - sEWSIntSectShortLen,
0384                                    sEWSTotalLen};
0385 
0386   const double rInner[nZplanes] = {sEndWheelNWallR,
0387                                    sEndWheelNWallR,
0388                                    sEWSIntSectRmin[lay],
0389                                    sEWSIntSectRmin[lay],
0390                                    sEWSIntSectRmin[lay],
0391                                    sEWSIntSectRmin[lay]};
0392 
0393   const double rOuter[nZplanes] = {sEWSExtSectRmax[lay],
0394                                    sEWSExtSectRmax[lay],
0395                                    sEWSExtSectRmax[lay],
0396                                    sEWSExtSectRmax[lay],
0397                                    sEWSIntSectRmax[lay],
0398                                    sEWSIntSectRmax[lay]};
0399 
0400   G4VSolid *endWSBasis = new G4Polycone(std::string("endwsbasis" + std::to_string(lay)), 0., 2. * M_PI * rad,
0401                                         nZplanes, zPlane, rInner, rOuter);
0402 
0403   // The holes in the veritcal wall
0404   auto *endwswalhol = new G4Tubs(std::string("endwswalhol" + std::to_string(lay)), 0, sEndWSWallHoleD / 2,
0405                                 1.5 * sEWSExtSectThick[lay],
0406                                 0, 2 * M_PI * rad);
0407 
0408   rmin = sEWSExtSectRmax[lay] - sEWSExtSectThick[lay] / 2;
0409   zpos = ServiceProperties::sEndWStepHoleZpos;
0410   dphi = 180. / sEndWSWallNHoles[lay];
0411   phimin = dphi / 2;
0412   for (int ihole = 0; ihole < 2 * sEndWSWallNHoles[lay]; ihole++)
0413   {
0414     double phi = phimin + ihole * dphi;
0415     xpos = rmin * sin(phi * deg);
0416     ypos = rmin * cos(phi * deg);
0417     Ra.set(-phi * deg, 90 * deg, 0);
0418     Ta.set(xpos, ypos, zpos);
0419     endWSBasis = new G4SubtractionSolid(std::string("endwsbasis-endwswalhol" + std::to_string(ihole) + "l" + std::to_string(lay)),
0420                                         endWSBasis, endwswalhol, &Ra, Ta);
0421   }
0422 
0423   // Now the Step as a Composite Shape (subtraction of a Pcon from a BBox)
0424   // (cutting volume should be slightly larger than desired region)
0425   rmin = sEWSExtSectRmax[lay] - sEWSExtSectThick[lay];
0426   xlen = sEndWSStepXlen[lay];
0427   double xDispl = sqrt(rmin * rmin - sEndWSStepYdispl[lay] * sEndWSStepYdispl[lay]) - xlen;
0428   ylen = sqrt(rmin * rmin - xDispl * xDispl) - sEndWSStepYdispl[lay];
0429 
0430   auto *stepBoxSSh = new G4Box(std::string("stepBoxSSh" + std::to_string(lay)), xlen / 2, ylen / 2,
0431                               (sEndWSStepZlen / 2) - 0.05 * mm);
0432 
0433   xpos = xDispl + stepBoxSSh->GetXHalfLength();
0434   ypos = sEndWSStepYdispl[lay] + stepBoxSSh->GetYHalfLength();
0435   rpos = std::sqrt(xpos * xpos + ypos * ypos);
0436 
0437   phimin = (90. * deg) - acos(sEndWSStepYdispl[lay] / rmin) * rad - 5 * deg;
0438   dphi = (90. * deg) - asin(xDispl / rmin) * rad - phimin + 5 * deg;
0439   rmax = rmin + 2 * stepBoxSSh->GetYHalfLength();
0440 
0441   auto *stepTubSSh = new G4Tubs(std::string("stepTubSSh" + std::to_string(lay)), rmin, rmax,
0442                                1.5 * sEndWSStepZlen / 2, phimin, dphi);
0443   Ra.set(0., 0., 0.);
0444   Ta.set(-xpos, -ypos, 0.);
0445   auto *stepSSh = new G4SubtractionSolid(std::string("stepSSh" + std::to_string(lay)),
0446                                         stepBoxSSh, stepTubSSh, &Ra, Ta);
0447 
0448   auto *matAl = PHG4Detector::GetDetectorMaterial("MVTX_EW_Al$");
0449 
0450   auto *endWheelSvol = new G4LogicalVolume(endWSBasis, matAl, std::string("EndWheelSBasis" + std::to_string(lay)));
0451   m_DisplayAction->AddVolume(endWheelSvol, "red");
0452   m_Detector->FillSupportLVArray(endWheelSvol);
0453 
0454   auto *stepSShLogVol = new G4LogicalVolume(stepSSh, matAl, std::string("StepSL" + std::to_string(lay) + "_LOGIC"));
0455   m_DisplayAction->AddVolume(stepSShLogVol, "red");
0456   m_Detector->FillSupportLVArray(stepSShLogVol);
0457 
0458   // Finally put everything in the mother volume
0459   zpos = (ServiceProperties::sEndWheelSNHolesZdist / 2) - (ServiceProperties::sEndWStepHoleZpos + ServiceProperties::sEndWStepHoleZdist);
0460   Ra.set(0., M_PI * rad, 0.);
0461   Ta.set(0, 0, -zpos);
0462   endWheel->AddPlacedVolume(endWheelSvol, Ta, &Ra);
0463 
0464   dphi = std::atan(ypos / xpos);
0465   double phi0 = PHG4MvtxDefs::mvtxdat[lay][PHG4MvtxDefs::kPhi0];
0466   const int numberOfStaves = PHG4MvtxDefs::mvtxdat[lay][PHG4MvtxDefs::kNStave];
0467   zpos += (stepBoxSSh->GetZHalfLength());
0468   for (int j = 0; j < numberOfStaves; j++)
0469   {
0470     double phi = phi0 * rad;
0471     phi += j * sEndWSStepHolePhi[lay] * deg;
0472     phi -= sEndWSStepHoleTilt[lay];
0473     xpos = rpos * cos(phi);
0474     ypos = rpos * sin(phi);
0475     Ra.set(0., 0., dphi - phi);
0476     Ta.set(xpos, ypos, -zpos);
0477     endWheel->AddPlacedVolume(stepSShLogVol, Ta, &Ra);
0478   }
0479 
0480   return;
0481 }
0482 
0483 //________________________________________________________________________________
0484 void PHG4MvtxSupport::CreateConeLayers(G4AssemblyVolume *&av)
0485 {
0486   for (unsigned int iLay = 0; iLay < PHG4MvtxDefs::kNLayers; iLay++)
0487   {
0488     GetConeVolume(iLay, av);
0489   }
0490 }
0491 
0492 //________________________________________________________________________________
0493 void PHG4MvtxSupport::GetConeVolume(int lay, G4AssemblyVolume *&av)
0494 {
0495   //
0496   // Creates the single CF cone
0497   // for a given layer of the MVTX detector
0498   // (Layer 0: MVTX-2-S-00005)
0499   // (Layer 1: MVTX-2-S-00032)
0500   // (Layer 2: MVTX-2-S-00047)
0501   //
0502   // Input:
0503   //         iLay : the layer number
0504   //
0505   // Output:
0506   //
0507   // Return:
0508   //
0509   // Created:      20 Jan 2023 Yasser Corrales Morales
0510   //
0511 
0512   const double sEndWheelSExtSectLen = 17 * mm;
0513 
0514   const double sThickness[3] = {1. * mm, 1.12 * mm, 1.12 * mm};
0515   const double sBigCylDmax[3] = {103 * mm, 149 * mm, 195 * mm};
0516   const double sBigCylDmin = sBigCylDmax[lay] - 2 * sThickness[lay];
0517   const double sSmallCylDmin[3] = {59.94 * mm, 75.98 * mm, 91.48 * mm};
0518   const double sTotalLen[3] = {186.8 * mm, 179.74 * mm, 223 * mm};
0519   const double sSmallCylLen[3] = {91.86 * mm, 89.38 * mm, 85.38 * mm};
0520   const double sConePlusSCLen[3] = {165.79 * mm, 158.51 * mm, 152.06 * mm};
0521 
0522   const int nZplanes = 4;
0523   const double zPlane[nZplanes] = {0 * mm,
0524                                    -sSmallCylLen[lay],
0525                                    -sConePlusSCLen[lay],
0526                                    -sTotalLen[lay]};
0527 
0528   const double rInner[nZplanes] = {sSmallCylDmin[lay] / 2,
0529                                    sSmallCylDmin[lay] / 2,
0530                                    sBigCylDmin / 2,
0531                                    sBigCylDmin / 2};
0532 
0533   const double rOuter[nZplanes] = {sSmallCylDmin[lay] / 2 + sThickness[lay],
0534                                    sSmallCylDmin[lay] / 2 + sThickness[lay],
0535                                    sBigCylDmax[lay] / 2,
0536                                    sBigCylDmax[lay] / 2};
0537 
0538   auto *coneSolid = new G4Polycone(std::string("cfConeL" + std::to_string(lay)), 0., 2. * M_PI * rad,
0539                                   nZplanes, zPlane, rInner, rOuter);
0540 
0541   auto *matCF = PHG4Detector::GetDetectorMaterial("MVTX_CarbonFiber$");
0542 
0543   auto *coneLogVol = new G4LogicalVolume(coneSolid, matCF,
0544                                         std::string("ConeL" + std::to_string(lay) + "_LOGIC"),
0545                                         nullptr, nullptr, nullptr);
0546 
0547   m_DisplayAction->AddVolume(coneLogVol, "MVTX_CarbonFiber$");
0548   m_Detector->FillSupportLVArray(coneLogVol);
0549 
0550   double zpos = ServiceProperties::sEndWheelSNHolesZdist / 2 - (ServiceProperties::sEndWStepHoleZpos + ServiceProperties::sEndWStepHoleZdist) + sEndWheelSExtSectLen;
0551   G4ThreeVector Ta = G4ThreeVector(0., 0., -zpos);
0552   G4RotationMatrix Ra;
0553   av->AddPlacedVolume(coneLogVol, Ta, &Ra);
0554 
0555   return;
0556 }
0557 
0558 //________________________________________________________________________________
0559 void PHG4MvtxSupport::CreateCYSS(G4AssemblyVolume *&av)
0560 {
0561   //
0562   // Creates the CYSS
0563   // (MVTX-s-S-00080)
0564   // (MVTX-2-S-00075)
0565   // (MVTX-s-S-00079)
0566   // (MVTX-s-S-00077)
0567   // (MVTX-s-S-00078)
0568   // (MVTX-s-S-00076)
0569   //
0570   // Input:
0571   //         av : assembly volume
0572   //
0573   // Output:
0574   //
0575   // Return:
0576   //
0577   //
0578   // Created:     20 Jan 2023 Yasser Corrales Morales
0579   //
0580 
0581   // Let's start creating the North CYSS Flange
0582   // We split the CYSS flange in 2 polycone,
0583   // Although it is a single piece.
0584   const double sFlgExtThick = 1 * mm;
0585   const double sFlgIntThick = 1.5 * mm;
0586   const double sFlgSringLen = 4.5 * mm;
0587   const double sFlgLringLen = 7.5 * mm;
0588   const double sFlgRmin = 23.6 * mm;
0589   const double sFlgRmax = 52.8 * mm;
0590   const double sFlgSringRmin = 46.4 * mm;
0591   const double sFlgSringRmax = 47.4 * mm;
0592   const double sFlgLringRmin = 50.6 * mm;
0593   const double sFlgLringRmax = 51.5 * mm;
0594 
0595   const int nZplanes = 4;
0596   const double zPlane_1[nZplanes] = {0. * mm,
0597                                      sFlgIntThick,
0598                                      sFlgIntThick,
0599                                      sFlgSringLen};
0600 
0601   const double rInner_1[nZplanes] = {sFlgRmin,
0602                                      sFlgRmin,
0603                                      sFlgSringRmin,
0604                                      sFlgSringRmin};
0605 
0606   const double rOuter_1[nZplanes] = {sFlgLringRmin,
0607                                      sFlgLringRmin,
0608                                      sFlgSringRmax,
0609                                      sFlgSringRmax};
0610 
0611   const double zPlane_2[nZplanes] = {0. * mm,
0612                                      sFlgExtThick,
0613                                      sFlgExtThick,
0614                                      sFlgLringLen};
0615 
0616   const double rInner_2[nZplanes] = {sFlgLringRmin,
0617                                      sFlgLringRmin,
0618                                      sFlgLringRmin,
0619                                      sFlgLringRmin};
0620 
0621   const double rOuter_2[nZplanes] = {sFlgRmax,
0622                                      sFlgRmax,
0623                                      sFlgLringRmax,
0624                                      sFlgLringRmax};
0625 
0626   auto *flangeSolid_1 = new G4Polycone("cyssFlangeNorth_1", 0., 2. * M_PI * rad,
0627                                       nZplanes, zPlane_1, rInner_1, rOuter_1);
0628 
0629   auto *flangeSolid_2 = new G4Polycone("cyssFlangeNorth_2", 0., 2. * M_PI * rad,
0630                                       nZplanes, zPlane_2, rInner_2, rOuter_2);
0631 
0632   auto *matAl = PHG4Detector::GetDetectorMaterial("MVTX_EW_Al$");
0633 
0634   auto *cyssFlangeLogVol_1 = new G4LogicalVolume(flangeSolid_1, matAl,
0635                                                 "cyssFlangeNorth_1_LOGIC",
0636                                                 nullptr, nullptr, nullptr);
0637 
0638   m_DisplayAction->AddVolume(cyssFlangeLogVol_1, "MVTX_EW_Al$");
0639   m_Detector->FillSupportLVArray(cyssFlangeLogVol_1);
0640 
0641   auto *cyssFlangeLogVol_2 = new G4LogicalVolume(flangeSolid_2, matAl,
0642                                                 "cyssFlangeNorth_2_LOGIC",
0643                                                 nullptr, nullptr, nullptr);
0644 
0645   m_DisplayAction->AddVolume(cyssFlangeLogVol_2, "MVTX_EW_Al$");
0646   m_Detector->FillSupportLVArray(cyssFlangeLogVol_2);
0647 
0648   double zpos = ServiceProperties::sEndWheelSNHolesZdist / 2 - (ServiceProperties::sEndWStepHoleZpos + ServiceProperties::sEndWStepHoleZdist) + ServiceProperties::sEndWheelNLen + sFlgIntThick;
0649   G4ThreeVector Ta = G4ThreeVector(0., 0., zpos);
0650   G4RotationMatrix Ra(0, M_PI * rad, 0.);
0651   av->AddPlacedVolume(cyssFlangeLogVol_1, Ta, &Ra);
0652   av->AddPlacedVolume(cyssFlangeLogVol_2, Ta, &Ra);
0653 
0654   // Now we create the CYSS cylinder
0655   const double sCYSScylRmax = 52.82 * mm;
0656   const double sCYSScylRmin = 51.70 * mm;
0657   const double sCYSScylLen = 425.77 * mm;
0658 
0659   auto *cyssCylSol = new G4Tubs("CYSScyl_SOLID", sCYSScylRmin, sCYSScylRmax, sCYSScylLen / 2,
0660                                0., 2 * M_PI);
0661 
0662   auto *matCF = PHG4Detector::GetDetectorMaterial("MVTX_CarbonFiber$");
0663   auto *cyssCylLog = new G4LogicalVolume(cyssCylSol, matCF, "CYSScyl_LOGIC",
0664                                         nullptr, nullptr, nullptr);
0665   m_DisplayAction->AddVolume(cyssCylLog, "MVTX_CarbonFiber$");
0666   m_Detector->FillSupportLVArray(cyssCylLog);
0667 
0668   zpos -= (sFlgIntThick - sCYSScylLen / 2 + ServiceProperties::sCYSSFlgSsfFlgNsf - ServiceProperties::sCYSSFlgSsfCylsf);
0669   Ta.set(0., 0., zpos);
0670   Ra.set(0, 0., 0.);
0671   av->AddPlacedVolume(cyssCylLog, Ta, &Ra);
0672 
0673   // and the CYSS Cone
0674   const double sCYSSconFlgDmin = 106.03 * mm;
0675   const double sCYSSconIntDmin = 211.00 * mm;
0676   const double sCYSSconFlgThick = 1.12 * mm;
0677   const double sCYSSconFlgLen = 13.48 * mm;
0678   const double sCYSSconNoseLen = 24.39 * mm;
0679   const double sCYSSconThick = 2.16 * mm;
0680   const double sCYSSconSlopeLen = 95.0 * mm;
0681   const double sCYSSconLen = 200.28 * mm;
0682 
0683   const int nZplanesCone = 5;
0684 
0685   const double zPlanesCone[nZplanesCone] = {0 * mm,
0686                                             sCYSSconFlgLen,
0687                                             sCYSSconNoseLen,
0688                                             sCYSSconSlopeLen,
0689                                             sCYSSconLen};
0690 
0691   const double rInnerCone[nZplanesCone] = {sCYSSconFlgDmin / 2,
0692                                            sCYSSconFlgDmin / 2,
0693                                            sCYSSconFlgDmin / 2,
0694                                            sCYSSconIntDmin / 2,
0695                                            sCYSSconIntDmin / 2};
0696 
0697   const double rOuterCone[nZplanesCone] = {(sCYSSconFlgDmin + sCYSSconFlgThick) / 2,
0698                                            (sCYSSconFlgDmin + sCYSSconThick) / 2,
0699                                            (sCYSSconFlgDmin + sCYSSconThick) / 2,
0700                                            (sCYSSconIntDmin + sCYSSconThick) / 2,
0701                                            (sCYSSconIntDmin + sCYSSconThick) / 2};
0702 
0703   auto *cyssConeSol = new G4Polycone("cyssConeSol", 0., 2. * M_PI * rad,
0704                                     nZplanesCone, zPlanesCone, rInnerCone, rOuterCone);
0705 
0706   auto *cyssConeLog = new G4LogicalVolume(cyssConeSol, matCF, "CYSScone_LOGIC",
0707                                          nullptr, nullptr, nullptr);
0708   m_DisplayAction->AddVolume(cyssConeLog, "MVTX_CarbonFiber$");
0709   m_Detector->FillSupportLVArray(cyssConeLog);
0710 
0711   zpos -= (sCYSScylLen / 2 + ServiceProperties::sCYSSFlgSsfCylsf - sCYSSconLen - ServiceProperties::sCYSSFlgSsfConesf);
0712   Ta.set(0., 0., zpos);
0713   Ra.set(0, M_PI * rad, 0.);
0714   av->AddPlacedVolume(cyssConeLog, Ta, &Ra);
0715 
0716   // Create Rib
0717   const double sCYSSribRint = 97.62 * mm;
0718   const double sCYSSribRext = 99.32 * mm;
0719   const double sCYSSribRmax = 105.30 * mm;
0720   const double sCYSSribWidth = 55.23 * mm;
0721   const double sCYSSribStep1pos = (15.6 + 7.7) / 2 * mm;
0722   const double sCYSSribStep2pos = (47.6 + 39.7) / 2 * mm;
0723   const double sCYSSribThick = 1.7 * mm;
0724 
0725   const int nZplanesRib = 10;
0726   const double zPlanesRib[nZplanesRib] = {0. * mm,
0727                                           sCYSSribStep1pos,
0728                                           sCYSSribStep1pos,
0729                                           sCYSSribStep1pos + sCYSSribThick,
0730                                           sCYSSribStep1pos + sCYSSribThick,
0731                                           sCYSSribStep2pos,
0732                                           sCYSSribStep2pos,
0733                                           sCYSSribStep2pos + sCYSSribThick,
0734                                           sCYSSribStep2pos + sCYSSribThick,
0735                                           sCYSSribWidth};
0736 
0737   const double rInnerRib[nZplanesRib] = {sCYSSribRint,
0738                                          sCYSSribRint,
0739                                          sCYSSribRint,
0740                                          sCYSSribRint,
0741                                          sCYSSribRmax - sCYSSribThick,
0742                                          sCYSSribRmax - sCYSSribThick,
0743                                          sCYSSribRint,
0744                                          sCYSSribRint,
0745                                          sCYSSribRint,
0746                                          sCYSSribRint};
0747 
0748   const double rOuterRib[nZplanesRib] = {sCYSSribRext,
0749                                          sCYSSribRext,
0750                                          sCYSSribRmax,
0751                                          sCYSSribRmax,
0752                                          sCYSSribRmax,
0753                                          sCYSSribRmax,
0754                                          sCYSSribRmax,
0755                                          sCYSSribRmax,
0756                                          sCYSSribRext,
0757                                          sCYSSribRext};
0758 
0759   auto *cyssRibSol = new G4Polycone("cyssRibSol", 0., 2. * M_PI * rad,
0760                                    nZplanesRib, zPlanesRib, rInnerRib, rOuterRib);
0761 
0762   auto *cyssRibLog = new G4LogicalVolume(cyssRibSol, matCF, "CYSSrib_LOGIC",
0763                                         nullptr, nullptr, nullptr);
0764   m_DisplayAction->AddVolume(cyssRibLog, "MVTX_CarbonFiber$");
0765   m_Detector->FillSupportLVArray(cyssRibLog);
0766 
0767   zpos -= (sCYSSconLen + ServiceProperties::sCYSSFlgSsfConesf - ServiceProperties::sCYSSFlgSsfRibsf);
0768   Ta.set(0., 0., zpos);
0769   Ra.set(0, 0., 0.);
0770   av->AddPlacedVolume(cyssRibLog, Ta, &Ra);
0771 
0772   // Flange South
0773   const double sFlgSRmax = 107.7 * mm;
0774   const double sFlgSRmin = 95.0 * mm;
0775   const double sFlgSRstep = 105.3 * mm;
0776   const double sFlgSChamfeEnd = 9. * mm;
0777   const double sFlgSTotalWidth = 20. * mm;
0778   const double sFlgSRimWidth = 7. * mm;
0779 
0780   const int nZplanesFlgS = 4;
0781   const double zPlanesFlgS[nZplanesFlgS] = {0. * mm,
0782                                             sFlgSRimWidth,
0783                                             sFlgSRimWidth,
0784                                             sFlgSTotalWidth};
0785 
0786   const double rInnerFlgS[nZplanesFlgS] = {sFlgSRmin,
0787                                            sFlgSRmin,
0788                                            sFlgSRmin,
0789                                            sFlgSRstep - sFlgSChamfeEnd};
0790 
0791   const double rOuterFlgS[nZplanesFlgS] = {sFlgSRmax,
0792                                            sFlgSRmax,
0793                                            sFlgSRstep,
0794                                            sFlgSRstep};
0795 
0796   auto *cyssFlgSSol = new G4Polycone("cyssFlgSSol", 0., 2. * M_PI * rad,
0797                                     nZplanesFlgS, zPlanesFlgS, rInnerFlgS, rOuterFlgS);
0798 
0799   auto *cyssFlgSLog = new G4LogicalVolume(cyssFlgSSol, matAl, "CYSSFlgS_LOGIC",
0800                                          nullptr, nullptr, nullptr);
0801   m_DisplayAction->AddVolume(cyssFlgSLog, "MVTX_EW_Al$");
0802   m_Detector->FillSupportLVArray(cyssFlgSLog);
0803 
0804   zpos -= (ServiceProperties::sCYSSFlgSsfRibsf);
0805   Ta.set(0., 0., zpos);
0806   Ra.set(0, 0., 0.);
0807   av->AddPlacedVolume(cyssFlgSLog, Ta, &Ra);
0808 
0809   return;
0810 }
0811 
0812 //________________________________________________________________________________
0813 void PHG4MvtxSupport::CreateServiceBarrel(G4AssemblyVolume *&av)
0814 {
0815   //
0816   // Creates the ServiceBarrel
0817   // (MVTX-2-S-00181)
0818   // (MVTX-2-S-00081)
0819   //
0820   // Input:
0821   //         av : assembly volume
0822   //
0823   // Output:
0824   //
0825   // Return:
0826   //
0827   //
0828   // Created:     21 Jan 2023 Yasser Corrales Morales
0829   //
0830 
0831   // Local Variables
0832   double zpos;
0833 
0834   G4ThreeVector Ta;
0835   G4RotationMatrix Ra;
0836 
0837   // MVTX North SB Flange
0838   const double sSBFlgNRmax = 107.7 * mm;
0839   const double sSBFlgNRmin = 95.0 * mm;
0840   const double sSBFlgNRimRmax = 105.3 * mm;
0841   const double sSBFlgNRimRmin = 103.3 * mm;
0842   const double sSBFlgNIntThick = 4.92 * mm;
0843   const double sSBFlgNExtThick = 7.00 * mm;
0844   const double sSBFlgNTotThick = 16.0 * mm;
0845 
0846   const int nZplanesFlgN = 5;
0847   const double zPlanesFlgN[nZplanesFlgN] = {0. * mm,
0848                                             sSBFlgNIntThick,
0849                                             sSBFlgNExtThick,
0850                                             sSBFlgNExtThick,
0851                                             sSBFlgNTotThick};
0852 
0853   const double rInnerFlgN[nZplanesFlgN] = {sSBFlgNRmin,
0854                                            sSBFlgNRmin,
0855                                            sSBFlgNRimRmin,
0856                                            sSBFlgNRimRmin,
0857                                            sSBFlgNRimRmin};
0858 
0859   const double rOuterFlgN[nZplanesFlgN] = {sSBFlgNRmax,
0860                                            sSBFlgNRmax,
0861                                            sSBFlgNRmax,
0862                                            sSBFlgNRimRmax,
0863                                            sSBFlgNRimRmax};
0864 
0865   auto *sbFlgNSol = new G4Polycone("sbFlgNSol", 0., 2. * M_PI * rad,
0866                                   nZplanesFlgN, zPlanesFlgN, rInnerFlgN, rOuterFlgN);
0867 
0868   auto *matAl = PHG4Detector::GetDetectorMaterial("MVTX_EW_Al$");
0869 
0870   auto *sbFlgNLog = new G4LogicalVolume(sbFlgNSol, matAl, "sbFlgN_LOGIC",
0871                                        nullptr, nullptr, nullptr);
0872   m_DisplayAction->AddVolume(sbFlgNLog, "MVTX_CarbonFiber$");
0873   m_Detector->FillSupportLVArray(sbFlgNLog);
0874 
0875   zpos = ServiceProperties::sEndWheelSNHolesZdist / 2 - (ServiceProperties::sEndWStepHoleZpos + ServiceProperties::sEndWStepHoleZdist) + ServiceProperties::sEndWheelNLen - ServiceProperties::sCYSSFlgSsfFlgNsf;
0876   Ta.set(0., 0., zpos);
0877   Ra.set(0, M_PI * rad, 0.);
0878   av->AddPlacedVolume(sbFlgNLog, Ta, &Ra);
0879 
0880   // SB Cylinder (To confirm)
0881   const double sSBcylRmin = 105.5 * mm;
0882   const double sSBcylRmax = 107.66 * mm;
0883   const double sSBcylLen = 1197.0 * mm;
0884 
0885   auto *sbCylSol = new G4Tubs("SBcyl_SOLID", sSBcylRmin, sSBcylRmax,
0886                              sSBcylLen / 2, 0., 2 * M_PI);
0887 
0888   auto *matCF = PHG4Detector::GetDetectorMaterial("MVTX_CarbonFiber$");
0889   auto *sbCylLog = new G4LogicalVolume(sbCylSol, matCF, "SBcyl_LOGIC",
0890                                       nullptr, nullptr, nullptr);
0891   m_DisplayAction->AddVolume(sbCylLog, "MVTX_CarbonFiber$");
0892   m_Detector->FillSupportLVArray(sbCylLog);
0893 
0894   zpos -= (sSBcylLen / 2 + sSBFlgNExtThick);
0895   Ta.set(0., 0., zpos);
0896   Ra.set(0, 0., 0.);
0897   av->AddPlacedVolume(sbCylLog, Ta, &Ra);
0898 
0899   return;
0900 }
0901 
0902 //________________________________________________________________________________
0903 void PHG4MvtxSupport::CreateCable(PHG4MvtxCable *object, G4AssemblyVolume &assemblyVolume)
0904 {
0905   std::string cableMaterials[2] = {object->get_coreMaterial(), "G4_POLYETHYLENE"};
0906 
0907   double dX = object->get_xNorth() - object->get_xSouth();
0908   double dY = object->get_yNorth() - object->get_ySouth();
0909   double dZ = object->get_zNorth() - object->get_zSouth();
0910 
0911   double rotY = dZ != 0. ? std::atan(dX / dZ) : 0.;
0912   double rotZ = dX != 0. ? std::atan(dY / dX) : 0.;
0913 
0914   double setX = (object->get_xSouth() + object->get_xNorth()) / 2;
0915   double setY = (object->get_ySouth() + object->get_yNorth()) / 2;
0916   double setZ = (object->get_zSouth() + object->get_zNorth()) / 2;
0917 
0918   double length = std::sqrt(dX * dX + dY * dY + dZ * dZ);
0919   double IR[2] = {0, object->get_coreRadius()};
0920   double OR[2] = {object->get_coreRadius(), object->get_sheathRadius()};
0921 
0922   G4RotationMatrix rot;
0923   rot.rotateY(rotY);
0924   rot.rotateZ(rotZ);
0925   G4ThreeVector place;
0926   place.setX(setX);
0927   place.setY(setY);
0928   place.setZ(setZ);
0929   G4Transform3D transform(rot, place);
0930   // we need just one of these but have multiple calls to this method
0931   static G4UserLimits *g4userLimits = new G4UserLimits(0.01);
0932 
0933   for (int i = 0; i < 2; ++i)
0934   {
0935     G4Material *trackerMaterial = PHG4Detector::GetDetectorMaterial(cableMaterials[i]);
0936 
0937     G4VSolid *cylinderSolid = new G4Tubs(G4String(object->get_name() + "_SOLID"),
0938                                          IR[i], OR[i], (length / 2.), 0, 2 * M_PI);
0939 
0940     G4LogicalVolume *cylinderLogic = new G4LogicalVolume(cylinderSolid, trackerMaterial,
0941                                                          G4String(object->get_name() + "_LOGIC"), nullptr, nullptr, g4userLimits);
0942     m_Detector->FillSupportLVArray(cylinderLogic);
0943 
0944     if (i == 0)
0945     {
0946       m_DisplayAction->AddVolume(cylinderLogic, cableMaterials[i]);
0947     }
0948     else
0949     {
0950       m_DisplayAction->AddVolume(cylinderLogic, object->get_color());
0951     }
0952 
0953     assemblyVolume.AddPlacedVolume(cylinderLogic, transform);
0954   }
0955 }
0956 
0957 //________________________________________________________________________________
0958 void PHG4MvtxSupport::CreateCableBundle(G4AssemblyVolume &assemblyVolume, const std::string &superName,
0959                                         bool enableSignal, bool enableCooling, bool enablePower,
0960                                         double x1, double x2, double y1, double y2, double z1, double z2)  //, double theta)
0961 {
0962   // Set up basic MVTX cable bundle (24 Samtec cables, 1 power cable, 2 cooling cables)
0963   double samtecCoreRadius = 0.01275 * cm;
0964   double samtecSheathRadius = 0.05 * cm;
0965   double coolingStaveCoreRadius = 0.056 * cm;
0966   double coolingStaveSheathRadius = 0.1 * cm;
0967   double coolingCoreRadius = 0.125 * cm;
0968   double coolingSheathRadius = 0.2 * cm;  //?
0969   double powerLargeCoreRadius = 0.069 * cm;
0970   double powerLargeSheathRadius = 0.158 * cm;
0971   double powerMediumCoreRadius = 0.033 * cm;
0972   double powerMediumSheathRadius = 0.082 * cm;
0973   double powerSmallCoreRadius = 0.028 * cm;
0974   double powerSmallSheathRadius = 0.0573 * cm;  //?
0975 
0976   double globalShiftX = 0.;
0977   double globalShiftY = -0.0984 * cm;
0978   double samtecShiftX = -6 * samtecSheathRadius + globalShiftX;
0979   double samtecShiftY = 1 * samtecSheathRadius + globalShiftY;
0980   double coolingShiftX = -3 * coolingSheathRadius + globalShiftX;
0981   double coolingShiftY = -1 * coolingSheathRadius + globalShiftY;
0982   double powerShiftX = 3.5 * powerLargeSheathRadius + globalShiftX;
0983   double powerShiftY = 6.1 * powerLargeSheathRadius + globalShiftY;
0984 
0985   // Samtec cables (we use 24 as there are 12 twinax)
0986   if (enableSignal)
0987   {
0988     unsigned int nSamtecWires = 24;
0989     unsigned int nRow = 8;
0990     unsigned int nCol = nSamtecWires / nRow;
0991     for (unsigned int iRow = 0; iRow < nRow; ++iRow)
0992     {
0993       for (unsigned int iCol = 0; iCol < nCol; ++iCol)
0994       {
0995         double deltaX = samtecShiftX + ((iCol + 1) * (samtecSheathRadius * 2.6));
0996         double deltaY = samtecShiftY - ((iRow + 1) * (samtecSheathRadius * 2.1));
0997         PHG4MvtxCable *cable = new PHG4MvtxCable(std::format("{}_samtec_{}_{}", superName, iRow, iCol),
0998                                                  "G4_Cu", samtecCoreRadius, samtecSheathRadius,
0999                                                  x1 + deltaX, x2 + deltaX, y1 + deltaY,
1000                                                  y2 + deltaY, z1, z2, "blue");
1001         CreateCable(cable, assemblyVolume);
1002         delete cable;
1003       }
1004     }
1005   }
1006 
1007   // Cooling Cables
1008   if (enableCooling)
1009   {
1010     unsigned int nCool = 2;
1011     std::string cooling_color[2] = {"red", "white"};
1012     // std::regex_constants::icase - TO IGNORE CASE.
1013     auto rx = std::regex{"MVTX_L([0-2])", std::regex_constants::icase};
1014     bool smallCooling = std::regex_search(superName, rx);
1015     PHG4MvtxCable *cable = nullptr;
1016     for (unsigned int iCool = 0; iCool < nCool; ++iCool)
1017     {
1018       double coreRadius = smallCooling ? coolingStaveCoreRadius : coolingCoreRadius;
1019       double sheathRadius = smallCooling ? coolingStaveSheathRadius : coolingSheathRadius;
1020       if (!smallCooling)
1021       {
1022         double deltaX = coolingShiftX + ((iCool + 1) * (sheathRadius * 2));
1023         double deltaY = coolingShiftY + (sheathRadius * 2);
1024         cable = new PHG4MvtxCable(std::format("{}_cooling_{}", superName, iCool),
1025                                   "G4_WATER", coreRadius, sheathRadius,
1026                                   x1 + deltaX, x2 + deltaX, y1 + deltaY,
1027                                   y2 + deltaY, z1, z2, cooling_color[iCool]);
1028       }
1029       else
1030       {
1031         double deltaX = coolingShiftX + (sheathRadius * 2);
1032         double deltaY = coolingShiftY + ((iCool + 1) * (sheathRadius * 2));
1033         cable = new PHG4MvtxCable(std::format("{}_cooling_{}", superName, iCool),
1034                                   "G4_WATER", coreRadius, sheathRadius,
1035                                   x1 + deltaX, x2 + deltaX, y1 + deltaY,
1036                                   y2 + deltaY, z1, z2, cooling_color[iCool]);
1037       }
1038       CreateCable(cable, assemblyVolume);
1039       delete cable;
1040     }
1041   }
1042 
1043   // Power Cables
1044   if (enablePower)
1045   {
1046     using PowerCableParameters = std::pair<std::pair<std::string, std::string>, std::pair<double, double>>;
1047     std::vector<PowerCableParameters> powerCables;
1048     std::vector<std::vector<double>> powerCableColors;
1049 
1050     powerCables.emplace_back(std::make_pair(std::format("{}_digiReturn", superName), "Large"), std::make_pair((-2.5 * powerLargeSheathRadius) + powerShiftX, (-2.5 * powerLargeSheathRadius) + powerShiftY));
1051     powerCables.emplace_back(std::make_pair(std::format("{}_digiSupply", superName), "Large"), std::make_pair((-4.5 * powerLargeSheathRadius) + powerShiftX, (-1.5 * powerLargeSheathRadius) + powerShiftY));
1052     powerCables.emplace_back(std::make_pair(std::format("{}_anaReturn", superName), "Medium"), std::make_pair((-4 * powerLargeSheathRadius) + powerShiftX, (-5.75 * powerMediumSheathRadius) + powerShiftY));
1053     powerCables.emplace_back(std::make_pair(std::format("{}_anaSupply", superName), "Medium"), std::make_pair((-5.1 * powerLargeSheathRadius) + powerShiftX, (-5.75 * powerMediumSheathRadius) + powerShiftY));
1054     powerCables.emplace_back(std::make_pair(std::format("{}_digiSense", superName), "Small"), std::make_pair((-10 * powerSmallSheathRadius) + powerShiftX, (-1 * powerSmallSheathRadius) + powerShiftY));
1055     powerCables.emplace_back(std::make_pair(std::format("{}_anaSense", superName), "Small"), std::make_pair((-8 * powerSmallSheathRadius) + powerShiftX, (-2 * powerSmallSheathRadius) + powerShiftY));
1056     powerCables.emplace_back(std::make_pair(std::format("{}_bias", superName), "Small"), std::make_pair((-6 * powerSmallSheathRadius) + powerShiftX, (-3 * powerSmallSheathRadius) + powerShiftY));
1057     powerCables.emplace_back(std::make_pair(std::format("{}_ground", superName), "Small"), std::make_pair((-4 * powerSmallSheathRadius) + powerShiftX, (-4 * powerSmallSheathRadius) + powerShiftY));
1058 
1059     for (PowerCableParameters &powerCable : powerCables)
1060     {
1061       double coreRad;
1062       double sheathRad;
1063       std::string cableColor;
1064       std::string cableType = powerCable.first.second;
1065       std::string cableName = powerCable.first.first;
1066       if (cableType == "Small")
1067       {
1068         coreRad = powerSmallCoreRadius;
1069         sheathRad = powerSmallSheathRadius;
1070       }
1071       else if (cableType == "Medium")
1072       {
1073         coreRad = powerMediumCoreRadius;
1074         sheathRad = powerMediumSheathRadius;
1075       }
1076       else
1077       {
1078         coreRad = powerLargeCoreRadius;
1079         sheathRad = powerLargeSheathRadius;
1080       }
1081 
1082       if (cableName == std::format("{}_digiReturn", superName))
1083       {
1084         cableColor = "black";
1085       }
1086       if (cableName == std::format("{}_digiSupply", superName))
1087       {
1088         cableColor = "red";
1089       }
1090       if (cableName == std::format("{}_anaReturn", superName))
1091       {
1092         cableColor = "black";
1093       }
1094       if (cableName == std::format("{}_anaSupply", superName))
1095       {
1096         cableColor = "red";
1097       }
1098       if (cableName == std::format("{}_digiSense", superName))
1099       {
1100         cableColor = "white";
1101       }
1102       if (cableName == std::format("{}_anaSense", superName))
1103       {
1104         cableColor = "green";
1105       }
1106       if (cableName == std::format("{}_bias", superName))
1107       {
1108         cableColor = "white";
1109       }
1110       if (cableName == std::format("{}_ground", superName))
1111       {
1112         cableColor = "green";
1113       }
1114 
1115       PHG4MvtxCable *cable = new PHG4MvtxCable(powerCable.first.first, "G4_Cu", coreRad, sheathRad,
1116                                                (x1 + powerCable.second.first), (x2 + powerCable.second.first),
1117                                                (y1 + powerCable.second.second), (y2 + powerCable.second.second), z1, z2, cableColor);
1118       CreateCable(cable, assemblyVolume);
1119       delete cable;
1120     }
1121   }
1122 }
1123 
1124 //________________________________________________________________________________
1125 G4AssemblyVolume *PHG4MvtxSupport::buildBarrelCable()
1126 {
1127   G4AssemblyVolume *av = new G4AssemblyVolume();
1128 
1129   CreateCableBundle(*av, "barrelCable", true, true, false, 0, 0, 0, 0,
1130                     ServiceProperties::BarrelCableEnd, ServiceProperties::BarrelCableStart);
1131   CreateCableBundle(*av, "barrelCable", false, false, true, 0, 0, 0, 0,
1132                     ServiceProperties::BarrelCableEnd,
1133                     -ServiceProperties::sEndWheelSNHolesZdist / 2 + (ServiceProperties::sEndWStepHoleZpos + ServiceProperties::sEndWStepHoleZdist) - 40 * cm);
1134   return av;
1135 }
1136 
1137 //________________________________________________________________________________
1138 G4AssemblyVolume *PHG4MvtxSupport::buildLayerCables(const int &lay)
1139 {
1140   G4AssemblyVolume *av = new G4AssemblyVolume();
1141   //  double rInner[3] = { 59.94 / 2 * mm, 75.98 / 2 * mm, 91.48 / 2 * mm };
1142   double rOuter[3] = {(103 - 2.) / 2 * mm, (149 - 2.24) / 2 * mm, (195 - 2.24) / 2 * mm};
1143   double zConeLen[3] = {186.8 * mm, 179.74 * mm, 223 * mm};
1144   double zMax = -ServiceProperties::sEndWheelSNHolesZdist / 2 + (ServiceProperties::sEndWStepHoleZpos + ServiceProperties::sEndWStepHoleZdist) - 17 * mm - zConeLen[lay];
1145   //  double zTransition2[3] = { -9.186 * cm, -8.938 *cm,  -8.538 * cm };
1146   CreateCableBundle(*av, std::string("MVTX_L" + std::to_string(lay) + "Cable"), true, true, false,
1147                     rOuter[lay] - 3 * mm, rOuter[lay] - 5 * mm, 0, 0,
1148                     ServiceProperties::BarrelCableStart + 1 * mm, zMax);
1149 
1150   //  double zCoolStart = - ServiceProperties::sEndWheelSNHolesZdist / 2 + ( ServiceProperties::sEndWStepHoleZpos + ServiceProperties::sEndWStepHoleZdist )
1151   //                     - 17 * mm - zConeLen[lay];
1152   //  CreateCableBundle( *av, Form( "MVTX_L%dCool_0", lay ), false, true, false, rInner[lay], rInner[lay], 0, 0,
1153   //                     ServiceProperties::BarrelCableStart,  );
1154   //  CreateCableBundle(*av, Form( "MVTX_L%dCable_1", lay ), true, false, false, rOuter[lay], rInner[lay], 0, 0, zTransition1[lay] + 0.1, zTransition2[lay]);
1155   //  CreateCableBundle(*av, Form( "MVTX_L%dCable_2", lay ), true, false, false, rInner[lay], rInner[lay], 0, 0, zTransition2[lay] + 0.1, zMax);
1156 
1157   return av;
1158 }
1159 
1160 //________________________________________________________________________________
1161 void PHG4MvtxSupport::ConstructMvtxSupport(G4LogicalVolume *&lv)
1162 {
1163   CreateMvtxSupportMaterials();
1164   m_avSupport = new G4AssemblyVolume();
1165 
1166   CreateEndWheelsSideN(m_avSupport);
1167   CreateEndWheelsSideS(m_avSupport);
1168   CreateConeLayers(m_avSupport);
1169   CreateCYSS(m_avSupport);
1170   CreateServiceBarrel(m_avSupport);
1171 
1172   G4RotationMatrix Ra;
1173   G4ThreeVector Ta = G4ThreeVector();
1174   G4Transform3D Tr(Ra, Ta);
1175   m_avSupport->MakeImprint(lv, Tr, 0, m_overlapCheck);
1176 
1177   unsigned int nStaves[PHG4MvtxDefs::kNLayers];
1178   unsigned int totStaves = 0;
1179   for (unsigned int i = 0; i < PHG4MvtxDefs::kNLayers; ++i)
1180   {
1181     nStaves[i] = (int) PHG4MvtxDefs::mvtxdat[i][PHG4MvtxDefs::kNStave];
1182     totStaves += nStaves[i];
1183   }
1184 
1185   m_avBarrelCable = buildBarrelCable();
1186   G4ThreeVector placeBarrelCable;
1187   for (unsigned int i = 0; i < totStaves; ++i)
1188   {
1189     double phi = (2.0 * M_PI / totStaves) * i;
1190     placeBarrelCable.setX((ServiceProperties::BarrelRadius - 1 * cm) * std::cos(phi));
1191     placeBarrelCable.setY((ServiceProperties::BarrelRadius - 1 * cm) * std::sin(phi));
1192     G4RotationMatrix rotBarrelCable;
1193     rotBarrelCable.rotateZ(phi + (-90. * deg));
1194     G4Transform3D transformBarrelCable(rotBarrelCable, placeBarrelCable);
1195     m_avBarrelCable->MakeImprint(lv, transformBarrelCable, 0, m_overlapCheck);
1196   }
1197 
1198   for (unsigned int iLayer = 0; iLayer < PHG4MvtxDefs::kNLayers; ++iLayer)
1199   {
1200     m_avLayerCable[iLayer] = buildLayerCables(iLayer);
1201     for (unsigned int iStave = 0; iStave < nStaves[iLayer]; ++iStave)
1202     {
1203       G4RotationMatrix rotCable;
1204       G4ThreeVector placeCable;
1205       double phi = (2.0 * M_PI / nStaves[iLayer]) * iStave;
1206       placeCable.setX(std::cos(phi));
1207       placeCable.setY(std::sin(phi));
1208       rotCable.rotateZ(phi + ((90. + ServiceProperties::cableRotate[iLayer]) * deg));
1209       G4Transform3D transformCable(rotCable, placeCable);
1210       m_avLayerCable[iLayer]->MakeImprint(lv, transformCable, 0, m_overlapCheck);
1211     }
1212   }
1213 }