Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:14:40

0001 //====================================================================
0002 //  LCGeo - LC detector models in DD4hep
0003 //--------------------------------------------------------------------
0004 // Mask based on the Beampipe driver (based on TubeX from Mokka), but not
0005 // filling the centre with Beam vaccum, just places cylinders in arbitrary
0006 // places with different alignments
0007 //  A.Sailer, CERN
0008 //  $Id$
0009 //====================================================================
0010 #include "FCC_OtherDetectorHelpers.h"
0011 
0012 #include "DD4hep/DD4hepUnits.h"
0013 #include "DD4hep/DetFactoryHelper.h"
0014 #include <cmath>
0015 #include <string>
0016 
0017 using dd4hep::Assembly;
0018 using dd4hep::ConeSegment;
0019 using dd4hep::DetElement;
0020 using dd4hep::Detector;
0021 using dd4hep::Material;
0022 using dd4hep::PlacedVolume;
0023 using dd4hep::Position;
0024 using dd4hep::Ref_t;
0025 using dd4hep::RotateY;
0026 using dd4hep::RotationY;
0027 using dd4hep::RotateX;
0028 using dd4hep::RotationX;
0029 using dd4hep::SensitiveDetector;
0030 using dd4hep::Solid;
0031 using dd4hep::SubtractionSolid;
0032 using dd4hep::Transform3D;
0033 using dd4hep::Tube;
0034 using dd4hep::Volume;
0035 
0036 static Ref_t create_element(Detector& theDetector, xml_h xmlHandle, SensitiveDetector /*sens*/) {
0037 
0038   //------------------------------------------
0039   //  See comments starting with '//**' for
0040   //     hints on porting issues
0041   //------------------------------------------
0042 
0043   std::cout << "This is the Mask:" << std::endl;
0044 
0045   // Access to the XML File
0046   xml_det_t xmlMask = xmlHandle;
0047   const std::string name = xmlMask.nameStr();
0048 
0049   //--------------------------------
0050   Assembly envelope(name + "_assembly");
0051   //--------------------------------
0052 
0053   DetElement tube(name, xmlMask.id());
0054 
0055   //  const double phi1 = 0 ;
0056   //  const double phi2 = 360.0*dd4hep::degree;
0057 
0058   // Parameters we have to know about
0059   dd4hep::xml::Component xmlParameter = xmlMask.child(_Unicode(parameter));
0060   const double crossingAngle = xmlParameter.attr<double>(_Unicode(crossingangle)) * 0.5;  //  only half the angle
0061 
0062   for (xml_coll_t c(xmlMask, Unicode("section")); c; ++c) {
0063 
0064     xml_comp_t xmlSection(c);
0065 
0066     ODH::ECrossType crossType = ODH::getCrossType(xmlSection.attr<std::string>(_Unicode(type)));
0067     const double zStart = xmlSection.attr<double>(_Unicode(start));
0068     const double zEnd = xmlSection.attr<double>(_Unicode(end));
0069     const double rInnerStart = xmlSection.attr<double>(_Unicode(rMin1));
0070     const double rInnerEnd = xmlSection.attr<double>(_Unicode(rMin2));
0071     const double rOuterStart = xmlSection.attr<double>(_Unicode(rMax1));
0072     const double rOuterEnd = xmlSection.attr<double>(_Unicode(rMax2));
0073     const double phi1 = xmlSection.attr<double>(_Unicode(Phi1));
0074     const double phi2 = xmlSection.attr<double>(_Unicode(Phi2));
0075     const double thickness = rOuterStart - rInnerStart;
0076     Material sectionMat = theDetector.material(xmlSection.materialStr());
0077     const std::string volName = "tube_" + xmlSection.nameStr();
0078 
0079     std::cout << std::setw(8) << zStart << std::setw(8) << zEnd << std::setw(8) << rInnerStart << std::setw(8)
0080               << rInnerEnd << std::setw(8) << rOuterStart << std::setw(8) << rOuterEnd << std::setw(8) << thickness
0081               << std::setw(8) << crossType << std::setw(8) << phi1 << std::setw(8) << phi2 << std::setw(15) << volName
0082               << std::setw(15) << sectionMat.name() << std::endl;
0083 
0084     // things which can be calculated immediately
0085     const double zHalf = fabs(zEnd - zStart) * 0.5;      // half z length of the cone
0086     const double zPosition = fabs(zEnd + zStart) * 0.5;  // middle z position
0087     Material material = sectionMat;
0088 
0089     // this could mess up your geometry, so better check it
0090     if (not ODH::checkForSensibleGeometry(crossingAngle, crossType)) {
0091       throw std::runtime_error(" Mask_o1_v01_noRot_geo.cpp : checkForSensibleGeometry() failed ");
0092     }
0093 
0094     const double rotateAngle =
0095         getCurrentAngle(crossingAngle, crossType);  // for the placement at +z (better make it const now)
0096     const double mirrorAngle = M_PI - rotateAngle;  // for the "mirrored" placement at -z
0097     // the "mirroring" in fact is done by a rotation of (almost) 180 degrees around the y-axis
0098 
0099     switch (crossType) {
0100     case ODH::kCenter:
0101     case ODH::kUpstream:
0102     case ODH::kDnstream: {
0103       // a volume on the z-axis, on the upstream branch, or on the downstream branch
0104 
0105       // absolute transformations for the placement in the world, rotate over X
0106       Transform3D transformer(RotationX(rotateAngle), RotateX(Position(0, 0, zPosition), rotateAngle));
0107       Transform3D transmirror(RotationX(mirrorAngle), RotateX(Position(0, 0, zPosition), mirrorAngle));
0108 
0109       // solid for the tube (including vacuum and wall): a solid cone
0110       ConeSegment tubeSolid(zHalf, rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, phi1, phi2);
0111 
0112       // tube consists of vacuum
0113       Volume tubeLog(volName, tubeSolid, material);
0114       tubeLog.setVisAttributes(theDetector, xmlMask.visStr());
0115 
0116       // placement of the tube in the world, both at +z and -z
0117       envelope.placeVolume(tubeLog, transformer);
0118       envelope.placeVolume(tubeLog, transmirror);
0119 
0120     } break;
0121 
0122     case ODH::kPunchedCenter: {
0123       // a cone with one or two inner holes (two tubes are punched out)
0124 
0125       const double rUpstreamPunch = rInnerStart;  // just alias names denoting what is meant here
0126       const double rDnstreamPunch = rInnerEnd;    // (the database entries are "abused" in this case)
0127 
0128       // relative transformations for the composition of the SubtractionVolumes
0129       Transform3D upstreamTransformer(RotationY(-crossingAngle), Position(zPosition * tan(-crossingAngle), 0, 0));
0130       Transform3D dnstreamTransformer(RotationY(+crossingAngle), Position(zPosition * tan(+crossingAngle), 0, 0));
0131 
0132       // absolute transformations for the final placement in the world (angles always equal zero and 180 deg)
0133       Transform3D placementTransformer(RotationY(rotateAngle), RotateY(Position(0, 0, zPosition), rotateAngle));
0134       Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY(Position(0, 0, zPosition), mirrorAngle));
0135 
0136       // the main solid and the two pieces (only tubes, for the moment) which will be punched out
0137       ConeSegment wholeSolid(zHalf, 0, rOuterStart, 0, rOuterEnd, phi1, phi2);
0138       Solid tmpSolid0, tmpSolid1, finalSolid0, finalSolid1;
0139 
0140       // the punched subtraction solids can be asymmetric and therefore have to be created twice:
0141       // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
0142       // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
0143 
0144       if (rUpstreamPunch > 1e-6) {                                     // do we need a hole on the upstream branch?
0145         Tube upstreamPunch(0, rUpstreamPunch, 5 * zHalf, phi1, phi2);  // a bit longer
0146         tmpSolid0 = SubtractionSolid(wholeSolid, upstreamPunch, upstreamTransformer);
0147         tmpSolid1 = SubtractionSolid(wholeSolid, upstreamPunch, dnstreamTransformer);  // [sic]
0148       } else {  // dont't do anything, just pass on the unmodified shape
0149         tmpSolid0 = wholeSolid;
0150         tmpSolid1 = wholeSolid;
0151       }
0152 
0153       if (rDnstreamPunch > 1e-6) {                                     // do we need a hole on the downstream branch?
0154         Tube dnstreamPunch(0, rDnstreamPunch, 5 * zHalf, phi1, phi2);  // a bit longer
0155         finalSolid0 = SubtractionSolid(tmpSolid0, dnstreamPunch, dnstreamTransformer);
0156         finalSolid1 = SubtractionSolid(tmpSolid1, dnstreamPunch, upstreamTransformer);  // [sic]
0157       } else {  // dont't do anything, just pass on the unmodified shape
0158         finalSolid0 = tmpSolid0;
0159         finalSolid1 = tmpSolid1;
0160       }
0161 
0162       // tube consists of vacuum (will later have two different daughters)
0163       Volume tubeLog0(volName + "_0", finalSolid0, material);
0164       Volume tubeLog1(volName + "_1", finalSolid1, material);
0165       tubeLog0.setVisAttributes(theDetector, xmlMask.visStr());
0166       tubeLog1.setVisAttributes(theDetector, xmlMask.visStr());
0167 
0168       // placement of the tube in the world, both at +z and -z
0169       envelope.placeVolume(tubeLog0, placementTransformer);
0170       envelope.placeVolume(tubeLog1, placementTransmirror);
0171 
0172       break;
0173     }
0174 
0175     case ODH::kPunchedUpstream:
0176     case ODH::kPunchedDnstream: {
0177       // a volume on the upstream or downstream branch with two inner holes
0178       // (implemented as a cone from which another tube is punched out)
0179 
0180       const double rCenterPunch = (crossType == ODH::kPunchedUpstream)
0181           ? (rInnerStart)
0182           : (rInnerEnd);  // just alias names denoting what is meant here
0183       const double rOffsetPunch = (crossType == ODH::kPunchedDnstream)
0184           ? (rInnerStart)
0185           : (rInnerEnd);  // (the database entries are "abused" in this case)
0186 
0187       // relative transformations for the composition of the SubtractionVolumes
0188       Transform3D punchTransformer(RotationY(-2 * rotateAngle), Position(zPosition * tan(-2 * rotateAngle), 0, 0));
0189       Transform3D punchTransmirror(RotationY(+2 * rotateAngle), Position(zPosition * tan(+2 * rotateAngle), 0, 0));
0190 
0191       // absolute transformations for the final placement in the world
0192       Transform3D placementTransformer(RotationY(rotateAngle), RotateY(Position(0, 0, zPosition), rotateAngle));
0193       Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY(Position(0, 0, zPosition), mirrorAngle));
0194 
0195       // the main solid and the piece (only a tube, for the moment) which will be punched out
0196       ConeSegment wholeSolid(zHalf, rCenterPunch, rOuterStart, rCenterPunch, rOuterEnd, phi1, phi2);
0197       Tube punchSolid(0, rOffsetPunch, 5 * zHalf, phi1, phi2);  // a bit longer
0198 
0199       // the punched subtraction solids can be asymmetric and therefore have to be created twice:
0200       // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
0201       // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
0202       SubtractionSolid finalSolid0(wholeSolid, punchSolid, punchTransformer);
0203       SubtractionSolid finalSolid1(wholeSolid, punchSolid, punchTransmirror);
0204 
0205       // tube consists of vacuum (will later have two different daughters)
0206       Volume tubeLog0(volName + "_0", finalSolid0, material);
0207       Volume tubeLog1(volName + "_1", finalSolid1, material);
0208       tubeLog0.setVisAttributes(theDetector, xmlMask.visStr());
0209       tubeLog1.setVisAttributes(theDetector, xmlMask.visStr());
0210 
0211       // placement of the tube in the world, both at +z and -z
0212       envelope.placeVolume(tubeLog0, placementTransformer);
0213       envelope.placeVolume(tubeLog1, placementTransmirror);
0214 
0215       break;
0216     }
0217     default: { throw std::runtime_error(" Mask_o1_v01_geo.cpp : fatal failure !! ??  "); }
0218 
0219     }  // end switch
0220   }    // for all xmlSections
0221 
0222   //--------------------------------------
0223   Volume mother = theDetector.pickMotherVolume(tube);
0224   PlacedVolume pv(mother.placeVolume(envelope));
0225   pv.addPhysVolID("system", xmlMask.id());  //.addPhysVolID("side", 0 ) ;
0226 
0227   tube.setVisAttributes(theDetector, xmlMask.visStr(), envelope);
0228 
0229   tube.setPlacement(pv);
0230 
0231   return tube;
0232 }
0233 
0234 DECLARE_DEPRECATED_DETELEMENT(DD4hep_FCC_Mask_o1_v01_noRot, create_element)
0235