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