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

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

geant4 tag 9.4

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  fragmentVector = 0;
153}
154////////////////////////////////////////////////////////////////////////////////
155//
156G4WilsonAblationModel::~G4WilsonAblationModel()
157{
158  if (theChannels != 0) theChannels = 0;
159  if (theChannelFactory != 0) delete theChannelFactory;
160}
161////////////////////////////////////////////////////////////////////////////////
162//
163G4FragmentVector *G4WilsonAblationModel::BreakItUp
164  (const G4Fragment &theNucleus)
165{
166//
167//
168// Initilise the pointer to the G4FragmentVector used to return the information
169// about the breakup.
170//
171  fragmentVector = new G4FragmentVector;
172  fragmentVector->clear();
173//
174//
175// Get the A, Z and excitation of the nucleus.
176//
177  G4int A     = (G4int) theNucleus.GetA();
178  G4int Z     = (G4int) theNucleus.GetZ();
179  G4double ex = theNucleus.GetExcitationEnergy();
180  if (verboseLevel >= 2)
181  {
182    G4cout <<"oooooooooooooooooooooooooooooooooooooooo"
183           <<"oooooooooooooooooooooooooooooooooooooooo"
184           <<G4endl;
185    G4cout.precision(6);
186    G4cout <<"IN G4WilsonAblationModel" <<G4endl;
187    G4cout <<"Initial prefragment A=" <<A
188           <<", Z=" <<Z
189           <<", excitation energy = " <<ex/MeV <<" MeV"
190           <<G4endl; 
191  }
192//
193//
194// Check that there is a nucleus to speak of.  It's possible there isn't one
195// or its just a proton or neutron.  In either case, the excitation energy
196// (from the Lorentz vector) is not used.
197//
198  if (A == 0)
199  {
200    if (verboseLevel >= 2)
201    {
202      G4cout <<"No nucleus to decay" <<G4endl;
203      G4cout <<"oooooooooooooooooooooooooooooooooooooooo"
204             <<"oooooooooooooooooooooooooooooooooooooooo"
205             <<G4endl;
206    }
207    return fragmentVector;
208  }
209  else if (A == 1)
210  {
211    G4LorentzVector lorentzVector = theNucleus.GetMomentum();
212    lorentzVector.setE(lorentzVector.e()-ex+10.0*eV);
213    if (Z == 0)
214    {
215      G4Fragment *fragment = new G4Fragment(lorentzVector,G4Neutron::Neutron());
216      fragmentVector->push_back(fragment);
217    }
218    else
219    {
220      G4Fragment *fragment = new G4Fragment(lorentzVector,G4Proton::Proton());
221      fragmentVector->push_back(fragment);
222    }
223    if (verboseLevel >= 2)
224    {
225      G4cout <<"Final fragment is in fact only a nucleon) :" <<G4endl;
226      G4cout <<(*fragmentVector)[0] <<G4endl;
227      G4cout <<"oooooooooooooooooooooooooooooooooooooooo"
228             <<"oooooooooooooooooooooooooooooooooooooooo"
229             <<G4endl;
230    }
231    return fragmentVector;
232  }
233//
234//
235// Then the number of nucleons ablated (either as nucleons or light nuclear
236// fragments) is based on a simple argument for the binding energy per nucleon.
237//
238  G4int DAabl = (G4int) (ex / B);
239  if (DAabl > A) DAabl = A;
240// The following lines are no longer accurate given we now treat the final fragment
241//  if (verboseLevel >= 2)
242//    G4cout <<"Number of nucleons ejected = " <<DAabl <<G4endl;
243
244//
245//
246// Determine the nuclear fragment from the ablation process by sampling the
247// Rudstam equation.
248//
249  G4int AF = A - DAabl;
250  G4int ZF = 0;
251  if (AF > 0)
252  {
253    G4double AFd = (G4double) AF;
254    G4double R = 11.8 / std::pow(AFd, 0.45);
255    G4int minZ = Z - DAabl;
256    if (minZ <= 0) minZ = 1;
257//
258//
259// Here we define an integral probability distribution based on the Rudstam
260// equation assuming a constant AF.
261//   
262    G4double sig[100];
263    G4double sum = 0.0;
264    for (G4int ii=minZ; ii<= Z; ii++)
265    {
266      sum   += std::exp(-R*std::pow(std::abs(ii - 0.486*AFd + 3.8E-04*AFd*AFd),1.5));
267      sig[ii] = sum;
268    }
269//
270//
271// Now sample that distribution to determine a value for ZF.
272//
273    G4double xi  = G4UniformRand();
274    G4int iz     = minZ;
275    G4bool found = false;
276    while (iz <= Z && !found)
277    {
278      found = (xi <= sig[iz]/sum);
279      if (!found) iz++;
280    }
281    if (iz > Z)
282      ZF = Z;
283    else
284      ZF = iz;
285  }
286  G4int DZabl = Z - ZF;
287//
288//
289// Now determine the nucleons or nuclei which have bee ablated.  The preference
290// is for the production of alphas, then other nuclei in order of decreasing
291// binding energy. The energies assigned to the products of the decay are
292// provisional for the moment (the 10eV is just to avoid errors with negative
293// excitation energies due to rounding).
294//
295  G4double totalEpost = 0.0;
296  evapType.clear();
297  for (G4int ift=0; ift<nFragTypes; ift++)
298  {
299    G4ParticleDefinition *type = fragType[ift];
300    G4double n  = std::floor((G4double) DAabl / type->GetBaryonNumber() + 1.0E-10);
301    G4double n1 = 1.0E+10;
302    if (fragType[ift]->GetPDGCharge() > 0.0)
303      n1 = std::floor((G4double) DZabl / type->GetPDGCharge() + 1.0E-10);
304    if (n > n1) n = n1;
305    if (n > 0.0)
306    {
307      G4double mass = type->GetPDGMass();
308      for (G4int j=0; j<(G4int) n; j++)
309      {
310        totalEpost += mass;
311        evapType.push_back(type);
312      }
313      DAabl -= (G4int) (n * type->GetBaryonNumber() + 1.0E-10);
314      DZabl -= (G4int) (n * type->GetPDGCharge() + 1.0E-10);
315    }
316  }
317//
318//
319// Determine the properties of the final nuclear fragment.  Note that if
320// the final fragment is predicted to have a nucleon number of zero, then
321// really it's the particle last in the vector evapType which becomes the
322// final fragment.  Therefore delete this from the vector if this is the
323// case.
324//
325  G4double massFinalFrag = 0.0;
326  if (AF > 0)
327    massFinalFrag = G4ParticleTable::GetParticleTable()->GetIonTable()->
328      GetIonMass(ZF,AF);
329  else
330  {
331    G4ParticleDefinition *type = evapType[evapType.size()-1];
332    AF                         = type->GetBaryonNumber();
333    ZF                         = (G4int) (type->GetPDGCharge() + 1.0E-10);
334    evapType.erase(evapType.end()-1);
335  }
336  totalEpost   += massFinalFrag;
337//
338//
339// Provide verbose output on the nuclear fragment if requested.
340//
341  if (verboseLevel >= 2)
342  {
343    G4cout <<"Final fragment      A=" <<AF
344           <<", Z=" <<ZF
345           <<G4endl;
346    for (G4int ift=0; ift<nFragTypes; ift++)
347    {
348      G4ParticleDefinition *type = fragType[ift];
349      G4int n                    = std::count(evapType.begin(),evapType.end(),type);
350      if (n > 0) 
351        G4cout <<"Particle type: " <<std::setw(10) <<type->GetParticleName()
352               <<", number of particles emitted = " <<n <<G4endl;
353    }
354  }
355//
356// Add the total energy from the fragment.  Note that the fragment is assumed
357// to be de-excited and does not undergo photo-evaporation .... I did mention
358// this is a bit of a crude model?
359//
360  G4double massPreFrag      = theNucleus.GetGroundStateMass();
361  G4double totalEpre        = massPreFrag + ex;
362  G4double excess           = totalEpre - totalEpost;
363//  G4Fragment *resultNucleus(theNucleus);
364  G4Fragment *resultNucleus = new G4Fragment(A, Z, theNucleus.GetMomentum());
365  G4ThreeVector boost(0.0,0.0,0.0);
366  G4int nEvap = 0;
367  if (produceSecondaries && evapType.size()>0)
368  {
369    if (excess > 0.0)
370    {
371      SelectSecondariesByEvaporation (resultNucleus);
372      nEvap = fragmentVector->size();
373      boost = resultNucleus->GetMomentum().findBoostToCM();
374      if (evapType.size() > 0)
375        SelectSecondariesByDefault (boost);
376    }
377    else
378      SelectSecondariesByDefault(G4ThreeVector(0.0,0.0,0.0));
379  }
380
381  if (AF > 0)
382  {
383    G4double mass = G4ParticleTable::GetParticleTable()->GetIonTable()->
384      GetIonMass(ZF,AF);
385    G4double e    = mass + 10.0*eV;
386    G4double p    = std::sqrt(e*e-mass*mass);
387    G4ThreeVector direction(0.0,0.0,1.0);
388    G4LorentzVector lorentzVector = G4LorentzVector(direction*p, e);
389    lorentzVector.boost(-boost);
390    *resultNucleus = G4Fragment(AF, ZF, lorentzVector);
391    fragmentVector->push_back(resultNucleus);
392  }
393//
394//
395// Provide verbose output on the ablation products if requested.
396//
397  if (verboseLevel >= 2)
398  {
399    if (nEvap > 0)
400    {
401      G4cout <<"----------------------" <<G4endl;
402      G4cout <<"Evaporated particles :" <<G4endl;
403      G4cout <<"----------------------" <<G4endl;
404    }
405    G4int ie = 0;
406    G4FragmentVector::iterator iter;
407    for (iter = fragmentVector->begin(); iter != fragmentVector->end(); iter++)
408    {
409      if (ie == nEvap)
410      {
411//        G4cout <<*iter  <<G4endl;
412        G4cout <<"---------------------------------" <<G4endl;
413        G4cout <<"Particles from default emission :" <<G4endl;
414        G4cout <<"---------------------------------" <<G4endl;
415      }
416      G4cout <<*iter <<G4endl;
417    }
418    G4cout <<"oooooooooooooooooooooooooooooooooooooooo"
419           <<"oooooooooooooooooooooooooooooooooooooooo"
420           <<G4endl;
421  }
422
423  return fragmentVector;   
424}
425////////////////////////////////////////////////////////////////////////////////
426//
427void G4WilsonAblationModel::SelectSecondariesByEvaporation
428  (G4Fragment *intermediateNucleus)
429{
430  G4Fragment theResidualNucleus = *intermediateNucleus;
431  G4bool evaporate = true;
432  while (evaporate && evapType.size() != 0)
433  {
434//
435//
436// Here's the cheaky bit.  We're hijacking the G4Evaporation model, in order to
437// more accurately sample to kinematics, but the species of the nuclear
438// fragments will be the ones of our choosing as above.
439//
440    std::vector <G4VEvaporationChannel*>  theChannels;
441    theChannels.clear();
442    std::vector <G4VEvaporationChannel*>::iterator i;
443    VectorOfFragmentTypes::iterator iter;
444    std::vector <VectorOfFragmentTypes::iterator> iters;
445    iters.clear();
446    iter = std::find(evapType.begin(), evapType.end(), G4Alpha::Alpha());
447    if (iter != evapType.end())
448    {
449      theChannels.push_back(new G4AlphaEvaporationChannel);
450      i = theChannels.end() - 1;
451      (*i)->SetOPTxs(OPTxs);
452      (*i)->UseSICB(useSICB);
453//      (*i)->Initialize(theResidualNucleus);
454      iters.push_back(iter);
455    }
456    iter = std::find(evapType.begin(), evapType.end(), G4He3::He3());
457    if (iter != evapType.end())
458    {
459      theChannels.push_back(new G4He3EvaporationChannel);
460      i = theChannels.end() - 1;
461      (*i)->SetOPTxs(OPTxs);
462      (*i)->UseSICB(useSICB);
463//      (*i)->Initialize(theResidualNucleus);
464      iters.push_back(iter);
465    }
466    iter = std::find(evapType.begin(), evapType.end(), G4Triton::Triton());
467    if (iter != evapType.end())
468    {
469      theChannels.push_back(new G4TritonEvaporationChannel);
470      i = theChannels.end() - 1;
471      (*i)->SetOPTxs(OPTxs);
472      (*i)->UseSICB(useSICB);
473//      (*i)->Initialize(theResidualNucleus);
474      iters.push_back(iter);
475    }
476    iter = std::find(evapType.begin(), evapType.end(), G4Deuteron::Deuteron());
477    if (iter != evapType.end())
478    {
479      theChannels.push_back(new G4DeuteronEvaporationChannel);
480      i = theChannels.end() - 1;
481      (*i)->SetOPTxs(OPTxs);
482      (*i)->UseSICB(useSICB);
483//      (*i)->Initialize(theResidualNucleus);
484      iters.push_back(iter);
485    }
486    iter = std::find(evapType.begin(), evapType.end(), G4Proton::Proton());
487    if (iter != evapType.end())
488    {
489      theChannels.push_back(new G4ProtonEvaporationChannel);
490      i = theChannels.end() - 1;
491      (*i)->SetOPTxs(OPTxs);
492      (*i)->UseSICB(useSICB);
493//      (*i)->Initialize(theResidualNucleus);
494      iters.push_back(iter);
495    }
496    iter = std::find(evapType.begin(), evapType.end(), G4Neutron::Neutron());
497    if (iter != evapType.end())
498    {
499      theChannels.push_back(new G4NeutronEvaporationChannel);
500      i = theChannels.end() - 1;
501      (*i)->SetOPTxs(OPTxs);
502      (*i)->UseSICB(useSICB);
503//      (*i)->Initialize(theResidualNucleus);
504      iters.push_back(iter);
505    }
506    G4int nChannels = theChannels.size();
507
508    std::vector<G4VEvaporationChannel*>::iterator iterEv;
509    for (iterEv=theChannels.begin(); iterEv!=theChannels.end(); iterEv++)
510      (*iterEv)->Initialize(*intermediateNucleus);
511    G4double totalProb = std::accumulate(theChannels.begin(),
512      theChannels.end(), 0.0, SumProbabilities());
513    if (totalProb > 0.0)
514    {
515//
516//
517// The emission probability for at least one of the evaporation channels is
518// positive, therefore work out which one should be selected and decay
519// the nucleus.
520//
521      G4double totalProb1      = 0.0;
522      G4double probEvapType[6] = {0.0};
523      for (G4int ich=0; ich<nChannels; ich++)
524      {
525        totalProb1      += theChannels[ich]->GetEmissionProbability();
526        probEvapType[ich]  = totalProb1 / totalProb;
527      }
528      G4double xi = G4UniformRand();
529      G4int i     = 0;
530      for (i=0; i<nChannels; i++)
531        if (xi < probEvapType[i]) break;
532      if (i > nChannels) i = nChannels - 1;
533      G4FragmentVector *evaporationResult = theChannels[i]->
534        BreakUp(*intermediateNucleus);
535      fragmentVector->push_back((*evaporationResult)[0]);
536      *intermediateNucleus = *(*evaporationResult)[1];
537      delete evaporationResult->back();
538      delete evaporationResult;
539      evapType.erase(iters[i]);
540    }
541    else
542    {
543//
544//
545// Probability for further evaporation is nil so have to escape from this
546// routine and set the energies of the secondaries to 10eV.
547//
548      evaporate = false;
549    }
550  }
551 
552  return;
553}
554////////////////////////////////////////////////////////////////////////////////
555//
556void G4WilsonAblationModel::SelectSecondariesByDefault (G4ThreeVector boost)
557{
558  for (unsigned i=0; i<evapType.size(); i++)
559  {
560    G4ParticleDefinition *type = evapType[i];
561    G4double mass              = type->GetPDGMass();
562    G4double e                 = mass + 10.0*eV;
563    G4double p                 = std::sqrt(e*e-mass*mass);
564    G4double costheta          = 2.0*G4UniformRand() - 1.0;
565    G4double sintheta          = std::sqrt((1.0 - costheta)*(1.0 + costheta));
566    G4double phi               = twopi * G4UniformRand() * rad;
567    G4ThreeVector direction(sintheta*std::cos(phi),sintheta*std::sin(phi),costheta);
568    G4LorentzVector lorentzVector = G4LorentzVector(direction*p, e);
569    lorentzVector.boost(-boost);
570// Possibility that the following line is not correctly carrying over A and Z
571// from particle definition.  Force values.  PRT 03/12/2009.
572//    G4Fragment *fragment          =
573//      new G4Fragment(lorentzVector, type);
574    G4int A = type->GetBaryonNumber();
575    G4int Z = (G4int) (type->GetPDGCharge() + 1.0E-10);
576    G4Fragment *fragment          = 
577      new G4Fragment(A, Z, lorentzVector);
578
579    fragmentVector->push_back(fragment);
580  }
581}
582////////////////////////////////////////////////////////////////////////////////
583//
584void G4WilsonAblationModel::PrintWelcomeMessage ()
585{
586  G4cout <<G4endl;
587  G4cout <<" *****************************************************************"
588         <<G4endl;
589  G4cout <<" Nuclear ablation model for nuclear-nuclear interactions activated"
590         <<G4endl;
591  G4cout <<" (Written by QinetiQ Ltd for the European Space Agency)"
592         <<G4endl;
593  G4cout <<" *****************************************************************"
594         <<G4endl;
595  G4cout << G4endl;
596
597  return;
598}
599////////////////////////////////////////////////////////////////////////////////
600//
Note: See TracBrowser for help on using the repository browser.