source: trunk/source/processes/hadronic/models/de_excitation/ablation/src/G4WilsonAblationModel.cc @ 1253

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

update geant4.9.3 tag

File size: 20.3 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// *                                                                  *
21// * Parts of this code which have been  developed by QinetiQ Ltd     *
22// * under contract to the European Space Agency (ESA) are the        *
23// * intellectual property of ESA. Rights to use, copy, modify and    *
24// * redistribute this software for general public use are granted    *
25// * in compliance with any licensing, distribution and development   *
26// * policy adopted by the Geant4 Collaboration. This code has been   *
27// * written by QinetiQ Ltd for the European Space Agency, under ESA  *
28// * contract 17191/03/NL/LvH (Aurora Programme).                     *
29// *                                                                  *
30// * By using,  copying,  modifying or  distributing the software (or *
31// * any work based  on the software)  you  agree  to acknowledge its *
32// * use  in  resulting  scientific  publications,  and indicate your *
33// * acceptance of all terms of the Geant4 Software license.          *
34// ********************************************************************
35//
36// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37//
38// MODULE:              G4WilsonAblationModel.cc
39//
40// Version:             1.0
41// Date:                08/12/2009
42// Author:              P R Truscott
43// Organisation:        QinetiQ Ltd, UK
44// Customer:            ESA/ESTEC, NOORDWIJK
45// Contract:            17191/03/NL/LvH
46//
47// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48//
49// CHANGE HISTORY
50// --------------
51//
52// 6 October 2003, P R Truscott, QinetiQ Ltd, UK
53// Created.
54//
55// 15 March 2004, P R Truscott, QinetiQ Ltd, UK
56// Beta release
57//
58// 08 December 2009, P R Truscott, QinetiQ Ltd, UK
59// Ver 1.0
60// Updated as a result of changes in the G4Evaporation classes.  These changes
61// affect mostly SelectSecondariesByEvaporation, and now you have variables
62// associated with the evaporation model which can be changed:
63//    OPTxs to select the inverse cross-section
64//    OPTxs = 0      => Dostrovski's parameterization
65//    OPTxs = 1 or 2 => Chatterjee's paramaterization
66//    OPTxs = 3 or 4 => Kalbach's parameterization
67//    useSICB        => use superimposed Coulomb Barrier for inverse cross
68//                      sections
69// Other problem found with G4Fragment definition using Lorentz vector and
70// **G4ParticleDefinition**.  This does not allow A and Z to be defined for the
71// fragment for some reason.  Now the fragment is defined more explicitly:
72//    G4Fragment *fragment = new G4Fragment(A, Z, lorentzVector);
73// to avoid this quirk.  Bug found in SelectSecondariesByDefault: *type is now
74// equated to evapType[i] whereas previously it was equated to fragType[i].
75//
76// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77////////////////////////////////////////////////////////////////////////////////
78//
79#include "G4WilsonAblationModel.hh"
80#include "Randomize.hh"
81#include "G4ParticleTable.hh"
82#include "G4IonTable.hh"
83#include "G4Alpha.hh"
84#include "G4He3.hh"
85#include "G4Triton.hh"
86#include "G4Deuteron.hh"
87#include "G4Proton.hh"
88#include "G4Neutron.hh"
89#include "G4AlphaEvaporationChannel.hh"
90#include "G4He3EvaporationChannel.hh"
91#include "G4TritonEvaporationChannel.hh"
92#include "G4DeuteronEvaporationChannel.hh"
93#include "G4ProtonEvaporationChannel.hh"
94#include "G4NeutronEvaporationChannel.hh"
95#include "G4LorentzVector.hh"
96#include "G4VEvaporationChannel.hh"
97
98#include <iomanip>
99#include <numeric>
100////////////////////////////////////////////////////////////////////////////////
101//
102G4WilsonAblationModel::G4WilsonAblationModel()
103{
104//
105//
106// Send message to stdout to advise that the G4Abrasion model is being used.
107//
108  PrintWelcomeMessage();
109//
110//
111// Set the default verbose level to 0 - no output.
112//
113  verboseLevel = 0; 
114//
115//
116// Set the binding energy per nucleon .... did I mention that this is a crude
117// model for nuclear de-excitation?
118//
119  B = 10.0 * MeV;
120//
121//
122// It is possuble to switch off secondary particle production (other than the
123// final nuclear fragment).  The default is on.
124//
125  produceSecondaries = true;
126//
127//
128// Now we need to define the decay modes.  We're using the G4Evaporation model
129// to help determine the kinematics of the decay.
130//
131  nFragTypes  = 6;
132  fragType[0] = G4Alpha::Alpha();
133  fragType[1] = G4He3::He3();
134  fragType[2] = G4Triton::Triton();
135  fragType[3] = G4Deuteron::Deuteron();
136  fragType[4] = G4Proton::Proton();
137  fragType[5] = G4Neutron::Neutron();
138//
139//
140// Set verboseLevel default to no output.
141//
142  verboseLevel = 0;
143  theChannelFactory = new G4EvaporationFactory();
144  theChannels = theChannelFactory->GetChannel();
145//
146//
147// Set defaults for evaporation classes.  These can be overridden by user
148// "set" methods.
149//
150  OPTxs   = 3;
151  useSICB = false;
152}
153////////////////////////////////////////////////////////////////////////////////
154//
155G4WilsonAblationModel::~G4WilsonAblationModel()
156{
157  if (theChannels != 0) theChannels = 0;
158  if (theChannelFactory != 0) delete theChannelFactory;
159}
160////////////////////////////////////////////////////////////////////////////////
161//
162G4FragmentVector *G4WilsonAblationModel::BreakItUp
163  (const G4Fragment &theNucleus)
164{
165//
166//
167// Initilise the pointer to the G4FragmentVector used to return the information
168// about the breakup.
169//
170  fragmentVector = new G4FragmentVector;
171  fragmentVector->clear();
172//
173//
174// Get the A, Z and excitation of the nucleus.
175//
176  G4int A     = (G4int) theNucleus.GetA();
177  G4int Z     = (G4int) theNucleus.GetZ();
178  G4double ex = theNucleus.GetExcitationEnergy();
179  if (verboseLevel >= 2)
180  {
181    G4cout <<"oooooooooooooooooooooooooooooooooooooooo"
182           <<"oooooooooooooooooooooooooooooooooooooooo"
183           <<G4endl;
184    G4cout.precision(6);
185    G4cout <<"IN G4WilsonAblationModel" <<G4endl;
186    G4cout <<"Initial prefragment A=" <<A
187           <<", Z=" <<Z
188           <<", excitation energy = " <<ex/MeV <<" MeV"
189           <<G4endl; 
190  }
191//
192//
193// Check that there is a nucleus to speak of.  It's possible there isn't one
194// or its just a proton or neutron.  In either case, the excitation energy
195// (from the Lorentz vector) is not used.
196//
197  if (A == 0)
198  {
199    if (verboseLevel >= 2)
200    {
201      G4cout <<"No nucleus to decay" <<G4endl;
202      G4cout <<"oooooooooooooooooooooooooooooooooooooooo"
203             <<"oooooooooooooooooooooooooooooooooooooooo"
204             <<G4endl;
205    }
206    return fragmentVector;
207  }
208  else if (A == 1)
209  {
210    G4LorentzVector lorentzVector = theNucleus.GetMomentum();
211    lorentzVector.setE(lorentzVector.e()-ex+10.0*eV);
212    if (Z == 0)
213    {
214      G4Fragment *fragment = new G4Fragment(lorentzVector,G4Neutron::Neutron());
215      fragmentVector->push_back(fragment);
216    }
217    else
218    {
219      G4Fragment *fragment = new G4Fragment(lorentzVector,G4Proton::Proton());
220      fragmentVector->push_back(fragment);
221    }
222    if (verboseLevel >= 2)
223    {
224      G4cout <<"Final fragment is in fact only a nucleon) :" <<G4endl;
225      G4cout <<(*fragmentVector)[0] <<G4endl;
226      G4cout <<"oooooooooooooooooooooooooooooooooooooooo"
227             <<"oooooooooooooooooooooooooooooooooooooooo"
228             <<G4endl;
229    }
230    return fragmentVector;
231  }
232//
233//
234// Then the number of nucleons ablated (either as nucleons or light nuclear
235// fragments) is based on a simple argument for the binding energy per nucleon.
236//
237  G4int DAabl = (G4int) (ex / B);
238  if (DAabl > A) DAabl = A;
239// The following lines are no longer accurate given we now treat the final fragment
240//  if (verboseLevel >= 2)
241//    G4cout <<"Number of nucleons ejected = " <<DAabl <<G4endl;
242
243//
244//
245// Determine the nuclear fragment from the ablation process by sampling the
246// Rudstam equation.
247//
248  G4int AF = A - DAabl;
249  G4int ZF = 0;
250  if (AF > 0)
251  {
252    G4double AFd = (G4double) AF;
253    G4double R = 11.8 / std::pow(AFd, 0.45);
254    G4int minZ = Z - DAabl;
255    if (minZ <= 0) minZ = 1;
256//
257//
258// Here we define an integral probability distribution based on the Rudstam
259// equation assuming a constant AF.
260//   
261    G4double sig[100];
262    G4double sum = 0.0;
263    for (G4int ii=minZ; ii<= Z; ii++)
264    {
265      sum   += std::exp(-R*std::pow(std::abs(ii - 0.486*AFd + 3.8E-04*AFd*AFd),1.5));
266      sig[ii] = sum;
267    }
268//
269//
270// Now sample that distribution to determine a value for ZF.
271//
272    G4double xi  = G4UniformRand();
273    G4int iz     = minZ;
274    G4bool found = false;
275    while (iz <= Z && !found)
276    {
277      found = (xi <= sig[iz]/sum);
278      if (!found) iz++;
279    }
280    if (iz > Z)
281      ZF = Z;
282    else
283      ZF = iz;
284  }
285  G4int DZabl = Z - ZF;
286//
287//
288// Now determine the nucleons or nuclei which have bee ablated.  The preference
289// is for the production of alphas, then other nuclei in order of decreasing
290// binding energy. The energies assigned to the products of the decay are
291// provisional for the moment (the 10eV is just to avoid errors with negative
292// excitation energies due to rounding).
293//
294  G4double totalEpost = 0.0;
295  evapType.clear();
296  for (G4int ift=0; ift<nFragTypes; ift++)
297  {
298    G4ParticleDefinition *type = fragType[ift];
299    G4double n  = std::floor((G4double) DAabl / type->GetBaryonNumber() + 1.0E-10);
300    G4double n1 = 1.0E+10;
301    if (fragType[ift]->GetPDGCharge() > 0.0)
302      n1 = std::floor((G4double) DZabl / type->GetPDGCharge() + 1.0E-10);
303    if (n > n1) n = n1;
304    if (n > 0.0)
305    {
306      G4double mass = type->GetPDGMass();
307      for (G4int j=0; j<(G4int) n; j++)
308      {
309        totalEpost += mass;
310        evapType.push_back(type);
311      }
312      DAabl -= (G4int) (n * type->GetBaryonNumber() + 1.0E-10);
313      DZabl -= (G4int) (n * type->GetPDGCharge() + 1.0E-10);
314    }
315  }
316//
317//
318// Determine the properties of the final nuclear fragment.  Note that if
319// the final fragment is predicted to have a nucleon number of zero, then
320// really it's the particle last in the vector evapType which becomes the
321// final fragment.  Therefore delete this from the vector if this is the
322// case.
323//
324  G4double massFinalFrag = 0.0;
325  if (AF > 0)
326    massFinalFrag = G4ParticleTable::GetParticleTable()->GetIonTable()->
327      GetIonMass(ZF,AF);
328  else
329  {
330    G4ParticleDefinition *type = evapType[evapType.size()-1];
331    AF                         = type->GetBaryonNumber();
332    ZF                         = (G4int) (type->GetPDGCharge() + 1.0E-10);
333    evapType.erase(evapType.end()-1);
334  }
335  totalEpost   += massFinalFrag;
336//
337//
338// Provide verbose output on the nuclear fragment if requested.
339//
340  if (verboseLevel >= 2)
341  {
342    G4cout <<"Final fragment      A=" <<AF
343           <<", Z=" <<ZF
344           <<G4endl;
345    for (G4int ift=0; ift<nFragTypes; ift++)
346    {
347      G4ParticleDefinition *type = fragType[ift];
348      G4int n                    = std::count(evapType.begin(),evapType.end(),type);
349      if (n > 0) 
350        G4cout <<"Particle type: " <<std::setw(10) <<type->GetParticleName()
351               <<", number of particles emitted = " <<n <<G4endl;
352    }
353  }
354//
355// Add the total energy from the fragment.  Note that the fragment is assumed
356// to be de-excited and does not undergo photo-evaporation .... I did mention
357// this is a bit of a crude model?
358//
359  G4double massPreFrag      = theNucleus.GetGroundStateMass();
360  G4double totalEpre        = massPreFrag + ex;
361  G4double excess           = totalEpre - totalEpost;
362//  G4Fragment *resultNucleus(theNucleus);
363  G4Fragment *resultNucleus = new G4Fragment(A, Z, theNucleus.GetMomentum());
364  G4ThreeVector boost(0.0,0.0,0.0);
365  G4int nEvap = 0;
366  if (produceSecondaries && evapType.size()>0)
367  {
368    if (excess > 0.0)
369    {
370      SelectSecondariesByEvaporation (resultNucleus);
371      nEvap = fragmentVector->size();
372      boost = resultNucleus->GetMomentum().findBoostToCM();
373      if (evapType.size() > 0)
374        SelectSecondariesByDefault (boost);
375    }
376    else
377      SelectSecondariesByDefault(G4ThreeVector(0.0,0.0,0.0));
378  }
379
380  if (AF > 0)
381  {
382    G4double mass = G4ParticleTable::GetParticleTable()->GetIonTable()->
383      GetIonMass(ZF,AF);
384    G4double e    = mass + 10.0*eV;
385    G4double p    = std::sqrt(e*e-mass*mass);
386    G4ThreeVector direction(0.0,0.0,1.0);
387    G4LorentzVector lorentzVector = G4LorentzVector(direction*p, e);
388    lorentzVector.boost(-boost);
389    *resultNucleus = G4Fragment(AF, ZF, lorentzVector);
390    fragmentVector->push_back(resultNucleus);
391  }
392//
393//
394// Provide verbose output on the ablation products if requested.
395//
396  if (verboseLevel >= 2)
397  {
398    if (nEvap > 0)
399    {
400      G4cout <<"----------------------" <<G4endl;
401      G4cout <<"Evaporated particles :" <<G4endl;
402      G4cout <<"----------------------" <<G4endl;
403    }
404    G4int ie = 0;
405    G4FragmentVector::iterator iter;
406    for (iter = fragmentVector->begin(); iter != fragmentVector->end(); iter++)
407    {
408      if (ie == nEvap)
409      {
410//        G4cout <<*iter  <<G4endl;
411        G4cout <<"---------------------------------" <<G4endl;
412        G4cout <<"Particles from default emission :" <<G4endl;
413        G4cout <<"---------------------------------" <<G4endl;
414      }
415      G4cout <<*iter <<G4endl;
416    }
417    G4cout <<"oooooooooooooooooooooooooooooooooooooooo"
418           <<"oooooooooooooooooooooooooooooooooooooooo"
419           <<G4endl;
420  }
421
422  return fragmentVector;   
423}
424////////////////////////////////////////////////////////////////////////////////
425//
426void G4WilsonAblationModel::SelectSecondariesByEvaporation
427  (G4Fragment *intermediateNucleus)
428{
429  G4Fragment theResidualNucleus = *intermediateNucleus;
430  G4bool evaporate = true;
431  while (evaporate && evapType.size() != 0)
432  {
433//
434//
435// Here's the cheaky bit.  We're hijacking the G4Evaporation model, in order to
436// more accurately sample to kinematics, but the species of the nuclear
437// fragments will be the ones of our choosing as above.
438//
439    std::vector <G4VEvaporationChannel*>  theChannels;
440    theChannels.clear();
441    std::vector <G4VEvaporationChannel*>::iterator i;
442    VectorOfFragmentTypes::iterator iter;
443    std::vector <VectorOfFragmentTypes::iterator> iters;
444    iters.clear();
445    iter = std::find(evapType.begin(), evapType.end(), G4Alpha::Alpha());
446    if (iter != evapType.end())
447    {
448      theChannels.push_back(new G4AlphaEvaporationChannel);
449      i = theChannels.end() - 1;
450      (*i)->SetOPTxs(OPTxs);
451      (*i)->UseSICB(useSICB);
452//      (*i)->Initialize(theResidualNucleus);
453      iters.push_back(iter);
454    }
455    iter = std::find(evapType.begin(), evapType.end(), G4He3::He3());
456    if (iter != evapType.end())
457    {
458      theChannels.push_back(new G4He3EvaporationChannel);
459      i = theChannels.end() - 1;
460      (*i)->SetOPTxs(OPTxs);
461      (*i)->UseSICB(useSICB);
462//      (*i)->Initialize(theResidualNucleus);
463      iters.push_back(iter);
464    }
465    iter = std::find(evapType.begin(), evapType.end(), G4Triton::Triton());
466    if (iter != evapType.end())
467    {
468      theChannels.push_back(new G4TritonEvaporationChannel);
469      i = theChannels.end() - 1;
470      (*i)->SetOPTxs(OPTxs);
471      (*i)->UseSICB(useSICB);
472//      (*i)->Initialize(theResidualNucleus);
473      iters.push_back(iter);
474    }
475    iter = std::find(evapType.begin(), evapType.end(), G4Deuteron::Deuteron());
476    if (iter != evapType.end())
477    {
478      theChannels.push_back(new G4DeuteronEvaporationChannel);
479      i = theChannels.end() - 1;
480      (*i)->SetOPTxs(OPTxs);
481      (*i)->UseSICB(useSICB);
482//      (*i)->Initialize(theResidualNucleus);
483      iters.push_back(iter);
484    }
485    iter = std::find(evapType.begin(), evapType.end(), G4Proton::Proton());
486    if (iter != evapType.end())
487    {
488      theChannels.push_back(new G4ProtonEvaporationChannel);
489      i = theChannels.end() - 1;
490      (*i)->SetOPTxs(OPTxs);
491      (*i)->UseSICB(useSICB);
492//      (*i)->Initialize(theResidualNucleus);
493      iters.push_back(iter);
494    }
495    iter = std::find(evapType.begin(), evapType.end(), G4Neutron::Neutron());
496    if (iter != evapType.end())
497    {
498      theChannels.push_back(new G4NeutronEvaporationChannel);
499      i = theChannels.end() - 1;
500      (*i)->SetOPTxs(OPTxs);
501      (*i)->UseSICB(useSICB);
502//      (*i)->Initialize(theResidualNucleus);
503      iters.push_back(iter);
504    }
505    G4int nChannels = theChannels.size();
506
507    std::vector<G4VEvaporationChannel*>::iterator iterEv;
508    for (iterEv=theChannels.begin(); iterEv!=theChannels.end(); iterEv++)
509      (*iterEv)->Initialize(*intermediateNucleus);
510    G4double totalProb = std::accumulate(theChannels.begin(),
511      theChannels.end(), 0.0, SumProbabilities());
512    if (totalProb > 0.0)
513    {
514//
515//
516// The emission probability for at least one of the evaporation channels is
517// positive, therefore work out which one should be selected and decay
518// the nucleus.
519//
520      G4double totalProb1      = 0.0;
521      G4double probEvapType[6] = {0.0};
522      for (G4int ich=0; ich<nChannels; ich++)
523      {
524        totalProb1      += theChannels[ich]->GetEmissionProbability();
525        probEvapType[ich]  = totalProb1 / totalProb;
526      }
527      G4double xi = G4UniformRand();
528      G4int i     = 0;
529      for (i=0; i<nChannels; i++)
530        if (xi < probEvapType[i]) break;
531      if (i > nChannels) i = nChannels - 1;
532      G4FragmentVector *evaporationResult = theChannels[i]->
533        BreakUp(*intermediateNucleus);
534      fragmentVector->push_back((*evaporationResult)[0]);
535      *intermediateNucleus = *(*evaporationResult)[1];
536      delete evaporationResult->back();
537      delete evaporationResult;
538      evapType.erase(iters[i]);
539    }
540    else
541    {
542//
543//
544// Probability for further evaporation is nil so have to escape from this
545// routine and set the energies of the secondaries to 10eV.
546//
547      evaporate = false;
548    }
549  }
550 
551  return;
552}
553////////////////////////////////////////////////////////////////////////////////
554//
555void G4WilsonAblationModel::SelectSecondariesByDefault (G4ThreeVector boost)
556{
557  for (unsigned i=0; i<evapType.size(); i++)
558  {
559    G4ParticleDefinition *type = evapType[i];
560    G4double mass              = type->GetPDGMass();
561    G4double e                 = mass + 10.0*eV;
562    G4double p                 = std::sqrt(e*e-mass*mass);
563    G4double costheta          = 2.0*G4UniformRand() - 1.0;
564    G4double sintheta          = std::sqrt((1.0 - costheta)*(1.0 + costheta));
565    G4double phi               = twopi * G4UniformRand() * rad;
566    G4ThreeVector direction(sintheta*std::cos(phi),sintheta*std::sin(phi),costheta);
567    G4LorentzVector lorentzVector = G4LorentzVector(direction*p, e);
568    lorentzVector.boost(-boost);
569// Possibility that the following line is not correctly carrying over A and Z
570// from particle definition.  Force values.  PRT 03/12/2009.
571//    G4Fragment *fragment          =
572//      new G4Fragment(lorentzVector, type);
573    G4int A = type->GetBaryonNumber();
574    G4int Z = (G4int) (type->GetPDGCharge() + 1.0E-10);
575    G4Fragment *fragment          = 
576      new G4Fragment(A, Z, lorentzVector);
577
578    fragmentVector->push_back(fragment);
579  }
580}
581////////////////////////////////////////////////////////////////////////////////
582//
583void G4WilsonAblationModel::PrintWelcomeMessage ()
584{
585  G4cout <<G4endl;
586  G4cout <<" *****************************************************************"
587         <<G4endl;
588  G4cout <<" Nuclear ablation model for nuclear-nuclear interactions activated"
589         <<G4endl;
590  G4cout <<" (Written by QinetiQ Ltd for the European Space Agency)"
591         <<G4endl;
592  G4cout <<" *****************************************************************"
593         <<G4endl;
594  G4cout << G4endl;
595
596  return;
597}
598////////////////////////////////////////////////////////////////////////////////
599//
Note: See TracBrowser for help on using the repository browser.