LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
MuNuclearSplittingProcessXSecBias.cxx
Go to the documentation of this file.
1 //
2 // This(these) is (are) a variance reduction technique(s).
3 //
4 //
5 // Secondary biasing code adapted from EventBiasing from Jane Tinslay, SLAC. 2008.
6 // (Who's now at Cisco, I think.) XSBiasing code from http://geant4.cern.ch/collaboration/workshops/workshop2002/slides/docs/flei/biasing.pdf. (And NOT from http://www.lcsim.org/software/geant4/doxygen/html/classG4HadronicProcess.html, where I *believe* the point is to bias primaries and secondaries from sub-classes of Cross-Sections in an already chosen
7 // broader class of XSs. This doesn't help us. We need more occurrences (albeit with small
8 // weights) of a specific process.
9 //
10 //
11 // The point is to create Nsplit secondaries with each muNucl process, so
12 // that we may, e.g., create many, otherwise-rare, K0s which
13 // may charge exchange into pernicious K+s which then mimic proton dk. And,
14 // additionally now to make the XSection for the muNucl process itself higher,
15 // keeping track of appropriate weights everywhere.
16 //
17 // echurch@fnal.gov, May, 2011.
18 //
19 
20 
22 
23 #include "Geant4/G4WrapperProcess.hh"
24 #include "Geant4/G4VParticleChange.hh"
25 #include "Geant4/G4SDManager.hh"
26 #include "Geant4/G4RunManager.hh"
27 #include "Geant4/G4Event.hh"
28 #include "Geant4/G4HCofThisEvent.hh"
29 #include "Geant4/G4Track.hh"
30 #include "Geant4/G4Step.hh"
31 #include "Geant4/G4TrackStatus.hh"
32 #include "Geant4/G4ParticleDefinition.hh"
33 #include "Geant4/G4ParticleTypes.hh"
34 #include "Geant4/Randomize.hh"
35 #include "Geant4/G4KaonZeroLong.hh"
36 #include "Geant4/G4ios.hh"
37 
38 #include "cetlib_except/exception.h"
39 
40 #include <TMath.h>
41 
42 namespace larg4 {
43 
44 
45 
46  G4VParticleChange* MuNuclearSplittingProcessXSecBias::PostStepDoIt(const G4Track& track, const G4Step& step)
47  {
48 
49  G4VParticleChange* pChange = pRegProcess->PostStepDoIt( track, step );
50  pChange->SetVerboseLevel(0);
51  pChange->SetSecondaryWeightByProcess(true);
52 
53  G4double secWeight = 1.0;
54  if (fNSplit>=1) secWeight = 1.0/fNSplit;
55  std::vector<G4Track*> secondaries; // Secondary store
56 
57  G4double nw=1.0;
58  // Let's go bias the underlying xsection.
59  if(xBiasMode==1)
60  {
61  G4double s = step.GetStepLength();
62  G4double x = pRegProcess->GetCurrentInteractionLength();
63  nw = pChange->GetParentWeight();
64  // need to undo the change made to the parent track in
65  // most recent step (1/wc).
66  // It seems to be possible to get here w.o. first having hit the
67  // AlongStep Method that initialied wc. So protect against division y 0.
68  if (wc < 1.0e-10) wc = 1.0;
69  nw *= 1/wc * (1. - exp(-s/x))/(1 - exp(-eFactor*s/x)) ;
70  G4cout << " MNSPXSB.PostStepDoit(): original wt = " << pChange->GetParentWeight() << " eF = " << eFactor << G4endl;
71  G4cout << " MNSPXSB.PostStepDoit(): New weight = " << nw << " wc = " << wc << " s= " << s <<" x = " << x << G4endl;
72  ((G4ParticleChange*)pChange)->ProposeParentWeight(nw) ;
73  }
74  else if (xBiasMode==2)
75  {
76  nw = pChange->GetParentWeight()*XBiasSecondaryWeight();
77  ((G4ParticleChange*)pChange)->ProposeParentWeight(nw) ;
78  // for (G4int i = 0; i < pChange->GetNumberOfSecondaries(); i++)
79  //pChange->GetSecondary(i)->SetWeight(nw);
80  if(G4UniformRand()<XBiasSurvivalProbability())
81  { // need to add the primary back in to balance the weight
82  // the position of the extra track should be moved to the next volume, but I don't know how yet.
83  // need to change number of secondary first before adding an additional track
84  pChange->SetNumberOfSecondaries(pChange->GetNumberOfSecondaries()+1);
85  G4ThreeVector mDirection = track.GetDynamicParticle()->GetMomentumDirection();
86  G4DynamicParticle* aD = new G4DynamicParticle((track.GetDynamicParticle())->GetDefinition(),
87  G4LorentzVector(mDirection,
88  (track.GetDynamicParticle())->GetKineticEnergy()+step.GetTotalEnergyDeposit()));
89  G4Track* secTrk = new G4Track(aD,step.GetDeltaTime(),step.GetDeltaPosition());
90  pChange->AddSecondary(secTrk);
91  pChange->GetSecondary(pChange->GetNumberOfSecondaries()-1)->
92  SetWeight(XBiasSurvivalProbability()*track.GetWeight());
93  }
94  else
95  {
96  nw = track.GetWeight();
97  pChange->ProposeParentWeight(nw);
98  }
99  }
100 
101  secWeight = secWeight*nw;
102 
103  // Loop over PostStepDoIt method to generate multiple secondaries.
104  // The point is for each value of ii up to Nsplit we want to re-toss
105  // all secondaries for the muNucl process. Each toss gives back numSec
106  // secondaries, which will be a different sample of species/momenta each time.
107  G4VParticleChange* particleChange = new G4VParticleChange();
108 
109  for (unsigned int ii=0; ii<(unsigned int)fNSplit; ii++) {
110  particleChange = pRegProcess->PostStepDoIt(track, step);
111  if (!particleChange)
112  throw std::runtime_error("MuNuclearSplittingProcessXSecBias::PostStepDoIt(): no particle change");
113  G4int j(0);
114  G4int numSec(particleChange->GetNumberOfSecondaries());
115  // Don't change weight of last secondary. It's the just-added primary in this mode.
116  for (j=0; j<numSec; j++)
117  {
118  G4Track* newSec = new G4Track(*(particleChange->GetSecondary(j)));
119  G4String pdgstr = newSec->GetParticleDefinition()->GetParticleName();
120  //G4double ke = newSec->GetKineticEnergy()/GeV;
121  G4int pdg = newSec->GetParticleDefinition()->GetPDGEncoding();
122  if (abs(pdg)==310 ||abs(pdg)==311 || abs(pdg)==3122 || abs(pdg)==2112)
123  {
124  // std::cout << "MuNuclSplProc: Creating " << pdgstr << " of Kinetic Energy " << ke << " GeV. numSec is " << j << std::endl;
125 
126  if (pdg==G4KaonZeroShort::KaonZeroShort()->GetPDGEncoding()&&G4UniformRand()<0.50)
127  {
128  pdg = G4KaonZeroLong::KaonZeroLong()->GetPDGEncoding();
129  pdgstr = G4KaonZeroLong::KaonZeroLong()->GetParticleName();
130  G4LorentzVector pK0L(newSec->GetMomentum(),TMath::Sqrt(TMath::Power(G4KaonZeroLong::KaonZeroLong()->GetPDGMass(),2)+TMath::Power(newSec->GetMomentum().mag(),2)));
131  G4DynamicParticle *newK0L = new G4DynamicParticle(G4KaonZeroLong::KaonZeroLong(),pK0L);
132 
133  G4Track* newSecK0L = new G4Track(newK0L,track.GetGlobalTime(),track.GetPosition());
134  secondaries.push_back(newSecK0L);
135  }
136  else
137  {
138  secondaries.push_back(newSec);
139  }
140  }
141  }
142  }
143 
144  pChange->SetNumberOfSecondaries(secondaries.size());
145  pChange->SetSecondaryWeightByProcess(true);
146  //pChange->ProposeTrackStatus(fStopAndKill); // End of the story for this muon.
147 
148  //int numSecAdd = secondaries.size();
149  std::vector<G4Track*>::iterator iter = secondaries.begin(); // Add all secondaries
150  while (iter != secondaries.end()) {
151  G4Track* myTrack = *iter;
152  G4String pdgstr = myTrack->GetParticleDefinition()->GetParticleName();
153  G4double ke = myTrack->GetKineticEnergy()/CLHEP::GeV;
154  G4int pdg = myTrack->GetParticleDefinition()->GetPDGEncoding();
155  if (abs(pdg)==130 ||abs(pdg)==310 ||abs(pdg)==311 || abs(pdg)==3122 || abs(pdg)==2112)
156  {
157  if (pdg!=2112)
158  std::cout << "MuNuclSplXSB(): Adding " << pdgstr << " of Kinetic Energy and weight " << ke << " GeV and " << secWeight << "." << std::endl;
159 
160  myTrack->SetWeight(secWeight);
161  pChange->AddSecondary(myTrack);
162  }
163  iter++;
164  }
165  return pChange;
166 
167  }
168 
170  const G4Track& track,
171  const G4Step& step
172  )
173  {
174 
175  wc = 1.0;
176 
177  if (xBiasMode==2)
178  {
179  /* I don't understand this. If I new it and Initialize(track) it works, but
180  it goes off and grinds through the event.
181  If I try to use pRegProcess->AlongStepDoIt() it crashes
182  at the GetParentWeight() just below.
183  */
184  G4VParticleChange* pC = new G4VParticleChange();
185  pC->Initialize(track);
186  //pC = pRegProcess->AlongStepDoIt( track, step);
187 
188  G4double nw = pC->GetParentWeight()*XBiasSecondaryWeight();
189  pC->ProposeParentWeight(nw) ;
190  for (G4int i = 0; i < pC->GetNumberOfSecondaries(); i++)
191  pC->GetSecondary(i)->SetWeight(nw);
192  //
193  if(G4UniformRand()<XBiasSurvivalProbability())
194  {
195  pC->SetNumberOfSecondaries(pC->GetNumberOfSecondaries()+1);
196  G4ThreeVector mDirection = track.GetDynamicParticle()->GetMomentumDirection();
197  G4DynamicParticle* aD = new G4DynamicParticle((track.GetDynamicParticle())->GetDefinition(),
198  G4LorentzVector(mDirection,
199  (track.GetDynamicParticle())->GetKineticEnergy()+step.GetTotalEnergyDeposit()));
200  G4Track* secTrk = new G4Track(aD,track.GetGlobalTime(),track.GetPosition()); // +step.GetDeltaTime(), ,+step.GetDeltaPosition()
201  secTrk->SetGoodForTrackingFlag(true);
202  pC->AddSecondary(secTrk); // Add the primary right back.
203  pC->GetSecondary(pC->GetNumberOfSecondaries()-1)->SetWeight(XBiasSurvivalProbability()*track.GetWeight());
204  //pC->ProposeTrackStatus(fStopAndKill); // 8-June-2011-21:36 MDT, from Finland, I (EDC) added this. Seems right. Makes it go, anyway. Almost too fast.
205  }
206 
207  return pC;
208  }
209  else if (xBiasMode==1)
210  {
211  fParticleChange.Initialize(track) ;
212  G4double s = step.GetStepLength();
213  G4double x = pRegProcess->GetCurrentInteractionLength();
214  //fParticleChange = &(pRegProcess->AlongStepDoIt( track, step));
215  wc = exp(-(1. - eFactor)*s/x);
216  G4double w = wc * fParticleChange.GetParentWeight();
217  fParticleChange.SetParentWeightByProcess(false);
218  fParticleChange.ProposeParentWeight(w) ;
219  if (w>100)
220  {
221  // G4cout << " MNSPXSB.AlongStepDoit(): GPW is " << w/wc << " wc = " << wc << ", CIL = "<< x << G4endl;
222  }
223 
224  return &fParticleChange;
225  }
226 
227  if (xBiasMode!=1 && xBiasMode!=2)
228  {
229  throw cet::exception("Incorrectly set Bias Mode. ")
230  << "Set XBiasMode to 0 or 1. " << xBiasMode << " not allowed!\n";
231  }
232  fParticleChange.Initialize(track) ;
233  return &fParticleChange;
234  }
235 
236 
238  {
239  G4double result = 0;
240  G4double nLTraversed = GetTotalNumberOfInteractionLengthTraversed();
241  G4double biasedProbability = 1.-std::exp(-nLTraversed);
242  G4double realProbability = 1-std::exp(-nLTraversed/eFactor);
243  result = (biasedProbability-realProbability)/biasedProbability;
244  return result;
245  }
246 
248  {
249  G4double result = 0;
250  G4double nLTraversed = GetTotalNumberOfInteractionLengthTraversed();
251  result = 1./eFactor*std::exp(-nLTraversed/eFactor*(1-1./eFactor));
252  return result;
253  }
254 
255 
257  {
259  -G4VProcess::theNumberOfInteractionLengthLeft;
260  }
261 
262 
264  G4double previousStepSize,
265  G4ForceCondition* condition )
266  {
267  // I believe this is the money line for the whole thing. By shrinking the
268  // interaction length in MuNuclear's process, it's more likely that
269  // this process will be chosen in the competition among processes.
270  if(xBiasMode)
271  {
272  G4double psgPIL = (1./eFactor) * pRegProcess->PostStepGetPhysicalInteractionLength(
273  track,
274  previousStepSize,
275  condition );
276  return psgPIL;
277  }
278 
279  return pRegProcess->PostStepGetPhysicalInteractionLength(
280  track,
281  previousStepSize,
282  condition );
283 
284 }
285 
286 
288  G4double previousStepSize,
289  G4double currentMinimumStep,
290  G4double& proposedSafety,
291  G4GPILSelection* selection )
292 {
293  if (xBiasMode==2)
294  {
295  // I am pretty sure this mode does not work because MuNuclear doesn't interact
296  // AlongStep. Below often (always?) returns a negative number, which I have to
297  // swizzle.
298  G4double intLen;
299  intLen = (1./eFactor) *
300  pRegProcess->AlongStepGetPhysicalInteractionLength( track,previousStepSize,
301  currentMinimumStep,proposedSafety,selection);
302  if (intLen<0) return currentMinimumStep;
303  else return intLen;
304  }
305  else
306  return DBL_MAX ;
307 }
308 
309 
310 } // end namespace
Float_t x
Definition: compare.C:6
Float_t s
Definition: plot.C:23
virtual G4double PostStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4ForceCondition *condition)
intermediate_table::iterator iterator
Geant4 interface.
Check of Geant4 to run the LArSoft detector simulation.
virtual G4double AlongStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double &proposedSafety, G4GPILSelection *selection)
G4VParticleChange * AlongStepDoIt(const G4Track &track, const G4Step &step)
Float_t e
Definition: plot.C:34
Float_t track
Definition: plot.C:34
Float_t w
Definition: plot.C:23
G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &step)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33