ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4Decay.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4Decay.cc
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 //
27 //
28 //
29 // --------------------------------------------------------------
30 // GEANT 4 class implementation file
31 //
32 // History: first implementation, based on object model of
33 // 2nd December 1995, G.Cosmo
34 // 7 July 1996 H.Kurashige
35 // ------------------------------------------------------------
36 // remove BuildPhysicsTable() 28 Nov. 1997 H.Kurashige
37 // change DBL_EPSIRON to DBL_MIN 14 Dec. 1997 H.Kurashige
38 // modified for new ParticleChange 12 Mar. 1998 H.Kurashige
39 // modified for "GoodForTrackingFlag" 19 June 1998 H.Kurashige
40 // rename thePhysicsTable to aPhyscisTable 2 Aug. 1998 H.Kurashige
41 // modified IsApplicable in order to protect the decay from registered
42 // to resonances 12 Dec. 1998 H.Kurashige
43 // remove G4ParticleMomentum 6 Feb. 99 H.Kurashige
44 // modified IsApplicable to activate G4Decay for resonances 1 Mar. 00 H.Kurashige
45 // Add External Decayer 23 Feb. 2001 H.Kurashige
46 // change LowestBinValue,HighestBinValue and TotBin(200) 9 Feb. 2002
47 //
48 
49 #include "G4Decay.hh"
50 
51 #include "G4PhysicalConstants.hh"
52 #include "G4SystemOfUnits.hh"
53 #include "G4DynamicParticle.hh"
54 #include "G4DecayProducts.hh"
55 #include "G4DecayTable.hh"
56 #include "G4VDecayChannel.hh"
57 #include "G4PhysicsLogVector.hh"
59 #include "G4VExtDecayer.hh"
60 
61 // constructor
62 G4Decay::G4Decay(const G4String& processName)
63  :G4VRestDiscreteProcess(processName, fDecay),
64  verboseLevel(1),
65  HighestValue(20.0),
66  fRemainderLifeTime(-1.0),
67  pExtDecayer(nullptr)
68 {
69  // set Process Sub Type
70  SetProcessSubType(static_cast<int>(DECAY));
71 
72 #ifdef G4VERBOSE
73  if (GetVerboseLevel()>1) {
74  G4cout << "G4Decay constructor " << " Name:" << processName << G4endl;
75  }
76 #endif
77 
79 }
80 
82 {
83  if (pExtDecayer != nullptr) {
84  delete pExtDecayer;
85  }
86 }
87 
89 {
90  // check if the particle is stable?
91  if (aParticleType.GetPDGLifeTime() <0.0) {
92  return false;
93  } else if (aParticleType.GetPDGMass() <= 0.0*MeV) {
94  return false;
95  } else {
96  return true;
97  }
98 }
99 
102 {
103  // returns the mean free path in GEANT4 internal units
104  G4double meanlife;
105 
106  // get particle
107  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
108  const G4ParticleDefinition* aParticleDef = aParticle->GetDefinition();
109  G4double aLife = aParticleDef->GetPDGLifeTime();
110 
111  // check if the particle is stable?
112  if (aParticleDef->GetPDGStable()) {
113  //1000000 times the life time of the universe
114  meanlife = 1e24 * s;
115 
116  } else {
117  meanlife = aLife;
118  }
119 
120 #ifdef G4VERBOSE
121  if (GetVerboseLevel()>1) {
122  G4cout << "mean life time: "<< meanlife/ns << "[ns]" << G4endl;
123  }
124 #endif
125 
126  return meanlife;
127 }
128 
130 {
131  // get particle
132  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
133  const G4ParticleDefinition* aParticleDef = aParticle->GetDefinition();
134  G4double aMass = aParticle->GetMass();
135  G4double aLife = aParticleDef->GetPDGLifeTime();
136 
137 
138  // returns the mean free path in GEANT4 internal units
139  G4double pathlength;
140  G4double aCtau = c_light * aLife;
141 
142  // check if the particle is stable?
143  if (aParticleDef->GetPDGStable()) {
144  pathlength = DBL_MAX;
145 
146  //check if the particle has very short life time ?
147  } else if (aCtau < DBL_MIN) {
148  pathlength = DBL_MIN;
149 
150  } else {
151  //calculate the mean free path
152  // by using normalized kinetic energy (= Ekin/mass)
153  G4double rKineticEnergy = aParticle->GetKineticEnergy()/aMass;
154  if ( rKineticEnergy > HighestValue) {
155  // gamma >> 1
156  pathlength = ( rKineticEnergy + 1.0)* aCtau;
157  } else if ( rKineticEnergy < DBL_MIN ) {
158  // too slow particle
159 #ifdef G4VERBOSE
160  if (GetVerboseLevel()>1) {
161  G4cout << "G4Decay::GetMeanFreePath() !!particle stops!!";
162  G4cout << aParticleDef->GetParticleName() << G4endl;
163  G4cout << "KineticEnergy:" << aParticle->GetKineticEnergy()/GeV <<"[GeV]";
164  }
165 #endif
166  pathlength = DBL_MIN;
167  } else {
168  // beta <1
169  pathlength = (aParticle->GetTotalMomentum())/aMass*aCtau ;
170  }
171  }
172  return pathlength;
173 }
174 
176 {
177  return;
178 }
179 
181 {
182  // The DecayIt() method returns by pointer a particle-change object.
183  // Units are expressed in GEANT4 internal units.
184 
185  // Initialize ParticleChange
186  // all members of G4VParticleChange are set to equal to
187  // corresponding member in G4Track
189 
190  // get particle
191  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
192  const G4ParticleDefinition* aParticleDef = aParticle->GetDefinition();
193 
194  // check if the particle is stable
195  if (aParticleDef->GetPDGStable()) return &fParticleChangeForDecay ;
196 
197 
198  //check if thePreAssignedDecayProducts exists
199  const G4DecayProducts* o_products = (aParticle->GetPreAssignedDecayProducts());
200  G4bool isPreAssigned = (o_products != nullptr);
201  G4DecayProducts* products = nullptr;
202 
203  // decay table
204  G4DecayTable *decaytable = aParticleDef->GetDecayTable();
205 
206  // check if external decayer exists
207  G4bool isExtDecayer = (decaytable == nullptr) && (pExtDecayer != nullptr);
208 
209  // Error due to NO Decay Table
210  if ( (decaytable == nullptr) && !isExtDecayer && !isPreAssigned ){
211  if (GetVerboseLevel()>0) {
212  G4cout << "G4Decay::DoIt : decay table not defined for ";
213  G4cout << aParticle->GetDefinition()->GetParticleName()<< G4endl;
214  }
216  ed << "For " << aParticle->GetDefinition()->GetParticleName()
217  << " decay probability exist but decay table is not defined "
218  << "- the particle will be killed;\n"
219  << " isExtDecayer: " << isExtDecayer
220  << "; isPreAssigned: " << isPreAssigned;
221  G4Exception( "G4Decay::DecayIt ",
222  "DECAY101",JustWarning, ed);
223 
225  // Kill the parent particle
228 
230  return &fParticleChangeForDecay ;
231  }
232 
233  if (isPreAssigned) {
234  // copy decay products
235  products = new G4DecayProducts(*o_products);
236  } else if ( isExtDecayer ) {
237  // decay according to external decayer
238  products = pExtDecayer->ImportDecayProducts(aTrack);
239  } else {
240  // Decay according to decay table.
241  // Keep trying to choose a candidate decay channel if the dynamic mass
242  // of the decaying particle is below the sum of the PDG masses of the
243  // candidate daughter particles.
244  // This is needed because the decay table used in Geant4 is based on
245  // the assumption of nominal PDG masses, but a wide resonance can have
246  // a dynamic masses well below its nominal PDG masses, and therefore
247  // some of its decay channels can be below the kinematical threshold.
248  // Note that, for simplicity, we ignore here the possibility that
249  // one or more of the candidate daughter particles can be, in turn,
250  // wide resonance. However, if this is the case, and the channel is
251  // accepted, then the masses of the resonance daughter particles will
252  // be sampled by taking into account their widths.
253  G4VDecayChannel* decaychannel = nullptr;
254  G4double massParent = aParticle->GetMass();
255  decaychannel = decaytable->SelectADecayChannel(massParent);
256  if ( decaychannel == nullptr) {
257  // decay channel not found
259  ed << "Can not determine decay channel for "
260  << aParticleDef->GetParticleName() << G4endl
261  << " mass of dynamic particle: "
262  << massParent/GeV << " (GEV)" << G4endl
263  << " dacay table has " << decaytable->entries()
264  << " entries" << G4endl;
265  G4double checkedmass=massParent;
266  if (massParent < 0.) {
267  checkedmass=aParticleDef->GetPDGMass();
268  ed << "Using PDG mass ("<<checkedmass/GeV
269  << "(GeV)) in IsOKWithParentMass" << G4endl;
270  }
271  for (G4int ic =0;ic <decaytable->entries();++ic) {
272  G4VDecayChannel * dc= decaytable->GetDecayChannel(ic);
273  ed << ic << ": BR " << dc->GetBR() << ", IsOK? "
274  << dc->IsOKWithParentMass(checkedmass)
275  << ", --> ";
276  G4int ndaughters=dc->GetNumberOfDaughters();
277  for (G4int id=0;id<ndaughters;++id) {
278  if (id>0) ed << " + "; // seperator, except for first
279  ed << dc->GetDaughterName(id);
280  }
281  ed << G4endl;
282  }
283  G4Exception("G4Decay::DoIt", "DECAY003", FatalException,ed);
284  } else {
285  // execute DecayIt()
286 #ifdef G4VERBOSE
287  G4int temp = decaychannel->GetVerboseLevel();
288  if (GetVerboseLevel()>1) {
289  G4cout << "G4Decay::DoIt : selected decay channel addr:"
290  << decaychannel <<G4endl;
291  decaychannel->SetVerboseLevel(GetVerboseLevel());
292  }
293 #endif
294  products = decaychannel->DecayIt(aParticle->GetMass());
295 #ifdef G4VERBOSE
296  if (GetVerboseLevel()>1) {
297  decaychannel->SetVerboseLevel(temp);
298  }
299 #endif
300 #ifdef G4VERBOSE
301  if (GetVerboseLevel()>2) {
302  if (! products->IsChecked() ) products->DumpInfo();
303  }
304 #endif
305  }
306  }
307 
308  // get parent particle information ...................................
309  G4double ParentEnergy = aParticle->GetTotalEnergy();
310  G4double ParentMass = aParticle->GetMass();
311  if (ParentEnergy < ParentMass) {
313  ed << "Total Energy is less than its mass - increased the energy"
314  << "\n Particle: " << aParticle->GetDefinition()->GetParticleName()
315  << "\n Energy:" << ParentEnergy/MeV << "[MeV]"
316  << "\n Mass:" << ParentMass/MeV << "[MeV]";
317  G4Exception( "G4Decay::DecayIt ",
318  "DECAY102",JustWarning, ed);
319  ParentEnergy = ParentMass;
320  }
321 
322  G4ThreeVector ParentDirection(aParticle->GetMomentumDirection());
323 
324  //boost all decay products to laboratory frame
325  G4double energyDeposit = 0.0;
326  G4double finalGlobalTime = aTrack.GetGlobalTime();
327  G4double finalLocalTime = aTrack.GetLocalTime();
328  if (aTrack.GetTrackStatus() == fStopButAlive ){
329  // AtRest case
330  finalGlobalTime += fRemainderLifeTime;
331  finalLocalTime += fRemainderLifeTime;
332  energyDeposit += aParticle->GetKineticEnergy();
333  if (isPreAssigned) products->Boost( ParentEnergy, ParentDirection);
334  } else {
335  // PostStep case
336  if (!isExtDecayer) products->Boost( ParentEnergy, ParentDirection);
337  }
338  // set polarization for daughter particles
339  DaughterPolarization(aTrack, products);
340 
341 
342  //add products in fParticleChangeForDecay
343  G4int numberOfSecondaries = products->entries();
344  fParticleChangeForDecay.SetNumberOfSecondaries(numberOfSecondaries);
345 #ifdef G4VERBOSE
346  if (GetVerboseLevel()>1) {
347  G4cout << "G4Decay::DoIt : Decay vertex :";
348  G4cout << " Time: " << finalGlobalTime/ns << "[ns]";
349  G4cout << " X:" << (aTrack.GetPosition()).x() /cm << "[cm]";
350  G4cout << " Y:" << (aTrack.GetPosition()).y() /cm << "[cm]";
351  G4cout << " Z:" << (aTrack.GetPosition()).z() /cm << "[cm]";
352  G4cout << G4endl;
353  G4cout << "G4Decay::DoIt : decay products in Lab. Frame" << G4endl;
354  products->DumpInfo();
355  }
356 #endif
357  G4int index;
358  G4ThreeVector currentPosition;
359  const G4TouchableHandle thand = aTrack.GetTouchableHandle();
360  for (index=0; index < numberOfSecondaries; index++){
361  // get current position of the track
362  currentPosition = aTrack.GetPosition();
363  // create a new track object
364  G4Track* secondary = new G4Track( products->PopProducts(),
365  finalGlobalTime ,
366  currentPosition );
367  // switch on good for tracking flag
368  secondary->SetGoodForTrackingFlag();
369  secondary->SetTouchableHandle(thand);
370  // add the secondary track in the List
372  }
373  delete products;
374 
375  // Kill the parent particle
378  fParticleChangeForDecay.ProposeLocalTime( finalLocalTime );
379 
380  // Clear NumberOfInteractionLengthLeft
382 
383  return &fParticleChangeForDecay ;
384 }
385 
387 {
388  // empty implementation
389 }
390 
391 
392 
394 {
397 
398  fRemainderLifeTime = -1.0;
399 }
400 
402 {
403  // Clear NumberOfInteractionLengthLeft
405 
407 }
408 
409 
411  const G4Track& track,
412  G4double previousStepSize,
414  )
415 {
416  // condition is set to "Not Forced"
417  *condition = NotForced;
418 
419  // pre-assigned Decay time
422 
423  if (pTime < 0.) {
424  // normal case
425  if ( previousStepSize > 0.0){
426  // subtract NumberOfInteractionLengthLeft
427  SubtractNumberOfInteractionLengthLeft(previousStepSize);
430  }
432  }
433  // get mean free path
434  currentInteractionLength = GetMeanFreePath(track, previousStepSize, condition);
435 
436 #ifdef G4VERBOSE
437  if ((currentInteractionLength <=0.0) || (verboseLevel>2)){
438  G4cout << "G4Decay::PostStepGetPhysicalInteractionLength " << G4endl;
439  track.GetDynamicParticle()->DumpInfo();
440  G4cout << " in Material " << track.GetMaterial()->GetName() <<G4endl;
441  G4cout << "MeanFreePath = " << currentInteractionLength/cm << "[cm]" <<G4endl;
442  }
443 #endif
444 
445  G4double value;
448  //fRemainderLifeTime = theNumberOfInteractionLengthLeft*aLife;
449  } else {
450  value = DBL_MAX;
451  }
452 
453  return value;
454 
455  } else {
456  //pre-assigned Decay time case
457  // reminder proper time
458  fRemainderLifeTime = pTime - track.GetProperTime();
459  if (fRemainderLifeTime <= 0.0) fRemainderLifeTime = 0.0;
460 
461  G4double rvalue=0.0;
462  // use pre-assigned Decay time to determine PIL
463  if (aLife>0.0) {
464  // ordinary particle
465  rvalue = (fRemainderLifeTime/aLife)*GetMeanFreePath(track, previousStepSize, condition);
466  } else {
467  // shortlived particle
468  rvalue = c_light * fRemainderLifeTime;
469  // by using normalized kinetic energy (= Ekin/mass)
470  G4double aMass = track.GetDynamicParticle()->GetMass();
471  rvalue *= track.GetDynamicParticle()->GetTotalMomentum()/aMass;
472  }
473  return rvalue;
474  }
475 }
476 
478  const G4Track& track,
480  )
481 {
482  // condition is set to "Not Forced"
483  *condition = NotForced;
484 
486  if (pTime >= 0.) {
487  fRemainderLifeTime = pTime - track.GetProperTime();
489  } else {
492  }
493  return fRemainderLifeTime;
494 }
495 
496 
498 {
499  pExtDecayer = val;
500 
501  // set Process Sub Type
502  if ( pExtDecayer !=0 ) {
503  SetProcessSubType(static_cast<int>(DECAY_External));
504  }
505 }
506 
508  const G4Track& aTrack,
509  const G4Step& aStep
510  )
511 {
512  if ( (aTrack.GetTrackStatus() == fStopButAlive ) ||
513  (aTrack.GetTrackStatus() == fStopAndKill ) ){
515  return &fParticleChangeForDecay;
516  } else {
517  return DecayIt(aTrack, aStep);
518  }
519 }
520 
521 void G4Decay::ProcessDescription(std::ostream& outFile) const
522 {
523  outFile << GetProcessName() << ": Decay of particles. \n"
524  << "kinematics of daughters are dertermined by DecayChannels "
525  << " or by PreAssignedDecayProducts\n";
526 }