SLIC  6.1.1
Simulation for the Linear Collider (SLIC) - Geant4 simulation application
MCParticleManager.cc
Go to the documentation of this file.
1 #include "MCParticleManager.hh"
2 
3 // SLIC
4 #include "EventSourceManager.hh"
5 
6 // Geant4
7 #include "G4SystemOfUnits.hh"
8 #include "globals.hh"
9 #include "Randomize.hh"
10 
11 namespace slic {
12 
13 void MCParticleManager::generateEvent(LCCollectionVec* particles, G4Event* event) {
14 
15  _inputVec = particles;
16  _primaryVec = std::vector<G4PrimaryParticle*>(particles->size());
17 
18 #if SLIC_LOG
19  log() << LOG::debug << LOG::head << "generating event " << event->GetEventID() << " from " << particles->size() << " particles" << LOG::endl << LOG::done;
20 #endif
21 
22  // Apply Z smearing to input particles.
23 #if SLIC_LOG
24  log() << LOG::debug << "applying Z smearing: " << EventSourceManager::instance()->getZSmearing() << LOG::done;
25 #endif
27 
29 #if SLIC_LOG
30  log() << LOG::debug << "applying Lorentz transform: " << EventSourceManager::instance()->getLorentzTransformationAngle() << LOG::done;
31 #endif
32  applyLorentzTransformation(particles, EventSourceManager::instance()->getLorentzTransformationAngle());
33 
34 #if SLIC_LOG
35  log() << LOG::endl;
36 #endif
37 
38  // Loop over MCParticle input list.
39  for (size_t i = 0; i < particles->size(); i++) {
40 
41  // Get the next MCParticle.
42  MCParticle* mcp = (MCParticle*) (*particles)[i];
43 
44  // Debug print information about the particle.
45 #ifdef SLIC_LOG
46  log() << LOG::debug << "processing MC particle " << i << LOG::endl
47  << " PDG: " << mcp->getPDG() << LOG::endl
48  << " gen status: " << mcp->getGeneratorStatus() << LOG::endl
49  << " sim status: " << mcp->getSimulatorStatus() << LOG::endl
50  << " energy: " << mcp->getEnergy() << LOG::endl
51  << " time: " << mcp->getTime() << LOG::endl
52  << " daughters: " << mcp->getDaughters().size() << LOG::endl
53  << " vertex: ( " << mcp->getVertex()[0] << ", " << mcp->getVertex()[1] << ", " << mcp->getVertex()[2] << " )" << LOG::endl
54  << " p: ( " << mcp->getMomentum()[0] << ", " << mcp->getMomentum()[1] << ", " << mcp->getMomentum()[2] << " )" << LOG::endl
55  << " charge: " << mcp->getCharge() << LOG::endl
56  << " mass: " << mcp->getMass() << LOG::endl
57  << " daughters: " << mcp->getDaughters().size() << LOG::endl
58  << " parents: " << mcp->getParents().size() << LOG::endl
59  << LOG::done;
60 #endif
61 
62  // Only process particles without parents; daughters will be handled recursively.
63  if (mcp->getParents().size() == 0) {
64 
65 #ifdef SLIC_LOG
66  log() << LOG::debug << "creating new vertex for MCParticle " << i << LOG::done;
67 #endif
68 
69  // Create a new primary vertex.
70  G4PrimaryVertex* vertex = createVertex(mcp);
71 
72 #ifdef SLIC_LOG
73  if (vertex != 0) {
74  log() << LOG::debug << "created vertex for MCParticle " << i << " at " << vertex->GetPosition() << LOG::done;
75  } else {
76  log() << LOG::debug << "no new vertex created for particle " << i << LOG::done;
77  }
78 #endif
79 
80 #ifdef SLIC_LOG
81  log() << LOG::debug << "creating primary for MCParticle " << i << LOG::done;
82 #endif
83 
84  // Create a primary particle and recursively create primaries for its daughters.
85  const std::set<G4PrimaryParticle*> primaries = createPrimary(0, mcp);
86 
87 #ifdef SLIC_LOG
88  log() << LOG::debug << "found " << primaries.size() << " relevant primaries" << LOG::done;
89 #endif
90 
91  // Were any primaries created?
92  if (primaries.size() > 0) {
93 
94 #ifdef SLIC_LOG
95  log() << LOG::debug << "created " << primaries.size() << " for MCParticle " << i << LOG::done;
96 #endif
97 
98  // Loop over returned set of primary particles.
99  for (std::set<G4PrimaryParticle*>::const_iterator it = primaries.begin(); it != primaries.end(); it++) {
100 
101  // Is this a top-level particle with no daughters?
102  if (!MCParticleManager::isDaughter((*it), primaries)) {
103 
104 #ifdef SLIC_LOG
105  log () << LOG::debug << "found primary " << indexOf((*it)) << " with no parent" << LOG::done;
106 #endif
107 
108  // Create a new vertex if necessary.
109  if (vertex == 0) {
110 #ifdef SLIC_LOG
111  log() << "creating vertex for MCParticle " << indexOf(_mcpMap[(*it)]) << LOG::done;
112 #endif
113  // Create vertex by looking up MCParticle from the primary.
114  vertex = createVertex(_mcpMap[(*it)]);
115  }
116 
117  // Add the primary particle to the vertex.
118 #ifdef SLIC_LOG
119  log() << "setting primary " << indexOf((*it)) << " on vertex" << LOG::done;
120 #endif
121  vertex->SetPrimary(*it);
122  }
123  }
124 
125  // Add the vertex to the event.
126  log() << LOG::debug << "adding primary vertex to event" << LOG::done;
127  event->AddPrimaryVertex(vertex);
128 
129  } else {
130 #ifdef SLIC_LOG
131  log() << LOG::debug << "no primary created for " << i << LOG::done;
132 #endif
133  // No primaries created so this record and its daughters are skipped!
134  if (vertex != 0) {
135 #ifdef SLIC_LOG
136  log() << LOG::debug << "deleting empty vertex for particle " << i << LOG::done;
137 #endif
138  delete vertex;
139  }
140  }
141  }
142  }
143 
144 #ifdef SLIC_LOG
145  log() << LOG::endl << "generated " << _primaryVec.size() << " primaries" << LOG::endl;
146  for (std::vector<G4PrimaryParticle*>::iterator it = _primaryVec.begin();
147  it != _primaryVec.end();
148  it++) {
149  G4PrimaryParticle* primary = (*it);
150  if (primary != 0) {
151  log() << LOG::endl << LOG::debug << "created primary " << indexOf(primary) << LOG::endl
152  << " PDG: " << primary->GetPDGcode() << LOG::endl
153  << " mass: " << primary->GetMass() << LOG::endl
154  << " charge: " << primary->GetCharge() << LOG::endl
155  << " momentum: " << primary->GetMomentum() << LOG::endl
156  << " proper time: " << primary->GetProperTime() << LOG::endl
157  << " has dau: " << (primary->GetDaughter() != 0) << LOG::endl;
158  if (primary->GetDaughter() != 0) {
159  std::vector<int> dauIndices;
160  G4PrimaryParticle* daughter = primary->GetDaughter();
161  while (daughter) {
162  dauIndices.push_back(indexOf(daughter));
163  daughter = daughter->GetNext();
164  }
165  log() << " daughters: " << dauIndices << LOG::endl;
166  }
167  } /* else {
168  log() << "primary is null!" << LOG::endl;
169  } */
170  }
171 #endif
172 
173  // Register the collection of MCParticles that was created.
174  setMCParticleCollection(particles);
175 }
176 
177 std::set<G4PrimaryParticle*> MCParticleManager::createPrimary(G4PrimaryParticle* parent, MCParticle* mcp) {
178 
179  // The MCParticle argument should not be null.
180  if (mcp == 0) {
181  G4Exception("", "", FatalException, "MCParticle is null.");
182  }
183 
184  // Set of primaries that will be returned.
185  std::set<G4PrimaryParticle*> primaries;
186 
187  G4PrimaryParticle* primary = 0;
188 
189  // Is this primary not created yet and does it have a valid generator status?
190  if (_primaryMap.count(mcp) == 0 && (mcp->getGeneratorStatus() == 1 || mcp->getGeneratorStatus() == 2)) {
191 
192 #ifdef SLIC_LOG
193  log() << LOG::debug << "creating primary for MC particle " << indexOf(mcp) << LOG::done;
194 #endif
195 
196  // Create the primary particle from the MCParticle's information.
197  primary = new G4PrimaryParticle();
198  primary->SetPDGcode(mcp->getPDG());
199  primary->SetCharge(mcp->getCharge());
200  primary->SetMass(mcp->getMass() * GeV);
201  const double* p = mcp->getMomentum();
202  primary->SetMomentum(p[0] * GeV, p[1] * GeV, p[2] * GeV);
203 
204  // Set the proper time by subtracting from first daughter's time.
205  if (mcp->getDaughters().size() > 0) {
206 #ifdef SLIC_LOG
207  log() << LOG::debug << "MCParticle " << indexOf(mcp) << " has "
208  << mcp->getDaughters().size() << " daughters " << LOG::done;
209 #endif
210 
211  MCParticle* dp = mcp->getDaughters()[0];
212  double properTime = fabs((dp->getTime() - mcp->getTime()) * mcp->getMass()) / mcp->getEnergy();
213  primary->SetProperTime(properTime * ns);
214 
215 #ifdef SLIC_LOG
216  log() << LOG::debug << "proper time for MCParticle " << indexOf(mcp) << " set to " << (properTime * ns) << LOG::done;
217 #endif
218  }
219 
220  // Map primary to MCParticle.
221  _primaryMap[mcp] = primary;
222 
223  // Map MCParticle to primary.
224  _mcpMap[primary] = mcp;
225 
226  // DEBUG: store index of primary matching the MCParticle
227  _primaryVec[indexOf(mcp)] = primary;
228 
229  if (parent != 0) {
230  parent->SetDaughter(primary);
231 #ifdef SLIC_LOG
232  log() << LOG::debug << "added dau primary " << MCParticleManager::indexOf(primary) << " to parent "
234 #endif
235  } else {
236 #ifdef SLIC_LOG
237  log() << LOG::debug << "skipping create primary on DOC particle" << LOG::done;
238 #endif
239  }
240 
241  primaries.insert(primary);
242 
243  // DEBUG: print primary info
244 #ifdef SLIC_LOG
245  if (primary != 0) {
246  log() << LOG::endl << LOG::debug << "created primary " << indexOf(primary) << LOG::endl
247  << " PDG: " << primary->GetPDGcode() << LOG::endl
248  << " mass: " << primary->GetMass() << LOG::endl
249  << " charge: " << primary->GetCharge() << LOG::endl
250  << " momentum: " << primary->GetMomentum() << LOG::endl
251  << " proper time: " << primary->GetProperTime() << LOG::endl
252  << " has dau: " << (primary->GetDaughter() != 0) << LOG::endl
253  << LOG::done;
254  }
255 #endif
256 
257  } else {
258 #ifdef SLIC_LOG
259  if (_primaryMap.count(mcp) == 0) {
260  log() << LOG::debug << "primary was already created for MCParticle " << MCParticleManager::indexOf(mcp) << LOG::done;
261  }
262 #endif
263  }
264 
265  for (int i = 0; i < mcp->getDaughters().size(); i++) {
266 #ifdef SLIC_LOG
267  log() << LOG::debug << "recursively creating primaries for " << indexOf(primary) << LOG::done;
268 #endif
269  std::set<G4PrimaryParticle*> daughters = createPrimary(primary, mcp->getDaughters()[i]);
270 #ifdef SLIC_LOG
271  log() << LOG::debug << "created " << daughters.size() << " daughter primaries" << LOG::done;
272 #endif
273 
274  if (daughters.size() > 0) {
275  primaries.insert(daughters.begin(), daughters.end());
276  }
277  }
278 #ifdef SLIC_LOG
279  log().getOutputStream().flush();
280 #endif
281 
282  return primaries;
283 }
284 
285 G4PrimaryVertex* MCParticleManager::createVertex(MCParticle* mcp) {
286 
287  G4PrimaryVertex* vertex = 0;
288 
289  if (mcp->getGeneratorStatus() == 1 || mcp->getGeneratorStatus() == 2) {
290 
291 #ifdef SLIC_LOG
292  log() << LOG::debug << "creating vertex for MC particle " << indexOf(mcp) << LOG::done;
293 #endif
294 
295  // Get the particle's origin.
296  const double* particleVertex = mcp->getVertex();
297  G4ThreeVector particlePosition(particleVertex[0], particleVertex[1], particleVertex[2]);
298 
299  // Get the particle's time.
300  G4double particleTime = mcp->getTime();
301 
302  // Create a new vertex for this particle.
303  vertex = new G4PrimaryVertex(particlePosition, particleTime);
304 
305 #ifdef SLIC_LOG
306  log() << LOG::debug << LOG::endl << "created vertex for " << indexOf(mcp) << LOG::endl
307  << " position: " << vertex->GetPosition() << LOG::endl
308  << " time: " << particleTime << LOG::endl
309  << LOG::done;
310 #endif
311  } else {
312 #ifdef SLIC_LOG
313  log() << LOG::debug << "skipped vertex creation for DOC particle " << indexOf(mcp) << LOG::done;
314 #endif
315  }
316 
317  return vertex;
318 }
319 
320 void MCParticleManager::applyLorentzTransformation(LCCollection* particles, const G4double alpha) {
321 
322  if (alpha == 0) {
323  return; // nothing to do
324  }
325 
326  // parameters of the Lorentz transformation matrix
327  const G4double gamma = sqrt(1 + sqr(tan(alpha)));
328  const G4double betagamma = tan(alpha);
329 
330  if (particles != 0) {
331 
332  int nMCP = particles->getNumberOfElements();
333 
334  for (int i = 0; i < nMCP; ++i) {
335 
336  IMPL::MCParticleImpl* mcp = dynamic_cast<IMPL::MCParticleImpl*>(particles->getElementAt(i));
337 
338  const double* p = mcp->getMomentum();
339 
340  // before the transformation
341  double pPrime[3];
342 
343  const G4double m = mcp->getMass();
344 
345  //G4cout << "pre pX: " << p[0] << G4endl;
346 
347  // after the transformation (boost in x-direction)
348  pPrime[0] = betagamma * sqrt(sqr(p[0]) + sqr(p[1]) + sqr(p[2]) + sqr(m)) + gamma * p[0];
349  pPrime[1] = p[1];
350  pPrime[2] = p[2];
351 
352  //G4cout << "transformed pX: " << pPrime[0] << G4endl;
353 
354  // py and pz remain the same, E changes implicitly with px
355  mcp->setMomentum(pPrime);
356  }
357  }
358 }
359 
360 G4double MCParticleManager::smearZPosition(const G4double rms) {
361  G4double z = 0;
362  if (rms != 0) {
363  // Generate smeared Z position.
364  z = G4RandGauss::shoot(0, rms/mm);
365  //G4cout << "Smeared Z position: " << z << G4endl;
366  }
367  return z;
368 }
369 
370 bool MCParticleManager::isDaughter(G4PrimaryParticle* particle, const std::set<G4PrimaryParticle*>& primaries) {
371  for (std::set<G4PrimaryParticle*>::iterator it = primaries.begin(); it != primaries.end(); it++) {
372  G4PrimaryParticle* dau = (*it)->GetDaughter();
373  while (dau != 0) {
374  if (dau == particle) {
375  return true;
376  }
377  dau = dau->GetNext();
378  }
379  }
380  return false;
381 }
382 
383 }
384 ;
static EventSourceManager * instance()
ostream & getOutputStream() const
Definition: LogStream.hh:143
int indexOf(MCParticle *particle)
std::vector< G4PrimaryParticle * > _primaryVec
void applyLorentzTransformation(LCCollection *mcparticles, const G4double angle)
void generateEvent(LCCollectionVec *mcparticles, G4Event *event)
PrimaryParticleMap _primaryMap
G4double smearZPosition(const G4double rms)
void setMCParticleCollection(LCCollectionVec *mcpVec)
LCCollectionVec * _inputVec
std::set< G4PrimaryParticle * > createPrimary(G4PrimaryParticle *parent, MCParticle *mcp)
G4PrimaryVertex * createVertex(MCParticle *mcp)
bool isDaughter(G4PrimaryParticle *particle, const std::set< G4PrimaryParticle * > &primaries)
LogStream & log()
Definition: Module.hh:99
@ debug
Definition: LogStream.hh:33
@ head
Definition: LogStream.hh:26
@ endl
Definition: LogStream.hh:26
@ done
Definition: LogStream.hh:26