Belle II Software development
G4LongLivedNeutralDecay.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9// modified from BelleII monopole simulation
10
11#include <simulation/longlivedneutral/G4LongLivedNeutral.h>
12#include <simulation/longlivedneutral/G4LongLivedNeutralDecay.h>
13
14#include "G4PhysicalConstants.hh"
15#include "G4SystemOfUnits.hh"
16#include "G4DynamicParticle.hh"
17#include "G4PrimaryParticle.hh"
18#include "G4DecayProducts.hh"
19#include "G4DecayTable.hh"
20#include "G4VDecayChannel.hh"
21#include "G4PhysicsLogVector.hh"
22#include "G4ParticleChangeForDecay.hh"
23
24
25using namespace Belle2;
26
27// constructor
29 : G4VRestDiscreteProcess(processName, fDecay),
30 verboseLevel(1),
31 HighestValue(20.0),
32 fRemainderLifeTime(-1.0)
33
34{
35 // set Process Sub Type
36 SetProcessSubType(static_cast<int>(DECAY));
37
38#ifdef G4VERBOSE
39 if (GetVerboseLevel() > 1) {
40 G4cout << "G4LongLivedNeutralDecay constructor " << " Name:" << processName << G4endl;
41 }
42#endif
43
44 pParticleChange = &fParticleChangeForDecay;
45}
46
48{
49
50}
51
52G4bool G4LongLivedNeutralDecay::IsApplicable(const G4ParticleDefinition& aParticleType)
53{
54 // original G4Decay checks for particle definition mass and lifetime, which are zero for generality
55 // the correct mass and lifetime are set for the G4PrimaryParticle
56 if (!aParticleType.GetPDGStable()) {
57 return true;
58 } else return false;
59}
60
61
62G4double G4LongLivedNeutralDecay::GetMeanLifeTime(const G4Track& aTrack,
63 G4ForceCondition*)
64{
65 const G4DynamicParticle* dynamicParticle = aTrack.GetDynamicParticle();
66 const G4PrimaryParticle* primaryParticle = dynamicParticle->GetPrimaryParticle();
67 G4double pTime = primaryParticle->GetProperTime();
68
69 return pTime;
70}
71
72G4double G4LongLivedNeutralDecay::GetMeanFreePath(const G4Track& aTrack, G4double, G4ForceCondition*)
73{
74
75 const G4DynamicParticle* dynamicParticle = aTrack.GetDynamicParticle();
76 const G4PrimaryParticle* primaryParticle = dynamicParticle->GetPrimaryParticle();
77 G4double pTime = primaryParticle->GetProperTime();
78 G4double aMass = primaryParticle->GetMass();
79 G4double aMomentum = primaryParticle->GetTotalMomentum();
80 return c_light * pTime * aMomentum / aMass;
81}
82
83void G4LongLivedNeutralDecay::BuildPhysicsTable(const G4ParticleDefinition&)
84{
85 return;
86}
87
88G4VParticleChange* G4LongLivedNeutralDecay::DecayIt(const G4Track& aTrack, const G4Step&)
89{
90 // The DecayIt() method returns by pointer a particle-change object.
91 // Units are expressed in GEANT4 internal units.
92 // Initialize ParticleChange
93 // all members of G4VParticleChange are set to equal to
94 // corresponding member in G4Track
95//
96
97 fParticleChangeForDecay.Initialize(aTrack);
98
99 // LongLivedNeutral: work only with DynamicParticle, not ParticleDefinition
100 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
101 const G4PrimaryParticle* aPrimaryParticle = aParticle->GetPrimaryParticle();
102
103 //check if thePreAssignedDecayProducts exists
104 const G4DecayProducts* o_products = (aParticle->GetPreAssignedDecayProducts());
105 G4bool isPreAssigned = (o_products != nullptr);
106 G4DecayProducts* products = nullptr;
107
108 if (isPreAssigned) {
109 // default: copy decay products
110 products = new G4DecayProducts(*o_products);
111 } else {
112 // Should not happen, since interaction and free path length are set to max
113 G4ExceptionDescription ed;
114 ed << "LongLivedNeutral particle:"
115 << " decay probability exist but no pre-assigned decay products defined "
116 << "- the particle will be killed;\n";
117 G4Exception("G4LongLivedNeutralDecay::DecayIt ",
118 "DECAY101", JustWarning, ed);
119
120 fParticleChangeForDecay.SetNumberOfSecondaries(0);
121 // Kill the parent particle
122 fParticleChangeForDecay.ProposeTrackStatus(fStopAndKill) ;
123 fParticleChangeForDecay.ProposeLocalEnergyDeposit(0.0);
124
125 ClearNumberOfInteractionLengthLeft();
127 }
128
129 // get parent particle information ...................................
130 G4double ParentEnergy = aPrimaryParticle->GetTotalEnergy();
131 G4double ParentMass = aPrimaryParticle->GetMass();
132 if (ParentEnergy < ParentMass) {
133 G4ExceptionDescription ed;
134 ed << "Total Energy is less than its mass - increased the energy"
135 << "\n Particle: " << "LongLivedNeutral"
136 << "\n Energy:" << ParentEnergy / MeV << "[MeV]"
137 << "\n Mass:" << ParentMass / MeV << "[MeV]";
138 G4Exception("G4LongLivedNeutralDecay::DecayIt ",
139 "DECAY102", JustWarning, ed);
140 ParentEnergy = ParentMass;
141 }
142
143 G4ThreeVector ParentDirection(aPrimaryParticle->GetMomentumDirection());
144
145 // assign a new parent to the products from info of the primary particle
146 const G4DynamicParticle dParticle(aPrimaryParticle->GetParticleDefinition(),
147 aPrimaryParticle->GetMomentumDirection(),
148 aPrimaryParticle->GetKineticEnergy(),
149 aPrimaryParticle->GetMass());
150
151 products->SetParentParticle(dParticle);
152 //boost all decay products to laboratory frame
153 G4double energyDeposit = 0.0;
154 G4double finalGlobalTime = aTrack.GetGlobalTime();
155 G4double finalLocalTime = aTrack.GetLocalTime();
156 if (aTrack.GetTrackStatus() == fStopButAlive) {
157 // AtRest case
158 finalGlobalTime += fRemainderLifeTime;
159 finalLocalTime += fRemainderLifeTime;
160 energyDeposit += aPrimaryParticle->GetKineticEnergy();
161 products->Boost(ParentEnergy, ParentDirection);
162 } else {
163 // default for LongLivedNeutral: PostStep case (decay in flight)
164 products->Boost(ParentEnergy, ParentDirection);
165 }
166
167 //add products in fParticleChangeForDecay
168 G4int numberOfSecondaries = products->entries();
169 fParticleChangeForDecay.SetNumberOfSecondaries(numberOfSecondaries);
170#ifdef G4VERBOSE
171 if (GetVerboseLevel() > 1) {
172 G4cout << "G4LongLivedNeutralDecay::DoIt : Decay vertex :";
173 G4cout << " Time: " << finalGlobalTime / ns << "[ns]";
174 G4cout << " proper time: " << finalLocalTime / ns << "[ns]";
175 G4cout << " X:" << (aTrack.GetPosition()).getX() / cm << "[cm]";
176 G4cout << " Y:" << (aTrack.GetPosition()).getY() / cm << "[cm]";
177 G4cout << " Z:" << (aTrack.GetPosition()).getZ() / cm << "[cm]";
178 G4cout << G4endl;
179 G4cout << "G4LongLivedNeutralDecay::DoIt : decay products in Lab. Frame" << G4endl;
180 products->DumpInfo();
181 }
182#endif
183
184 G4int index;
185 G4ThreeVector currentPosition;
186 const G4TouchableHandle thand = aTrack.GetTouchableHandle();
187 for (index = 0; index < numberOfSecondaries; index++) {
188 // get current position of the track
189 currentPosition = aTrack.GetPosition();
190 // create a new track object
191 G4Track* secondary = new G4Track(products->PopProducts(),
192 finalGlobalTime,
193 currentPosition);
194 // switch on good for tracking flag
195 secondary->SetGoodForTrackingFlag();
196 secondary->SetTouchableHandle(thand);
197 // add the secondary track in the List
198 fParticleChangeForDecay.AddSecondary(secondary);
199 }
200 delete products;
201
202 // Kill the parent particle
203 fParticleChangeForDecay.ProposeTrackStatus(fStopAndKill) ;
204 fParticleChangeForDecay.ProposeLocalEnergyDeposit(energyDeposit);
205 fParticleChangeForDecay.ProposeLocalTime(finalLocalTime);
206
207 // Clear NumberOfInteractionLengthLeft
208 ClearNumberOfInteractionLengthLeft();
209
211}
212
213
215{
216 currentInteractionLength = -1.0;
217 ResetNumberOfInteractionLengthLeft();
218
219
220 fRemainderLifeTime = -1.0;
221}
222
224{
225 // Clear NumberOfInteractionLengthLeft
226 ClearNumberOfInteractionLengthLeft();
227
228 currentInteractionLength = -1.0;
229}
230
231
233 const G4Track& track,
234 G4double previousStepSize,
235 G4ForceCondition* condition
236)
237{
238 // condition is set to "Not Forced"
239 *condition = NotForced;
240
241 // pre-assigned Decay time
242 G4double pTime = track.GetDynamicParticle()->GetPrimaryParticle()->GetProperTime();
243 if (pTime >= 0.) {
244 // default for LongLived Particle: pre-assigned decay time case
245 fRemainderLifeTime = pTime - track.GetProperTime();
246 if (fRemainderLifeTime <= 0.0) fRemainderLifeTime = 0.0;
247
248 // use normalized kinetic energy (= Ekin/mass)
249 G4double rvalue = c_light * fRemainderLifeTime;
250 const G4DynamicParticle* dynamicParticle = track.GetDynamicParticle();
251 const G4PrimaryParticle* primaryParticle = dynamicParticle->GetPrimaryParticle();
252 G4double aMass = primaryParticle->GetMass();
253 G4double aMomentum = primaryParticle->GetTotalMomentum();
254 rvalue *= aMomentum / aMass;
255 return rvalue;
256
257 } else {
258 // no pre-assigned proper decay time --> stable
259 return previousStepSize * DBL_MAX;
260 }
261}
262
264 const G4Track& track,
265 G4ForceCondition* condition
266)
267{
268 // condition is set to "Not Forced"
269 *condition = NotForced;
270 G4double pTime = track.GetDynamicParticle()->GetPrimaryParticle()->GetProperTime();
271 if (pTime >= 0.) {
272 // general case for LongLivedNeutral
273 fRemainderLifeTime = pTime - track.GetProperTime();
274 if (fRemainderLifeTime <= 0.0) fRemainderLifeTime = DBL_MIN;
275 } else {
276 // LongLivedNeutral case: set stable if there is no pre-assigned decay time
277 fRemainderLifeTime = 1e24 * s;
278 }
279 return fRemainderLifeTime;
280}
281
282
284 const G4Track& aTrack,
285 const G4Step& aStep
286)
287{
288 if ((aTrack.GetTrackStatus() == fStopButAlive) ||
289 (aTrack.GetTrackStatus() == fStopAndKill)) {
290 fParticleChangeForDecay.Initialize(aTrack);
292 } else {
293 return DecayIt(aTrack, aStep);
294 }
295}
296
virtual G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep) override
G4VProcess::PostStepDoIt() implemention.
virtual G4double GetMeanFreePath(const G4Track &aTrack, G4double previousStepSize, G4ForceCondition *condition) override
GetMeanFreePath returns ctau*beta*gamma for decay in flight.
virtual G4double PostStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4ForceCondition *condition) override
G4VProcess::PostStepGetPhysicalInteractionLength() implemention.
virtual G4double AtRestGetPhysicalInteractionLength(const G4Track &track, G4ForceCondition *condition) override
G4VProcess::AtRestGetPhysicalInteractionLength() implemention.
G4ParticleChangeForDecay fParticleChangeForDecay
ParticleChange for decay process.
G4LongLivedNeutralDecay(const G4String &processName="LongLivedNeutralDecay")
Constructor.
G4double fRemainderLifeTime
ParticleChange for decay process.
virtual void EndTracking() override
inform End of tracking for each track to the physics process
virtual G4VParticleChange * DecayIt(const G4Track &aTrack, const G4Step &aStep)
G4Decay::DecayIt() implemention.
virtual G4double GetMeanLifeTime(const G4Track &aTrack, G4ForceCondition *condition) override
GetMeanLifeTime returns ctau for decay at rest.
virtual G4bool IsApplicable(const G4ParticleDefinition &) override
returns "true" if the decay process can be applied to the particle type.
virtual void BuildPhysicsTable(const G4ParticleDefinition &) override
In G4Decay, thePhysicsTable stores values of beta * std::sqrt( 1 - beta*beta) as a function of normal...
virtual void StartTracking(G4Track *) override
inform Start of tracking for each track to the physics process
Abstract base class for different kinds of events.