FieldSetup::FieldSetup(lucretiaManager* lman) : fFieldManager(0), fChordFinder(0), fEquation(0), fElFieldValue(), fStepper(0), fIntgrDriver(0), fMinStep(lman->EMStepSize*m) { fUniform=lman->EMisUniform; if (fUniform==1) { double magField[3]={0,0,0}; lman->GetUniformField(magField); fMfield = new G4UniformMagField(G4ThreeVector(magField[0]*tesla,magField[1]*tesla,magField[2]*tesla)); fEquation = new G4EqMagElectricField(fMfield); } else if (fUniform==2) { double eField[3]={0,0,0}; lman->GetUniformField(eField); fEfield = new G4UniformElectricField(G4ThreeVector(eField[0]*kilovolt/m,eField[1]*kilovolt/m,eField[2]*kilovolt/m)); fEquation = new G4EqMagElectricField(fEfield); } else { fEMfield = new GlobalField(lman); // Gets field data from LucretiaManager object fEquation = new G4EqMagElectricField(fEMfield); } fFieldManager = GetGlobalFieldManager(); UpdateField(lman); }
G4VPhysicalVolume* TargetDetectorConstruction::Construct() { G4NistManager* nist = G4NistManager::Instance(); nist->SetVerbose(1); G4double rhoVacuum = CLHEP::universe_mean_density; G4double pVacuum = 1.0e-19*pascal; G4double TVacuum = 0.1*kelvin; G4Material* graphite = new G4Material("Graphite", 6., 12.*g/mole, 1.82*g/cm3); G4Material* vacuum = new G4Material("Vacuum", 1., 1.01*g/mole, rhoVacuum, kStateGas, TVacuum, pVacuum); /****************************/ // World /****************************/ G4bool checkOverlaps = true; G4double earthRadius = 100*cm; G4Orb* worldSolid = new G4Orb("World", earthRadius); G4LogicalVolume* logicWorld = new G4LogicalVolume(worldSolid, vacuum, "World"); G4VPhysicalVolume* physWorld = new G4PVPlacement(0, G4ThreeVector(), logicWorld, "World", 0, false, 0, checkOverlaps); /****************************/ // Target /****************************/ G4VisAttributes* colorGraphite = new G4VisAttributes(G4Colour(0.8, 0.0, 0.0, 0.7)); G4Tubs* targetSolid = new G4Tubs("Target", 0., 3*cm, 30.*cm, 0., 2*M_PI); G4LogicalVolume* logicTarget = new G4LogicalVolume(targetSolid, graphite, "Target"); G4VPhysicalVolume* physTarget = new G4PVPlacement(0, G4ThreeVector(), logicTarget, "Target", logicWorld, false, 0, checkOverlaps); logicTarget->SetVisAttributes(colorGraphite); return physWorld; }
TargetHits::TargetHits() : G4VHit() { fTrack = -1; fPosition = G4ThreeVector(); fEnergy = 0.; fMomentum = G4ThreeVector(); fTime = 0.; fParticle = NULL; }
/* * ray fire test, distance to in * points inside of a volume */ TEST_F(DagSolidTest,test_5) { G4ThreeVector position = G4ThreeVector(0.,0.,0.); G4ThreeVector direction = G4ThreeVector(1.,0.,0.); double distance = vol_1->DistanceToIn(position,direction); // distance should be set to infinity since there are no other volumes // to enter EXPECT_EQ(kInfinity,distance); return; }
GSMS::Geometry::Geometry() { m_world = NULL; defineMaterials(); G4Box* world_box = new G4Box( "world_box", 2*m, 2*m, 2*m); G4LogicalVolume* world_log = new G4LogicalVolume( world_box, m_materials["Air"], "world_log"); m_world = new G4PVPlacement( 0, G4ThreeVector(0. ,0. ,0.), "world_phys", world_log, NULL, false, 0); world_log->SetVisAttributes(G4VisAttributes::Invisible); }
/* * ray fire test, distance to out calc normal as well * point just outside of a volume, vnorm should be false */ TEST_F(DagSolidTest, test_8 ) { // point inside cell looking out G4ThreeVector position = G4ThreeVector(51.,0.,0.); G4ThreeVector direction = G4ThreeVector(1.,0.,0.); G4ThreeVector normal; bool v_norm = false; double distance = vol_1->DistanceToOut(position,direction,true,&v_norm,&normal); // when the point is outside the volume, v_norm should be false EXPECT_FALSE(v_norm); // distance should be set to infinity EXPECT_EQ(kInfinity,distance); return; }
void BIPrimaryGeneratorAction::GeneratePrimaries(G4Event *event) { //G4double coneTheta = 15.*deg; //G4ThreeVector particleVec = GetParVec(coneTheta); //fEnergy = fEneFnc->GetRandom() * MeV; G4ThreeVector particleVec = GetParVecEne(); fProtonGun->SetParticleMomentumDirection(particleVec); fProtonGun->SetParticlePosition(G4ThreeVector(0., 0., fZPosition)); fProtonGun->SetParticleEnergy(fEnergy); fProtonGun->GeneratePrimaryVertex(event); /* G4AnalysisManager *anaMan = G4AnalysisManager::Instance(); anaMan->FillNtupleIColumn(1, 0, 11); anaMan->FillNtupleDColumn(1, 1, fEnergy); anaMan->FillNtupleDColumn(1, 2, particleVec.x()); anaMan->FillNtupleDColumn(1, 3, particleVec.y()); anaMan->FillNtupleDColumn(1, 4, particleVec.z()); anaMan->AddNtupleRow(1); */ G4AutoLock lock(&mutexInPGA); if (nEveInPGA++ % 10000 == 0) G4cout << nEveInPGA - 1 << " events done" << G4endl; }
/* * ray fire test, distance to out calc normal as well * points inside of a volume, point on surface */ TEST_F(DagSolidTest,test_7) { // point inside cell looking out G4ThreeVector position = G4ThreeVector(50.,0.,0.); G4ThreeVector direction = G4ThreeVector(1.,0.,0.); G4ThreeVector normal; bool v_norm = false; double distance = vol_1->DistanceToOut(position,direction,true,&v_norm,&normal); // when the point is inside or on the surface of the volume, v_norm should be true EXPECT_TRUE(v_norm); // distance should be set to 0.0 in this case EXPECT_EQ(0.0,distance); return; }
/* * ray fire test, distance to out */ TEST_F(DagSolidTest,test_3) { G4ThreeVector position = G4ThreeVector(-100.,0.,0.); G4ThreeVector direction = G4ThreeVector(1.,0.,0.); double distance = vol_1->DistanceToOut(position,direction); // DistanceToOut normally only called from inside the volume // but in this case, we expect the ray to skip over the volume // and give the distance to when we leave the volume instead // distance should be set to 50.0 mm since the point // is in the center of the box EXPECT_EQ(150.0,distance); return; }
//--------------------------------------------------------------------- TrackInformation::TrackInformation() : G4VUserTrackInformation() { fOriginalTrackID = 0; fParticleDefinition = 0; fOriginalPosition = G4ThreeVector(0.,0.,0.); fOriginalMomentum = G4ThreeVector(0.,0.,0.); fOriginalEnergy = 0.; fOriginalTime = 0.; fTrackingStatus = 1; fSourceTrackID = -1; fSourceDefinition = 0; fSourcePosition = G4ThreeVector(0.,0.,0.); fSourceMomentum = G4ThreeVector(0.,0.,0.); fSourceEnergy = 0.; fSourceTime = 0.; }
//------------------------------------------------------------------------- TrackInformation::TrackInformation(const G4Track* aTrack) : G4VUserTrackInformation() { fOriginalTrackID = aTrack->GetTrackID(); fParticleDefinition = aTrack->GetDefinition(); fOriginalPosition = aTrack->GetPosition(); fOriginalMomentum = aTrack->GetMomentum(); fOriginalEnergy = aTrack->GetTotalEnergy(); fOriginalTime = aTrack->GetGlobalTime(); fTrackingStatus = 1; fSourceTrackID = -1; fSourceDefinition = 0; fSourcePosition = G4ThreeVector(0.,0.,0.); fSourceMomentum = G4ThreeVector(0.,0.,0.); fSourceEnergy = 0.; fSourceTime = 0.; }
/* * Point in volume test */ TEST_F(DagSolidTest,point_in_volume) { // sample position G4ThreeVector position = G4ThreeVector(0.,0.,0.); // point in volume test EInside inside = vol_1->Inside(position); EXPECT_EQ(kInside,inside); return; }
void CollimationParticleGun::SetParticleDetails(double x, double y, double xp, double yp, double dp) { //UNITS MUST BE MeV, mm, rad! const G4double mp = particle->GetPDGMass(); /* G4double BeamMomentum = sqrt((ReferenceEnergy*ReferenceEnergy) - (mp*mp)); G4double ParticleMomentum = BeamMomentum * (1.0 + dp); G4double ParticleKE = sqrt((ParticleMomentum*ParticleMomentum) + (mp*mp)) - mp; G4cout << ParticleKE << "\t" << ParticleMomentum << "\t" << BeamMomentum << "\t" << ReferenceEnergy << "\t" << dp << std::endl; */ //The kinetic energy (Total energy - rest mass) ParticleGun->SetParticleEnergy(dp - mp); double p = sqrt(dp*dp - mp*mp); //How to deal with longitudinal coordinate? ParticleGun->SetParticlePosition(G4ThreeVector(x, y, 0)); ParticleGun->SetParticleMomentumDirection(G4ThreeVector(xp,yp,p)); }
/* * ray fire test, distance to in * only for points external to a volume */ TEST_F(DagSolidTest,test_2) { G4ThreeVector position = G4ThreeVector(-100.,0.,0.); double distance = vol_1->DistanceToIn(position); // DistanceToIn point external to volume should give distance // to entry, distance should be set to 50.0 mm EXPECT_EQ(50.0,distance); return; }
G4ThreeVector BIPrimaryGeneratorAction::GetParVec(G4double limit) { G4double theta = acos(1. - G4UniformRand() * (1. - cos(limit))); G4double phi = G4UniformRand() * 2. * CLHEP::pi; G4double vx = sin(theta) * cos(phi); G4double vy = sin(theta) * sin(phi); G4double vz = cos(theta); G4ThreeVector particleVec = G4ThreeVector(vx, vy, vz); return particleVec; }
/* * Point on surface tolerance, kCarTolerance/2.0 = 5.0e-9 * of a surface should return outside */ TEST_F(DagSolidTest,point_out_surface_tolerance) { // sample position G4ThreeVector position = G4ThreeVector(50.+(9.99e-9/2.0),0.,0.); // point in volume test EInside inside = vol_1->Inside(position); EXPECT_EQ(kSurface,inside); return; }
/* * ray fire test, distance to out, called * when point is inside of volume */ TEST_F(DagSolidTest,test_4) { G4ThreeVector position = G4ThreeVector(0.,0.,0.); double distance = vol_1->DistanceToOut(position); // distance should be set to 50.0 mm since the point // is in the center of the box EXPECT_EQ(50.0,distance); return; }
G4VPhysicalVolume* DetectorConstruction::Construct() { //------------------------------------------------------ materials G4double a; // atomic mass G4double z; // atomic number G4double density; G4Material* Ar = new G4Material("ArgonGas", z= 18., a= 39.95*g/mole, density= 1.782*mg/cm3); G4Material* Pb = new G4Material("Lead", z= 82., a= 207.19*g/mole, density= 11.35*g/cm3); //------------------------------------------------------ volumes //------------------------------ experimental hall (world volume) //------------------------------ beam line along x axis G4double expHall_x = 3.0*m; G4double expHall_y = 1.0*m; G4double expHall_z = 1.0*m; G4Box* experimentalHall_box = new G4Box("expHall_box",expHall_x,expHall_y,expHall_z); experimentalHall_log = new G4LogicalVolume(experimentalHall_box,Ar,"expHall_log",0,0,0); experimentalHall_phys = new G4PVPlacement(0,G4ThreeVector(),experimentalHall_log,"expHall",0,false,0); //------------------------------ a calorimeter block G4double block_x = 1.0*m; G4double block_y = 1.0*m; G4double block_z = 1.0*m; G4Box* calorimeterBlock_box = new G4Box("calBlock_box",block_x,block_y,block_z); calorimeterBlock_log = new G4LogicalVolume(calorimeterBlock_box,Pb,"caloBlock_log",0,0,0); G4double blockPos_x = 2*block_x+0.0*m; G4double blockPos_y = 0.0*m; G4double blockPos_z = 0.0*m; calorimeterBlock_phys = new G4PVPlacement(0,G4ThreeVector(blockPos_x,blockPos_y,blockPos_z),calorimeterBlock_log,"caloBlock",experimentalHall_log,false,0); return experimentalHall_phys; }
/* // For using ROOT classes. // When using ROOT classes, it have to be thread local or mutex locked. // I don't know _G4MT_TLS_ is truely needed or not. // https://indico.cern.ch/event/226961/material-old/0/0?contribId=0 // In case without, this code looks like working well... G4ThreadLocal TF1 *fEneFnc_G4MT_TLS_ = 0; */ BIPrimaryGeneratorAction::BIPrimaryGeneratorAction() : G4VUserPrimaryGeneratorAction(), fProtonGun(0), fEneFnc(NULL) { G4AutoLock lock(&mutexInPGA); Int_t seed = time(NULL) + G4Threading::G4GetThreadId() * 100000; gRandom->SetSeed(seed); /* if(!fEneFnc_G4MT_TLS_) fEneFnc_G4MT_TLS_ = new TF1("fEneFnc", "expo(0)+expo(2)+gaus(4)", 0., 30.); fEneFnc = fEneFnc_G4MT_TLS_; */ fEneFnc = new TF1("fEneFnc", "expo(0)+expo(2)+gaus(4)", 0., 30.); fEneFnc->SetParameter(0, 2.67164e+01); fEneFnc->SetParameter(1, -8.35969e-01); fEneFnc->SetParameter(2, 2.15801e+01); fEneFnc->SetParameter(3, -7.66820e-02); fEneFnc->SetParameter(4, 3.79820e+09); fEneFnc->SetParameter(5, 8.94835e+00); fEneFnc->SetParameter(6, 3.04310e+00); fEnergy = fEneFnc->GetRandom() * MeV; G4int nPar = 1; fProtonGun = new G4ParticleGun(nPar); fZPosition = -300.*mm; G4ParticleTable *parTable = G4ParticleTable::GetParticleTable(); G4ParticleDefinition *proton = parTable->FindParticle("proton"); fProtonGun->SetParticleDefinition(proton); fProtonGun->SetParticlePosition(G4ThreeVector(0., 0., fZPosition)); fProtonGun->SetParticleMomentumDirection(G4ThreeVector(0., 0., 1.)); fProtonGun->SetParticleEnergy(fEnergy); TFile *file = new TFile("randomSource.root", "OPEN"); fHisSource = (TH2D*)file->Get("fHisMap"); fHisSource->SetName("fHisSource"); DefineCommands(); }
void BIPrimaryGeneratorAction::FirstBeamGun() { G4AutoLock lock(&mutexInPGA); fEnergy = fEneFnc->GetRandom() * MeV; lock.unlock(); //G4double x = (G4UniformRand() * 12.5 - 6.25)*mm; G4double x = (G4UniformRand() * 12.5 - 6.25) * 1.41421356*mm; G4double y = (G4UniformRand() * 48.75 - 24.375)*mm; fParticleGun->SetParticlePosition(G4ThreeVector(x, y, fZPosition)); }
G4VPhysicalVolume * GeantDetectorConstruction::Construct() { // World G4double worldSize = 5 * ( std::abs( gOptions->GetDetZ_cm() * cm ) + std::abs( gOptions->GetPartZ_cm() * cm ) ) ; G4Box * worldSolid = new G4Box("WorldS", worldSize, worldSize, worldSize); G4LogicalVolume * worldLV = new G4LogicalVolume( worldSolid, G4NistManager::Instance()->FindOrBuildMaterial("G4_Galactic"), "World"); G4VPhysicalVolume * worldPV = new G4PVPlacement( 0, G4ThreeVector(0,0,0), worldLV, "WorldPV", 0, false, 0, true); // Scatterer plane G4Box * scatPlaneSolid = new G4Box("scatPlaneSolid", worldSize, worldSize, gOptions->GetScatThick_um() * um / 2 ); G4Material * scatMat = G4NistManager::Instance()->FindOrBuildMaterial("G4_Si"); G4cout << "Scatterer material: " << scatMat->GetName() << " Radiation length = "<< scatMat->GetRadlen() / cm << " cm"<< G4endl; G4LogicalVolume * scatPlaneLV = new G4LogicalVolume( scatPlaneSolid, scatMat, "scatPlaneLV"); new G4PVPlacement( 0, G4ThreeVector(0,0,0), scatPlaneLV, "scatPlanePV", worldLV, false, 0, true); // Detector plane G4Box * detPlaneSolid = new G4Box("detPlaneSolid", worldSize, worldSize, 1 * um ); G4LogicalVolume * detPlaneLV = new G4LogicalVolume( detPlaneSolid, G4NistManager::Instance()->FindOrBuildMaterial("G4_Galactic"), "detPlaneLV"); new G4PVPlacement( 0, G4ThreeVector( 0, 0, ( gOptions->GetDetZ_cm() + detPlaneSolid->GetZHalfLength() ) * cm ), detPlaneLV, "DetPlanePV", worldLV, false, 0, true); fDetPlaneSD = new GeantTrackerSD( 0 ); SetSensitiveDetector( detPlaneLV, fDetPlaneSD ); return worldPV; }
void BIPrimaryGeneratorAction::SecondBeamGun() { G4double x, y; fHisSource->GetRandom2(x, y); fEnergy = pow(10., (y - 152.) / fDy) * 20 * MeV; G4double theta = CLHEP::pi * ((x - 78.) / fDx) / 180.; G4double phi = G4UniformRand() * fPhiLimit; G4double vx = sin(theta) * cos(phi); G4double vy = sin(theta) * sin(phi); G4double vz = cos(theta); fParVec = G4ThreeVector(vx, vy, vz); fParticleGun->SetParticleMomentumDirection(fParVec); }
// // 24. Cylindrical Cut Section or Cut Tube: // // G4CutTubs(const G4String& pName, // G4double pRMin, // G4double pRMax, // G4double pDz, // G4double pSPhi, // G4double pDPhi, // G4ThreeVector pLowNorm, // G4ThreeVector pHighNorm) void doCutTubs(const std::string &name, double rIn, double rOut, double zhalf, double startPhi, double deltaPhi, std::array<double, 3> lowNorm, std::array<double, 3> highNorm) { G4CutTubs g4(name, rIn, rOut, zhalf, startPhi, deltaPhi, G4ThreeVector(lowNorm[0], lowNorm[1], lowNorm[2]), G4ThreeVector(highNorm[0], highNorm[1], highNorm[2])); DDI::CutTubs dd( zhalf, rIn, rOut, startPhi, deltaPhi, lowNorm[0], lowNorm[1], lowNorm[2], highNorm[0], highNorm[1], highNorm[2]); DDCutTubs dds = DDSolidFactory::cuttubs(name, zhalf, rIn, rOut, startPhi, deltaPhi, lowNorm[0], lowNorm[1], lowNorm[2], highNorm[0], highNorm[1], highNorm[2]); dd.stream(std::cout); std::cout << std::endl; std::cout << "\tg4 volume = " << g4.GetCubicVolume() / cm3 << " cm3" << std::endl; std::cout << "\tdd volume = " << dd.volume() / cm3 << " cm3" << std::endl; std::cout << "\tDD Information: " << dds << " vol= " << dds.volume() << std::endl; }
void GSMS::Source::generate_G4(G4GeneralParticleSource* dst, G4double dAngle) { if (!dst) return; for(int i=0; i<m_gamma.size(); i++) { G4float ene = m_gamma[i].first; G4float act = m_gamma[i].second; dst->AddaSource(act); dst->SetParticleDefinition(G4Gamma::Gamma()); G4SingleParticleSource* src = dst->GetCurrentSource(); src->GetEneDist()->SetMonoEnergy(ene); src->GetAngDist()->SetAngDistType("iso"); src->GetPosDist()->SetPosDisType("Point"); src->GetEneDist()->SetEnergyDisType("Mono"); //src->GetPosDist()->SetCentreCoords(get_coords()); //src->GetPosDist()->SetCentreCoords(G4ThreeVector(1., 0., 0.)); src->GetPosDist()->SetCentreCoords(G4ThreeVector(m_x, m_y, m_z)); G4double basePhi = 0.0; m_x != 0.0 ? basePhi = std::atan(m_y/m_x) : m_y > 0 ? basePhi = pi/2 : basePhi = -pi/2; if(m_x < 0.0 ) basePhi = -pi + basePhi; std::cerr << "X: " << m_x << " Y: " << m_y << " Phi: " << basePhi << std::endl; G4double dPhi = GSMS::get_hull().get_delta_phi(get_coords()); G4double baseTheta = pi/2;//TODO G4double dTheta = GSMS::get_hull().get_delta_theta(get_coords()); std::cerr << "dPhi: " << dPhi*360/2/pi << "; dTheta" << dTheta*360/2/pi << std::endl; //dPhi = 3*pi/2/180;//2*pi/2/180; //dTheta = 16*pi/2/180;//6*pi/2/180; src->GetAngDist()->SetMinPhi(basePhi - dPhi); src->GetAngDist()->SetMaxPhi(basePhi + dPhi); src->GetAngDist()->SetMinTheta(baseTheta - dTheta); src->GetAngDist()->SetMaxTheta(baseTheta + dTheta); std::cerr << ene << std::endl; std::cerr << act << std::endl; } }
// Primary event void PrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent) { /* * To avoid dependence on Detector Construction we will get an envelope volume * from the G4LogicalVolumeStore * * Here we will be assuming our box is sitting in a world where the radiation flux * is coming from the -x direction. Thus we will have a uniform random start location * through the YZ plane */ G4double envSizeX = 0.; G4double envSizeYZ = 0.; if ( !EnvelopeBox ) { G4LogicalVolume* envLV = G4LogicalVolumeStore::GetInstance() -> GetVolume("World"); if ( envLV ) EnvelopeBox = dynamic_cast<G4Box*>( envLV -> GetSolid() ); } if ( EnvelopeBox ) { envSizeYZ = EnvelopeBox -> GetYHalfLength() *2.; envSizeX = EnvelopeBox -> GetXHalfLength() *2.; } else { G4ExceptionDescription msg; msg << "World volume of box shape is not found.\n"; msg << "Perhaps you have changed the geometry.\n"; msg << "\nWhere has the world gone?"; G4Exception("PrimaryGeneratorAction::GeneratePrimaries()","Mycode0001",JustWarning,msg); } // We won't use the outer 10% edge G4double size = 0.9; // Since we are starting in the -x direction and firing in the x direction we want the // particles to come uniformly out of the YZ plane G4double x0 = 0.5 * envSizeX; G4double y0 = size * envSizeYZ * (G4UniformRand() - 0.5); G4double z0 = size * envSizeYZ * (G4UniformRand() - 0.5); particleGun -> SetParticlePosition(G4ThreeVector(-x0,y0,z0)); //particleGun -> SetParticleMomentumDirection(G4ThreeVector(1.0,0.,0.)); // Pure x momentum particleGun -> GeneratePrimaryVertex(anEvent); // creates the initial momentum }
G4ThreeVector BIPrimaryGeneratorAction::GetParVecEne() { G4double x, y; while(1){// HisSource should be changed start with 0 fHisSource->GetRandom2(x, y); if(x >= 78) break; } fEnergy = pow(10., (y - 152.) / fDy) * 20; G4double theta = CLHEP::pi * ((x - 78.) / fDx) / 180.; G4double phi = G4UniformRand() * 2. * CLHEP::pi; G4double vx = sin(theta) * cos(phi); G4double vy = sin(theta) * sin(phi); G4double vz = cos(theta); G4ThreeVector particleVec = G4ThreeVector(vx, vy, vz); return particleVec; }
PrimaryGeneratorAction::PrimaryGeneratorAction() : G4VUserPrimaryGeneratorAction(), particleGun(0), EnvelopeBox(0) { G4int n_particle = 1; particleGun = new G4ParticleGun(n_particle); // Here we'll load the whole particle table to be able to call a lookup G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable(); G4String particleName; G4ParticleDefinition* particle = particleTable -> FindParticle(particleName="gamma"); particleGun -> SetParticleDefinition(particle); particleGun -> SetParticleEnergy(6.0 * MeV); //particleGun -> SetParticlePosition(G4ThreeVector(-1.*m, 0.*m, 0.*m)); particleGun -> SetParticleMomentumDirection(G4ThreeVector(1., 0., 0.)); }
void BIPrimaryGeneratorAction::ThirdBeamGun() { G4AutoLock lock(&mutexInPGA); fEnergy = fEneFnc->GetRandom() * MeV; lock.unlock(); G4double theta; if(fEnergy > 30.*MeV){ lock.lock(); theta = fAngFnc->GetRandom() * deg; lock.unlock(); } else theta = acos(1. - G4UniformRand() * (1. - cos(20.*deg))); G4double phi = G4UniformRand() * fPhiLimit; G4double vx = sin(theta) * cos(phi); G4double vy = sin(theta) * sin(phi); G4double vz = cos(theta); fParVec = G4ThreeVector(vx, vy, vz); fParticleGun->SetParticleMomentumDirection(fParVec); }
int AddSmallCons(G4double dist, G4double density, G4LogicalVolume* motherLogical, int level) { G4double dTheta = THETA_DIST_FACTOR * 2 * asin(SMALL_CONS_R / dist) * mm; /* Theta distance between adjacent cons */ const G4double SMALL_CONS_R = 25; /* Radius of the samll cons */ int cnt = 0; for(G4double theta = dTheta; theta + dTheta < M_PI; theta += dTheta) { // theta is between [0, Pi] G4double dPhi = PHI_DIST_FACTOR * 2 * asin(SMALL_CONS_R / (dist * sin(theta))); /* Phi distance between adjacent spheres */ for (G4double phi = dPhi; 2 * phi + dPhi < M_PI; phi += dPhi ) // phi is between [0, Pi/2] if (density == 1.0 || G4UniformRand() <= density) { /* Cons from the outer layers will have bigger radius */ G4Cons* smallCons = new G4Cons("", 0 * mm, SMALL_CONS_R * mm, 0 * mm, 0.1 * mm, 50 * level * mm, 0 * deg, 360 * deg); /* Calculate the new center of the cons */ G4ThreeVector v(dist * sin(theta) * cos(phi) * mm, dist * sin(theta) * sin(phi) * mm, dist * cos(theta) * mm); G4RotationMatrix* rot = new G4RotationMatrix(); G4double alfa = v.angle(G4ThreeVector(0, 0, 1)); rot->rotateY(M_PI-v.theta()/*(M_PI-alfa) * rad*/); rot->rotateX(-v.phi()); G4LogicalVolume* logicSmallCons = new G4LogicalVolume(smallCons, Air, "", 0, 0, 0); G4PVPlacement* physiSmallCons = new G4PVPlacement(0, v, logicSmallCons, "", motherLogical, false, 0, false); //assert(physiSmallCons->CheckOverlaps()); cnt++; } } return cnt; }
/* // For using ROOT classes. // When using ROOT classes, it have to be thread local or mutex locked. // I don't know _G4MT_TLS_ is truely needed or not. // https://indico.cern.ch/event/226961/material-old/0/0?contribId=0 // In case without, this code looks like working well... G4ThreadLocal TF1 *fEneFnc_G4MT_TLS_ = 0; */ BIPrimaryGeneratorAction::BIPrimaryGeneratorAction(BeamType beamType, G4bool gridFlag, G4bool quarterFlag) : G4VUserPrimaryGeneratorAction(), fParticleGun(nullptr), fInputFile(nullptr), fHisSource(nullptr), fEneFnc(nullptr), fAngFnc(nullptr) { fBeamType = beamType; fForGrid = gridFlag; fUseQuarter = quarterFlag; if(fUseQuarter) fPhiLimit = 0.5 * CLHEP::pi; else fPhiLimit = 2. * CLHEP::pi; fDx = (458. - 78.) / 15.; fDy = (332 - 152) / (log10(60.) - log10(20.)); G4AutoLock lock(&mutexInPGA); Int_t seed = G4UniformRand() * 1000000; G4cout << "Seed of PGA = " << seed << G4endl; gRandom->SetSeed(seed); G4int nPar = 1; fParticleGun = new G4ParticleGun(nPar); fZPosition = -300.*mm; //fZPosition = -160.*mm; // Minimum distance for new beam fParVec = G4ThreeVector(0., 0., 1.); G4ParticleTable *parTable = G4ParticleTable::GetParticleTable(); G4ParticleDefinition *proton = parTable->FindParticle("proton"); fParticleGun->SetParticleDefinition(proton); fParticleGun->SetParticlePosition(G4ThreeVector(0., 0., fZPosition)); fParticleGun->SetParticleMomentumDirection(fParVec); fParticleGun->SetParticleEnergy(fEnergy); fInputFile = new TFile("randomSource.root", "OPEN"); fHisSource = (TH2D*)fInputFile->Get("HisMap"); fHisSource->SetName("fHisSource"); DefineCommands(); // Pointer of Function is not good for readable code? // And also, use if statement does not make program slow. if(fBeamType == kFirstBeam){ fEneFnc = new TF1("fncEne", "exp([0]*x)", 0., 100.); fEneFnc->SetParameter(0, -4.77205e-02); GunFuncPointer = &BIPrimaryGeneratorAction::FirstBeamGun; } else if(fBeamType == kSecondBeam) GunFuncPointer = &BIPrimaryGeneratorAction::SecondBeamGun; else if(fBeamType == kThirdBeam){ fEneFnc = new TF1("fncEne", "exp([0]*x)", 0., 100.); fEneFnc->SetParameter(0, -4.77205e-02); fAngFnc = new TF1("fAngFnc", "exp([0]*x)", 0., 20.); fAngFnc->SetParameter(0, -8.98131e-02); GunFuncPointer = &BIPrimaryGeneratorAction::ThirdBeamGun; } else{ G4cout << "Beam type is wrong. Please check it." << G4endl; exit(0); } }