diff --git a/source/geometries/Honeycomb.cc b/source/geometries/Honeycomb.cc new file mode 100644 index 0000000000..bc4112e72c --- /dev/null +++ b/source/geometries/Honeycomb.cc @@ -0,0 +1,193 @@ +// ---------------------------------------------------------------------------- +// nexus | Honeycomb.cc +// +// Support structure to the EP copper plate. +// +// The NEXT Collaboration +// ---------------------------------------------------------------------------- + +#include "Honeycomb.h" +#include "HoneycombBeam.h" +#include "MaterialsList.h" +#include "Visibilities.h" +#include "CylinderPointSampler.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace nexus { + + using namespace CLHEP; + + Honeycomb::Honeycomb(): GeometryBase(), + angle_(pi / 6.), + beam_dist_(102.25 * mm), + beam_thickn_(6 * mm) + { + compl_angle_ = pi/2. - angle_; + + /// Initializing the geometry navigator (used in vertex generation) + geom_navigator_ = + G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking(); + } + + Honeycomb::~Honeycomb() + { + } + + void Honeycomb::Construct() + { + G4double shorter_height = 117 * mm; + G4double longer_height = 130 * mm; + G4double longer_length = 1210.6*mm; + + HoneycombBeam* short_beam = + new HoneycombBeam(beam_thickn_, 1085.9*mm, 184*mm, shorter_height); + HoneycombBeam* medium_beam = + new HoneycombBeam(beam_thickn_, 1170.2*mm, 273.5*mm, longer_height); + HoneycombBeam* long_beam = + new HoneycombBeam(beam_thickn_, longer_length, 407.4*mm, longer_height); + + G4double short_displ = (longer_height-shorter_height)/2.; + + short_beam->Construct(); + medium_beam->Construct(); + long_beam->Construct(); + + + G4MultiUnion* struct_solid = new G4MultiUnion("HONEYCOMB"); + + G4RotationMatrix rot; + rot.rotateX(3*pi/2.); + + G4ThreeVector ini_pos = + G4ThreeVector(-(beam_dist_+beam_thickn_)/2., 0., 0.); + struct_solid->AddNode(long_beam->GetSolidVol(), + G4Transform3D(rot, ini_pos)); + + G4RotationMatrix rot_left; + rot_left.rotateX(3*pi/2.); + rot_left.rotateY(-compl_angle_); + G4RotationMatrix rot_right; + rot_right.rotateX(3*pi/2.); + rot_right.rotateY(-(pi/2.+angle_)); + + G4double r_pos = + 1/2*beam_dist_+ 2*(beam_dist_+beam_thickn_) + 1/2*beam_thickn_; + r_pos = r_pos + (beam_dist_ + beam_thickn_)/2.*cos(compl_angle_) + 2.75*cm; + G4double x = r_pos * sin(angle_); + G4double z = r_pos * cos(angle_); + + struct_solid->AddNode(short_beam->GetSolidVol(), + G4Transform3D(rot_left, + G4ThreeVector(x, short_displ, z))); + struct_solid->AddNode(short_beam->GetSolidVol(), + G4Transform3D(rot_right, + G4ThreeVector(-x, short_displ, z))); + struct_solid->AddNode(short_beam->GetSolidVol(), + G4Transform3D(rot_left, + G4ThreeVector(-x, short_displ, -z))); + struct_solid->AddNode(short_beam->GetSolidVol(), + G4Transform3D(rot_right, + G4ThreeVector(x, short_displ, -z))); + + + x = (r_pos-(beam_dist_+beam_thickn_)) * sin(angle_); + z = (r_pos-(beam_dist_+beam_thickn_)) * cos(angle_); + struct_solid->AddNode(medium_beam->GetSolidVol(), + G4Transform3D(rot_left, G4ThreeVector(x, 0., z))); + struct_solid->AddNode(medium_beam->GetSolidVol(), + G4Transform3D(rot_left, G4ThreeVector(-x, 0., -z))); + struct_solid->AddNode(medium_beam->GetSolidVol(), + G4Transform3D(rot_right, G4ThreeVector(x, 0., -z))); + + struct_solid->AddNode(medium_beam->GetSolidVol(), + G4Transform3D(rot_right, G4ThreeVector(-x, 0., z))); + + + x = (r_pos-2*(beam_dist_+beam_thickn_)) * sin(angle_); + z = (r_pos-2*(beam_dist_+beam_thickn_)) * cos(angle_); + struct_solid->AddNode(long_beam->GetSolidVol(), + G4Transform3D(rot_left, G4ThreeVector(x, 0., z))); + + + struct_solid->AddNode(long_beam->GetSolidVol(), + G4Transform3D(rot_left, G4ThreeVector(-x, 0., -z))); + + struct_solid->AddNode(long_beam->GetSolidVol(), + G4Transform3D(rot_right, G4ThreeVector(x, 0., -z))); + struct_solid->AddNode(long_beam->GetSolidVol(), + G4Transform3D(rot_right, G4ThreeVector(-x, 0., z))); + + + x = ini_pos.x() - (beam_dist_+beam_thickn_); + struct_solid->AddNode(medium_beam->GetSolidVol(), + G4Transform3D(rot, G4ThreeVector(x, 0., 0.))); + x = ini_pos.x() - 2*(beam_dist_+beam_thickn_); + struct_solid->AddNode(short_beam->GetSolidVol(), + G4Transform3D(rot, + G4ThreeVector(x, short_displ, 0.))); + x = ini_pos.x() + (beam_dist_+beam_thickn_); + struct_solid->AddNode(long_beam->GetSolidVol(), + G4Transform3D(rot, G4ThreeVector(x, 0., 0.))); + x = ini_pos.x() + 2*(beam_dist_+beam_thickn_); + struct_solid->AddNode(medium_beam->GetSolidVol(), + G4Transform3D(rot, G4ThreeVector(x, 0., 0.))); + x = ini_pos.x() + 3*(beam_dist_+beam_thickn_); + struct_solid->AddNode(short_beam->GetSolidVol(), + G4Transform3D(rot, + G4ThreeVector(x, short_displ, 0.))); + + struct_solid->Voxelize(); + + G4LogicalVolume* struct_logic = + new G4LogicalVolume(struct_solid, materials::Steel(), "HONEYCOMB"); + + G4RotationMatrix rot_placement; + rot_placement.rotateZ(-pi/2); + rot_placement.rotateY(-pi/2); + + G4double hc_posz = end_of_EP_copper_plate_z_ + longer_height/2.; + new G4PVPlacement(G4Transform3D(rot_placement, + G4ThreeVector(0., 0., hc_posz)), + struct_logic, "HONEYCOMB", mother_logic_, + false, 0, false); + + G4VisAttributes red_col = nexus::Red(); + red_col.SetForceSolid(true); + struct_logic->SetVisAttributes(red_col); + + // Vertex generator + gen_ = + new CylinderPointSampler(0., longer_length/2., longer_height/2., + 0., 360.*deg, 0, + G4ThreeVector(0., 0., hc_posz)); + + } + + G4ThreeVector Honeycomb::GenerateVertex(const G4String& region) const + { + G4ThreeVector vertex(0, 0, 0); + + if (region == "HONEYCOMB") { + G4VPhysicalVolume* VertexVolume; + do { + vertex = gen_->GenerateVertex(VOLUME); + G4ThreeVector glob_vtx(vertex); + glob_vtx = glob_vtx - GetCoordOrigin(); + VertexVolume = geom_navigator_->LocateGlobalPointAndSetup(glob_vtx, 0, false); + } while (VertexVolume->GetName() != region); + } + else { + G4Exception("[Honeycomb]", "GenerateVertex()", FatalException, + "Unknown vertex generation region!"); + } + + return vertex; + } +} diff --git a/source/geometries/Honeycomb.h b/source/geometries/Honeycomb.h new file mode 100644 index 0000000000..654f00427f --- /dev/null +++ b/source/geometries/Honeycomb.h @@ -0,0 +1,64 @@ +// ---------------------------------------------------------------------------- +// nexus | Honeycomb.h +// +// Support structure to the EP copper plate. +// +// The NEXT Collaboration +// ---------------------------------------------------------------------------- + +#ifndef HONEYCOMB_H +#define HONEYCOMB_H + +#include "GeometryBase.h" + +#include + +namespace nexus { + class CylinderPointSampler; + + class Honeycomb: public GeometryBase + { + public: + /// Constructor + Honeycomb(); + + /// Destructor + ~Honeycomb(); + + void Construct(); + + /// Generate a vertex within a given region of the geometry + G4ThreeVector GenerateVertex(const G4String& region) const; + + /// Sets the logical volume where all inner elements are placed + void SetMotherLogicalVolume(G4LogicalVolume* mother_logic); + + /// Sets the z position of the outer surface of the copper plate + void SetEndOfCopperPlateZ(G4double z); + + + + private: + + G4LogicalVolume* mother_logic_; + + G4double end_of_EP_copper_plate_z_; + + // Relationships among beams + G4double angle_, beam_dist_, beam_thickn_; + G4double compl_angle_; + + CylinderPointSampler* gen_; + + G4Navigator* geom_navigator_; + }; + + inline void Honeycomb::SetMotherLogicalVolume(G4LogicalVolume* mother_logic) { + mother_logic_ = mother_logic;} + + inline void Honeycomb::SetEndOfCopperPlateZ(G4double z) { + end_of_EP_copper_plate_z_ = z;} + +} // end namespace nexus + +#endif diff --git a/source/geometries/HoneycombBeam.cc b/source/geometries/HoneycombBeam.cc new file mode 100644 index 0000000000..ac3fdefd8a --- /dev/null +++ b/source/geometries/HoneycombBeam.cc @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------- +// nexus | HoneycombBeam.cc +// +// Beam of the support structure to the EP copper plate. +// +// The NEXT Collaboration +// ---------------------------------------------------------------------------- + +#include "HoneycombBeam.h" +#include "MaterialsList.h" + +#include +#include +#include + + +namespace nexus { + + using namespace CLHEP; + + HoneycombBeam::HoneycombBeam(G4double thickn, G4double length_b, + G4double length_t, G4double height): + GeometryBase(), + length_b_(length_b), + length_t_(length_t), + height_(height), + thickn_(thickn) + { + } + + HoneycombBeam::~HoneycombBeam() + { + } + + void HoneycombBeam::Construct() + { + beam_solid_ = + new G4Trd("HONEYCOMB_BEAM", thickn_/2., thickn_/2., length_b_/2., + length_t_/2., height_/2.); + G4Material* steel = materials::Steel(); + G4LogicalVolume* beam_logic = + new G4LogicalVolume(beam_solid_, steel, "HONEYCOMB_BEAM"); + + this->SetLogicalVolume(beam_logic); + } + +} diff --git a/source/geometries/HoneycombBeam.h b/source/geometries/HoneycombBeam.h new file mode 100644 index 0000000000..220140a483 --- /dev/null +++ b/source/geometries/HoneycombBeam.h @@ -0,0 +1,42 @@ +// ---------------------------------------------------------------------------- +// nexus | HoneycombBeam.h +// +// Beam of the support structure to the EP copper plate. +// +// The NEXT Collaboration +// ---------------------------------------------------------------------------- + +#ifndef HONEYCOMB_BEAM_H +#define HONEYCOMB_BEAM_H + +#include "GeometryBase.h" + +class G4Trd; + +namespace nexus { + + class HoneycombBeam: public GeometryBase + { + public: + /// Constructor + HoneycombBeam(G4double thickn, G4double length_b, + G4double length_t, G4double height); + + /// Destructor + ~HoneycombBeam(); + + void Construct(); + + G4Trd* GetSolidVol() const; + + + private: + + G4double length_b_, length_t_, height_, thickn_; + G4Trd* beam_solid_; + }; + + inline G4Trd* HoneycombBeam::GetSolidVol() const {return beam_solid_;} +} // end namespace nexus + +#endif diff --git a/source/geometries/Next100.cc b/source/geometries/Next100.cc index 545b7618d0..547114a9e0 100644 --- a/source/geometries/Next100.cc +++ b/source/geometries/Next100.cc @@ -256,7 +256,8 @@ namespace nexus { (region == "FIELD_RING") || (region == "GATE_RING") || (region == "ANODE_RING") || - (region == "RING_HOLDER")) { + (region == "RING_HOLDER") || + (region == "HONEYCOMB")) { vertex = inner_elements_->GenerateVertex(region); } diff --git a/source/geometries/Next100EnergyPlane.cc b/source/geometries/Next100EnergyPlane.cc index 253888aff6..1624cb61ad 100644 --- a/source/geometries/Next100EnergyPlane.cc +++ b/source/geometries/Next100EnergyPlane.cc @@ -76,7 +76,7 @@ namespace nexus { /// 4. A vacuum volume that encapsulates the sapphire window, /// the optical pad, the PMT and the internal part of the base is made; /// this volume fits exactly the hole previously done in the copper. - /// 5. This volume is replicated by the number of the PMts and placed + /// 5. This volume is replicated by the number of the PMTs and placed /// in the gas volume, inside the holes excavated in the copper. @@ -126,7 +126,8 @@ namespace nexus { G4double hut_length = hut_hole_length_ + hut_length_short_; G4double transl_z = copper_plate_thickn_/2. + hut_length/2 - offset/2.; G4Tubs* short_hut_solid = - new G4Tubs("SHORT_HUT", 0., hut_diam_/2., (hut_length + offset)/2., 0., twopi); + new G4Tubs("SHORT_HUT", 0., hut_diam_/2., (hut_length + offset)/2., + 0., twopi); hut_pos = short_hut_pos_[0]; hut_pos.setZ(transl_z); G4UnionSolid* copper_plate_hut_solid = @@ -193,7 +194,8 @@ namespace nexus { transl_z = - copper_plate_thickn_/2. + hole_length_front_/2. - offset/2.; hole_pos.setZ(transl_z); G4SubtractionSolid* copper_plate_solid = - new G4SubtractionSolid("EP_COPPER_PLATE", copper_plate_hut_solid, hole_solid, 0, hole_pos); + new G4SubtractionSolid("EP_COPPER_PLATE", copper_plate_hut_solid, + hole_solid, 0, hole_pos); for (G4int i=1; iConstruct(); G4LogicalVolume* pmt_logic = pmt_->GetLogicalVolume(); G4double pmt_rel_posz = pmt_->GetRelPosition().z(); - pmt_zpos_ = - -vacuum_front_length/2. + sapphire_window_thickn_ + tpb_thickn_ + - optical_pad_thickn_ + pmt_rel_posz; + pmt_zpos_ = -vacuum_front_length/2. + sapphire_window_thickn_ + + tpb_thickn_ + optical_pad_thickn_ + pmt_rel_posz; G4ThreeVector pmt_pos = G4ThreeVector(0., 0., pmt_zpos_); pmt_rot_ = new G4RotationMatrix(); @@ -339,12 +347,12 @@ namespace nexus { G4Tubs* pmt_base_solid = new G4Tubs("PMT_BASE", 0., pmt_base_diam_/2., pmt_base_thickn_/2., 0., twopi); - G4LogicalVolume* pmt_base_logic = - new G4LogicalVolume(pmt_base_solid, - G4NistManager::Instance()->FindOrBuildMaterial("G4_KAPTON"), - "PMT_BASE"); + G4LogicalVolume* pmt_base_logic + = new G4LogicalVolume(pmt_base_solid, + G4NistManager::Instance()->FindOrBuildMaterial("G4_KAPTON"), "PMT_BASE"); - G4double pmt_base_posz = vacuum_front_length/2. + hole_length_rear_ + hut_hole_length_/2.; + G4double pmt_base_posz = + vacuum_front_length/2. + hole_length_rear_ + hut_hole_length_/2.; G4VPhysicalVolume* pmt_base_phys = new G4PVPlacement(0, G4ThreeVector(0., 0., pmt_base_posz), @@ -353,8 +361,8 @@ namespace nexus { /// Placing the encapsulating volume with all internal components in place vacuum_posz_ = copper_plate_posz_ - copper_plate_thickn_/2. - + vacuum_front_length/2. - sapphire_window_thickn_ - tpb_thickn_ - - optical_pad_thickn_ - pmt_stand_out_; + + vacuum_front_length/2. - sapphire_window_thickn_ - + tpb_thickn_ - optical_pad_thickn_ - pmt_stand_out_; G4ThreeVector pos; for (int i=0; i Next100EnergyPlane::GetPMTPosInGas() const { return pmt_positions_;} + inline G4double Next100EnergyPlane::GetCopperPlateEndZ() const {return copper_plate_end_z_;} + } //end namespace nexus #endif diff --git a/source/geometries/Next100InnerElements.cc b/source/geometries/Next100InnerElements.cc index b03657b56a..d010046d5f 100644 --- a/source/geometries/Next100InnerElements.cc +++ b/source/geometries/Next100InnerElements.cc @@ -10,6 +10,7 @@ #include "Next100InnerElements.h" #include "Next100FieldCage.h" #include "Next100EnergyPlane.h" +#include "Honeycomb.h" #include "Next100TrackingPlane.h" #include @@ -32,6 +33,7 @@ namespace nexus { gas_(nullptr), field_cage_ (new Next100FieldCage(grid_thickn)), energy_plane_ (new Next100EnergyPlane()), + honeycomb_ (new Honeycomb()), tracking_plane_(new Next100TrackingPlane()), msg_(nullptr) { @@ -76,6 +78,12 @@ namespace nexus { pmt_pos_ = energy_plane_->GetPMTPosInGas(); + // Honeycomb support structure for EP + honeycomb_->SetMotherLogicalVolume(mother_logic_); + honeycomb_->SetCoordOrigin(coord_origin); + honeycomb_->SetEndOfCopperPlateZ(energy_plane_->GetCopperPlateEndZ()); + honeycomb_->Construct(); + // Tracking plane tracking_plane_->SetMotherPhysicalVolume(mother_phys_); tracking_plane_->SetCoordOrigin(coord_origin); @@ -122,6 +130,10 @@ namespace nexus { (region == "PMT_BASE")) { vertex = energy_plane_->GenerateVertex(region); } + // Honeycomb region + else if (region == "HONEYCOMB") { + vertex = honeycomb_->GenerateVertex(region); + } // Tracking Plane regions else if ((region == "TP_COPPER_PLATE") || (region == "SIPM_BOARD") || diff --git a/source/geometries/Next100InnerElements.h b/source/geometries/Next100InnerElements.h index a838bc8568..3311e88d76 100644 --- a/source/geometries/Next100InnerElements.h +++ b/source/geometries/Next100InnerElements.h @@ -25,6 +25,7 @@ namespace nexus { class Next100FieldCage; class Next100EnergyPlane; + class Honeycomb; class Next100TrackingPlane; class Next100InnerElements : public GeometryBase @@ -75,6 +76,7 @@ namespace nexus { // Detector parts Next100FieldCage* field_cage_; Next100EnergyPlane* energy_plane_; + Honeycomb* honeycomb_; Next100TrackingPlane* tracking_plane_; // Messenger for the definition of control commands