From 111c2cc6e31868af77e7929363eac16b1ce6e67e Mon Sep 17 00:00:00 2001
From: Chengdong Fu <fucd@ihep.ac.cn>
Date: Mon, 26 Apr 2021 14:50:20 +0800
Subject: [PATCH] add first version of SiTrackerSkewRing

---
 Detector/DetCRD/CMakeLists.txt                |   3 +-
 .../src/Tracker/SiTrackerSkewRing_v01_geo.cpp | 227 ++++++++++++++++++
 2 files changed, 229 insertions(+), 1 deletion(-)
 create mode 100644 Detector/DetCRD/src/Tracker/SiTrackerSkewRing_v01_geo.cpp

diff --git a/Detector/DetCRD/CMakeLists.txt b/Detector/DetCRD/CMakeLists.txt
index 55e33178..ff4bd817 100644
--- a/Detector/DetCRD/CMakeLists.txt
+++ b/Detector/DetCRD/CMakeLists.txt
@@ -17,7 +17,8 @@ find_package(ROOT COMPONENTS MathCore GenVector Geom REQUIRED)
 
 gaudi_add_module(DetCRD
                  SOURCES src/Calorimeter/CRDEcal.cpp
-                         src/Other/CRDBeamPipe_v01_geo.cpp
+		  	 src/Tracker/SiTrackerSkewRing_v01_geo.cpp
+                       	 src/Other/CRDBeamPipe_v01_geo.cpp
 		 LINK ${DD4hep_COMPONENT_LIBRARIES}
 )
 
diff --git a/Detector/DetCRD/src/Tracker/SiTrackerSkewRing_v01_geo.cpp b/Detector/DetCRD/src/Tracker/SiTrackerSkewRing_v01_geo.cpp
new file mode 100644
index 00000000..4f768ac8
--- /dev/null
+++ b/Detector/DetCRD/src/Tracker/SiTrackerSkewRing_v01_geo.cpp
@@ -0,0 +1,227 @@
+// $Id: $
+//==========================================================================
+//  Detector description implementation for CEPC
+//--------------------------------------------------------------------------
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+// 
+// Author     : FU Chengdong
+//==========================================================================
+// Specialized generic detector constructor for skew planar
+//              _______________
+//              \      |      /
+//               \     |     /
+//                \    |    /
+//                 \   |   /
+//                  \__|__/
+//                  center                       
+//
+// z       :      z position at maximum radius of center
+// dz      :      z gap between odd and even modules
+// gap     :      rphi gap between neighbouring modules
+// rmin    :      minimum radius at center
+// rmax    :      maximum radius at center
+// phi0    :      start phi for #0 module
+// skew    :      skew angle
+// nmodules:      module number at phi direction
+// is_pixel:      pixel tag for reconstruction
+//==========================================================================
+#include <DD4hep/Detector.h>
+#include "DD4hep/DetFactoryHelper.h"
+#include "XML/Utilities.h"
+#include "DDRec/Surface.h"
+#include "DDRec/DetectorData.h"
+#include "Math/AxisAngle.h"
+
+#include <map>
+
+using namespace std;
+
+using dd4hep::DetElement;
+using dd4hep::Detector;
+using dd4hep::Material;
+using dd4hep::PlacedVolume;
+using dd4hep::SensitiveDetector;
+using dd4hep::Volume;
+using dd4hep::Trap;
+using dd4hep::_toString;
+using dd4hep::Position;
+using dd4hep::Transform3D;
+using dd4hep::Rotation3D;
+using dd4hep::RotationZYX;
+
+static dd4hep::Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens){
+  typedef vector<PlacedVolume> Placements;
+  xml_det_t   x_det     = e;
+  Material    air       = description.air();
+  int         det_id    = x_det.id();
+  string      name      = x_det.nameStr();
+  bool        reflect   = x_det.reflect(false);
+  DetElement  tracker(name, det_id);
+
+  Volume envelope = dd4hep::xml::createPlacedEnvelope(description, e, tracker);
+  dd4hep::xml::setDetectorTypeFlag(e, tracker) ;
+  if(description.buildType()==dd4hep::BUILD_ENVELOPE) return tracker;
+  envelope.setVisAttributes(description.visAttributes("SeeThrough"));
+
+  sens.setType("tracker");
+  std::cout << " ** building SiTrackerEndcapRing_v01 ..." << std::endl ;
+
+  dd4hep::rec::ZDiskPetalsData*  zDiskPetalsData = new dd4hep::rec::ZDiskPetalsData;
+
+  PlacedVolume pv;
+
+  for(xml_coll_t li(x_det,_U(layer)); li; ++li)  {
+    xml_comp_t  x_layer(li);
+    int layer_id    = x_layer.id();
+
+    double zstart   = x_layer.z();
+    double dz       = x_layer.dz();
+    double rmin     = x_layer.inner_r();
+    double rmax     = x_layer.outer_r();
+    double phi0     = x_layer.phi0(0);
+    double skew     = x_layer.skew(0);
+    double gap      = x_layer.gap();
+    bool   is_pixel = x_layer.attr<bool>(_Unicode(is_pixel)); 
+    int    nmodules = x_layer.nmodules();
+
+    double dphi       = 2*M_PI/nmodules;
+    double phi        = phi0;
+    double x1         = rmin*tan(0.5*dphi) - 0.5*gap;
+    double x2         = rmax*tan(0.5*dphi) - 0.5*gap;
+    double half_width = (rmax-rmin)/2/cos(skew);
+    double rpos       = (rmax+rmin)/2;
+    double zpos       = zstart + half_width*sin(skew);
+
+    double layer_thickness        = 0.;
+    double sensitive_thickness[2] = {0.,0.};
+    double support_thickness      = 0.;
+    int    nsensor                = 0;
+    for(xml_coll_t ci(x_layer,_U(component)); ci; ++ci){
+      xml_comp_t c     = ci;
+      double thickness = c.thickness();
+      layer_thickness  += thickness;
+      if(c.isSensitive()){
+	sensitive_thickness[nsensor] = thickness;
+	nsensor++;
+      }
+      else      support_thickness   += thickness;
+    }
+    double half_thickness = layer_thickness/2;
+    double zshift_support = dz + 0.5*(sensitive_thickness[0] + sensitive_thickness[1] + support_thickness);
+
+    //std::cout << " ****Layer: " << layer_id << " nmodules = " << nmodules << " z = " << zpos << " zshift = " << zshift_support
+    //	      << " rmin = " << rmin << " rmax = " << rmax << " x1 = " << x1 << " x2 = " << x2 << " thickness = " << layer_thickness << std::endl;    
+    
+    Trap   moduleSolid(half_thickness, 0, 0, half_width, x1, x2, 0, half_width, x1, x2, 0);
+    Volume moduleVol(_toString(layer_id,"layer%d"), moduleSolid, air);
+    moduleVol.setVisAttributes(description.visAttributes(x_layer.visStr()));
+    
+    Placements sensitives;
+    int    sensor_id = 1;
+    int    c_id      = 0;
+    double c_pos     = -half_thickness;
+    for(xml_coll_t ci(x_layer,_U(component)); ci; ++ci, c_id++){
+      xml_comp_t c       = ci;
+      double     c_thickness = c.thickness();
+      Material   c_mat   = description.material(c.materialStr());
+      string     c_name  = _toString(c_id,"component%d");
+      Trap       c_solid(c_thickness/2, 0, 0, half_width, x1, x2, 0, half_width, x1, x2, 0);
+      Volume     c_vol(c_name, c_solid, c_mat);
+      c_vol.setVisAttributes(description.visAttributes(c.visStr()));
+      pv = moduleVol.placeVolume(c_vol,Position(0,0,c_pos+c_thickness/2));
+      if(c.isSensitive()){
+        tracker.check(sensor_id > 2," fromCompact: "+c_name+" Max of 2 modules allowed!");
+        pv.addPhysVolID("sensor", sensor_id);
+        c_vol.setSensitiveDetector(sens);
+	sensitives.push_back(pv);
+        ++sensor_id;
+      }
+      c_pos += c_thickness;
+    }
+    
+    for(int module_id=0; module_id<nmodules; module_id++){
+      
+      string m_base = _toString(layer_id,"layer%d") + _toString(module_id,"_module%d");
+      
+      double x = rpos*std::cos(phi);
+      double y = rpos*std::sin(phi);
+      double zshift_layer   = zshift_support - 0.5*sensitive_thickness[0] + 0.5*sensitive_thickness[1];
+      //std::cout << "****** module_id = " << module_id << " phi = " << phi << " x = " << x << " y = " << y
+      //	<< " zsup = " << zpos+zshift_support << " zsens = " << zpos+zshift_support-0.5*sensitive_thickness[0]-0.5*support_thickness << std::endl;
+      DetElement module(tracker, m_base+"_pos", det_id);
+      Rotation3D rot = Rotation3D(ROOT::Math::AxisAngle(dd4hep::PositionPolar(1,M_PI/2,-M_PI/2+phi),-skew))*Rotation3D(RotationZYX(-M_PI/2+phi,0,0));
+      pv = envelope.placeVolume(moduleVol, Transform3D(rot, Position(x,y,zpos+zshift_layer)));
+      pv.addPhysVolID("side",1).addPhysVolID("layer", layer_id).addPhysVolID("module",module_id);
+      module.setPlacement(pv);
+      for(size_t ic=0; ic<sensitives.size(); ++ic)  {
+	PlacedVolume sens_pv = sensitives[ic];
+	DetElement comp_elt(module, sens_pv.volume().name(), module_id);
+	comp_elt.setPlacement(sens_pv);
+      }
+
+      if(reflect){
+	Rotation3D rotRef = Rotation3D(ROOT::Math::AxisAngle(dd4hep::PositionPolar(1,M_PI/2,-M_PI/2+phi),skew))*Rotation3D(RotationZYX(M_PI/2-phi,M_PI,0));
+	pv = envelope.placeVolume(moduleVol, Transform3D(rotRef, Position(x,y,-zpos-zshift_layer)));
+	pv.addPhysVolID("side",-1).addPhysVolID("layer",layer_id).addPhysVolID("module",module_id);
+	DetElement r_module(tracker, m_base+"_neg", det_id);
+	r_module.setPlacement(pv);
+	for(size_t ic=0; ic<sensitives.size(); ++ic)  {
+	  PlacedVolume sens_pv = sensitives[ic];
+	  DetElement comp_elt(r_module, sens_pv.volume().name(), module_id);
+	  comp_elt.setPlacement(sens_pv);
+	}
+      }
+      zshift_support = -zshift_support;
+      phi   +=  dphi;
+    }
+
+    dd4hep::rec::ZDiskPetalsData::LayerLayout thisLayer;
+    thisLayer.typeFlags[ dd4hep::rec::ZDiskPetalsData::SensorType::DoubleSided ] = bool(sensor_id>2);
+    thisLayer.typeFlags[ dd4hep::rec::ZDiskPetalsData::SensorType::Pixel ]       = is_pixel;
+    thisLayer.petalHalfAngle      = dphi/2;
+    thisLayer.alphaPetal          = skew;
+    thisLayer.zPosition           = zpos;
+    thisLayer.petalNumber         = nmodules;
+    thisLayer.sensorsPerPetal     = sensor_id-1;
+    thisLayer.phi0                = phi0;
+    thisLayer.zOffsetSupport      = fabs(zshift_support);
+    thisLayer.distanceSupport     = rmin;
+    thisLayer.thicknessSupport    = support_thickness;
+    thisLayer.widthInnerSupport   = 2.*x1;
+    thisLayer.widthOuterSupport   = 2.*x2;
+    thisLayer.lengthSupport       = 2.*half_width;
+    thisLayer.zOffsetSensitive    = fabs(zshift_support) - 0.5*support_thickness - 0.5*sensitive_thickness[0];
+    thisLayer.distanceSensitive   = rmin;
+    thisLayer.thicknessSensitive  = sensitive_thickness[0];
+    thisLayer.widthInnerSensitive = 2.*x1;
+    thisLayer.widthOuterSensitive = 2.*x2;
+    thisLayer.lengthSensitive     = 2.*half_width;
+
+    zDiskPetalsData->layers.push_back(thisLayer);
+  }
+
+  dd4hep::xml::Component recPar = x_det.child(_Unicode(reconstruction));
+  const double strip_width  = recPar.attr< double >(_Unicode(strip_width));
+  const double strip_length = recPar.attr< double >(_Unicode(strip_length));
+  const double strip_pitch  = recPar.attr< double >(_Unicode(strip_pitch));
+  const double strip_angle  = recPar.attr< double >(_Unicode(strip_angle));
+
+  zDiskPetalsData->widthStrip  = strip_width;
+  zDiskPetalsData->lengthStrip = strip_length;
+  zDiskPetalsData->pitchStrip  = strip_pitch;
+  zDiskPetalsData->angleStrip  = strip_angle;
+
+  std::cout << (*zDiskPetalsData) << std::endl;
+  tracker.addExtension<dd4hep::rec::ZDiskPetalsData>( zDiskPetalsData );
+  
+  if ( x_det.hasAttr(_U(combineHits)) ) {
+    tracker.setCombineHits(x_det.attr<bool>(_U(combineHits)),sens);
+  }
+  
+  return tracker;
+}
+
+DECLARE_DETELEMENT(SiTrackerSkewRing_v01, create_detector)
-- 
GitLab