# include # include #include "LXePMTSD.hh" #include "LXePMTHit.hh" #include "DetectorConstruction.hh" #include "G4UIsession.hh" #include "G4NistManager.hh" #include "G4Material.hh" #include "G4Element.hh" #include "G4LogicalBorderSurface.hh" #include "G4LogicalSkinSurface.hh" #include "G4OpticalSurface.hh" #include "G4Box.hh" #include "G4Tubs.hh" #include "G4LogicalVolume.hh" #include "G4ThreeVector.hh" #include "G4PVPlacement.hh" #include "G4SystemOfUnits.hh" #include "G4SubtractionSolid.hh" #include "G4UnitsTable.hh" #include "G4Colour.hh" #include "G4VisAttributes.hh" #include "globals.hh" #include "G4PhysicalConstants.hh" #include "G4SDManager.hh" #include "G4MultiFunctionalDetector.hh" #include "G4VPrimitiveScorer.hh" #include "G4Cache.hh" #include "G4UnionSolid.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... using namespace std; DetectorConstruction::~DetectorConstruction() { } DetectorConstruction::DetectorConstruction() : G4VUserDetectorConstruction() { fExpHall_x = fExpHall_y = fExpHall_z = 0.1*m; fScint = nullptr; fScintMPT = new G4MaterialPropertiesTable(); fWorldMPT = new G4MaterialPropertiesTable(); fScint_LV = nullptr; fWindow_LV = nullptr; fWorld_LV = nullptr; //// MATERIALS DEFINITION // // Vacuum G4Material* Vacuum = new G4Material("Vacuum", 1.0 , 1.01*g/mole, 1.0E-25*g/cm3, kStateGas, 2.73*kelvin, 3.0E-18*pascal ); G4MaterialPropertiesTable* Vacuum_MPT = new G4MaterialPropertiesTable; G4double ph_energy[]= {1.*eV, 5.*eV}; G4double Vacuum_rindex[]= {1.,1.}; Vacuum_MPT->AddProperty("RINDEX", ph_energy, Vacuum_rindex, 2); // CsI(Tl) ifstream myfile; string line; float temp_0, temp_1, temp_2, temp_3, temp_4; vector ScintEnergy; vector ScintDistr; vector Rindex; vector Absor; vector Reflect; myfile.open ("../data/CsI_Tl_data.txt"); if(!myfile.is_open()) cout << "material input file could not be opened/found." << endl; else { getline(myfile, line); // skip first line while(getline(myfile, line)) { const char* linechar = line.c_str(); sscanf(linechar, "%f %f %f %f %f", &temp_0, &temp_1, &temp_2, &temp_3, &temp_4); ScintEnergy.push_back(temp_0*eV); ScintDistr.push_back(temp_1); Rindex.push_back(temp_2); Absor.push_back(temp_3*cm); Reflect.push_back(temp_4); } } G4int ScintEntries = ScintEnergy.size(); myfile.close(); for (int i=0; iFindOrBuildMaterial("G4_CESIUM_IODIDE"); /* G4Element* Tl =NistMan->FindOrBuildElement("G4_Tl"); G4Material* CsI_Tl = new G4Material("CsI_Tl",4.51*g/cm3,2); // CSI + Tl doping CsI_Tl->AddMaterial(CsI,99.6*perCent); CsI_Tl->AddElement(Tl,0.4*perCent); */ G4MaterialPropertiesTable* CsI_MPT = new G4MaterialPropertiesTable; CsI_MPT->AddProperty("RINDEX", ScintEnergy.data(), Rindex.data(), ScintEntries); CsI_MPT->AddProperty("FASTCOMPONENT", ScintEnergy.data(), ScintDistr.data(), ScintEntries)->SetSpline(true); // scint spectrum CsI_MPT->AddProperty("ABSLENGTH", ScintEnergy.data(), Absor.data(), ScintEntries); G4double Temp_abs[2]= {0.001*cm,0.001*cm}; //CsI_MPT->AddProperty("ABSLENGTH", ph_energy, Temp_abs, 2)->SetSpline(true); CsI_MPT->AddConstProperty("SCINTILLATIONYIELD", 100./MeV); //CsI_MPT->AddConstProperty("SCINTILLATIONYIELD", 65000./MeV); CsI_MPT->AddConstProperty("FASTTIMECONSTANT", 700.*ns); CsI_MPT->AddConstProperty("SLOWTIMECONSTANT", 3500.*ns); CsI_MPT->AddConstProperty("YIELDRATIO", 0.57); // fast component/total CsI_MPT->AddConstProperty("RESOLUTIONSCALE", 1.);// TO TUNE photon yield spread: G4double sigma = ResolutionScale * std::sqrt(MeanNumberOfPhotons); G4cout << "CSI material table is: " << endl; CsI_MPT->DumpTable(); // Sensor vector SiPmEnergy; vector SiPmEff; myfile.open ("../data/SiPm_data.txt"); if(!myfile.is_open()) cout << "material input file could not be opened/found." << endl; else { getline(myfile, line); // skip first line while(getline(myfile, line)) { const char* linechar = line.c_str(); sscanf(linechar, "%f %f", &temp_0, &temp_1); SiPmEnergy.push_back(temp_0*eV); SiPmEff.push_back(temp_1); } } G4int SiPmEntries = SiPmEnergy.size(); myfile.close(); fSensor_MPT = new G4MaterialPropertiesTable; G4double Temp_eff[]= {1.,1.}; fSensor_MPT->AddProperty("EFFICIENCY", SiPmEnergy.data(), SiPmEff.data(), SiPmEntries)->SetSpline(true); //fSensor_MPT->AddProperty("EFFICIENCY", ph_energy, Temp_eff, 2); G4cout << "Sensor material table is: " << endl; fSensor_MPT ->DumpTable(); // Glass G4Material* Glass =NistMan->FindOrBuildMaterial("G4_GLASS_PLATE"); fWindow_MPT = new G4MaterialPropertiesTable; G4double Glass_rindex[]= {1.5,1.5}; fWindow_MPT->AddProperty("RINDEX", ph_energy, Glass_rindex, 2); ///// fWorldMaterial = Vacuum; fScintMaterial = CsI; fWindowMaterial= Glass; fScintMaterial->SetMaterialPropertiesTable(CsI_MPT); //fScintMaterial->GetIonisation()->SetBirksConstant(0.126*mm/MeV); fWorldMaterial->SetMaterialPropertiesTable(Vacuum_MPT); fWindowMaterial->SetMaterialPropertiesTable(fWindow_MPT); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4VPhysicalVolume* DetectorConstruction::Construct() { G4Colour white (1.0, 1.0, 1.0) ; // white G4Colour gray (0.5, 0.5, 0.5) ; // gray G4Colour black (0.0, 0.0, 0.0) ; // black G4Colour red (1.0, 0.0, 0.0) ; // red G4Colour green (0.0, 1.0, 0.0) ; // green G4Colour blue (0.0, 0.0, 1.0) ; // blue G4Colour cyan (0.0, 1.0, 1.0) ; // cyan G4Colour magenta (1.0, 0.0, 1.0) ; // magenta G4Colour yellow (1.0, 1.0, 0.0) ; // yellow // ------------- Volumes -------------- // The experimental Hall G4Box* world_box = new G4Box("World", fExpHall_x, fExpHall_y, fExpHall_z); fWorld_LV = new G4LogicalVolume(world_box, fWorldMaterial, "World", 0, 0, 0); G4VisAttributes * fWorldVisAtt = new G4VisAttributes(white); fWorldVisAtt->SetForceWireframe (true); fWorld_LV->SetVisAttributes(fWorldVisAtt); G4VPhysicalVolume* world_PV = new G4PVPlacement(0, G4ThreeVector(), fWorld_LV, "World", 0, false, 0); // The scintillator tile G4Tubs* scintillator_tile_cylinder = new G4Tubs("Scintillator_tile", 0, 20*mm, 0.5*6*mm, 0, 360); // cylinder fScint_LV = new G4LogicalVolume(scintillator_tile_cylinder, fScintMaterial, "Scint", 0, 0, 0); G4VisAttributes * fScintVisAtt = new G4VisAttributes(white); //fScintVisAtt->SetForceSolid(true); fScint_LV->SetVisAttributes(fScintVisAtt); G4ThreeVector position_crystal = G4ThreeVector(0.*cm, 0.*cm, 0.*cm); fScint = new G4PVPlacement(0, position_crystal, fScint_LV, "Crystal", fWorld_LV, false, 0); //physical volume // Window G4Box* Window_Box = new G4Box("Window", 0.5*6.*mm, 0.5*6.*mm, 0.5*1*mm); fWindow_LV = new G4LogicalVolume(Window_Box, fWindowMaterial, "Window_LV", 0, 0, 0); G4VisAttributes * WindowVisAtt = new G4VisAttributes(cyan); //fWindowVisAtt->SetForceSolid(true); fWindow_LV->SetVisAttributes(WindowVisAtt); fposition_Window = new G4ThreeVector(0.*cm, 0.*cm, 3.*mm+0.5*1.*mm); fWindow = new G4PVPlacement(0, *fposition_Window, fWindow_LV, "Window", fWorld_LV, false, 0); // The outer regions G4Box* out_space = new G4Box("out_space", 0.5*50.*mm, 0.5*50.*mm, 0.5*6*mm); // to construct scint interfaces above and below G4Box* sensor_space = new G4Box("sensor_space", 0.5*6.*mm, 0.5*6.*mm, 0.5*1*mm); // to construct scint interfaces above and below G4SubtractionSolid* out_space_side_hollow = new G4SubtractionSolid("out_space_side_hollow", out_space, scintillator_tile_cylinder); G4ThreeVector zTrans_1(0, 0, -3.*mm+0.5*1.*mm); G4RotationMatrix* yRot = new G4RotationMatrix; G4SubtractionSolid* out_space_above_hollow = new G4SubtractionSolid("out_space_above_hollow", out_space, sensor_space,yRot, zTrans_1); G4LogicalVolume* out_space_LV = new G4LogicalVolume(out_space, fWorldMaterial, "out_space_LV", 0, 0, 0); G4LogicalVolume* out_space_side_hollow_LV = new G4LogicalVolume(out_space_side_hollow, fWorldMaterial, "out_space_side_hollow_LV", 0, 0, 0); G4LogicalVolume* out_space_above_hollow_LV = new G4LogicalVolume(out_space_above_hollow, fWorldMaterial, "out_space_above_hollow_LV", 0, 0, 0); G4VisAttributes * outVisAtt = new G4VisAttributes(yellow); //outVisAtt->SetForceSolid(true); //outVisAtt->SetForceWireframe (true); out_space_LV->SetVisAttributes(outVisAtt); out_space_side_hollow_LV->SetVisAttributes(outVisAtt); out_space_above_hollow_LV->SetVisAttributes(outVisAtt); G4ThreeVector position_out_above = G4ThreeVector(0.*cm, 0.*cm, 3.*mm+0.5*6.*mm); G4ThreeVector position_out_side = G4ThreeVector(0.*cm, 0.*cm, 0.*mm); G4ThreeVector position_out_below = G4ThreeVector(0.*cm, 0.*cm, -3.*mm-0.5*6.*mm); G4VPhysicalVolume* out_space_above = new G4PVPlacement(0, position_out_above, out_space_above_hollow_LV, "out_space_above", fWorld_LV, false, 0); G4VPhysicalVolume* out_space_below = new G4PVPlacement(0, position_out_below, out_space_LV, "out_space_below", fWorld_LV, false, 0); G4VPhysicalVolume* out_space_side = new G4PVPlacement(0, position_out_side, out_space_side_hollow_LV, "out_space_side", fWorld_LV, false, 0); // ------------- Surfaces -------------- G4OpticalSurface* above_opticalSurface = new G4OpticalSurface("above_surface"); G4OpticalSurface* below_opticalSurface = new G4OpticalSurface("below_surface"); G4OpticalSurface* side_opticalSurface = new G4OpticalSurface("side_surface"); G4OpticalSurface* window_opticalSurface = new G4OpticalSurface("window_surface"); G4OpticalSurface* detector_opticalSurface = new G4OpticalSurface("detector_surface"); // REAL SURFACE DAVIS (no reflectivity required) above_opticalSurface -> SetType(dielectric_LUTDAVIS); above_opticalSurface -> SetModel(DAVIS); above_opticalSurface -> SetFinish(RoughTeflon_LUT); G4LogicalBorderSurface* above_opticalSurface_LS = new G4LogicalBorderSurface("above_surface_LS",fScint, out_space_above, above_opticalSurface); if (above_opticalSurface_LS) above_opticalSurface_LS->DumpInfo(); below_opticalSurface -> SetType(dielectric_LUTDAVIS); below_opticalSurface -> SetModel(DAVIS); below_opticalSurface -> SetFinish(RoughTeflon_LUT); G4LogicalBorderSurface* below_opticalSurface_LS = new G4LogicalBorderSurface("below_surface_LS",fScint, out_space_below, below_opticalSurface); if (below_opticalSurface_LS) below_opticalSurface_LS->DumpInfo(); side_opticalSurface -> SetType(dielectric_LUTDAVIS); side_opticalSurface -> SetModel(DAVIS); side_opticalSurface -> SetFinish(RoughTeflon_LUT); G4LogicalBorderSurface* side_opticalSurface_LS = new G4LogicalBorderSurface("side_surface_LS",fScint, out_space_side, side_opticalSurface); if (side_opticalSurface_LS) side_opticalSurface_LS->DumpInfo(); window_opticalSurface -> SetType(dielectric_LUTDAVIS); window_opticalSurface -> SetModel(DAVIS); window_opticalSurface -> SetFinish(Detector_LUT); window_opticalSurface ->SetMaterialPropertiesTable(fSensor_MPT); G4LogicalBorderSurface* window_opticalSurface_LS = new G4LogicalBorderSurface("window_surface_LS", fScint, fWindow, window_opticalSurface); if (window_opticalSurface_LS) window_opticalSurface_LS->DumpInfo(); return world_PV; } void DetectorConstruction::ConstructSDandField() { // SiPM SD if (!fPmt_SD.Get()) { //Created here so it exists as pmts are being placed G4cout << "Construction /LXeDet/pmtSD" << G4endl; LXePMTSD* pmt_SD = new LXePMTSD("/LXeDet/pmtSD"); fPmt_SD.Put(pmt_SD); pmt_SD->InitPMTs(1); //let pmtSD know # of pmts vector PmTPositions; PmTPositions.push_back(*fposition_Window); pmt_SD->SetPmtPositions(PmTPositions); } G4SDManager::GetSDMpointer()->AddNewDetector(fPmt_SD.Get()); //sensitive detector is not actually on the photocathode. //processHits gets done manually by the stepping action. //It is used to detect when photons hit and get absorbed&detected at the //boundary to the photocathode (which doesnt get done by attaching it to a //logical volume. //It does however need to be attached to something or else it doesnt get //reset at the begining of events SetSensitiveDetector(fWindow_LV, fPmt_SD.Get()); }