Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4KaonMinusAbsorptionAtRest.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 // Author: Christian V"olcker (Christian.Volcker@cern.ch),
27 //
28 // Creation date: November 1997
29 //
30 // Testfile: ../G4KaonMinusAbsorptionAtRestTest.cc
31 //
32 // Modifications:
33 // Maria Grazia Pia September 1998
34 // Various bug fixes, eliminated several memory leaks
35 //
36 // -------------------------------------------------------------------
37 
38 
40 
41 #include "G4StopDeexcitation.hh"
44 #include "G4ReactionKinematics.hh"
46 #include "G4HadronicDeprecate.hh"
47 
48 G4KaonMinusAbsorptionAtRest::G4KaonMinusAbsorptionAtRest(const G4String& processName,
49  G4ProcessType aType ) :
50  G4VRestProcess (processName, aType)
51 {
52  G4HadronicDeprecate("G4KaonMinusAbsorptionAtRest");
53  if (verboseLevel>0) {
54  G4cout << GetProcessName() << " is created "<< G4endl;
55  }
57 
58  // see Cohn et al, PLB27(1968) 527;
59  // Davis et al, PLB1(1967) 434;
60 
61  pionAbsorptionRate = 0.07;
62 
63  // see VanderVelde-Wilquet et al, Nuov.Cim.39A(1978)538;
64  // see VanderVelde-Wilquet et al, Nuov.Cim.38A(1977)178;
65  // see VanderVelde-Wilquet et al, Nucl.Phys.A241(1975)511;
66  // primary production rates ( for absorption on Carbon)
67  // .. other elements are extrapolated by the halo factor.
68 
69  rateLambdaZeroPiZero = 0.052;
70  rateSigmaMinusPiPlus = 0.199;
71  rateSigmaPlusPiMinus = 0.446;
72  rateSigmaZeroPiZero = 0.303;
73  rateLambdaZeroPiMinus = 0.568;
74  rateSigmaZeroPiMinus = 0.216;
75  rateSigmaMinusPiZero = 0.216;
76 
77  // for sigma- p -> lambda n
78  // sigma+ n -> lambda p
79  // sigma- n -> lambda
80  // all values compatible with 0.55 same literature as above.
81 
82  sigmaPlusLambdaConversionRate = 0.55;
83  sigmaMinusLambdaConversionRate = 0.55;
84  sigmaZeroLambdaConversionRate = 0.55;
85 
87 }
88 
89 
91 {
93 }
94 
96 {
98 }
99 
101 {
103 }
104 
106 (const G4Track& track, const G4Step& )
107 {
108  stoppedHadron = track.GetDynamicParticle();
109 
110  // Check applicability
111 
112  if (!IsApplicable(*(stoppedHadron->GetDefinition())))
113  {
114  G4cerr <<"G4KaonMinusAbsorptionAtRest:ERROR, particle must be a Kaon!" <<G4endl;
115  return 0;
116  }
117 
119  material = track.GetMaterial();
120  nucleus = 0;
121  do
122  {
123  // Select the nucleus, get nucleon
124  nucleus = new G4Nucleus(material);
125  if (nucleus->GetA_asInt() < 1.5)
126  {
127  delete nucleus;
128  nucleus = 0;
129  }
130  } while(nucleus == 0);
131 
132  G4double Z = nucleus->GetZ_asInt();
133  G4double A = nucleus->GetA_asInt();
134 
135  // Do the interaction with the nucleon
136  G4DynamicParticleVector* absorptionProducts = KaonNucleonReaction();
137 
138  //A.R. 26-Jul-2012 Coverity fix
139  if ( ! absorptionProducts ) {
140  G4Exception("G4KaonMinusAbsorptionAtRest::AtRestDoIt()", "HAD_STOP_0001",
141  FatalException, "NULL absorptionProducts");
142  return 0;
143  }
144 
145  // Secondary interactions
146 
147  G4DynamicParticle* thePion;
148  unsigned int i;
149  for(i = 0; i < absorptionProducts->size(); i++)
150  {
151  thePion = (*absorptionProducts)[i];
152  if (thePion->GetDefinition() == G4PionMinus::PionMinus()
153  || thePion->GetDefinition() == G4PionPlus::PionPlus()
154  || thePion->GetDefinition() == G4PionZero::PionZero())
155  {
156  if (AbsorbPionByNucleus(thePion))
157  {
158  absorptionProducts->erase(absorptionProducts->begin()+i);
159  i--;
160  delete thePion;
161  if (verboseLevel > 1)
162  G4cout << "G4KaonMinusAbsorption::AtRestDoIt: Pion absorbed in Nucleus"
163  << G4endl;
164  }
165  }
166  }
167 
168  G4DynamicParticle* theSigma;
169  G4DynamicParticle* theLambda;
170  for (i = 0; i < absorptionProducts->size(); i++)
171  {
172  theSigma = (*absorptionProducts)[i];
173  if (theSigma->GetDefinition() == G4SigmaMinus::SigmaMinus()
174  || theSigma->GetDefinition() == G4SigmaPlus::SigmaPlus()
175  || theSigma->GetDefinition() == G4SigmaZero::SigmaZero())
176  {
177  theLambda = SigmaLambdaConversion(theSigma);
178  if (theLambda != 0){
179  absorptionProducts->erase(absorptionProducts->begin()+i);
180  i--;
181  delete theSigma;
182  absorptionProducts->push_back(theLambda);
183 
184  if (verboseLevel > 1)
185  G4cout << "G4KaonMinusAbsorption::AtRestDoIt: SigmaLambdaConversion Done"
186  << G4endl;
187  }
188  }
189  }
190 
191  // Nucleus deexcitation
192 
193  G4double productEnergy = 0.;
194  G4ThreeVector pProducts(0.,0.,0.);
195 
196  unsigned int nAbsorptionProducts = 0;
197  if (absorptionProducts != 0) nAbsorptionProducts = absorptionProducts->size();
198 
199  for ( i = 0; i<nAbsorptionProducts; i++)
200  {
201  pProducts += (*absorptionProducts)[i]->GetMomentum();
202  productEnergy += (*absorptionProducts)[i]->GetKineticEnergy();
203  }
204 
205  G4double newZ = nucleus->GetZ_asInt();
206  G4double newA = nucleus->GetA_asInt();
207 
208  G4double bDiff = G4NucleiProperties::GetBindingEnergy(static_cast<G4int>(A),static_cast<G4int>(Z)) -
209  G4NucleiProperties::GetBindingEnergy(static_cast<G4int>(newA), static_cast<G4int>(newZ));
210 
211  G4StopDeexcitationAlgorithm* nucleusAlgorithm = new G4StopTheoDeexcitation();
212  G4StopDeexcitation stopDeexcitation(nucleusAlgorithm);
213 
214  nucleus->AddExcitationEnergy(bDiff);
215 
216  // returns excitation energy for the moment ..
217  G4double energyDeposit = nucleus->GetEnergyDeposit();
218  if (verboseLevel>0)
219  {
220  G4cout << " -- KaonAtRest -- excitation = "
221  << energyDeposit
222  << ", pNucleus = "
223  << pProducts
224  << ", A: "
225  << A
226  << ", "
227  << newA
228  << ", Z: "
229  << Z
230  << ", "
231  << newZ
232  << G4endl;
233  }
234 
235  if (energyDeposit < 0.)
236  G4Exception("G4KaonMinusAbsorptionAtRest::AtRestDoIt()", "HAD_STOP_0002",
237  FatalException, "Excitation energy < 0");
238  delete nucleus;
239 
240  G4ReactionProductVector* fragmentationProducts = stopDeexcitation.DoBreakUp(newA,newZ,energyDeposit,pProducts);
241 
242  unsigned int nFragmentationProducts = 0;
243  if (fragmentationProducts != 0) nFragmentationProducts = fragmentationProducts->size();
244 
245  //Initialize ParticleChange
246  aParticleChange.Initialize(track);
247  aParticleChange.SetNumberOfSecondaries(G4int(nAbsorptionProducts+nFragmentationProducts) );
248 
249  // update List of alive particles. put energy deposit at the right place ...
250  for (i = 0; i < nAbsorptionProducts; i++)
251  {aParticleChange.AddSecondary((*absorptionProducts)[i]); }
252  if (absorptionProducts != 0) delete absorptionProducts;
253 
254 // for (i = 0; i < nFragmentationProducts; i++)
255 // { aParticleChange.AddSecondary(fragmentationProducts->at(i)); }
256  for(i=0; i<nFragmentationProducts; i++)
257  {
258  G4DynamicParticle * aNew =
259  new G4DynamicParticle((*fragmentationProducts)[i]->GetDefinition(),
260  (*fragmentationProducts)[i]->GetTotalEnergy(),
261  (*fragmentationProducts)[i]->GetMomentum());
262  G4double newTime = aParticleChange.GetGlobalTime((*fragmentationProducts)[i]->GetFormationTime());
263  aParticleChange.AddSecondary(aNew, newTime);
264  delete (*fragmentationProducts)[i];
265  }
266  if (fragmentationProducts != 0) delete fragmentationProducts;
267 
268  // finally ...
269  aParticleChange.ProposeTrackStatus(fStopAndKill); // Kill the incident Kaon
270  return &aParticleChange;
271 }
272 
273 
274 G4DynamicParticle G4KaonMinusAbsorptionAtRest::GetAbsorbingNucleon()
275 {
276  G4DynamicParticle aNucleon;
277 
278  // Get nucleon definition, based on Z,N of current Nucleus
279  aNucleon.SetDefinition(SelectAbsorbingNucleon());
280 
281  // Fermi momentum distribution in three dimensions
282  G4ThreeVector pFermi = nucleus->GetFermiMomentum();
283  aNucleon.SetMomentum(pFermi);
284 
285  return aNucleon;
286 }
287 
288 G4ParticleDefinition* G4KaonMinusAbsorptionAtRest::SelectAbsorbingNucleon()
289 {
290  // (Ch. Voelcker) extended from ReturnTargetParticle():
291  // Choose a proton or a neutron as the absorbing particle,
292  // taking weight into account!
293  // Update nucleon's atomic numbers.
294 
295  G4ParticleDefinition* absorbingParticleDef;
296 
297  G4double ranflat = G4UniformRand();
298 
299  G4double myZ = nucleus->GetZ_asInt(); // number of protons
300  G4double myN = nucleus->GetA_asInt(); // number of nucleons (not neutrons!!)
301 
302  // See VanderVelde-Wilquet et al, Nuov.Cim.39A(1978)538;
303  G4double carbonRatioNP = 0.18; // (Rn/Rp)c, see page 544
304 
305  G4double neutronProtonRatio = NeutronHaloFactor(myZ,myN)*carbonRatioNP*(myN-myZ)/myZ;
306  G4double protonProbability = 1./(1.+neutronProtonRatio);
307 
308  if ( ranflat < protonProbability )
309  {
310  absorbingParticleDef = G4Proton::Proton();
311  myZ-= 1.;
312  }
313  else
314  { absorbingParticleDef = G4Neutron::Neutron(); }
315 
316  myN -= 1.;
317  nucleus->SetParameters(myN,myZ);
318  return absorbingParticleDef;
319 }
320 
321 
322 G4double G4KaonMinusAbsorptionAtRest::NeutronHaloFactor(G4double Z, G4double N)
323 {
324  // this function should take care of the probability for absorption
325  // on neutrons, depending on number of protons Z and number of neutrons N-Z
326  // parametrisation from fit to
327  // VanderVelde-Wilquet et al, Nuov.Cim.39A(1978)538;
328  //
329 
330  if (Z == 1.) return 1.389; // deuterium
331  else if (Z == 2.) return 1.78; // helium
332  else if (Z == 10.) return 0.66; // neon
333  else
334  return 0.6742+(N-Z)*0.06524;
335 }
336 
337 
338 G4DynamicParticleVector* G4KaonMinusAbsorptionAtRest::KaonNucleonReaction()
339 {
341 
342  G4double ranflat = G4UniformRand();
343  G4double prob = 0;
344 
345  G4ParticleDefinition* producedBaryonDef;
346  G4ParticleDefinition* producedMesonDef;
347 
348  G4double iniZ = nucleus->GetZ_asInt();
349  G4double iniA = nucleus->GetA_asInt();
350 
351  G4DynamicParticle aNucleon = GetAbsorbingNucleon();
352 
353  // DHW 15 may 2011: unused: G4double nucleonMass;
354 
355  if (aNucleon.GetDefinition() == G4Proton::Proton())
356  {
357  // DHW 15 May 2011: unused: nucleonMass = proton_mass_c2+electron_mass_c2;
358  if ( (prob += rateLambdaZeroPiZero) > ranflat)
359  { // lambda pi0
360  producedBaryonDef = G4Lambda::Lambda();
361  producedMesonDef = G4PionZero::PionZero();
362  }
363  else if ((prob += rateSigmaPlusPiMinus) > ranflat)
364  { // sigma+ pi-
365  producedBaryonDef = G4SigmaPlus::SigmaPlus();
366  producedMesonDef = G4PionMinus::PionMinus();
367  }
368  else if ((prob += rateSigmaMinusPiPlus) > ranflat)
369  { // sigma- pi+
370  producedBaryonDef = G4SigmaMinus::SigmaMinus();
371  producedMesonDef = G4PionPlus::PionPlus();
372  }
373  else
374  { // sigma0 pi0
375  producedBaryonDef = G4SigmaZero::SigmaZero();
376  producedMesonDef = G4PionZero::PionZero();
377  }
378  }
379  else if (aNucleon.GetDefinition() == G4Neutron::Neutron())
380  {
381  // DHW 15 May 2011: unused: nucleonMass = neutron_mass_c2;
382  if ((prob += rateLambdaZeroPiMinus) > ranflat)
383  { // lambda pi-
384  producedBaryonDef = G4Lambda::Lambda();
385  producedMesonDef = G4PionMinus::PionMinus();
386  }
387  else if ((prob += rateSigmaZeroPiMinus) > ranflat)
388  { // sigma0 pi-
389  producedBaryonDef = G4SigmaZero::SigmaZero();
390  producedMesonDef = G4PionMinus::PionMinus();
391  }
392  else
393  { // sigma- pi0
394  producedBaryonDef = G4SigmaMinus::SigmaMinus();
395  producedMesonDef = G4PionZero::PionZero();
396  }
397  }
398  else
399  {
400  if (verboseLevel>0)
401  {
402  G4cout
403  << "G4KaonMinusAbsorption::KaonNucleonReaction: "
404  << aNucleon.GetDefinition()->GetParticleName()
405  << " is not a good nucleon - check G4Nucleus::ReturnTargetParticle()!"
406  << G4endl;
407  }
408 
409  //A.R. 26-Jul-2012 Coverity fix
410  if ( products ) delete products;
411 
412  return 0;
413  }
414 
415  G4double newZ = nucleus->GetZ_asInt();
416  G4double newA = nucleus->GetA_asInt();
417 
418  // Modify the Kaon mass to take nuclear binding energy into account
419  // .. using mas formula ..
420  // .. using mass table ..
421  // equivalent to -'initialBindingEnergy+nucleus.GetBindingEnergy' !
422 
423  G4double nucleonBindingEnergy =
424  -G4NucleiProperties::GetBindingEnergy(static_cast<G4int>(iniA), static_cast<G4int>(iniZ) )
425  +G4NucleiProperties::GetBindingEnergy(static_cast<G4int>(newA), static_cast<G4int>(newZ) );
426 
427  G4DynamicParticle modifiedHadron = (*stoppedHadron);
428  modifiedHadron.SetMass(stoppedHadron->GetMass() + nucleonBindingEnergy);
429 
430  // Setup outgoing dynamic particles
431  G4ThreeVector dummy(0.,0.,0.);
432  G4DynamicParticle* producedBaryon = new G4DynamicParticle(producedBaryonDef,dummy);
433  G4DynamicParticle* producedMeson = new G4DynamicParticle(producedMesonDef,dummy);
434 
435  // Produce the secondary particles in a twobody process:
436  G4ReactionKinematics theReactionKinematics;
437  theReactionKinematics.TwoBodyScattering( &modifiedHadron, &aNucleon,
438  producedBaryon, producedMeson);
439 
440  products->push_back(producedBaryon);
441  products->push_back(producedMeson);
442 
443  if (verboseLevel > 1)
444  {
445  G4cout
446  << "G4KaonMinusAbsorption::KaonNucleonReaction: Number of primaries = "
447  << products->size()
448  << ": " <<producedMesonDef->GetParticleName()
449  << ", " <<producedBaryonDef->GetParticleName() << G4endl;
450  }
451 
452  return products;
453 }
454 
455 
456 G4bool G4KaonMinusAbsorptionAtRest::AbsorbPionByNucleus(G4DynamicParticle* aPion)
457 {
458  // Needs some more investigation!
459 
460  G4double ranflat = G4UniformRand();
461 
462  if (ranflat < pionAbsorptionRate){
463  // Add pion energy to ExcitationEnergy and NucleusMomentum
464  nucleus->AddExcitationEnergy(aPion->GetTotalEnergy());
465  nucleus->AddMomentum(aPion->GetMomentum());
466  }
467 
468  return (ranflat < pionAbsorptionRate);
469 }
470 
471 G4DynamicParticle* G4KaonMinusAbsorptionAtRest::SigmaLambdaConversion(G4DynamicParticle* aSigma)
472 {
473  G4double ranflat = G4UniformRand();
474  G4double sigmaLambdaConversionRate;
475 
476  G4double A = nucleus->GetA_asInt();
477  G4double Z = nucleus->GetZ_asInt();
478 
479  G4double newZ = Z;
480  // DHW 15 May 2011: unused: G4double nucleonMassDifference = 0;
481 
482  G4ParticleDefinition* inNucleonDef=NULL;
483  G4ParticleDefinition* outNucleonDef=NULL;
484 
485  // Decide which sigma
486  switch((int) aSigma->GetDefinition()->GetPDGCharge()) {
487 
488  case 1:
489  sigmaLambdaConversionRate = sigmaPlusLambdaConversionRate;
490  inNucleonDef = G4Neutron::Neutron();
491  outNucleonDef = G4Proton::Proton();
492  newZ = Z+1;
493  // DHW 15 May 2011: unused: nucleonMassDifference = neutron_mass_c2 - proton_mass_c2-electron_mass_c2;
494  break;
495 
496  case -1:
497  sigmaLambdaConversionRate = sigmaMinusLambdaConversionRate;
498  inNucleonDef = G4Proton::Proton();
499  outNucleonDef = G4Neutron::Neutron();
500  newZ = Z-1;
501  // DHW 15 May 2011: unused: nucleonMassDifference = proton_mass_c2+electron_mass_c2 - neutron_mass_c2;
502  break;
503 
504  case 0:
505  sigmaLambdaConversionRate = sigmaZeroLambdaConversionRate;
506  // The 'outgoing' nucleon is just virtual, to keep the energy-momentum
507  // balance and will not appear in the ParticleChange. Therefore no need
508  // choose between neutron and proton here!
509  inNucleonDef = G4Neutron::Neutron();
510  outNucleonDef = G4Neutron::Neutron();
511  break;
512 
513  default:
514  sigmaLambdaConversionRate = 0.;
515  // Add dummy particles to avoid possibility of passing NULL pointers
516  inNucleonDef = G4Proton::Proton();
517  outNucleonDef = G4Proton::Proton();
518  }
519 
520  if (ranflat >= sigmaLambdaConversionRate) return 0;
521 
522  G4ThreeVector dummy(0.,0.,0.);
523 
524  // Fermi momentum distribution in three dimensions
525  G4ThreeVector momentum = nucleus->GetFermiMomentum();
526 
527  G4ParticleDefinition* lambdaDef = G4Lambda::Lambda();
528 
529  G4DynamicParticle inNucleon(inNucleonDef,momentum);
530  G4DynamicParticle outNucleon(outNucleonDef,dummy);
531  G4DynamicParticle* outLambda = new G4DynamicParticle(lambdaDef,dummy);
532 
533  G4ReactionKinematics theReactionKinematics;
534 
535  // Now do the twobody scattering
536  theReactionKinematics.TwoBodyScattering(aSigma, &inNucleon,
537  &outNucleon, outLambda);
538 
539  // Binding energy of nucleus has changed. This will change the
540  // ExcitationEnergy.
541  // .. using mass formula ..
542  // .. using mass table ..
543  // equivalent to -'initialBindingEnergy+nucleus.GetBindingEnergy' !
544 
545  // Add energy and momentum to nucleus, change Z,A
546  nucleus->AddExcitationEnergy(outNucleon.GetKineticEnergy());
547  nucleus->AddMomentum(outNucleon.GetMomentum());
548  nucleus->SetParameters(A,newZ);
549 
550  // The calling routine is responsible to delete the sigma!!
551  return outLambda;
552 }
553 
554 
555