Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-13 08:27:20

0001 // SPDX-License-Identifier: LGPL-3.0-or-later
0002 // Copyright (C) 2022 Shima Shimizu, Jihee Kim
0003 
0004 #include "DD4hep/DetFactoryHelper.h"
0005 #include "DD4hep/OpticalSurfaces.h"
0006 #include "DD4hep/Printout.h"
0007 #include "DDRec/DetectorData.h"
0008 #include "DDRec/Surface.h"
0009 #include <XML/Helper.h>
0010 #include <XML/Utilities.h>
0011 #include <algorithm>
0012 #include <iostream>
0013 #include <math.h>
0014 #include <tuple>
0015 //////////////////////////////////////////////////
0016 // Far Forward Ion Zero Degree Calorimeter - Ecal
0017 // Reference from ATHENA ScFiCalorimeter_geo.cpp
0018 //////////////////////////////////////////////////
0019 
0020 using namespace std;
0021 using namespace dd4hep;
0022 
0023 // main
0024 static Ref_t create_detector(Detector& desc, xml_h handle, SensitiveDetector sens) {
0025   xml::DetElement detElem = handle;
0026   std::string detName     = detElem.nameStr();
0027   int detID               = detElem.id();
0028   DetElement det(detName, detID);
0029   sens.setType("calorimeter");
0030   auto dim      = detElem.dimensions();
0031   auto xwidth   = dim.x();
0032   auto ywidth   = dim.y();
0033   auto length   = dim.z();
0034   xml_dim_t pos = detElem.position();
0035   xml_dim_t rot = detElem.rotation();
0036 
0037   // apply any detector type flags set in XML
0038   dd4hep::xml::setDetectorTypeFlag(detElem, det);
0039 
0040   // envelope
0041   Box envShape(xwidth * 0.5, ywidth * 0.5, length * 0.5);
0042   Volume env(detName + "_envelope", envShape, desc.material("Air"));
0043   env.setVisAttributes(desc.visAttributes(detElem.visStr()));
0044 
0045   // build frame
0046   xml_comp_t fr   = detElem.child(_Unicode(support));
0047   auto fx         = xwidth;
0048   auto fy         = ywidth;
0049   auto fz         = fr.attr<double>(_Unicode(sizez));
0050   auto fthickness = fr.attr<double>(_Unicode(thickness));
0051 
0052   Box frShape(fx / 2., fy / 2., fz / 2.);
0053   auto frMat = desc.material(fr.attr<std::string>(_Unicode(material)));
0054   Volume frVol("frame_vol", frShape, frMat);
0055   frVol.setVisAttributes(desc.visAttributes(fr.visStr()));
0056 
0057   xml_comp_t mod_x = detElem.child(_Unicode(module));
0058   auto nx          = mod_x.attr<int>(_Unicode(nx));
0059   auto ny          = mod_x.attr<int>(_Unicode(ny));
0060 
0061   // crystal tower
0062   xml_comp_t twr = mod_x.child(_Unicode(tower));
0063   double tsx     = twr.attr<double>(_Unicode(cellx));
0064   double tsy     = twr.attr<double>(_Unicode(celly));
0065   double tsz     = twr.thickness();
0066   Material t_mat = desc.material(twr.materialStr());
0067   string t_name  = twr.nameStr();
0068 
0069   Box t_Shape(tsx / 2., tsy / 2., tsz / 2.);
0070   Volume t_Vol("tower_vol", t_Shape, t_mat);
0071   t_Vol.setVisAttributes(desc.visAttributes(twr.visStr()));
0072   if (twr.isSensitive())
0073     t_Vol.setSensitiveDetector(sens);
0074 
0075   // readout socket
0076   xml_comp_t sct = mod_x.child(_Unicode(socket));
0077   double ssx     = sct.attr<double>(_Unicode(cellx));
0078   double ssy     = sct.attr<double>(_Unicode(celly));
0079   double ssz     = sct.thickness();
0080   Material s_mat = desc.material(sct.materialStr());
0081   string s_name  = sct.nameStr();
0082 
0083   Box s_Shape(ssx / 2., ssy / 2., ssz / 2.);
0084   Volume s_Vol("socket_vol", s_Shape, s_mat);
0085   s_Vol.setVisAttributes(desc.visAttributes(sct.visStr()));
0086 
0087   PlacedVolume pv;
0088   double x_pos_0          = -(nx * tsx + (nx - 1) * fthickness) / 2.;
0089   double y_pos_0          = -(ny * tsy + (ny - 1) * fthickness) / 2.;
0090   double twr_z_pos_in_fr  = -fz / 2. + tsz / 2.;
0091   double sct_z_pos_in_env = -length / 2. + tsz + ssz / 2.;
0092   int mod_i               = 0;
0093   for (int ix = 0; ix < nx; ix++) {
0094     double x_pos = x_pos_0 + ix * (tsx + fthickness) + tsx / 2.;
0095 
0096     for (int iy = 0; iy < ny; iy++) {
0097       double y_pos = y_pos_0 + iy * (tsy + fthickness) + tsy / 2.;
0098 
0099       mod_i++;
0100 
0101       Position twr_pos(x_pos, y_pos, twr_z_pos_in_fr);
0102       pv = frVol.placeVolume(t_Vol, twr_pos);
0103       pv.addPhysVolID(t_name, mod_i);
0104 
0105       Position sct_pos(x_pos, y_pos, sct_z_pos_in_env);
0106       pv = env.placeVolume(s_Vol, sct_pos);
0107     }
0108   }
0109 
0110   double f_zpos = -length / 2. + fz / 2.;
0111   Position fr_pos(0, 0, f_zpos);
0112   pv = env.placeVolume(frVol, fr_pos);
0113 
0114   // detector position and rotation
0115   Volume motherVol = desc.pickMotherVolume(det);
0116   Transform3D tr(RotationZYX(rot.z(), rot.y(), rot.x()), Position(pos.x(), pos.y(), pos.z()));
0117   PlacedVolume envPV = motherVol.placeVolume(env, tr);
0118   envPV.addPhysVolID("system", detID);
0119   det.setPlacement(envPV);
0120   return det;
0121 }
0122 
0123 DECLARE_DETELEMENT(ZDC_Crystal, create_detector)