Skip to content
Snippets Groups Projects
Commit fc1c0465 authored by Chao Peng's avatar Chao Peng
Browse files

Fix DAWN view for barrel calorimeter support

parent b75d2576
No related branches found
Tags canyonlands-v1.1
No related merge requests found
<lccdd>
<display>
<vis name="EcalBarrelEnvelope_vis" alpha="0.9" r="0.99" g="0.5" b="0" showDaughters="true" visible="false" />
<vis name="EcalBarrelStave_vis" alpha="0.9" r="0.99" g="0.5" b="0" showDaughters="true" visible="false" />
<vis name="EcalBarrelEnvelope_vis" alpha="0.9" r="0.99" g="0.5" b="0" showDaughters="true" visible="false" />
<vis name="EcalBarrelStave_vis" alpha="0.9" r="0.99" g="0.5" b="0" showDaughters="true" visible="false" />
<vis name="EcalBarrelFiberLayer_vis" alpha="0.9" r="0.1" g="0.5" b="0.5" showDaughters="false" visible="true" />
</display>
<define>
<comment>
......@@ -85,7 +86,6 @@
<dimensions numsides="EcalBarrel_ModRepeat"
rmin="EcalBarrel_rmin"
z="EcalBarrel_length"/>
<staves vis="EcalBarrelStave_vis"/>
<layer repeat="EcalBarrelImagingLayers_num" vis="AnlBlue"
space_between="EcalBarrel_ScFiLayerThickness + EcalBarrel_SpaceBetween"
space_before="0.*cm">
......@@ -115,18 +115,16 @@
rmin="EcalBarrel_rmin"
z="EcalBarrel_length"/>
<staves vis="EcalBarrelStave_vis">
<support inside="true" material="Steel235" vis="AnlOrange"
thickness="EcalBarrel_Support_thickness"
n_beams="3" grid_size="25.0*cm" >
<support material="Steel235" vis="AnlOrange" n_beams="3" grid_size="25.0*cm"
thickness="EcalBarrel_Support_thickness" beam_thickness="EcalBarrel_Support_thickness/4" >
</support>
</staves>
<layer repeat="EcalBarrelImagingLayers_num-1" vis="AnlBlue"
space_between="EcalBarrel_ImagingLayerThickness + EcalBarrel_SpaceBetween"
space_before="EcalBarrel_ImagingLayerThickness + EcalBarrel_SpaceBetween/2.">
<slice material="Lead" thickness="EcalBarrel_RadiatorThickness" vis="EcalBarrelFibersVis">
<slice material="Lead" thickness="EcalBarrel_RadiatorThickness" vis="EcalBarrelFiberLayer_vis">
<fiber material="PlasticScint"
sensitive="yes"
vis="EcalBarrelFiberVis"
radius="EcalBarrel_FiberRadius"
spacing_x="EcalBarrel_FiberXSpacing"
spacing_z="EcalBarrel_FiberZSpacing"/>
......@@ -138,14 +136,12 @@
space_before="EcalBarrel_ImagingLayerThickness + EcalBarrel_SpaceBetween">
<slice material="Lead"
thickness="EcalBarrel_FiberLayerThickness/EcalBarrel_FiberChunkLayers_num"
vis="EcalBarrelFiberLayerVis">
vis="EcalBarrelFiberLayer_vis">
<fiber material="PlasticScint"
sensitive="yes"
vis="EcalBarrelFiberVis"
radius="EcalBarrel_FiberRadius"
spacing_x="EcalBarrel_FiberXSpacing"
spacing_z="EcalBarrel_FiberZSpacing">
</fiber>
spacing_z="EcalBarrel_FiberZSpacing"/>
</slice>
</layer>
</detector>
......
......@@ -3,9 +3,13 @@
// Assembly is used as the envelope so two different detectors can be interlayered with each other
//
//
// Implementation of the Sci Fiber geometry: M. Żurek 06/19/2021
// Support interlayers between multiple detectors: C. Peng 07/09/2021
// 06/19/2021: Implementation of the Sci Fiber geometry. M. Żurek
// 07/09/2021: Support interlayers between multiple detectors. C. Peng
// 07/23/2021: Add assemblies as mother volumes of fibers to reduce the number of daughter volumes. C. Peng, M. Żurek
// Reference: TGeo performance issue with large number of daughter volumes
// https://indico.cern.ch/event/967418/contributions/4075358/attachments/2128099/3583278/201009_shKo_dd4hep.pdf
// 07/24/2021: Changed support implementation to avoid too many uses of boolean geometries. DAWN view seems to have
// issue dealing with it. C. Peng
#include "DD4hep/DetFactoryHelper.h"
#include "XML/Layering.h"
......@@ -17,13 +21,17 @@ using namespace dd4hep;
using namespace dd4hep::detail;
typedef ROOT::Math::XYPoint Point;
// headers for helper functions, defined in BarrelCalorimeterHybrid_geo
// fiber placement helpers, defined in BarrelCalorimeterHybrid_geo
vector<vector<Point>> fiberPositions(double radius, double x_spacing, double z_spacing,
double x, double z, double phi, double spacing_tol = 1e-2);
std::pair<int, int> getNdivisions(double x, double z, double dx, double dz);
vector<tuple<int, Point, Point, Point, Point>> gridPoints(int div_x, int div_z, double x, double z, double phi);
void buildFibers(Detector& desc, SensitiveDetector sens, Volume &s_vol, xml_comp_t x_fiber,
std::tuple<double, double, double, double> dimensions);
// geometry helpers
void buildFibers(Detector& desc, SensitiveDetector &sens, Volume &mother, xml_comp_t x_fiber,
const std::tuple<double, double, double, double> &dimensions);
void buildSupport(Detector& desc, Volume &mother, xml_comp_t x_support,
const std::tuple<double, double, double, double> &dimensions);
// barrel ecal layers contained in an assembly
......@@ -33,7 +41,6 @@ static Ref_t create_detector(Detector& desc, xml_h e, SensitiveDetector sens) {
Material air = desc.air();
int det_id = x_det.id();
string det_name = x_det.nameStr();
xml_comp_t x_staves = x_det.staves();
double offset = x_det.attr<double>(_Unicode(offset));
xml_comp_t x_dim = x_det.dimensions();
int nsides = x_dim.numsides();
......@@ -150,75 +157,22 @@ static Ref_t create_detector(Detector& desc, xml_h e, SensitiveDetector sens) {
sdet.add(sd);
}
Solid support_frame_s;
// optional stave support
if (x_staves.hasChild("support")) {
xml_comp_t x_support = x_staves.child(_U(support));
double support_thickness = getAttrOrDefault(x_support, _U(thickness), 5.0 * cm);
double trd_x1_support = (2 * std::tan(hphi) * l_pos_z + support_thickness)/2;
// is the support on the inside surface?
bool is_inside_support = getAttrOrDefault<bool>(x_support, _Unicode(inside), true);
double trd_x1 = std::tan(hphi) * inner_r;
double trd_x2 = std::tan(hphi) * (l_pos_z + support_thickness);
double trd_y1 = x_dim.z()/2.;
// number of "beams" running the length of the stave.
int n_beams = getAttrOrDefault<int>(x_support, _Unicode(n_beams), 3);
double beam_thickness = support_thickness / 4.0; // maybe a parameter later...
trd_x1_support = (2 * std::tan(hphi) * (l_pos_z + beam_thickness)) / 2.;
double grid_size = getAttrOrDefault(x_support, _Unicode(grid_size), 25.0 * cm);
double beam_width = 2.0 * trd_x1_support / (n_beams + 1); // quick hack to make some gap between T beams
double cross_beam_thickness = support_thickness/4.0;
//double trd_x1_support = (2 * std::tan(hphi) * (inner_r + beam_thickness)) / 2.;
double trd_x2_support = trd_x2;
int n_cross_supports = std::floor((trd_y1-cross_beam_thickness)/grid_size);
Box beam_vert_s(beam_thickness / 2.0 , trd_y1, support_thickness / 2.0 );
Box beam_hori_s(beam_width / 2.0, trd_y1, beam_thickness / 2.0);
UnionSolid T_beam_s(beam_vert_s, beam_hori_s, Position(0, 0, -support_thickness / 2.0 + beam_thickness / 2.0));
// cross supports
Trapezoid trd_support(trd_x1_support,trd_x2_support,
beam_thickness / 2.0, beam_thickness / 2.0,
support_thickness / 2.0 - cross_beam_thickness/2.0);
UnionSolid support_array_start_s(T_beam_s,trd_support,Position(0,0,cross_beam_thickness/2.0));
for (int isup = 0; isup < n_cross_supports; isup++) {
support_array_start_s = UnionSolid(support_array_start_s, trd_support,
Position(0, -1.0 * isup * grid_size, cross_beam_thickness/2.0));
support_array_start_s = UnionSolid(support_array_start_s, trd_support,
Position(0, 1.0 * isup * grid_size, cross_beam_thickness/2.0));
if (x_det.hasChild(_U(staves))) {
xml_comp_t x_staves = x_det.staves();
mod_vol.setVisAttributes(desc.visAttributes(x_staves.visStr()));
if (x_staves.hasChild(_U(support))) {
buildSupport(desc, mod_vol, x_staves.child(_U(support)), {inner_r, l_pos_z, x_dim.z(), hphi});
}
support_array_start_s =
UnionSolid(support_array_start_s, beam_hori_s,
Position(-1.8 * 0.5*(trd_x1+trd_x2_support) / n_beams, 0, -support_thickness / 2.0 + beam_thickness / 2.0));
support_array_start_s =
UnionSolid(support_array_start_s, beam_hori_s,
Position(1.8 * 0.5*(trd_x1+trd_x2_support) / n_beams, 0, -support_thickness / 2.0 + beam_thickness / 2.0));
support_array_start_s =
UnionSolid(support_array_start_s, beam_vert_s, Position(-1.8 * 0.5*(trd_x1+trd_x2_support) / n_beams, 0, 0));
support_array_start_s =
UnionSolid(support_array_start_s, beam_vert_s, Position(1.8 * 0.5*(trd_x1+trd_x2_support) / n_beams, 0, 0));
support_frame_s = support_array_start_s;
Material support_mat = desc.material(x_support.materialStr());
Volume support_vol("support_frame_v", support_frame_s, support_mat);
support_vol.setVisAttributes(desc,x_support.visStr());
// figure out how to best place
auto pv = mod_vol.placeVolume(support_vol, Position(0.0, 0.0, l_pos_z + support_thickness / 2.0));
}
//l_pos_z += support_thickness;
// Set envelope volume attributes.
envelope.setAttributes(desc, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
return sdet;
}
void buildFibers(Detector& desc, SensitiveDetector sens, Volume &s_vol, xml_comp_t x_fiber,
std::tuple<double, double, double, double> dimensions)
void buildFibers(Detector& desc, SensitiveDetector &sens, Volume &s_vol, xml_comp_t x_fiber,
const std::tuple<double, double, double, double> &dimensions)
{
auto [s_trd_x1, s_thick, s_length, hphi] = dimensions;
double f_radius = getAttrOrDefault(x_fiber, _U(radius), 0.1 * cm);
......@@ -258,7 +212,7 @@ void buildFibers(Detector& desc, SensitiveDetector sens, Volume &s_vol, xml_comp
// Check to which grid fiber belongs to
for (auto &poly_vtx : grid_vtx) {
if (p.y() != l_pos_y) {
std::cerr << Form("Expected the same y position from a same line: %.2f, but got %.f", l_pos_y, p.y())
std::cerr << Form("Expected the same y position from a same line: %.2f, but got %.2f", l_pos_y, p.y())
<< std::endl;
continue;
}
......@@ -289,11 +243,96 @@ void buildFibers(Detector& desc, SensitiveDetector sens, Volume &s_vol, xml_comp
PlacedVolume fiber_phv = lfibers.placeVolume(f_vol, Position(p.x(), 0., 0.));
fiber_phv.addPhysVolID(f_id_grid, f_grid_id + 1).addPhysVolID(f_id_fiber, f_id + 1);
}
lfibers.ptr()->Voxelize("");
Transform3D l_tr(RotationZYX(0,0,M_PI*0.5),Position(0., 0, l_pos_y));
s_vol.placeVolume(lfibers, l_tr);
}
}
// DAWN view seems to have some issue with overlapping solids even if they were unions
// The support is now built without overlapping
void buildSupport(Detector& desc, Volume &mod_vol, xml_comp_t x_support,
const std::tuple<double, double, double, double> &dimensions)
{
auto [inner_r, l_pos_z, stave_length, hphi] = dimensions;
double support_thickness = getAttrOrDefault(x_support, _Unicode(thickness), 5. * cm);
double beam_thickness = getAttrOrDefault(x_support, _Unicode(beam_thickness), support_thickness/4.);
// sanity check
if (beam_thickness > support_thickness/3.) {
std::cerr << Form("beam_thickness (%.2f) cannot be greater than support_thickness/3 (%.2f), shrink it to fit",
beam_thickness, support_thickness/3.) << std::endl;
beam_thickness = support_thickness/3.;
}
double trd_x1_support = std::tan(hphi) * l_pos_z;
double trd_x2_support = std::tan(hphi) * (l_pos_z + support_thickness);
double trd_y = stave_length / 2.;
Assembly env_vol ("support_envelope");
double grid_size = getAttrOrDefault(x_support, _Unicode(grid_size), 25. * cm);
int n_cross_supports = std::floor(trd_y - beam_thickness)/grid_size;
// number of "beams" running the length of the stave.
// @TODO make it configurable
int n_beams = getAttrOrDefault(x_support, _Unicode(n_beams), 3);;
double beam_width = 2. * trd_x1_support / (n_beams + 1); // quick hack to make some gap between T beams
double beam_gap = getAttrOrDefault(x_support, _Unicode(beam_gap), 3.*cm);
// build H-shape beam
double beam_space_x = beam_width + beam_gap;
double beam_space_z = support_thickness - beam_thickness;
double cross_thickness = support_thickness - 2.*beam_thickness;
double beam_pos_z = -beam_thickness / 2.;
double beam_center_z = support_thickness / 2. + beam_pos_z;
Box beam_vert_s(beam_thickness / 2. , trd_y, cross_thickness / 2.);
Box beam_hori_s(beam_width / 2., trd_y, beam_thickness / 2.);
UnionSolid T_beam_s(beam_hori_s, beam_vert_s, Position(0., 0., beam_space_z / 2.));
UnionSolid H_beam_s(T_beam_s, beam_hori_s, Position(0., 0., support_thickness - beam_thickness));
Volume H_beam_vol("H_beam", H_beam_s, desc.material(x_support.materialStr()));
H_beam_vol.setVisAttributes(desc, x_support.visStr());
// place H beams first
double beam_start_x = - (n_beams - 1) * (beam_width + beam_gap) / 2.;
for (int i = 0; i < n_beams; ++i) {
Position beam_pos(beam_start_x + i * (beam_width + beam_gap), 0., - support_thickness / 2. - beam_pos_z);
env_vol.placeVolume(H_beam_vol, beam_pos);
}
// place central crossing beams that connects the H beams
double cross_x = beam_space_x - beam_thickness;
Box cross_s(cross_x / 2., beam_thickness / 2., cross_thickness / 2.);
Volume cross_vol("cross_center_beam", cross_s, desc.material(x_support.materialStr()));
cross_vol.setVisAttributes(desc, x_support.visStr());
for (int i = 0; i < n_beams - 1; ++i) {
env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), 0., 0.));
for (int j = 1; j < n_cross_supports; j++) {
env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), -j * grid_size, 0.));
env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), j * grid_size, 0.));
}
}
// place edge crossing beams that connects the neighbour support
// @TODO: connection part is still using boolean volumes, maybe problematic to DAWN
double cross_edge_x = trd_x1_support + beam_start_x - beam_thickness / 2.;
double cross_trd_x1 = cross_edge_x + std::tan(hphi) * beam_thickness;
double cross_trd_x2 = cross_trd_x1 + 2.* std::tan(hphi) * cross_thickness;
double edge_pos_x = beam_start_x - beam_thickness / 2. - cross_trd_x1 / 2.;
Trapezoid cross_s2_trd (cross_trd_x1 / 2., cross_trd_x2 / 2.,
beam_thickness / 2., beam_thickness / 2., cross_thickness / 2.);
Box cross_s2_box ((cross_trd_x2 - cross_trd_x1)/2., beam_thickness / 2., cross_thickness / 2.);
SubtractionSolid cross_s2(cross_s2_trd, cross_s2_box, Position((cross_trd_x1 + cross_trd_x2) / 4., 0., 0.));
Volume cross_vol2("cross_edge_beam", cross_s2, desc.material(x_support.materialStr()));
cross_vol2.setVisAttributes(desc, x_support.visStr());
env_vol.placeVolume(cross_vol2, Position(edge_pos_x, 0., 0.));
env_vol.placeVolume(cross_vol2, Transform3D(Translation3D(-edge_pos_x, 0., 0.) * RotationZ(M_PI)));
for (int j = 1; j < n_cross_supports; j++) {
env_vol.placeVolume(cross_vol2, Position(edge_pos_x, -j * grid_size, 0.));
env_vol.placeVolume(cross_vol2, Position(edge_pos_x, j * grid_size, 0.));
env_vol.placeVolume(cross_vol2, Transform3D(Translation3D(-edge_pos_x, -j * grid_size, 0.) * RotationZ(M_PI)));
env_vol.placeVolume(cross_vol2, Transform3D(Translation3D(-edge_pos_x, j * grid_size, 0.) * RotationZ(M_PI)));
}
mod_vol.placeVolume(env_vol, Position(0.0, 0.0, l_pos_z + support_thickness/2.));
}
DECLARE_DETELEMENT(athena_EcalBarrelInterlayers, create_detector)
// DECLARE_DETELEMENT(athena_EcalBarrelInterlayers, create_detector)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment