#include <G4INCLElasticChannel.hh>
Inheritance diagram for G4INCL::ElasticChannel:
Public Member Functions | |
ElasticChannel (Nucleus *n, Particle *p1, Particle *p2) | |
virtual | ~ElasticChannel () |
FinalState * | getFinalState () |
Definition at line 47 of file G4INCLElasticChannel.hh.
Definition at line 46 of file G4INCLElasticChannel.cc.
00047 :theNucleus(n), particle1(p1), particle2(p2) 00048 { 00049 }
G4INCL::ElasticChannel::~ElasticChannel | ( | ) | [virtual] |
FinalState * G4INCL::ElasticChannel::getFinalState | ( | ) | [virtual] |
Implements G4INCL::IChannel.
Definition at line 55 of file G4INCLElasticChannel.cc.
References G4INCL::FinalState::addModifiedParticle(), G4INCL::CrossSections::calculateNNDiffCrossSection(), G4INCL::ParticleTable::effectiveNucleonMass, G4INCL::ParticleTable::getIsospin(), G4INCL::Particle::getMomentum(), G4INCL::Particle::getType(), G4INCL::ThreeVector::getX(), G4INCL::ThreeVector::getY(), G4INCL::ThreeVector::getZ(), G4INCL::ThreeVector::mag2(), G4INCL::KinematicsUtils::momentumInLab(), G4INCL::Neutron, G4INCL::ThreeVector::perp2(), G4INCL::Proton, G4INCL::Particle::setMomentum(), G4INCL::Particle::setType(), G4INCL::Random::shoot(), G4INCL::Math::sign(), G4INCL::KinematicsUtils::squareTotalEnergyInCM(), and G4INCL::Math::twoPi.
00056 { 00057 ParticleType p1TypeOld = particle1->getType(); 00058 ParticleType p2TypeOld = particle2->getType(); 00059 00060 /* Concerning the way we calculate the lab momentum, see the considerations 00061 * in CrossSections::elasticNNLegacy(). 00062 */ 00063 const G4double s = KinematicsUtils::squareTotalEnergyInCM(particle1, particle2); 00064 const G4double pl = KinematicsUtils::momentumInLab(s, ParticleTable::effectiveNucleonMass, ParticleTable::effectiveNucleonMass); 00065 00066 const G4int isospin = ParticleTable::getIsospin(particle1->getType()) + 00067 ParticleTable::getIsospin(particle2->getType()); 00068 00069 // Calculate the outcome of the channel: 00070 G4double psq = particle1->getMomentum().mag2(); 00071 G4double pnorm = std::sqrt(psq); 00072 G4double b = CrossSections::calculateNNDiffCrossSection(pl, isospin); 00073 G4double btmax = 4.0 * psq * b; 00074 G4double z = std::exp(-btmax); 00075 G4double ranres = Random::shoot(); 00076 G4double y = 1.0 - ranres * (1.0 - z); 00077 G4double T = std::log(y)/b; 00078 G4int iexpi = 0; 00079 G4double apt = 1.0; 00080 00081 // Handle np case 00082 if((particle1->getType() == Proton && particle2->getType() == Neutron) || 00083 (particle1->getType() == Neutron && particle2->getType() == Proton)) { 00084 if(pl > 800.0) { 00085 const G4double x = 0.001 * pl; // Transform to GeV 00086 apt = (800.0/pl)*(800.0/pl); 00087 G4double cpt = std::max(6.23 * std::exp(-1.79*x), 0.3); 00088 G4double alphac = 100.0 * 1.0e-6; 00089 G4double aaa = (1 + apt) * (1 - std::exp(-btmax))/b; 00090 G4double argu = psq * alphac; 00091 00092 if(argu >= 8) { 00093 argu = 0.0; 00094 } else { 00095 argu = std::exp(-4.0 * argu); 00096 } 00097 00098 G4double aac = cpt * (1.0 - argu)/alphac; 00099 G4double fracpn = aaa/(aac + aaa); 00100 if(Random::shoot() > fracpn) { 00101 z = std::exp(-4.0 * psq *alphac); 00102 iexpi = 1; 00103 y = 1.0 - ranres*(1.0 - z); 00104 T = std::log(y)/alphac; 00105 } 00106 } 00107 } 00108 00109 G4double ctet = 1.0 + 0.5*T/psq; 00110 if(std::abs(ctet) > 1.0) ctet = Math::sign(ctet); 00111 G4double stet = std::sqrt(1.0 - ctet*ctet); 00112 G4double rndm = Random::shoot(); 00113 00114 G4double fi = Math::twoPi * rndm; 00115 G4double cfi = std::cos(fi); 00116 G4double sfi = std::sin(fi); 00117 00118 G4double xx = particle1->getMomentum().perp2(); 00119 G4double zz = std::pow(particle1->getMomentum().getZ(), 2); 00120 00121 if(xx >= (zz * 1.0e-8)) { 00122 ThreeVector p = particle1->getMomentum(); 00123 G4double yn = std::sqrt(xx); 00124 G4double zn = yn * pnorm; 00125 G4double ex[3], ey[3], ez[3]; 00126 ez[0] = p.getX() / pnorm; 00127 ez[1] = p.getY() / pnorm; 00128 ez[2] = p.getZ() / pnorm; 00129 00130 // Vector Ex is chosen arbitrarily: 00131 ex[0] = p.getY() / yn; 00132 ex[1] = -p.getX() / yn; 00133 ex[2] = 0.0; 00134 00135 ey[0] = p.getX() * p.getZ() / zn; 00136 ey[1] = p.getY() * p.getZ() / zn; 00137 ey[2] = -xx/zn; 00138 00139 G4double pX = (ex[0]*cfi*stet + ey[0]*sfi*stet + ez[0]*ctet) * pnorm; 00140 G4double pY = (ex[1]*cfi*stet + ey[1]*sfi*stet + ez[1]*ctet) * pnorm; 00141 G4double pZ = (ex[2]*cfi*stet + ey[2]*sfi*stet + ez[2]*ctet) * pnorm; 00142 00143 ThreeVector p1momentum = ThreeVector(pX, pY, pZ); 00144 particle1->setMomentum(p1momentum); 00145 particle2->setMomentum(-p1momentum); 00146 } else { // if(xx < (zz * 1.0e-8)) { 00147 G4double momZ = particle1->getMomentum().getZ(); 00148 G4double pX = momZ * cfi * stet; 00149 G4double pY = momZ * sfi * stet; 00150 G4double pZ = momZ * ctet; 00151 00152 ThreeVector p1momentum(pX, pY, pZ); 00153 particle1->setMomentum(p1momentum); 00154 particle2->setMomentum(-p1momentum); 00155 } 00156 00157 // Handle backward scattering here. 00158 00159 if((particle1->getType() == Proton && particle2->getType() == Neutron) || 00160 (particle1->getType() == Neutron && particle2->getType() == Proton)) { 00161 rndm = Random::shoot(); 00162 apt = 1.0; 00163 if(pl > 800.0) { 00164 apt = std::pow(800.0/pl, 2); 00165 } 00166 if(iexpi == 1 || rndm > 1.0/(1.0 + apt)) { 00167 particle1->setType(p2TypeOld); 00168 particle2->setType(p1TypeOld); 00169 } 00170 } 00171 00172 // Note: there is no need to update the kinetic energies of the particles, 00173 // as this is elastic scattering. 00174 00175 FinalState *fs = new FinalState(); 00176 fs->addModifiedParticle(particle1); 00177 fs->addModifiedParticle(particle2); 00178 00179 return fs; 00180 00181 }