#include "DetectorConstruction.hh" DetectorConstruction::DetectorConstruction() { } DetectorConstruction::~DetectorConstruction() { } G4VPhysicalVolume *DetectorConstruction::Construct() { G4bool checkOverlaps = true; G4NistManager *nist = G4NistManager::Instance(); G4Material *worldMat = nist->FindOrBuildMaterial("G4_AIR"); G4Material *leadMat = nist->FindOrBuildMaterial("G4_Pb"); // Define custom material for EJ315 (Liquid Scintillator) G4double density = 0.954 * g/cm3; G4Element* H = new G4Element("Hydrogen", "H", 1., 1.00784 * g/mole); G4Element* C = new G4Element("Carbon", "C", 6., 12.0107 * g/mole); G4Element* D = new G4Element("Deuterium", "D", 1., 2.014 * g/mole); // EJ-315 Composition from the datasheet G4double fractionMassD = 4.06e22 / (4.06e22 + 2.87e20 + 4.10e22); G4double fractionMassH = 2.87e20 / (4.06e22 + 2.87e20 + 4.10e22); G4double fractionMassC = 4.10e22 / (4.06e22 + 2.87e20 + 4.10e22); density = 0.954 * g/cm3; G4Material* EJ315 = new G4Material("EJ315", density, 3); EJ315->AddElement(D, fractionMassD); EJ315->AddElement(H, fractionMassH); EJ315->AddElement(C, fractionMassC); // Assign Optical Properties const G4int nEntries = 6; G4double PhotonEnergy[nEntries] = { 2.48*eV, 2.58*eV, 2.72*eV, 2.86*eV, 3.10*eV, 3.26*eV }; // 500 nm to 380 nm G4double Scintillation[nEntries] = { 0.1, 0.3, 0.7, 1.0, 0.6, 0.2 }; // Approximate emission spectrum G4MaterialPropertiesTable* EJ315MPT = new G4MaterialPropertiesTable(); EJ315MPT->AddProperty("SCINTILLATION", PhotonEnergy, Scintillation, nEntries, true); EJ315MPT->AddConstProperty("SCINTILLATIONYIELD", 9200.0 / MeV, true); EJ315MPT->AddConstProperty("RESOLUTIONSCALE", 1.0, true); EJ315MPT->AddConstProperty("SCINTILLATIONTIMECONSTANT1", 3.5 * ns, true); EJ315MPT->AddConstProperty("RINDEX", 1.498, true); EJ315MPT->AddConstProperty("ABSLENGTH", 3.0 * m, true); // Bulk Light Attenuation EJ315->SetMaterialPropertiesTable(EJ315MPT); // Create the World Volume G4double xWorld = 1. *m; G4double yWorld = 1. *m; G4double zWorld = 1. *m; G4Box *solidWorld = new G4Box("solidWorld", 0.5 * xWorld, 0.5 * yWorld, 0.5 * zWorld); logicWorld = new G4LogicalVolume(solidWorld, worldMat, "logicWorld"); G4VPhysicalVolume *physWorld = new G4PVPlacement(0, G4ThreeVector(0., 0., 0. ), logicWorld, "physWorld", 0, false, 0, checkOverlaps); G4VisAttributes *worldVisAtt = new G4VisAttributes(G4Color(1.0, 1.0, 1.0, 0.1)); worldVisAtt->SetForceWireframe(true); logicWorld->SetVisAttributes(worldVisAtt); // Liquid Scintillator (EJ315) G4double scintillatorRadius = 3. * cm; G4double scintillatorHeight = 7. * cm; G4Tubs *solidScintillator = new G4Tubs("solidScintillator", 0., scintillatorRadius, scintillatorHeight / 2, 0., 360. * deg); logicScintillator = new G4LogicalVolume(solidScintillator, EJ315, "logicScintillator"); G4VPhysicalVolume *physScintillator = new G4PVPlacement(0, G4ThreeVector(0., 0., 6.5 * cm), logicScintillator, "physScintillator", logicWorld, false, checkOverlaps); G4VisAttributes *scintillatorVisAtt = new G4VisAttributes(G4Color(1.0, 0.0, 0.0, 0.5)); scintillatorVisAtt->SetForceSolid(true); logicScintillator->SetVisAttributes(scintillatorVisAtt); // Optical Pad (EJ-560) G4double opticalPadThickness = 0.15 * cm; G4Tubs *solidOpticalPad = new G4Tubs("solidOpticalPad", 0., scintillatorRadius, opticalPadThickness / 2, 0., 360. * deg); logicOpticalPad = new G4LogicalVolume(solidOpticalPad, nist->FindOrBuildMaterial("G4_SILICON_DIOXIDE"), "logicOpticalPad"); G4VPhysicalVolume *physOpticalPad = new G4PVPlacement(0, G4ThreeVector(0., 0., 6.5 * cm + scintillatorHeight / 2 + opticalPadThickness / 2), logicOpticalPad, "physOpticalPad", logicWorld, false, checkOverlaps); G4VisAttributes *opticalPadVisAtt = new G4VisAttributes(G4Color(0.0, 1.0, 0.0, 0.5)); opticalPadVisAtt->SetForceSolid(true); logicOpticalPad->SetVisAttributes(opticalPadVisAtt); // PMT Window G4double pmtWindowThickness = 0.2 * cm; G4Tubs *solidPMTWindow = new G4Tubs("solidPMTWindow", 0., scintillatorRadius, pmtWindowThickness / 2, 0., 360. * deg); logicPMTWindow = new G4LogicalVolume(solidPMTWindow, nist->FindOrBuildMaterial("G4_Pyrex_Glass"), "logicPMTWindow"); G4VPhysicalVolume *physPMTWindow = new G4PVPlacement(0, G4ThreeVector(0., 0., 6.5 * cm + scintillatorHeight / 2 + opticalPadThickness + pmtWindowThickness / 2), logicPMTWindow, "physPMTWindow", logicWorld, false, checkOverlaps); G4VisAttributes *pmtWindowVisAtt = new G4VisAttributes(G4Color(0.0, 0.0, 1.0, 0.5)); pmtWindowVisAtt->SetForceSolid(true); logicPMTWindow->SetVisAttributes(pmtWindowVisAtt); // Aluminum Housing G4Material *housingMaterial = nist->FindOrBuildMaterial("G4_Al"); G4double housingOuterRadius = 3.5 * cm; G4Tubs *solidHousing = new G4Tubs("solidHousing", scintillatorRadius, housingOuterRadius, (scintillatorHeight + opticalPadThickness + pmtWindowThickness) / 2, 0., 360. * deg); G4LogicalVolume *logicHousing = new G4LogicalVolume(solidHousing, housingMaterial, "logicHousing"); G4VPhysicalVolume *physHousing = new G4PVPlacement(0, G4ThreeVector(0., 0., 3. * cm + (scintillatorHeight + opticalPadThickness + pmtWindowThickness) / 2), logicHousing, "physHousing", logicWorld, false, checkOverlaps); G4VisAttributes *housingVisAtt = new G4VisAttributes(G4Color(0.5, 0.5, 0.5, 0.5)); housingVisAtt->SetForceWireframe(true); logicHousing->SetVisAttributes(housingVisAtt); // Housing Lid G4double lidThickness = 0.5 * cm; G4Tubs *solidLid = new G4Tubs("solidLid", 0., housingOuterRadius, lidThickness / 2, 0., 360. * deg); G4LogicalVolume *logicLid = new G4LogicalVolume(solidLid, housingMaterial, "logicLid"); G4VPhysicalVolume *physLid = new G4PVPlacement(0, G4ThreeVector(0., 0., 2.5 * cm +(lidThickness)/2), logicLid, "physLid", logicWorld, false, checkOverlaps); G4VisAttributes *lidVisAtt = new G4VisAttributes(G4Color(0.5, 0.5, 0.5, 0.5)); lidVisAtt->SetForceWireframe(true); logicLid->SetVisAttributes(lidVisAtt); // Cesium-137 Source G4Material *csSourceMat = nist->FindOrBuildMaterial("G4_CESIUM_IODIDE"); G4double csSourceRadius = 1. * mm; G4double csSourcePositionZ = -1. * cm; G4Sphere *solidCsSource = new G4Sphere("solidCsSource", 0., csSourceRadius, 0., 360. * deg, 0., 180. * deg); G4LogicalVolume *logicCsSource = new G4LogicalVolume(solidCsSource, csSourceMat, "logicCsSource"); G4VPhysicalVolume *physCsSource = new G4PVPlacement(0, G4ThreeVector(0., 0., csSourcePositionZ), logicCsSource, "physCsSource", logicWorld, false, checkOverlaps); G4VisAttributes *csSourceVisAtt = new G4VisAttributes(G4Color(1.0, 0.0, 1.0, 0.5)); csSourceVisAtt->SetForceSolid(true); logicCsSource->SetVisAttributes(csSourceVisAtt); return physWorld; } void DetectorConstruction::ConstructSDandField() { G4SDManager* sdManager = G4SDManager::GetSDMpointer(); // Ensure the SD is created and registered first SensitiveDetector* sensDet = new SensitiveDetector("sensDet"); sdManager->AddNewDetector(sensDet); // Assign the SD to the logical volume, ensuring logicScintillator is valid if (logicScintillator) { logicScintillator->SetSensitiveDetector(sensDet); } else { G4cerr << "Error: logicScintillator is null in ConstructSDandField()" << G4endl; } }