// // ******************************************************************** // #include "GarfieldDetectorConstruction.hh" #include "G4AutoDelete.hh" #include "G4Box.hh" #include "G4Colour.hh" #include "G4GeometryManager.hh" #include "G4GlobalMagFieldMessenger.hh" #include "G4LogicalVolume.hh" #include "G4LogicalVolumeStore.hh" #include "G4Material.hh" #include "G4NistManager.hh" #include "G4PVPlacement.hh" #include "G4PVReplica.hh" #include "G4PhysicalConstants.hh" #include "G4PhysicalVolumeStore.hh" #include "G4RunManager.hh" #include "G4SolidStore.hh" #include "G4SystemOfUnits.hh" #include "G4Tubs.hh" #include "G4VisAttributes.hh" #include "GarfieldG4FastSimulationModel.hh" #include "GarfieldMessenger.hh" #include "G4RegionStore.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... GarfieldDetectorConstruction::GarfieldDetectorConstruction() : G4VUserDetectorConstruction() { fGarfieldMessenger = new GarfieldMessenger(this); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... GarfieldDetectorConstruction::~GarfieldDetectorConstruction() { delete fGarfieldMessenger; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4VPhysicalVolume* GarfieldDetectorConstruction::Construct() { // Define materials DefineMaterials(); // Define volumes return DefineVolumes(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void GarfieldDetectorConstruction::DefineMaterials() { G4bool isotopes = false; G4NistManager* nistManager = G4NistManager::Instance(); // Load commonly used materials nistManager->FindOrBuildMaterial("G4_AIR"); // Ensure G4_AIR is available nistManager->FindOrBuildMaterial("G4_STAINLESS-STEEL"); // PRC outer shell material nistManager->FindOrBuildMaterial("G4_W"); // Tungsten wire material // Create P10 gas (90% Argon, 10% Methane) G4Element* Ar = nistManager->FindOrBuildElement("Ar", isotopes); G4Element* C = nistManager->FindOrBuildElement("C", isotopes); G4Element* H = nistManager->FindOrBuildElement("H", isotopes); G4Material* CH4 = new G4Material("CH4", 0.667 * CLHEP::mg / CLHEP::cm3, 2); CH4->AddElement(C, 1); CH4->AddElement(H, 4); G4Material* P10 = new G4Material("P10", 1.5 * CLHEP::mg / CLHEP::cm3, 2); P10->AddElement(Ar, 90 * perCent); P10->AddMaterial(CH4, 10 * perCent); // Log materials table for verification G4cout << *(G4Material::GetMaterialTable()) << G4endl; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4VPhysicalVolume* GarfieldDetectorConstruction::DefineVolumes() { G4NistManager* nist = G4NistManager::Instance(); G4Material* worldMaterial = nist->FindOrBuildMaterial("G4_AIR"); G4Material* shellMaterial = nist->FindOrBuildMaterial("G4_STAINLESS-STEEL"); G4Material* gasMaterial = nist->FindOrBuildMaterial("P10"); // P10 approximated as Ar G4Material* wireMaterial = nist->FindOrBuildMaterial("G4_W"); // World: 100 m x 100 m x 100 m G4double worldSize = 100. * m; G4Box* worldS = new G4Box("World", worldSize / 2, worldSize / 2, worldSize / 2); G4LogicalVolume* worldLV = new G4LogicalVolume(worldS, worldMaterial, "World"); G4VPhysicalVolume* worldPV = new G4PVPlacement(0, G4ThreeVector(), worldLV, "World", nullptr, false, 0, fCheckOverlaps); // PRC Outer (Shell): 10 cm x 10 cm x 6 m, blue G4double prcWidth = 0.1 * m; G4double prcHeight = 0.1 * m; G4double prcLength = 6. * m; G4double wallThickness = 0.0023 * m; G4Box* prcOuterS = new G4Box("PRCOuter", prcWidth / 2, prcHeight / 2, prcLength / 2); G4LogicalVolume* prcOuterLV = new G4LogicalVolume(prcOuterS, shellMaterial, "PRCOuter"); G4UserLimits* shellLimit = new G4UserLimits(0.0023 * m); // 0.23 cm step limit prcOuterLV->SetUserLimits(shellLimit); G4VisAttributes* prcOuterVis = new G4VisAttributes(G4Colour::Blue()); prcOuterLV->SetVisAttributes(prcOuterVis); fTubePV = new G4PVPlacement(0, G4ThreeVector(), prcOuterLV, "PRCOuter", worldLV, false, 0, fCheckOverlaps); // PRC Inner (Gas): 9.54 cm x 9.54 cm x 6 m, grey G4double prcInnerWidth = prcWidth - 2 * wallThickness; G4double prcInnerHeight = prcHeight - 2 * wallThickness; G4Box* prcInnerS = new G4Box("PRCInner", prcInnerWidth / 2, prcInnerHeight / 2, prcLength / 2); G4LogicalVolume* prcInnerLV = new G4LogicalVolume(prcInnerS, gasMaterial, "PRCInner"); G4Region* regionGarfield = G4RegionStore::GetInstance()->GetRegion("RegionGarfield"); if (!regionGarfield) { regionGarfield = new G4Region("RegionGarfield"); G4cout << "GarfieldDetectorConstruction: Created RegionGarfield" << G4endl; } regionGarfield->AddRootLogicalVolume(prcInnerLV); G4cout << "GarfieldDetectorConstruction: Added PRCInner to RegionGarfield" << G4endl; G4VisAttributes* prcInnerVis = new G4VisAttributes(G4Colour::Green()); prcInnerLV->SetVisAttributes(prcInnerVis); fGasPV = new G4PVPlacement(0, G4ThreeVector(), prcInnerLV, "PRCInner", prcOuterLV, false, 0, fCheckOverlaps); // Anode Wire: 0.05 mm radius, 6 m length, red G4double wireRadius = 0.00005 * m; G4Tubs* wireS = new G4Tubs("AnodeWire", 0, wireRadius, prcLength / 2, 0, 2 * pi); G4LogicalVolume* wireLV = new G4LogicalVolume(wireS, wireMaterial, "AnodeWire"); G4UserLimits* stepLimit = new G4UserLimits(0.001 * mm); wireLV->SetUserLimits(stepLimit); G4VisAttributes* wireVis = new G4VisAttributes(G4Colour::Red()); wireLV->SetVisAttributes(wireVis); fWirePV = new G4PVPlacement(0, G4ThreeVector(), wireLV, "AnodeWire", prcInnerLV, false, 0, fCheckOverlaps); return worldPV; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4Material* GarfieldDetectorConstruction::AbsorberMaterialWithSingleIsotope( G4String name, G4String symbol, G4double density, G4int Z, G4int A) { // define a material from an isotope // G4int ncomponents; G4double abundance, massfraction; G4Isotope* isotope = new G4Isotope(symbol, Z, A); G4Element* element = new G4Element(name, symbol, ncomponents = 1); element->AddIsotope(isotope, abundance = 100. * perCent); G4Material* material = new G4Material(name, density, ncomponents = 1); material->AddElement(element, massfraction = 100. * perCent); return material; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void GarfieldDetectorConstruction::SetAbsorberMaterial( G4String materialChoice) { // search the material by its name G4Material* newMaterial = G4NistManager::Instance()->FindOrBuildMaterial(materialChoice); if (newMaterial) { if (fAbsorberMaterial != newMaterial) { fAbsorberMaterial = newMaterial; if (fAbsorberLV) { fAbsorberLV->SetMaterial(fAbsorberMaterial); } G4RunManager::GetRunManager()->PhysicsHasBeenModified(); } } else { G4cout << "\n--> warning from GarfieldDetectorConstruction::SetMaterial : " << materialChoice << " not found" << G4endl; } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......