source: trunk/source/processes/hadronic/stopping/src/G4KaonMinusAbsorptionAtRest.cc @ 1347

Last change on this file since 1347 was 1347, checked in by garnier, 13 years ago

geant4 tag 9.4

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