From 48cb929a90d6f311a83218a32f19c4dcd3b5b25d Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Sun, 11 Nov 2012 20:50:34 +0000
Subject: [PATCH] Some improvements and implementation of the CLIC_ILD_CDR
model
---
.../src/CylindricalBarrelCalorimeter_geo.cpp | 6 +-
.../src/CylindricalEndcapCalorimeter_geo.cpp | 2 +-
.../CLICSiD/src/MultiLayerTracker_geo.cpp | 2 +-
.../src/compact/Tesla_LumiCalX_geo.cpp | 31 +-
.../src/compact/Tesla_SEcal03_geo.cpp | 491 ++++----
.../ILDExDet/src/compact/Tesla_VXD03_geo.cpp | 20 +-
.../ILDExDet/src/compact/Tesla_coil00_geo.cpp | 7 +-
.../ILDExDet/src/compact/Tesla_ftd01_geo.cpp | 88 +-
.../ILDExDet/src/compact/Tesla_hcal04_geo.cpp | 1057 +++++++----------
.../ILDExDet/src/compact/Tesla_mask04_geo.cpp | 13 +-
.../ILDExDet/src/compact/Tesla_sit00_geo.cpp | 22 +-
.../ILDExDet/src/compact/Tesla_tpc02_geo.cpp | 30 +-
.../ILDExDet/src/compact/Tesla_tube01_geo.cpp | 45 +-
.../src/compact/Tesla_tubeX01_geo.cpp | 867 ++++----------
.../ILDExDet/src/compact/Tesla_yoke02_geo.cpp | 5 +-
15 files changed, 1128 insertions(+), 1558 deletions(-)
diff --git a/DDExamples/CLICSiD/src/CylindricalBarrelCalorimeter_geo.cpp b/DDExamples/CLICSiD/src/CylindricalBarrelCalorimeter_geo.cpp
index 0ee29506b..f52351494 100644
--- a/DDExamples/CLICSiD/src/CylindricalBarrelCalorimeter_geo.cpp
+++ b/DDExamples/CLICSiD/src/CylindricalBarrelCalorimeter_geo.cpp
@@ -38,7 +38,7 @@ static Ref_t create_detector(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens
double router = r + x_slice.thickness();
Material slice_mat = lcdd.material(x_slice.materialStr());
string slice_name = layer_name + _toString(m,"slice%d");
- Tube slice_tube(r,router,z * 2);
+ Tube slice_tube(r,router,z*2);
Volume slice_vol (slice_name,slice_tube,slice_mat);
if ( x_slice.isSensitive() ) slice_vol.setSensitiveDetector(sens);
@@ -48,14 +48,14 @@ static Ref_t create_detector(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens
layer_vol.placeVolume(slice_vol,IdentityPos());
}
layer_vol.setVisAttributes(lcdd,x_layer.visStr());
- layer_tub.setDimensions(rlayer,r,z * 2);
+ layer_tub.setDimensions(rlayer,r,z*2,0,2*M_PI);
PlacedVolume layer_physvol = envelopeVol.placeVolume(layer_vol,IdentityPos());
layer_physvol.addPhysVolID(_A(layer),n);
++n;
}
}
- envelope.setDimensions(rmin,r,2.*z);
+ envelope.setDimensions(rmin,r,2*z,0,2*M_PI);
// Set region of slice
envelopeVol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
diff --git a/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp b/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp
index 9282af509..86661b81b 100644
--- a/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp
+++ b/DDExamples/CLICSiD/src/CylindricalEndcapCalorimeter_geo.cpp
@@ -60,7 +60,7 @@ static Ref_t create_detector(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens
++n;
}
}
- envelope.setDimensions(rmin,rmax,totWidth,2.*M_PI);
+ envelope.setDimensions(rmin,rmax,totWidth,0,2*M_PI);
// Set attributes of slice
envelopeVol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
diff --git a/DDExamples/CLICSiD/src/MultiLayerTracker_geo.cpp b/DDExamples/CLICSiD/src/MultiLayerTracker_geo.cpp
index 1cd4ce24e..64e5979fa 100644
--- a/DDExamples/CLICSiD/src/MultiLayerTracker_geo.cpp
+++ b/DDExamples/CLICSiD/src/MultiLayerTracker_geo.cpp
@@ -48,7 +48,7 @@ static Ref_t create_detector(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens
// Slices have no extra id. Take the ID of the layer!
spv.addPhysVolID(_X(layer),n);
}
- l_tub.setDimensions(rmin,r,z,2*M_PI);
+ l_tub.setDimensions(rmin,r,z,0,2*M_PI);
cout << l_name << " " << rmin << " " << r << " " << z << endl;
l_vol.setVisAttributes(lcdd,x_layer.visStr());
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_LumiCalX_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_LumiCalX_geo.cpp
index 905b5db5c..a97a54aab 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_LumiCalX_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_LumiCalX_geo.cpp
@@ -18,8 +18,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
xml_comp_t x_layer= e.child(_X(layer));
string name = x_det.nameStr();
Material air = lcdd.air();
- DetElement lcal(name,x_det.id());
- Volume mother = lcdd.pickMotherVolume(lcal);
+ DetElement side("pos",x_det.id());
// LumiCal dimensions
int n_layers = x_layer.attr<int>(_A(nmodules));
@@ -83,7 +82,8 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
Tube cell_tube(cal_innerradius,(cal_innerradius+thetastrip_dr), cell_thick);//, phistrip_dphi);
Volume cell_vol (name+"_cell",cell_tube,cell_mat);
cell_vol.setVisAttributes(cell_vis);
-
+ cell_vol.setSensitiveDetector(sens);
+
// here PHI silicon sector
Tube sector_tube(cal_innerradius,cal_outerradius,cell_thick);//,phistrip_dphi);
Volume sector_vol(name+"_sector",sector_tube,cell_mat);
@@ -97,6 +97,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
// Replicate strips within a theta and phi plane padded version
Volume sens_theta_vol = Ref_t(sector_tube->Divide(sector_vol, (name+"_sector_theta").c_str(), 1, ncell_theta, 0., thetastrip_dr));
sens_theta_vol.setVisAttributes(cell_vis);
+
Volume sens_phi_vol = Ref_t(sensor_tube->Divide(sensor_vol, (name+"_sensor_phi").c_str(), 2, ncell_phi, 0., phistrip_dphi*RAD_2_DEGREE));
sens_phi_vol.setVisAttributes(cell_vis);
@@ -116,17 +117,35 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
// position of first layer
double lay_z = -cal_hz + layer_hz;
+
// Put the layers into the LumiCal sub-module
+ PlacedVolume pv;
for (int nLay = 1; nLay < n_layers+1; nLay++) {
- env_vol.placeVolume(lay_vol,Position(0,0,lay_z));
+ DetElement layer_det(side,_toString(nLay,"layer%d"),nLay);
+ pv = env_vol.placeVolume(lay_vol,Position(0,0,lay_z));
+ layer_det.setPlacement(pv);
lay_z += (layer_hz*2.0+layer_gap);
}
// Place two LumiCal sub-modules into the world
double z_center = z_begin+cal_hz;
+
//Debug: one side centered only: mother.placeVolume(env_vol,Position(0,0,0),Rotation(0,bx_angle,0));
- mother.placeVolume(env_vol,Position(0,0,z_center).rotateY(bx_angle),Rotation(0,bx_angle,0));
- mother.placeVolume(env_vol,Position(0,0,z_center).rotateY(M_PI-bx_angle),Rotation(0,M_PI-bx_angle,0));
+ DetElement lcal(name,x_det.id());
+ Volume mother = lcdd.pickMotherVolume(lcal);
+ Assembly assembly(name);
+
+ pv = assembly.placeVolume(env_vol,Position(0,0,z_center).rotateY(bx_angle),Rotation(0,bx_angle,0));
+ side.setPlacement(pv);
+ lcal.add(side);
+
+ DetElement other_side = side.clone("neg",-x_det.id());
+ pv = assembly.placeVolume(env_vol,Position(0,0,z_center).rotateY(M_PI-bx_angle),Rotation(0,M_PI-bx_angle,0));
+ other_side.setPlacement(pv);
+ lcal.add(other_side);
+ assembly.setVisAttributes(lcdd.visAttributes(x_det.visStr()));
+ pv = mother.placeVolume(assembly);
+ lcal.setPlacement(pv);
return lcal;
}
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_SEcal03_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_SEcal03_geo.cpp
index 2037f94eb..fe912f8e3 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_SEcal03_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_SEcal03_geo.cpp
@@ -9,35 +9,12 @@
#include "DD4hep/DetFactoryHelper.h"
#include "TGeoBBox.h"
-using namespace std;
-using namespace DD4hep;
-using namespace DD4hep::Geometry;
-
-namespace {
- struct ECAL : public DetElement {
+namespace DD4hep { namespace Geometry {
+ struct SEcal03Data : public DetElement::Object {
typedef Position Dimension;
- enum { ECALBARREL };
- LCDD& lcdd;
- SensitiveDetector& sens_det;
-
- xml_det_t x_det;
- xml_comp_t x_barrel;
- xml_comp_t x_endcap;
- xml_comp_t x_support;
- xml_comp_t x_front;
-
- xml_comp_t x_shield;
- struct XMLSlab : public xml_comp_t {
- xml_comp_t shield;
- xml_comp_t copper;
- xml_comp_t sensitive;
- xml_comp_t ground;
- xml_comp_t glue;
- XMLSlab() : xml_comp_t(0), shield(0), copper(0), sensitive(0), ground(0), glue(0) {}
- XMLSlab& operator=(const xml_h& e) { this->Element::operator=(e); return *this; }
- } m_xml_slab;
-
- struct Slab_t {
+ enum { ECALBARREL=1, ECALENDCAPPLUS=2, ECALENDCAPMINUS=3 };
+ enum { SIDE_PLUS=0, SIDE_MINUS=1 };
+ struct Slab {
double h_fiber_thickness;
double shield_thickness;
VisAttr vis;
@@ -56,12 +33,12 @@ namespace {
double glue_thickness;
double total_thickness;
- Slab_t() : h_fiber_thickness(0), shield_thickness(0), ground_thickness(0),
- sensitive_thickness(0), copper_thickness(0), glue_thickness(0),
- total_thickness(0) {}
+ Slab() : h_fiber_thickness(0), shield_thickness(0), ground_thickness(0),
+ sensitive_thickness(0), copper_thickness(0), glue_thickness(0),
+ total_thickness(0) {}
} m_slab;
- struct Layer {
+ struct Layer {
int nLayer;
double thickness;
Material rad_mat;
@@ -70,7 +47,7 @@ namespace {
Volume m_center_tube;
Position m_alveolus;
- struct Barrel_t : public Dimension {
+ struct Barrel : public DetElement {
typedef std::vector<Layer*> Layers;
int numTowers;
@@ -78,186 +55,193 @@ namespace {
double top;
double thickness;
double inner_r;
+ double dim_z;
Material radiatorMaterial;
+ Material material;
+ VisAttr vis;
Layers layers;
- Volume stave;
int numStaves, numModules;
- PlacedVolume module[9][6];
+ DetElement module[9][6];
+ SensitiveDetector sensDet;
+ /// Helper function to allow assignment
+ DetElement& operator=(const DetElement& d) { return this->DetElement::operator=(d); }
} m_barrel;
- struct Endcap_t {
+ struct Endcap : public DetElement {
typedef std::vector<Layer*> Layers;
double rmin;
double rmax;
- double z;
+ double dim_z;
double thickness;
- Volume sideA;
- Volume sideB;
- PlacedVolume pvSideA;
- PlacedVolume pvSideB;
+ VisAttr vis;
Layers layers;
+ SensitiveDetector sensDet;
+ SensitiveDetector ringSD;
+ DetElement side[2];
+ /// Helper function to allow assignment
+ DetElement& operator=(const DetElement& d) { return this->DetElement::operator=(d); }
} m_endcap;
+ struct Shield {
+ Material material;
+ VisAttr vis;
+ double thickness;
+ } m_shield;
int m_numLayer;
+ double m_front_thickness;
double m_lateral_face_thickness;
double m_fiber_thickness;
+ double m_support_thickness;
double m_guard_ring_size;
double m_cell_size;
double m_cables_gap;
double m_endcap_center_box_size;
double m_centerTubDisplacement;
VisAttr m_radiatorVis;
+ LimitSet m_limits;
+
+ std::vector<Volume> EC_TowerSlabs;
+ std::vector<Volume> EC_Towers[3];
+ std::vector<Position> EC_TowerXYCenters;
+ LCDD* lcdd;
+ std::string name;
+ DetElement self;
+ };
- vector<Volume> EC_TowerSlabs;
- vector<Volume> EC_Towers[3];
- vector<Position> EC_TowerXYCenters;
-
+ struct SEcal03 : public SEcal03Data {
/// Standard constructor
- ECAL(LCDD& l, const xml_det_t& e, SensitiveDetector& s);
-
+ SEcal03() : SEcal03Data() {}
+ /// Detector construction function
+ DetElement construct(LCDD& lcdd, xml_det_t e);
/// Simple access to the radiator thickness depending on the layer
double radiatorThickness(int layer_id) const;
-
/// Build Endcap Standard Module
- Volume buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSolid, const Volume& siVol, const Rotation& rot);
-
+ Volume buildEndcap(DetElement det,bool Zminus, const Endcap& endcap, const Solid& siSolid, const Volume& siVol, const Rotation& rot);
/// Build barrel volume
- Volume buildBarrelStave(const Barrel_t& barrel);
-
+ std::pair<DetElement,Volume> buildBarrelStave(const Barrel& barrel);
/// Build slab
- Volume buildSlab(bool barrel, const Dimension dim);
-
+ Volume buildSlab(bool barrel, const Dimension dim, SensitiveDetector& sd);
// Build radiator solid
- Volume buildRadiator(const string& name, const Dimension& dim, const Material& mat);
+ Volume buildRadiator(const std::string& name, const Dimension& dim, const Material& mat);
};
-}
+}}
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
#define N_FIBERS_ALVOULUS 3
#define N_FIBERS_W_STRUCTURE 2
-
-ECAL::ECAL(LCDD& l, const xml_det_t& e, SensitiveDetector& s)
- : DetElement(e.nameStr(), e.id()), lcdd(l), x_det(e), x_barrel(0),
- x_endcap(0), x_support(0), x_front(0), x_shield(0), sens_det(s)
-{
- // EC_Initialize() builds the Slabs and the radiator plates for the several towers
- // to be placed latter into each module
- string det_nam = name();
- Volume motherVol = lcdd.pickMotherVolume(*this);
- /*
- <detector id="<id>" name="<name>" type="<type>"
- inner_r="TPC_outer_radius+Ecal_Tpc_gap"
- lateral_face_thickness="Ecal_lateral_face_thickness"
- fiber_thickness="Ecal_fiber_thickness"
- guard_ring_size="Ecal_guard_ring_size"
- cell_size="Ecal_cell_size"
- alveolus_gap="Ecal_Alveolus_Air_Gap"
- >
- <support thickness="Ecal_support_thickness"/>
- <front thickness="Ecal_front_face_thickness"/>
- <pcbshield thickness="Ecal_Slab_PCB_thickness + Ecal_Slab_copper_thickness + Ecal_Slab_shielding"/>
-
- <layer id="1" repeat="Ecal_nlayers1" thickness="Ecal_radiator_thickness1" material="Ecal_radiator_material"/>
- <layer id="2" repeat="Ecal_nlayers2" thickness="Ecal_radiator_thickness2" material="Ecal_radiator_material"/>
- <layer id="3" repeat="Ecal_nlayers3" thickness="Ecal_radiator_thickness3" material="Ecal_radiator_material"/>
- <slab h_fiber_thickness="Ecal_H_fiber_thickness" sensitive="Ecal_sensitive_material">
- <shielding thickness="Ecal_Slab_shielding"/>
- <copper thickness="Ecal_Slab_copper_thickness"/>
- <ground> thickness="Ecal_Slab_ground_thickness"/>
- <glue thickness="Ecal_Slab_glue_gap"/>
- <sensitive thickness="Ecal_Si_thickness"/>
- </slab>
- <barrel zhalf="Ecal_Barrel_halfZ" towers="Ecal_barrel_number_of_towers"/>
- <endcap extra_size="Ecal_endcap_extra_size" center_box_size="Ecal_endcap_center_box_size"/>
- </detector>
- */
- x_support = x_det.child(Unicode("support"));
- x_barrel = x_det.child(_X(barrel));
- x_endcap = x_det.child(_X(endcap));
- x_front = x_det.child(Unicode("front"));
- x_shield = x_det.child(Unicode("pcbshield"));
-
- m_xml_slab = x_det.child(Unicode("slab"));
- m_xml_slab.shield = m_xml_slab.child(Unicode("shielding"));
- m_xml_slab.copper = m_xml_slab.child(Unicode("copper"));
- m_xml_slab.sensitive = m_xml_slab.child(Unicode("sensitive"));
- m_xml_slab.ground = m_xml_slab.child(Unicode("ground"));
- m_xml_slab.glue = m_xml_slab.child(Unicode("glue"));
-
- double endcap_extra_size = x_endcap.attr<double>(Unicode("extra_size"));
- double crossing_angle = x_det.attr<double>(Unicode("crossing_angle"));
- m_cables_gap = x_det.attr<double>(Unicode("cables_gap"));
- m_lateral_face_thickness = x_det.attr<double>(Unicode("lateral_face_thickness"));
- m_fiber_thickness = x_det.attr<double>(Unicode("fiber_thickness"));
- m_cell_size = x_det.attr<double>(Unicode("cell_size"));
- m_guard_ring_size = x_det.attr<double>(Unicode("guard_ring_size"));
-
- m_slab.vis = lcdd.visAttributes("EcalSlabVis");
- m_slab.h_fiber_thickness = m_xml_slab.attr<double>(Unicode("h_fiber_thickness"));
- m_slab.shield_thickness = m_xml_slab.shield.thickness();
- m_slab.ground_thickness = m_xml_slab.ground.thickness();
- m_slab.ground_mat = lcdd.material(m_xml_slab.ground.materialStr());
- m_slab.ground_vis = lcdd.visAttributes("EcalSlabGroundVis");
- m_slab.sensitive_thickness = m_xml_slab.sensitive.thickness();
- m_slab.sensitive_mat = lcdd.material(m_xml_slab.sensitive.materialStr());
- m_slab.sensitive_vis = lcdd.visAttributes("EcalSlabSensitiveVis");
- m_slab.copper_thickness = m_xml_slab.copper.thickness();
- m_slab.copper_mat = lcdd.material(m_xml_slab.copper.materialStr());
- m_slab.glue_thickness = m_xml_slab.glue.thickness();
- m_slab.wafer_vis = lcdd.visAttributes("EcalWaferVis");
- m_radiatorVis = lcdd.visAttributes("EcalRadiatorVis");
+#define _U(text) Unicode(#text)
+
+
+/// Detector construction function
+DetElement SEcal03::construct(LCDD& l, xml_det_t x_det) {
+ lcdd = &l;
+ name = x_det.nameStr();
+ self.assign(dynamic_cast<Value<TNamed,SEcal03>*>(this),name,x_det.typeStr());
+ self._data().id = x_det.id();
+ xml_comp_t x_param = x_det.child(_U(param));
+ xml_comp_t x_barrel = x_det.child(_X(barrel));
+ xml_comp_t x_endcap = x_det.child(_X(endcap));
+ xml_comp_t x_shield = x_det.child(_U(pcbshield));
+ xml_comp_t m_xml_slab = x_det.child(_U(slab));
+ xml_comp_t m_xml_slab_shield = m_xml_slab.child(_U(shielding));
+ xml_comp_t m_xml_slab_copper = m_xml_slab.child(_U(copper));
+ xml_comp_t m_xml_slab_sensitive= m_xml_slab.child(_U(sensitive));
+ xml_comp_t m_xml_slab_ground = m_xml_slab.child(_U(ground));
+ xml_comp_t m_xml_slab_glue = m_xml_slab.child(_U(glue));
+
+ double endcap_extra_size = x_endcap.attr<double>(_U(extra_size));
+ double crossing_angle = x_param.attr<double>(_U(crossing_angle));
+ Assembly assembly(name+"_assembly");
+ // Hosting volume
+ Volume motherVol = lcdd->pickMotherVolume(self);
+ // User limits for this sub detector
+ m_limits = lcdd->limitSet(x_det.limitsStr());
+
+ m_cables_gap = x_param.attr<double>(_U(cables_gap));
+ m_lateral_face_thickness = x_param.attr<double>(_U(lateral_face_thickness));
+ m_fiber_thickness = x_param.attr<double>(_U(fiber_thickness));
+ m_cell_size = x_param.attr<double>(_U(cell_size));
+ m_guard_ring_size = x_param.attr<double>(_U(guard_ring_size));
+ m_front_thickness = x_param.attr<double>(_U(front_face_thickness));
+ m_support_thickness = x_param.attr<double>(_U(support_thickness));
+
+ m_shield.vis = lcdd->visAttributes(x_shield.visStr());
+ m_shield.material = lcdd->material(x_shield.materialStr());
+ m_shield.thickness = x_shield.thickness();
+
+ m_slab.vis = lcdd->visAttributes("EcalSlabVis");
+ m_slab.h_fiber_thickness = m_xml_slab.attr<double>(_U(h_fiber_thickness));
+ m_slab.shield_thickness = m_xml_slab_shield.thickness();
+ m_slab.ground_thickness = m_xml_slab_ground.thickness();
+ m_slab.ground_mat = lcdd->material(m_xml_slab_ground.materialStr());
+ m_slab.ground_vis = lcdd->visAttributes("EcalSlabGroundVis");
+ m_slab.sensitive_thickness = m_xml_slab_sensitive.thickness();
+ m_slab.sensitive_mat = lcdd->material(m_xml_slab_sensitive.materialStr());
+ m_slab.sensitive_vis = lcdd->visAttributes("EcalSlabSensitiveVis");
+ m_slab.copper_thickness = m_xml_slab_copper.thickness();
+ m_slab.copper_mat = lcdd->material(m_xml_slab_copper.materialStr());
+ m_slab.glue_thickness = m_xml_slab_glue.thickness();
+ m_slab.wafer_vis = lcdd->visAttributes("EcalWaferVis");
+ m_radiatorVis = lcdd->visAttributes("EcalRadiatorVis");
size_t i=0;
for(xml_coll_t c(x_det,_X(layer)); c; ++c, ++i) {
xml_comp_t layer(c);
m_layers[i].nLayer = layer.repeat();
m_layers[i].thickness = layer.thickness();
- m_layers[i].rad_mat = lcdd.material(layer.materialStr());
+ m_layers[i].rad_mat = lcdd->material(layer.materialStr());
m_barrel.layers.push_back(&m_layers[i]);
m_endcap.layers.push_back(&m_layers[i]);
}
m_numLayer = m_layers[0].nLayer + m_layers[1].nLayer + m_layers[2].nLayer;
m_slab.total_thickness = m_slab.shield_thickness + m_slab.copper_thickness +
- x_shield.thickness() + m_slab.sensitive_thickness + m_slab.glue_thickness +
- m_slab.ground_thickness + x_det.attr<double>(Unicode("alveolus_gap")) / 2;
+ m_shield.thickness + m_slab.sensitive_thickness + m_slab.glue_thickness +
+ m_slab.ground_thickness + x_param.attr<double>(_U(alveolus_gap)) / 2;
double total_thickness =
m_layers[0].nLayer * m_layers[0].thickness +
m_layers[1].nLayer * m_layers[1].thickness +
m_layers[2].nLayer * m_layers[2].thickness +
int(m_numLayer/2) * (N_FIBERS_W_STRUCTURE * 2 * m_fiber_thickness) + // fiber around W struct layers
(m_numLayer + 1) * (m_slab.total_thickness + (N_FIBERS_ALVOULUS + 1 ) * m_fiber_thickness) + // slabs plus fiber around and inside
- x_support.thickness() + x_front.thickness();
-
- m_barrel.numTowers = x_barrel.attr<int>(Unicode("towers"));
+ m_support_thickness + m_front_thickness;
+
+ m_barrel.numTowers = x_barrel.attr<int>(_U(towers));
m_barrel.thickness = total_thickness;
m_barrel.inner_r = x_barrel.inner_r();
- m_barrel.z = 2 * x_barrel.zhalf() / 5.;
+ m_barrel.dim_z = 2 * x_barrel.zhalf() / 5.;
m_barrel.bottom = 2. * std::tan(M_PI/8.) * m_barrel.inner_r + 2.* std::tan(M_PI/8.) * m_barrel.thickness;
m_barrel.top = 2. * std::tan(M_PI/8.) * m_barrel.inner_r; //m_barrel.bottom - 2.0 * m_barrel.thickness;
- m_barrel.radiatorMaterial = lcdd.material(x_barrel.attr<string>(Unicode("radiatorMaterial")));
+ m_barrel.vis = lcdd->visAttributes(x_barrel.visStr());
+ m_barrel.material = lcdd->material(x_barrel.materialStr());
+ m_barrel.radiatorMaterial = lcdd->material(x_barrel.attr<string>(_U(radiatorMaterial)));
- double module_z_offset = m_barrel.z*2.5 + m_cables_gap + m_barrel.thickness/2.;
+ double module_z_offset = m_barrel.dim_z*2.5 + m_cables_gap + m_barrel.thickness/2.;
+ m_endcap.vis = lcdd->visAttributes(x_endcap.visStr());
m_endcap.thickness = total_thickness;
m_endcap.rmin = x_barrel.inner_r();
m_endcap.rmax = x_barrel.inner_r() + m_endcap.thickness + endcap_extra_size;
- m_endcap.z = module_z_offset;
+ m_endcap.dim_z = module_z_offset;
- m_alveolus.z = (m_barrel.z - 2. * m_lateral_face_thickness) / m_barrel.numTowers -
+ m_alveolus.z = (m_barrel.dim_z - 2. * m_lateral_face_thickness) / m_barrel.numTowers -
2 * N_FIBERS_ALVOULUS * m_fiber_thickness -
2 * m_slab.h_fiber_thickness -
2 * m_slab.shield_thickness;
- double siPlateSize = x_endcap.attr<double>(Unicode("center_box_size")) -
+ double siPlateSize = x_endcap.attr<double>(_U(center_box_size)) -
2.0 * m_lateral_face_thickness -
- 2.0 * x_endcap.attr<double>(Unicode("ring_gap"));
+ 2.0 * x_endcap.attr<double>(_U(ring_gap));
- m_centerTubDisplacement = m_endcap.z * std::tan(crossing_angle/2000);
- m_center_tube = Tube(m_endcap.rmin,m_endcap.rmin,0.);
- Box ec_ringSiBox (siPlateSize/2.,siPlateSize/2.,m_slab.sensitive_thickness/2.);
+ m_centerTubDisplacement = m_endcap.dim_z * std::tan(crossing_angle/2000);
+ m_center_tube = Tube(0,m_endcap.rmin,total_thickness);
+ Box ec_ringSiBox (siPlateSize/2,siPlateSize/2,m_slab.sensitive_thickness/2);
SubtractionSolid ec_ringSiSolid1(ec_ringSiBox,m_center_tube,Position(m_centerTubDisplacement,0,0),Rotation());
- Volume ec_ringSiVol1 (det_nam+"_ec_ring_volPlus",ec_ringSiSolid1,m_slab.sensitive_mat);
+ Volume ec_ringSiVol1 ("ring_plus",ec_ringSiSolid1,m_slab.sensitive_mat);
SubtractionSolid ec_ringSiSolid2(ec_ringSiBox,m_center_tube,Position(-m_centerTubDisplacement,0,0),Rotation());
- Volume ec_ringSiVol2 (det_nam+"_ec_ring_volNeg",ec_ringSiSolid2,m_slab.sensitive_mat);
+ Volume ec_ringSiVol2 ("ring_minus",ec_ringSiSolid2,m_slab.sensitive_mat);
//=================================================
//
@@ -291,13 +275,13 @@ ECAL::ECAL(LCDD& l, const xml_det_t& e, SensitiveDetector& s)
// While the towers have the same shape use the same logical volumes and parameters.
if(last_dim_x != m_alveolus.x) {
//printf("%s> Build slab x=%f y=%f\n",name().c_str(),m_alveolus.x,m_alveolus.y);
- EC_TowerSlabs.push_back(buildSlab(false,Dimension(m_alveolus.y,m_slab.total_thickness,m_alveolus.x)));
+ EC_TowerSlabs.push_back(buildSlab(false,Dimension(m_alveolus.y,m_slab.total_thickness,m_alveolus.x),m_endcap.sensDet));
if( m_layers[0].nLayer > 0 )
- EC_Towers[0].push_back(buildRadiator(det_nam+"_T1",Dimension(m_alveolus.y,m_layers[0].thickness,m_alveolus.x),m_layers[0].rad_mat));
+ EC_Towers[0].push_back(buildRadiator(name+"_T1",Dimension(m_alveolus.y,m_layers[0].thickness,m_alveolus.x),m_layers[0].rad_mat));
if( m_layers[1].nLayer > 0 )
- EC_Towers[1].push_back(buildRadiator(det_nam+"_T2",Dimension(m_alveolus.y,m_layers[1].thickness,m_alveolus.x),m_layers[1].rad_mat));
+ EC_Towers[1].push_back(buildRadiator(name+"_T2",Dimension(m_alveolus.y,m_layers[1].thickness,m_alveolus.x),m_layers[1].rad_mat));
if( m_layers[2].nLayer > 0 )
- EC_Towers[2].push_back(buildRadiator(det_nam+"_T3",Dimension(m_alveolus.y,m_layers[2].thickness,m_alveolus.x),m_layers[2].rad_mat));
+ EC_Towers[2].push_back(buildRadiator(name+"_T3",Dimension(m_alveolus.y,m_layers[2].thickness,m_alveolus.x),m_layers[2].rad_mat));
last_dim_x = m_alveolus.x;
}
else {
@@ -309,12 +293,50 @@ ECAL::ECAL(LCDD& l, const xml_det_t& e, SensitiveDetector& s)
EC_TowerXYCenters.push_back(Position(-(y_curr + m_alveolus.y/2.),-(-m_alveolus.x/2. + x_right),0));
}
- m_endcap.sideA = buildEndcap(false,m_endcap,ec_ringSiSolid1,ec_ringSiVol1,Rotation());
- m_endcap.pvSideA = motherVol.placeVolume(m_endcap.sideA,Position(0,0,module_z_offset));
- m_endcap.sideB = buildEndcap(true,m_endcap,ec_ringSiSolid2,ec_ringSiVol2,Rotation());
- m_endcap.pvSideA = motherVol.placeVolume(m_endcap.sideB,Position(0,0,-module_z_offset),Rotation(M_PI,0,0));
-
- m_barrel.stave = buildBarrelStave(m_barrel);
+ // Setup the sensitive detectors for barrel, endcap+ and endcap-
+ SensitiveDetector sd = m_barrel.sensDet = SensitiveDetector("EcalBarrel");
+ Readout ro = lcdd->readout(x_barrel.readoutStr());
+ sd.setHitsCollection(ro.name());
+ sd.setReadout(ro);
+ lcdd->addSensitiveDetector(sd);
+
+ sd = m_endcap.sensDet = SensitiveDetector("EcalEndcapRings");
+ ro = lcdd->readout(x_endcap.attr<string>(_U(ring_readout)));
+ sd.setHitsCollection(ro.name());
+ sd.setReadout(ro);
+ lcdd->addSensitiveDetector(sd);
+
+ sd = m_endcap.ringSD = SensitiveDetector("EcalEndcap");
+ ro = lcdd->readout(x_endcap.readoutStr());
+ sd.setHitsCollection(ro.name());
+ sd.setReadout(ro);
+ lcdd->addSensitiveDetector(sd);
+
+ ec_ringSiVol1.setSensitiveDetector(m_endcap.ringSD);
+ ec_ringSiVol2.setSensitiveDetector(m_endcap.ringSD);
+ ec_ringSiVol1.setVisAttributes(m_endcap.vis);
+ ec_ringSiVol2.setVisAttributes(m_endcap.vis);
+ ec_ringSiVol1.setLimitSet(m_limits);
+ ec_ringSiVol2.setLimitSet(m_limits);
+
+ Volume vol;
+ PlacedVolume pv;
+ DetElement det;
+ m_barrel = DetElement(self,"barrel",ECALBARREL);
+ m_endcap = DetElement(self,"endcaps",0);
+ det = DetElement(m_endcap,"plus",ECALENDCAPPLUS);
+ vol = buildEndcap(det,false,m_endcap,ec_ringSiSolid1,ec_ringSiVol1,Rotation());
+ pv = assembly.placeVolume(vol,Position(0,0,module_z_offset));
+ det.setPlacement(pv);
+ m_endcap.side[SIDE_PLUS] = det;
+
+ det = DetElement(m_endcap,"minus",ECALENDCAPMINUS);
+ vol = buildEndcap(det,true,m_endcap,ec_ringSiSolid2,ec_ringSiVol2,Rotation());
+ pv = assembly.placeVolume(vol,Position(0,0,-module_z_offset),Rotation(M_PI,0,0));
+ det.setPlacement(pv);
+ m_endcap.side[SIDE_MINUS] = det;
+
+ std::pair<DetElement,Volume> stave = buildBarrelStave(m_barrel);
// BarrelStandardModule placements
double X = 0;//m_barrel.thickness * std::tan(M_PI/4.);
double Y = m_barrel.inner_r + m_barrel.thickness/2;
@@ -322,25 +344,49 @@ ECAL::ECAL(LCDD& l, const xml_det_t& e, SensitiveDetector& s)
::memset(&m_barrel.module[0][0],0,sizeof(m_barrel.module));
m_barrel.numStaves = 8;
m_barrel.numModules = 5;
- for(int stav_id=1; stav_id < 9; ++stav_id) {
+
+ DetElement mod_det;
+ for(int stav_id=1; stav_id < 9; ++stav_id) {
+ int stave_ident = ECALBARREL*100+stav_id;
+ DetElement stave_det(m_barrel,_toString(stav_id,"stave%d"),stave_ident);
+ Assembly staveVol(_toString(stav_id,"stave%d"));
for(int mod_id=1; mod_id < 6; ++mod_id) {
double phi = (stav_id-1) * M_PI/4.;
- double z_offset = (2.*mod_id-6.)*m_barrel.z/2.;
+ double z_offset = (2.*mod_id-6.)*m_barrel.dim_z/2.;
Rotation rot(M_PI/2,phi,0);
Position pos(X,Y,z_offset);
- PlacedVolume pv = motherVol.placeVolume(m_barrel.stave,pos.rotateZ(phi),rot);
+ int mod_ident = stave_ident+mod_id;
+ pv = staveVol.placeVolume(stave.second,pos.rotateZ(phi),rot);
pv.addPhysVolID("barrel",ECALBARREL*100+stav_id*10+mod_id);
- m_barrel.module[stav_id-1][mod_id-1] = pv;
+ if ( !mod_det.isValid() ) { // same as if(first) ...
+ stave.first->SetName(_toString(mod_id,"module%d").c_str());
+ stave.first._data().id = mod_ident;
+ mod_det = stave.first;
+ }
+ else {
+ mod_det = stave.first.clone(_toString(mod_id,"module%d"),mod_ident);
+ }
+ stave_det.add(mod_det);
+ mod_det.setPlacement(pv);
+ m_barrel.module[stav_id-1][mod_id-1] = mod_det;
::printf("Place Barrel stave:%d,%d Phi:%.4f Pos: %.2f %.2f %.2f \n",stav_id,mod_id,phi,
pos.x,pos.y,pos.z);
//theBarrelSD->SetStaveRotationMatrix(stav_id,phi);
//theBarrelSD->SetModuleZOffset(mod_id,z_offset);
}
+ pv = assembly.placeVolume(staveVol);
+ stave_det.setPlacement(pv);
}
+ assembly.setVisAttributes(lcdd->visAttributes(x_det.visStr()));
+ pv = motherVol.placeVolume(assembly);
+ m_barrel.setPlacement(pv);
+ m_endcap.setPlacement(pv);
+ self.setPlacement(pv);
+ return self;
}
/// Simple access to the radiator thickness depending on the layer
-double ECAL::radiatorThickness(int layer_id) const {
+double SEcal03::radiatorThickness(int layer_id) const {
if(layer_id <= m_layers[0].nLayer)
return m_layers[0].thickness;
else if(layer_id <= (m_layers[0].nLayer + m_layers[1].nLayer))
@@ -349,27 +395,25 @@ double ECAL::radiatorThickness(int layer_id) const {
}
// Build radiator solid
-Volume ECAL::buildRadiator(const string& name, const Dimension& dim, const Material& mat) {
+Volume SEcal03::buildRadiator(const string& name, const Dimension& dim, const Material& mat) {
Box box(dim.x/2,dim.z/2,dim.y/2);
//::printf("%s> Radiator: %.2f %.2f %.2f\n",name.c_str(),dim.x/2,dim.z/2,dim.y/2);
- Volume vol(name+"_radiator",box,mat);
+ Volume vol("radiator",box,mat);
vol.setVisAttributes(m_radiatorVis);
return vol;
}
/// Build slab
-Volume ECAL::buildSlab(bool barrel, Dimension dim) {
- string nam = name();
-
+Volume SEcal03::buildSlab(bool barrel, Dimension dim, SensitiveDetector& sd) {
// Slab solid: hx, hz, hy
Box slabBox(dim.x/2,dim.z/2,dim.y/2);
- Volume slabVol(nam+"_slab",slabBox,lcdd.air());
+ Volume slabVol("slab",slabBox,lcdd->air());
slabVol.setVisAttributes(m_slab.vis);
double y_slab_floor = -dim.y/2;
// Ground plate
Box groundBox(dim.x/2,dim.z/2,m_slab.ground_thickness/2);
- Volume groundVol(nam+"_ground",groundBox,m_slab.ground_mat);
+ Volume groundVol("ground",groundBox,m_slab.ground_mat);
groundVol.setVisAttributes(m_slab.ground_vis);
slabVol.placeVolume(groundVol,Position(0,0,y_slab_floor+m_slab.ground_thickness/2));
y_slab_floor += m_slab.ground_thickness;
@@ -377,7 +421,7 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
// Si layer
// we place a big plane of Si and inside it the Si wafers, to simplify the gard ring placements
Box siBox(dim.x/2,dim.z/2,m_slab.sensitive_thickness/2);
- Volume siVol(nam+"_sensitive",siBox,m_slab.sensitive_mat);
+ Volume siVol("sensitive",siBox,m_slab.sensitive_mat);
siVol.setVisAttributes(m_slab.sensitive_vis);
slabVol.placeVolume(siVol,Position(0,0,y_slab_floor + m_slab.sensitive_thickness/2));
@@ -400,13 +444,13 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
double wafer_dim_z = N_cells_in_Z * cell_dim_z;
Box waferBox(wafer_dim_x/2, wafer_dim_z/2, m_slab.sensitive_thickness/2);
- Volume waferVol(nam+"_wafer",waferBox,m_slab.sensitive_mat);
+ Volume waferVol("wafer",waferBox,m_slab.sensitive_mat);
waferVol.setVisAttributes(m_slab.wafer_vis);
- // waferVol.setLimits(pULimits);
- // waferVol->SetSensitiveDetector(theSD);
+ waferVol.setSensitiveDetector(sd);
+ waferVol.setLimitSet(m_limits);
//::printf("%s> ...slab dim: %.4f x %.4f x %.4f Grnd:%.4f %.4f %.4f Sensitive:%.4f %.4f %.4f \n",
- // nam.c_str(), dim.x/2,dim.z/2,dim.y/2,dim.x/2,dim.z/2,m_slab.ground_thickness/2,
+ // name.c_str(), dim.x/2,dim.z/2,dim.y/2,dim.x/2,dim.z/2,m_slab.ground_thickness/2,
// dim.x/2,dim.z/2,m_slab.sensitive_thickness/2);
// As the same method builds both barrel and end cap
@@ -417,7 +461,7 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
int num_wafer_x = int(floor(dim.x / real_wafer_size_x));
double wafer_pos_x = -dim.x/2 + m_guard_ring_size + wafer_dim_x /2 ;
// ::printf("%s> ...Building slab for barrel: wafer dim: %.4f x %.4f real:%.4f [%d] pos:%4.f\n",
- // nam.c_str(), wafer_dim_x, wafer_dim_z, real_wafer_size_x, num_wafer_x, wafer_pos_x);
+ // name.c_str(), wafer_dim_x, wafer_dim_z, real_wafer_size_x, num_wafer_x, wafer_pos_x);
for (int iwaf = 1; iwaf < num_wafer_x + 1; iwaf++) {
double wafer_pos_z = -dim.z/2 + m_guard_ring_size + wafer_dim_z /2;
for (int n_wafer_z = 1; n_wafer_z < 3; n_wafer_z++) {
@@ -438,10 +482,10 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
int N_cells_x_remaining = int(floor((resting_dim_x - 2 * m_guard_ring_size)/cell_dim_x));
wafer_dim_x = N_cells_x_remaining * cell_dim_x;
Box waf_box(wafer_dim_x/2, wafer_dim_z/2, m_slab.sensitive_thickness/2);
- Volume waf_vol(nam+"_wafer_rest",waf_box,m_slab.sensitive_mat);
- //waf_vol.setLimits(pULimits);
+ Volume waf_vol("wafer_rest",waf_box,m_slab.sensitive_mat);
waf_vol.setVisAttributes(m_slab.wafer_vis);
- //waf_vol->SetSensitiveDetector(theSD);
+ waf_vol.setSensitiveDetector(sd);
+ waf_vol.setLimitSet(m_limits);
real_wafer_size_x = wafer_dim_x + 2 * m_guard_ring_size;
wafer_pos_x = -dim.x/2 + num_wafer_x * real_wafer_size_x + real_wafer_size_x/2;
@@ -458,7 +502,7 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
double wafer_pos_x = -dim.z/2 + m_guard_ring_size + wafer_dim_z /2;
int num_wafer_x = int(floor(dim.z/real_wafer_size_x));
//::printf("%s> ...Building slab for endcap: wafer dim: %.4f x %.4f real:%.4f [%d] pos:%4.f\n",
- // nam.c_str(), wafer_dim_x, wafer_dim_z, real_wafer_size_x, num_wafer_x, wafer_pos_x);
+ // name.c_str(), wafer_dim_x, wafer_dim_z, real_wafer_size_x, num_wafer_x, wafer_pos_x);
for (int iwaf_x=1; iwaf_x < num_wafer_x + 1; iwaf_x++) {
double wafer_pos_z = -dim.x/2 + m_guard_ring_size + wafer_dim_x /2;
for (int iwaf_z = 1; iwaf_z < 3; ++iwaf_z) {
@@ -476,10 +520,10 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
int N_cells_x_remaining = int(std::floor((resting_dim_x - 2 * m_guard_ring_size)/cell_dim_z));
wafer_dim_x = N_cells_x_remaining * cell_dim_z;
Box waf_box(wafer_dim_z/2, wafer_dim_x/2, m_slab.sensitive_thickness/2);
- Volume waf_vol(nam+"_wafer", waf_box, m_slab.sensitive_mat);
+ Volume waf_vol("wafer", waf_box, m_slab.sensitive_mat);
waf_vol.setVisAttributes(m_slab.sensitive_vis);
- //waf_vol.setLimits(pULimits);
- //waf_vol->SetSensitiveDetector(theSD);
+ waf_vol.setSensitiveDetector(sd);
+ waf_vol.setLimitSet(m_limits);
wafer_pos_x = -dim.z/2 + num_wafer_x * real_wafer_size_x + (wafer_dim_x + 2 * m_guard_ring_size)/2;
real_wafer_size_x = wafer_dim_x + 2 * m_guard_ring_size;
double wafer_pos_z = -dim.x/2 + m_guard_ring_size + wafer_dim_z /2;
@@ -495,23 +539,23 @@ Volume ECAL::buildSlab(bool barrel, Dimension dim) {
y_slab_floor += (m_slab.sensitive_thickness+m_slab.glue_thickness);
// The PCB layer, the copper and the shielding are placed as a big G10 layer,
// as the copper and the shielding ones are very tiny.
- Box pcbShieldBox(dim.x/2,dim.z/2,x_shield.thickness()/2);
- Volume pcbShieldVol(nam+"_shield",pcbShieldBox,lcdd.material(x_shield.materialStr()));
- pcbShieldVol.setVisAttributes(lcdd.visAttributes(x_shield.visStr()));
- slabVol.placeVolume(pcbShieldVol,Position(0,0,y_slab_floor+x_shield.thickness()/2));
+ Box pcbShieldBox(dim.x/2,dim.z/2,m_shield.thickness/2);
+ Volume pcbShieldVol("pcbshield",pcbShieldBox,m_shield.material);
+ pcbShieldVol.setVisAttributes(m_shield.vis);
+ slabVol.placeVolume(pcbShieldVol,Position(0,0,y_slab_floor+m_shield.thickness/2));
return slabVol;
}
/// Build Endcap Standard Module
-Volume ECAL::buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSolid, const Volume& siVol, const Rotation& rot) {
- // While waiting for more geometric details,
- // build a simple Endcap using a fiber polyhedra
- // and substract the center box
- string nam = name();
+Volume SEcal03::buildEndcap(DetElement det,bool Zminus, const Endcap& endcap,
+ const Solid& siSolid, const Volume& siVol, const Rotation& rot)
+{
+ // While waiting for more geometric details, build a simple Endcap using
+ // a fiber polyhedra and substract the center box
PolyhedraRegular hedra(8, 0, endcap.rmax, m_endcap.thickness);
SubtractionSolid solid(hedra, m_center_tube, Position(), rot);
- Volume endcap_vol(nam+"_endcap", solid,lcdd.material(x_shield.materialStr()));
- endcap_vol.setVisAttributes(lcdd.visAttributes(x_endcap.visStr()));
+ Volume endcap_vol("endcap", solid,m_shield.material);
+ endcap_vol.setVisAttributes(m_endcap.vis);
//----------------------------------------------------
// Radiator plates in the EndCap structure also as polyhedra,
@@ -523,39 +567,39 @@ Volume ECAL::buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSol
double r_inner = m_lateral_face_thickness;
double r_outer = endcap.rmax - m_lateral_face_thickness;
double box_dim = (m_endcap_center_box_size - m_lateral_face_thickness)/ 2.;
- VisAttr ring_vis = lcdd.visAttributes("EcalRingVis");
+ VisAttr ring_vis = lcdd->visAttributes("EcalRingVis");
if(m_layers[0].nLayer > 0 ) {
PolyhedraRegular hedra_rad(8, r_inner, r_outer, m_layers[0].thickness);
SubtractionSolid sol_rad(hedra_rad, m_center_tube, Position(), rot);
- vol_radL1 = Volume(nam+"_ECL1_radiator",sol_rad, m_layers[0].rad_mat);
+ vol_radL1 = Volume("ECL1_radiator",sol_rad, m_layers[0].rad_mat);
vol_radL1.setVisAttributes(m_radiatorVis);
// plate for slab in ring
Box box_ring(box_dim,box_dim, m_layers[0].thickness/2);
SubtractionSolid sol_ring(box_ring,m_center_tube,Position(), rot);
- vol_ringL1 = Volume(nam+"_ECL1_ring",sol_ring,m_layers[0].rad_mat);
+ vol_ringL1 = Volume(name+"_ECL1_ring",sol_ring,m_layers[0].rad_mat);
vol_ringL1.setVisAttributes(ring_vis);
}
if(m_layers[1].nLayer > 0 ) {
PolyhedraRegular hedra_rad(8, r_inner, r_outer, m_layers[1].thickness);
SubtractionSolid sol_rad(hedra_rad, m_center_tube, Position(), rot);
- vol_radL2 = Volume(nam+"_ECL2_radiator",sol_rad, m_layers[0].rad_mat);
+ vol_radL2 = Volume("ECL2_radiator",sol_rad, m_layers[0].rad_mat);
vol_radL2.setVisAttributes(m_radiatorVis);
// plate for slab in ring
Box box_ring(box_dim,box_dim, m_layers[1].thickness/2);
SubtractionSolid sol_ring(box_ring,m_center_tube,Position(), rot);
- vol_ringL2 = Volume(nam+"_ECL2_ring",sol_ring,m_layers[0].rad_mat);
+ vol_ringL2 = Volume(name+"_ECL2_ring",sol_ring,m_layers[0].rad_mat);
vol_ringL2.setVisAttributes(ring_vis);
}
if(m_layers[2].nLayer > 0 ) {
PolyhedraRegular hedra_rad(8, r_inner, r_outer, m_layers[2].thickness);
SubtractionSolid sol_rad(hedra_rad, m_center_tube, Position(), rot);
- vol_radL3 = Volume(nam+"_ECL3_radiator",sol_rad, m_layers[0].rad_mat);
+ vol_radL3 = Volume("ECL3_radiator",sol_rad, m_layers[0].rad_mat);
vol_radL3.setVisAttributes(m_radiatorVis);
// plate for slab in ring
Box box_ring(box_dim,box_dim, m_layers[2].thickness/2);
SubtractionSolid sol_ring(box_ring,m_center_tube,Position(), rot);
- vol_ringL3 = Volume(nam+"_ECL3_ring",sol_ring,m_layers[2].rad_mat);
+ vol_ringL3 = Volume(name+"_ECL3_ring",sol_ring,m_layers[2].rad_mat);
vol_ringL3.setVisAttributes(ring_vis);
}
@@ -565,7 +609,7 @@ Volume ECAL::buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSol
// We count the layers starting from IP and from 1, so odd layers should be
// inside slabs and even ones on the structure.
- double z_floor = -m_endcap.thickness/2 + x_front.thickness() + N_FIBERS_ALVOULUS * m_fiber_thickness;
+ double z_floor = -m_endcap.thickness/2 + m_front_thickness + N_FIBERS_ALVOULUS * m_fiber_thickness;
//
// ATTENTION, TWO LAYERS PER LOOP AS THERE IS ONE INSIDE THE ALVEOLUS.
//
@@ -578,9 +622,10 @@ Volume ECAL::buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSol
PlacedVolume pv;
//num_layers = 2;
for(int layer_id = 1; layer_id <= num_layers; layer_id+=2) {
+
// place the tower layer for the four modules
double rad_thickness = m_layers[0].thickness;
- //::printf("%s> installing layer %d....\n",name(),layer_id);
+ //::printf("%s> installing layer %d....\n",name,layer_id);
rad_thickness = radiatorThickness(layer_id);
if(layer_id <= m_layers[0].nLayer) {
vol_ring = vol_ringL1;
@@ -684,22 +729,22 @@ Volume ECAL::buildEndcap(bool Zminus, const Endcap_t& endcap, const Solid& siSol
}
/// Barrel Standard Module
-Volume ECAL::buildBarrelStave(const Barrel_t& barrel) {
- string nam = name();
- Trapezoid barrelTrd(barrel.bottom/2, barrel.top/2, barrel.z/2, barrel.z/2, barrel.thickness/2);
- Volume barrelVol(nam+"_barrel",barrelTrd,lcdd.material(x_barrel.materialStr()));
- barrelVol.setVisAttributes(lcdd.visAttributes(x_barrel.visStr()));
+pair<DetElement,Volume> SEcal03::buildBarrelStave(const Barrel& barrel) {
+ DetElement staveDet("stave",0);
+ Trapezoid staveTrd(barrel.bottom/2, barrel.top/2, barrel.dim_z/2, barrel.dim_z/2, barrel.thickness/2);
+ Volume staveVol("stave",staveTrd,m_barrel.material);
+ staveVol.setVisAttributes(m_barrel.vis);
// We count the layers starting from IP and from 1, so odd layers should be inside slabs and
// even ones on the structure.
// The structure W layers are here big plans, as the gap between each W plate is too small
// to create problems. The even W layers are part of H structure placed inside the alveolus.
- double y_floor = x_front.thickness() + N_FIBERS_ALVOULUS * m_fiber_thickness;
+ double y_floor = m_front_thickness + N_FIBERS_ALVOULUS * m_fiber_thickness;
double z_pos;
PlacedVolume pv;
for(int layer_id = 1; layer_id < m_numLayer+1; layer_id+=2) {// ATTENTION, TWO LAYERS PER LOOP
- // build and place the several Alveolus with
- // the slabs and the radiator layer inside.
+ DetElement layerDet(staveDet,_toString(layer_id,"layer%d"),layer_id);
+ // build and place the several Alveolus with the slabs and the radiator layer inside.
double rad_thick = radiatorThickness(layer_id);
double alveolus_dim_y = 2 * m_slab.total_thickness + rad_thick + 2 * m_fiber_thickness;
@@ -709,23 +754,22 @@ Volume ECAL::buildBarrelStave(const Barrel_t& barrel) {
// To simplify we place each slab and the radiator layer directly into the fiber module.
//
// Build a slab:
- Volume slabVol = buildSlab(true,Dimension(alveolus_dim_x,m_slab.total_thickness,m_alveolus.z));
+ Volume slabVol = buildSlab(true,Dimension(alveolus_dim_x,m_slab.total_thickness,m_alveolus.z),m_barrel.sensDet);
// Place the Slab and radiator inside the H, here directly into the module fiber as the
// H structure is also built in fiber.
- double z_tower_center = -barrel.z /2 + m_lateral_face_thickness
+ double z_tower_center = -barrel.dim_z /2 + m_lateral_face_thickness
+ m_fiber_thickness * N_FIBERS_ALVOULUS + m_slab.shield_thickness
+ m_slab.h_fiber_thickness + m_alveolus.z /2;
Dimension radDim1(alveolus_dim_x,rad_thick,m_alveolus.z);
- Volume radVol1 = buildRadiator(nam+"_barrel_radiator1",radDim1,barrel.radiatorMaterial);
+ Volume radVol1 = buildRadiator("radiator1",radDim1,barrel.radiatorMaterial);
for (int itow = m_barrel.numTowers; itow > 0; --itow ) {
- y_fl = y_floor;
+ y_fl = y_floor;
x_off = 0; // to be calculed
y_off = y_fl - barrel.thickness/2 + m_slab.total_thickness/2;
-
// Place First Slab
- pv = barrelVol.placeVolume(slabVol,Position(x_off,z_tower_center,y_off),Rotation(M_PI,0,0));
+ pv = staveVol.placeVolume(slabVol,Position(x_off,z_tower_center,y_off),Rotation(M_PI,0,0));
pv.addPhysVolID("tower",itow * 1000 + layer_id);
#if 0
if (itow == Ecal_barrel_number_of_towers) {
@@ -739,13 +783,13 @@ Volume ECAL::buildBarrelStave(const Barrel_t& barrel) {
// Radiator layer "inside" alveolus
y_off = -barrel.thickness/2 + y_fl + rad_thick/2.;
- pv = barrelVol.placeVolume(radVol1,Position(0,z_tower_center,y_off));
+ pv = staveVol.placeVolume(radVol1,Position(0,z_tower_center,y_off));
pv.addPhysVolID("tower",itow * 1000 + layer_id);
y_fl += rad_thick + m_fiber_thickness;
y_off = -barrel.thickness/2 + y_fl + m_slab.total_thickness/2;
// Second Slab: starts from bottom to up
- pv = barrelVol.placeVolume(radVol1,Position(0,z_tower_center,y_off));
+ pv = staveVol.placeVolume(radVol1,Position(0,z_tower_center,y_off));
pv.addPhysVolID("tower",itow * 1000 + layer_id + 1);
#if 0
if (itow == Ecal_barrel_number_of_towers) {
@@ -769,20 +813,19 @@ Volume ECAL::buildBarrelStave(const Barrel_t& barrel) {
// Build and place the structure radiator layer into the module
double radiator_dim_x = barrel.bottom - 2*(y_floor+rad_thick)*std::tan(M_PI/8);
- double radiator_dim_z = barrel.z - 2.*m_lateral_face_thickness - 2*N_FIBERS_W_STRUCTURE * m_fiber_thickness;
+ double radiator_dim_z = barrel.dim_z - 2.*m_lateral_face_thickness - 2*N_FIBERS_W_STRUCTURE * m_fiber_thickness;
Dimension radDim2(radiator_dim_x,rad_thick,radiator_dim_z);
- Volume radVol2 = buildRadiator(nam+"barrel_radiator2",radDim2,barrel.radiatorMaterial);
- pv = barrelVol.placeVolume(radVol2,Position(0,0,-barrel.thickness/2+y_floor+rad_thick/2));
+ Volume radVol2 = buildRadiator("radiator2",radDim2,barrel.radiatorMaterial);
+ pv = staveVol.placeVolume(radVol2,Position(0,0,-barrel.thickness/2+y_floor+rad_thick/2));
// update the y_floor
y_floor += (rad_thick + (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE) * m_fiber_thickness);
}
- return barrelVol;
+ return make_pair(staveDet,staveVol);
}
-static Ref_t create(LCDD& lcdd, const xml_h& elt, SensitiveDetector& sens) {
- ECAL ecal(lcdd,elt,sens);
- return ecal;
+static Ref_t create_detector(LCDD& lcdd, const xml_h& element) {
+ return (new Value<TNamed,SEcal03>())->construct(lcdd,element);
}
-DECLARE_DETELEMENT(Tesla_SEcal03,create);
+DECLARE_SUBDETECTOR(Tesla_SEcal03,create_detector);
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp
index e6a30fb29..b4057d80e 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp
@@ -85,7 +85,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
vxd.assign(vxd_data,name,x_det.typeStr());
vxd_data->id = x_det.id();
- Assembly detector_vol(name+"_vol");
+ Assembly assembly(name+"_vol");
Volume motherVol = lcdd.pickMotherVolume(vxd);
@@ -181,7 +181,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
double r = layer.radius + (layer.isEven() ? thickness+layer.gap : -thickness);
double z = ldd_len + end_electronics_zhalf + ldd_gap/2.;
- layer_vol.placeVolume(vol,ZylinderPos(r,offset_phi+side_band_electronics_width,phi,z), Rotation(PIby2,phi,0.));
+ layer_vol.placeVolume(vol,ZylinderPos(r,offset_phi+side_band_electronics_width,phi, z), Rotation(PIby2,phi,0.));
layer_vol.placeVolume(vol,ZylinderPos(r,offset_phi+side_band_electronics_width,phi,-z),Rotation(PIby2,phi,0.));
}
}
@@ -243,7 +243,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
pv = layer_vol.placeVolume(active_layer_vol,ZylinderPos(r,offset_phi+side_band_electronics_width,phi,-z),Rotation(PIby2,phi,0.));
pv.addPhysVolID("layer",layer.id);
}
- detector_vol.placeVolume(layer_vol);
+ assembly.placeVolume(layer_vol);
}
//****************************************
@@ -254,14 +254,14 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
Tube support_tube(shell_rmin,shell_rmin+shell_thickess,shell_zhalf);
Volume support_vol (name+"_support",support_tube,support_mat);
support_vol.setVisAttributes(lcdd, x_supp.visStr());
- detector_vol.placeVolume(support_vol);
+ assembly.placeVolume(support_vol);
// ************support endplates************
Tube endplate_tube(x_endpl.rmin(),x_endpl.rmax(),x_endpl.zhalf());
Volume endplate_vol (name+"_endcap",endplate_tube,support_mat);
endplate_vol.setVisAttributes(lcdd, x_endpl.visStr());
- detector_vol.placeVolume(endplate_vol,Position(0,0, (shell_zhalf + x_endpl.zhalf())));
- detector_vol.placeVolume(endplate_vol,Position(0,0,-(shell_zhalf + x_endpl.zhalf())));
+ assembly.placeVolume(endplate_vol,Position(0,0, (shell_zhalf + x_endpl.zhalf())));
+ assembly.placeVolume(endplate_vol,Position(0,0,-(shell_zhalf + x_endpl.zhalf())));
// ************support endplates for the layer 1************
Tube endplate_support_tube(x_endp1.rmin(),x_endp1.rmax(),x_endp1.zhalf());
@@ -269,8 +269,8 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
const LayerParams::Ladders& l1 = vxd_data->layers[0].ladders;
double z = l1.len + 2.0*end_electronics_zhalf + shell_thickess/2. + (be_ladder_block_length*2) ;
endplate_support_vol.setVisAttributes(lcdd, x_endp1.visStr());
- detector_vol.placeVolume(endplate_support_vol,Position(0,0, z));
- detector_vol.placeVolume(endplate_support_vol,Position(0,0,-z));
+ assembly.placeVolume(endplate_support_vol,Position(0,0, z));
+ assembly.placeVolume(endplate_support_vol,Position(0,0,-z));
#if 0
//*** Cryostat ***************************************************************
@@ -323,7 +323,9 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
return true;
#endif
- PlacedVolume lpv = motherVol.placeVolume(detector_vol);
+
+ assembly.setVisAttributes(lcdd.visAttributes(x_det.visStr()));
+ PlacedVolume lpv = motherVol.placeVolume(assembly);
return vxd;
}
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_coil00_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_coil00_geo.cpp
index 05acb78a3..9b9c0a7e1 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_coil00_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_coil00_geo.cpp
@@ -17,15 +17,16 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
xml_det_t x_det = e;
string name = x_det.nameStr();
DetElement sdet(name,x_det.id());
- Assembly assembly(name+"_assembly");
+ Assembly assembly(name);
xml_comp_t x_coil = x_det.child(Unicode("coil"));
Tube coilTub(x_coil.inner_r(),x_coil.outer_r(),x_coil.zhalf());
- Volume coilVol(name+"_coil",coilTub,lcdd.material(x_coil.materialStr()));
+ Volume coilVol("coil",coilTub,lcdd.material(x_coil.materialStr()));
coilVol.setVisAttributes(lcdd.visAttributes(x_det.visStr()));
assembly.placeVolume(coilVol);
- lcdd.pickMotherVolume(sdet).placeVolume(assembly);
+ PlacedVolume pv=lcdd.pickMotherVolume(sdet).placeVolume(assembly);
+ sdet.setPlacement(pv);
return sdet;
}
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_ftd01_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_ftd01_geo.cpp
index 6521a6c49..0ff59c3e6 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_ftd01_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_ftd01_geo.cpp
@@ -3,6 +3,11 @@
// AIDA Detector description implementation for LCD
//--------------------------------------------------------------------
//
+// This subdetector is rather simple: Just a set of disk
+// perpendicular to the beam.
+// - No special user limits required for simulation.
+// -
+//
// Author : M.Frank
//
//====================================================================
@@ -12,21 +17,49 @@
using namespace std;
using namespace DD4hep;
using namespace DD4hep::Geometry;
+#define _U(text) Unicode(#text)
+
+/*
+ * Tesla namespace declaration
+ */
+namespace Tesla {
+
+ /** @class DiskExtension Ftd01.h Tesla/Ftd01.h
+ *
+ * Example how to use a detector element extension object
+ *
+ * @author M.Frank
+ * @version 1.0
+ */
+ struct DiskExtension {
+ PlacedVolume sensitive, support;
+ DiskExtension() {}
+ DiskExtension(const DiskExtension& c)
+ : sensitive(c.sensitive), support(c.support) {}
+ DiskExtension(const DiskExtension& c, DetElement& /* org */)
+ : sensitive(c.sensitive), support(c.support) {}
+ DiskExtension& operator=(const DiskExtension& c) {
+ sensitive=c.sensitive;
+ support=c.support;
+ return *this;
+ }
+ };
+}
static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens) {
xml_det_t x_det = e;
string name = x_det.nameStr();
Rotation reflect_rot(M_PI,0,0);
DetElement sdet(name,x_det.id());
- Assembly ftdVol(name+"_assembly");
+ Assembly ftdVol(name);
Volume motherVol = lcdd.pickMotherVolume(sdet);
- xml_comp_t x_disks = x_det.child(Unicode("disks"));
- xml_comp_t x_cables = x_det.child(Unicode("cables"));
- xml_comp_t x_cylinder = x_det.child(Unicode("cylinder"));
- xml_comp_t x_support = x_det.child(Unicode("support"));
- xml_comp_t x_inner_support = x_support.child(Unicode("inner"));
- xml_comp_t x_outer_support = x_support.child(Unicode("outer"));
+ xml_comp_t x_disks = x_det.child(_U(disks));
+ xml_comp_t x_cables = x_det.child(_U(cables));
+ xml_comp_t x_cylinder = x_det.child(_U(cylinder));
+ xml_comp_t x_support = x_det.child(_U(support));
+ xml_comp_t x_inner_support = x_support.child(_U(inner));
+ xml_comp_t x_outer_support = x_support.child(_U(outer));
VisAttr supportVis = lcdd.visAttributes(x_support.visStr());
VisAttr cablesVis = lcdd.visAttributes(x_cables.visStr());
@@ -35,44 +68,56 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
Material supportMat = lcdd.material(x_support.materialStr());
Material diskMat = lcdd.material(x_disks.materialStr());
- double si_thickness = x_disks.attr<double>(Unicode("si_thickness1"));
- double si_thickness2 = x_disks.attr<double>(Unicode("si_thickness2"));
+ double si_thickness = x_disks.attr<double>(_U(si_thickness1));
+ double si_thickness2 = x_disks.attr<double>(_U(si_thickness2));
double inner_support_thickness = x_inner_support.thickness();
double inner_support_length = x_inner_support.length();
double outer_support_thickness = x_outer_support.thickness();
double outer_support_length = x_outer_support.length();
struct Cylinder { double z_start, z_stop, r1, r2; } inner_cyl, outer_cyl;
-
PlacedVolume pv;
- for(xml_coll_t c(x_disks,Unicode("disk")); c; ++c) {
+ for(xml_coll_t c(x_disks,_U(disk)); c; ++c) {
+ typedef Tesla::DiskExtension _Ext;
xml_comp_t x_disk = c;
int id = x_disk.id();
double z_pos = x_disk.z();
double inner_r = x_disk.inner_r();
double outer_r = x_disk.outer_r();
+ DetElement disk_pos(sdet,_toString(id,"disk%d_neg"),id);
+ DetElement disk_neg(sdet,_toString(id,"disk%d_pos"),id);
+ _Ext *ext_pos=disk_pos.addExtension<_Ext>(new _Ext());
+ _Ext *ext_neg=disk_neg.addExtension<_Ext>(new _Ext());
{ //... Si sensitive
Tube tub(inner_r,outer_r,si_thickness/2.0);
- Volume vol(name+_toString(id,"_disk%d_Si"),tub,diskMat);
+ Volume vol(_toString(id,"_disk%d_Si"),tub,diskMat);
vol.setVisAttributes(lcdd.visAttributes(x_disk.visStr()));
+ // This is the sensitive element: add senssitive detector
+ vol.setSensitiveDetector(sens);
pv = ftdVol.placeVolume(vol,Position(0,0, z_pos));
pv.addPhysVolID("disk",id);
+ disk_pos.setPlacement(pv);
+ ext_pos->sensitive = pv;
pv = ftdVol.placeVolume(vol,Position(0,0,-z_pos));
pv.addPhysVolID("disk",-id);
+ disk_neg.setPlacement(pv);
+ ext_neg->sensitive = pv;
}
{ //... Support
Tube tub(inner_r,outer_r,inner_support_thickness);
- Volume vol(name+_toString(id,"_disk%d_Support"),tub,supportMat);
+ Volume vol(_toString(id,"_disk%d_support"),tub,supportMat);
double z = z_pos + si_thickness + inner_support_thickness;
vol.setVisAttributes(supportVis);
pv = ftdVol.placeVolume(vol,Position(0,0, z));
pv.addPhysVolID("disk",id);
+ ext_pos->support = pv;
pv = ftdVol.placeVolume(vol,Position(0,0,-z));
pv.addPhysVolID("disk",-id);
+ ext_neg->support = pv;
}
/* { //... Outer support rings
Tube tub(outer_r,outer_r+outer_support.thickness,outer_support_length);
- Volume vol(name+_toString(id,"disk%d_outer_support"),tub,supportMat);
+ Volume vol(_toString(id,"disk%d_outer_support"),tub,supportMat);
vol.setVisAttributes(supportVis);
pv = ftdVol.placeVolume(vol,Position(0,0, z_pos));
pv.addPhysVolID("disk",id);
@@ -114,16 +159,16 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
assert(zhalf>0);
Tube tub_cyl(outer_cyl.r1,outer_cyl.r1+outer_cyl_thickness+cables_thickness,zhalf);
- Volume vol_cyl(name+"_outerCylinder",tub_cyl,supportMat);
+ Volume vol_cyl("outerCylinder",tub_cyl,supportMat);
vol_cyl.setVisAttributes(cylinderVis);
pv = ftdVol.placeVolume(vol_cyl,Position(0,0,cyl_z_pos));
pv.addPhysVolID("side",1);
pv = ftdVol.placeVolume(vol_cyl,Position(0,0,-cyl_z_pos));
pv.addPhysVolID("side",-1);
-
+
/*
Tube tub_cables(outer_cyl.r1,outer_cyl.r1+cables_thickness,zhalf);
- Volume vol_cables(name+"_cables",tub_cables,cablesMat);
+ Volume vol_cables("cables",tub_cables,cablesMat);
vol_cables.setVisAttributes(cablesVis);
ftdVol.placeVolume(vol_cables,Position());
*/
@@ -137,7 +182,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
Cone cone_cyl(inner_cyl.r1-outer_cyl_thickness-cables_thickness,inner_cyl.r1,
inner_cyl.r2-outer_cyl_thickness-cables_thickness,inner_cyl.r2,zhalf);
- Volume vol_cyl(name+"_innerCables",cone_cyl,supportMat);
+ Volume vol_cyl("innerCables",cone_cyl,supportMat);
vol_cyl.setVisAttributes(cylinderVis);
pv = ftdVol.placeVolume(vol_cyl,Position(0,0,cyl_z_pos));
pv.addPhysVolID("side",1);
@@ -145,12 +190,13 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
pv.addPhysVolID("side",-1);
Cone cone_cables(inner_cyl.r1-cables_thickness,inner_cyl.r1,
- inner_cyl.r2-cables_thickness,inner_cyl.r2,zhalf);
- Volume vol_cables(name+"_innerCables",cone_cables,cablesMat);
+ inner_cyl.r2-cables_thickness,inner_cyl.r2,zhalf);
+ Volume vol_cables("coneCables",cone_cables,cablesMat);
vol_cables.setVisAttributes(cablesVis);
ftdVol.placeVolume(vol_cables);
}
- motherVol.placeVolume(ftdVol);
+ pv = motherVol.placeVolume(ftdVol);
+ sdet.setPlacement(pv);
return sdet;
}
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_hcal04_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_hcal04_geo.cpp
index 1e78c1508..3d23524d5 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_hcal04_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_hcal04_geo.cpp
@@ -7,233 +7,294 @@
//
//====================================================================
#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/Detector.h"
#include "TGeoTube.h"
-using namespace std;
-using namespace DD4hep;
-using namespace DD4hep::Geometry;
-
-#define _U(text) Unicode(#text)
-
namespace DD4hep {
namespace Geometry {
struct Hcal04Data : public DetElement::Object {
enum {HCALBARREL = 1, HCALENDCAPPLUS=2, HCALENDCAPMINUS=3 };
+ enum {SIDE_PLUS=0, SIDE_MINUS=1 };
- typedef Position Dimension;
- Material radiatorMat;
- string model;
- struct Barrel {
- Dimension bottom, middle, top;
- Dimension module;
- Dimension cells;
- double y1_for_x;
- double y2_for_x;
- double inner_r;
- int numLayer;
- } barrel;
-
- struct Layer : public Dimension {
+ struct Layer {
int id;
- union {
- struct { double y_offset, dim_x; } layer;
- struct { double z_offset, dim_z; } end_layer;
- struct { double z_offset, dim_z; } endcap_layer;
+ union Vals {
+ struct BL { double y_offset, dim_x, dim_z; } layer;
+ struct EL { double z_offset, dim_z; } end_layer;
+ struct EC { double z_offset, dummy; } endcap_layer;
} values;
- Dimension offset;
};
- struct Layers : public std::vector<Layer> {
- } barrel_layers, end_layers, endcap_layers;
-
+ struct Layers : public std::vector<Layer> { };
struct Stave {
int id;
double phi;
double inner_r;
double z_offset;
};
- struct Staves : public std::vector<Stave> {
- } staves;
-
+ struct Staves : public std::vector<Stave> { };
struct Module {
int id;
+ int type;
double z_offset;
};
- struct Modules : public std::vector<Module> {
- } modules;
-
- struct Chambers {
- double x, thickness, z;
- } chamber;
+ struct Modules : public std::vector<Module> { };
struct RPC {
double g10_thickness;
- double glass_thickness;
- double gas_thickness;
double spacer_thickness;
double spacer_gap;
- } rpc;
- double fiberGap;
- SensitiveDetector barrelSensitiveDetector;
- };
+ struct { double thickness; Material material; VisAttr vis; } radiator, glass, gas;
+ struct { double thickness, gap; } spacer;
+ } m_rpc;
+
+ struct Barrel : public DetElement {
+ double bottom_dim_x;
+ double middle_dim_x;
+ double top_dim_x;
+ double y1_for_x, y2_for_x;
+ double y1_for_z, y2_for_z, y3_for_z, top_end_dim_z;
+ double inner_r;
+ double module_dim_z;
+ double cell_dim_x, cell_dim_z;
+ double chamber_thickness;
+ double chamber_dim_z;
+ int numLayer;
+ Layers layers, end_layers;
+ Staves staves;
+ Modules modules;
+ SensitiveDetector sensRegular, sensEndModule;
+ /// Helper function to allow assignment
+ DetElement& operator=(const DetElement& d) { return this->DetElement::operator=(d); }
+ } m_barrel;
+
+ struct Endcap : public DetElement {
+ Layers layers;
+ double rmin, rmax, dz;
+ double chamber_thickness;
+ SensitiveDetector sensDet;
+ struct EndcapSide : public DetElement {
+ int id;
+ Position position;
+ DetElement& operator=(const DetElement& d)
+ { return this->DetElement::operator=(d); }
+ } side[2];
+ } m_endcap;
+
+ VisAttr m_scintVis;
+ VisAttr m_moduleVis;
+ VisAttr m_endModuleVis;
+ VisAttr m_endcapModuleVis;
+ VisAttr m_chamberVis;
+ Material m_scintMaterial;
+ Material m_radiatorMat;
+ LimitSet m_limits;
+ double m_fiberGap;
+ std::string m_model;
+ DetElement self;
+ LCDD* lcdd;
+ std::string name;
+ };
struct Hcal04 : public Hcal04Data {
- LCDD* lcdd;
- xml_det_t x_det;
- xml_comp_t x_barrel;
- xml_comp_t x_endcap;
- xml_comp_t x_bottom;
- xml_comp_t x_middle;
- xml_comp_t x_top;
- xml_comp_t x_cells;
- xml_comp_t x_module;
- xml_comp_t x_rpc;
- xml_comp_t x_rad;
- xml_comp_t x_glass;
- xml_comp_t x_param;
-
- VisAttr m_chamberVis, m_moduleVis;
- Material m_scintillatorMat;
-
- Hcal04()
- : Hcal04Data(), x_det(0), x_barrel(0), x_endcap(0), x_bottom(0), x_middle(0), x_top(0),
- x_cells(0), x_module(0), x_rpc(0), x_rad(0), x_glass(0), x_param(0) {}
-
- void construct(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens);
+ /// Default constructor
+ Hcal04() : Hcal04Data() {}
+ /// Detector construction function
+ DetElement construct(LCDD& lcdd, xml_det_t e);
/// Build and place Barrel Regular Modules
void buildBarrelRegularModules(Volume assembly);
+ /// Build and place Barrel End Modules
void buildBarrelEndModules(Volume assembly);
-
- // EndCap Modules
+ // Build and place EndCap Modules
void buildEndcaps(Volume assembly);
-
/// Build Box with RPC1 chamber
- Volume buildRPC1Box(const std::string& nam, Box box, const Layer& layer);
+ Volume buildRPC1Box(const std::string& nam, Box box, const Layer& layer, SensitiveDetector& sensdet);
};
}
}
-void Hcal04::construct(LCDD& l, const xml_h& e, SensitiveDetector& sens) {
- /*
- <constant name="Hcal_spacer_thickness" value="8*mm"/>
- <constant name="Hcal_nlayers" value="38"/>
- <constant name="Hcal_endcap_nlayers" value="38"/>
-
- <endcap nlayers="Hcal_endcap_nlayers" fiber_gap="Hcal_fiber_gap">
- <barrel sensitive_model="scintillator" nlayers="Hcal_nlayers">
- <top x=""/>
- <middle x=""/>
- <bottom x=""/>
- <module x=""/>
- <rpc g10_thickness="" glass_thickness="" gas_thickness="" spacer_thickness="Hcal_spacer_thickness" spacer_gap=""/>
- </barrel>
- */
- lcdd = &l;
- x_det = e;
- x_barrel = x_det.child(_U(barrel));
- x_endcap = x_det.child(_U(endcap));
- x_param = x_det.child(_U(param));
-
- x_bottom = x_det.child(Unicode("bottom"));
- x_middle = x_det.child(Unicode("middle"));
- x_top = x_det.child(Unicode("top"));
- x_cells = x_det.child(Unicode("cells"));
- x_module = x_det.child(Unicode("module"));
- x_rpc = x_det.child(Unicode("rpc"));
- x_rad = x_det.child(Unicode("rpc"));
-
- string nam = x_det.nameStr();
- Assembly assembly(nam+"_assembly");
-
- Volume motherVol = lcdd->pickMotherVolume(Ref_t(this));
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+
+#define _U(text) Unicode(#text)
+
+static double s_geo_tolerance = 1e-10;
+
+/// Detector construction function
+DetElement Hcal04::construct(LCDD& l, xml_det_t x_det) {
+ lcdd = &l;
+ name = x_det.nameStr();
+ self.assign(dynamic_cast<Value<TNamed,Hcal04>*>(this),name,x_det.typeStr());
+
+ xml_comp_t x_barrel = x_det.child(_U(barrel));
+ xml_comp_t x_endcap = x_det.child(_U(endcap));
+ xml_comp_t x_param = x_det.child(_U(param));
+ xml_comp_t x_rpc = x_det.child(_U(rpc));
+ xml_comp_t x_scintillator = x_det.child(_U(scintillator));
+ xml_comp_t x_module = x_barrel.child(_U(module));
+ xml_comp_t x_end_module = x_barrel.child(_U(end_module));
+ xml_comp_t x_endcap_module = x_endcap.child(_U(module));
+
+ Assembly assembly(name);
+ Volume motherVol = lcdd->pickMotherVolume(Ref_t(this));
+
// Visualisation attributes
- VisAttr vis = lcdd->visAttributes(x_det.visStr());
- m_moduleVis = lcdd->visAttributes("HcalVis");
- m_chamberVis = lcdd->visAttributes("HcalChamberVis");
- m_scintillatorMat = lcdd->material("polystyrene");
+ VisAttr vis = lcdd->visAttributes(x_det.visStr());
+ m_moduleVis = lcdd->visAttributes(x_module.visStr());
+ m_endModuleVis = lcdd->visAttributes(x_end_module.visStr());
+ m_endcapModuleVis = lcdd->visAttributes(x_endcap_module.visStr());
+ m_chamberVis = lcdd->visAttributes(x_param.attr<string>(_U(chamber_vis)));
+ m_scintVis = lcdd->visAttributes(x_scintillator.visStr());
+ m_scintMaterial = lcdd->material(x_scintillator.materialStr());
//--------- BarrelHcal Sensitive detector -----
- model = x_det.attr<string>(Unicode("model"));
- fiberGap = x_det.attr<double>(Unicode("fiber_gap"));
- radiatorMat = lcdd->material(x_rad.materialStr());
-
- barrel.numLayer = x_barrel.attr<int>(Unicode("num_layer"));
- barrel.bottom.x = x_bottom.x();
- barrel.middle.x = x_middle.x();
- barrel.top.x = x_top.x();
- barrel.module.x = x_module.x();
- barrel.y1_for_x = x_module.attr<double>(Unicode("y1_for_x"));
- barrel.y2_for_x = x_module.attr<double>(Unicode("y2_for_x"));
- //double chamber_tickness = x_params.attr<double>(Unicode("chamber_tickness"));
- barrel.cells.x = x_cells.x();
- barrel.cells.z = x_cells.z();
+ m_model = x_param.attr<string>(_U(sensitive_model));
+ m_fiberGap = x_param.attr<double>(_U(fiber_gap));
+ m_radiatorMat = lcdd->material(x_param.attr<string>(_U(radiator_material)));
+
+ m_barrel.chamber_thickness = x_barrel.attr<double>(_U(chamber_thickness));
+ m_barrel.numLayer = x_barrel.attr<int>(_U(num_layer));
+ m_barrel.inner_r = x_barrel.inner_r();
+
+ // Paremeters for regular barrel modules
+ m_barrel.chamber_dim_z = x_module.attr<double>(_U(chamber_dim_z));
+ m_barrel.module_dim_z = x_module.attr<double>(_U(dim_z));
+ m_barrel.bottom_dim_x = x_module.attr<double>(_U(bottom_dim_x));
+ m_barrel.middle_dim_x = x_module.attr<double>(_U(middle_dim_x));
+ m_barrel.top_dim_x = x_module.attr<double>(_U(top_dim_x));
+ m_barrel.y1_for_x = x_module.attr<double>(_U(y_dim1_for_x));
+ m_barrel.y2_for_x = x_module.attr<double>(_U(y_dim2_for_x));
+ m_barrel.cell_dim_x = x_module.attr<double>(_U(cell_dim_x));
+ m_barrel.cell_dim_z = x_module.attr<double>(_U(cell_dim_z));
+
+ // Parameters for barrel end-module
+ m_barrel.y1_for_z = x_end_module.attr<double>(_U(y_dim1_for_z));
+ m_barrel.y2_for_z = x_end_module.attr<double>(_U(y_dim2_for_z));
+ m_barrel.y3_for_z = x_end_module.attr<double>(_U(y_dim3_for_z));
+ m_barrel.top_end_dim_z = x_end_module.attr<double>(_U(top_end_dim_z));
-
// if RPC1 read the RPC parameters
- if ( model == "RPC1" ) {
- rpc.g10_thickness =x_rpc.attr<double>(Unicode("g10_thickness"));
- rpc.glass_thickness =x_rpc.attr<double>(Unicode("glass_thickness"));
- rpc.gas_thickness =x_rpc.attr<double>(Unicode("gas_thickness"));
- rpc.spacer_thickness =x_rpc.attr<double>(Unicode("spacer_thickness"));
- rpc.spacer_gap =x_rpc.attr<double>(Unicode("spacer_gap"));
+ if ( m_model == "RPC1" ) {
+ xml_comp_t x_rad = x_rpc.child(_U(radiator));
+ xml_comp_t x_gas = x_rpc.child(_U(gas));
+ xml_comp_t x_glass = x_rpc.child(_U(glass));
+ xml_comp_t x_spacer = x_rpc.child(_U(spacer));
+ m_rpc.spacer.thickness = x_spacer.thickness();
+ m_rpc.spacer.gap = x_spacer.gap();
+ m_rpc.radiator.thickness = x_rad.thickness();
+ m_rpc.radiator.material = lcdd->material(x_rad.materialStr());
+ m_rpc.gas.thickness = x_gas.thickness();
+ m_rpc.gas.material = lcdd->material(x_gas.materialStr());
+ m_rpc.gas.vis = lcdd->visAttributes(x_gas.visStr());
+ m_rpc.glass.thickness = x_glass.thickness();
+ m_rpc.glass.material = lcdd->material(x_glass.materialStr());
+ m_rpc.glass.vis = lcdd->visAttributes(x_glass.visStr());
}
{ // Read the barrel layers
+ Stave stave;
Layer layer;
- barrel_layers.clear();
+ Module module;
+ m_barrel.layers.clear();
for(xml_coll_t c(x_barrel.child(_U(layers)),_X(layer)); c; ++c) {
xml_comp_t l(c);
layer.id = l.id();
layer.values.layer.dim_x = l.dim_x();
layer.values.layer.y_offset = l.y_offset();
- barrel_layers.push_back(layer);
+ m_barrel.layers.push_back(layer);
}
- assert(barrel.numLayer != barrel_layers.size());
- }
- { // Read the barrel end-layers
- Layer layer;
- end_layers.clear();
+ assert(m_barrel.numLayer != m_barrel.layers.size());
+ // Read the barrel end-layers
+ m_barrel.end_layers.clear();
for(xml_coll_t c(x_barrel.child(_U(end_layers)),_U(end_layer)); c; ++c) {
xml_comp_t l(c);
layer.id = l.id();
layer.values.end_layer.dim_z = l.dim_z();
layer.values.end_layer.z_offset = l.z_offset();
- end_layers.push_back(layer);
+ m_barrel.end_layers.push_back(layer);
+ }
+ assert(m_barrel.numLayer != m_barrel.end_layers.size());
+ m_barrel.staves.clear();
+ for(xml_coll_t c(x_barrel.child(_X(staves)),_X(stave)); c; ++c) {
+ xml_comp_t s(c);
+ stave.id = s.id();
+ stave.phi = s.phi();
+ //stave.inner_r = s.inner_r();
+ //stave.z_offset = s.z_offset();
+ m_barrel.staves.push_back(stave);
+ }
+ m_barrel.modules.clear();
+ for(xml_coll_t c(x_barrel.child(_X(modules)),_X(module)); c; ++c) {
+ xml_comp_t m(c);
+ module.id = m.id();
+ module.type = m.attr<int>(_A(type));
+ module.z_offset = m.z_offset();
+ m_barrel.modules.push_back(module);
}
- assert(barrel.numLayer != end_layers.size());
}
- { // Read the endcap layers
+ { // Read the endcap structure
+ int cnt=0;
Layer layer;
- barrel_layers.clear();
+ for(xml_coll_t c(x_endcap.child(_U(positions)),_X(position)); c; ++c, ++cnt) {
+ xml_comp_t ec(c);
+ m_endcap.side[cnt].id = ec.id();
+ m_endcap.side[cnt].position = Position(ec.x(),ec.y(),ec.z());
+ }
+ m_endcap.rmin = x_endcap_module.rmin();
+ m_endcap.rmax = x_endcap_module.rmax();
+ m_endcap.dz = x_endcap_module.dz();
+ m_endcap.chamber_thickness = m_barrel.chamber_thickness;
+
+ cout << name << ": End cap: rmin=" << m_endcap.rmin << " rmax=" << m_endcap.rmax << " dz=" << m_endcap.dz << endl;
+ // Read the endcap layers
+ m_endcap.layers.clear();
for(xml_coll_t c(x_endcap.child(_X(layers)),_X(layer)); c; ++c) {
xml_comp_t l(c);
layer.id = l.id();
- layer.values.end_layer.z_offset = l.z_offset();
- endcap_layers.push_back(layer);
+ layer.values.endcap_layer.dummy = 0;
+ layer.values.endcap_layer.z_offset = l.z_offset();
+ m_endcap.layers.push_back(layer);
}
- assert(barrel.numLayer != end_layers.size());
- }
-
+ }
#if 0
// The cell boundaries does not really exist as G4 volumes. So,
// to avoid long steps over running several cells, the
// theMaxStepAllowed inside the sensitive material is the
// pad smaller x or z dimension.
- theMaxStepAllowed= std::min(barrel.cells.x,barrel.cells.z);
-
+ theMaxStepAllowed= std::min(m_barrel.cells.x,m_barrel.cells.z);
// Hcal barrel regular modules
- theBarrilRegSD = new SD(barrel.cells.x,barrel.cells.z,chamber_tickness,HCALBARREL,"HcalBarrelReg");
- RegisterSensitiveDetector(theBarrilRegSD);
-
+ theBarrilRegSD = new SD(m_barrel.cells.x,m_barrel.cells.z,chamber_tickness,HCALBARREL,"HcalBarrelReg");
// Hcal barrel end modules
- theBarrilEndSD = new SD(barrel.cells.x,barrel.cells.z,chamber_tickness,HCALBARREL,"HcalBarrelEnd");
- RegisterSensitiveDetector(theBarrilEndSD);
-
+ theBarrilEndSD = new SD(m_barrel.cells.x,m_barrel.cells.z,chamber_tickness,HCALBARREL,"HcalBarrelEnd");
// Hcal endcap modules
- theENDCAPEndSD = new HECSD(barrel.cells.x,barrel.cells.z,chamber_tickness,HCALENDCAPMINUS,"HcalEndCaps");
- RegisterSensitiveDetector(theENDCAPEndSD);
+ theENDCAPEndSD = new HECSD(m_barrel.cells.x,m_barrel.cells.z,chamber_tickness,HCALENDCAPMINUS,"HcalEndCaps");
#endif
+ m_barrel = DetElement(self,"barrel",HCALBARREL);
+
+ // Setup the sensitive detectors for barrel, endcap+ and endcap-
+ SensitiveDetector& sd = m_barrel.sensRegular = SensitiveDetector("HcalBarrelRegular");
+ Readout ro = lcdd->readout(x_module.readoutStr());
+ sd.setHitsCollection(ro.name());
+ sd.setReadout(ro);
+ lcdd->addSensitiveDetector(sd);
+
+ sd = m_barrel.sensEndModule = SensitiveDetector("HcalBarrelEndModule");
+ ro = lcdd->readout(x_end_module.readoutStr());
+ sd.setHitsCollection(ro.name());
+ sd.setReadout(ro);
+ lcdd->addSensitiveDetector(sd);
+
+ sd = m_endcap.sensDet = SensitiveDetector("HcalEndcap");
+ ro = lcdd->readout(x_endcap_module.readoutStr());
+ sd.setHitsCollection(ro.name());
+ sd.setReadout(ro);
+ lcdd->addSensitiveDetector(sd);
+
+ // User limits for this sub detector
+ m_limits = lcdd->limitSet(x_det.limitsStr());
+
// Barrel
buildBarrelRegularModules(assembly);
buildBarrelEndModules(assembly);
@@ -241,574 +302,324 @@ void Hcal04::construct(LCDD& l, const xml_h& e, SensitiveDetector& sens) {
// EndCap Modules
buildEndcaps(assembly);
- motherVol.placeVolume(assembly);
+ PlacedVolume pv = motherVol.placeVolume(assembly);
+ m_barrel.setPlacement(pv);
+ self.setPlacement(pv);
+ return self;
}
/// Build and place Barrel Regular Modules
-void Hcal04::buildBarrelRegularModules(Volume parent) {
- string nam = x_det.nameStr();
+void Hcal04::buildBarrelRegularModules(Volume assembly) {
+ DetElement module("module",0);
// Attention: on bâtit le module dans la verticale à cause du G4Trd et on le tourne avant de le positioner
- Trapezoid trdBottom(barrel.bottom.x/2, barrel.middle.x/2,barrel.module.z/2, barrel.module.z/2, barrel.y1_for_x/2);
- Trapezoid trdTop (barrel.middle.x/2, barrel.top.x/2, barrel.module.z/2, barrel.module.z/2, barrel.y2_for_x/2);
+ Trapezoid trdBottom(m_barrel.bottom_dim_x/2, m_barrel.middle_dim_x/2,m_barrel.module_dim_z/2, m_barrel.module_dim_z/2, m_barrel.y1_for_x/2);
+ Trapezoid trdTop (m_barrel.middle_dim_x/2, m_barrel.top_dim_x/2, m_barrel.module_dim_z/2, m_barrel.module_dim_z/2, m_barrel.y2_for_x/2);
- UnionSolid modSolid (trdBottom, trdTop, Position(0,0,(barrel.y1_for_x+barrel.y2_for_x)/2.));
- Volume modVolume(nam+"_module",modSolid,radiatorMat);
+ UnionSolid modSolid (trdBottom,trdTop,Position(0,0,(m_barrel.y1_for_x+m_barrel.y2_for_x)/2));
+ Volume modVolume("regModule",modSolid,m_radiatorMat);
modVolume.setVisAttributes(m_moduleVis);
- double chambers_y_off_correction = barrel.y2_for_x/2;
- double bottomDimY = barrel.y1_for_x/2;
-
- //G4UserLimits* pULimits= new G4UserLimits(theMaxStepAllowed);
+ double chambers_y_off_correction = m_barrel.y2_for_x/2;
+ double bottomDimY = m_barrel.y1_for_x/2;
PlacedVolume pv;
- double Xoff = 0;
- double Yoff = x_module.offset();
- for(Layers::const_iterator i=barrel_layers.begin(); i != barrel_layers.end(); ++i) {
- const Layer& layer = *i;
- double thickness = layer.y/2;
- Box chamberBox(layer.x/2,layer.y/2,layer.z/2);
+ for(Layers::const_iterator i=m_barrel.layers.begin(); i != m_barrel.layers.end(); ++i) {
+ const Layer& lay = *i;
+ DetElement det_layer(module,_toString(lay.id,"layer%d"),lay.id);
+ double dim_x = lay.values.layer.dim_x/2;
+ double thickness = m_barrel.chamber_thickness/2;
+
+ Box chamberBox(dim_x,m_barrel.chamber_dim_z/2,thickness);
Volume chamberVol;
- if ( model == "scintillator") {
+ if ( m_model == "scintillator") {
//fg: introduce (empty) fiber gap - should be filled with fibres and cables
- Box scintBox(layer.x/2,layer.z/2,(thickness - fiberGap)/2);
- Volume scintVol(nam+_toString(layer.id,"_scint%d"),scintBox,m_scintillatorMat);
- scintVol.setSensitiveDetector(barrelSensitiveDetector);
- scintVol.setVisAttributes(m_chamberVis);
- //scintVol.setAttributes(lcdd,"",x_slice.limitsStr(),x_slice.visStr());
- //scintVol.setLimits(pULimits);
- //scintVol->SetSensitiveDetector(theBarrilRegSD);
- chamberVol = Volume(nam+_toString(layer.id,"_chamber%d"),chamberBox,lcdd->air());
- pv = chamberVol.placeVolume(scintVol,Position(0,0,-fiberGap/2));
+ Box scintBox(dim_x,m_barrel.chamber_dim_z/2,thickness - m_fiberGap/2);
+ Volume scintVol(_toString(lay.id,"scint%d"),scintBox,m_scintMaterial);
+ scintVol.setSensitiveDetector(m_barrel.sensRegular);
+ scintVol.setVisAttributes(m_scintVis);
+ scintVol.setLimitSet(m_limits);
+ chamberVol = Volume(_toString(lay.id,"chamber%d"),chamberBox,lcdd->air());
+ pv = chamberVol.placeVolume(scintVol,Position(0,0,-m_fiberGap/2));
}
- else if (model == "RPC1") {
- string nam = x_det.nameStr()+_toString(layer.id,"_barrel_layer_%d");
- chamberVol = buildRPC1Box(nam,chamberBox,layer);
+ else if (m_model == "RPC1") {
+ chamberVol = buildRPC1Box(_toString(lay.id,"layer_%d"),chamberBox,lay,m_barrel.sensRegular);
}
else {
- throw runtime_error("Unknown sensitive model:"+model+" for detector hcal04");
+ throw runtime_error("Unknown sensitive model:"+m_model+" for detector hcal04");
}
chamberVol.setVisAttributes(m_chamberVis);
- const Position& pos = layer.offset;
- pv = modVolume.placeVolume(chamberVol,Position(pos.x,pos.z,pos.y+chambers_y_off_correction));
- pv.addPhysVolID("layer",layer.id);
- }
-
- double Y = barrel.inner_r+barrel.y1_for_x/2;
- for(Staves::const_iterator i=staves.begin(); i!=staves.end(); ++i) {
+ pv = modVolume.placeVolume(chamberVol,Position(0,0,lay.values.layer.y_offset+chambers_y_off_correction));
+ pv.addPhysVolID("layer",lay.id);
+ det_layer.setPlacement(pv);
+ }
+
+ DetElement det_mod;
+ double Y = m_barrel.inner_r+m_barrel.y1_for_x/2;
+ for(Staves::const_iterator i=m_barrel.staves.begin(); i!=m_barrel.staves.end(); ++i) {
const Stave& s = *i;
- Rotation rot(M_PI/2,s.phi,0);
- for(Modules::const_iterator j=modules.begin(); j!=modules.end(); ++j) {
+ Rotation rot(-M_PI/2,s.phi,0);
+ DetElement stave_det(m_barrel,_toString(s.id,"reg_stave%d"),s.id*10);
+ for(Modules::const_iterator j=m_barrel.modules.begin(); j!=m_barrel.modules.end(); ++j) {
const Module& m = *j;
- Position pos(0,Y,m.z_offset);
- pv = parent.placeVolume(modVolume,pos.rotateZ(s.phi),rot);
- pv.addPhysVolID("module",HCALBARREL*100+s.id*10+m.id);
+ if ( m.type == 1 ) {
+ Position pos(0,Y,m.z_offset);
+ if ( !det_mod.isValid() ) {
+ module._data().id = m.id;
+ module->SetName(_toString(m.id,"module%d").c_str());
+ det_mod = module;
+ }
+ else {
+ det_mod = module.clone(_toString(m.id,"module%d"),m.id);
+ }
+ pv = assembly.placeVolume(modVolume,pos.rotateZ(s.phi),rot);
+ pv.addPhysVolID("module",HCALBARREL*100+s.id*10+m.id);
+ stave_det.add(det_mod);
+ det_mod.setPlacement(pv);
+ }
}
}
}
/// Barrel End Modules
void Hcal04::buildBarrelEndModules(Volume assembly) {
-
-#if 0
- // End modules
- db->exec("select y1_for_z/2. AS YZ1H,2_for_z/2. AS YZ2H, y3_for_z/2. AS YZ3H, top_end_dim_z/2. AS TZ from barrel_end_module;");
- db->getTuple();
- double YZ1H = end_layers.y1_for_z/2;
- double YZ2H = end_layers.y2_for_z/2;
- double YZ3H = end_layers.y3_for_z/2;
- double TZ = end_layers.z;
- double chambers_y_off_correction = YZ3H;
-
- db->exec("select bottom_dim_x/2 AS BHX,midle_dim_x/2. AS MHX, top_dim_x/2 AS THX, y1_for_x/2. AS YX1H,y_dim2_for_x/2. AS YX2H,module_dim_z/2. AS DHZ from barrel_module,barrel_regular_module;");
- db->getTuple();
- double BHX = db->fetchDouble("BHX");
- double MHX = db->fetchDouble("MHX");
- double THX = db->fetchDouble("THX");
- double YX1H = db->fetchDouble("YX1H");
- double YX2H = db->fetchDouble("YX2H");
- double DHZ = db->fetchDouble("DHZ");
+ DetElement module("module",0);
+ double YZ1H = m_barrel.y1_for_z/2;
+ double YZ2H = m_barrel.y2_for_z/2;
+ double YZ3H = m_barrel.y3_for_z/2;
+ double TZ = m_barrel.top_end_dim_z/2;
+ double BHX = m_barrel.bottom_dim_x/2;
+ double MHX = m_barrel.middle_dim_x/2;
+ double THX = m_barrel.top_dim_x/2;
+ double YX1H = m_barrel.y1_for_x/2;
+ double YX2H = m_barrel.y2_for_x/2;
+ double DHZ = m_barrel.module_dim_z/2;
// Attention: on bâtit le module dans la verticale à cause des G4Trd et on le tourne avant de le positioner
- //
- // Base
-
- double MHXZ = barrel.bottom.x/2 + (end_layers.y1_for_z/2 + end_layers.y2_for_z/2) * (barrel.middle.x/2 - barrel.bottom.x/2)/barrel.y1_for_x/2;
- Trapezoid base1(barrel.bottom.x/2, MHXZ, barrel.module.z/2, barrelmodule.z/2,YZH1+YZH2);
- Trapezoid base2(MHXZ, barrel.middle.x/2,end_layers.z,end_layers.z,YX1H-(YZ1H+YZ2H));
+ double MHXZ = BHX+(YZ1H+YZ2H)*(MHX-BHX)/YX1H;
+ Trapezoid base1(BHX,MHXZ,DHZ,DHZ,YZ1H+YZ2H);
+ Trapezoid base2(MHXZ,MHX,TZ,TZ,YX1H-(YZ1H+YZ2H));
UnionSolid base(base1,base2,Position(0,TZ-DHZ,YX1H));
-
- Trapezoid topTrd(MHX,THX,TZ,TZ,YX2H);
+ Trapezoid topTrd(MHX,THX,TZ,TZ,YX2H);
UnionSolid trd(base,topTrd,Position(0,TZ-DHZ,2*YX1H-(YZ1H+YZ2H)+YX2H));
- double MHXZ1 = BHX+((YZ1H+YZ2H)-(TZ-DHZ))*(MHX-BHX)/YX1H;
+ double MHXZ1 = BHX+((YZ1H+YZ2H)-(TZ-DHZ))*(MHX-BHX)/YX1H;
double pDX = TZ-DHZ;
- double pDz = std::sqrt(4*YZ2H*YZ2H+pDX*pDX)/2.;
+ double pDz = std::sqrt(4*YZ2H*YZ2H+pDX*pDX)/2;
double pTheta = M_PI/2 - std::atan(2*pDz/pDX);
Trap trap(pDz,-pTheta,0,MHXZ1,s_geo_tolerance,s_geo_tolerance,0,MHXZ,pDX,pDX,0);
- UnionSolid ensemble(trd, trap,Rotation(0,0,M_PI/2),
- Position(0,DHZ+pDX-pDz*tan(pTheta),YZ1H+YZ2H-pDz));
- Volume endBarrelVol(nam+"barrelHcalModule",ensemble,radiatorMat);
- endBarrelVol.setVisAttributes(lcdd->visAttributes("HcalVis"));
+ UnionSolid ensemble(trd, trap,Position(0,DHZ+pDX-pDz*std::tan(pTheta),YZ1H+YZ2H-pDz),Rotation(0,0,M_PI/2));
+ Volume endBarrelVol("endModule",ensemble,m_radiatorMat);
+ endBarrelVol.setVisAttributes(m_endModuleVis);
// Chambers in the Hcal Barrel
//------------------------------------------------------------------------------------------------------
- //G4UserLimits* pULimits= new G4UserLimits(theMaxStepAllowed);
+ double chambers_y_off_correction = m_barrel.y3_for_z/2;
PlacedVolume pv;
- G4VisAttributes *dBarrelVolVisAtt = new G4VisAttributes(G4Colour(.2,.8,.2));
- VisAtt->SetForceWireframe(true);
-
-
- db->exec("select barrel_regular_layer.layer_id,chamber_dim_x/2. AS xdh,chamber_tickness/2. AS ydh,chamber_dim_z/2. AS zdh, fiber_gap from hcal,barrel_regular_layer,barrel_end_layer where barrel_regular_layer.layer_id = barrel_end_layer.layer_id ;");
- G4UserLimits* pULimits = new G4UserLimits(theMaxStepAllowed);
-
- for(size_t i=barrel_layers.begin(); i != barrel_layers.end(); ++i) {
-
- const Layer& blay = barrel_layers[i];
- const Layer& elay = end_layers[i];
- Box chamberBox(layer.x/2,elay.z/2,chamber.thickness);
- if( model == "scintillator" ) {
+ double ydh = m_barrel.chamber_thickness/2;
+ double zdh = m_barrel.chamber_dim_z/2;
+ for(size_t i=0; i < m_barrel.layers.size(); ++i) {
+ int layer_id = m_barrel.layers[i].id;
+ DetElement det_layer(module,_toString(layer_id,"layer%d"),layer_id);
+ const Layer::Vals::BL& blay = m_barrel.layers[i].values.layer;
+ const Layer::Vals::EL& elay = m_barrel.end_layers[i].values.end_layer;
+ double xdh = blay.dim_x/2;
+ Box chamberBox(xdh,zdh,ydh);
+ Volume chamberVol;
+ if( m_model == "scintillator" ) {
//fg: introduce (empty) fiber gap - should be filled with fibres and cables
- chamberVol = Volume(nam+_toString(i,"_chamber%d"),chamberBox,lcdd->air());
-
- double fiberGap = db->fetchDouble("fiber_gap") ;
- double scintHalfWidth = db->fetchDouble("ydh") - fiberGap / 2. ;
-
// fiber gap can't be larger than total chamber
- assert( scintHalfWidth > 0. ) ;
-
- G4Box * ScintSolid =
- new G4Box("ScintSolid",
- db->fetchDouble("xdh"), //hx
- db->fetchDouble("zdh"), //hz attention!
- scintHalfWidth ); //hy attention!
- G4LogicalVolume* ScintLog =
- new G4LogicalVolume(ScintSolid,
- CGAGeometryManager::GetMaterial("polystyrene"),
- "ScintLogical",
- 0, 0, pULimits);
- // only scinitllator is sensitive
- ScintLog->SetSensitiveDetector(theBarrilEndSD);
- int layer_id = db->fetchInt("layer_id") ;
- new MyPlacement(0, G4ThreeVector( 0,0, - fiberGap / 2. ), ScintLog,
- "Scintillator", ChamberLogical, false, layer_id);
- ChamberLog [ layer_id ] = ChamberLogical ;
+ assert( (ydh - m_fiberGap/2) > 0.);
+ Box scintBox(xdh,zdh,ydh - m_fiberGap / 2);
+ Volume scintVol(_toString(layer_id,"scint%d"),scintBox,m_scintMaterial);
+ scintVol.setSensitiveDetector(m_barrel.sensEndModule);
+ scintVol.setVisAttributes(m_scintVis);
+ scintVol.setLimitSet(m_limits);
+ chamberVol = Volume(_toString(layer_id,"chamber%d"),chamberBox,lcdd->air());
+ pv = chamberVol.placeVolume(scintVol,Position(0,0,-m_fiberGap/2));
}
- else if (SensitiveModel == "RPC1") {
- G4int layer_id = db->fetchInt("layer_id");
- ChamberLog [layer_id] =
- BuildRPC1Box(nam,ChamberSolid,theBarrilEndSD,layer_id,pULimits);
+ else if (m_model == "RPC1") {
+ string nam = _toString(layer_id,"layer_%d");
+ chamberVol = buildRPC1Box(nam,chamberBox,m_barrel.end_layers[i],m_barrel.sensEndModule);
}
- else Control::Abort("Invalid sensitive model in the dababase!",MOKKA_ERROR_BAD_DATABASE_PARAMETERS);
- ChamberLog[db->fetchInt("layer_id")]->SetVisAttributes(VisAtt);
- }
-
- // End Chamber Placements
- // module x and y offsets (needed for the SD)
- db->exec("select 0 AS module_x_offset, module_y_offset from barrel_module;");
- db->getTuple();
- double Xoff,Yoff;
- Xoff = db->fetchDouble("module_x_offset");
- Yoff = db->fetchDouble("module_y_offset");
-
- db->exec("select barrel_regular_layer.layer_id, 0. as chamber_x_offset,chamber_y_offset,chamber_z_offset as chamber_z_offset,chamber_dim_z/2 AS YHALF,chamber_dim_x/2. as XHALF from barrel_regular_layer,barrel_end_layer where barrel_regular_layer.layer_id = barrel_end_layer.layer_id;");
-
- while(db->getTuple()!=NULL){
- G4int layer_id = db->fetchInt("layer_id");
- new MyPlacement(0,
- G4ThreeVector(db->fetchDouble("chamber_x_offset"),
- db->fetchDouble("chamber_z_offset"),
- db->fetchDouble("chamber_y_offset")+
- chambers_y_off_correction),
- //!!attention!! y<->z
- ChamberLog [db->fetchInt("layer_id")],
- "ChamberBarrel",
- endBarrelVol,false,layer_id);
+ else {
+ throw runtime_error("Unknown sensitive model:"+m_model+" for detector hcal04");
+ }
+ chamberVol.setVisAttributes(m_chamberVis);
+ pv = endBarrelVol.placeVolume(chamberVol,Position(0,elay.z_offset,blay.y_offset+chambers_y_off_correction));
+ pv.addPhysVolID("layer",layer_id);
}
-
//------------------------------------------------------------------------------------------------------
- // // Barrel End Module placements
- db->exec("select stave_id,module_id,module_type,stave_phi_offset,inner_radius,module_z_offset from barrel,barrel_stave, barrel_module, barrel_modules where module_type = 2;"); // un module: AND module_id = 1 AND stave_id = 1
-
-
- // Take care of this return here: if is possible when building
- // the Hcal prototype single module, where there isn't end modules
- // at all !!!
- if(db->getTuple()==NULL) return;
-
- double Y;
- Y = db->fetchDouble("inner_radius")+YZ1H+YZ2H;
- G4int stave_inv [8] = {1,8,7,6,5,4,3,2};
- do {
- double phirot = db->fetchDouble("stave_phi_offset")*pi/180;
- G4RotationMatrix *rot=new G4RotationMatrix();
- double Z = db->fetchDouble("module_z_offset");
- double Xplace = -Y*sin(phirot);
- double Yplace = Y*cos(phirot);
- G4int stave_number = db->fetchInt("stave_id");
- rot->rotateX(pi*0.5); // on couche le module.
-
- if(Z>0) {
- rot->rotateZ(pi);
- Xplace = - Xplace;
- stave_number = stave_inv[stave_number-1];
+ // Barrel End Module placements
+ bool first = true;
+ double Y = m_barrel.inner_r+YZ1H+YZ2H;
+ int stave_inv [8] = {1,8,7,6,5,4,3,2};
+ for(Staves::const_iterator i=m_barrel.staves.begin(); i!=m_barrel.staves.end(); ++i) {
+ const Stave& s = *i;
+ DetElement stave_det(m_barrel,_toString(s.id,"end_stave%d"),s.id*10);
+ for(Modules::const_iterator j=m_barrel.modules.begin(); j!=m_barrel.modules.end(); ++j) {
+ const Module& m = *j;
+ if ( m.type == 2 ) {
+ int stave_id = m.z_offset>0 ? s.id : stave_inv[s.id-1];
+ Rotation rot(-M_PI/2,s.phi,(m.z_offset>0 ? M_PI : 0));
+ Position pos(0,Y,m.z_offset);
+ DetElement det_mod = first ? module : module.clone(_toString(m.id,"module%d"),m.id);
+ if (first) {
+ first = false;
+ module._data().id = m.id;
+ module->SetName(_toString(m.id,"module%d").c_str());
+ }
+ pv = assembly.placeVolume(endBarrelVol,pos.rotateZ(/*m.z_offset>0?s.phi:- */s.phi),rot);
+ pv.addPhysVolID("module",HCALBARREL*100+stave_id*10+m.id);
+ stave_det.add(det_mod);
+ det_mod.setPlacement(pv);
+ //theBarrilEndSD->SetStaveRotationMatrix(stave_id,s.phi);
+ //theBarrilEndSD->SetModuleZOffset(m.id,m.z_offset);
+ }
}
-
- rot->rotateY(phirot);
- new MyPlacement(rot,
- G4ThreeVector(Xplace,
- Yplace,
- Z),
- EnvLogHcalModuleBarrel,
- "BarrelHcalModule",
- MotherLog,
- false,
- HCALBARREL*100+stave_number*10+db->fetchInt("module_id"));
- theBarrilEndSD->SetStaveRotationMatrix(db->fetchInt("stave_id"),phirot);
- theBarrilEndSD->
- SetModuleZOffset(db->fetchInt("module_id"),
- db->fetchDouble("module_z_offset"));
- } while(db->getTuple()!=NULL);
-#endif
+ }
}
/// Build EndCap Modules
void Hcal04::buildEndcaps(Volume assembly) {
-
-
-#if 0
- db->exec("select module_radius AS pRMax, module_dim_z/2. AS pDz, center_box_size/2. AS pRMin from endcap_standard_module;");
- db->getTuple();
-
- double zPlane[2];
- zPlane[0]=-db->fetchDouble("pDz");
- zPlane[1]=-zPlane[0];
-
- double rInner[2],rOuter[2];
- rInner[0]=rInner[1]=db->fetchDouble("pRMin");
- rOuter[0]=rOuter[1]=db->fetchDouble("pRMax");
- G4Polyhedra *EndCapSolid=
- new G4Polyhedra("HcalEndCapSolid",
- 0.,
- 360.,
- 32,
- 2,
- zPlane,
- rInner,
- rOuter);
-
-
- G4VisAttributes *VisAtt = new G4VisAttributes(G4Colour(.8,.8,.2));
- VisAtt->SetForceWireframe(true);
- VisAtt->SetDaughtersInvisible(true);
- //VisAtt->SetForceSolid(true);
-
- G4LogicalVolume* EndCapLogical =
- new G4LogicalVolume(EndCapSolid,
- RadiatorMaterial,
- "EndCapLogical",
- 0, 0, 0);
- EndCapLogical->SetVisAttributes(VisAtt);
+ int n_edges = 8;
+ DetElement sdet("side_plus",HCALENDCAPPLUS);
+ PolyhedraRegular hedra(n_edges,m_endcap.rmin,m_endcap.rmax,m_endcap.dz*2);
+ Volume modVolume("endcap",hedra,m_radiatorMat);
+ modVolume.setVisAttributes(m_endcapModuleVis);
+ modVolume.setVisAttributes(m_endModuleVis);
// build and place the chambers in the Hcal Endcaps
- EndcapChambers(EndCapLogical);
-
- // Placements
-
- db->exec("select endcap_id,endcap_z_offset from endcap;");
-
- G4RotationMatrix *rotEffect=new G4RotationMatrix();
- rotEffect->rotateZ(pi/8.);
- G4int ModuleNumber = HCALENDCAPPLUS*100+16;
- double Z1=0;
- while(db->getTuple()!=NULL){
- Z1=db->fetchDouble("endcap_z_offset");
- new MyPlacement(rotEffect,
- G4ThreeVector(0.,
- 0.,
- Z1),
- EndCapLogical,
- "EndCapPhys",
- MotherLog,
- false,
- ModuleNumber);
- rotEffect=new G4RotationMatrix();
- rotEffect->rotateZ(pi/8.);
- rotEffect->rotateY(pi); // On inverse les endcaps
- ModuleNumber -= (HCALENDCAPPLUS-HCALENDCAPMINUS)*100 + 6;
- }
- theENDCAPEndSD->
- SetModuleZOffset(0,
- fabs(Z1));
- theENDCAPEndSD->
- SetModuleZOffset(6,
- fabs(Z1));
-#endif
-}
-#if 0
-void Hcal04::EndcapChambers(G4LogicalVolume* MotherLog) {
- // Chambers in the Hcal04::Endcaps
- // standard endcap chamber solid:
-
- db->exec("select chamber_radius AS pRMax, chamber_tickness/2. AS pDz, fiber_gap, center_box_size/2. AS pRMin from endcap_standard_module,hcal;");
- db->getTuple();
-
- // G4Polyhedra Envelope parameters
- G4int numSide = 32;
- G4int numZPlanes = 2;
-
- double zPlane[2];
- zPlane[0]=-db->fetchDouble("pDz");
- zPlane[1]=-zPlane[0];
-
- double rInner[2],rOuter[2];
- rInner[0]=rInner[1]=db->fetchDouble("pRMin");
- rOuter[0]=rOuter[1]=db->fetchDouble("pRMax");
-
- PolyHedraRegular hedra(2,endcap.rmin,endcap.rmax,endcap.z);
-
- // G4UserLimits* pULimits=new G4UserLimits(theMaxStepAllowed);
- // standard endcap chamber logical
-
-
- G4LogicalVolume* EndCapChamberLogical=0;
-
- if(SensitiveModel == "scintillator") {
+ PolyhedraRegular chamberSolid(n_edges,m_endcap.rmin,m_endcap.rmax,m_endcap.chamber_thickness);
+ Volume chamberVol;
+ if(m_model == "scintillator") {
//fg: introduce (empty) fiber gap - should be filled with fibres and cables
- Volume vol(
- EndCapChamberLogical =
- new G4LogicalVolume(EndCapChamberSolid,
- CGAGeometryManager::GetMaterial("air"),
- "EndCapChamberLogical",
- 0, 0, 0);
- double fiber_gap = db->fetchDouble("fiber_gap") ;
- double scintHalfWidth = db->fetchDouble("pDz") - fiber_gap / 2. ;
+ double scintHalfWidth = m_endcap.chamber_thickness - m_fiberGap/2;
+ double zplanes[2] = {-scintHalfWidth,scintHalfWidth};
// fiber gap can't be larger than total chamber
assert( scintHalfWidth > 0. ) ;
-
- double zPlaneScint[2];
- zPlaneScint[0]=-scintHalfWidth ;
- zPlaneScint[1]=-zPlaneScint[0];
- G4Polyhedra *EndCapScintSolid=new G4Polyhedra("EndCapScintSolid",
- phiStart,
- phiTotal,
- numSide,
- numZPlanes,
- zPlaneScint,
- rInner,
- rOuter);
- G4LogicalVolume* ScintLog =
- new G4LogicalVolume(EndCapScintSolid,
- CGAGeometryManager::GetMaterial("polystyrene"),
- "EndCapScintLogical",
- 0, 0, pULimits);
+ chamberVol = Volume("chamber",chamberSolid,lcdd->air());
+ PolyhedraRegular scintSolid(n_edges,m_endcap.rmin,m_endcap.rmax,zplanes);
+ Volume scintVol ("scintillator",scintSolid,m_scintMaterial);
+ scintVol.setVisAttributes(m_scintVis);
// only scinitllator is sensitive
- ScintLog->SetSensitiveDetector(theENDCAPEndSD);
- new MyPlacement(0, G4ThreeVector( 0,0, - fiber_gap / 2. ), ScintLog,
- "EndCapScintillator", EndCapChamberLogical, false, 0 );
+ //ScintLog->SetSensitiveDetector(theENDCAPEndSD);
+ chamberVol.placeVolume(scintVol,Position(0,0,-m_fiberGap));
}
- else if (SensitiveModel == "RPC1") {
- EndCapChamberLogical =
- BuildRPC1Polyhedra(EndCapChamberSolid,
- theENDCAPEndSD,
- phiStart,
- phiTotal,
- numSide,
- numZPlanes,
- zPlane,
- rInner,
- rOuter,
- pULimits);
+ else if (m_model == "RPC1") {
+ chamberVol = Volume("rpc1",chamberSolid,m_rpc.radiator.material);
+ PolyhedraRegular glassSolid(n_edges,m_endcap.rmin,m_endcap.rmax,m_rpc.glass.thickness);
+ Volume glassVol("glass",glassSolid,m_rpc.glass.material);
+ glassVol.setVisAttributes(m_rpc.glass.vis);
+
+ // build the gas gap
+ PolyhedraRegular gasSolid(n_edges,m_endcap.rmin,m_endcap.rmax,m_rpc.gas.thickness);
+ Volume gasVol("gas",gasSolid,m_rpc.gas.material);
+ gasVol.setVisAttributes(m_rpc.gas.vis);
+ gasVol.setSensitiveDetector(m_endcap.sensDet);
+ gasVol.setLimitSet(m_limits);
+
+ // placing the all.
+ // Z offset starts pointing to the chamber border.
+ double z_offset = m_endcap.dz;
+ // first glass after the g10_thickness
+ z_offset += m_rpc.radiator.thickness + m_rpc.glass.thickness/2.;
+ chamberVol.placeVolume(glassVol,Position(0,0,z_offset));
+ // set Z offset to the next first glass border
+ z_offset += m_rpc.glass.thickness/2;
+ // gas gap placing
+ z_offset += m_rpc.gas.thickness/2;
+ chamberVol.placeVolume(gasVol,Position(0,0,z_offset));
+ // set ZOffset to the next gas gap border
+ z_offset += m_rpc.gas.thickness/2;
+ // second glass, after the g10_thickness, the first glass and the gas gap.
+ z_offset += m_rpc.glass.thickness/2;
+ chamberVol.placeVolume(glassVol,Position(0,0,z_offset));
}
- else Control::Abort("Invalid sensitive model in the dababase!",MOKKA_ERROR_BAD_DATABASE_PARAMETERS);
-
- G4VisAttributes *VisAtt = new G4VisAttributes(G4Colour(1.,1.,1.));
- EndCapChamberLogical->SetVisAttributes(VisAtt);
-
-
+ else {
+ throw runtime_error("Invalid sensitive model in the dababase for "+name+"!");
+ }
+ PlacedVolume pv;
+ chamberVol.setVisAttributes(m_chamberVis);
// standard endcap chamber placements
- db->exec("select layer_id,chamber_z_offset AS Zoff from endcap_layer;");
-
- G4int layer_id;
- while(db->getTuple()!=NULL){
- layer_id=db->fetchInt("layer_id");
- new MyPlacement(0,
- G4ThreeVector(0.,
- 0.,
- db->fetchDouble("Zoff")),
- EndCapChamberLogical,
- "EndCapChamberPhys",
- MotherLog,false,layer_id);
- }
-}
-
-
-Volume Hcal04::buildRPC1Polyhedra(G4Polyhedra* ChamberSolid,
- SD* theSD,
- double phiStart,
- double phiTotal,
- G4int numSide,
- G4int numZPlanes,
- const double zPlane[],
- const double rInner[],
- const double rOuter[],
- G4UserLimits* pULimits)
-{
- // fill the Chamber Envelope with G10
- G4LogicalVolume *ChamberLog =
- new G4LogicalVolume(ChamberSolid,
- CGAGeometryManager::GetMaterial("g10"),
- "RPC1", 0, 0, 0);
- //
- // build the RPC glass
- double NewZPlane[2];
- NewZPlane[0] = glass_thickness/2.;
- NewZPlane[1] = -NewZPlane[0];
- G4Polyhedra * GlassSolid =
- new G4Polyhedra("RPC1Glass",
- phiStart,
- phiTotal,
- numSide,
- numZPlanes,
- NewZPlane,
- rInner,
- rOuter);
-
- G4LogicalVolume *GlassLogical =
- new G4LogicalVolume(GlassSolid,
- CGAGeometryManager::GetMaterial("pyrex"),
- "RPC1glass",
- 0, 0, 0);
-
- G4VisAttributes * VisAtt = new G4VisAttributes(G4Colour(.8,0,.2));
- VisAtt->SetForceWireframe(true);
- GlassLogical->SetVisAttributes(VisAtt);
-
- // build the gas gap
- NewZPlane[0] = gas_thickness/2.;
- NewZPlane[1] = -NewZPlane[0];
- G4Polyhedra * GasSolid = new G4Polyhedra("RPC1Gas",
- phiStart,
- phiTotal,
- numSide,
- numZPlanes,
- NewZPlane,
- rInner,
- rOuter);
-
- G4LogicalVolume *GasLogical =
- new G4LogicalVolume(GasSolid,CGAGeometryManager::GetMaterial("RPCGAS1"),
- "RPC1gas",0, 0, pULimits);
-
- VisAtt = new G4VisAttributes(G4Colour(.1,0,.8));
- VisAtt->SetForceWireframe(true);
- //VisAtt->SetForceSolid(true);
- GasLogical->SetVisAttributes(VisAtt);
+ for(Layers::const_iterator i=m_endcap.layers.begin(); i != m_endcap.layers.end(); ++i) {
+ const Layer& layer = *i;
+ DetElement det_layer(sdet,_toString(layer.id,"layer%d"),layer.id);
+ pv = modVolume.placeVolume(chamberVol,Position(0,0,layer.values.endcap_layer.z_offset));
+ pv.addPhysVolID("layer",layer.id);
+ det_layer.setPlacement(pv);
+ }
- // PLugs the sensitive detector HERE!
- GasLogical->SetSensitiveDetector(theSD);
- // placing the all.
- // ZOffset starts pointing to the chamber border.
- double ZOffset = zPlane[0];
-
- // first glass after the g10_thickness
- ZOffset += rpc.g10_thickness + glass_thickness/2.;
- new MyPlacement(0,
- G4ThreeVector(0,0,ZOffset),
- GlassLogical,
- "RPCGlass",
- ChamberLog,
- false,
- 0);
-
- // set ZOffset to the next first glass border
- ZOffset += glass_thickness/2.;
-
- // gas gap placing
- ZOffset += gas_thickness/2.; // center !
- new MyPlacement(0,
- G4ThreeVector(0,0,ZOffset),
- GasLogical,
- "RPCGas",
- ChamberLog,
- false,
- 0);
-
- // set ZOffset to the next gas gap border
- ZOffset += gas_thickness/2.;
-
- // second glass, after the g10_thickness, the first glass
- // and the gas gap.
- ZOffset += glass_thickness/2.; // center !
- new MyPlacement(0,
- G4ThreeVector(0,0,ZOffset),
- GlassLogical,
- "RPCGlass",
- ChamberLog,
- false,
- 0);
- return ChamberLog;
+ // Now place the endcaps
+ pv = assembly.placeVolume(modVolume,m_endcap.side[SIDE_PLUS].position,Rotation(0,M_PI/8,0));
+ pv.addPhysVolID("module",HCALENDCAPPLUS*100+16);
+ sdet.setPlacement(pv);
+ self.add(sdet);
+ m_endcap.side[SIDE_PLUS] = sdet;
+
+ pv = assembly.placeVolume(modVolume,m_endcap.side[SIDE_MINUS].position,Rotation(M_PI,M_PI/8,M_PI));
+ pv.addPhysVolID("module",HCALENDCAPMINUS*100+16);
+ sdet = sdet.clone("endcap_minus",HCALENDCAPMINUS);
+ self.add(sdet);
+ sdet.setPlacement(pv);
+ m_endcap.side[SIDE_MINUS] = sdet;
+
+ //theENDCAPEndSD->SetModuleZOffset(0,fabs(Z1));
+ //theENDCAPEndSD->SetModuleZOffset(6,fabs(Z1));
}
-#endif
/// Build Box with RPC1 chamber
-Volume Hcal04::buildRPC1Box(const string& nam, Box box, const Layer& layer) {
- // SD* theSD,
- // G4UserLimits* pULimits)
+Volume Hcal04::buildRPC1Box(const string& nam, Box box, const Layer& layer, SensitiveDetector& sensdet) {
Material g10_mat = lcdd->material("G10");
// fill the Chamber Envelope with G10
Volume chamberVol(nam+"_rpc",box,g10_mat);
// build the RPC glass !!attention!! y<->z
- Box glassBox(box.x(),box.y(),rpc.glass_thickness/2.0);
+ Box glassBox(box.x(),box.y(),m_rpc.glass.thickness/2.0);
Volume glassVol(nam+"_RPC_glass",glassBox,lcdd->material("pyrex"));
glassVol.setVisAttributes(lcdd->visAttributes("HcalRpcGlassVis"));
// build the standard spacer !!attention!! y<->z
- Box spacerBox(box.x(),rpc.spacer_thickness/2,rpc.gas_thickness/2);
+ Box spacerBox(box.x(),m_rpc.spacer.thickness/2,m_rpc.gas.thickness/2);
Volume spacerVol(nam+"_spacer",spacerBox,g10_mat);
spacerVol.setVisAttributes(lcdd->visAttributes("HcalRpcSpacerVis"));
- Box gasBox(box.x(),box.y(),rpc.gas_thickness/2.0);
+ Box gasBox(box.x(),box.y(),m_rpc.gas.thickness/2.0);
Volume gasVol(nam+"_RPC_gas",glassBox,lcdd->material("RPCGAS1"));
gasVol.setVisAttributes(lcdd->visAttributes("HcalRpcGasVis"));
+ gasVol.setSensitiveDetector(sensdet);
+ gasVol.setLimitSet(m_limits);
// PLugs the sensitive detector HERE!
// gasVol->SetSensitiveDetector(theSD);
// placing the spacers inside the gas gap
- double MaxY = box.y()-rpc.spacer_thickness/2;
- for(double ypos=-box.y() + rpc.spacer_thickness/2; ypos < MaxY; ypos += rpc.spacer_gap)
+ double MaxY = box.y()-m_rpc.spacer.thickness/2;
+ for(double ypos=-box.y() + m_rpc.spacer.thickness/2; ypos < MaxY; ypos += m_rpc.spacer.gap)
gasVol.placeVolume(spacerVol,Position(0,ypos,0));
// placing the all. ZOffset starts pointing to the chamber border.
double zpos = -box.z();
-
// first glass border after the g10_thickness
- zpos += rpc.g10_thickness + rpc.glass_thickness/2.;
+ zpos += m_rpc.radiator.thickness + m_rpc.glass.thickness/2.;
chamberVol.placeVolume(glassVol,Position(0,0,zpos));
// set zpos to the next first glass border + gas gap placing
- zpos += rpc.glass_thickness/2. + rpc.gas_thickness/2.;
+ zpos += m_rpc.glass.thickness/2. + m_rpc.gas.thickness/2.;
PlacedVolume pv = chamberVol.placeVolume(gasVol,Position(0,0,zpos));
pv.addPhysVolID("layer",layer.id);
// set zpos to the next gas gap border + second glass
- zpos += rpc.gas_thickness/2. + rpc.glass_thickness/2.;
+ zpos += m_rpc.gas.thickness/2. + m_rpc.glass.thickness/2.;
pv = chamberVol.placeVolume(glassVol,Position(0,0,zpos));
return chamberVol;
}
-static Ref_t create(LCDD& lcdd, const xml_h& element, SensitiveDetector& sens) {
- DetElement sdet;
- xml_det_t x_det = element;
- Value<TNamed,Hcal04>* ptr = new Value<TNamed,Hcal04>();
- sdet.assign(ptr,x_det.nameStr(),x_det.typeStr());
- ptr->construct(lcdd,element,sens);
- return sdet;
+static Ref_t create_detector(LCDD& lcdd, const xml_h& element) {
+ return (new Value<TNamed,Hcal04>())->construct(lcdd,element);
}
-DECLARE_DETELEMENT(Tesla_hcal04,create);
+DECLARE_SUBDETECTOR(Tesla_hcal04,create_detector);
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_mask04_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_mask04_geo.cpp
index 161ace0fb..9d76987fe 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_mask04_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_mask04_geo.cpp
@@ -13,12 +13,12 @@ using namespace std;
using namespace DD4hep;
using namespace DD4hep::Geometry;
-static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens) {
+static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector&) {
xml_det_t x_det = e;
string name = x_det.nameStr();
Rotation reflect_rot(M_PI,0,0);
DetElement sdet(name,x_det.id());
- Assembly maskVol(name+"_assembly");
+ Assembly maskVol(name);
Volume motherVol = lcdd.pickMotherVolume(sdet);
xml_comp_t x_masks = x_det.child(Unicode("masks"));
xml_comp_t x_quad = x_det.child(Unicode("quadrupole"));
@@ -34,7 +34,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
z0 = (z1+z2)/2.0;
Tube tub(rmin,rmax,dz);
- Volume vol(name+_toString(id,"_mask%d"),tub,lcdd.material(x_m.materialStr()));
+ Volume vol(_toString(id,"_mask%d"),tub,lcdd.material(x_m.materialStr()));
vol.setVisAttributes(lcdd.visAttributes(x_m.visStr()));
pv = maskVol.placeVolume(vol,Position(0,0,z0));
pv.addPhysVolID("mask",id);
@@ -52,19 +52,20 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
Tube iron(x_yoke.rmin(),x_yoke.rmax(),yoke_dz);
Tube cave(x_coil.rmin(),x_coil.rmax(),coil_dz+10.0);
SubtractionSolid yoke(iron,cave,Position(0,0,coil_pos - yoke_pos + 10.),Rotation());
- Volume vol(name+"_yoke",yoke,lcdd.material(x_yoke.materialStr()));
+ Volume vol("yoke",yoke,lcdd.material(x_yoke.materialStr()));
vol.setVisAttributes(lcdd.visAttributes(x_yoke.visStr()));
maskVol.placeVolume(vol,Position(0,0, yoke_pos));
maskVol.placeVolume(vol,Position(0,0,-yoke_pos),reflect_rot);
}
{ // Place coil
Tube tub(x_coil.rmin(),x_coil.rmax(),coil_dz);
- Volume vol(name+"_coil",tub,lcdd.material(x_coil.materialStr()));
+ Volume vol("coil",tub,lcdd.material(x_coil.materialStr()));
vol.setVisAttributes(lcdd.visAttributes(x_coil.visStr()));
maskVol.placeVolume(vol,Position(0,0, coil_pos));
maskVol.placeVolume(vol,Position(0,0,-coil_pos),reflect_rot);
}
- motherVol.placeVolume(maskVol);
+ pv = motherVol.placeVolume(maskVol);
+ sdet.setPlacement(pv);
return sdet;
}
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_sit00_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_sit00_geo.cpp
index 29f3388f9..a7f4f6e35 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_sit00_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_sit00_geo.cpp
@@ -14,21 +14,27 @@ using namespace DD4hep;
using namespace DD4hep::Geometry;
static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens) {
- xml_det_t x_det = e;
- string name = x_det.nameStr();
- DetElement sdet(name,x_det.id());
- Assembly sitVol(name+"_assembly");
- Volume motherVol = lcdd.pickMotherVolume(sdet);
+ xml_det_t x_det = e;
+ string name = x_det.nameStr();
+ DetElement sdet(name,x_det.id());
+ Assembly sitVol(name+"_assembly");
+ Volume motherVol = lcdd.pickMotherVolume(sdet);
+ PlacedVolume pv;
for(xml_coll_t c(x_det,Unicode("layer")); c; ++c) {
xml_comp_t x_layer = c;
double zhalf = x_layer.zhalf();
+ string layer_nam = _toString(x_layer.id(),"_layer%d");
+ DetElement layer_det(sdet,layer_nam,x_layer.id());
Tube tub(x_layer.inner_r(),x_layer.inner_r()+x_layer.thickness(),zhalf);
- Volume vol(name+_toString(x_layer.id(),"_layer%d"),tub,lcdd.material(x_layer.materialStr()));
+ Volume vol(layer_nam,tub,lcdd.material(x_layer.materialStr()));
vol.setVisAttributes(lcdd.visAttributes(x_layer.visStr()));
- sitVol.placeVolume(vol);
+ vol.setSensitiveDetector(sens);
+ pv = sitVol.placeVolume(vol);
+ layer_det.setPlacement(pv);
}
- motherVol.placeVolume(sitVol);
+ pv = motherVol.placeVolume(sitVol);
+ sdet.setPlacement(pv);
return sdet;
}
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_tpc02_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_tpc02_geo.cpp
index c011d1ea6..55347be4d 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_tpc02_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_tpc02_geo.cpp
@@ -13,7 +13,7 @@ using namespace std;
using namespace DD4hep;
using namespace DD4hep::Geometry;
-static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens_det) {
+static Ref_t create_element(LCDD& lcdd, const xml_h& e) {
xml_det_t x_det = e;
string name = x_det.nameStr();
DetElement sdet(name,x_det.id());
@@ -25,6 +25,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens_
xml_comp_t x_sens = x_det.child(Unicode("sensitive"));
xml_comp_t x_fch = x_det.child(Unicode("fch"));
Material gasMat = lcdd.material(x_sens.materialStr());
+ PlacedVolume pv;
struct cylinder_t { double inner, outer, zhalf; };
cylinder_t env = { x_envelope.inner_r(), x_envelope.outer_r(), x_envelope.zhalf() };
@@ -32,6 +33,13 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens_
cylinder_t fch = { x_fch.inner_r(), x_fch.outer_r(), x_fch.thickness()/2.0 };
cylinder_t sens = { x_sens.inner_r(), x_sens.outer_r(), 0.0 };
+ // TPC sensitive detector
+ SensitiveDetector sens_det("TPC");
+ Readout ro = lcdd.readout(x_sens.readoutStr());
+ sens_det.setHitsCollection(ro.name());
+ sens_det.setReadout(ro);
+ lcdd.addSensitiveDetector(sens_det);
+
// the TPC mother volume
Tube envTub(env.inner,env.outer,env.zhalf);
Volume envVol(name+"_envelope",envTub,lcdd.air());
@@ -61,8 +69,8 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens_
double lay_thick = (sens.outer-sens.inner)/num_layer;
Tube layerTub(sens.inner+i*lay_thick,sens.inner+(i+1)*lay_thick,env.zhalf);
Volume layerVol(name+_toString(i,"_layer%d"),layerTub,gasMat);
+ layerVol.setSensitiveDetector(sens_det);
layerVol.setVisAttributes(layerVis);
- //TPCChamberLogical->SetSensitiveDetector(theTPCSD);
envVol.placeVolume(layerVol);
}
@@ -82,18 +90,22 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens_
// FCH = two sensitive twin Si plates, just to register the particle step inside it.
// Threshold is 20% of a MIP. For Si we have 0.34 KeV/micron as MIP.
+ SensitiveDetector fchSD("TPCfch");
+ ro = lcdd.readout(x_fch.readoutStr());
+ fchSD.setHitsCollection(ro.name());
+ fchSD.setReadout(ro);
+ lcdd.addSensitiveDetector(fchSD);
+
Tube fchTub(fch.inner,fch.outer,fch.zhalf);
- Volume fchVol(name+"_fch",fchTub,lcdd.material(x_fch.materialStr()));
+ Volume fchVol("fch",fchTub,lcdd.material(x_fch.materialStr()));
fchVol.setVisAttributes(lcdd.visAttributes(x_fch.visStr()));
+ fchVol.setSensitiveDetector(fchSD);
envVol.placeVolume(fchVol,Position(0,0, env.zhalf+wall.zhalf+fch.zhalf));
envVol.placeVolume(fchVol,Position(0,0,-(env.zhalf+wall.zhalf+fch.zhalf)));
- // FCH Sensitive detector
- //theFCHSD = new TRKSD00("FCH", fch_thickness * mm * 340 * keV * 0.2);
- //FCHLogical->SetSensitiveDetector(theFCHSD);
-
- motherVol.placeVolume(envVol);
+ pv = motherVol.placeVolume(envVol);
+ sdet.setPlacement(pv);
return sdet;
}
-DECLARE_DETELEMENT(Tesla_tpc02,create_element);
+DECLARE_SUBDETECTOR(Tesla_tpc02,create_element);
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_tube01_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_tube01_geo.cpp
index bc84d0771..eb7fe41c7 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_tube01_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_tube01_geo.cpp
@@ -12,8 +12,9 @@
using namespace std;
using namespace DD4hep;
using namespace DD4hep::Geometry;
+#define _U(text) Unicode(#text)
-static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens) {
+static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector&) {
struct Tube_Desc { double zhalf, thickness, radius; };
struct Cone_Desc { double z, rmin, rmax; };
@@ -21,12 +22,12 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
string name = x_det.nameStr();
Rotation reflect_rot(M_PI,0,0);
DetElement beampipe(name,x_det.id());
- Assembly beampipeVol(name+"_assembly");
+ Assembly beampipeVol("assembly");
Volume motherVol = lcdd.pickMotherVolume(beampipe);
- xml_comp_t x_central = x_det.child(Unicode("central_tube"));
- xml_comp_t x_lateral = x_det.child(Unicode("lateral_tubes"));
- xml_comp_t x_ends = x_det.child(Unicode("ends"));
- xml_comp_t x_vacuum = x_det.child(Unicode("vacuum"));
+ xml_comp_t x_central = x_det.child(_U(central_tube));
+ xml_comp_t x_lateral = x_det.child(_U(lateral_tubes));
+ xml_comp_t x_ends = x_det.child(_U(ends));
+ xml_comp_t x_vacuum = x_det.child(_U(vacuum));
Material beampipeMat = lcdd.material(xml_comp_t(x_det).materialStr());
Material ironMat = lcdd.material("Iron");
Material vacuumMat = lcdd.vacuum();
@@ -34,8 +35,9 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
VisAttr beampipeVis = lcdd.visAttributes(x_det.visStr());
VisAttr vacuumVis = lcdd.visAttributes(x_vacuum.visStr());
VisAttr endVis = lcdd.visAttributes(x_ends.visStr());
- Tube_Desc central = {x_central.zhalf(), x_central.thickness(), x_central.inner_r()};
- Tube_Desc lateral = {x_lateral.zmin(),x_lateral.thickness(),x_lateral.inner_r()};
+ Tube_Desc central = {x_central.zhalf(),x_central.thickness(),x_central.inner_r()};
+ Tube_Desc lateral = {x_lateral.zmin(), x_lateral.thickness(),x_lateral.inner_r()};
+ PlacedVolume pv;
{ // beam vacuum inside the tube
Tube tube(0,central.radius,central.zhalf);
@@ -45,7 +47,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
}
{ // Be tube
Tube tube(central.radius,central.radius+central.thickness,central.zhalf);
- Volume vol (name+"_BeTube",tube,beampipeMat);
+ Volume vol (name+"_Be_tube",tube,beampipeMat);
vol.setVisAttributes(beampipeVis);
beampipeVol.placeVolume(vol);
}
@@ -83,7 +85,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
double z_tube = (end_zmin + inner_zmin)/2.0;
{ // inner beam vacuum lateral tubes
Tube tube(0,lateral.radius,inner_zhalf);
- Volume vol (name+"_lat_vacuum",tube,vacuumMat);
+ Volume vol (name+"_lateral_vacuum",tube,vacuumMat);
vol.setVisAttributes(vacuumVis);
beampipeVol.placeVolume(vol,Position(0,0, z_tube));
beampipeVol.placeVolume(vol,Position(0,0,-z_tube));
@@ -91,17 +93,17 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
{ // inner Be lateral tubes
Tube tube(lateral.radius,lateral.radius+lateral.thickness,inner_zhalf);
- Volume vol (name+"_lat_BeTube",tube, beampipeMat);
+ Volume vol (name+"_lateral_BeTube",tube, beampipeMat);
vol.setVisAttributes(beampipeVis);
beampipeVol.placeVolume(vol,Position(0,0, z_tube));
beampipeVol.placeVolume(vol,Position(0,0,-z_tube));
}
{ // VXD strip lines on lateral tubes
- xml_comp_t s = x_det.child(Unicode("strips"));
+ xml_comp_t s = x_det.child(_U(strips));
Tube tube(lateral.radius+lateral.thickness+s.gap(),
lateral.radius+lateral.thickness+s.gap()+s.thickness(),inner_zhalf);
- Volume vol(name+"_lat_Strips",tube,lcdd.material(s.materialStr()));
+ Volume vol(name+"_lateral_Strips",tube,lcdd.material(s.materialStr()));
vol.setVisAttributes(lcdd.visAttributes(s.visStr()));
beampipeVol.placeVolume(vol,Position(0,0, z_tube));
beampipeVol.placeVolume(vol,Position(0,0,-z_tube));
@@ -110,11 +112,11 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
// ends lateral cones and tubes
size_t cnt = 0;
Cone_Desc cones[5];
- for(xml_coll_t c(x_det,Unicode("cone")); c; ++c, ++cnt) {
+ for(xml_coll_t c(x_lateral,_U(cone)); c; ++c, ++cnt) {
xml_comp_t x_con = c;
- cones[cnt].z = x_con.z();
- cones[cnt].rmin = x_con.rmin();
- cones[cnt].rmax = x_con.rmax();
+ cones[cnt].z = x_con.z();
+ cones[cnt].rmin = x_con.rmin();
+ cones[cnt].rmax = x_con.rmax();
}
{ // vacuum lateral cone
double dz = (x_lateral.dz() - end_thickness)/2.0;
@@ -126,7 +128,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
Cone fe_end_cone (dz,lateral.radius,lateral.radius+end_thickness,
cones[0].rmin,cones[0].rmin+end_thickness);
- Volume fe_end_vol( name+"_lat_fe",fe_end_cone,ironMat);
+ Volume fe_end_vol(name+"_lateral_fe",fe_end_cone,ironMat);
fe_end_vol.setVisAttributes(endVis);
// put vacuum and iron cones into world
@@ -140,7 +142,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
neg.z = -(pos.z = z_cone+dz);
for(int i=0; i<5; ++i ) {
Tube vac_tub(0, cones[i].rmin, cones[i].z);
- Volume vac_vol(name+_toString(i,"_vac_%d"),vac_tub,vacuumMat);
+ Volume vac_vol(_toString(i,"vac_%d"),vac_tub,vacuumMat);
vac_vol.setVisAttributes(vacuumVis);
// Update Z-placement
neg.z = -(pos.z += cones[i].z);
@@ -148,7 +150,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
beampipeVol.placeVolume(vac_vol,neg);
Tube fe_tub (cones[i].rmin, cones[i].rmax, cones[i].z);
- Volume fe_vol (name+_toString(i,"_fe_%d"),fe_tub,ironMat);
+ Volume fe_vol (name+_toString(i,"_feTube%d"),fe_tub,ironMat);
fe_vol.setVisAttributes(endVis);
beampipeVol.placeVolume(fe_vol,pos);
beampipeVol.placeVolume(fe_vol,neg);
@@ -156,7 +158,8 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
neg.z = -(pos.z += cones[i].z);
}
}
- motherVol.placeVolume(beampipeVol);
+ pv = motherVol.placeVolume(beampipeVol);
+ beampipe.setPlacement(pv);
return beampipe;
}
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_tubeX01_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_tubeX01_geo.cpp
index 12253bb20..be9b8cce3 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_tubeX01_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_tubeX01_geo.cpp
@@ -1,339 +1,74 @@
-#if 0
- G4double crossingAngle = theGeometryEnvironment.GetParameterAsDouble("TUBE_crossing_angle");
- G4double z_begin = theGeometryEnvironment.GetParameterAsDouble("Lcal_z_begin");
- G4double r_max = theGeometryEnvironment.GetParameterAsDouble("Lcal_outer_radius");
- G4double r_min = theGeometryEnvironment.GetParameterAsDouble("Lcal_inner_radius");
- G4int n_layer = theGeometryEnvironment.GetParameterAsInt("Lcal_n_layers");
- G4double tungsten_thickness= theGeometryEnvironment.GetParameterAsDouble("Lcal_tungsten_thickness");
- G4double support_thickness = theGeometryEnvironment.GetParameterAsDouble("Lcal_support_thickness");
- G4double silicon_thickness = theGeometryEnvironment.GetParameterAsDouble("Lcal_silicon_thickness");
- G4double layer_gap = theGeometryEnvironment.GetParameterAsDouble("Lcal_layer_gap");
- G4double z_end = z_begin + (tungsten_thickness + support_thickness + silicon_thickness + layer_gap)*(double)n_layer;
-
- G4double alpha = crossingAngle / 2.* mrad;
- G4double width = z_end - z_begin;
-
- G4double r_inner_min = (width + z_begin * cos(alpha )) * tan(2.*alpha);
- G4double lcal_rot_extra_r = width * sin(alpha);
- G4double lcal_rot_extra_z = r_max * sin(alpha);
- G4double opening_angle = r_max/z_end;
- actual_opening_angle = opening_angle;
-
- //save for lcal
- //check if inner radius change is needed
- dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_back\";");
- dbtmp->getTuple();
- G4double r = dbtmp->fetchDouble("rInnerStart");
-
- if ( (r_min - 0.5 - lcal_rot_extra_r) < r)
- {
- r = r_min - 0.5 - lcal_rot_extra_r;
- G4cout << " ...change r_min of tube (lcal rotation) r = " << r << G4endl;
- }
-
- if (dbtmp->fetchDouble("zEnd") * tan(alpha) > r)
- {
- r_min = r_inner_min;
- G4cout << " ...change r_min of lcal (lateral tubes crossAngle) r = " << r_min << G4endl;
- }
-
-//save for lcal
- actual_lcal_rin = r_min;
-
- G4double vxd_r = theGeometryEnvironment.GetParameterAsDouble("VXD_inner_radius");
- G4double thickness;
-
- dbtmp->exec("SELECT * FROM tube WHERE name=\"ip_inner_parallel\";");
- dbtmp->getTuple();
- thickness = dbtmp->fetchDouble("rOuterStart") - dbtmp->fetchDouble("rInnerStart");
-
- //ip_inner_parallel 0.5mm gap between pipe and vxd
- dbtmp->exec( ("UPDATE tube SET rOuterStart = " + double2str(vxd_r - 0.5) + " WHERE name = \"ip_inner_parallel\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rOuterEnd = " + double2str(vxd_r - 0.5) + " WHERE name = \"ip_inner_parallel\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rInnerStart = " + double2str(vxd_r - 0.5 - thickness) + " WHERE name = \"ip_inner_parallel\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rInnerEnd = " + double2str(vxd_r - 0.5 - thickness) + " WHERE name = \"ip_inner_parallel\";").data() );
-
-
- dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_front\";");
- dbtmp->getTuple();
- width = dbtmp->fetchDouble("zEnd") - dbtmp->fetchDouble("zStart");
- r = dbtmp->fetchDouble("rInnerStart");
-
- //ip_outer_bulge
- dbtmp->exec("SELECT * FROM tube WHERE name=\"ip_outer_bulge\";");
- dbtmp->getTuple();
- thickness = dbtmp->fetchDouble("rOuterEnd") - dbtmp->fetchDouble("rInnerEnd");
-
- dbtmp->exec( ("UPDATE tube SET zEnd = " + double2str(z_begin - width - lcal_rot_extra_z) + " WHERE name = \"ip_outer_bulge\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rOuterEnd = " + double2str(r_max) + " WHERE name = \"ip_outer_bulge\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rInnerEnd = " + double2str(r_max - thickness) + " WHERE name = \"ip_outer_bulge\";").data() );
-
- //lumcal_front
- //0.5 cm gap between lcal and tube ?
-
- dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_front\";");
- dbtmp->getTuple();
- r = dbtmp->fetchDouble("rInnerStart");
-
- dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_wall\";");
- dbtmp->getTuple();
- thickness = dbtmp->fetchDouble("rOuterEnd") - dbtmp->fetchDouble("rInnerEnd");
-
- G4cout << "lumcal_wall thickness = " << thickness << G4endl;
-
- dbtmp->exec( ("UPDATE tube SET zStart = " + double2str(z_begin - width - lcal_rot_extra_z) + " WHERE name = \"lumcal_front\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET zEnd = " + double2str(z_begin - lcal_rot_extra_z) + " WHERE name = \"lumcal_front\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rOuterStart = " + double2str(r_max) + " WHERE name = \"lumcal_front\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rOuterEnd = " + double2str(r_max) + " WHERE name = \"lumcal_front\";").data() );
-
- if ( (r_min - 0.5 - lcal_rot_extra_r) < r)
- {
- dbtmp->exec( ("UPDATE tube SET rInnerStart = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_front\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rInnerEnd = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_front\";").data() );
- }
-
- //lumcal_wall
- dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_wall\";");
- dbtmp->getTuple();
- r = dbtmp->fetchDouble("rOuterStart");
-
- dbtmp->exec( ("UPDATE tube SET zStart = " + double2str(z_begin - lcal_rot_extra_z) + " WHERE name = \"lumcal_wall\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET zEnd = " + double2str( z_end + lcal_rot_extra_z) + " WHERE name = \"lumcal_wall\";").data() );
-
- if ( (r_min - 0.5 - lcal_rot_extra_r) < r)
- {
- dbtmp->exec( ("UPDATE tube SET rOuterStart = " + double2str( r_min - 0.5 - lcal_rot_extra_r ) + " WHERE name = \"lumcal_wall\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rOuterEnd = " + double2str( r_min - 0.5 - lcal_rot_extra_r ) + " WHERE name = \"lumcal_wall\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rInnerStart = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_wall\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rInnerEnd = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_wall\";").data() );
- }
-
- //lumcal_back
- dbtmp->exec("SELECT * FROM tube WHERE name=\"lumcal_back\";");
- dbtmp->getTuple();
- r = dbtmp->fetchDouble("rInnerStart");
-
- dbtmp->exec( ("UPDATE tube SET zStart = " + double2str( z_end + lcal_rot_extra_z) + " WHERE name = \"lumcal_back\";").data() );
-
- if ( (r_min - 0.5 - lcal_rot_extra_r) < r)
- {
- dbtmp->exec( ("UPDATE tube SET rInnerStart = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_back\";").data() );
-
- dbtmp->exec( ("UPDATE tube SET rInnerEnd = " + double2str(r_min - 0.5 - lcal_rot_extra_r - thickness) + " WHERE name = \"lumcal_back\";").data() );
- }
-
- return true;
-}
-
-G4bool STubeX00::PostLoadScriptAction(Database* dbtmp, CGAGeometryEnvironment& )
-{
- G4cout << "STubeX00 set the following geomerty parameters : " << endl;
- dbtmp->exec("SELECT * FROM tube;");
- while (dbtmp->getTuple())
- {
- G4cout << " " << dbtmp->fetchString("name") << " : rIn1 = " << dbtmp->fetchDouble("rInnerStart");
- G4cout << " rOut1 = " << dbtmp->fetchDouble("rOuterStart") << " rIn2 = " << dbtmp->fetchDouble("rInnerEnd");
- G4cout << " rOut2 = " << dbtmp->fetchDouble("rOuterEnd") << " zStart = " << dbtmp->fetchDouble("zStart");
- G4cout << " zEnd = " << dbtmp->fetchDouble("zEnd") << endl;
- }
-
-//pass the opening angle to others
- (*Control::globalModelParameters)["TUBE_opening_angle"] = double2str(actual_opening_angle);
-
-//pass updated lcal rin
- (*Control::globalModelParameters)["Lcal_inner_radius"] = double2str(actual_lcal_rin);
-
- G4cout << "STubeX00 PostLoadScriptAction set opening angle "
- << actual_opening_angle << G4endl;
-
- G4cout << "STubeX00 PostLoadScriptAction set LCAL rIn "
- << actual_lcal_rin << G4endl;
-
- return true;
-}
-
-
-
-
-// *********************************************************
-// * Mokka *
-// * -- A Detailed Geant 4 Simulation for the ILC -- *
-// * *
-// * polywww.in2p3.fr/geant4/tesla/www/mokka/mokka.html *
-// *********************************************************
+// $Id:$
+//====================================================================
+// AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
//
-// $Id: TubeX01.cc,v 1.5 2008/10/15 16:51:53 steve Exp $
-// $Name: mokka-07-00 $
+// Author : M.Frank
//
-// History:
-// - first implementation as Tube00: Paulo Mora de Freitas, Sep 2002
-// - modified from Tube00 to Tube01DT: Ties Behnke, 2003-02-11
-// - modified for a crossing angle as TubeX00: Adrian Vogel, 2005-05-18
-// - modified for fancier geometries as TubeX01: Adrian Vogel, 2006-04-20
-
-#include "TubeX01.hh"
-#include "MySQLWrapper.hh"
-#include "CGAGeometryManager.hh"
-#include "CGAGeometryEnvironment.hh"
-#include "CGADefs.h"
-#include "Control.hh"
-
-#include "globals.hh"
-#include "G4ThreeVector.hh"
-#include "G4RotationMatrix.hh"
-#include "G4Transform3D.hh"
-
-#include "G4VisAttributes.hh"
-#include "G4Material.hh"
-#include "G4Cons.hh"
-#include "G4Tubs.hh"
-#include "G4SubtractionSolid.hh"
-#include "G4LogicalVolume.hh"
-#include "G4PVPlacement.hh"
-
-#ifdef MOKKA_GEAR
-#include "gearimpl/GearParametersImpl.h"
-#include "MokkaGear.h"
-#include "G4EmCalculator.hh"
-#include "G4ParticleTable.hh"
-#endif
-
-
-INSTANTIATE(TubeX01)
-
-G4bool TubeX01::ContextualConstruct(const CGAGeometryEnvironment &env, G4LogicalVolume *worldLog)
-{
- // useful values for construction of tubes and cones
- const G4double phi1 = 0.0 * deg; // all cones start at zero...
- const G4double phi2 = 360.0 * deg; // ...and cover the whole 360 degrees
-
- // some visualization attributes for the tube wall and the vacuum inside
- G4VisAttributes *wallVisAttrib = new G4VisAttributes(G4Colour(1.0, 0.7, 0.5)); // light brown
- //wallVisAttrib->SetForceSolid(true);
- G4VisAttributes *vacuumVisAttrib = new G4VisAttributes(G4Colour(0.0, 0.0, 0.5)); // dark blue
- vacuumVisAttrib->SetVisibility(false); // there isn't anything, so what do you expect?
-
- const G4double crossingAngle = env.GetParameterAsDouble("ILC_Main_Crossing_Angle") / 2 * mrad; // only half the angle
- const G4String dbName = env.GetDBName() + "_" + env.GetParameterAsString("ILC_Main_Crossing_Angle");
- Database *db = new Database(dbName.c_str());
-
- G4bool usingOffsets = false;
- TReferenceMap referenceOffsets;
- db->exec("SELECT * FROM `_references`;");
- while (db->getTuple()) {
- const G4String globalName = db->fetchString("globalName");
- const G4String localName = db->fetchString("localName");
- const G4double assumedValue = db->fetchDouble("assumption") * mm;
- const G4double currentValue = env.GetParameterAsDouble(globalName);
- const G4double offsetValue = currentValue - assumedValue;
- referenceOffsets[localName] = offsetValue;
-
- if (offsetValue != 0) {
- G4cout
- << "TubeX01: Using " << globalName << " = "
- << currentValue / mm << " mm instead of "
- << assumedValue / mm << " mm" << G4endl;
- usingOffsets = true;
- }
- }
- if (usingOffsets) Control::Log("TubeX01: Be sure you know what you're doing!");
-
- bool firstPiece = true;
- material = "";
- beam_inner_radius = -99999;
- beam_thickness = -99999;
-
- db->exec("SELECT * FROM `tube`;");
- while (db->getTuple()) {
- // reference values for r- and z-values
- const G4String zStartRef = db->fetchString("zStartRef");
- const G4String zEndRef = db->fetchString("zEndRef");
- const G4String rInnerStartRef = db->fetchString("rInnerStartRef");
- const G4String rInnerEndRef = db->fetchString("rInnerEndRef");
- const G4String rOuterStartRef = db->fetchString("rOuterStartRef");
- const G4String rOuterEndRef = db->fetchString("rOuterEndRef");
-
- const G4double zStartOffset = (zStartRef == "") ? (0) : (referenceOffsets[zStartRef]);
- const G4double zEndOffset = (zEndRef == "") ? (0) : (referenceOffsets[zEndRef]);
- const G4double rInnerStartOffset = (rInnerStartRef == "") ? (0) : (referenceOffsets[rInnerStartRef]);
- const G4double rInnerEndOffset = (rInnerEndRef == "") ? (0) : (referenceOffsets[rInnerEndRef]);
- const G4double rOuterStartOffset = (rOuterStartRef == "") ? (0) : (referenceOffsets[rOuterStartRef]);
- const G4double rOuterEndOffset = (rOuterEndRef == "") ? (0) : (referenceOffsets[rOuterEndRef]);
-
- // fields in the data tuple
- const ECrossType crossType = ECrossType(db->fetchInt("crossType")); // positioning of the volume
- const G4double zStart = db->fetchDouble("zStart") * mm + zStartOffset;
- const G4double zEnd = db->fetchDouble("zEnd") * mm + zEndOffset;
- const G4double rInnerStart = db->fetchDouble("rInnerStart") * mm + rInnerStartOffset;
- const G4double rInnerEnd = db->fetchDouble("rInnerEnd") * mm + rInnerEndOffset;
- const G4double rOuterStart = db->fetchDouble("rOuterStart") * mm + rOuterStartOffset;
- const G4double thickness = rOuterStart - rInnerStart;
- const G4double rOuterEnd = db->fetchDouble("rOuterEnd") * mm + rOuterEndOffset;
- const G4String materialName = db->fetchString("material");
- const G4String volName = "tube_" + db->fetchString("name");
-
- if(volName == "tube_IPOuterTube"){
-
- std::ostringstream oss1;
- oss1 << zStart;
- (*Control::globalModelParameters)["TUBE_IPOuterTube_start_z"] = oss1.str();
- std::ostringstream oss2;
- oss2 << zEnd;
- (*Control::globalModelParameters)["TUBE_IPOuterTube_end_z"] = oss2.str();
- std::ostringstream oss3;
- oss3 << rOuterStart;
- (*Control::globalModelParameters)["TUBE_IPOuterTube_start_radius"] = oss3.str();
- std::ostringstream oss4;
- oss4 << rOuterEnd;
- (*Control::globalModelParameters)["TUBE_IPOuterTube_end_radius"] = oss4.str();
-
- }
-
- if(volName == "tube_IPOuterBulge"){
-
- std::ostringstream oss1;
- oss1 << zEnd;
- (*Control::globalModelParameters)["TUBE_IPOuterBulge_end_z"] = oss1.str();
- std::ostringstream oss2;
- oss2 << rOuterEnd;
- (*Control::globalModelParameters)["TUBE_IPOuterBulge_end_radius"] = oss2.str();
+//====================================================================
+#include "DD4hep/DetFactoryHelper.h"
+#include "TGeoTube.h"
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Geometry;
+#define _U(text) Unicode(#text)
+
+
+namespace {
+ typedef enum { // These constants are also used in the MySQL database:
+ kCenter = 0, // centered on the z-axis
+ kUpstream = 1, // on the upstream branch, rotated by half the crossing angle
+ kDnstream = 2, // on the downstream branch, rotated by half the crossing angle
+
+ kPunchedCenter = 3, // centered, with one or two inner holes
+ kPunchedUpstream = 4, // on the upstream branch, with two inner holes
+ kPunchedDnstream = 5, // on the downstrem branch, with two inner holes
+
+ kUpstreamClippedFront = 6, // upstream, with the front face parallel to the xy-plane
+ kDnstreamClippedFront = 7, // downstream, with the front face parallel to the xy-plane
+ kUpstreamClippedRear = 8, // upstream, with the rear face parallel to the xy-plane
+ kDnstreamClippedRear = 9, // downstream, with the rear face parallel to the xy-plane
+ kUpstreamClippedBoth = 10, // upstream, with both faces parallel to the xy-plane
+ kDnstreamClippedBoth = 11, // downstream, with both faces parallel to the xy-plane
+
+ kUpstreamSlicedFront = 12, // upstream, with the front face parallel to a tilted piece
+ kDnstreamSlicedFront = 13, // downstream, with the front face parallel to a tilted piece
+ kUpstreamSlicedRear = 14, // upstream, with the rear face parallel to a tilted piece
+ kDnstreamSlicedRear = 15, // downstream, with the rear face parallel to a tilted piece
+ kUpstreamSlicedBoth = 16, // upstream, with both faces parallel to a tilted piece
+ kDnstreamSlicedBoth = 17 // downstream, with both faces parallel to a tilted piece
+ } ECrossType;
+}
- }
-
- if(firstPiece)
- {
- firstPiece = false;
- material = materialName;
- beam_inner_radius = rInnerStart;
- beam_thickness = thickness;
- }
- // things which can be calculated immediately
- zHalf = fabs(zEnd - zStart) / 2; // half z length of the cone
- const G4double zPosition = fabs(zEnd + zStart) / 2; // middle z position
- G4Material *coreMaterial = CGAGeometryManager::GetMaterial("beam"); // always the same
- G4Material *wallMaterial = CGAGeometryManager::GetMaterial(materialName);
- // this could mess up your geometry, so better check it
- if (crossingAngle == 0 && crossType != kCenter) {
- Control::Log("TubeX01: You are trying to build a crossing geometry without a crossing angle.\n"
- "This is probably not what you want - better check your geometry data!");
- return false; // premature exit, Mokka will abort now
- }
+static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector&) {
+ xml_det_t x_det = e;
+ string name = x_det.nameStr();
+ Rotation reflect_rot(M_PI,0,0);
+ DetElement sdet(name,x_det.id());
+ Assembly assembly(name);
+ double crossingAngle = x_det.attr<double>(_U(crossing_angle));
+ Material coreMat = lcdd.vacuum();
+ VisAttr vacuumVis = lcdd.visAttributes("TubeVacuumVis");
+
+ PlacedVolume pv;
+ struct dim_t { double inner_r, outer_r, z; };
+ for(xml_coll_t c(x_det.child(_U(tubes)),_U(tube)); c; ++c) {
+ xml_comp_t x_c = c;
+ xml_comp_t x_end = c.child(_A(end));
+ xml_comp_t x_start = c.child(_A(start));
+ dim_t end = { x_end.inner_r(), x_end.outer_r(), x_end.z()};
+ dim_t start = { x_start.inner_r(), x_start.outer_r(), x_start.z()};
+ Material mat = lcdd.material(x_c.materialStr());
+ VisAttr vis = lcdd.visAttributes(x_c.visStr());
+ int crossType = x_c.attr<int>(_U(crossType));
+
+ double angle = 0;
+ string nam = x_c.nameStr();
+ double zHalf = std::fabs(start.z - end.z) / 2; // half z length of the cone
+ double zPos = std::fabs(start.z + end.z) / 2; // middle z position
- register G4double tmpAngle;
switch (crossType) {
case kUpstream:
case kPunchedUpstream:
@@ -343,7 +78,7 @@ G4bool TubeX01::ContextualConstruct(const CGAGeometryEnvironment &env, G4Logical
case kUpstreamSlicedFront:
case kUpstreamSlicedRear:
case kUpstreamSlicedBoth:
- tmpAngle = -crossingAngle; break;
+ angle = -crossingAngle; break;
case kDnstream:
case kPunchedDnstream:
case kDnstreamClippedFront:
@@ -352,354 +87,244 @@ G4bool TubeX01::ContextualConstruct(const CGAGeometryEnvironment &env, G4Logical
case kDnstreamSlicedFront:
case kDnstreamSlicedRear:
case kDnstreamSlicedBoth:
- tmpAngle = +crossingAngle; break;
+ angle = +crossingAngle; break;
default:
- tmpAngle = 0; break;
+ angle = 0; break;
}
- const G4double rotateAngle = tmpAngle; // for the placement at +z (better make it const now)
- const G4double mirrorAngle = 180 * deg - rotateAngle; // for the "mirrored" placement at -z
- // the "mirroring" in fact is done by a rotation of (almost) 180 degrees around the y-axis
-
+
+ cout << name << "> Building " << nam << " " << crossType << " " << vis.name() << endl;
+ double reflect_angle = M_PI - angle;
+ Volume vol, wall;
+ SubtractionSolid solid;
switch (crossType) {
case kCenter:
case kUpstream:
case kDnstream: {
// a volume on the z-axis, on the upstream branch, or on the downstream branch
-
- // absolute transformations for the placement in the world
- G4Transform3D transformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition).rotateY(rotateAngle));
- G4Transform3D transmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition).rotateY(mirrorAngle));
-
- // solid for the tube (including vacuum and wall): a solid cone
- G4Cons *tubeSolid = new G4Cons(volName, 0, rOuterStart, 0, rOuterEnd, zHalf, phi1, phi2);
-
- // tube consists of vacuum
- G4LogicalVolume *tubeLog = new G4LogicalVolume(tubeSolid, coreMaterial, volName, 0, 0, 0, true);
- tubeLog->SetVisAttributes(vacuumVisAttrib);
-
- // placement of the tube in the world, both at +z and -z
- new G4PVPlacement(transformer, tubeLog, volName, worldLog, false, 0);
- new G4PVPlacement(transmirror, tubeLog, volName, worldLog, false, 1);
-
+ ConeSegment cone(zHalf, 0, start.outer_r, 0, end.outer_r);
+ vol = Volume(name+"_"+nam+"_vakuum",cone,lcdd.vacuum());
+ vol.setVisAttributes(vacuumVis);
// if inner and outer radii are equal, then omit the tube wall
- if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
- // the wall solid: a tubular cone
- G4Cons *wallSolid = new G4Cons(volName + "_wall", rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf, phi1, phi2);
-
- // the wall consists of the material given in the database
- G4LogicalVolume *wallLog = new G4LogicalVolume(wallSolid, wallMaterial, volName + "_wall", 0, 0, 0, true);
- wallLog->SetVisAttributes(wallVisAttrib);
-
- // placement as a daughter volume of the tube, will appear in both placements of the tube
- new G4PVPlacement(0, 0, wallLog, volName + "_wall", tubeLog, false, 0);
- }
+ if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) { // the wall solid: a tubular cone
+ ConeSegment wall(zHalf, start.inner_r, start.outer_r, start.inner_r, end.outer_r);
+ Volume vol_wall(name+"_"+nam+"_wall",cone,mat);
+ vol.setVisAttributes(vis);
+ vol.placeVolume(vol_wall);
+ }
+ assembly.placeVolume(vol,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+ assembly.placeVolume(vol,Position(0,0,zPos).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
break;
}
case kPunchedCenter: {
// a volume on the z-axis with one or two inner holes
// (implemented as a cone from which tubes are punched out)
-
- const G4double rUpstreamPunch = rInnerStart; // just alias names denoting what is meant here
- const G4double rDnstreamPunch = rInnerEnd; // (the database entries are "abused" in this case)
-
- // relative transformations for the composition of the G4SubtractionVolumes
- G4Transform3D upstreamTransformer(G4RotationMatrix().rotateY(-crossingAngle), G4ThreeVector(zPosition * tan(-crossingAngle), 0, 0));
- G4Transform3D dnstreamTransformer(G4RotationMatrix().rotateY(+crossingAngle), G4ThreeVector(zPosition * tan(+crossingAngle), 0, 0));
-
- // absolute transformations for the final placement in the world (angles always equal zero and 180 deg)
- G4Transform3D placementTransformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition).rotateY(rotateAngle));
- G4Transform3D placementTransmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition).rotateY(mirrorAngle));
-
- // solid for the tube (including vacuum and wall): a solid cone
- G4Cons *tubeSolid = new G4Cons(volName, 0, rOuterStart, 0, rOuterEnd, zHalf, phi1, phi2);
-
- // tube consists of vacuum (will later have two different daughters)
- G4LogicalVolume *tubeLog0 = new G4LogicalVolume(tubeSolid, coreMaterial, volName + "_0", 0, 0, 0, true);
- G4LogicalVolume *tubeLog1 = new G4LogicalVolume(tubeSolid, coreMaterial, volName + "_1", 0, 0, 0, true);
- tubeLog0->SetVisAttributes(vacuumVisAttrib);
- tubeLog1->SetVisAttributes(vacuumVisAttrib);
-
- // placement of the tube in the world, both at +z and -z
- new G4PVPlacement(placementTransformer, tubeLog0, volName, worldLog, false, 0);
- new G4PVPlacement(placementTransmirror, tubeLog1, volName, worldLog, false, 1);
-
+ double rUpstreamPunch = start.inner_r; // just alias names denoting what is meant here
+ double rDnstreamPunch = end.inner_r; // (the database entries are "abused" in this case)
+ ConeSegment cone(zHalf, 0, start.outer_r, 0, end.outer_r);
+ vol = Volume(name+"_"+nam+"_vakuum",cone,lcdd.vacuum());
+ vol.setVisAttributes(vacuumVis);
+ assembly.placeVolume(vol,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+ assembly.placeVolume(vol,Position(0,0,zPos).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
+
// the wall solid and placeholders for possible G4SubtractionSolids
- G4Cons *wholeSolid = new G4Cons(volName + "_wall_whole", 0, rOuterStart, 0, rOuterEnd, zHalf, phi1, phi2);
- G4VSolid *tmpSolid0, *tmpSolid1, *wallSolid0, *wallSolid1;
-
+ ConeSegment wallCone(zHalf,0,start.outer_r,0,end.outer_r);
+ Solid solid1 = cone, solid2 = cone;
// the punched subtraction solids can be asymmetric and therefore have to be created twice:
// one time in the "right" way, another time in the "reverse" way, because the "mirroring"
// rotation around the y-axis will not only exchange +z and -z, but also +x and -x
- if (rUpstreamPunch) { // do we need a hole on the upstream branch?
- G4Tubs *upstreamPunch = new G4Tubs(volName + "_wall_punch_up", 0, rUpstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
- tmpSolid0 = new G4SubtractionSolid(volName + "_wall_tmp_0", wholeSolid, upstreamPunch, upstreamTransformer);
- tmpSolid1 = new G4SubtractionSolid(volName + "_wall_tmp_1", wholeSolid, upstreamPunch, dnstreamTransformer); // [sic]
- } else { // dont't do anything, just pass on the unmodified shape
- tmpSolid0 = wholeSolid;
- tmpSolid1 = wholeSolid;
- }
-
- if (rDnstreamPunch) { // do we need a hole on the downstream branch?
- G4Tubs *dnstreamPunch = new G4Tubs(volName + "_wall_punch_dn", 0, rDnstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
- wallSolid0 = new G4SubtractionSolid(volName + "_wall_0", tmpSolid0, dnstreamPunch, dnstreamTransformer);
- wallSolid1 = new G4SubtractionSolid(volName + "_wall_1", tmpSolid1, dnstreamPunch, upstreamTransformer); // [sic]
- } else { // dont't do anything, just pass on the unmodified shape
- wallSolid0 = tmpSolid0;
- wallSolid1 = tmpSolid1;
- }
-
+ if ( start.inner_r ) { // do we need a hole on the upstream branch?
+ Tube punch(0,start.inner_r,5*zHalf);
+ solid1 = SubtractionSolid(wallCone,punch,Position(zPos*std::tan(-crossingAngle),0,0),Rotation(0,-crossingAngle,0));
+ solid2 = SubtractionSolid(wallCone,punch,Position(zPos*std::tan(+crossingAngle),0,0),Rotation(0,+crossingAngle,0));
+ }
+ if ( end.inner_r ) { // do we need a hole on the downstream branch?
+ Tube punch(0,start.inner_r,5*zHalf);
+ solid1 = SubtractionSolid(solid1,punch,Position(zPos*std::tan(+crossingAngle),0,0),Rotation(0,+crossingAngle,0));
+ solid2 = SubtractionSolid(solid2,punch,Position(zPos*std::tan(-crossingAngle),0,0),Rotation(0,-crossingAngle,0));
+ }
// the wall consists of the material given in the database
- G4LogicalVolume *wallLog0 = new G4LogicalVolume(wallSolid0, wallMaterial, volName + "_wall_0", 0, 0, 0, true);
- G4LogicalVolume *wallLog1 = new G4LogicalVolume(wallSolid1, wallMaterial, volName + "_wall_1", 0, 0, 0, true);
- wallLog0->SetVisAttributes(wallVisAttrib);
- wallLog1->SetVisAttributes(wallVisAttrib);
-
- // placement as a daughter volumes of the tube
- new G4PVPlacement(0, 0, wallLog0, volName + "_wall", tubeLog0, false, 0);
- new G4PVPlacement(0, 0, wallLog1, volName + "_wall", tubeLog1, false, 1);
+ wall = Volume(name+"_"+nam+"_pos",solid1,mat);
+ wall.setVisAttributes(vis);
+ assembly.placeVolume(wall,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+ wall = Volume(name+"_"+nam+"_neg",solid2,mat);
+ wall.setVisAttributes(vis);
+ assembly.placeVolume(wall,Position(0,0,zPos).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
break;
}
case kPunchedUpstream:
case kPunchedDnstream: {
// a volume on the upstream or downstream branch with two inner holes
// (implemented as a cone from which another tube is punched out)
-
- const G4double rCenterPunch = (crossType == kPunchedUpstream) ? (rInnerStart) : (rInnerEnd); // just alias names denoting what is meant here
- const G4double rOffsetPunch = (crossType == kPunchedDnstream) ? (rInnerStart) : (rInnerEnd); // (the database entries are "abused" in this case)
-
- // relative transformations for the composition of the G4SubtractionVolumes
- G4Transform3D punchTransformer(G4RotationMatrix().rotateY(-2 * rotateAngle), G4ThreeVector(zPosition * tan(-2 * rotateAngle), 0, 0));
- G4Transform3D punchTransmirror(G4RotationMatrix().rotateY(+2 * rotateAngle), G4ThreeVector(zPosition * tan(+2 * rotateAngle), 0, 0));
-
- // absolute transformations for the final placement in the world
- G4Transform3D placementTransformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition).rotateY(rotateAngle));
- G4Transform3D placementTransmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition).rotateY(mirrorAngle));
-
- // solid for the tube (including vacuum and wall): a solid cone
- G4Cons *tubeSolid = new G4Cons(volName, 0, rOuterStart, 0, rOuterEnd, zHalf, phi1, phi2);
-
- // tube consists of vacuum (will later have two different daughters)
- G4LogicalVolume *tubeLog0 = new G4LogicalVolume(tubeSolid, coreMaterial, volName + "_0", 0, 0, 0, true);
- G4LogicalVolume *tubeLog1 = new G4LogicalVolume(tubeSolid, coreMaterial, volName + "_1", 0, 0, 0, true);
- tubeLog0->SetVisAttributes(vacuumVisAttrib);
- tubeLog1->SetVisAttributes(vacuumVisAttrib);
-
- // placement of the tube in the world, both at +z and -z
- new G4PVPlacement(placementTransformer, tubeLog0, volName, worldLog, false, 0);
- new G4PVPlacement(placementTransmirror, tubeLog1, volName, worldLog, false, 1);
-
+ double rCenterPunch = (crossType == kPunchedUpstream) ? start.inner_r : end.inner_r; // radius of the central hole
+ double rOffsetPunch = (crossType == kPunchedDnstream) ? start.inner_r : end.inner_r; // radius of the off-axis hole
+ ConeSegment cone(zHalf, 0, start.outer_r, 0, end.outer_r);
+ vol = Volume(name+"_"+nam+"_vakuum",cone,lcdd.vacuum());
+ vol.setVisAttributes(vacuumVis);
+
+ assembly.placeVolume(vol,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+ assembly.placeVolume(vol,Position(0,0,zPos).rotateY(reflect_angle),Rotation(0,reflect_angle,0));
+
// the wall solid and the piece (only a tube, for the moment) which will be punched out
- G4Cons *wholeSolid = new G4Cons(volName + "_wall_whole", rCenterPunch, rOuterStart, rCenterPunch, rOuterEnd, zHalf, phi1, phi2);
- G4Tubs *punchSolid = new G4Tubs(volName + "_wall_punch", 0, rOffsetPunch, 5 * zHalf, phi1, phi2); // a bit longer
-
+ ConeSegment whole(zHalf,rCenterPunch,start.outer_r,rCenterPunch,end.outer_r);
+ Tube punch(0,rOffsetPunch,5*zHalf);
// the punched subtraction solids can be asymmetric and therefore have to be created twice:
// one time in the "right" way, another time in the "reverse" way, because the "mirroring"
// rotation around the y-axis will not only exchange +z and -z, but also +x and -x
- G4SubtractionSolid *wallSolid0 = new G4SubtractionSolid(volName + "_wall_0", wholeSolid, punchSolid, punchTransformer);
- G4SubtractionSolid *wallSolid1 = new G4SubtractionSolid(volName + "_wall_1", wholeSolid, punchSolid, punchTransmirror);
-
- // the wall consists of the material given in the database
- G4LogicalVolume *wallLog0 = new G4LogicalVolume(wallSolid0, wallMaterial, volName + "_wall_0", 0, 0, 0, true);
- G4LogicalVolume *wallLog1 = new G4LogicalVolume(wallSolid1, wallMaterial, volName + "_wall_1", 0, 0, 0, true);
- wallLog0->SetVisAttributes(wallVisAttrib);
- wallLog1->SetVisAttributes(wallVisAttrib);
-
- // placement as a daughter volumes of the tube
- new G4PVPlacement(0, 0, wallLog0, volName + "_wall", tubeLog0, false, 0);
- new G4PVPlacement(0, 0, wallLog1, volName + "_wall", tubeLog1, false, 1);
- break;
+ solid = SubtractionSolid(whole, punch, Position(zPos*std::tan(-crossingAngle),0,0),Rotation(0,-crossingAngle,0));
+ wall = Volume(name+"_"+nam+"_wall_pos",solid,mat);
+ wall.setVisAttributes(vis);
+ assembly.placeVolume(wall,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+
+ solid = SubtractionSolid(whole, punch, Position(zPos*std::tan(crossingAngle),0,0),Rotation(0,crossingAngle,0));
+ wall = Volume(name+"_"+nam+"_wall_neg",solid,mat);
+ wall.setVisAttributes(vis);
+ assembly.placeVolume(wall,Position(0,0,zPos).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
+ break;
}
case kUpstreamClippedFront:
case kDnstreamClippedFront:
case kUpstreamSlicedFront:
case kDnstreamSlicedFront: {
// a volume on the upstream or donwstream branch, but with the front face parallel to the xy-plane
- // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
+ // or to a piece tilted in the other direction ("sliced" like a salami with 2 * angle)
// (implemented as a slightly longer cone from which the end is clipped off)
// the volume which will be used for clipping: a solid tube
- const G4double clipSize = rOuterStart; // the right order of magnitude for the clipping volume (alias name)
- G4Tubs *clipSolid = new G4Tubs(volName + "_clip", 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
-
+ double clipSize = start.outer_r; // the right order of magnitude for the clipping volume (alias name)
+ Tube clip(0, 2 * clipSize, clipSize);
// relative transformations for the composition of the G4SubtractionVolumes
- const G4double clipAngle = (crossType == kUpstreamClippedFront || crossType == kDnstreamClippedFront) ? (rotateAngle) : (2 * rotateAngle);
- const G4double clipShift = (zStart - clipSize) / cos(clipAngle) - (zPosition - clipSize / 2); // question: why is this correct?
- G4Transform3D clipTransformer(G4RotationMatrix().rotateY(-clipAngle), G4ThreeVector(0, 0, clipShift));
- G4Transform3D clipTransmirror(G4RotationMatrix().rotateY(+clipAngle), G4ThreeVector(0, 0, clipShift));
-
- // absolute transformations for the final placement in the world
- G4Transform3D placementTransformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition - clipSize / 2).rotateY(rotateAngle));
- G4Transform3D placementTransmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition - clipSize / 2).rotateY(mirrorAngle));
-
- // solid for the tube (including vacuum and wall): a solid cone
- G4Cons *wholeSolid = new G4Cons(volName + "_whole", 0, rOuterStart, 0, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
-
- // clip away the protruding end
- G4SubtractionSolid *tubeSolid0 = new G4SubtractionSolid(volName + "_0", wholeSolid, clipSolid, clipTransformer);
- G4SubtractionSolid *tubeSolid1 = new G4SubtractionSolid(volName + "_1", wholeSolid, clipSolid, clipTransmirror);
-
- // tube consists of vacuum (will later have two different daughters)
- G4LogicalVolume *tubeLog0 = new G4LogicalVolume(tubeSolid0, coreMaterial, volName + "_0", 0, 0, 0, true);
- G4LogicalVolume *tubeLog1 = new G4LogicalVolume(tubeSolid1, coreMaterial, volName + "_1", 0, 0, 0, true);
- tubeLog0->SetVisAttributes(vacuumVisAttrib);
- tubeLog1->SetVisAttributes(vacuumVisAttrib);
-
- // placement of the tube in the world, both at +z and -z
- new G4PVPlacement(placementTransformer, tubeLog0, volName, worldLog, false, 0);
- new G4PVPlacement(placementTransmirror, tubeLog1, volName, worldLog, false, 1);
-
- if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
- // the wall solid: a tubular cone
- G4Cons *wallWholeSolid = new G4Cons(volName + "_wall_whole", rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
-
- // clip away the protruding end
- G4SubtractionSolid *wallSolid0 = new G4SubtractionSolid(volName + "_wall_0", wallWholeSolid, clipSolid, clipTransformer);
- G4SubtractionSolid *wallSolid1 = new G4SubtractionSolid(volName + "_wall_1", wallWholeSolid, clipSolid, clipTransmirror);
-
- // the wall consists of the material given in the database
- G4LogicalVolume *wallLog0 = new G4LogicalVolume(wallSolid0, wallMaterial, volName + "_wall_0", 0, 0, 0, true);
- G4LogicalVolume *wallLog1 = new G4LogicalVolume(wallSolid1, wallMaterial, volName + "_wall_1", 0, 0, 0, true);
- wallLog0->SetVisAttributes(wallVisAttrib);
- wallLog1->SetVisAttributes(wallVisAttrib);
-
- // placement as a daughter volumes of the tube
- new G4PVPlacement(0, 0, wallLog0, volName + "_wall", tubeLog0, false, 0);
- new G4PVPlacement(0, 0, wallLog1, volName + "_wall", tubeLog1, false, 1);
- }
- break;
+ double clipAngle = (crossType == kUpstreamClippedFront || crossType == kDnstreamClippedFront) ? (angle) : (2 * angle);
+ double clipShift = (start.z - clipSize) / cos(clipAngle) - (zPos - clipSize / 2); // question: why is this correct?
+ Position clip_pos(0,0,clipShift), clip_pos_pos(clip_pos), clip_pos_neg(clip_pos);
+ clip_pos_pos.rotateY(-clipAngle);
+ clip_pos_neg.rotateY(+clipAngle);
+
+ ConeSegment wallCone, whole(zHalf+clipSize/2, 0, start.outer_r, 0, end.outer_r);
+ solid = SubtractionSolid(whole, clip, clip_pos_pos,Rotation(0,-clipAngle,0));
+ wall = Volume(name+"_"+nam+"_pos",solid,lcdd.vacuum());
+ wall.setVisAttributes(vacuumVis);
+ if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+ wallCone = ConeSegment(zHalf+clipSize/2,start.inner_r,start.outer_r,end.inner_r,end.outer_r);
+ SubtractionSolid wallSolid(wallCone,clip,clip_pos_pos,Rotation(0,-clipAngle,0));
+ Volume wall (name+"_"+nam+"_wall_solid",wallSolid,mat);
+ wall.setVisAttributes(vis);
+ wall.placeVolume(wall);
+ }
+ assembly.placeVolume(wall,Position(0,0,zPos-clipSize/2).rotateY(angle),Rotation(0,angle,0));
+
+ solid = SubtractionSolid(whole, clip, clip_pos_neg,Rotation(0,clipAngle,0));
+ wall = Volume(name+"_"+nam+"_wall_neg",solid,lcdd.vacuum());
+ wall.setVisAttributes(vis);
+ if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+ SubtractionSolid wallSolid(wallCone,clip, clip_pos_neg, Rotation(0,+clipAngle,0));
+ Volume wall (name+"_"+nam+"_wall_solid",wallSolid,mat);
+ wall.placeVolume(wall);
+ }
+ assembly.placeVolume(wall,Position(0,0,zPos - clipSize / 2).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
+ break;
}
case kUpstreamClippedRear:
case kDnstreamClippedRear:
case kUpstreamSlicedRear:
case kDnstreamSlicedRear: {
// a volume on the upstream or donwstream branch, but with the rear face parallel to the xy-plane
- // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
+ // or to a piece tilted in the other direction ("sliced" like a salami with 2 * angle)
// (implemented as a slightly longer cone from which the end is clipped off)
// the volume which will be used for clipping: a solid tube
- const G4double clipSize = rOuterEnd; // the right order of magnitude for the clipping volume (alias name)
- G4Tubs *clipSolid = new G4Tubs(volName + "_clip", 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
-
+ double clipSize = start.outer_r; // the right order of magnitude for the clipping volume (alias name)
+ Tube clip(0, 2 * clipSize, clipSize);
// relative transformations for the composition of the G4SubtractionVolumes
- const G4double clipAngle = (crossType == kUpstreamClippedRear || crossType == kDnstreamClippedRear) ? (rotateAngle) : (2 * rotateAngle);
- const G4double clipShift = (zEnd + clipSize) / cos(clipAngle) - (zPosition + clipSize / 2); // question: why is this correct?
- G4Transform3D clipTransformer(G4RotationMatrix().rotateY(-clipAngle), G4ThreeVector(0, 0, clipShift));
- G4Transform3D clipTransmirror(G4RotationMatrix().rotateY(+clipAngle), G4ThreeVector(0, 0, clipShift));
-
- // absolute transformations for the final placement in the world
- G4Transform3D placementTransformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition + clipSize / 2).rotateY(rotateAngle));
- G4Transform3D placementTransmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition + clipSize / 2).rotateY(mirrorAngle));
-
- // solid for the tube (including vacuum and wall): a solid cone
- G4Cons *wholeSolid = new G4Cons(volName + "_whole", 0, rOuterStart, 0, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
-
- // clip away the protruding end
- G4SubtractionSolid *tubeSolid0 = new G4SubtractionSolid(volName + "_0", wholeSolid, clipSolid, clipTransformer);
- G4SubtractionSolid *tubeSolid1 = new G4SubtractionSolid(volName + "_1", wholeSolid, clipSolid, clipTransmirror);
-
- // tube consists of vacuum (will later have two different daughters)
- G4LogicalVolume *tubeLog0 = new G4LogicalVolume(tubeSolid0, coreMaterial, volName + "_0", 0, 0, 0, true);
- G4LogicalVolume *tubeLog1 = new G4LogicalVolume(tubeSolid1, coreMaterial, volName + "_1", 0, 0, 0, true);
- tubeLog0->SetVisAttributes(vacuumVisAttrib);
- tubeLog1->SetVisAttributes(vacuumVisAttrib);
-
- // placement of the tube in the world, both at +z and -z
- new G4PVPlacement(placementTransformer, tubeLog0, volName, worldLog, false, 0);
- new G4PVPlacement(placementTransmirror, tubeLog1, volName, worldLog, false, 1);
-
- if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
- // the wall solid: a tubular cone
- G4Cons *wallWholeSolid = new G4Cons(volName + "_wall_whole", rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
-
- // clip away the protruding end
- G4SubtractionSolid *wallSolid0 = new G4SubtractionSolid(volName + "_wall_0", wallWholeSolid, clipSolid, clipTransformer);
- G4SubtractionSolid *wallSolid1 = new G4SubtractionSolid(volName + "_wall_1", wallWholeSolid, clipSolid, clipTransmirror);
-
- // the wall consists of the material given in the database
- G4LogicalVolume *wallLog0 = new G4LogicalVolume(wallSolid0, wallMaterial, volName + "_wall_0", 0, 0, 0, true);
- G4LogicalVolume *wallLog1 = new G4LogicalVolume(wallSolid1, wallMaterial, volName + "_wall_1", 0, 0, 0, true);
- wallLog0->SetVisAttributes(wallVisAttrib);
- wallLog1->SetVisAttributes(wallVisAttrib);
-
- // placement as a daughter volumes of the tube
- new G4PVPlacement(0, 0, wallLog0, volName + "_wall", tubeLog0, false, 0);
- new G4PVPlacement(0, 0, wallLog1, volName + "_wall", tubeLog1, false, 1);
- }
- break;
+ double clipAngle = (crossType == kUpstreamClippedRear || crossType == kDnstreamClippedRear) ? (angle) : (2 * angle);
+ double clipShift = (end.z + clipSize) / cos(clipAngle) - (zPos + clipSize / 2); // question: why is this correct?
+ Position clip_pos(0,0,clipShift), clip_pos_pos(clip_pos), clip_pos_neg(clip_pos);
+ clip_pos_pos.rotateY(-clipAngle);
+ clip_pos_neg.rotateY(+clipAngle);
+
+ ConeSegment wallCone, whole(zHalf+clipSize/2,0, start.outer_r, 0, end.outer_r);
+ solid = SubtractionSolid(whole, clip, clip_pos_pos,Rotation(0,-clipAngle,0));
+ vol = Volume(name+"_"+nam+"_pos",solid,lcdd.vacuum());
+ vol.setVisAttributes(vacuumVis);
+ if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+ wallCone = ConeSegment(zHalf + clipSize/2,start.inner_r,start.outer_r,end.inner_r,end.outer_r);
+ solid = SubtractionSolid(wallCone,clip,clip_pos_pos,Rotation(0,-clipAngle,0));
+ Volume wall (name+"_"+nam+"_wall_solid",solid,mat);
+ wall.setVisAttributes(vis);
+ vol.placeVolume(wall);
+ }
+ assembly.placeVolume(vol,Position(0,0,zPos+clipSize/2).rotateY(angle),Rotation(0,angle,0));
+
+ solid = SubtractionSolid(whole, clip, clip_pos_neg,Rotation(0,clipAngle,0));
+ vol = Volume(name+"_"+nam+"_wall_neg",solid,lcdd.vacuum());
+ vol.setVisAttributes(vis);
+ if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+ solid = SubtractionSolid(wallCone, clip, clip_pos_neg, Rotation(0,+clipAngle,0));
+ Volume wall (name+"_"+nam+"_wall_solid",solid,mat);
+ wall.setVisAttributes(vis);
+ vol.placeVolume(wall);
+ }
+ assembly.placeVolume(vol,Position(0,0,zPos+clipSize/2).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
+ break;
}
case kUpstreamClippedBoth:
case kDnstreamClippedBoth:
case kUpstreamSlicedBoth:
case kDnstreamSlicedBoth: {
// a volume on the upstream or donwstream branch, but with both faces parallel to the xy-plane
- // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
+ // or to a piece tilted in the other direction ("sliced" like a salami with 2 * angle)
// (implemented as a slightly longer cone from which the end is clipped off)
-
+
// the volume which will be used for clipping: a solid tube
- const G4double clipSize = rOuterEnd; // the right order of magnitude for the clipping volume (alias name)
- G4Tubs *clipSolid = new G4Tubs(volName + "_clip", 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
-
+ double clipSize = end.outer_r; // the right order of magnitude for the clipping volume (alias name)
+ Tube clip(0, 2 * clipSize, clipSize);
// relative transformations for the composition of the G4SubtractionVolumes
- const G4double clipAngle = (crossType == kUpstreamClippedBoth || crossType == kDnstreamClippedBoth) ? (rotateAngle) : (2 * rotateAngle);
- const G4double clipShiftFrnt = (zStart - clipSize) / cos(clipAngle) - zPosition;
- const G4double clipShiftRear = (zEnd + clipSize) / cos(clipAngle) - zPosition;
- G4Transform3D clipTransformerFrnt(G4RotationMatrix().rotateY(-clipAngle), G4ThreeVector(0, 0, clipShiftFrnt));
- G4Transform3D clipTransformerRear(G4RotationMatrix().rotateY(-clipAngle), G4ThreeVector(0, 0, clipShiftRear));
- G4Transform3D clipTransmirrorFrnt(G4RotationMatrix().rotateY(+clipAngle), G4ThreeVector(0, 0, clipShiftFrnt));
- G4Transform3D clipTransmirrorRear(G4RotationMatrix().rotateY(+clipAngle), G4ThreeVector(0, 0, clipShiftRear));
-
- // absolute transformations for the final placement in the world
- G4Transform3D placementTransformer(G4RotationMatrix().rotateY(rotateAngle), G4ThreeVector(0, 0, zPosition).rotateY(rotateAngle));
- G4Transform3D placementTransmirror(G4RotationMatrix().rotateY(mirrorAngle), G4ThreeVector(0, 0, zPosition).rotateY(mirrorAngle));
-
+ double clipAngle = (crossType == kUpstreamClippedBoth || crossType == kDnstreamClippedBoth) ? (angle) : (2 * angle);
+ double clipShiftFrnt = (start.z - clipSize) / cos(clipAngle) - zPos;
+ double clipShiftRear = (end.z + clipSize) / cos(clipAngle) - zPos;
// solid for the tube (including vacuum and wall): a solid cone
- G4Cons *wholeSolid = new G4Cons(volName + "_whole", 0, rOuterStart, 0, rOuterEnd, zHalf + clipSize, phi1, phi2); // a bit longer
-
- // clip away the protruding ends
- G4SubtractionSolid *tmpSolid0 = new G4SubtractionSolid(volName + "_tmp_0", wholeSolid, clipSolid, clipTransformerFrnt);
- G4SubtractionSolid *tmpSolid1 = new G4SubtractionSolid(volName + "_tmp_1", wholeSolid, clipSolid, clipTransmirrorFrnt);
- G4SubtractionSolid *tubeSolid0 = new G4SubtractionSolid(volName + "_0", tmpSolid0, clipSolid, clipTransformerRear);
- G4SubtractionSolid *tubeSolid1 = new G4SubtractionSolid(volName + "_1", tmpSolid1, clipSolid, clipTransmirrorRear);
-
- // tube consists of vacuum (will later have two different daughters)
- G4LogicalVolume *tubeLog0 = new G4LogicalVolume(tubeSolid0, coreMaterial, volName + "_0", 0, 0, 0, true);
- G4LogicalVolume *tubeLog1 = new G4LogicalVolume(tubeSolid1, coreMaterial, volName + "_1", 0, 0, 0, true);
- tubeLog0->SetVisAttributes(vacuumVisAttrib);
- tubeLog1->SetVisAttributes(vacuumVisAttrib);
-
- // placement of the tube in the world, both at +z and -z
- new G4PVPlacement(placementTransformer, tubeLog0, volName, worldLog, false, 0);
- new G4PVPlacement(placementTransmirror, tubeLog1, volName, worldLog, false, 1);
-
- if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
- // the wall solid: a tubular cone
- G4Cons *wallWholeSolid = new G4Cons(volName + "_wall_whole", rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf + clipSize, phi1, phi2); // a bit longer
-
+ ConeSegment wallCone, whole(zHalf + clipSize, 0, start.outer_r, 0, end.outer_r);
+
+ // Primary side:
+ solid = SubtractionSolid(whole, clip, Position(0,0,clipShiftFrnt),Rotation(0,-clipAngle,0));
+ solid = SubtractionSolid(whole, clip, Position(0,0,clipShiftRear),Rotation(0,-clipAngle,0));
+ vol = Volume(name+"_"+nam+"_pos",solid,lcdd.vacuum());
+ vol.setVisAttributes(vacuumVis);
+ if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+ wallCone = ConeSegment(zHalf + clipSize,start.inner_r,start.outer_r,end.inner_r,end.outer_r);
// clip away the protruding ends
- G4SubtractionSolid *wallTmpSolid0 = new G4SubtractionSolid(volName + "_wall_tmp_0", wallWholeSolid, clipSolid, clipTransformerFrnt);
- G4SubtractionSolid *wallTmpSolid1 = new G4SubtractionSolid(volName + "_wall_tmp_1", wallWholeSolid, clipSolid, clipTransmirrorFrnt);
- G4SubtractionSolid *wallSolid0 = new G4SubtractionSolid(volName + "_wall_0", wallTmpSolid0, clipSolid, clipTransformerRear);
- G4SubtractionSolid *wallSolid1 = new G4SubtractionSolid(volName + "_wall_1", wallTmpSolid1, clipSolid, clipTransmirrorRear);
-
- // the wall consists of the material given in the database
- G4LogicalVolume *wallLog0 = new G4LogicalVolume(wallSolid0, wallMaterial, volName + "_wall_0", 0, 0, 0, true);
- G4LogicalVolume *wallLog1 = new G4LogicalVolume(wallSolid1, wallMaterial, volName + "_wall_1", 0, 0, 0, true);
- wallLog0->SetVisAttributes(wallVisAttrib);
- wallLog1->SetVisAttributes(wallVisAttrib);
-
- // placement as a daughter volumes of the tube
- new G4PVPlacement(0, 0, wallLog0, volName + "_wall", tubeLog0, false, 0);
- new G4PVPlacement(0, 0, wallLog1, volName + "_wall", tubeLog1, false, 1);
- }
+ solid = SubtractionSolid(wallCone,clip,Position(0,0,clipShiftFrnt),Rotation(0,-clipAngle,0));
+ solid = SubtractionSolid(solid, clip,Position(0,0,clipShiftRear),Rotation(0,-clipAngle,0));
+ wall = Volume(name+"_"+nam+"_pos_wall",solid,mat);
+ wall.setVisAttributes(vis);
+ vol.placeVolume(wall);
+ }
+ assembly.placeVolume(vol,Position(0,0,zPos).rotateY(angle),Rotation(0,angle,0));
+
+ // Mirror side:
+ solid = SubtractionSolid(whole, clip, Position(0,0,clipShiftFrnt),Rotation(0,+clipAngle,0));
+ solid = SubtractionSolid(whole, clip, Position(0,0,clipShiftRear),Rotation(0,+clipAngle,0));
+ vol = Volume(name+"_"+nam+"_wall_neg",solid,lcdd.vacuum());
+ vol.setVisAttributes(vis);
+ if (start.inner_r != start.outer_r || end.inner_r != end.outer_r) {
+ solid = SubtractionSolid(wallCone,clip,Position(0,0,clipShiftFrnt),Rotation(0,+clipAngle,0));
+ solid = SubtractionSolid(solid, clip,Position(0,0,clipShiftRear),Rotation(0,+clipAngle,0));
+ Volume wall (name+"_"+nam+"_neg_wall",solid,mat);
+ wall.setVisAttributes(vis);
+ vol.placeVolume(wall);
+ }
+ assembly.placeVolume(vol,Position(0,0,zPos).rotateY(reflect_angle),Rotation(M_PI,reflect_angle,0));
break;
}
- default: {
- Control::Log("TubeX01: Unimplemented \"crossType\" code.");
- return false; // fatal failure
- }
- } // switch (crossType)
- } // while (db->getTuple())
- delete db;
- return true;
+ default: {
+ cout << "MaskX01: Unimplemented \"crossType\" code:" << crossType << endl;
+ throw runtime_error("MaskX01: Unimplemented \"crossType\" code.");
+ break;
+ }
+ }
+ }
+ assembly.setVisAttributes(lcdd.visAttributes(x_det.visStr()));
+ sdet.setPlacement(lcdd.pickMotherVolume(sdet).placeVolume(assembly));
+ return sdet;
}
-#endif
+
+DECLARE_DETELEMENT(Tesla_tubeX01,create_element);
diff --git a/DDExamples/ILDExDet/src/compact/Tesla_yoke02_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_yoke02_geo.cpp
index 6ece95496..88365203e 100644
--- a/DDExamples/ILDExDet/src/compact/Tesla_yoke02_geo.cpp
+++ b/DDExamples/ILDExDet/src/compact/Tesla_yoke02_geo.cpp
@@ -18,7 +18,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
xml_det_t x_det = e;
string name = x_det.nameStr();
DetElement sdet(name,x_det.id());
- Assembly assembly(name+"_assembly");
+ Assembly assembly(name);
xml_comp_t x_barrel = x_det.child(Unicode("barrel"));
xml_comp_t x_endcap = x_det.child(Unicode("endcap"));
param_t barrel = { x_barrel.inner_r(), x_barrel.outer_r(), x_barrel.zhalf()};
@@ -43,7 +43,8 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens)
assembly.placeVolume(volume,Position(0,0,-x_endcap.z()));
}
- lcdd.pickMotherVolume(sdet).placeVolume(assembly);
+ PlacedVolume pv = lcdd.pickMotherVolume(sdet).placeVolume(assembly);
+ sdet.setPlacement(pv);
return sdet;
}
--
GitLab