G4NucleiModel Class Reference

#include <G4NucleiModel.hh>


Public Types

typedef std::pair< std::vector<
G4CascadParticle >, std::vector<
G4InuclElementaryParticle > > 
modelLists

Public Member Functions

 G4NucleiModel ()
 G4NucleiModel (G4int a, G4int z)
 G4NucleiModel (G4InuclNuclei *nuclei)
 ~G4NucleiModel ()
void setVerboseLevel (G4int verbose)
void generateModel (G4InuclNuclei *nuclei)
void generateModel (G4int a, G4int z)
void reset (G4int nHitNeutrons=0, G4int nHitProtons=0, const std::vector< G4ThreeVector > *hitPoints=0)
void printModel () const
G4double getDensity (G4int ip, G4int izone) const
G4double getFermiMomentum (G4int ip, G4int izone) const
G4double getFermiKinetic (G4int ip, G4int izone) const
G4double getPotential (G4int ip, G4int izone) const
G4double getRadiusUnits () const
G4double getRadius () const
G4double getRadius (G4int izone) const
G4double getVolume (G4int izone) const
G4int getNumberOfZones () const
G4int getZone (G4double r) const
G4int getNumberOfNeutrons () const
G4int getNumberOfProtons () const
G4bool empty () const
G4bool stillInside (const G4CascadParticle &cparticle)
G4CascadParticle initializeCascad (G4InuclElementaryParticle *particle)
void initializeCascad (G4InuclNuclei *bullet, G4InuclNuclei *target, modelLists &output)
std::pair< G4int, G4intgetTypesOfNucleonsInvolved () const
void generateParticleFate (G4CascadParticle &cparticle, G4ElementaryParticleCollider *theEPCollider, std::vector< G4CascadParticle > &cascade)
G4bool isProjectile (const G4CascadParticle &cparticle) const
G4bool worthToPropagate (const G4CascadParticle &cparticle) const
G4InuclElementaryParticle generateNucleon (G4int type, G4int zone) const
G4LorentzVector generateNucleonMomentum (G4int type, G4int zone) const
G4double absorptionCrossSection (G4double e, G4int type) const
G4double totalCrossSection (G4double ke, G4int rtype) const


Detailed Description

Definition at line 82 of file G4NucleiModel.hh.


Member Typedef Documentation

typedef std::pair<std::vector<G4CascadParticle>, std::vector<G4InuclElementaryParticle> > G4NucleiModel::modelLists

Definition at line 152 of file G4NucleiModel.hh.


Constructor & Destructor Documentation

G4NucleiModel::G4NucleiModel (  ) 

Definition at line 194 of file G4NucleiModel.cc.

00195   : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
00196     A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
00197     neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
00198     current_nucl2(0) {}

G4NucleiModel::G4NucleiModel ( G4int  a,
G4int  z 
)

Definition at line 200 of file G4NucleiModel.cc.

References generateModel().

00201   : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
00202     A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
00203     neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
00204     current_nucl2(0) {
00205   generateModel(a,z);
00206 }

G4NucleiModel::G4NucleiModel ( G4InuclNuclei nuclei  )  [explicit]

Definition at line 208 of file G4NucleiModel.cc.

References generateModel(), and G4InuclParticleNames::nuclei.

00209   : verboseLevel(0), nuclei_radius(0.), nuclei_volume(0.), number_of_zones(0),
00210     A(0), Z(0), theNucleus(0), neutronNumber(0), protonNumber(0),
00211     neutronNumberCurrent(0), protonNumberCurrent(0), current_nucl1(0),
00212     current_nucl2(0) {
00213   generateModel(nuclei);
00214 }

G4NucleiModel::~G4NucleiModel (  ) 

Definition at line 216 of file G4NucleiModel.cc.

00216                               {
00217   delete theNucleus;
00218   theNucleus = 0;
00219 }


Member Function Documentation

G4double G4NucleiModel::absorptionCrossSection ( G4double  e,
G4int  type 
) const

Definition at line 1646 of file G4NucleiModel.cc.

References G4cerr, G4cout, G4CascadeParameters::gammaQDScale(), G4CascadeInterpolator< NBINS >::interpolate(), photon, G4InuclParticleNames::pionMinus, G4InuclParticleNames::pionPlus, and G4InuclParticleNames::pionZero.

01646                                                                             {
01647   if (type != pionPlus && type != pionMinus && type != pionZero &&
01648       type != photon) {
01649     G4cerr << " absorptionCrossSection only valid for incident pions" << G4endl;
01650     return 0.;
01651   }
01652 
01653   G4double csec = 0.;
01654 
01655   // Pion absorption is parametrized for low vs. medium energy
01656   if (type == pionPlus || type == pionMinus || type == pionZero) {
01657     if (ke < 0.3) csec = (0.1106 / std::sqrt(ke) - 0.8
01658                           + 0.08 / ((ke-0.123)*(ke-0.123) + 0.0056) );
01659     else if (ke < 1.0) csec = 3.6735 * (1.0-ke)*(1.0-ke);     
01660   }
01661 
01662   // Photon cross-section is binned from parametrization by Mi. Kossov
01663   if (type == photon) {
01664     static const G4double gammaQDscale = G4CascadeParameters::gammaQDScale();
01665     static const G4double kebins[] =
01666       {  0.0,  0.01, 0.013, 0.018, 0.024, 0.032, 0.042, 0.056, 0.075, 0.1,
01667          0.13, 0.18, 0.24,  0.32,  0.42,  0.56,  0.75,  1.0,   1.3,   1.8,
01668          2.4,  3.2,  4.2,   5.6,   7.5,   10.0,  13.0,  18.0,  24.0, 32.0 };
01669     static const G4double gammaD[] =
01670       { 2.8,    1.3,    0.89,   0.56,   0.38,   0.27,   0.19,   0.14,   0.098,
01671         0.071, 0.054,  0.0003, 0.0007, 0.0027, 0.0014, 0.001,  0.0012, 0.0005,
01672         0.0003, 0.0002,0.0002, 0.0002, 0.0002, 0.0002, 0.0001, 0.0001, 0.0001,
01673         0.0001, 0.0001, 0.0001 };
01674     static G4CascadeInterpolator<30> interp(kebins);
01675     csec = interp.interpolate(ke, gammaD) * gammaQDscale;
01676   }
01677 
01678   if (csec < 0.0) csec = 0.0;
01679 
01680   if (verboseLevel > 2) {
01681     G4cout << " ekin " << ke << " abs. csec " << csec << " mb" << G4endl;   
01682   }
01683 
01684   return crossSectionUnits * csec;
01685 }

G4bool G4NucleiModel::empty (  )  const [inline]

Definition at line 141 of file G4NucleiModel.hh.

Referenced by G4IntraNucleiCascader::generateCascade().

00141                        { 
00142     return neutronNumberCurrent < 1 && protonNumberCurrent < 1; 
00143   }

void G4NucleiModel::generateModel ( G4int  a,
G4int  z 
)

Definition at line 241 of file G4NucleiModel.cc.

References G4InuclSpecialFunctions::G4cbrt(), G4cout, G4endl, neutron, printModel(), G4InuclParticleNames::proton, and reset().

00241                                                   {
00242   if (verboseLevel) {
00243     G4cout << " >>> G4NucleiModel::generateModel A " << a << " Z " << z
00244            << G4endl;
00245   }
00246 
00247   // If model already built, just return; otherwise intialize everything
00248   if (a == A && z == Z) {
00249     if (verboseLevel > 1) G4cout << " model already generated" << z << G4endl;
00250     reset();
00251     return;
00252   }
00253 
00254   A = a;
00255   Z = z;
00256   delete theNucleus;
00257   theNucleus = new G4InuclNuclei(A,Z);          // For conservation checking
00258 
00259   neutronNumber = A - Z;
00260   protonNumber = Z;
00261   reset();
00262 
00263   if (verboseLevel > 3) {
00264     G4cout << "  crossSectionUnits = " << crossSectionUnits << G4endl
00265            << "  radiusUnits = " << radiusUnits << G4endl
00266            << "  skinDepth = " << skinDepth << G4endl
00267            << "  radiusScale = " << radiusScale << G4endl
00268            << "  radiusScale2 = " << radiusScale2 << G4endl
00269            << "  radiusForSmall = " << radiusForSmall << G4endl
00270            << "  radScaleAlpha  = " << radScaleAlpha << G4endl
00271            << "  fermiMomentum = " << fermiMomentum << G4endl
00272            << "  piTimes4thirds = " << piTimes4thirds << G4endl;
00273   }
00274 
00275   G4double nuclearRadius;               // Nuclear radius computed from A
00276   if (A>4) nuclearRadius = radiusScale*G4cbrt(A) + radiusScale2/G4cbrt(A);
00277   else     nuclearRadius = radiusForSmall * (A==4 ? radScaleAlpha : 1.);
00278 
00279   // This will be used to pre-allocate lots of arrays below
00280   number_of_zones = (A < 5) ? 1 : (A < 100) ? 3 : 6;
00281 
00282   // Clear all parameters arrays for reloading
00283   binding_energies.clear();
00284   nucleon_densities.clear();
00285   zone_potentials.clear();
00286   fermi_momenta.clear();
00287   zone_radii.clear();
00288   zone_volumes.clear();
00289 
00290   fillBindingEnergies();
00291   fillZoneRadii(nuclearRadius);
00292 
00293   G4double tot_vol = fillZoneVolumes(nuclearRadius);    // Woods-Saxon integral
00294 
00295   fillPotentials(proton, tot_vol);              // Protons
00296   fillPotentials(neutron, tot_vol);             // Neutrons
00297 
00298   // Additional flat zone potentials for other hadrons
00299   const std::vector<G4double> vp(number_of_zones, (A>4)?pion_vp:pion_vp_small);
00300   const std::vector<G4double> kp(number_of_zones, kaon_vp);
00301   const std::vector<G4double> hp(number_of_zones, hyperon_vp);
00302 
00303   zone_potentials.push_back(vp);
00304   zone_potentials.push_back(kp);
00305   zone_potentials.push_back(hp);
00306 
00307   nuclei_radius = zone_radii.back();
00308   nuclei_volume = std::accumulate(zone_volumes.begin(),zone_volumes.end(),0.);
00309 
00310   if (verboseLevel > 3) printModel();
00311 }

void G4NucleiModel::generateModel ( G4InuclNuclei nuclei  ) 

Definition at line 237 of file G4NucleiModel.cc.

References G4InuclParticleNames::nuclei.

Referenced by G4NucleiModel(), and G4IntraNucleiCascader::initialize().

00237                                                        {
00238   generateModel(nuclei->getA(), nuclei->getZ());
00239 }

G4InuclElementaryParticle G4NucleiModel::generateNucleon ( G4int  type,
G4int  zone 
) const

Definition at line 585 of file G4NucleiModel.cc.

References G4cout, and generateNucleonMomentum().

00585                                                            {
00586   if (verboseLevel > 1) {
00587     G4cout << " >>> G4NucleiModel::generateNucleon" << G4endl;
00588   }
00589 
00590   G4LorentzVector mom = generateNucleonMomentum(type, zone);
00591   return G4InuclElementaryParticle(mom, type);
00592 }

G4LorentzVector G4NucleiModel::generateNucleonMomentum ( G4int  type,
G4int  zone 
) const

Definition at line 576 of file G4NucleiModel.cc.

References G4InuclSpecialFunctions::G4cbrt(), G4InuclSpecialFunctions::generateWithRandomAngles(), getFermiMomentum(), G4InuclElementaryParticle::getParticleMass(), and G4InuclSpecialFunctions::inuclRndm().

Referenced by generateNucleon().

00576                                                                    {
00577   G4double pmod = getFermiMomentum(type, zone) * G4cbrt(inuclRndm());
00578   G4double mass = G4InuclElementaryParticle::getParticleMass(type);
00579 
00580   return generateWithRandomAngles(pmod, mass);
00581 }

void G4NucleiModel::generateParticleFate ( G4CascadParticle cparticle,
G4ElementaryParticleCollider theEPCollider,
std::vector< G4CascadParticle > &  cascade 
)

Definition at line 790 of file G4NucleiModel.cc.

References G4CascadeCheckBalance::collide(), G4ElementaryParticleCollider::collide(), G4cerr, G4cout, G4InuclParticle::getCharge(), G4CascadParticle::getCurrentZone(), G4CollisionOutput::getOutgoingParticles(), G4CascadParticle::getParticle(), G4CascadParticle::getPosition(), G4CascadParticle::incrementCurrentPath(), G4InuclElementaryParticle::nucleon(), G4CollisionOutput::numberOfOutgoingParticles(), G4CascadeCheckBalance::okay(), G4CollisionOutput::printCollisionOutput(), G4CascadParticle::propagateAlongThePath(), G4InuclElementaryParticle::quasi_deutron(), G4CollisionOutput::reset(), G4VCascadeCollider::setVerboseLevel(), G4InuclElementaryParticle::type(), and G4CascadParticle::updatePosition().

Referenced by G4IntraNucleiCascader::generateCascade().

00792                                                                        {
00793   if (verboseLevel > 1)
00794     G4cout << " >>> G4NucleiModel::generateParticleFate" << G4endl;
00795 
00796   if (verboseLevel > 2) G4cout << " cparticle: " << cparticle << G4endl;
00797 
00798   // Create four-vector checking
00799 #ifdef G4CASCADE_CHECK_ECONS
00800   G4CascadeCheckBalance balance(0.005, 0.01, "G4NucleiModel");  // Second arg is in GeV
00801   balance.setVerboseLevel(verboseLevel);
00802 #endif
00803 
00804   outgoing_cparticles.clear();          // Clear return buffer for this event
00805   generateInteractionPartners(cparticle);       // Fills "thePartners" data
00806 
00807   if (thePartners.empty()) { // smth. is wrong -> needs special treatment
00808     if (verboseLevel)
00809       G4cerr << " generateParticleFate-> got empty interaction-partners list "
00810              << G4endl;
00811     return;
00812   }
00813 
00814   G4int npart = thePartners.size();     // Last item is a total-path placeholder
00815 
00816   if (npart == 1) {             // cparticle is on the next zone entry
00817     cparticle.propagateAlongThePath(thePartners[0].second);
00818     cparticle.incrementCurrentPath(thePartners[0].second);
00819     boundaryTransition(cparticle);
00820     outgoing_cparticles.push_back(cparticle);
00821     
00822     if (verboseLevel > 2) G4cout << " next zone \n" << cparticle << G4endl;
00823   } else {                      // there are possible interactions
00824     if (verboseLevel > 1)
00825       G4cout << " processing " << npart-1 << " possible interactions" << G4endl;
00826 
00827     G4ThreeVector old_position = cparticle.getPosition();
00828     G4InuclElementaryParticle& bullet = cparticle.getParticle();
00829     G4bool no_interaction = true;
00830     G4int zone = cparticle.getCurrentZone();
00831     
00832     for (G4int i=0; i<npart-1; i++) {   // Last item is a total-path placeholder
00833       if (i > 0) cparticle.updatePosition(old_position); 
00834       
00835       G4InuclElementaryParticle& target = thePartners[i].first; 
00836 
00837       if (verboseLevel > 3) {
00838         if (target.quasi_deutron()) G4cout << " try absorption: ";
00839         G4cout << " target " << target.type() << " bullet " << bullet.type()
00840                << G4endl;
00841       }
00842 
00843       EPCoutput.reset();
00844       theEPCollider->collide(&bullet, &target, EPCoutput);
00845 
00846       // If collision failed, exit loop over partners
00847       if (EPCoutput.numberOfOutgoingParticles() == 0) break;
00848 
00849       if (verboseLevel > 2) {
00850         EPCoutput.printCollisionOutput();
00851 #ifdef G4CASCADE_CHECK_ECONS
00852         balance.collide(&bullet, &target, EPCoutput);
00853         balance.okay();         // Do checks, but ignore result
00854 #endif
00855       }
00856 
00857       // Get list of outgoing particles for evaluation
00858       std::vector<G4InuclElementaryParticle>& outgoing_particles = 
00859         EPCoutput.getOutgoingParticles();
00860       
00861       if (!passFermi(outgoing_particles, zone)) continue; // Interaction fails
00862 
00863       // Trailing effect: reject interaction at previously hit nucleon
00864       cparticle.propagateAlongThePath(thePartners[i].second);
00865       G4ThreeVector new_position = cparticle.getPosition();
00866 
00867       if (!passTrailing(new_position)) continue;
00868       collisionPts.push_back(new_position);
00869 
00870       // Sort particles according to beta (fastest first)
00871       std::sort(outgoing_particles.begin(), outgoing_particles.end(),
00872                 G4ParticleLargerBeta() );
00873 
00874       if (verboseLevel > 2)
00875         G4cout << " adding " << outgoing_particles.size()
00876                << " output particles" << G4endl;
00877 
00878       // NOTE:  Embedded temporary is optimized away (no copying gets done)
00879       for (G4int ip = 0; ip < G4int(outgoing_particles.size()); ip++) { 
00880         outgoing_cparticles.push_back(G4CascadParticle(outgoing_particles[ip],
00881                                                        new_position, zone,
00882                                                        0.0, 0));
00883       }
00884       
00885       no_interaction = false;
00886       current_nucl1 = 0;
00887       current_nucl2 = 0;
00888       
00889 #ifdef G4CASCADE_DEBUG_CHARGE
00890       {
00891         G4double out_charge = 0.0;
00892         
00893         for (G4int ip = 0; ip < G4int(outgoing_particles.size()); ip++) 
00894           out_charge += outgoing_particles[ip].getCharge();
00895         
00896         G4cout << " multiplicity " << outgoing_particles.size()
00897                << " bul type " << bullet.type()
00898                << " targ type " << target.type()
00899                << "\n initial charge "
00900                << bullet.getCharge() + target.getCharge() 
00901                << " out charge " << out_charge << G4endl;  
00902       }
00903 #endif
00904       
00905       if (verboseLevel > 2)
00906         G4cout << " partner type " << target.type() << G4endl;
00907       
00908       if (target.nucleon()) {
00909         current_nucl1 = target.type();
00910       } else {
00911         if (verboseLevel > 2) G4cout << " good absorption " << G4endl;
00912         current_nucl1 = (target.type() - 100) / 10;
00913         current_nucl2 = target.type() - 100 - 10 * current_nucl1;
00914       }   
00915       
00916       if (current_nucl1 == 1) {
00917         if (verboseLevel > 3) G4cout << " decrement proton count" << G4endl;
00918         protonNumberCurrent--;
00919       } else {
00920         if (verboseLevel > 3) G4cout << " decrement neutron count" << G4endl;
00921         neutronNumberCurrent--;
00922       } 
00923       
00924       if (current_nucl2 == 1) {
00925         if (verboseLevel > 3) G4cout << " decrement proton count" << G4endl;
00926         protonNumberCurrent--;
00927       } else if (current_nucl2 == 2) {
00928         if (verboseLevel > 3) G4cout << " decrement neutron count" << G4endl;
00929         neutronNumberCurrent--;
00930       }
00931       
00932       break;
00933     }           // loop over partners
00934     
00935     if (no_interaction) {               // still no interactions
00936       if (verboseLevel > 1) G4cout << " no interaction " << G4endl;
00937 
00938       // For conservation checking (below), get particle before updating
00939       static G4InuclElementaryParticle prescatCP;       // Avoid memory churn
00940       prescatCP = cparticle.getParticle();
00941 
00942       // Last "partner" is just a total-path placeholder
00943       cparticle.updatePosition(old_position); 
00944       cparticle.propagateAlongThePath(thePartners[npart-1].second);
00945       cparticle.incrementCurrentPath(thePartners[npart-1].second);
00946       boundaryTransition(cparticle);
00947       outgoing_cparticles.push_back(cparticle);
00948 
00949       // Check conservation for simple scattering (ignore target nucleus!)
00950 #ifdef G4CASCADE_CHECK_ECONS
00951       if (verboseLevel > 2) {
00952         balance.collide(&prescatCP, 0, outgoing_cparticles);
00953         balance.okay();         // Report violations, but don't act on them
00954       }
00955 #endif
00956     }   // if (no_interaction)
00957   }     // if (npart == 1) [else]
00958 
00959   return;
00960 }

G4double G4NucleiModel::getDensity ( G4int  ip,
G4int  izone 
) const [inline]

Definition at line 101 of file G4NucleiModel.hh.

Referenced by printModel().

00101                                                    {
00102     return nucleon_densities[ip - 1][izone];
00103   }

G4double G4NucleiModel::getFermiKinetic ( G4int  ip,
G4int  izone 
) const

Definition at line 562 of file G4NucleiModel.cc.

References G4InuclElementaryParticle::getParticleMass().

Referenced by worthToPropagate().

00562                                                                    {
00563   G4double ekin = 0.0;
00564   
00565   if (ip < 3 && izone < number_of_zones) {      // ip for proton/neutron only
00566     G4double pfermi = fermi_momenta[ip - 1][izone]; 
00567     G4double mass = G4InuclElementaryParticle::getParticleMass(ip);
00568     
00569     ekin = std::sqrt(pfermi*pfermi + mass*mass) - mass;
00570   }  
00571   return ekin;
00572 }

G4double G4NucleiModel::getFermiMomentum ( G4int  ip,
G4int  izone 
) const [inline]

Definition at line 105 of file G4NucleiModel.hh.

Referenced by generateNucleonMomentum(), and printModel().

00105                                                          {
00106     return fermi_momenta[ip - 1][izone];
00107   }

G4int G4NucleiModel::getNumberOfNeutrons (  )  const [inline]

Definition at line 138 of file G4NucleiModel.hh.

Referenced by G4IntraNucleiCascader::generateCascade().

00138 { return neutronNumberCurrent; }

G4int G4NucleiModel::getNumberOfProtons (  )  const [inline]

Definition at line 139 of file G4NucleiModel.hh.

Referenced by G4IntraNucleiCascader::generateCascade().

00139 { return protonNumberCurrent; }

G4int G4NucleiModel::getNumberOfZones (  )  const [inline]

Definition at line 132 of file G4NucleiModel.hh.

00132 { return number_of_zones; }

G4double G4NucleiModel::getPotential ( G4int  ip,
G4int  izone 
) const [inline]

Definition at line 111 of file G4NucleiModel.hh.

Referenced by printModel().

00111                                                      {
00112     if (ip == 9) return 0.0;            // Special case for photons
00113     G4int ip0 = ip < 3 ? ip - 1 : 2;
00114     if (ip > 10 && ip < 18) ip0 = 3;
00115     if (ip > 20) ip0 = 4;
00116     return izone < number_of_zones ? zone_potentials[ip0][izone] : 0.0;
00117   }

G4double G4NucleiModel::getRadius ( G4int  izone  )  const [inline]

Definition at line 123 of file G4NucleiModel.hh.

00123                                         {
00124     return ( (izone<0) ? 0.
00125              : (izone<number_of_zones) ? zone_radii[izone] : nuclei_radius);
00126   }

G4double G4NucleiModel::getRadius (  )  const [inline]

Definition at line 122 of file G4NucleiModel.hh.

00122 { return nuclei_radius; }

G4double G4NucleiModel::getRadiusUnits (  )  const [inline]

Definition at line 120 of file G4NucleiModel.hh.

Referenced by G4IntraNucleiCascader::processSecondary().

00120 { return radiusUnits*CLHEP::fermi; }

std::pair<G4int, G4int> G4NucleiModel::getTypesOfNucleonsInvolved (  )  const [inline]

Definition at line 158 of file G4NucleiModel.hh.

Referenced by G4IntraNucleiCascader::generateCascade().

00158                                                            {
00159     return std::pair<G4int, G4int>(current_nucl1, current_nucl2);
00160   }

G4double G4NucleiModel::getVolume ( G4int  izone  )  const [inline]

Definition at line 127 of file G4NucleiModel.hh.

00127                                         {
00128     return ( (izone<0) ? 0.
00129              : (izone<number_of_zones) ? zone_volumes[izone] : nuclei_volume);
00130   }

G4int G4NucleiModel::getZone ( G4double  r  )  const [inline]

Definition at line 133 of file G4NucleiModel.hh.

Referenced by G4IntraNucleiCascader::processSecondary().

00133                                   {
00134     for (G4int iz=0; iz<number_of_zones; iz++) if (r<zone_radii[iz]) return iz;
00135     return number_of_zones;
00136   }

void G4NucleiModel::initializeCascad ( G4InuclNuclei bullet,
G4InuclNuclei target,
modelLists output 
)

Definition at line 1184 of file G4NucleiModel.cc.

References G4LorentzConvertor::backToTheLab(), G4InuclSpecialFunctions::bindingEnergy(), G4cout, G4InuclSpecialFunctions::generateWithRandomAngles(), G4InuclNuclei::getA(), G4InuclParticle::getEnergy(), G4InuclParticle::getKineticEnergy(), G4InuclParticle::getMass(), G4InuclNuclei::getZ(), G4InuclSpecialFunctions::inuclRndm(), G4InuclSpecialFunctions::randomPHI(), and G4LorentzConvertor::toTheTargetRestFrame().

01186                                                          {
01187   if (verboseLevel) {
01188     G4cout << " >>> G4NucleiModel::initializeCascad(bullet,target,output)"
01189            << G4endl;
01190   }
01191 
01192   const G4double large = 1000.0;
01193   const G4double max_a_for_cascad = 5.0;
01194   const G4double ekin_cut = 2.0;
01195   const G4double small_ekin = 1.0e-6;
01196   const G4double r_large2for3 = 62.0;
01197   const G4double r0forAeq3 = 3.92;
01198   const G4double s3max = 6.5;
01199   const G4double r_large2for4 = 69.14;
01200   const G4double r0forAeq4 = 4.16;
01201   const G4double s4max = 7.0;
01202   const G4int itry_max = 100;
01203 
01204   // Convenient references to input buffer contents
01205   std::vector<G4CascadParticle>& casparticles = output.first;
01206   std::vector<G4InuclElementaryParticle>& particles = output.second;
01207 
01208   casparticles.clear();         // Reset input buffer to fill this event
01209   particles.clear();
01210 
01211   // first decide whether it will be cascad or compound final nuclei
01212   G4int ab = bullet->getA();
01213   G4int zb = bullet->getZ();
01214   G4int at = target->getA();
01215   G4int zt = target->getZ();
01216 
01217   G4double massb = bullet->getMass();   // For creating LorentzVectors below
01218 
01219   if (ab < max_a_for_cascad) {
01220 
01221     G4double benb = bindingEnergy(ab,zb)/GeV / G4double(ab);
01222     G4double bent = bindingEnergy(at,zt)/GeV / G4double(at);
01223     G4double ben = benb < bent ? bent : benb;
01224 
01225     if (bullet->getKineticEnergy()/ab > ekin_cut*ben) {
01226       G4int itryg = 0;
01227 
01228       while (casparticles.size() == 0 && itryg < itry_max) {      
01229         itryg++;
01230         particles.clear();
01231       
01232         //    nucleons coordinates and momenta in nuclei rest frame
01233         coordinates.clear();
01234         momentums.clear();
01235      
01236         if (ab < 3) { // deuteron, simplest case
01237           G4double r = 2.214 - 3.4208 * std::log(1.0 - 0.981 * inuclRndm());
01238           G4ThreeVector coord1 = generateWithRandomAngles(r).vect();
01239           coordinates.push_back(coord1);
01240           coordinates.push_back(-coord1);
01241 
01242           G4double p = 0.0;
01243           G4bool bad = true;
01244           G4int itry = 0;
01245 
01246           while (bad && itry < itry_max) {
01247             itry++;
01248             p = 456.0 * inuclRndm();
01249 
01250             if (p * p / (p * p + 2079.36) / (p * p + 2079.36) > 1.2023e-4 * inuclRndm() &&
01251                p * r > 312.0) bad = false;
01252           }
01253 
01254           if (itry == itry_max)
01255             if (verboseLevel > 2){ 
01256               G4cout << " deutron bullet generation-> itry = " << itry_max << G4endl;   
01257             }
01258 
01259           p = 0.0005 * p;
01260 
01261           if (verboseLevel > 2){ 
01262             G4cout << " p nuc " << p << G4endl;
01263           }
01264 
01265           G4LorentzVector mom = generateWithRandomAngles(p, massb);
01266 
01267           momentums.push_back(mom);
01268           mom.setVect(-mom.vect());
01269           momentums.push_back(-mom);
01270         } else {
01271           G4ThreeVector coord1;
01272 
01273           G4bool badco = true;
01274 
01275           G4int itry = 0;
01276         
01277           if (ab == 3) {
01278             while (badco && itry < itry_max) {
01279               if (itry > 0) coordinates.clear();
01280               itry++;   
01281               G4int i(0);    
01282 
01283               for (i = 0; i < 2; i++) {
01284                 G4int itry1 = 0;
01285                 G4double ss, u, rho; 
01286                 G4double fmax = std::exp(-0.5) / std::sqrt(0.5);
01287 
01288                 while (itry1 < itry_max) {
01289                   itry1++;
01290                   ss = -std::log(inuclRndm());
01291                   u = fmax * inuclRndm();
01292                   rho = std::sqrt(ss) * std::exp(-ss);
01293 
01294                   if (rho > u && ss < s3max) {
01295                     ss = r0forAeq3 * std::sqrt(ss);
01296                     coord1 = generateWithRandomAngles(ss).vect();
01297                     coordinates.push_back(coord1);
01298 
01299                     if (verboseLevel > 2){
01300                       G4cout << " i " << i << " r " << coord1.mag() << G4endl;
01301                     }
01302                     break;
01303                   }
01304                 }
01305 
01306                 if (itry1 == itry_max) { // bad case
01307                   coord1.set(10000.,10000.,10000.);
01308                   coordinates.push_back(coord1);
01309                   break;
01310                 }
01311               }
01312 
01313               coord1 = -coordinates[0] - coordinates[1]; 
01314               if (verboseLevel > 2) {
01315                 G4cout << " 3  r " << coord1.mag() << G4endl;
01316               }
01317 
01318               coordinates.push_back(coord1);        
01319             
01320               G4bool large_dist = false;
01321 
01322               for (i = 0; i < 2; i++) {
01323                 for (G4int j = i+1; j < 3; j++) {
01324                   G4double r2 = (coordinates[i]-coordinates[j]).mag2();
01325 
01326                   if (verboseLevel > 2) {
01327                     G4cout << " i " << i << " j " << j << " r2 " << r2 << G4endl;
01328                   }
01329 
01330                   if (r2 > r_large2for3) {
01331                     large_dist = true;
01332 
01333                     break; 
01334                   }      
01335                 }
01336 
01337                 if (large_dist) break;
01338               } 
01339 
01340               if(!large_dist) badco = false;
01341 
01342             }
01343 
01344           } else { // a >= 4
01345             G4double b = 3./(ab - 2.0);
01346             G4double b1 = 1.0 - b / 2.0;
01347             G4double u = b1 + std::sqrt(b1 * b1 + b);
01348             G4double fmax = (1.0 + u/b) * u * std::exp(-u);
01349           
01350             while (badco && itry < itry_max) {
01351 
01352               if (itry > 0) coordinates.clear();
01353               itry++;
01354               G4int i(0);
01355             
01356               for (i = 0; i < ab-1; i++) {
01357                 G4int itry1 = 0;
01358                 G4double ss; 
01359 
01360                 while (itry1 < itry_max) {
01361                   itry1++;
01362                   ss = -std::log(inuclRndm());
01363                   u = fmax * inuclRndm();
01364 
01365                   if (std::sqrt(ss) * std::exp(-ss) * (1.0 + ss/b) > u
01366                       && ss < s4max) {
01367                     ss = r0forAeq4 * std::sqrt(ss);
01368                     coord1 = generateWithRandomAngles(ss).vect();
01369                     coordinates.push_back(coord1);
01370 
01371                     if (verboseLevel > 2) {
01372                       G4cout << " i " << i << " r " << coord1.mag() << G4endl;
01373                     }
01374 
01375                     break;
01376                   }
01377                 }
01378 
01379                 if (itry1 == itry_max) { // bad case
01380                   coord1.set(10000.,10000.,10000.);
01381                   coordinates.push_back(coord1);
01382                   break;
01383                 }
01384               }
01385 
01386               coord1 *= 0.0;    // Cheap way to reset
01387               for(G4int j = 0; j < ab -1; j++) coord1 -= coordinates[j];
01388 
01389               coordinates.push_back(coord1);   
01390 
01391               if (verboseLevel > 2){
01392                 G4cout << " last r " << coord1.mag() << G4endl;
01393               }
01394             
01395               G4bool large_dist = false;
01396 
01397               for (i = 0; i < ab-1; i++) {
01398                 for (G4int j = i+1; j < ab; j++) {
01399              
01400                   G4double r2 = (coordinates[i]-coordinates[j]).mag2();
01401 
01402                   if (verboseLevel > 2){
01403                     G4cout << " i " << i << " j " << j << " r2 " << r2 << G4endl;
01404                   }
01405 
01406                   if (r2 > r_large2for4) {
01407                     large_dist = true;
01408 
01409                     break; 
01410                   }      
01411                 }
01412 
01413                 if (large_dist) break;
01414               } 
01415 
01416               if (!large_dist) badco = false;
01417             }
01418           } 
01419 
01420           if(badco) {
01421             G4cout << " can not generate the nucleons coordinates for a "
01422                    << ab << G4endl;     
01423 
01424             casparticles.clear();       // Return empty buffer on error
01425             particles.clear();
01426             return;
01427 
01428           } else { // momentums
01429             G4double p, u, x;
01430             G4LorentzVector mom;
01431             //G4bool badp = True;
01432 
01433             for (G4int i = 0; i < ab - 1; i++) {
01434               G4int itry2 = 0;
01435 
01436               while(itry2 < itry_max) {
01437                 itry2++;
01438                 u = -std::log(0.879853 - 0.8798502 * inuclRndm());
01439                 x = u * std::exp(-u);
01440 
01441                 if(x > inuclRndm()) {
01442                   p = std::sqrt(0.01953 * u);
01443                   mom = generateWithRandomAngles(p, massb);
01444                   momentums.push_back(mom);
01445 
01446                   break;
01447                 }
01448               } // while (itry2 < itry_max)
01449 
01450               if(itry2 == itry_max) {
01451                 G4cout << " can not generate proper momentum for a "
01452                        << ab << G4endl;
01453 
01454                 casparticles.clear();   // Return empty buffer on error
01455                 particles.clear();
01456                 return;
01457               } 
01458             }   // for (i=0 ...
01459             // last momentum
01460 
01461             mom *= 0.;          // Cheap way to reset
01462             mom.setE(bullet->getEnergy()+target->getEnergy());
01463 
01464             for(G4int j=0; j< ab-1; j++) mom -= momentums[j]; 
01465 
01466             momentums.push_back(mom);
01467           } 
01468         }
01469  
01470         // Coordinates and momenta at rest are generated, now back to the lab
01471         G4double rb = 0.0;
01472         G4int i(0);
01473 
01474         for(i = 0; i < G4int(coordinates.size()); i++) {      
01475           G4double rp = coordinates[i].mag2();
01476 
01477           if(rp > rb) rb = rp;
01478         }
01479 
01480         // nuclei i.p. as a whole
01481         G4double s1 = std::sqrt(inuclRndm()); 
01482         G4double phi = randomPHI();
01483         G4double rz = (nuclei_radius + rb) * s1;
01484         G4ThreeVector global_pos(rz*std::cos(phi), rz*std::sin(phi),
01485                                  -(nuclei_radius+rb)*std::sqrt(1.0-s1*s1));
01486 
01487         for (i = 0; i < G4int(coordinates.size()); i++) {
01488           coordinates[i] += global_pos;
01489         }  
01490 
01491         // all nucleons at rest
01492         raw_particles.clear();
01493 
01494         for (G4int ipa = 0; ipa < ab; ipa++) {
01495           G4int knd = ipa < zb ? 1 : 2;
01496           raw_particles.push_back(G4InuclElementaryParticle(momentums[ipa], knd));
01497         } 
01498       
01499         G4InuclElementaryParticle dummy(small_ekin, 1);
01500         G4LorentzConvertor toTheBulletRestFrame(&dummy, bullet);
01501         toTheBulletRestFrame.toTheTargetRestFrame();
01502 
01503         particleIterator ipart;
01504 
01505         for (ipart = raw_particles.begin(); ipart != raw_particles.end(); ipart++) {
01506           ipart->setMomentum(toTheBulletRestFrame.backToTheLab(ipart->getMomentum())); 
01507         }
01508 
01509         // fill cascad particles and outgoing particles
01510 
01511         for(G4int ip = 0; ip < G4int(raw_particles.size()); ip++) {
01512           G4LorentzVector mom = raw_particles[ip].getMomentum();
01513           G4double pmod = mom.rho();
01514           G4double t0 = -mom.vect().dot(coordinates[ip]) / pmod;
01515           G4double det = t0 * t0 + nuclei_radius * nuclei_radius
01516                        - coordinates[ip].mag2();
01517           G4double tr = -1.0;
01518 
01519           if(det > 0.0) {
01520             G4double t1 = t0 + std::sqrt(det);
01521             G4double t2 = t0 - std::sqrt(det);
01522 
01523             if(std::fabs(t1) <= std::fabs(t2)) {         
01524               if(t1 > 0.0) {
01525                 if(coordinates[ip].z() + mom.z() * t1 / pmod <= 0.0) tr = t1;
01526               }
01527 
01528               if(tr < 0.0 && t2 > 0.0) {
01529 
01530                 if(coordinates[ip].z() + mom.z() * t2 / pmod <= 0.0) tr = t2;
01531               }
01532 
01533             } else {
01534               if(t2 > 0.0) {
01535 
01536                 if(coordinates[ip].z() + mom.z() * t2 / pmod <= 0.0) tr = t2;
01537               }
01538 
01539               if(tr < 0.0 && t1 > 0.0) {
01540                 if(coordinates[ip].z() + mom.z() * t1 / pmod <= 0.0) tr = t1;
01541               }
01542             } 
01543 
01544           }
01545 
01546           if(tr >= 0.0) { // cascad particle
01547             coordinates[ip] += mom.vect()*tr / pmod;
01548             casparticles.push_back(G4CascadParticle(raw_particles[ip], 
01549                                                     coordinates[ip], 
01550                                                     number_of_zones, large, 0));
01551 
01552           } else {
01553             particles.push_back(raw_particles[ip]); 
01554           } 
01555         }
01556       }    
01557 
01558       if(casparticles.size() == 0) {
01559         particles.clear();
01560 
01561         G4cout << " can not generate proper distribution for " << itry_max
01562                << " steps " << G4endl;
01563       }    
01564     }
01565   }
01566 
01567   if(verboseLevel > 2){
01568     G4int ip(0);
01569 
01570     G4cout << " cascad particles: " << casparticles.size() << G4endl;
01571     for(ip = 0; ip < G4int(casparticles.size()); ip++)
01572       G4cout << casparticles[ip] << G4endl;
01573 
01574     G4cout << " outgoing particles: " << particles.size() << G4endl;
01575     for(ip = 0; ip < G4int(particles.size()); ip++)
01576       G4cout << particles[ip] << G4endl;
01577   }
01578 
01579   return;       // Buffer has been filled
01580 }

G4CascadParticle G4NucleiModel::initializeCascad ( G4InuclElementaryParticle particle  ) 

Definition at line 1164 of file G4NucleiModel.cc.

References G4cout, G4InuclSpecialFunctions::generateWithFixedTheta(), and G4InuclSpecialFunctions::inuclRndm().

Referenced by G4IntraNucleiCascader::setupCascade().

01164                                                                    {
01165   if (verboseLevel > 1) {
01166     G4cout << " >>> G4NucleiModel::initializeCascad(particle)" << G4endl;
01167   }
01168 
01169   const G4double large = 1000.0;
01170 
01171   // FIXME:  Previous version generated random sin(theta), then used -cos(theta)
01172   //         Using generateWithRandomAngles changes result!
01173   // G4ThreeVector pos = generateWithRandomAngles(nuclei_radius).vect();
01174   G4double costh = std::sqrt(1.0 - inuclRndm());
01175   G4ThreeVector pos = generateWithFixedTheta(-costh, nuclei_radius);
01176 
01177   G4CascadParticle cpart(*particle, pos, number_of_zones, large, 0);
01178 
01179   if (verboseLevel > 2) G4cout << cpart << G4endl;
01180 
01181   return cpart;
01182 }

G4bool G4NucleiModel::isProjectile ( const G4CascadParticle cparticle  )  const

Definition at line 1071 of file G4NucleiModel.cc.

References G4cout, G4CascadParticle::getCurrentPath(), G4CascadParticle::getCurrentZone(), G4CascadParticle::getNumberOfReflections(), and G4CascadParticle::movingInsideNuclei().

01071                                                                           {
01072   if (verboseLevel > 2) {
01073     G4cout << " isProjectile(cparticle): zone "
01074            << cparticle.getCurrentZone() << " of " << number_of_zones
01075            << " path " << cparticle.getCurrentPath()
01076            << " movingInside " << cparticle.movingInsideNuclei()
01077            << " nReflections " << cparticle.getNumberOfReflections()
01078            << G4endl;
01079   }
01080 
01081   return (cparticle.getCurrentZone() == number_of_zones-1 &&    // At surface
01082           cparticle.getCurrentPath() == 1000. &&                // Input primary
01083           cparticle.getNumberOfReflections() <= 0 &&            // first pass
01084           (cparticle.movingInsideNuclei()||number_of_zones==1)  // inbound
01085           );
01086 }

void G4NucleiModel::printModel (  )  const

Definition at line 540 of file G4NucleiModel.cc.

References G4cout, getDensity(), getFermiMomentum(), and getPotential().

Referenced by generateModel().

00540                                      {
00541   if (verboseLevel > 1) {
00542     G4cout << " >>> G4NucleiModel::printModel" << G4endl;
00543   }
00544 
00545   G4cout << " nuclei model for A " << A << " Z " << Z << G4endl
00546          << " proton binding energy " << binding_energies[0]
00547          << " neutron binding energy " << binding_energies[1] << G4endl
00548          << " Nuclei radius " << nuclei_radius << " volume " << nuclei_volume
00549          << " number of zones " << number_of_zones << G4endl;
00550 
00551   for (G4int i = 0; i < number_of_zones; i++)
00552     G4cout << " zone " << i+1 << " radius " << zone_radii[i] 
00553            << " volume " << zone_volumes[i] << G4endl
00554            << " protons: density " << getDensity(1,i) << " PF " << 
00555       getFermiMomentum(1,i) << " VP " << getPotential(1,i) << G4endl
00556            << " neutrons: density " << getDensity(2,i) << " PF " << 
00557       getFermiMomentum(2,i) << " VP " << getPotential(2,i) << G4endl
00558            << " pions: VP " << getPotential(3,i) << G4endl;
00559 }

void G4NucleiModel::reset ( G4int  nHitNeutrons = 0,
G4int  nHitProtons = 0,
const std::vector< G4ThreeVector > *  hitPoints = 0 
)

Definition at line 224 of file G4NucleiModel.cc.

Referenced by G4IntraNucleiCascader::copyWoundedNucleus(), generateModel(), and G4IntraNucleiCascader::newCascade().

00225                                                                      {
00226   neutronNumberCurrent = neutronNumber - nHitNeutrons;
00227   protonNumberCurrent  = protonNumber - nHitProtons;
00228   
00229   // zero or copy collision point array for trailing effect
00230   if (!hitPoints || !hitPoints->empty()) collisionPts.clear();
00231   else collisionPts = *hitPoints;
00232 }

void G4NucleiModel::setVerboseLevel ( G4int  verbose  )  [inline]

Definition at line 90 of file G4NucleiModel.hh.

Referenced by G4IntraNucleiCascader::setVerboseLevel().

00090 { verboseLevel = verbose; }

G4bool G4NucleiModel::stillInside ( const G4CascadParticle cparticle  )  [inline]

Definition at line 145 of file G4NucleiModel.hh.

References G4CascadParticle::getCurrentZone().

Referenced by G4IntraNucleiCascader::generateCascade().

00145                                                         {
00146     return cparticle.getCurrentZone() < number_of_zones;
00147   }

G4double G4NucleiModel::totalCrossSection ( G4double  ke,
G4int  rtype 
) const

Definition at line 1688 of file G4NucleiModel.cc.

References G4cerr, G4CascadeChannel::getCrossSection(), and G4CascadeChannelTables::GetTable().

01689 {
01690   // All scattering cross-sections are available from tables
01691   const G4CascadeChannel* xsecTable = G4CascadeChannelTables::GetTable(rtype);
01692   if (!xsecTable) {
01693     G4cerr << " unknown collison type = " << rtype << G4endl;
01694     return 0.;
01695   }
01696 
01697   return (crossSectionUnits * xsecTable->getCrossSection(ke));
01698 }

G4bool G4NucleiModel::worthToPropagate ( const G4CascadParticle cparticle  )  const

Definition at line 1088 of file G4NucleiModel.cc.

References G4cout, G4CascadParticle::getCurrentZone(), getFermiKinetic(), G4InuclParticle::getKineticEnergy(), G4CascadParticle::getParticle(), G4InuclElementaryParticle::nucleon(), G4CascadParticle::reflectedNow(), and G4InuclElementaryParticle::type().

Referenced by G4IntraNucleiCascader::generateCascade().

01088                                                                               {
01089   if (verboseLevel > 1) {
01090     G4cout << " >>> G4NucleiModel::worthToPropagate" << G4endl;
01091   }
01092 
01093   const G4double ekin_scale = 2.0;
01094 
01095   G4bool worth = true;
01096 
01097   if (cparticle.reflectedNow()) {       // Just reflected -- keep going?
01098     G4int zone = cparticle.getCurrentZone();
01099     G4int ip = cparticle.getParticle().type();
01100 
01101     // NOTE:  Temporarily backing out use of potential for non-nucleons
01102     G4double ekin_cut = (cparticle.getParticle().nucleon()) ?
01103       getFermiKinetic(ip, zone) : 0.; //*** getPotential(ip, zone);
01104 
01105     worth = cparticle.getParticle().getKineticEnergy()/ekin_scale > ekin_cut;
01106 
01107     if (verboseLevel > 3) {
01108       G4cout << " type=" << ip
01109              << " ekin=" << cparticle.getParticle().getKineticEnergy()
01110              << " potential=" << ekin_cut
01111              << " : worth? " << worth << G4endl;
01112     }
01113   }
01114 
01115   return worth;
01116 }


The documentation for this class was generated from the following files:
Generated on Mon May 27 17:52:45 2013 for Geant4 by  doxygen 1.4.7