// // ******************************************************************** // * 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. * // * 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. * // ******************************************************************** // // $Id: G4GeneratorPrecompoundInterface.cc 92692 2015-09-14 07:06:19Z gcosmo $ // // ----------------------------------------------------------------------------- // GEANT 4 class file // // History: first implementation // HPW, 10DEC 98, the decay part originally written by Gunter Folger // in his FTF-test-program. // // M.Kelsey, 28 Jul 2011 -- Replace loop to decay input secondaries // with new utility class, simplify cleanup loops // ----------------------------------------------------------------------------- #include #include #include "G4GeneratorPrecompoundInterface.hh" #include "G4PhysicalConstants.hh" #include "G4SystemOfUnits.hh" #include "G4DynamicParticleVector.hh" #include "G4KineticTrackVector.hh" #include "G4Proton.hh" #include "G4Neutron.hh" #include "G4Deuteron.hh" #include "G4Triton.hh" #include "G4He3.hh" #include "G4Alpha.hh" #include "G4V3DNucleus.hh" #include "G4Nucleon.hh" #include "G4AntiProton.hh" #include "G4AntiNeutron.hh" #include "G4AntiDeuteron.hh" #include "G4AntiTriton.hh" #include "G4AntiHe3.hh" #include "G4AntiAlpha.hh" #include "G4FragmentVector.hh" #include "G4ReactionProduct.hh" #include "G4ReactionProductVector.hh" #include "G4PreCompoundModel.hh" #include "G4ExcitationHandler.hh" #include "G4DecayKineticTracks.hh" #include "G4HadronicInteractionRegistry.hh" //--------------------------------------------------------------------- #include "Randomize.hh" #include "G4Log.hh" //#define debugPrecoInt G4GeneratorPrecompoundInterface::G4GeneratorPrecompoundInterface(G4VPreCompoundModel* preModel) : CaptureThreshold(70*MeV) // Uzhi 1.05.2015 10 ->70 { proton = G4Proton::Proton(); neutron = G4Neutron::Neutron(); deuteron=G4Deuteron::Deuteron(); triton =G4Triton::Triton(); He3 =G4He3::He3(); He4 =G4Alpha::Alpha(); ANTIproton=G4AntiProton::AntiProton(); ANTIneutron=G4AntiNeutron::AntiNeutron(); ANTIdeuteron=G4AntiDeuteron::AntiDeuteron(); ANTItriton =G4AntiTriton::AntiTriton(); ANTIHe3 =G4AntiHe3::AntiHe3(); ANTIHe4 =G4AntiAlpha::AntiAlpha(); if(preModel) { SetDeExcitation(preModel); } else { G4HadronicInteraction* hadi = G4HadronicInteractionRegistry::Instance()->FindModel("PRECO"); G4VPreCompoundModel* pre = static_cast(hadi); if(!pre) { pre = new G4PreCompoundModel(); } SetDeExcitation(pre); } } G4GeneratorPrecompoundInterface::~G4GeneratorPrecompoundInterface() { } G4ReactionProductVector* G4GeneratorPrecompoundInterface:: Propagate(G4KineticTrackVector* theSecondaries, G4V3DNucleus* theNucleus) { #ifdef debugPrecoInt G4cout<GetMassNumber()<<" "<GetCharge()<size()<size()<GetMassNumber(); G4int aZ=theNucleus->GetCharge(); // G4double TargetNucleusMass = G4NucleiProperties::GetNuclearMass(anA, aZ); G4int numberOfEx = 0; G4int numberOfCh = 0; G4int numberOfHoles = 0; G4double R = theNucleus->GetNuclearRadius(); G4LorentzVector captured4Momentum(0.,0.,0.,0.); G4LorentzVector Residual4Momentum(0.,0.,0.,0.); // TargetNucleusMass is not need at the moment G4LorentzVector Secondary4Momentum(0.,0.,0.,0.); // loop over secondaries G4KineticTrackVector::iterator iter; for(iter=theSecondaries->begin(); iter !=theSecondaries->end(); ++iter) { const G4ParticleDefinition* part = (*iter)->GetDefinition(); G4double e = (*iter)->Get4Momentum().e(); G4double mass = (*iter)->Get4Momentum().mag(); G4ThreeVector mom = (*iter)->Get4Momentum().vect(); if((part != proton && part != neutron) || // Uzhi 2.05.2015 (e > mass + CaptureThreshold) || ((*iter)->GetPosition().mag() > R)) { G4ReactionProduct * theNew = new G4ReactionProduct(part); theNew->SetMomentum(mom); theNew->SetTotalEnergy(e); theTotalResult->push_back(theNew); Secondary4Momentum += (*iter)->Get4Momentum(); // Uzhi 29 April #ifdef debugPrecoInt G4cout<<"Secondary 4Mom "<GetParticleName()<<" "<<(*iter)->Get4Momentum()<<" " <<(*iter)->Get4Momentum().mag()< -CaptureThreshold*G4Log( G4UniformRand()) ) { // Added by Uzhi 2.05.2015 G4ReactionProduct * theNew = new G4ReactionProduct(part); theNew->SetMomentum(mom); theNew->SetTotalEnergy(e); theTotalResult->push_back(theNew); Secondary4Momentum += (*iter)->Get4Momentum(); // Uzhi 29 April #ifdef debugPrecoInt G4cout<<"Secondary 4Mom "<GetParticleName()<<" "<<(*iter)->Get4Momentum()<<" " <<(*iter)->Get4Momentum().mag()<GetPDGCharge()/eplus + 0.1); aZ += Z; numberOfCh += Z; captured4Momentum += (*iter)->Get4Momentum(); #ifdef debugPrecoInt G4cout<<"Captured 4Mom "<GetParticleName()<<(*iter)->Get4Momentum()<StartLoop() ? theNucleus->GetNextNucleon() : 0; while(theCurrentNucleon) /* Loop checking, 31.08.2015, G.Folger */ { if(theCurrentNucleon->AreYouHit()) { ++numberOfHoles; ++numberOfEx; --anA; aZ -= G4int(theCurrentNucleon->GetDefinition()->GetPDGCharge()/eplus + 0.1); Residual4Momentum -= theCurrentNucleon->Get4Momentum(); } theCurrentNucleon = theNucleus->GetNextNucleon(); } #ifdef debugPrecoInt G4cout<StartLoop() ? theNucleus->GetNextNucleon() : 0; while(theCurrentNucleon) /* Loop checking, 31.08.2015, G.Folger */ { if(theCurrentNucleon->AreYouHit()) { if(theCurrentNucleon->Get4Momentum().mag() < theCurrentNucleon->GetDefinition()->GetPDGMass()) QGSM=true; } theCurrentNucleon = theNucleus->GetNextNucleon(); } #ifdef debugPrecoInt if(!QGSM){ G4cout<= aZ) { if(!QGSM) { // FTF model was used G4double fMass = G4NucleiProperties::GetNuclearMass(anA, aZ); // G4LorentzVector exciton4Momentum = Residual4Momentum + captured4Momentum; exciton4Momentum = Residual4Momentum + captured4Momentum; //exciton4Momentum.setE(std::sqrt(exciton4Momentum.vect().mag2()+sqr(fMass))); G4double ActualMass = exciton4Momentum.mag(); if(ActualMass <= fMass ) { //E*<=0, Uzhi 5.05.2015 exciton4Momentum.setE(std::sqrt(exciton4Momentum.vect().mag2()+sqr(fMass))); // Uzhi 13.05.2015 } #ifdef debugPrecoInt G4double exEnergy = 0.0; if(ActualMass <= fMass ) {exEnergy = 0.;} // Uzhi 5.05.2015 else {exEnergy = ActualMass - fMass;} G4cout<<"Ground state residual Mass "<GetMassNumber(), theNucleus->GetCharge()); exciton4Momentum = GetPrimaryProjectile()->Get4Momentum() + G4LorentzVector(0.,0.,0.,InitialTargetMass) -Secondary4Momentum; G4double fMass = G4NucleiProperties::GetNuclearMass(anA, aZ); G4double ActualMass = exciton4Momentum.mag(); #ifdef debugPrecoInt G4cout<>Uzhi; #endif } } // Need to de-excite the remnant nucleus only if excitation energy > 0. G4Fragment anInitialState(anA, aZ, exciton4Momentum); anInitialState.SetNumberOfParticles(numberOfEx-numberOfHoles); anInitialState.SetNumberOfCharged(numberOfCh); anInitialState.SetNumberOfHoles(numberOfHoles); G4ReactionProductVector * aPrecoResult = theDeExcitation->DeExcite(anInitialState); // fill pre-compound part into the result, and return #ifdef debugPrecoInt G4cout<<"Target fragment number "<size()<size(); ++ll) { theTotalResult->push_back(aPrecoResult->operator[](ll)); #ifdef debugPrecoInt G4cout<<"Fragment "<operator[](ll)->GetDefinition()->GetParticleName()<<" " <operator[](ll)->GetMomentum()<<" " <operator[](ll)->GetTotalEnergy()<<" " <operator[](ll)->GetDefinition()->GetPDGMass()<GetMassNumber()<<" " <GetCharge()<GetMassNumber()<<" " <GetCharge()<size()<Get4Momentum()<<" " <Get4Momentum().mag()<GetMassNumber(); G4int aZ=theNucleus->GetCharge(); G4int numberOfEx = 0; G4int numberOfCh = 0; G4int numberOfHoles = 0; G4double exEnergy = 0.0; G4double R = theNucleus->GetNuclearRadius(); G4LorentzVector Target4Momentum(0.,0.,0.,0.); // loop over wounded target nucleus G4Nucleon * theCurrentNucleon = theNucleus->StartLoop() ? theNucleus->GetNextNucleon() : 0; while(theCurrentNucleon) /* Loop checking, 31.08.2015, G.Folger */ { if(theCurrentNucleon->AreYouHit()) { ++numberOfHoles; ++numberOfEx; --anA; aZ -= G4int(theCurrentNucleon->GetDefinition()->GetPDGCharge()/ eplus + 0.1); exEnergy += theCurrentNucleon->GetBindingEnergy(); Target4Momentum -=theCurrentNucleon->Get4Momentum(); } theCurrentNucleon = theNucleus->GetNextNucleon(); } #ifdef debugPrecoInt G4cout<<"Residual Target A Z E* 4mom "<GetDefinition()->GetBaryonNumber() < -1; G4ThreeVector bst = GetPrimaryProjectile()->Get4Momentum().boostVector(); G4int anAb=theProjectileNucleus->GetMassNumber(); G4int aZb=theProjectileNucleus->GetCharge(); G4int numberOfExB = 0; G4int numberOfChB = 0; G4int numberOfHolesB = 0; G4double exEnergyB = 0.0; G4double Rb = theProjectileNucleus->GetNuclearRadius(); G4LorentzVector Projectile4Momentum(0.,0.,0.,0.); // loop over wounded projectile nucleus theCurrentNucleon = theProjectileNucleus->StartLoop() ? theProjectileNucleus->GetNextNucleon() : 0; while(theCurrentNucleon) /* Loop checking, 31.08.2015, G.Folger */ { if(theCurrentNucleon->AreYouHit()) { ++numberOfHolesB; ++numberOfExB; --anAb; if(!ProjectileIsAntiNucleus) { aZb -= G4int(theCurrentNucleon->GetDefinition()->GetPDGCharge()/ eplus + 0.1); } else { aZb += G4int(theCurrentNucleon->GetDefinition()->GetPDGCharge()/ eplus - 0.1); } exEnergyB += theCurrentNucleon->GetBindingEnergy(); Projectile4Momentum -=theCurrentNucleon->Get4Momentum(); } theCurrentNucleon = theProjectileNucleus->GetNextNucleon(); } G4bool ExistTargetRemnant = G4double (numberOfHoles) < 0.3* G4double (numberOfHoles + anA); G4bool ExistProjectileRemnant= G4double (numberOfHolesB) < 0.3*G4double (numberOfHolesB + anAb); #ifdef debugPrecoInt G4cout<<"Projectile residual A Z E* 4mom "<size()<begin(); iter !=theSecondaries->end(); ++iter) { const G4ParticleDefinition* part = (*iter)->GetDefinition(); G4LorentzVector aTrack4Momentum=(*iter)->Get4Momentum(); if( part != proton && part != neutron && (part != ANTIproton && ProjectileIsAntiNucleus) && (part != ANTIneutron && ProjectileIsAntiNucleus) ) { G4ReactionProduct * theNew = new G4ReactionProduct(part); theNew->SetMomentum(aTrack4Momentum.vect()); theNew->SetTotalEnergy(aTrack4Momentum.e()); theTotalResult->push_back(theNew); #ifdef debugPrecoInt SecondrNum++; secondary4Momemtum += (*iter)->Get4Momentum(); G4cout<<"Secondary "<GetDefinition()->GetParticleName()<<" " <GetMomentum()<<" "<GetTotalEnergy()< (aTrack4Momentum + Target4Momentum).mag() - aTrack4Momentum.mag() - Target4Momentum.mag()) && ((*iter)->GetPosition().mag() < R); } // --------------------------- G4LorentzVector Position((*iter)->GetPosition(), (*iter)->GetFormationTime()); Position.boost(bst); G4bool CanBeCapturedByProjectile = false; if( !ProjectileIsAntiNucleus && ( part == proton || part == neutron)) { CanBeCapturedByProjectile = ExistProjectileRemnant && (-CaptureThreshold*G4Log( G4UniformRand()) > (aTrack4Momentum + Projectile4Momentum).mag() - aTrack4Momentum.mag() - Projectile4Momentum.mag()) && (Position.vect().mag() < Rb); } if( ProjectileIsAntiNucleus && ( part == ANTIproton || part == ANTIneutron)) { CanBeCapturedByProjectile = ExistProjectileRemnant && (-CaptureThreshold*G4Log( G4UniformRand()) > (aTrack4Momentum + Projectile4Momentum).mag() - aTrack4Momentum.mag() - Projectile4Momentum.mag()) && (Position.vect().mag() < Rb); } if(CanBeCapturedByTarget && CanBeCapturedByProjectile) { if(G4UniformRand() < 0.5) { CanBeCapturedByTarget = true; CanBeCapturedByProjectile = false;} else { CanBeCapturedByTarget = false; CanBeCapturedByProjectile = true;} } if(CanBeCapturedByTarget) { // within the target nucleus, neutron or proton // now calculate A, Z of the fragment, momentum, // number of exciton states #ifdef debugPrecoInt G4cout<<"Track is CapturedByTarget "<<" "<GetParticleName()<<" " <GetPDGCharge()/eplus + 0.1); aZ += Z; numberOfCh += Z; Target4Momentum +=aTrack4Momentum; delete (*iter); } else if(CanBeCapturedByProjectile) { // within the projectile nucleus, neutron or proton // now calculate A, Z of the fragment, momentum, // number of exciton states #ifdef debugPrecoInt G4cout<<"Track is CapturedByProjectile"<<" "<GetParticleName()<<" " <GetPDGCharge()/eplus + 0.1); if( ProjectileIsAntiNucleus ) Z=-Z; aZb += Z; numberOfChB += Z; Projectile4Momentum +=aTrack4Momentum; delete (*iter); } else { // the track is not captured G4ReactionProduct * theNew = new G4ReactionProduct(part); theNew->SetMomentum(aTrack4Momentum.vect()); theNew->SetTotalEnergy(aTrack4Momentum.e()); theTotalResult->push_back(theNew); #ifdef debugPrecoInt SecondrNum++; secondary4Momemtum += (*iter)->Get4Momentum(); /* G4cout<<"Secondary "<GetDefinition()->GetParticleName()<<" " <GetMassNumber()) && (exEnergy <= 0.)) {Target4Momentum.setE(fMass);} G4double RemnMass=Target4Momentum.mag(); if(RemnMass < fMass) { RemnMass=fMass + exEnergy; Target4Momentum.setE(std::sqrt(Target4Momentum.vect().mag2() + RemnMass*RemnMass)); } else { exEnergy=RemnMass-fMass;} if( exEnergy < 0.) exEnergy=0.; // Need to de-excite the remnant nucleus G4Fragment anInitialState(anA, aZ, Target4Momentum); anInitialState.SetNumberOfParticles(numberOfEx-numberOfHoles); anInitialState.SetNumberOfCharged(numberOfCh); anInitialState.SetNumberOfHoles(numberOfHoles); G4ReactionProductVector * aPrecoResult = theDeExcitation->DeExcite(anInitialState); #ifdef debugPrecoInt G4cout<<"Target fragment number "<size()<size(); ++ll) { theTotalResult->push_back(aPrecoResult->operator[](ll)); #ifdef debugPrecoInt G4cout<<"Target fragment "<operator[](ll)->GetDefinition()->GetParticleName()<<" " <operator[](ll)->GetMomentum()<<" " <operator[](ll)->GetTotalEnergy()<<" " <operator[](ll)->GetMass()<GetMassNumber())&& (exEnergyB <= 0.)) {Projectile4Momentum = GetPrimaryProjectile()->Get4Momentum();} #ifdef debugPrecoInt G4cout<<"Final projectile residual A Z E* Pmom Pmag2 "<DeExcite(anInitialState); #ifdef debugPrecoInt G4cout<<"Projectile fragment number "<size()<size(); ++ll) { G4LorentzVector tmp=G4LorentzVector(aPrecoResult->operator[](ll)->GetMomentum(), // Uzhi 2015 aPrecoResult->operator[](ll)->GetTotalEnergy());// Uzhi 2015 tmp.boost(-bstToCM); // Transformation to the system of original remnant // Uzhi 2015 aPrecoResult->operator[](ll)->SetMomentum(tmp.vect()); // Uzhi 2015 aPrecoResult->operator[](ll)->SetTotalEnergy(tmp.e()); // Uzhi 2015 if(ProjectileIsAntiNucleus) { const G4ParticleDefinition * aFragment=aPrecoResult->operator[](ll)->GetDefinition(); const G4ParticleDefinition * LastFragment=aFragment; if (aFragment == proton) {LastFragment=G4AntiProton::AntiProtonDefinition();} else if(aFragment == neutron) {LastFragment=G4AntiNeutron::AntiNeutronDefinition();} else if(aFragment == deuteron){LastFragment=G4AntiDeuteron::AntiDeuteronDefinition();} else if(aFragment == triton) {LastFragment=G4AntiTriton::AntiTritonDefinition();} else if(aFragment == He3) {LastFragment=G4AntiHe3::AntiHe3Definition();} else if(aFragment == He4) {LastFragment=G4AntiAlpha::AntiAlphaDefinition();} else {} aPrecoResult->operator[](ll)->SetDefinitionAndUpdateE(LastFragment); } #ifdef debugPrecoInt G4cout<<"Projectile fragment "<operator[](ll)->GetDefinition()->GetParticleName()<<" " <operator[](ll)->GetMomentum()<<" " <operator[](ll)->GetTotalEnergy()<<" " <operator[](ll)->GetMass()<push_back(aPrecoResult->operator[](ll)); } delete aPrecoResult; } return theTotalResult; }