Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:18:15

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