Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4ChargeExchange Class Reference

#include <G4ChargeExchange.hh>

Inheritance diagram for G4ChargeExchange:

Public Member Functions

 G4ChargeExchange (G4ChargeExchangeXS *)
 ~G4ChargeExchange () override
 G4ChargeExchange (const G4ChargeExchange &right)=delete
const G4ChargeExchangeoperator= (const G4ChargeExchange &right)=delete
G4bool operator== (const G4ChargeExchange &right) const =delete
G4bool operator!= (const G4ChargeExchange &right) const =delete
G4HadFinalStateApplyYourself (const G4HadProjectile &aTrack, G4Nucleus &targetNucleus) override
G4double SampleT (const G4ParticleDefinition *theSec, const G4int A, const G4double tmax) const
Public Member Functions inherited from G4HadronicInteraction
 G4HadronicInteraction (const G4String &modelName="HadronicModel")
virtual ~G4HadronicInteraction ()
virtual G4double SampleInvariantT (const G4ParticleDefinition *p, G4double plab, G4int Z, G4int A)
virtual G4bool IsApplicable (const G4HadProjectile &aTrack, G4Nucleus &targetNucleus)
G4double GetMinEnergy () const
G4double GetMinEnergy (const G4Material *aMaterial, const G4Element *anElement) const
void SetMinEnergy (G4double anEnergy)
void SetMinEnergy (G4double anEnergy, const G4Element *anElement)
void SetMinEnergy (G4double anEnergy, const G4Material *aMaterial)
G4double GetMaxEnergy () const
G4double GetMaxEnergy (const G4Material *aMaterial, const G4Element *anElement) const
void SetMaxEnergy (const G4double anEnergy)
void SetMaxEnergy (G4double anEnergy, const G4Element *anElement)
void SetMaxEnergy (G4double anEnergy, const G4Material *aMaterial)
G4int GetVerboseLevel () const
void SetVerboseLevel (G4int value)
const G4StringGetModelName () const
void DeActivateFor (const G4Material *aMaterial)
void ActivateFor (const G4Material *aMaterial)
void DeActivateFor (const G4Element *anElement)
void ActivateFor (const G4Element *anElement)
G4bool IsBlocked (const G4Material *aMaterial) const
G4bool IsBlocked (const G4Element *anElement) const
void SetRecoilEnergyThreshold (G4double val)
G4double GetRecoilEnergyThreshold () const
virtual const std::pair< G4double, G4doubleGetFatalEnergyCheckLevels () const
virtual std::pair< G4double, G4doubleGetEnergyMomentumCheckLevels () const
void SetEnergyMomentumCheckLevels (G4double relativeLevel, G4double absoluteLevel)
virtual void ModelDescription (std::ostream &outFile) const
virtual void BuildPhysicsTable (const G4ParticleDefinition &)
virtual void InitialiseModel ()
 G4HadronicInteraction (const G4HadronicInteraction &right)=delete
const G4HadronicInteractionoperator= (const G4HadronicInteraction &right)=delete
G4bool operator== (const G4HadronicInteraction &right) const =delete
G4bool operator!= (const G4HadronicInteraction &right) const =delete

Additional Inherited Members

Protected Member Functions inherited from G4HadronicInteraction
void SetModelName (const G4String &nam)
G4bool IsBlocked () const
void Block ()
Protected Attributes inherited from G4HadronicInteraction
G4HadFinalState theParticleChange
G4int verboseLevel
G4double theMinEnergy
G4double theMaxEnergy
G4bool isBlocked

Detailed Description

Definition at line 51 of file G4ChargeExchange.hh.

Constructor & Destructor Documentation

◆ G4ChargeExchange() [1/2]

G4ChargeExchange::G4ChargeExchange ( G4ChargeExchangeXS * ptr)
explicit

Definition at line 65 of file G4ChargeExchange.cc.

66 : G4HadronicInteraction("ChargeExchange"),
67 fXSection(ptr), fXSWeightFactor(1.0)
68{
69 lowEnergyLimit = 1.*CLHEP::MeV;
70 secID = G4PhysicsModelCatalog::GetModelID( "model_ChargeExchange" );
72 fHandler = new G4ExcitationHandler();
73 if (nullptr != fXSection) {
74 fXSWeightFactor = 1.0/fXSection->GetCrossSectionFactor();
75 }
76}
G4HadronicInteraction(const G4String &modelName="HadronicModel")
static G4NistManager * Instance()
static G4int GetModelID(const G4int modelIndex)

Referenced by G4ChargeExchange(), operator!=(), operator=(), and operator==().

◆ ~G4ChargeExchange()

G4ChargeExchange::~G4ChargeExchange ( )
override

Definition at line 78 of file G4ChargeExchange.cc.

79{
80 delete fHandler;
81}

◆ G4ChargeExchange() [2/2]

G4ChargeExchange::G4ChargeExchange ( const G4ChargeExchange & right)
delete

Member Function Documentation

◆ ApplyYourself()

G4HadFinalState * G4ChargeExchange::ApplyYourself ( const G4HadProjectile & aTrack,
G4Nucleus & targetNucleus )
overridevirtual

Reimplemented from G4HadronicInteraction.

Definition at line 83 of file G4ChargeExchange.cc.

85{
86 theParticleChange.Clear();
87 auto part = aTrack.GetDefinition();
88 G4double ekin = aTrack.GetKineticEnergy();
89
90 G4int A = targetNucleus.GetA_asInt();
91 G4int Z = targetNucleus.GetZ_asInt();
92
93 if (ekin <= lowEnergyLimit) {
94 return &theParticleChange;
95 }
96 theParticleChange.SetWeightChange(fXSWeightFactor);
97
98 G4int projPDG = part->GetPDGEncoding();
99 // for hydrogen targets and positive projectile change exchange
100 // is not possible on proton, only on deuteron
101 if (1 == Z && (211 == projPDG || 321 == projPDG)) { A = 2; }
102
103 if (verboseLevel > 1) {
104 G4cout << "G4ChargeExchange for " << part->GetParticleName()
105 << " PDGcode= " << projPDG << " on nucleus Z= " << Z
106 << " A= " << A << " N= " << A - Z
107 << G4endl;
108 }
109
111 G4LorentzVector lv0 = aTrack.Get4Momentum();
112
113 // select final state
114 const G4ParticleDefinition* theSecondary =
115 fXSection->SampleSecondaryType(part, aTrack.GetMaterial(),
116 Z, A, aTrack.GetTotalEnergy());
117 G4int pdg = theSecondary->GetPDGEncoding();
118
119 if (verboseLevel > 1)
120 G4cout << " Secondary " << theSecondary->GetParticleName() << " pdg=" << pdg << G4endl;
121
122 // omega(782) and f2(1270)
123 G4bool isShortLived = (pdg == 223 || pdg == 225);
124
125 // atomic number of the recoil nucleus
126 if (projPDG == -211) { --Z; }
127 else if (projPDG == 211) { ++Z; }
128 else if (projPDG == -321) { --Z; }
129 else if (projPDG == 321) { ++Z; }
130 else if (projPDG == 130) {
131 if (theSecondary->GetPDGCharge() > 0.0) { --Z; }
132 else { ++Z; }
133 } else {
134 // not ready for other projectile
135 return &theParticleChange;
136 }
137
138 // recoil nucleus
139 const G4ParticleDefinition* theRecoil = nullptr;
140 if (Z == 0 && A == 1) { theRecoil = G4Neutron::Neutron(); }
141 else if (Z == 1 && A == 1) { theRecoil = G4Proton::Proton(); }
142 else if (Z == 1 && A == 2) { theRecoil = G4Deuteron::Deuteron(); }
143 else if (Z == 1 && A == 3) { theRecoil = G4Triton::Triton(); }
144 else if (Z == 2 && A == 3) { theRecoil = G4He3::He3(); }
145 else if (Z == 2 && A == 4) { theRecoil = G4Alpha::Alpha(); }
146
147 // check if there is enough energy for the final state
148 // and sample mass of produced state
149 // sample kinematics
150 G4LorentzVector lv1(0.0, 0.0, 0.0, mass1);
151 G4LorentzVector lv = lv0 + lv1;
152 G4double m0 = lv.mag();
153 const G4double mass0 = theSecondary->GetPDGMass();
154 G4double mass2 = mass0;
155 G4double mass3;
156 G4bool ok = false;
157
158 if (verboseLevel > 1) {
159 G4cout << " Secondary meson " << theSecondary->GetParticleName()
160 << " mass(MeV)=" << mass2 << " pdg=" << pdg
161 << " Final Z=" << Z << " isShortLived=" << isShortLived
162 << " " << lv
163 << G4endl;
164 }
165 // fixed recoil mass
166 if (nullptr != theRecoil) {
167 mass3 = theRecoil->GetPDGMass();
168 ok = (m0 > mass2 + mass3);
169
170 // excited nuclear state
171 } else {
173 const G4double eFermi = 10*CLHEP::MeV;
174 for (G4int i=0; i<10; ++i) {
175 mass3 = mass30 + eFermi*G4UniformRand();
176 if (m0 > mass2 + mass3) {
177 ok = true;
178 break;
179 }
180 }
181 }
182 if (isShortLived) {
183 const G4double elim = 300*CLHEP::MeV;
184 ok = false;
185 for (G4int i=0; i<10; ++i) {
186 if (SampleMass(mass2, theSecondary->GetPDGWidth(), elim)) {
187 if (m0 > mass2 + mass3) {
188 ok = true;
189 break;
190 }
191 }
192 }
193 }
194
195 // not possible kinematically
196 if (!ok) { return &theParticleChange; }
197
198 G4double e2 = (m0*m0 + mass2*mass2 - mass3*mass3)/(2*m0);
199 G4double momentumCMS = std::sqrt(e2*e2 - mass2*mass2);
200 G4double tmax = 4*momentumCMS*momentumCMS;
201
202 // for projectile pion t depends on final state
203 G4double t;
204 if (fXSection->isPion()) {
205 t = fXSection->SampleTforPion(aTrack.GetTotalEnergy(), tmax);
206 }
207 else {
208 t = SampleT(theSecondary, A, tmax);
209 }
210
211 G4double phi = G4UniformRand()*CLHEP::twopi;
212 G4double cost = 1. - 2.0*t/tmax;
213
214 // if cos(theta) negative, there is a numerical problem
215 // instead of making scattering backward, make in this case
216 // no scattering
217 if (std::abs(cost) > 1.0) { cost = 1.0; }
218
219 G4double sint = std::sqrt((1.0 - cost)*(1.0 + cost));
220
221 if (verboseLevel > 1) {
222 G4cout << " t= " << t << " tmax(GeV^2)= " << tmax/(GeV*GeV)
223 << " cos(t)=" << cost << " sin(t)=" << sint << G4endl;
224 }
225 G4LorentzVector lv2(momentumCMS*sint*std::cos(phi),
226 momentumCMS*sint*std::sin(phi),
227 momentumCMS*cost, e2);
228
229 // kinematics in the final state, may be a warning should be added if
230 G4ThreeVector bst = lv.boostVector();
231 lv2.boost(bst);
232 lv -= lv2;
233 if (lv.e() < mass3) {
234 lv.setE(mass3);
235 }
236
237 // prepare secondary particles
238 theParticleChange.SetStatusChange(stopAndKill);
239 theParticleChange.SetEnergyChange(0.0);
240 theParticleChange.SetWeightChange(fXSWeightFactor);
241
242 if (!isShortLived) {
243 auto aSec = new G4DynamicParticle(theSecondary, lv2);
244 theParticleChange.AddSecondary(aSec, secID);
245 } else {
246 auto channel = theSecondary->GetDecayTable()->SelectADecayChannel(mass2);
247 auto products = channel->DecayIt(mass2);
248 G4ThreeVector bst1 = lv2.boostVector();
249 G4int N = products->entries();
250 for (G4int i=0; i<N; ++i) {
251 auto p = (*products)[i];
252 auto lvp = p->Get4Momentum();
253 lvp.boost(bst1);
254 auto pnew = new G4DynamicParticle(*p);
255 pnew->Set4Momentum(lvp);
256 theParticleChange.AddSecondary(pnew, secID);
257 }
258 delete products;
259 }
260
261 // recoil is a stable isotope
262 if (nullptr != theRecoil) {
263 auto aRec = new G4DynamicParticle(theRecoil, lv);
264 theParticleChange.AddSecondary(aRec, secID);
265 } else {
266 // recoil is a fragment, which may be unstable
267 G4Fragment frag(A, Z, lv);
268 auto products = fHandler->BreakItUp(frag);
269 for (auto & prod : *products) {
270 auto dp = new G4DynamicParticle(prod->GetDefinition(), prod->GetMomentum());
271 theParticleChange.AddSecondary(dp, secID);
272 delete prod;
273 }
274 delete products;
275 }
276 return &theParticleChange;
277}
@ stopAndKill
CLHEP::HepLorentzVector G4LorentzVector
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
const G4double A[17]
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
Hep3Vector boostVector() const
static G4Alpha * Alpha()
Definition G4Alpha.cc:83
G4double SampleT(const G4ParticleDefinition *theSec, const G4int A, const G4double tmax) const
G4VDecayChannel * SelectADecayChannel(G4double parentMass=-1.)
static G4Deuteron * Deuteron()
Definition G4Deuteron.cc:90
const G4Material * GetMaterial() const
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4LorentzVector & Get4Momentum() const
G4double GetTotalEnergy() const
static G4He3 * He3()
Definition G4He3.cc:90
static G4Neutron * Neutron()
Definition G4Neutron.cc:101
static G4double GetNuclearMass(const G4double A, const G4double Z)
G4int GetA_asInt() const
Definition G4Nucleus.hh:78
G4int GetZ_asInt() const
Definition G4Nucleus.hh:84
G4DecayTable * GetDecayTable() const
const G4String & GetParticleName() const
static G4Proton * Proton()
Definition G4Proton.cc:90
static G4Triton * Triton()
Definition G4Triton.cc:90
virtual G4DecayProducts * DecayIt(G4double parentMass=-1.0)=0
#define N
Definition crc32.c:57

◆ operator!=()

G4bool G4ChargeExchange::operator!= ( const G4ChargeExchange & right) const
delete

◆ operator=()

const G4ChargeExchange & G4ChargeExchange::operator= ( const G4ChargeExchange & right)
delete

◆ operator==()

G4bool G4ChargeExchange::operator== ( const G4ChargeExchange & right) const
delete

◆ SampleT()

G4double G4ChargeExchange::SampleT ( const G4ParticleDefinition * theSec,
const G4int A,
const G4double tmax ) const

Definition at line 279 of file G4ChargeExchange.cc.

281{
282 const G4double GeV2 = CLHEP::GeV*CLHEP::GeV;
283 const G4double numLimit = 18.;
284
285 G4double tmax = ltmax/GeV2;
286 if (verboseLevel > 1) {
287 G4cout << "G4ChargeExchange::SampleT tmax(GeV^2)=" << tmax << G4endl;
288 }
289
290 G4double aa, bb, cc, dd;
291 G4Pow* g4pow = G4Pow::GetInstance();
292 G4double a13 = g4pow->Z13(A);
293 if (A <= 62) {
294 aa = (A*A);
295 bb = 14.5*a13*a13;
296 cc = 1.4*a13;
297 dd = 10.;
298 } else {
299 aa = g4pow->powZ(A, 1.33);
300 bb = 60.*a13;
301 cc = 0.4*g4pow->powZ(A, 0.40);
302 dd = 10.;
303 }
304 G4double q1 = 1.0 - G4Exp(-std::min(bb*tmax, numLimit));
305 G4double q2 = 1.0 - G4Exp(-std::min(dd*tmax, numLimit));
306 G4double s1 = q1*aa;
307 G4double s2 = q2*cc;
308 if ((s1 + s2)*G4UniformRand() < s2) {
309 q1 = q2;
310 bb = dd;
311 }
312 return -GeV2*G4Log(1.0 - G4UniformRand()*q1)/bb;
313}
const G4double GeV2
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition G4Exp.hh:132
G4double G4Log(G4double x)
Definition G4Log.hh:169
static G4Pow * GetInstance()
Definition G4Pow.cc:41
G4double powZ(G4int Z, G4double y) const
Definition G4Pow.hh:225
G4double Z13(G4int Z) const
Definition G4Pow.hh:123

Referenced by ApplyYourself().


The documentation for this class was generated from the following files: