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

Last change on this file since 1007 was 1007, checked in by garnier, 15 years ago

update to geant4.9.2

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