Skip to content
Snippets Groups Projects
DIRC_geo.cpp 13 KiB
Newer Older
#include "DD4hep/DetFactoryHelper.h"
#include "DD4hep/OpticalSurfaces.h"
#include "DD4hep/Printout.h"
#include "DDRec/DetectorData.h"
#include "DDRec/Surface.h"
#include <XML/Helper.h>
//////////////////////////////////
// Central Barrel DIRC
//////////////////////////////////

using namespace std;
using namespace dd4hep;

Dmitry Romanov's avatar
Dmitry Romanov committed
// Fixed Trap constructor. This function is a workaround of this bug:
// https://github.com/AIDASoft/DD4hep/issues/850
// Should be used instead of dd4hep::Trap(pName, pZ, pY, pX, pLTX) constructor
dd4hep::Trap MakeTrap( const std::string& pName, double pZ, double pY, double pX, double pLTX );

static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens)
{
Dmitry Romanov's avatar
Dmitry Romanov committed
  xml_det_t xml_det   = e;
  string    det_name = xml_det.nameStr();
  int       det_id   = xml_det.id();

  // Main detector xml element
  xml_dim_t dirc_dim   = xml_det.dimensions();
  xml_dim_t dirc_pos   = xml_det.position();
  xml_dim_t dirc_rot   = xml_det.rotation();
  double    det_rin   = dirc_dim.rmin();
  double    det_rout  = dirc_dim.rmax();
  double    SizeZ = dirc_dim.length();
Dmitry Romanov's avatar
Dmitry Romanov committed
  // DEBUG
  // double mirror_r1 = x_det.attr<double>(_Unicode(r1));

  // DIRC box:
  xml_comp_t xml_box_module = xml_det.child(_U(module));

  Material Vacuum = desc.material("Vacuum");
Dmitry Romanov's avatar
Dmitry Romanov committed
  Material air = desc.material("AirOptical");
  Material quartz = desc.material("Quartz");
  Material epotek = desc.material("Epotek");
  Material nlak33a = desc.material("Nlak33a");
  auto& bar_material = quartz;
  auto mirror_material = desc.material("Aluminum");  // mirror material
Dmitry Romanov's avatar
Dmitry Romanov committed
  Tube     det_geo(det_rin, det_rout, SizeZ / 2., 0., 360.0 * deg);
  //Volume   det_volume("DIRC", det_geo, Vacuum);
  Assembly   det_volume("DIRC");
  det_volume.setVisAttributes(desc.visAttributes(xml_det.visStr()));

  DetElement   det(det_name, det_id);
  Volume       mother_vol = desc.pickMotherVolume(det);

  Transform3D  tr(RotationZYX(0, dirc_rot.theta(), 0.0), Position(0.0, 0.0, dirc_pos.z()));
  PlacedVolume det_plvol = mother_vol.placeVolume(det_volume, tr);

  det_plvol.addPhysVolID("system", det_id);
  det.setPlacement(det_plvol);

  // Parts Dimentions

  int fLensId = 6; // focusing system
                   // 0    no lens
                   // 1    spherical lens
                   // 3    3-layer spherical lens
                   // 6    3-layer cylindrical lens
                   // 10   ideal lens (thickness = 0, ideal focusing)
  
  int fGeomType = 0;  // Full DIRC - 0, 1 only one plate
  int fRunType = 0;   // 0, 10 - simulation, 1, 5 - lookup table, 2,3,4 - reconstruction


  double fPrizm[4];
  fPrizm[0] = 360 * mm;
  fPrizm[1] = 300 * mm;
  fPrizm[3] = 50 * mm;
  fPrizm[2] = fPrizm[3] + 300 * tan(32 * deg) * mm;
  double fBarsGap = 0.15 * mm;

  std::cout << "DIRC: fPrizm[2] " << fPrizm[2] << std::endl;

  double fdTilt = 80 * deg;
  double fPrizmT[6];
  fPrizmT[0] = 390 * mm;
  fPrizmT[1] = (400 - 290 * cos(fdTilt)) * mm; //
  fPrizmT[2] = 290 * sin(fdTilt) * mm;       // hight
  fPrizmT[3] = 50 * mm;                      // face
  fPrizmT[4] = 290 * mm;
  fPrizmT[5] = 290 * cos(fdTilt)* mm;

  double fMirror[3];
  fMirror[0] = 20 * mm;
  fMirror[1] = fPrizm[0];
  fMirror[2] = 1 * mm;
  //  fPrizm[0] = 170; fPrizm[1] = 300; fPrizm[2] = 50+300*tan(45*deg); fPrizm[3] = 50;

//  double fBar[3];
//  fBar[0] = 17 * mm;
//  fBar[1] = (fPrizm[0] - (fNBar - 1) * fBarsGap) / fNBar;
//  fBar[2] = 1050 * mm; // 4200; //4200

  double fMcpTotal[3];
  double fMcpActive[3];
  fMcpTotal[0] = fMcpTotal[1] = 53 + 4;
  fMcpTotal[2] = 1*mm;
  fMcpActive[0] = fMcpActive[1] = 53;
  fMcpActive[2] = 1*mm;
Dmitry Romanov's avatar
Dmitry Romanov committed
  double fLens[4];
  fLens[0] = fLens[1] = 40 * mm;
  fLens[2] = 10 * mm;
  double fRadius = (det_rin + det_rout)/2;
Dmitry Romanov's avatar
Dmitry Romanov committed
  double fBoxWidth = fPrizm[0];

  double fFd[3];
  fFd[0] = fBoxWidth;
  fFd[1] = fPrizm[2];
  fFd[2] = 1 * mm;

  fLens[0] = fPrizm[3];
  fLens[1] = fPrizm[0];
  fLens[2] = 12 * mm;

  // Getting box XML
  const int fNBoxes = xml_box_module.repeat();
  const double box_width = xml_box_module.width();
  const double box_height = xml_box_module.height();
  const double box_length = xml_box_module.length() + 550*mm;


  // The DIRC
  Assembly dirc_module("DIRCModule");

  //Volume lDirc("lDirc", gDirc, air);
  dirc_module.setVisAttributes(desc.visAttributes(xml_box_module.visStr()));


  // FD... whatever F and D is
  xml_comp_t xml_fd = xml_box_module.child(_Unicode(fd));
  Box gFd("gFd", xml_fd.height()/2, xml_fd.width()/2, xml_fd.thickness()/2);
  Volume lFd ("lFd", gFd, desc.material(xml_fd.materialStr()));
  lFd.setVisAttributes(desc.visAttributes(xml_fd.visStr()));
  //lFd.setSensitiveDetector(sens);


  // The Bar
  xml_comp_t xml_bar = xml_box_module.child(_Unicode(bar));
  double bar_height = xml_bar.height();
  double bar_width = xml_bar.width();
  double bar_length = xml_bar.length();
  Box gBar("gBar", bar_height/2, bar_width/2, bar_length/2);
  Volume lBar("lBar", gBar, desc.material(xml_bar.materialStr()));
  lBar.setVisAttributes(desc.visAttributes(xml_bar.visStr()));

  // Glue
  xml_comp_t xml_glue = xml_box_module.child(_Unicode(glue));
  double glue_thickness = xml_glue.thickness();  // 0.05 * mm;
  Box gGlue("gGlue", bar_height/2, bar_width/2, glue_thickness/2);
  Volume lGlue("lGlue", gGlue, desc.material(xml_glue.materialStr()));
  lGlue.setVisAttributes(desc.visAttributes(xml_glue.visStr()));

  sens.setType("photoncounter");
Dmitry Romanov's avatar
Dmitry Romanov committed
  lBar.setSensitiveDetector(sens);

  int bars_repeat_z = 4;    // TODO parametrize!
  double bar_assm_length = (bar_length + glue_thickness) * bars_repeat_z;
  int fNBar = xml_bar.repeat();
  double bar_gap = xml_bar.gap();
  for (int y_index = 0; y_index < fNBar; y_index++) {
    double shift_y = y_index * (bar_width + bar_gap) - 0.5 * box_width + 0.5 * bar_width;
    for (int z_index = 0; z_index < bars_repeat_z; z_index++) {
      double z = -0.5 * bar_assm_length + 0.5 * bar_length + (bar_length + glue_thickness) * z_index;
      auto placed_bar = dirc_module.placeVolume(lBar, Position(0, shift_y, z));
      dirc_module.placeVolume(lGlue, Position(0, shift_y, z + 0.5 * (bar_length + glue_thickness)));
      placed_bar.addPhysVolID("section", z_index);
      placed_bar.addPhysVolID("bar", y_index);
    }
Dmitry Romanov's avatar
Dmitry Romanov committed


  // The Mirror
  xml_comp_t xml_mirror = xml_box_module.child(_Unicode(mirror));
  Box gMirror("gMirror", xml_mirror.height()/2, xml_mirror.width()/2, xml_mirror.thickness()/2);
  Volume lMirror("lMirror", gMirror, desc.material(xml_mirror.materialStr()));
  dirc_module.placeVolume(lMirror, Position(0, 0, -0.5 * (bar_assm_length - xml_mirror.thickness())));
  lMirror.setVisAttributes(desc.visAttributes(xml_mirror.visStr()));

  // The mirror optical surface
  OpticalSurfaceManager surfMgr = desc.surfaceManager();
  auto surf = surfMgr.opticalSurface("MirrorOpticalSurface");
  SkinSurface skin(desc, det, Form("dirc_mirror_optical_surface"), surf, lMirror);
  skin.isValid();

  // LENS
  // Lens volumes
  Volume lLens1;
  Volume lLens2;
  Volume lLens3;

  double lensMinThikness = 2.0 * mm;
  double layer12 = lensMinThikness * 2;

  // r1 = (r1==0)? 27.45: r1;
  // r2 = (r2==0)? 20.02: r2;

  double r1 = 33 * mm;
  double r2 = 24 * mm;
  double shight = 25 * mm;

  Position zTrans1(0, 0, -r1 - fLens[2] / 2. + r1 - sqrt(r1 * r1 - shight / 2. * shight / 2.) + lensMinThikness);
  Position zTrans2(0, 0, -r2 - fLens[2] / 2. + r2 - sqrt(r2 * r2 - shight / 2. * shight / 2.) + layer12);

  Box gfbox("fbox", 0.5 * fLens[0], 0.5 * fLens[1], 0.5 * fLens[2]);
  Box gcbox("cbox", 0.5 * fLens[0], 0.5 * fLens[1] + 1*mm, 0.5 * fLens[2]);

//  Volume gfbox_volume("gfbox_volume", gfbox, bar_material);
//  lDirc.placeVolume(gfbox_volume, Position(0, 0, 0));
//
//  Volume gcbox_volume("gcbox_volume", gcbox, bar_material);
//  lDirc.placeVolume(gcbox_volume, Position(0, 0, 50));


  Position tTrans1(0.5 * (fLens[0] + shight), 0, -fLens[2] + layer12);
  Position tTrans0(-0.5 * (fLens[0] + shight), 0, -fLens[2] + layer12);
  SubtractionSolid tubox("tubox", gfbox, gcbox, tTrans1);
  SubtractionSolid gubox("gubox", tubox, gcbox, tTrans0);

//  Volume tubox_volume("tubox_volume", tubox, bar_material);
//  lDirc.placeVolume(tubox_volume, Position(0, 0, 100));
//
//  Volume gubox_volume("gubox_volume", gubox, bar_material);
//  lDirc.placeVolume(gubox_volume, Position(0, 0, 150));

  Tube gcylinder1("Cylinder1", 0, r1, 0.5 * fLens[1], 0 * deg, 360 * deg);
  Tube gcylinder2("Cylinder2", 0, r2, 0.5 * fLens[1] - 0.5*mm, 0 * deg, 360 * deg);
  Tube gcylinder1c("Cylinder1c", 0, r1, 0.5 * fLens[1] + 0.5*mm, 0 * deg, 360 * deg);
  Tube gcylinder2c("Cylinder2c", 0, r2, 0.5 * fLens[1] + 0.5*mm, 0 * deg, 360 * deg);
  RotationX xRot(-M_PI / 2.);

  IntersectionSolid gLens1("Lens1", gubox, gcylinder1, Transform3D(xRot, zTrans1));
  SubtractionSolid gLenst("temp", gubox, gcylinder1c, Transform3D(xRot, zTrans1));

//  Volume gLens1_volume("gLens1_volume", gLens1, bar_material);
//  lDirc.placeVolume(gLens1_volume, Position(0, 0, 200));
//
//  Volume gLenst_volume("gLenst_volume", gLenst, bar_material);
//  lDirc.placeVolume(gLenst_volume, Position(0, 0, 250));

  IntersectionSolid gLens2("Lens2", gLenst, gcylinder2, Transform3D(xRot, zTrans2));
  SubtractionSolid gLens3("Lens3", gLenst, gcylinder2c, Transform3D(xRot, zTrans2));

  lLens1 = Volume("lLens1", gLens1, bar_material);
  lLens2 = Volume("lLens2", gLens2, nlak33a);
  lLens3 = Volume("lLens3", gLens3, bar_material);

  lLens1.setVisAttributes(desc.visAttributes("DIRCLens1"));
  lLens2.setVisAttributes(desc.visAttributes("DIRCLens2"));
  lLens3.setVisAttributes(desc.visAttributes("DIRCLens3"));


  double shifth = 0.5 * (bar_assm_length + fLens[2]);
  // fmt::print("LENS HERE shifth={}\n", shifth);

  lLens1.setVisAttributes(desc.visAttributes("AnlTeal"));
  dirc_module.placeVolume(lLens1, Position(0, 0, shifth));
  dirc_module.placeVolume(lLens2, Position(0, 0, shifth));
  dirc_module.placeVolume(lLens3, Position(0, 0, shifth));
Dmitry Romanov's avatar
Dmitry Romanov committed
  // The Prizm
  Trap gPrizm = MakeTrap("gPrizm", fPrizm[0], fPrizm[1], fPrizm[2], fPrizm[3]);
  Volume lPrizm("lPrizm", gPrizm, bar_material);
  lPrizm.setVisAttributes(desc.visAttributes("DIRCPrism"));

  //G4RotationMatrix *fdRot = new G4RotationMatrix();
  //G4RotationMatrix *fdrot = new G4RotationMatrix();
  double evshiftz = 0.5 * bar_assm_length + fPrizm[1] + fMcpActive[2] / 2. + fLens[2];
  double evshiftx = -3*mm;

  double prism_shift_x = (fPrizm[2] + fPrizm[3]) / 4. - 0.5 * fPrizm[3] + 1.5*mm;
  double prism_shift_z = 0.5 * (bar_assm_length + fPrizm[1]) + fLens[2];

  Position  fPrismShift(prism_shift_x, 0, prism_shift_z);
  dirc_module.placeVolume(lPrizm, Transform3D(xRot, fPrismShift));
  dirc_module.placeVolume(lFd, Position(0.5 * fFd[1] - 0.5 * fPrizm[3] - evshiftx, 0, evshiftz));

  double dphi = 2 * M_PI / (double)fNBoxes;
  for (int i = 0; i < fNBoxes; i++) {
    double phi = dphi * i;
    double dx = -fRadius * cos(phi);
    double dy = -fRadius * sin(phi);

    //G4RotationMatrix *tRot = new G4RotationMatrix();

    Transform3D  tr(RotationZ(phi+M_PI), Position(dx, dy, 0));
    PlacedVolume box_placement = det_volume.placeVolume(dirc_module, tr);
    box_placement.addPhysVolID("module", i);


    // fmt::print("placing dircbox # {} -tphi={:.0f} dx={:.0f}, dy={:.0f}\n", i, phi/deg, dx/cm, dy/cm);

    //new G4PVPlacement(tRot, G4ThreeVector(dx, dy, 0), lDirc, "wDirc", lExpHall, false, i);
  }

    
  //////////////////
  // DIRC Bars
  //////////////////

  // double bar_radius   = 83.65 * cm;
  // double bar_length   = SizeZ;
  // double bar_width    = 42. * cm;
  // double bar_thicknes = 1.7 * cm;
  // int    bar_count    = 2 * M_PI * bar_radius / bar_width;
  // double bar_dphi     = 2 * 3.1415926 / bar_count;
  // Material bar_material = desc.material("Quartz");

  // Box    bar_geo(bar_thicknes / 2., bar_width / 2., bar_length / 2.);
  // Volume bar_volume("cb_DIRC_bars_Logix", bar_geo, bar_material);
  // bar_volume.setVisAttributes(desc.visAttributes(xml_det.visStr()));
  // sens.setType("photoncounter");
  // bar_volume.setSensitiveDetector(sens);

  // for (int ia = 0; ia < bar_count; ia++) {
  //   double phi = (ia * (bar_dphi));
  //   double x   = -bar_radius * cos(phi);
  //   double y   = -bar_radius * sin(phi);

  //   Transform3D  tr(RotationZ(bar_dphi * ia), Position(x, y, 0));
  //   PlacedVolume barPV = det_volume.placeVolume(bar_volume, tr);
  //   barPV.addPhysVolID("module", ia);
  // }
Dmitry Romanov's avatar
Dmitry Romanov committed
DECLARE_DETELEMENT(cb_DIRC, createDetector)

dd4hep::Trap MakeTrap( const std::string& pName, double pZ, double pY, double pX, double pLTX )
{
    // Fixed Trap constructor. This function is a workaround of this bug:
    // https://github.com/AIDASoft/DD4hep/issues/850
    // Should be used instead of dd4hep::Trap(pName, pZ, pY, pX, pLTX) constructor

    double fDz  = 0.5*pZ;
    double fTthetaCphi = 0;
    double fTthetaSphi = 0;
    double fDy1 = 0.5*pY;
    double fDx1 = 0.5*pX;
    double fDx2 = 0.5*pLTX;
    double fTalpha1 = 0.5*(pLTX - pX)/pY;
    double fDy2 = fDy1;
    double fDx3 = fDx1;
    double fDx4 = fDx2;
    double fTalpha2 = fTalpha1;

    return Trap(pName, fDz,  fTthetaCphi,  fTthetaSphi,
                fDy1,  fDx1,  fDx2,  fTalpha1,
                fDy2,  fDx3,  fDx4,  fTalpha2);
}