// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * * // * Parts of this code which have been developed by QinetiQ Ltd * // * under contract to the European Space Agency (ESA) are the * // * intellectual property of ESA. Rights to use, copy, modify and * // * redistribute this software for general public use are granted * // * in compliance with any licensing, distribution and development * // * policy adopted by the Geant4 Collaboration. This code has been * // * written by QinetiQ Ltd for the European Space Agency, under ESA * // * contract 17191/03/NL/LvH (Aurora Programme). * // * * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // // MODULE: G4WilsonAbrasionModel.cc // // Version: 1.0 // Date: 08/12/2009 // Author: P R Truscott // Organisation: QinetiQ Ltd, UK // Customer: ESA/ESTEC, NOORDWIJK // Contract: 17191/03/NL/LvH // // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // // CHANGE HISTORY // -------------- // // 6 October 2003, P R Truscott, QinetiQ Ltd, UK // Created. // // 15 March 2004, P R Truscott, QinetiQ Ltd, UK // Beta release // // 18 January 2005, M H Mendenhall, Vanderbilt University, US // Pointers to theAbrasionGeometry and products generated by the deexcitation // handler deleted to prevent memory leaks. Also particle change of projectile // fragment previously not properly defined. // // 08 December 2009, P R Truscott, QinetiQ Ltd, Ltd // ver 1.0 // There was originally a possibility of the minimum impact parameter AFTER // considering Couloumb repulsion, rm, being too large. Now if: // rm >= fradius * (rP + rT) // where fradius is currently 0.99, then it is assumed the primary track is // unchanged. Additional conditions to escape from while-loop over impact // parameter: if the loop counter evtcnt reaches 1000, the primary track is // continued. // Additional clauses have been included in // G4WilsonAbrasionModel::GetNucleonInducedExcitation // Previously it was possible to get sqrt of negative number as Wilson // algorithm not properly defined if either: // rT > rP && rsq < rTsq - rPsq) or (rP > rT && rsq < rPsq - rTsq) // // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /////////////////////////////////////////////////////////////////////////////// #include "G4WilsonAbrasionModel.hh" #include "G4WilsonRadius.hh" #include "G4NuclearAbrasionGeometry.hh" #include "G4WilsonAblationModel.hh" #include "G4ExcitationHandler.hh" #include "G4Evaporation.hh" #include "G4FermiBreakUp.hh" #include "G4StatMF.hh" #include "G4ParticleDefinition.hh" #include "G4DynamicParticle.hh" #include "Randomize.hh" #include "G4Fragment.hh" #include "G4ReactionProductVector.hh" #include "G4LorentzVector.hh" #include "G4ParticleMomentum.hh" #include "G4Poisson.hh" #include "G4ParticleTable.hh" #include "G4IonTable.hh" #include "globals.hh" G4WilsonAbrasionModel::G4WilsonAbrasionModel (G4bool useAblation1) :G4HadronicInteraction("G4WilsonAbrasion") { // Send message to stdout to advise that the G4Abrasion model is being used. PrintWelcomeMessage(); // Set the default verbose level to 0 - no output. verboseLevel = 0; useAblation = useAblation1; // No de-excitation handler has been supplied - define the default handler. theExcitationHandler = new G4ExcitationHandler; theExcitationHandlerx = new G4ExcitationHandler; if (useAblation) { theAblation = new G4WilsonAblationModel; theAblation->SetVerboseLevel(verboseLevel); theExcitationHandler->SetEvaporation(theAblation); theExcitationHandlerx->SetEvaporation(theAblation); } else { theAblation = NULL; G4Evaporation * theEvaporation = new G4Evaporation; G4FermiBreakUp * theFermiBreakUp = new G4FermiBreakUp; G4StatMF * theMF = new G4StatMF; theExcitationHandler->SetEvaporation(theEvaporation); theExcitationHandler->SetFermiModel(theFermiBreakUp); theExcitationHandler->SetMultiFragmentation(theMF); theExcitationHandler->SetMaxAandZForFermiBreakUp(12, 6); theExcitationHandler->SetMinEForMultiFrag(5.0*MeV); theEvaporation = new G4Evaporation; theFermiBreakUp = new G4FermiBreakUp; theExcitationHandlerx->SetEvaporation(theEvaporation); theExcitationHandlerx->SetFermiModel(theFermiBreakUp); theExcitationHandlerx->SetMaxAandZForFermiBreakUp(12, 6); } // Set the minimum and maximum range for the model (despite nomanclature, // this is in energy per nucleon number). SetMinEnergy(70.0*MeV); SetMaxEnergy(10.1*GeV); isBlocked = false; // npK, when mutiplied by the nuclear Fermi momentum, determines the range of // momentum over which the secondary nucleon momentum is sampled. r0sq = 0.0; npK = 5.0; B = 10.0 * MeV; third = 1.0 / 3.0; fradius = 0.99; conserveEnergy = false; conserveMomentum = true; } G4WilsonAbrasionModel::G4WilsonAbrasionModel (G4ExcitationHandler *aExcitationHandler) { // // // Send message to stdout to advise that the G4Abrasion model is being used. // PrintWelcomeMessage(); // // // Set the default verbose level to 0 - no output. // verboseLevel = 0; // // // The user is able to provide the excitation handler as well as an argument // which is provided in this instantiation is used to determine // whether the spectators of the interaction are free following the abrasion. // theExcitationHandler = aExcitationHandler; theExcitationHandlerx = new G4ExcitationHandler; G4Evaporation * theEvaporation = new G4Evaporation; G4FermiBreakUp * theFermiBreakUp = new G4FermiBreakUp; theExcitationHandlerx->SetEvaporation(theEvaporation); theExcitationHandlerx->SetFermiModel(theFermiBreakUp); theExcitationHandlerx->SetMaxAandZForFermiBreakUp(12, 6); // // // Set the minimum and maximum range for the model (despite nomanclature, this // is in energy per nucleon number). // SetMinEnergy(70.0*MeV); SetMaxEnergy(10.1*GeV); isBlocked = false; // // // npK, when mutiplied by the nuclear Fermi momentum, determines the range of // momentum over which the secondary nucleon momentum is sampled. // npK = 5.0; B = 10.0 * MeV; third = 1.0 / 3.0; fradius = 0.99; conserveEnergy = false; conserveMomentum = true; } //////////////////////////////////////////////////////////////////////////////// // G4WilsonAbrasionModel::~G4WilsonAbrasionModel () { // // // The destructor doesn't have to do a great deal! // if (theExcitationHandler) delete theExcitationHandler; if (theExcitationHandlerx) delete theExcitationHandlerx; if (useAblation) delete theAblation; // delete theExcitationHandler; // delete theExcitationHandlerx; } //////////////////////////////////////////////////////////////////////////////// // G4HadFinalState *G4WilsonAbrasionModel::ApplyYourself ( const G4HadProjectile &theTrack, G4Nucleus &theTarget) { // // // The secondaries will be returned in G4HadFinalState &theParticleChange - // initialise this. The original track will always be discontinued and // secondaries followed. // theParticleChange.Clear(); theParticleChange.SetStatusChange(stopAndKill); // // // Get relevant information about the projectile and target (A, Z, energy/nuc, // momentum, etc). // const G4ParticleDefinition *definitionP = theTrack.GetDefinition(); const G4double AP = definitionP->GetBaryonNumber(); const G4double ZP = definitionP->GetPDGCharge(); G4LorentzVector pP = theTrack.Get4Momentum(); G4double E = theTrack.GetKineticEnergy()/AP; G4double AT = theTarget.GetN(); G4double ZT = theTarget.GetZ(); G4double TotalEPre = theTrack.GetTotalEnergy() + theTarget.AtomicMass(AT, ZT) + theTarget.GetEnergyDeposit(); G4double TotalEPost = 0.0; // // // Determine the radii of the projectile and target nuclei. // G4WilsonRadius aR; G4double rP = aR.GetWilsonRadius(AP); G4double rT = aR.GetWilsonRadius(AT); G4double rPsq = rP * rP; G4double rTsq = rT * rT; if (verboseLevel >= 2) { G4cout <<"########################################" <<"########################################" <1, i.e. an interaction MUST occur. // while (Dabr == 0) { // Added by MHM 20050119 to fix leaking memory on second pass through this loop if (theAbrasionGeometry) { delete theAbrasionGeometry; theAbrasionGeometry = NULL; } // // // Sample the impact parameter. For the moment, this class takes account of // electrostatic effects on the impact parameter, but (like HZETRN AND NUCFRG2) // does not make any correction for the effects of nuclear-nuclear repulsion. // G4double rPT = rP + rT; G4double rPTsq = rPT * rPT; // // // This is a "catch" to make sure we don't go into an infinite loop because the // energy is too low to overcome nuclear repulsion. PRT 20091023. If the // value of rm < fradius * rPT then we're unlikely to sample a small enough // impact parameter (energy of incident particle is too low). Return primary // and don't complete nuclear interaction analysis. // if (rm >= fradius * rPT) { theParticleChange.SetStatusChange(isAlive); theParticleChange.SetEnergyChange(theTrack.GetKineticEnergy()); theParticleChange.SetMomentumChange(theTrack.Get4Momentum().vect().unit()); if (verboseLevel >= 2) { G4cout <<"Particle energy too low to overcome repulsion." < rPT && ++evtcnt < 1000) { G4double bsq = rPTsq * G4UniformRand(); r = (rm + std::sqrt(rm*rm + 4.0*bsq)) / 2.0; } // // // We've tried to sample this 1000 times, but failed. Assume nuclei do not // collide. // if (evtcnt >= 1000) { theParticleChange.SetStatusChange(isAlive); theParticleChange.SetEnergyChange(theTrack.GetKineticEnergy()); theParticleChange.SetMomentumChange(theTrack.Get4Momentum().vect().unit()); if (verboseLevel >= 2) { G4cout <<"Particle energy too low to overcome repulsion." < rP) { G4double x = (rPsq + rsq - rTsq) / 2.0 / r; if (x > 0.0) CT = 2.0 * std::sqrt(rTsq - x*x); else CT = 2.0 * std::sqrt(rTsq - rsq); } else { G4double x = (rTsq + rsq - rPsq) / 2.0 / r; if (x > 0.0) CT = 2.0 * std::sqrt(rTsq - x*x); else CT = 2.0 * rT; } // // // Determine the number of abraded nucleons. Note that the mean number of // abraded nucleons is used to sample the Poisson distribution. The Poisson // distribution is sampled only ten times with the current impact parameter, // and if it fails after this to find a case for which the number of abraded // nucleons >1, the impact parameter is re-sampled. // theAbrasionGeometry = new G4NuclearAbrasionGeometry(AP,AT,r); F = theAbrasionGeometry->F(); G4double lambda = 16.6*fermi / std::pow(E/MeV,0.26); G4double Mabr = F * AP * (1.0 - std::exp(-CT/lambda)); G4long n = 0; for (G4int i = 0; i<10; i++) { n = G4Poisson(Mabr); if (n > 0) { if (n>AP) Dabr = (G4int) AP; else Dabr = (G4int) n; break; } } } if (verboseLevel >= 2) { G4cout <GetParticle()->DumpInfo(); G4DynamicParticle *dyn = theParticleChange.GetSecondary(i)->GetParticle(); G4cout <<"New nucleon (P) " <GetDefinition()->GetParticleName() <<" : " <Get4Momentum() <GetParticle()->DumpInfo(); G4DynamicParticle *dyn = theParticleChange.GetSecondary(i)->GetParticle(); G4cout <<"New nucleon (T) " <GetDefinition()->GetParticleName() <<" : " <Get4Momentum() <GetZ() != fragmentP->GetA()) products = theExcitationHandler->BreakItUp(*fragmentP); else products = theExcitationHandlerx->BreakItUp(*fragmentP); delete fragmentP; fragmentP = NULL; G4ReactionProductVector::iterator iter; for (iter = products->begin(); iter != products->end(); ++iter) { G4DynamicParticle *secondary = new G4DynamicParticle((*iter)->GetDefinition(), (*iter)->GetTotalEnergy(), (*iter)->GetMomentum()); theParticleChange.AddSecondary (secondary); // Added MHM 20050118 G4String particleName = (*iter)->GetDefinition()->GetParticleName(); delete (*iter); // get rid of leftover particle def! // Added MHM 20050118 if (verboseLevel >= 2 && particleName.find("[",0) < particleName.size()) { G4cout <<"------------------------" <GetPDGMass(); G4double E = std::sqrt(p*p + nucleonMass*nucleonMass)-nucleonMass; dynamicNucleon = new G4DynamicParticle(typeNucleon,direction,E); theParticleChange.AddSecondary (dynamicNucleon); pabr += p*direction; } // // // Next determine the details of the nuclear prefragment .. that is if there // is one or more protons in the residue. (Note that the 1 eV in the total // energy is a safety factor to avoid any possibility of negative rest mass // energy.) // G4Fragment *fragment = NULL; if (Z-Zabr>=1.0) { G4double ionMass = G4ParticleTable::GetParticleTable()->GetIonTable()-> GetIonMass(G4lrint(Z-Zabr),G4lrint(A-Aabr)); G4double E = std::sqrt(pabr.mag2() + ionMass*ionMass); G4LorentzVector lorentzVector = G4LorentzVector(-pabr, E + 1.0*eV); fragment = new G4Fragment((G4int) (A-Aabr), (G4int) (Z-Zabr), lorentzVector); } return fragment; } //////////////////////////////////////////////////////////////////////////////// // G4double G4WilsonAbrasionModel::GetNucleonInducedExcitation (G4double rP, G4double rT, G4double r) { // // // Initialise variables. // G4double Cl = 0.0; G4double rPsq = rP * rP; G4double rTsq = rT * rT; G4double rsq = r * r; // // // Depending upon the impact parameter, a different form of the chord length is // is used. // if (r > rT) Cl = 2.0*std::sqrt(rPsq + 2.0*r*rT - rsq - rTsq); else Cl = 2.0*rP; // // // The next lines have been changed to include a "catch" to make sure if the // projectile and target are too close, Ct is set to twice rP or twice rT. // Otherwise the standard Wilson algorithm should work fine. // PRT 20091023. // G4double Ct = 0.0; if (rT > rP && rsq < rTsq - rPsq) Ct = 2.0 * rP; else if (rP > rT && rsq < rPsq - rTsq) Ct = 2.0 * rT; else { G4double bP = (rPsq+rsq-rTsq)/2.0/r; G4double x = rPsq - bP*bP; if (x < 0.0) { G4cerr <<"########################################" <<"########################################" < 1.5*fermi) Ex += 13.0 * Cl / fermi /3.0 * (Ct/fermi - 1.5); return Ex; } //////////////////////////////////////////////////////////////////////////////// // void G4WilsonAbrasionModel::SetUseAblation (G4bool useAblation1) { if (useAblation != useAblation1) { useAblation = useAblation1; delete theExcitationHandler; delete theExcitationHandlerx; theExcitationHandler = new G4ExcitationHandler; theExcitationHandlerx = new G4ExcitationHandler; if (useAblation) { theAblation = new G4WilsonAblationModel; theAblation->SetVerboseLevel(verboseLevel); theExcitationHandler->SetEvaporation(theAblation); theExcitationHandlerx->SetEvaporation(theAblation); } else { theAblation = NULL; G4Evaporation * theEvaporation = new G4Evaporation; G4FermiBreakUp * theFermiBreakUp = new G4FermiBreakUp; G4StatMF * theMF = new G4StatMF; theExcitationHandler->SetEvaporation(theEvaporation); theExcitationHandler->SetFermiModel(theFermiBreakUp); theExcitationHandler->SetMultiFragmentation(theMF); theExcitationHandler->SetMaxAandZForFermiBreakUp(12, 6); theExcitationHandler->SetMinEForMultiFrag(5.0*MeV); theEvaporation = new G4Evaporation; theFermiBreakUp = new G4FermiBreakUp; theExcitationHandlerx->SetEvaporation(theEvaporation); theExcitationHandlerx->SetFermiModel(theFermiBreakUp); theExcitationHandlerx->SetMaxAandZForFermiBreakUp(12, 6); } } return; } //////////////////////////////////////////////////////////////////////////////// // void G4WilsonAbrasionModel::PrintWelcomeMessage () { G4cout <