Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // INCL++ intra-nuclear cascade model 27 // Alain Boudard, CEA-Saclay, France 28 // Joseph Cugnon, University of Liege, Belgium 29 // Jean-Christophe David, CEA-Saclay, France 30 // Pekka Kaitaniemi, CEA-Saclay, France, and Helsinki Institute of Physics, Finland 31 // Sylvie Leray, CEA-Saclay, France 32 // Davide Mancusi, CEA-Saclay, France 33 // 34 #define INCLXX_IN_GEANT4_MODE 1 35 36 #include "globals.hh" 37 38 /** \file G4INCLParticleSampler.cc 39 * \brief Class for sampling particles in a nucleus 40 * 41 * \date 18 July 2012 42 * \author Davide Mancusi 43 */ 44 45 #include "G4INCLParticleSampler.hh" 46 #include "G4INCLParticleTable.hh" 47 #include "G4INCLNuclearDensityFactory.hh" 48 49 namespace G4INCL { 50 51 ParticleSampler::ParticleSampler(const G4int A, const G4int Z, const G4int S) : 52 sampleOneProton(&ParticleSampler::sampleOneParticleWithoutRPCorrelation), 53 sampleOneNeutron(&ParticleSampler::sampleOneParticleWithoutRPCorrelation), 54 theA(A), 55 theZ(Z), 56 theS(S), 57 theDensity(NULL), 58 thePotential(NULL) 59 { 60 std::fill(theRCDFTable, theRCDFTable + UnknownParticle, static_cast<InterpolationTable *>(NULL)); 61 std::fill(thePCDFTable, thePCDFTable + UnknownParticle, static_cast<InterpolationTable *>(NULL)); 62 std::fill(rpCorrelationCoefficient, rpCorrelationCoefficient + UnknownParticle, 1.); 63 rpCorrelationCoefficient[Proton] = ParticleTable::getRPCorrelationCoefficient(Proton); 64 rpCorrelationCoefficient[Neutron] = ParticleTable::getRPCorrelationCoefficient(Neutron); 65 rpCorrelationCoefficient[Lambda] = ParticleTable::getRPCorrelationCoefficient(Lambda); 66 } 67 68 ParticleSampler::~ParticleSampler() { 69 } 70 71 void ParticleSampler::setDensity(NuclearDensity const * const d) { 72 theDensity = d; 73 updateSampleOneParticleMethods(); 74 } 75 76 void ParticleSampler::setPotential(NuclearPotential::INuclearPotential const * const p) { 77 thePotential = p; 78 updateSampleOneParticleMethods(); 79 } 80 81 void ParticleSampler::updateSampleOneParticleMethods() { 82 if(theDensity && thePotential) { 83 if(rpCorrelationCoefficient[Proton]>0.99999) { 84 sampleOneProton = &ParticleSampler::sampleOneParticleWithRPCorrelation; 85 } else { 86 sampleOneProton = &ParticleSampler::sampleOneParticleWithFuzzyRPCorrelation; 87 } 88 if(rpCorrelationCoefficient[Neutron]>0.99999) { 89 sampleOneNeutron = &ParticleSampler::sampleOneParticleWithRPCorrelation; 90 } else { 91 sampleOneNeutron = &ParticleSampler::sampleOneParticleWithFuzzyRPCorrelation; 92 } 93 } else { 94 sampleOneProton = &ParticleSampler::sampleOneParticleWithoutRPCorrelation; 95 sampleOneNeutron = &ParticleSampler::sampleOneParticleWithoutRPCorrelation; 96 } 97 } 98 99 ParticleList ParticleSampler::sampleParticles(const ThreeVector &position) { 100 ParticleList aList; 101 sampleParticlesIntoList(position, aList); 102 return aList; 103 } 104 105 void ParticleSampler::sampleParticlesIntoList(const ThreeVector &position, ParticleList &theList) { 106 107 if(sampleOneProton == &ParticleSampler::sampleOneParticleWithoutRPCorrelation) { 108 // sampling without correlation, we need to initialize the CDF tables 109 theRCDFTable[Proton] = NuclearDensityFactory::createRCDFTable(Proton, theA, theZ); 110 thePCDFTable[Proton] = NuclearDensityFactory::createPCDFTable(Proton, theA, theZ); 111 theRCDFTable[Neutron] = NuclearDensityFactory::createRCDFTable(Neutron, theA, theZ); 112 thePCDFTable[Neutron] = NuclearDensityFactory::createPCDFTable(Neutron, theA, theZ); 113 theRCDFTable[Lambda] = NuclearDensityFactory::createRCDFTable(Lambda, theA, theZ); 114 thePCDFTable[Lambda] = NuclearDensityFactory::createPCDFTable(Lambda, theA, theZ); 115 } 116 117 theList.resize(theA); 118 if(theA > 2) { 119 ParticleType type = Proton; 120 ParticleSamplerMethod sampleOneParticle = sampleOneProton; 121 for(G4int i = 0; i < theA; ++i) { 122 if(i == theZ) { // Nucleons [Z..A-1] are neutrons 123 type = Lambda; 124 sampleOneParticle = sampleOneNeutron; // hypothesis: Lambdas follow the same rules than neutrons 125 } 126 if(i == theZ - theS) type = Neutron; 127 Particle *p = (this->*sampleOneParticle)(type); 128 p->setPosition(position + p->getPosition()); 129 theList[i] = p; 130 } 131 } else { 132 // For deuterons, only sample the proton position and momentum. The 133 // neutron position and momenta are determined by the conditions of 134 // vanishing CM position and total momentum. 135 // assert(theZ==1); 136 Particle *aProton = (this->*(this->sampleOneProton))(Proton); 137 Particle *aNeutron = new Particle(Neutron, -aProton->getMomentum(), position - aProton->getPosition()); 138 aProton->setPosition(position + aProton->getPosition()); 139 theList[0] = aProton; 140 theList[1] = aNeutron; 141 } 142 } 143 144 Particle *ParticleSampler::sampleOneParticleWithRPCorrelation(const ParticleType t) const { 145 // assert(theDensity && thePotential); 146 const G4double theFermiMomentum = thePotential->getFermiMomentum(t); 147 const ThreeVector momentumVector = Random::sphereVector(theFermiMomentum); 148 const G4double momentumAbs = momentumVector.mag(); 149 const G4double momentumRatio = momentumAbs/theFermiMomentum; 150 const G4double reflectionRadius = theDensity->getMaxRFromP(t, momentumRatio); 151 const ThreeVector positionVector = Random::sphereVector(reflectionRadius); 152 Particle *aParticle = new Particle(t, momentumVector, positionVector); 153 aParticle->setUncorrelatedMomentum(momentumAbs); 154 return aParticle; 155 } 156 157 Particle *ParticleSampler::sampleOneParticleWithoutRPCorrelation(const ParticleType t) const { 158 const G4double position = (*(theRCDFTable[t]))(Random::shoot()); 159 const G4double momentum = (*(thePCDFTable[t]))(Random::shoot()); 160 ThreeVector positionVector = Random::normVector(position); 161 ThreeVector momentumVector = Random::normVector(momentum); 162 return new Particle(t, momentumVector, positionVector); 163 } 164 165 Particle *ParticleSampler::sampleOneParticleWithFuzzyRPCorrelation(const ParticleType t) const { 166 // assert(theDensity && thePotential); 167 std::pair<G4double,G4double> ranNumbers = Random::correlatedUniform(rpCorrelationCoefficient[t]); 168 const G4double x = Math::pow13(ranNumbers.first); 169 const G4double y = Math::pow13(ranNumbers.second); 170 const G4double theFermiMomentum = thePotential->getFermiMomentum(t); 171 const ThreeVector momentumVector = Random::normVector(y*theFermiMomentum); 172 const G4double reflectionRadius = theDensity->getMaxRFromP(t, x); 173 const ThreeVector positionVector = Random::sphereVector(reflectionRadius); 174 Particle *aParticle = new Particle(t, momentumVector, positionVector); 175 aParticle->setUncorrelatedMomentum(x*theFermiMomentum); 176 return aParticle; 177 } 178 179 } 180 181