#include "ParallelWorldConstruction.hh" #include "ParallelWorldMessenger.hh" #include "ParallelWorldParam.hh" #include "DetectorConstruction.hh" #include "PhaseSpaceSD.hh" #include "G4Box.hh" #include "G4LogicalVolume.hh" #include "G4PVPlacement.hh" #include "G4PVParameterised.hh" #include "G4Material.hh" #include "G4SystemOfUnits.hh" #include "G4SDManager.hh" ParallelWorldConstruction::ParallelWorldConstruction( G4String& parallelWorldName ) :G4VUserParallelWorld(parallelWorldName), fDetSpacing(25*CLHEP::mm), fContainerLength(1900*CLHEP::mm) { fParallelWorldMessenger = new ParallelWorldMessenger(this); } ParallelWorldConstruction::~ParallelWorldConstruction() { delete fParallelWorldMessenger; } void ParallelWorldConstruction::Construct() { if( !fDetSpacing || fDetSpacing < 1*CLHEP::nm ){ G4String eMessage = "ParallelWorldConstruction::Construct() \n"; eMessage = eMessage + "fDetSpacing not set. Set it with /parallel/detector/spacing in macro."; throw std::out_of_range( eMessage ); } G4SDManager* SDman = G4SDManager::GetSDMpointer(); // % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % // --->>> ROOM <<<--- // % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % // Ghost world which overlaps with the beamline geometry G4VPhysicalVolume* pGhostWorld = GetWorld(); G4LogicalVolume* lGhostWorld = pGhostWorld->GetLogicalVolume(); // % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % // --->>> SENSITIVE DETECTORS <<<--- // % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % //------------------------------------------------------------------------------------ // Container for parametrised volumes // Position relative to room: z = -4200 + fContainerLength/2 //------------------------------------------------------------------------------------ // Shift container to overlap with the beamline G4double fRoomSizeZ = 8400.*CLHEP::mm; G4double containerPositionZ = -fRoomSizeZ/2 + fContainerLength/2; // Container and detector width G4double width = 1000.*CLHEP::mm; // Container G4Box* sParallelContainer = new G4Box( "parallel_container", width/2, width/2, fContainerLength/2 ); G4LogicalVolume* lParallelContainer = new G4LogicalVolume( sParallelContainer, 0, "parallel_container" ); new G4PVPlacement( 0, G4ThreeVector(0., 0., containerPositionZ), lParallelContainer, "parallel_container", lGhostWorld, false, 0 ); // Thickness of detectors G4double thickness = 1.*CLHEP::nm; //------------------------------------------------------------------------------------ // Sensitive detecotr on parametrised volumes // - A sensitive detector is defined on the parametrised volumes so that every hit // in an event is recorded in the same hits collection. The ID of the parametrised // volume a hit occurred in is then a unique property of that hit and can be used // to determine the position at which the hit occured. //------------------------------------------------------------------------------------ G4cout << "+++ DEBUG +++ fDetSpacing +++ " << fDetSpacing << G4endl; // Number of volumes fNoOfCopies = (G4int) ( fContainerLength/fDetSpacing ); // If detector chosen in macro with /parallel/detector command is 'all' if( fDetChoice == "all" ){ // Define solid and logical volume to be replicated G4VSolid* sParallelDet = new G4Box( "parallel_detector", width/2, width/2, thickness/2 ); G4LogicalVolume* lParallelDet = new G4LogicalVolume( sParallelDet, 0, "parallel_detector" ); // Construct fNoOfCopies parametrised volumes along the z axis ParallelWorldParam* parametrisation = new ParallelWorldParam(); new G4PVParameterised( "parallel_detector", lParallelDet, lParallelContainer, kZAxis, fNoOfCopies, parametrisation ); // Define sensitive detector on parametrised volumes PhaseSpaceSD* sd = new PhaseSpaceSD( "/sd/phaseSpace" ); SDman->AddNewDetector( sd ); lParallelDet->SetSensitiveDetector( sd ); } //------------------------------------------------------------------------------------ // Sensitive detector on single volume // - Defines sensitive detector on a volume chosen in the macro using the // /parallel/detector command. //------------------------------------------------------------------------------------ if( fDetChoice != "all" ){ G4String sdVolName = "sd_" + fDetChoice; // Define map of component positions of face closest to the source, ie the face // hit first by the proton beam. This allows retrieving the position by the component's name. std::map< G4String, G4ThreeVector > componentPosition; componentPosition["scatterfoil1"] = G4ThreeVector(0., 0., -869.*CLHEP::mm); componentPosition["tube1"] = G4ThreeVector(0., 0., -593.*CLHEP::mm); componentPosition["nozzle"] = G4ThreeVector(0., 0., 750.*CLHEP::mm); componentPosition["outside"] = G4ThreeVector(0., 0., 818.*CLHEP::mm); // 1768 mm // Define volume for sensitive detector G4VSolid* sDetector = new G4Box( sdVolName, width/2, width/2, thickness/2 ); G4LogicalVolume* lDetector = new G4LogicalVolume( sDetector, 0, sdVolName ); // Shift position of detector so faces of detector and component volume coincide G4ThreeVector detPosition = componentPosition.at(fDetChoice) + G4ThreeVector(0., 0., 0.5*CLHEP::nm); new G4PVPlacement(0, detPosition, lDetector, sdVolName, lParallelContainer, 0, 0, 0); // Define sensitive detector on volume PhaseSpaceSD* sd = new PhaseSpaceSD( "/sd/phaseSpace/" + fDetChoice ); SDman->AddNewDetector( sd ); lDetector->SetSensitiveDetector( sd ); } }