Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 //
0014 // Specialized generic detector constructor
0015 // 
0016 //==========================================================================
0017 #include "DD4hep/DetFactoryHelper.h"
0018 #include "XML/Layering.h"
0019 
0020 using namespace std;
0021 using namespace dd4hep;
0022 using namespace dd4hep::detail;
0023 
0024 static void placeStaves(DetElement& parent, DetElement& stave, double rmin, int numsides, double total_thickness,
0025                         Volume envelopeVolume, double innerAngle, Volume sectVolume) {
0026   double innerRotation = innerAngle;
0027   double offsetRotation = -innerRotation / 2;
0028   double sectCenterRadius = rmin + total_thickness / 2;
0029   double rotX = M_PI / 2;
0030   double rotY = -offsetRotation;
0031   double posX = -sectCenterRadius * std::sin(rotY);
0032   double posY = sectCenterRadius * std::cos(rotY);
0033 
0034   for (int module = 1; module <= numsides; ++module) {
0035     DetElement det = module > 1 ? stave.clone(_toString(module,"stave%d")) : stave;
0036     Transform3D trafo(RotationZYX(0, rotY, rotX), Translation3D(-posX, -posY, 0));
0037     PlacedVolume pv = envelopeVolume.placeVolume(sectVolume,trafo);
0038     // Not a valid volID: pv.addPhysVolID("stave", 0);
0039     pv.addPhysVolID("module", module);
0040     det.setPlacement(pv);
0041     parent.add(det);
0042     rotY -= innerRotation;
0043     posX = -sectCenterRadius * std::sin(rotY);
0044     posY = sectCenterRadius * std::cos(rotY);
0045   }
0046 }
0047 
0048 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) {
0049   xml_det_t x_det = e;
0050   Layering layering(x_det);
0051   xml_comp_t staves = x_det.staves();
0052   xml_dim_t dim = x_det.dimensions();
0053   string det_name = x_det.nameStr();
0054   Material air = description.air();
0055   double totalThickness = layering.totalThickness();
0056   double gap = xml_dim_t(x_det).gap();
0057   int numSides = dim.numsides();
0058   double detZ = dim.z();
0059   double rmin = dim.rmin();
0060   DetElement sdet(det_name, x_det.id());
0061   DetElement stave("stave1", x_det.id());
0062   Volume motherVol = description.pickMotherVolume(sdet);
0063 
0064 #if 0
0065   int totalRepeat = 0;
0066   int totalSlices = 0;
0067   for (xml_coll_t c(x_det, _U(layer)); c; ++c) {
0068     xml_comp_t x_layer = c;
0069     int repeat = x_layer.repeat();
0070     totalRepeat += repeat;
0071     totalSlices += x_layer.numChildren(_U(slice));
0072   }
0073 #endif
0074   PolyhedraRegular polyhedra(numSides, rmin, rmin + totalThickness, detZ);
0075   Volume envelopeVol(det_name, polyhedra, air);
0076 
0077   // Add the subdetector envelope to the structure.
0078   double innerAngle = 2 * M_PI / numSides;
0079   double halfInnerAngle = innerAngle / 2;
0080   double tan_inner = std::tan(halfInnerAngle) * 2;
0081   double innerFaceLen = rmin * tan_inner;
0082   double outerFaceLen = (rmin + totalThickness) * tan_inner;
0083   double staveThickness = totalThickness;
0084 
0085   Trapezoid staveTrdOuter(innerFaceLen / 2, outerFaceLen / 2, detZ / 2, detZ / 2, staveThickness / 2);
0086   Volume staveOuterVol("stave_outer", staveTrdOuter, air);
0087 
0088   Trapezoid staveTrdInner(innerFaceLen / 2 - gap, outerFaceLen / 2 - gap, detZ / 2, detZ / 2, staveThickness / 2);
0089   Volume staveInnerVol("stave_inner", staveTrdInner, air);
0090 
0091   double layerOuterAngle = (M_PI - innerAngle) / 2;
0092   double layerInnerAngle = (M_PI / 2 - layerOuterAngle);
0093   double layer_pos_z = -(staveThickness / 2);
0094   double layer_dim_x = innerFaceLen / 2 - gap * 2;
0095   int layer_num = 1;
0096 
0097   //#### LayeringExtensionImpl* layeringExtension = new LayeringExtensionImpl();
0098   //#### Position layerNormal(0,0,1);
0099 
0100   for (xml_coll_t xc(x_det, _U(layer)); xc; ++xc) {
0101     xml_comp_t x_layer = xc;
0102     int repeat = x_layer.repeat();            // Get number of times to repeat this layer.
0103     const Layer* lay = layering.layer(layer_num - 1); // Get the layer from the layering engine.
0104     // Loop over repeats for this layer.
0105     for (int j = 0; j < repeat; j++) {
0106       string layer_name = _toString(layer_num, "layer%d");
0107       double layer_thickness = lay->thickness();
0108       DetElement layer(stave, layer_name, layer_num);
0109       //### layeringExtension->setLayer(layer_num, layer, layerNormal);
0110 
0111       // Layer position in Z within the stave.
0112       layer_pos_z += layer_thickness / 2;
0113       // Layer box & volume
0114       Volume layer_vol(layer_name, Box(layer_dim_x, detZ / 2, layer_thickness / 2), air);
0115 
0116       // Create the slices (sublayers) within the layer.
0117       double slice_pos_z = -(layer_thickness / 2);
0118       int slice_number = 1;
0119       for (xml_coll_t xk(x_layer, _U(slice)); xk; ++xk) {
0120         xml_comp_t x_slice = xk;
0121         string slice_name = _toString(slice_number, "slice%d");
0122         double slice_thickness = x_slice.thickness();
0123         Material slice_material = description.material(x_slice.materialStr());
0124         DetElement slice(layer, slice_name, slice_number);
0125 
0126         slice_pos_z += slice_thickness / 2;
0127         // Slice volume & box
0128         Volume slice_vol(slice_name, Box(layer_dim_x, detZ / 2, slice_thickness / 2), slice_material);
0129 
0130         if (x_slice.isSensitive()) {
0131           sens.setType("calorimeter");
0132           slice_vol.setSensitiveDetector(sens);
0133         }
0134         // Set region, limitset, and vis.
0135         slice_vol.setAttributes(description, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0136         // slice PlacedVolume
0137         PlacedVolume slice_phv = layer_vol.placeVolume(slice_vol, Position(0, 0, slice_pos_z));
0138         slice_phv.addPhysVolID("slice", slice_number);
0139 
0140         slice.setPlacement(slice_phv);
0141         // Increment Z position for next slice.
0142         slice_pos_z += slice_thickness / 2;
0143         // Increment slice number.
0144         ++slice_number;
0145       }
0146       // Set region, limitset, and vis.
0147       layer_vol.setAttributes(description, x_layer.regionStr(), x_layer.limitsStr(), x_layer.visStr());
0148 
0149       // Layer physical volume.
0150       PlacedVolume layer_phv = staveInnerVol.placeVolume(layer_vol, Position(0, 0, layer_pos_z));
0151       layer_phv.addPhysVolID("layer", layer_num);
0152       layer.setPlacement(layer_phv);
0153 
0154       // Increment the layer X dimension.
0155       layer_dim_x += layer_thickness * std::tan(layerInnerAngle);    // * 2;
0156       // Increment the layer Z position.
0157       layer_pos_z += layer_thickness / 2;
0158       // Increment the layer number.
0159       ++layer_num;
0160     }
0161   }
0162 
0163   // Add stave inner physical volume to outer stave volume.
0164   staveOuterVol.placeVolume(staveInnerVol);
0165   if ( staves )  {
0166     // Set the vis attributes of the outer stave section.
0167     stave.setVisAttributes(description, staves.visStr(), staveInnerVol);
0168     stave.setVisAttributes(description, staves.visStr(), staveOuterVol);
0169   }
0170   // Place the staves.
0171   placeStaves(sdet, stave, rmin, numSides, totalThickness, envelopeVol, innerAngle, staveOuterVol);
0172   // Set envelope volume attributes.
0173   envelopeVol.setAttributes(description, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
0174 
0175   double z_offset = dim.hasAttr(_U(z_offset)) ? dim.z_offset() : 0.0;
0176   Transform3D transform(RotationZ(M_PI / numSides), Translation3D(0, 0, z_offset));
0177   PlacedVolume env_phv = motherVol.placeVolume(envelopeVol, transform);
0178   env_phv.addPhysVolID("system", sdet.id());
0179   env_phv.addPhysVolID("barrel", 0);
0180   sdet.setPlacement(env_phv);
0181 
0182   //#### sdet.addExtension<SubdetectorExtension>(new SubdetectorExtensionImpl(sdet));
0183   //#### sdet.addExtension<LayeringExtension>(layeringExtension);
0184   return sdet;
0185 }
0186 
0187 DECLARE_DETELEMENT(DD4hep_PolyhedraBarrelCalorimeter2, create_detector)