diff --git a/DDExamples/CLICSiD/src/CylindricalBarrelCalorimeter_geo.cpp b/DDExamples/CLICSiD/src/CylindricalBarrelCalorimeter_geo.cpp index 0ee29506b815f7fde51c3441334a42d8cd0d1678..f523514946a5126ca140f446dea6033d2b7c18ee 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 9282af5095cc36babbe1e31aaa6c09cd45869305..86661b81bf37c7e1dfba5cea0a08d079dce607e8 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 1cd4ce24e1a80fbcaf817f2037628a61f59dbdca..64e5979fafd5459315f29fa108b52706cba7184b 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 905b5db5c7427a8b2ae93decf9d356ec04ae171f..a97a54aab71eddce37bb3529ff013549540ed68d 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 2037f94eb1347914af817135f720b1995d90ef7c..fe912f8e3d8a1470fe27851a860bda2ad4947004 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 e6a30fb29be6ed6d7d5ee3800e3683303bbd6af6..b4057d80e9c64aecfbd0731ad93a24de3e957c39 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 05acb78a30e16e64d21c22624358967d6a052748..9b9c0a7e12d890188c4c003b23abeee742039fc2 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 6521a6c491d4696023d3112d0a599e6db330d017..0ff59c3e628ac514effe8d94c0dc5d29bed66411 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 1e78c150847bf9ea10dd473d29cfba10e8da5bb0..3d23524d5f5facd2ee31bfe7b2e194c681cf71b5 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 161ace0fbab6fb6362455220b2f6f309936f616d..9d76987fe2bc8a5de92994bbad4b4d536e86edd8 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 29f3388f9aa93a57525ce2869e8024312fb18656..a7f4f6e35235aac6984bd76b1dbbc411c5815a3d 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 c011d1ea691ad18b43c83dd59255b0958e290929..55347be4d0d7b5af147526a77e13cff2a04804f8 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 bc84d0771a6cf5224ba04934af0fbd55963e3350..eb7fe41c7c5c6daa07d32b0f430111c0631194f7 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 12253bb2052f94d8d15337b820d1bb75201ce28b..be9b8cce3f7b26160d7c5da0ccbc720ddfe2f9b4 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 6ece95496f5567e246c50168ef9190def38e489f..88365203ee326336a17c2a3e823184ebe522b59f 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; }