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; }
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)); }
// 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 }
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); }
void GSMS::Digitizer::Digitize() { m_coll = new DigitsCollection("GSMSDigitizer", "DigitsCollection"); G4DigiManager* digiMan = G4DigiManager::GetDMpointer(); G4int hCollID = digiMan->GetHitsCollectionID("eDep"); G4THitsMap<G4double>* evtMap = NULL; evtMap = (G4THitsMap<G4double>*)(digiMan->GetHitsCollection(hCollID)); if(!evtMap) return; std::map<G4int, G4double*>::iterator itr = evtMap->GetMap()->begin(); for(; itr != evtMap->GetMap()->end(); itr++) { G4double eneDep = *(itr->second); G4double eneChan = 0; // if (eneChan > 10.) // { double dResCs137 = 0.085;//ResolutionScale; G4double dResA = std::sqrt(0.662)*dResCs137; double dRes = dResA/std::sqrt(eneDep);//ResolutionScale; G4double sigma = dRes*eneDep/2.355; // std::cerr << "Mean: " << eneDep << ", Sigma: " << sigma << ", Res: " << dRes; eneChan = G4RandGauss::shoot(eneDep,sigma) / 3 * 1024; // std::cerr << ", Value: " << eneChan << std::endl; // } // else // { // eneChan = G4int(G4Poisson(eneChan)); // }; // std::cerr << ", Channel: " << eneChan; G4double time = G4UniformRand() * (m_etime - m_stime); if(eneChan >= m_dnu) { Digi* digi = new Digi; digi->set_time(time); digi->set_channel(int(eneChan)); digi->set_ene(eneDep); m_coll->insert(digi); } } StoreDigiCollection(m_coll); }
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); }
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; }
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; }
G4VParticleChange* RichG4Cerenkov::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep){ // Do not do RICH stuff // return G4Cerenkov::PostStepDoIt(aTrack,aStep); // Get the current point G4Material &material=*aTrack.GetMaterial(); if(!(material.GetName()==aerogel_name) && !(material.GetName()==naf_name)) return G4Cerenkov::PostStepDoIt(aTrack,aStep); // This is a RICH radiator, use the tools already available to compute everything // Copy and paste of original G4Cerenkov class aParticleChange.Initialize(aTrack); const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle(); const G4Material* aMaterial = aTrack.GetMaterial(); G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint(); G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint(); if(!aParticle || !aMaterial || !pPreStepPoint || !pPostStepPoint)return pParticleChange; G4ThreeVector x0 = pPreStepPoint->GetPosition(); G4ThreeVector p0 = aStep.GetDeltaPosition().unit(); G4double t0 = pPreStepPoint->GetGlobalTime(); G4MaterialPropertiesTable* aMaterialPropertiesTable = aMaterial->GetMaterialPropertiesTable(); if (!aMaterialPropertiesTable) return pParticleChange; const G4MaterialPropertyVector* Rindex = aMaterialPropertiesTable->GetProperty("RINDEX"); if (!Rindex) return pParticleChange; // particle charge const G4double charge = aParticle->GetDefinition()->GetPDGCharge(); // particle beta const G4double beta = (pPreStepPoint ->GetBeta() + pPostStepPoint->GetBeta())/2.; G4double step_length = aStep.GetStepLength(); G4double MeanNumberOfPhotons=GetAverageNumberOfPhotons(charge,beta,step_length/cm,x0,p0); // Copy and paste from the original function if (MeanNumberOfPhotons <= 0.0) { // return unchanged particle and no secondaries aParticleChange.SetNumberOfSecondaries(0); return pParticleChange; } MeanNumberOfPhotons *= step_length; G4int NumPhotons = (G4int) G4Poisson(MeanNumberOfPhotons); if (NumPhotons <= 0) { // return unchanged particle and no secondaries aParticleChange.SetNumberOfSecondaries(0); return pParticleChange; } //////////////////////////////////////////////////////////////// aParticleChange.SetNumberOfSecondaries(NumPhotons); if (fTrackSecondariesFirst) { if (aTrack.GetTrackStatus() == fAlive ) aParticleChange.ProposeTrackStatus(fSuspend); } //////////////////////////////////////////////////////////////// G4double BetaInverse = 1./beta; for (G4int i = 0; i < NumPhotons; i++) { G4double sampledEnergy, sampledRI; G4double cosTheta, sin2Theta; geant _RINDEX; geant _p; _p=getmomentum_(&_RINDEX); // _p is in GeV/c, _RINDEX is the refractive index for this guy sampledEnergy=_p*GeV; // energy in G4 units sampledRI=_RINDEX; cosTheta = BetaInverse / sampledRI; sin2Theta = (1.0 - cosTheta)*(1.0 + cosTheta); // Generate random position of photon on cone surface // defined by Theta G4double rand = G4UniformRand(); G4double phi = twopi*rand; G4double sinPhi = sin(phi); G4double cosPhi = cos(phi); // calculate x,y, and z components of photon energy // (in coord system with primary particle direction // aligned with the z axis) G4double sinTheta = sqrt(sin2Theta); G4double px = sinTheta*cosPhi; G4double py = sinTheta*sinPhi; G4double pz = cosTheta; // Create photon momentum direction vector // The momentum direction is still with respect // to the coordinate system where the primary // particle direction is aligned with the z axis G4ParticleMomentum photonMomentum(px, py, pz); // Rotate momentum direction back to global reference // system photonMomentum.rotateUz(p0); // Determine polarization of new photon G4double sx = cosTheta*cosPhi; G4double sy = cosTheta*sinPhi; G4double sz = -sinTheta; G4ThreeVector photonPolarization(sx, sy, sz); // Rotate back to original coord system photonPolarization.rotateUz(p0); // Generate a new photon: G4DynamicParticle* aCerenkovPhoton = new G4DynamicParticle(G4OpticalPhoton::OpticalPhoton(), photonMomentum); aCerenkovPhoton->SetPolarization (photonPolarization.x(), photonPolarization.y(), photonPolarization.z()); aCerenkovPhoton->SetKineticEnergy(sampledEnergy); rand = G4UniformRand(); G4double delta=rand*aStep.GetStepLength(); G4double deltaTime = delta / ((pPreStepPoint->GetVelocity()+ pPostStepPoint->GetVelocity())/2.); G4double aSecondaryTime = t0 + deltaTime; G4ThreeVector aSecondaryPosition = x0 + rand * aStep.GetDeltaPosition(); G4Track* aSecondaryTrack = new G4Track(aCerenkovPhoton,aSecondaryTime,aSecondaryPosition); aSecondaryTrack->SetTouchableHandle(aStep.GetPreStepPoint()->GetTouchableHandle()); aSecondaryTrack->SetParentID(aTrack.GetTrackID()); aParticleChange.AddSecondary(aSecondaryTrack); } if (verboseLevel>0) { G4cout << "\n Exiting from RichG4Cerenkov::DoIt -- NumberOfSecondaries = " << aParticleChange.GetNumberOfSecondaries() << G4endl; } return pParticleChange; }
G4VParticleChange* RichG4OpBoundaryProcess::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) { // I do not know where these guys come, but I kill them explicitly if(isnan(aTrack.GetPosition()[0]) || isnan(aTrack.GetMomentum()[0])){ aParticleChange.ProposeTrackStatus(fStopAndKill); return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); } // Initialization aParticleChange.Initialize(aTrack); // Get the properties of the particle const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle(); G4double thePhotonMomentum = aParticle->GetTotalMomentum(); G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint(); G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint(); if(isnan(pPreStepPoint->GetPosition()[0])){ aParticleChange.ProposeTrackStatus(fStopAndKill); return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); } if (pPostStepPoint->GetStepStatus() != fGeomBoundary){ return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); } if (aTrack.GetStepLength()<=1e-7){ return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); } G4Material *Material1 = pPreStepPoint -> GetMaterial(); G4Material *Material2 = pPostStepPoint -> GetMaterial(); // Follow the standard path if not RICH radiator to vacuum transition if(!(Material1->GetName()==aerogel_name)) return G4OpBoundaryProcess::PostStepDoIt(aTrack,aStep); // return TOFG4OpBoundaryProcess::PostStepDoIt(aTrack,aStep); if(Material2->GetName()==aerogel_name) return G4OpBoundaryProcess::PostStepDoIt(aTrack,aStep); // return TOFG4OpBoundaryProcess::PostStepDoIt(aTrack,aStep); if(!Material1->GetMaterialPropertiesTable() || !Material2->GetMaterialPropertiesTable()){ aParticleChange.ProposeTrackStatus(fStopAndKill); return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); } OldMomentum = aParticle->GetMomentumDirection(); OldPolarization = aParticle->GetPolarization(); // Get the normal of the surface G4ThreeVector theGlobalPoint = pPostStepPoint->GetPosition(); G4Navigator* theNavigator = G4TransportationManager::GetTransportationManager()-> GetNavigatorForTracking(); G4ThreeVector theLocalPoint = theNavigator-> GetGlobalToLocalTransform(). TransformPoint(theGlobalPoint); G4ThreeVector theLocalNormal; // Normal points back into volume G4bool valid; theLocalNormal = theNavigator->GetLocalExitNormal(&valid); if (valid) { theLocalNormal = -theLocalNormal; } else { aParticleChange.ProposeTrackStatus(fStopAndKill); return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); G4cerr << " RichG4OpBoundaryProcess/PostStepDoIt(): " << " The Navigator reports that it returned an invalid normal" << G4endl; G4Exception("RichG4OpBoundaryProcess::PostStepDoIt", "Invalid Surface Normal", EventMustBeAborted, "Geometry must return valid surface normal"); // return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); } theGlobalNormal = theNavigator->GetLocalToGlobalTransform(). TransformAxis(theLocalNormal); if (OldMomentum * theGlobalNormal > 0.0) { theGlobalNormal = -theGlobalNormal; } // Get the refractive index G4ThreeVector position = aTrack.GetPosition(); const G4double cvpwl=1.2398E-6; G4double wavelength=cvpwl/thePhotonMomentum*GeV; Rindex1=RichRadiatorTileManager::get_refractive_index(position[0]/cm,position[1]/cm,wavelength); G4MaterialPropertyVector* Rindex = Material2->GetMaterialPropertiesTable()->GetProperty("RINDEX"); if(!Rindex){ aParticleChange.ProposeTrackStatus(fStopAndKill); return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); } #if G4VERSION_NUMBER >945 Rindex2 = Rindex->Value(thePhotonMomentum); #else Rindex2 = Rindex->GetProperty(thePhotonMomentum); #endif // SKIP photons exiting through the lateral sides of the tiles if(std::abs(theGlobalNormal[2])<1e-6){ cout <<" g4rich::abs "<<std::abs(theGlobalNormal[2])<<" "<<abs(theGlobalNormal[2])<<" "<<theGlobalNormal[2]<<endl; return G4OpBoundaryProcess::PostStepDoIt(aTrack,aStep); } // if(abs(theGlobalNormal[2])<1e-6) return TOFG4OpBoundaryProcess::PostStepDoIt(aTrack,aStep); DielectricDielectric(); // return G4OpBoundaryProcess::PostStepDoIt(aTrack, aStep); //CJD this solves the f*****g problem NewMomentum = NewMomentum.unit(); NewPolarization = NewPolarization.unit(); if(Material1->GetName()==aerogel_name){ // Simple parameterization to get the right number of p.e. if(G4UniformRand()<RICHDB::scatloss){ aParticleChange.ProposeTrackStatus(fStopAndKill); return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); } // Forward scattering if(G4UniformRand()<RICHDB::scatprob){ // Aerogel scattering effect double phi=2*M_PI*G4UniformRand(); double theta=sqrt(-2*log(G4UniformRand()))*RICHDB::scatang; // Build the vector G4ThreeVector direction(sin(theta)*cos(phi),sin(theta)*sin(phi),cos(theta)); direction.rotateUz(NewMomentum); NewMomentum=direction.unit(); } } aParticleChange.ProposeMomentumDirection(NewMomentum); aParticleChange.ProposePolarization(NewPolarization); return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); }
/* // 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); } }