Skip to content
Snippets Groups Projects
Commit 587b974d authored by lintao@ihep.ac.cn's avatar lintao@ihep.ac.cn
Browse files

Merge branch 'fix/otk-geometry' into 'master'

Add OTK geometry

See merge request !168
parents 1b5d59b5 2a02f015
No related branches found
No related tags found
1 merge request!168Add OTK geometry
Pipeline #14667 passed with stage
in 14 minutes and 55 seconds
<lccdd>
<info name="OTKBarrel_v02"
title="CepC OTKBarrel"
author="Li Zhihao"
url="http://cepc.ihep.ac.cn"
contact="lizhihao@ihep.ac.cn"
status="developing"
version="v02">
<comment>CepC Outer Tracker</comment>
</info>
<define>
<!--<constant name="OTKBarrel_inner_radius" value="1800*mm"/>-->
<!--<constant name="OTKBarrel_outer_radius" value="1814.09*mm"/>-->
<constant name="OTKBarrel_module_width" value="104.40*mm"/> <!-- 2*52.20*mm -->
<constant name="OTKBarrel_module_thickness" value="10.8*mm"/>
<constant name="OTKBarrel_module_length_inner" value="175.0*mm"/> <!-- 2*87.50*mm -->
<constant name="OTKBarrel_module_length_outer" value="180.0*mm"/> <!-- 2*90.00*mm -->
<constant name="OTKBarrel_ladder_width" value="104.40*mm"/> <!-- OTKBarrel_module_width -->
<constant name="OTKBarrel_ladder_length_inner"
value="4*OTKBarrel_module_length_inner"/> <!-- 4*OTKBarrel_module_length_inner -->
<constant name="OTKBarrel_ladder_length_outer"
value="4*OTKBarrel_module_length_outer"/> <!-- 4*OTKBarrel_module_length_outer -->
<constant name="OTKBarrel_stave_length"
value="4*(OTKBarrel_ladder_length_inner + OTKBarrel_ladder_length_outer)"/>
</define>
<detectors>
<detector id="DetID_OTKBarrel" name="OTKBarrel" type="SiTracker_otkbarrel_v02" vis="OTKBarrelVis"
readout="OTKBarrelCollection" insideTrackingVolume="true">
<type_flags type="DetType_TRACKER + DetType_BARREL + DetType_STRIP "/>
<envelope vis="SeeThrough">
<shape type="Tube" rmin="OTKBarrel_inner_radius" rmax="OTKBarrel_outer_radius"
dz="OTKBarrel_stave_length / 2" material="Air"/>
</envelope>
<stave name="OTKBarrel_stave" repeat="110" length="OTKBarrel_stave_length"
thickness="OTKBarrel_module_thickness" width="OTKBarrel_ladder_width" vis="SeeThrough">
<ladder name="OTKBarrel_ladder" repeat_inner="4" repeat_outer="4" width="OTKBarrel_ladder_width"
length_inner="OTKBarrel_ladder_length_inner" length_outer="OTKBarrel_ladder_length_outer"
thickness="OTKBarrel_module_thickness" vis_inner="SeeThrough" vis_outer="SeeThrough">
<module name="OTKBarrel_module" thickness="OTKBarrel_module_thickness" repeat="4"
width="OTKBarrel_module_width" length_inner="OTKBarrel_module_length_inner"
length_outer="OTKBarrel_module_length_outer" vis="SeeThrough">
<layer name="carbon_fiber_plane_inner" width="100.40*mm" thickness="0.3*mm" material="CarbonFiber" vis="BlackVis"/>
<layer name="carbon_fiber_honeycomb" width="100.40*mm" thickness="2.4*mm" material="CarbonFiber" vis="BlackVis">
<tube name="titanium_cooling_pipe" inner_diameter="1.6*mm" outer_diameter="2.0*mm"
material="CarbonFiber"/>
</layer>
<layer name="carbon_fiber_plane_outer" width="100.40*mm" thickness="0.3*mm" material="CarbonFiber" vis="BlackVis"/>
<layer name="sensor" sensitive="True" width="OTKBarrel_module_width" thickness="0.3*mm" material="CarbonFiber" vis="FTDSensitiveVis"/>
<data_aggregation name="first_data_aggregation" width="OTKBarrel_module_width" thickness="7.5*mm" length="7.0*mm" vis="SeeThrough">
<layer name="PCB" thickness="0.5*mm" width="OTKBarrel_module_width" length="7.0*mm" vis="GreenVis"/>
<DC name="DC-DC" thickness="7.0*mm" width="10.0*mm" length="3.0*mm" vis="YellowVis"/>
</data_aggregation>
</module>
<data_aggregation name="second_data_aggregation" thickness="7.0*mm" width="20.0*mm" length="10.0*mm" vis="YellowVis"/>
</ladder>
</stave>
</detector>
</detectors>
<readouts>
<readout name="OTKBarrelCollection">
<id>system:5,side:-2,layer:9,module:8,sensor:8,active:8</id>
</readout>
</readouts>
</lccdd>
\ No newline at end of file
<lccdd>
<info name="OTKEndcap_v02"
title="CepC OTKEndcap"
author="Li Zhihao"
url="http://cepc.ihep.ac.cn"
contact="lizhihao@ihep.ac.cn"
status="developing"
version="v02">
<comment>CepC Outer Tracker</comment>
</info>
<define>
<constant name="OTKEndcap_inner_radius" value="400*mm"/>
<constant name="OTKEndcap_outer_radius" value="1820*mm"/>
<constant name="OTKEndcap_zmin" value="2910*mm"/>
<constant name="OTKEndcap_zmax" value="2930*mm"/>
</define>
<detectors>
<detector id="DetID_OTKEndcap" name="OTKEndcap" type="SiTracker_otkendcap_v02" vis="OTKEndcapVis"
readout="OTKEndcapCollection" insideTrackingVolume="true">
<type_flags type="DetType_TRACKER + DetType_ENDCAP "/>
<envelope vis="SeeThrough">
<shape type="BooleanShape" operation="Subtraction" material="Air">
<shape type="Tube" rmin="OTKEndcap_inner_radius-env_safety" rmax="OTKEndcap_outer_radius+env_safety"
dz="OTKEndcap_zmax"/>
<shape type="Tube" rmin="OTKEndcap_inner_radius" rmax="OTKEndcap_outer_radius"
dz="OTKEndcap_zmin+env_safety"/>
</shape>
</envelope>
<rings zmax="OTKEndcap_zmax">
<ring name="A1" inner_radius="406*mm" outer_radius="(534-0.2)*mm" repeat="16*5" aggregation="2" vis="SeeThrough"/>
<ring name="A2" inner_radius="534*mm" outer_radius="(662-0.5)*mm" repeat="16*5" aggregation="2" vis="SeeThrough"/>
<ring name="B1" inner_radius="662*mm" outer_radius="(790-0.2)*mm" repeat="16*7" aggregation="2" vis="SeeThrough"/>
<ring name="B2" inner_radius="790*mm" outer_radius="(862-0.2)*mm" repeat="16*7" aggregation="1" vis="SeeThrough"/>
<ring name="B3" inner_radius="862*mm" outer_radius="(1008-0.5)*mm" repeat="16*7" aggregation="2" vis="SeeThrough"/>
<ring name="C1" inner_radius="1008*mm" outer_radius="(1123-0.2)*mm" repeat="16*10" aggregation="2" vis="SeeThrough"/>
<ring name="C2" inner_radius="1123*mm" outer_radius="(1255-0.2)*mm" repeat="16*10" aggregation="2" vis="SeeThrough"/>
<ring name="C3" inner_radius="1255*mm" outer_radius="(1324-0.2)*mm" repeat="16*10" aggregation="1" vis="SeeThrough"/>
<ring name="C4" inner_radius="1324*mm" outer_radius="(1400-0.5)*mm" repeat="16*10" aggregation="1" vis="SeeThrough"/>
<ring name="D1" inner_radius="1400*mm" outer_radius="(1460-0.2)*mm" repeat="16*14" aggregation="1" vis="SeeThrough"/>
<ring name="D2" inner_radius="1460*mm" outer_radius="(1520-0.2)*mm" repeat="16*14" aggregation="1" vis="SeeThrough"/>
<ring name="D3" inner_radius="1520*mm" outer_radius="(1668-0.2)*mm" repeat="16*14" aggregation="2" vis="SeeThrough"/>
<ring name="D4" inner_radius="1668*mm" outer_radius="(1816-0.2)*mm" repeat="16*14" aggregation="2" vis="SeeThrough"/>
</rings>
<layers thickness="11.4*mm">
<first_data_aggregation name="first_data_aggregation" thickness="7.5*mm" height="7*mm">
<DC name="DC-DC" thickness="7.0*mm"/>
<layer name="PCB" thickness="0.5*mm"/>
</first_data_aggregation>
<second_data_aggregation name="second_data_aggregation" thickness="7.5*mm">
<DC name="DC-DC" thickness="7.0*mm"/>
<layer name="PCB" thickness="0.5*mm"/>
</second_data_aggregation>
<layer name="sensor" sensitive="True" thickness="0.3*mm" material="CarbonFiber" vis="FTDSensitiveVis"/>
<layer name="carbon_fiber_plane" thickness="0.3*mm" material="CarbonFiber" vis="FTDSupportVis"/>
<layer name="titanium_cooling_plate" thickness="3*mm" material="CarbonFiber" vis="FTDSupportVis"/>
<layer name="carbon_fiber_back_plate" thickness="0.3*mm" material="CarbonFiber" vis="FTDSupportVis"/>
</layers>
</detector>
</detectors>
<readouts>
<readout name="OTKEndcapCollection">
<id>system:5,side:-2,layer:9,module:8,sensor:8,active:8</id>
</readout>
</readouts>
</lccdd>
\ No newline at end of file
#include "DD4hep/DetFactoryHelper.h"
#include "DD4hep/DetType.h"
#include "DDRec/Surface.h"
#include "DDRec/DetectorData.h"
#include "XML/Utilities.h"
#include <cmath>
using namespace dd4hep;
static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector sens)
{
xml_det_t x_det = e;
Material air = theDetector.air();
int det_id = x_det.id();
const std::string name = x_det.nameStr();
DetElement otk_barrel(name, det_id);
const xml::Component envelop_xml_element = x_det.child("envelope");
Volume envelope = createPlacedEnvelope(theDetector, e, otk_barrel);
envelope = envelope.setVisAttributes(theDetector, envelop_xml_element.attr<std::string>("vis"));
setDetectorTypeFlag(e, otk_barrel);
if (theDetector.buildType() == BUILD_ENVELOPE) return otk_barrel;
if (x_det.hasAttr(_U(sensitive)))
{
const xml_dim_t sd_typ = x_det.child(_U(sensitive));
sens.setType(sd_typ.typeStr());
}
else
{
sens.setType("tracker");
}
const std::string detector_name = x_det.attr<std::string>(_U(name));
const std::string detector_type = x_det.attr<std::string>(_U(type));
std::cout << "Processing Detector: " << detector_name
<< ", Type: " << detector_type << std::endl;
/* ================ read parameter from xml file ===================== */
// read parameter of stave
const xml::Component stave = x_det.child("stave");
auto stave_name = stave.attr<std::string>("name");
int stave_repeat = stave.attr<int>("repeat");
double angle_step = 2 * M_PI / stave_repeat;
double stave_length = theDetector.constant<double>(stave.attr<std::string>("length"));
double stave_thickness = theDetector.constant<double>(stave.attr<std::string>("thickness"));
double stave_width = theDetector.constant<double>(stave.attr<std::string>("width"));
DetElement stave_det(stave_name, det_id);
// read parameter of ladders in stave
const xml::Component ladder = stave.child(_U(ladder));
auto ladder_name = ladder.attr<std::string>("name");
int ladder_repeat_inner = ladder.attr<int>("repeat_inner");
int ladder_repeat_outer = ladder.attr<int>("repeat_outer");
double ladder_width = theDetector.constant<double>(ladder.attr<std::string>("width"));
double ladder_thickness = theDetector.constant<double>(ladder.attr<std::string>("thickness"));
double ladder_length_inner = theDetector.constant<double>(ladder.attr<std::string>("length_inner"));
double ladder_length_outer = theDetector.constant<double>(ladder.attr<std::string>("length_outer"));
DetElement inner_ladder_det("inner_" + ladder_name, det_id);
DetElement outer_ladder_det("outer_" + ladder_name, det_id);
Box inner_ladder_shape(ladder_thickness / 2.0, ladder_width / 2.0, ladder_length_inner / 2.0);
Volume inner_ladder_vol("inner_" + ladder_name, inner_ladder_shape, air);
inner_ladder_vol = inner_ladder_vol.setVisAttributes(theDetector, ladder.attr<std::string>("vis_inner"));
Box outer_ladder_shape(ladder_thickness / 2.0, ladder_width / 2.0, ladder_length_outer / 2.0);
Volume outer_ladder_vol("outer_" + ladder_name, outer_ladder_shape, air);
outer_ladder_vol = outer_ladder_vol.setVisAttributes(theDetector, ladder.attr<std::string>("vis_outer"));
// read parameter of second data-aggregation in module
const xml::Component second_data_aggregation = ladder.child("data_aggregation");
auto second_data_aggregation_name = second_data_aggregation.attr<std::string>("name");
double second_data_aggregation_thickness = second_data_aggregation.attr<double>("thickness");
double second_data_aggregation_width = second_data_aggregation.attr<double>("width");
double second_data_aggregation_length = second_data_aggregation.attr<double>("length");
Box second_data_aggregation_shape(second_data_aggregation_thickness / 2.0, second_data_aggregation_width / 2.0,
second_data_aggregation_length / 2.0);
Volume second_data_aggregation_vol(second_data_aggregation_name, second_data_aggregation_shape,
air);
second_data_aggregation_vol = second_data_aggregation_vol.setVisAttributes(
theDetector, second_data_aggregation.attr<std::string>("vis"));
// read parameter of module in ladder
const xml::Component module = ladder.child("module");
auto module_name = module.attr<std::string>("name");
double module_thickness = theDetector.constant<double>(module.attr<std::string>("thickness"));
int module_repeat = module.attr<int>("repeat");
double module_width = theDetector.constant<double>(module.attr<std::string>("width"));
double module_length_inner = theDetector.constant<double>(module.attr<std::string>("length_inner"));
double module_length_outer = theDetector.constant<double>(module.attr<std::string>("length_outer"));
DetElement inner_module_det("inner_" + module_name, det_id);
DetElement outer_module_det("outer_" + module_name, det_id);
// read parameter of first data-aggregation in module
xml::Component first_data_aggregation = module.child("data_aggregation");
auto first_data_aggregation_name = first_data_aggregation.attr<std::string>("name");
double first_data_aggregation_thickness = first_data_aggregation.attr<double>("thickness");
double first_data_aggregation_width = theDetector.constant<double>(
first_data_aggregation.attr<std::string>("width"));
double first_data_aggregation_length = first_data_aggregation.attr<double>("length");
Box first_data_aggregation_shape(first_data_aggregation_thickness / 2.0, first_data_aggregation_width / 2.0,
first_data_aggregation_length / 2.0);
Volume first_data_aggregation_vol(first_data_aggregation_name, first_data_aggregation_shape,
air);
first_data_aggregation_vol = first_data_aggregation_vol.setVisAttributes(
theDetector, first_data_aggregation.attr<std::string>("vis"));
{
xml::Component pcb = first_data_aggregation.child("layer");
auto pcb_name = pcb.attr<std::string>("name");
double pcb_thickness = pcb.attr<double>("thickness");
double pcb_width = theDetector.constant<double>(pcb.attr<std::string>("width"));
double pcb_length = pcb.attr<double>("length");
Box pcb_shape(pcb_thickness / 2.0, pcb_width / 2.0, pcb_length / 2.0);
Volume pcb_vol(pcb_name, pcb_shape, air);
pcb_vol = pcb_vol.setVisAttributes(theDetector, pcb.attr<std::string>("vis"));
first_data_aggregation_vol.placeVolume(
pcb_vol, Position((-first_data_aggregation_thickness + pcb_thickness) / 2.0, 0, 0));
xml::Component dc = first_data_aggregation.child("DC");
auto dc_name = dc.attr<std::string>("name");
double dc_thickness = dc.attr<double>("thickness");
double dc_width = dc.attr<double>("width");
double dc_length = dc.attr<double>("length");
Box dc_shape(dc_thickness / 2.0, dc_width / 2.0, dc_length / 2.0);
Volume dc_vol(dc_name, dc_shape, air);
dc_vol = dc_vol.setVisAttributes(theDetector,dc.attr<std::string>("vis"));
first_data_aggregation_vol.placeVolume(
dc_vol, Position((first_data_aggregation_thickness - dc_thickness) / 2.0, 0, 0));
}
Box stave_shape(stave_thickness / 2.0, stave_width / 2.0, stave_length / 2.0);
double stave_sub_shape_width = (stave_width - first_data_aggregation_width) / 2.0;
Box stave_sub_shape(first_data_aggregation_thickness / 2.0, stave_sub_shape_width / 2.0, stave_length / 2.0);
SubtractionSolid stave_subtracted_shape(stave_shape, stave_sub_shape, Position(
(stave_thickness - first_data_aggregation_thickness) / 2.0,
-stave_width / 2.0 + stave_sub_shape_width / 2.0, 0));
Volume stave_vol(stave_name, stave_subtracted_shape, air);
stave_vol = stave_vol.setVisAttributes(theDetector, stave.attr<std::string>("vis"));
double module_envelope_shape_base_thickness = module_thickness - first_data_aggregation_thickness;
Position translation(module_thickness / 2.0, 0, 0);
Box inner_module_envelope_shape_base(module_envelope_shape_base_thickness / 2.0, module_width / 2.0,
module_length_inner / 2.0);
UnionSolid inner_module_envelope_shape(inner_module_envelope_shape_base, first_data_aggregation_shape, translation);
Volume inner_module_envelope_vol(module_name + "_inner",
inner_module_envelope_shape, air);
inner_module_envelope_vol = inner_module_envelope_vol.
setVisAttributes(theDetector, module.attr<std::string>("vis"));
Box outer_module_envelope_shape_base(module_envelope_shape_base_thickness / 2.0, module_width / 2.0,
module_length_outer / 2.0);
UnionSolid outer_module_envelope_shape(outer_module_envelope_shape_base, first_data_aggregation_shape, translation);
Volume outer_module_envelope_vol(module_name + "_outer",
outer_module_envelope_shape, air);
outer_module_envelope_vol = outer_module_envelope_vol.
setVisAttributes(theDetector, module.attr<std::string>("vis"));
// Process layers in module
double x_offset = -module_envelope_shape_base_thickness / 2.0;
double thickness_sensitive = 0 * mm;
double thickness_support = 0 * mm;
for (xml_coll_t layers(module, "layer"); layers; ++layers)
{
xml::Component layer = xml::Handle_t(layers);
auto layer_name = layer.attr<std::string>("name");
double layer_thickness = layer.attr<double>("thickness");
double layer_width = layer.attr<double>("width");
DetElement inner_layer_det(layer_name, det_id);
DetElement outer_layer_det(layer_name, det_id);
const Material material = theDetector.material(layer.attr<std::string>("material"));
auto vis = layer.attr<std::string>("vis");
auto is_sensitive = layer.hasAttr(_U(sensitive));
const Box inner_layer_shape(layer_thickness / 2.0, layer_width / 2.0, module_length_inner / 2.0);
Volume inner_layer_vol(module_name + layer_name, inner_layer_shape, material);
inner_layer_vol = inner_layer_vol.setVisAttributes(theDetector, vis);
const Box outer_layer_box(layer_thickness / 2.0, layer_width / 2.0, module_length_outer / 2.0);
Volume outer_layer_vol(module_name + layer_name, outer_layer_box, material);
outer_layer_vol = outer_layer_vol.setVisAttributes(theDetector, vis);
rec::SurfaceType surf_type;
if (is_sensitive)
{
double sub_half_x = layer_thickness / 2.0;
double sub_half_y = layer_width / 4.0;
double sub_half_z_inner = module_length_inner / 4.0;
double sub_half_z_outer = module_length_outer / 4.0;
Box sub_box_shape_inner(sub_half_x, sub_half_y, sub_half_z_inner);
Box sub_box_shape_outer(sub_half_x, sub_half_y, sub_half_z_outer);
std::vector<std::pair<Position, Position>> sub_box_positions = {
{{0, sub_half_y, sub_half_z_inner}, {0, sub_half_y, sub_half_z_outer}},
{{0, sub_half_y, -sub_half_z_inner}, {0, sub_half_y, -sub_half_z_outer}},
{{0, -sub_half_y, -sub_half_z_inner}, {0, -sub_half_y, -sub_half_z_outer}},
{{0, -sub_half_y, sub_half_z_inner}, {0, -sub_half_y, sub_half_z_outer}}
};
for (size_t i = 0; i < 4; ++i)
{
Volume sub_box_vol_inner(module_name + layer_name + std::to_string(i), sub_box_shape_inner, material);
Volume sub_box_vol_outer(module_name + layer_name + std::to_string(i), sub_box_shape_outer, material);
sub_box_vol_inner = sub_box_vol_inner.setVisAttributes(theDetector, "SeeThrough");
sub_box_vol_outer = sub_box_vol_outer.setVisAttributes(theDetector, "SeeThrough");
sub_box_vol_outer = sub_box_vol_outer.setSensitiveDetector(sens);
sub_box_vol_inner = sub_box_vol_inner.setSensitiveDetector(sens);
inner_layer_vol.placeVolume(sub_box_vol_inner, sub_box_positions[i].first).addPhysVolID("sensor", i);
outer_layer_vol.placeVolume(sub_box_vol_outer, sub_box_positions[i].second).addPhysVolID("sensor", i);
}
thickness_sensitive += layer_thickness;
surf_type = rec::SurfaceType::Sensitive;
}
else
{
thickness_support += layer_thickness;
surf_type = rec::SurfaceType::Plane;
}
rec::Vector3D u(0., 0., 1.);
rec::Vector3D v(0., 1., 0.);
rec::Vector3D n(1., 0., 0.);
rec::VolPlane inner_surf(inner_layer_vol, surf_type, layer_thickness / 2.0, layer_thickness / 2.0, u, v, n);
rec::VolPlane outer_surf(outer_layer_vol, surf_type, layer_thickness / 2.0, layer_thickness / 2.0, u, v, n);
rec::volSurfaceList(inner_layer_det)->push_back(inner_surf);
rec::volSurfaceList(outer_layer_det)->push_back(outer_surf);
//TODO: add tube
// if (layer.hasChild(_U(tube)))
// {
// xml::Component tube = layer.child(_U(tube));
// auto tube_name = tube.attr<std::string>("name");
// double inner_diameter = tube.attr<double>("inner_diameter");
// double outer_diameter = tube.attr<double>("outer_diameter");
// }
// construct module
Position layer_pos(x_offset + layer_thickness / 2.0, 0, 0);
inner_layer_det.setPlacement(inner_module_envelope_vol.placeVolume(inner_layer_vol, layer_pos));
outer_layer_det.setPlacement(outer_module_envelope_vol.placeVolume(outer_layer_vol, layer_pos));
inner_module_det.add(inner_layer_det);
outer_module_det.add(outer_layer_det);
x_offset += layer_thickness;
}
// construct module
DetElement first_data_aggregation_det_inner(first_data_aggregation_name, det_id);
DetElement first_data_aggregation_det_outer(first_data_aggregation_name, det_id);
Position first_data_aggregation_pos(x_offset + first_data_aggregation_thickness / 2.0, 0, 0);
first_data_aggregation_det_inner.setPlacement(
inner_module_envelope_vol.placeVolume(first_data_aggregation_vol, first_data_aggregation_pos));
first_data_aggregation_det_outer.setPlacement(
outer_module_envelope_vol.placeVolume(first_data_aggregation_vol, first_data_aggregation_pos));
inner_module_det.add(first_data_aggregation_det_inner);
outer_module_det.add(first_data_aggregation_det_outer);
// construct ladder
for (int i = 0; i < module_repeat; ++i)
{
double z_position = -(module_repeat / 2.0) * module_length_inner + module_length_inner / 2.0 + i *
module_length_inner;
Position pos((module_envelope_shape_base_thickness - ladder_thickness) / 2.0, 0, z_position);
auto cloned_inner_module_det = inner_module_det.clone("inner_" + module_name + std::to_string(i), det_id);
cloned_inner_module_det.setPlacement(
inner_ladder_vol.placeVolume(inner_module_envelope_vol, pos).addPhysVolID("active", i));
inner_ladder_det.add(cloned_inner_module_det);
double z_position_outer = -(module_repeat / 2.0) * module_length_outer + module_length_outer / 2.0 + i *
module_length_outer;
Position pos_outer((module_envelope_shape_base_thickness - ladder_thickness) / 2.0, 0, z_position_outer);
auto cloned_outer_module_det = outer_module_det.clone("outer_" + module_name + std::to_string(i), det_id);
cloned_outer_module_det.setPlacement(
outer_ladder_vol.placeVolume(outer_module_envelope_vol, pos_outer).addPhysVolID("active", i));
outer_ladder_det.add(cloned_outer_module_det);
}
DetElement second_data_aggregation_det_inner(second_data_aggregation_name, det_id);
DetElement second_data_aggregation_det_outer(second_data_aggregation_name, det_id);
Position second_data_aggregation_pos((ladder_thickness - second_data_aggregation_thickness) / 2.0,
(module_width - second_data_aggregation_width) / 2.0, 0);
second_data_aggregation_det_inner.setPlacement(
inner_ladder_vol.placeVolume(second_data_aggregation_vol, second_data_aggregation_pos));
second_data_aggregation_det_outer.setPlacement(
outer_ladder_vol.placeVolume(second_data_aggregation_vol, second_data_aggregation_pos));
inner_ladder_det.add(second_data_aggregation_det_inner);
outer_ladder_det.add(second_data_aggregation_det_outer);
// inner ladder
for (int i = 0; i < ladder_repeat_inner; ++i)
{
double z_position = -(ladder_repeat_inner / 2.0) * ladder_length_inner + (i + 0.5) * ladder_length_inner;
Position pos(0, 0, z_position);
auto cloned_inner_ladder_det = inner_ladder_det.clone("inner_" + ladder_name + std::to_string(i), det_id);
cloned_inner_ladder_det.setPlacement(
stave_vol.placeVolume(inner_ladder_vol, pos).addPhysVolID("module", ladder_repeat_outer / 2 + i));
stave_det.add(cloned_inner_ladder_det);
}
// outer ladder (positive x)
for (int i = 0; i < ladder_repeat_outer / 2; ++i)
{
double z_position = ladder_length_inner * (ladder_repeat_inner / 2.0) + (i + 0.5) * ladder_length_outer;
Position pos(0, 0, z_position);
auto cloned_outer_ladder_det = outer_ladder_det.clone("outer_" + ladder_name + std::to_string(i + 1), det_id);
cloned_outer_ladder_det.setPlacement(stave_vol.placeVolume(outer_ladder_vol, pos).addPhysVolID(
"module", ladder_repeat_outer / 2 + ladder_repeat_inner + i));
stave_det.add(cloned_outer_ladder_det);
}
// outer ladder (neg x)
for (int i = 0; i < ladder_repeat_outer / 2; ++i)
{
double z_position = -ladder_length_inner * (ladder_repeat_inner / 2.0) - (i + 0.5) * ladder_length_outer;
Position pos(0, 0, z_position);
auto cloned_outer_ladder_det = outer_ladder_det.clone("outer_" + ladder_name + std::to_string(-i - 1), det_id);
cloned_outer_ladder_det.setPlacement(stave_vol.placeVolume(outer_ladder_vol, pos).addPhysVolID("module", i));
stave_det.add(cloned_outer_ladder_det);
}
// place rotated stave into envelope
double otk_inner_radius = theDetector.constant<double>("OTKBarrel_inner_radius");
double stave_x_offset = otk_inner_radius + stave_thickness / 2.0;
double stave_y_offset = stave_width / 2.0;
auto z_planar_data = new rec::ZPlanarData;
for (int i = 0; i < stave_repeat; ++i)
{
double angle = i * angle_step;
// calculate rotated pos
double rotated_x = stave_x_offset * cos(angle) - stave_y_offset * sin(angle);
double rotated_y = stave_x_offset * sin(angle) + stave_y_offset * cos(angle);
auto cloned_stave_det = stave_det.clone("stave_" + std::to_string(i), det_id);
cloned_stave_det.setPlacement(
envelope.placeVolume(stave_vol, Transform3D(RotationZ(angle), Position(rotated_x, rotated_y, 0.0))).
addPhysVolID("layer", i).addPhysVolID("side", 0));
otk_barrel.add(cloned_stave_det);
rec::ZPlanarData::LayerLayout otk_barrel_layer;
otk_barrel_layer.phi0 = angle;
otk_barrel_layer.ladderNumber = ladder_repeat_outer + ladder_repeat_inner;
otk_barrel_layer.thicknessSensitive = thickness_sensitive;
otk_barrel_layer.thicknessSupport = thickness_support;
otk_barrel_layer.distanceSensitive = otk_inner_radius + thickness_support;
otk_barrel_layer.distanceSupport = otk_inner_radius;
otk_barrel_layer.offsetSensitive = stave_y_offset;
otk_barrel_layer.offsetSupport = stave_y_offset;
otk_barrel_layer.widthSensitive = module_width;
otk_barrel_layer.widthSupport = module_width;
otk_barrel_layer.sensorsPerLadder = module_repeat * 4;
double z_half = ladder_length_inner * ladder_repeat_inner / 2.0 + ladder_length_outer * ladder_repeat_outer /
2.0;
otk_barrel_layer.zHalfSensitive = z_half;
otk_barrel_layer.zHalfSupport = z_half;
z_planar_data->layers.push_back(otk_barrel_layer);
}
#ifdef DET_ELEMENT_DEBUG
check_det_element(otk_barrel);
#endif
otk_barrel.addExtension<rec::ZPlanarData>(z_planar_data);
if (x_det.hasAttr(_U(combineHits)))
{
otk_barrel.setCombineHits(x_det.attr<bool>(_U(combineHits)), sens);
}
return otk_barrel;
}
DECLARE_DETELEMENT(SiTracker_otkbarrel_v02, create_element)
#include "DD4hep/DetFactoryHelper.h"
#include "DD4hep/DetType.h"
#include "DDRec/Surface.h"
#include "DDRec/DetectorData.h"
#include "XML/Utilities.h"
#include <cmath>
using namespace dd4hep;
inline double calculate_polygon_side_length(const double radius, const int sides)
{
return 2 * radius * tan(M_PI / sides);
}
// #define DET_ELEMENT_DEBUG
#ifdef DET_ELEMENT_DEBUG
void check_det_element(const DetElement det)
{
std::cout << "Checking DetElement: " << det.name() << std::endl;
if (det.children().size() == 0)
{
std::cout << "name: " << det.name() << std::endl;
std::cout << "path: " << det.path() << std::endl;
std::cout << "No Children: " << det.name() << std::endl;
const auto list = det.extension<rec::VolSurfaceList>(false);
if (!list) return;
for (auto surf : *list)
{
std::cout << "!!!Surface: " << surf.volume().name() << std::endl;
}
return;
}
for (auto [fst, snd] : det.children())
{
check_det_element(snd);
}
}
#endif
static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector sens)
{
xml_det_t x_det = e;
Material air = theDetector.air();
int det_id = x_det.id();
const std::string name = x_det.nameStr();
DetElement otk_endcaps(name, det_id);
const xml::Component envelop_xml_element = x_det.child("envelope");
Volume envelope = createPlacedEnvelope(theDetector, e, otk_endcaps);
envelope = envelope.setVisAttributes(theDetector, envelop_xml_element.attr<std::string>("vis"));
setDetectorTypeFlag(e, otk_endcaps);
if (theDetector.buildType() == BUILD_ENVELOPE) return otk_endcaps;
if (x_det.hasAttr(_U(sensitive)))
{
const xml_dim_t sd_typ = x_det.child(_U(sensitive));
sens.setType(sd_typ.typeStr());
}
else
{
sens.setType("tracker");
}
const std::string detector_name = x_det.attr<std::string>(_U(name));
const std::string detector_type = x_det.attr<std::string>(_U(type));
std::cout << "Processing Detector: " << detector_name
<< ", Type: " << detector_type << std::endl;
// start construction
const xml::Component rings_xml = x_det.child("rings");
const xml::Component layers_xml = x_det.child("layers");
double zmax = theDetector.constant<double>(rings_xml.attr<std::string>("zmax"));
const xml::Component first_data_aggregation = layers_xml.child("first_data_aggregation");
const double first_data_aggregation_thickness = first_data_aggregation.attr<double>("thickness");
int ring_num = 0;
for (xml_coll_t rings(rings_xml, "ring"); rings; ++rings, ++ring_num)
{
xml::Component ring = xml::Handle_t(rings);
const auto ring_name = ring.attr<std::string>("name");
const double ring_inner_radius = ring.attr<double>("inner_radius");
const double ring_outer_radius = ring.attr<double>("outer_radius");
const int repeat = ring.attr<int>("repeat");
double angle_step = 2 * M_PI / repeat;
DetElement ring_piece_det(ring_name, det_id);
const double trapezoid_height = ring_outer_radius - ring_inner_radius;
const double trapezoid_inner_length = calculate_polygon_side_length(ring_inner_radius, repeat);
const double trapezoid_outer_length = calculate_polygon_side_length(ring_outer_radius, repeat);
const double layers_thickness = layers_xml.attr<double>("thickness");
const double layers_base_thickness = layers_thickness - first_data_aggregation_thickness;
Trapezoid layer_base_shape(trapezoid_inner_length / 2.0, trapezoid_outer_length / 2.0,
layers_base_thickness / 2.0, layers_base_thickness / 2.0, trapezoid_height / 2.0);
Volume layer_base_vol(ring_name, layer_base_shape, air);
layer_base_vol = layer_base_vol.setVisAttributes(theDetector, ring.attr<std::string>("vis"));
double y_offset = -layers_base_thickness / 2.0;
{
}
for (xml_coll_t layers(layers_xml, "layer"); layers; ++layers)
{
const xml::Component layer = xml::Handle_t(layers);
const auto layer_name = layer.attr<std::string>("name");
const double layer_thickness = layer.attr<double>("thickness");
const Material material = theDetector.material(layer.attr<std::string>("material"));
const auto vis = layer.attr<std::string>("vis");
auto is_sensitive = layer.hasAttr(_U(sensitive));
DetElement layer_base_det(layer_name, det_id);
rec::SurfaceType surf_type;
Trapezoid layer_shape(trapezoid_inner_length / 2.0, trapezoid_outer_length / 2.0, layer_thickness / 2.0,
layer_thickness / 2.0, trapezoid_height / 2.0);
Volume layer_vol(layer_name, layer_shape, material);
layer_vol = layer_vol.setVisAttributes(theDetector, vis);
if (is_sensitive)
{
layer_vol = layer_vol.setSensitiveDetector(sens);
surf_type = rec::SurfaceType::Sensitive;
}
else
{
surf_type = rec::SurfaceType::Plane;
}
rec::Vector3D u(0., 0., 1.);
rec::Vector3D v(0., 1., 0.);
rec::Vector3D n(1., 0., 0.);
rec::VolPlane surf(layer_vol, surf_type, layer_thickness / 2.0, layer_thickness / 2.0, u, v, n);
rec::volSurfaceList(layer_base_det)->push_back(surf);
layer_base_det.setPlacement(
layer_base_vol.placeVolume(layer_vol, Position(0, y_offset + layer_thickness / 2.0, 0)));
ring_piece_det.add(layer_base_det);
y_offset += layer_thickness;
}
auto rotationX = RotationX(90.0 * deg);
auto rotationZ = RotationZ(90.0 * deg);
auto neg_rotationX = RotationX(-90.0 * deg);
auto neg_rotationZ = RotationZ(-90.0 * deg);
for (int i = 0; i < repeat; ++i)
{
double angle = i * angle_step;
double r_offset = ring_inner_radius + trapezoid_height / 2.0;
double rotated_x = r_offset * cos(angle);
double rotated_y = r_offset * sin(angle);
auto transform = Transform3D(
RotationZ(angle) * rotationZ * rotationX,
Position(rotated_x, rotated_y,
zmax - layers_base_thickness / 2.0));
auto neg_transform = Transform3D(
RotationZ(angle) * neg_rotationZ * neg_rotationX,
Position(rotated_x, rotated_y,
-(zmax - layers_base_thickness / 2.0)));
auto cloned_ring_piece_det = ring_piece_det.clone(ring_name + std::to_string(i + 1));
auto cloned_neg_ring_piece_det = ring_piece_det.clone(ring_name + std::to_string(-(i + 1)));
auto pv = envelope.placeVolume(layer_base_vol, transform).addPhysVolID("side", -1).addPhysVolID("module", i)
.addPhysVolID("layer", ring_num);
auto neg_pv = envelope.placeVolume(layer_base_vol, neg_transform).addPhysVolID("side", 1).
addPhysVolID("module", i).addPhysVolID("layer", ring_num);
cloned_ring_piece_det.setPlacement(pv);
cloned_neg_ring_piece_det.setPlacement(neg_pv);
otk_endcaps.add(cloned_ring_piece_det);
otk_endcaps.add(cloned_neg_ring_piece_det);
}
}
#ifdef DET_ELEMENT_DEBUG
check_det_element(otk_endcaps);
#endif
return otk_endcaps;
}
DECLARE_DETELEMENT(SiTracker_otkendcap_v02, create_element)
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