ATLAS Offline Software
G4HadIntProcessor.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Class Header
7 
8 // ISF
17 
18 #include <G4HadronElasticProcess.hh>
19 
20 // Trk inlcude
22 
23 // Geant4
24 #include "G4Material.hh"
25 #include "G4RunManager.hh"
26 #include "G4ParticleGun.hh"
27 #include "G4Box.hh"
28 #include "G4LogicalVolume.hh"
29 #include "G4PVPlacement.hh"
30 #include "QGSP_BERT.hh"
31 #include "QGSP_BIC.hh"
32 #include "FTFP_BERT.hh"
33 #include "G4UImanager.hh"
34 #include "G4NistManager.hh"
35 #include "G4VEnergyLossProcess.hh"
36 #include <G4MaterialCutsCouple.hh>
37 #include <G4HadronInelasticProcess.hh>
38 
39 #include "globals.hh"
40 #include "G4CrossSectionDataStore.hh"
41 #include "G4Element.hh"
42 #include "G4ElementVector.hh"
43 #include "G4IsotopeVector.hh"
44 #include "G4Neutron.hh"
45 #include "G4ProductionCutsTable.hh"
46 #include "G4ios.hh"
47 
48 // TruthUtils
50 
51 // CLHEP
52 #include "CLHEP/Units/SystemOfUnits.h"
53 #include "AtlasHepMC/GenParticle.h"
54 #include "AtlasHepMC/GenVertex.h"
55 #include "CLHEP/Random/RandExponential.h"
56 #include "CLHEP/Random/RandFlat.h"
57 
58 // STD
59 #include <math.h>
60 
61 namespace {
63  const double s_projectionFactor = sqrt(2.);
64 }
65 
66 // constructor
67 iFatras::G4HadIntProcessor::G4HadIntProcessor(const std::string& t, const std::string& n, const IInterface* p) :
68  base_class(t,n,p),
69  m_rndGenSvc("AtDSFMTGenSvc", n),
70  m_g4RunManagerHelper("iGeant4::G4RunManagerHelper/G4RunManagerHelper"),
71  m_doElastic(false),
72  m_hadIntProbScale(1.0),
73  m_minMomentum(50.0),
74  m_particleBroker("ISF_ParticleBrokerSvc", n),
75  m_truthRecordSvc("ISF_ValidationTruthService", n),
76  m_randomEngine(0),
77  m_randomEngineName("FatrasRnd")
78 {
79  // steering
80  declareProperty("MomentumCut" , m_minMomentum );
81  declareProperty("DoElasticInteractions" , m_doElastic );
82  declareProperty("HadronicInteractionScaleFactor" , m_hadIntProbScale=1.0 , "Scale probability of HadrInteractions" );
83  // ISF Services and Tools
84  declareProperty("ParticleBroker" , m_particleBroker , "ISF Particle Broker" );
85  declareProperty("TruthRecordSvc" , m_truthRecordSvc , "ISF Particle Truth Svc" );
86  // random number generator
87  declareProperty("RandomNumberService" , m_rndGenSvc , "Random number generator");
88  declareProperty("RandomStreamName" , m_randomEngineName , "Name of the random number stream");
89  declareProperty("G4RunManagerHelper" , m_g4RunManagerHelper);
90 }
91 
92 
93 
94 // destructor
96 {}
97 
98 // Athena standard methods
99 // initialize
101 {
102  ATH_MSG_DEBUG( "initialize()" );
103 
104  // ISF Services
105  if (m_particleBroker.retrieve().isFailure()){
106  ATH_MSG_FATAL( "Could not retrieve ParticleBroker: " << m_particleBroker );
107  return StatusCode::FAILURE;
108  }
109  if (m_truthRecordSvc.retrieve().isFailure()){
110  ATH_MSG_FATAL( "Could not retrieve TruthRecordSvc: " << m_truthRecordSvc );
111  return StatusCode::FAILURE;
112  }
113 
114  // get the random generator serice
115  if (m_rndGenSvc.retrieve().isFailure()){
116  ATH_MSG_FATAL( "Could not retrieve " << m_rndGenSvc );
117  return StatusCode::FAILURE;
118  } else
119  ATH_MSG_VERBOSE( "Successfully retrieved " << m_rndGenSvc );
120 
121  //Get own engine with own seeds:
122  m_randomEngine = m_rndGenSvc->GetEngine(m_randomEngineName);
123  if (!m_randomEngine) {
124  ATH_MSG_FATAL( "Could not get random engine '" << m_randomEngineName << "'" );
125  return StatusCode::FAILURE;
126  }
127 
128  // all good
129  ATH_MSG_DEBUG("initialize() successful");
130  return StatusCode::SUCCESS;
131 }
132 
133 
134 // finalize
136 {
137  ATH_MSG_DEBUG( "finalize() successful" );
138  return StatusCode::SUCCESS;
139 }
140 
141 
142 std::map<int,G4VProcess*>::const_iterator iFatras::G4HadIntProcessor::initProcessPDG(int pdg)
143 {
144  ATH_MSG_VERBOSE( " [ g4sim ] Registering Geant4 processes for particles with pdg code " << pdg );
145 
146  // return value
147  std::map<int,G4VProcess*>::const_iterator ret = m_g4HadrInelasticProcesses.end();
148 
149 
150  G4ParticleDefinition *parDef = G4ParticleTable::GetParticleTable()->FindParticle( pdg);
151 
152  // check if everythin is set up properly
153  if ( !parDef || !parDef->GetProcessManager() ) {
154  ATH_MSG_WARNING( " [ ---- ] Unable to register particle type with PDG code " << pdg );
155  return ret;
156 
157  }
158 
159  // get Geant4 processes
160  G4ProcessVector *physIntVector = parDef->GetProcessManager()->GetPostStepProcessVector(typeGPIL);
161  //G4ProcessVector *physIntVector = parDef->GetProcessManager()->GetProcessVector(idxAll);
162  // G4ProcessVector *physIntVector = parDef->GetProcessManager()->GetPostStepProcessVector(typeDoIt);
163  if ( !physIntVector) {
164  ATH_MSG_WARNING( " [ ---- ] No Geant4 processes registered for PDG code " << pdg << " particles" );
165  return m_g4HadrInelasticProcesses.end();
166  }
167 
168  // loop over all processes of current particle type
169  for( size_t np=0; np < physIntVector->size(); np++) {
170  // get current process
171  G4VProcess* curProc = (*physIntVector)(np);
172  // NULL means the process is inactivated by a user on fly.
173  if ( curProc == 0 ) continue;
174 
175  ATH_MSG_VERBOSE( " [ g4sim ] Found Geant4 process " << curProc->GetProcessName());
176 
177  G4HadronInelasticProcess *hadInelastic = dynamic_cast<G4HadronInelasticProcess*>( curProc);
178  G4HadronElasticProcess *hadElastic = dynamic_cast<G4HadronElasticProcess*>( curProc);
179  ATH_MSG_DEBUG( " hadronic process inelastic,elastic " << hadInelastic << ", " << hadElastic);
180  if ( !hadInelastic && !hadElastic) {
181  ATH_MSG_VERBOSE( " [ g4sim ] Current process not an inelastic or elastic hadronic process -> process not registered" );
182  continue;
183  }
184 
185  if (hadInelastic || hadElastic) {
186  //Prepare and build the Physics table for primaries
187  curProc->PreparePhysicsTable(*parDef);
188  curProc->BuildPhysicsTable(*parDef);
189  }
190 
191  if(hadInelastic){
192  ret = m_g4HadrInelasticProcesses.insert( std::pair<int,G4VProcess*>( pdg, hadInelastic) ).first;
193  ATH_MSG_DEBUG( " [ g4sim ] Registered Geant4 hadronic interaction processes for particles with pdg code " << pdg );
194  }
195  if(m_doElastic && hadElastic ){
196  ret = m_g4HadrElasticProcesses.insert( std::pair<int,G4VProcess*>( pdg, hadElastic) ).first;
197  G4ProcessType pType = curProc->GetProcessType();
198  ATH_MSG_DEBUG( " [ g4sim ] Registered Geant4 ELASTIC hadronic interaction processes for particles with pdg code "
199  << pdg << "and process " << pType);
200  }
201 
202 
203  } // process loop
204 
205  // return iterator to insterted G4VProcess
206  return ret;
207 }
208 
210  double, double, double,
211  const Trk::MaterialProperties& mprop, double pathCorrection,
213 {
214  // do not treat geantinos
215  if (particle==Trk::geantino) return false;
216 
217  bool processSecondaries = true;
218 
219  // the layer material
220  const Trk::MaterialProperties* ematprop = dynamic_cast<const Trk::MaterialProperties*>(&(mprop));
221  if (!ematprop) {
222  ATH_MSG_WARNING("[ ---- ] Unable to cast MaterialProperties->MaterialProperties -> no material interactions for this particle");
223  return false;
224  }
225  ATH_MSG_DEBUG("[ g4sim ] Material t/X0, t/L0 : " << pathCorrection*ematprop->thicknessInX0() << ", " << pathCorrection*ematprop->thicknessInL0() );
226 
227  // compute a random interaction- and radiation length,
228  // according to the mean values
229  double meanIntLength = pathCorrection*ematprop->l0();
230  double rndIntLength = CLHEP::RandExponential::shoot(m_randomEngine, meanIntLength);
231  double thickness = pathCorrection*ematprop->thickness();
232 
233  // test for hadronic interactions
234  if ( rndIntLength < thickness ) {
235  ATH_MSG_DEBUG(" [ g4sim ] computing hadronic interaction on current particle in current material layer");
236  return doHadronicInteraction( 0., position, momentum, &(ematprop->material()), particle, processSecondaries);
237  }
238 
239  // hadronic interaction did not happen
240  return false;
241 }
242 
243 
244 StatusCode iFatras::G4HadIntProcessor::initG4RunManager ATLAS_NOT_THREAD_SAFE () {
245 
246  ATH_MSG_DEBUG("[ g4sim ] Initializing G4RunManager");
247 
248  // Get the G4RunManagerHelper ( no initialization of G4RunManager done )
249  ATH_CHECK( m_g4RunManagerHelper.retrieve() );
250 
251  G4RunManager* g4runManager = m_g4RunManagerHelper->fastG4RunManager();
252  g4runManager->SetVerboseLevel(10);
253 
254  initProcessPDG( 211);
255  initProcessPDG(-211);
256  initProcessPDG(2212);
257  initProcessPDG(-2212);
258  initProcessPDG(2112);
259  initProcessPDG( 130);
260  initProcessPDG( 321);
261  initProcessPDG( 111);
262  initProcessPDG(-321);
263 
264  // define the available G4Material
265  m_g4Material.clear();
266 
267  G4NistManager* G4Nist = G4NistManager::Instance();
268  G4Material* air = G4Nist->G4NistManager::FindOrBuildMaterial("G4_AIR");
269  if (air) {
270  G4MaterialCutsCouple airCuts = G4MaterialCutsCouple(air);
271  // airCuts->SetIndex(0); // ?
272  std::pair<G4Material*,G4MaterialCutsCouple> airMat(air,airCuts);
273  m_g4Material.push_back(std::pair<float,std::pair<G4Material*,G4MaterialCutsCouple> >(0.,airMat));
274  }
275  G4Material* h = G4Nist->G4NistManager::FindOrBuildMaterial("G4_H");
276  if (h) {
277  G4MaterialCutsCouple hCuts = G4MaterialCutsCouple(h);
278  std::pair<G4Material*,G4MaterialCutsCouple> hMat(h,hCuts);
279  m_g4Material.push_back(std::pair<float,std::pair<G4Material*,G4MaterialCutsCouple> >(1.,hMat));
280  }
281  G4Material* al = G4Nist->G4NistManager::FindOrBuildMaterial("G4_Al");
282  if (al) {
283  G4MaterialCutsCouple alCuts = G4MaterialCutsCouple(al);
284  std::pair<G4Material*,G4MaterialCutsCouple> alMat(al,alCuts);
285  m_g4Material.push_back(std::pair<float,std::pair<G4Material*,G4MaterialCutsCouple> >(13.,alMat));
286  }
287  G4Material* si = G4Nist->G4NistManager::FindOrBuildMaterial("G4_Si");
288  if (si) {
289  G4MaterialCutsCouple siCuts = G4MaterialCutsCouple(si);
290  std::pair<G4Material*,G4MaterialCutsCouple> siMat(si,siCuts);
291  m_g4Material.push_back(std::pair<float,std::pair<G4Material*,G4MaterialCutsCouple> >(14.,siMat));
292  }
293  G4Material* ar = G4Nist->G4NistManager::FindOrBuildMaterial("G4_Ar");
294  if (ar) {
295  G4MaterialCutsCouple arCuts = G4MaterialCutsCouple(ar);
296  std::pair<G4Material*,G4MaterialCutsCouple> arMat(ar,arCuts);
297  m_g4Material.push_back(std::pair<float,std::pair<G4Material*,G4MaterialCutsCouple> >(18.,arMat));
298  }
299  G4Material* fe = G4Nist->G4NistManager::FindOrBuildMaterial("G4_Fe");
300  if (fe) {
301  G4MaterialCutsCouple feCuts = G4MaterialCutsCouple(fe);
302  std::pair<G4Material*,G4MaterialCutsCouple> feMat(fe,feCuts);
303  m_g4Material.push_back(std::pair<float,std::pair<G4Material*,G4MaterialCutsCouple> >(26.,feMat));
304  }
305  G4Material* pb = G4Nist->G4NistManager::FindOrBuildMaterial("G4_Pb");
306  if (pb) {
307  G4MaterialCutsCouple pbCuts = G4MaterialCutsCouple(pb);
308  std::pair<G4Material*,G4MaterialCutsCouple> pbMat(pb,pbCuts);
309  m_g4Material.push_back(std::pair<float,std::pair<G4Material*,G4MaterialCutsCouple> >(82.,pbMat));
310  }
311 
312  ATH_MSG_INFO("material vector size for had interaction:"<< m_g4Material.size());
313 
314  //G4cout << *(G4Material::GetMaterialTable()) << std::endl;
315 
316  // Flush the G4 cout/cerr: ATLASSIM-5137
317  G4cout << std::flush;
318  G4cerr << std::flush;
319 
320  return StatusCode::SUCCESS;
321 }
322 
324  double time, const Amg::Vector3D& position, const Amg::Vector3D& momentum,
325  const Trk::Material *ematprop) const
326 {
327  ISF::ISFParticleVector chDef(0);
328 
329  const int pdg = parent->pdgCode();
330 
331  // ions not handled at the moment
332  if ( pdg>10000 ) return chDef;
333 
334  /*
335  * This mutex needs to be locked when calling methods that may modify the process map
336  * (e.g. initProcessPDG). We rely on the fact that std::map iterators remain valid even
337  * when new elements are added. So we only lock on write-access.
338  */
339  static std::mutex processMapMutex;
340 
341  // initialize G4RunManager if not done already
342  static const StatusCode g4RunManagerInit = [&]() {
343  std::scoped_lock lock(processMapMutex);
344  auto this_nc ATLAS_THREAD_SAFE = const_cast<iFatras::G4HadIntProcessor*>(this);
345  StatusCode sc ATLAS_THREAD_SAFE = this_nc->initG4RunManager();
346  return sc;
347  }();
348  if (g4RunManagerInit.isFailure()) return chDef;
349 
350  // find corresponding hadronic interaction process ----------------------------------------------
351  //
352  std::map<int, G4VProcess*>::const_iterator processIter_inelast = m_g4HadrInelasticProcesses.find(pdg);
353  std::map<int, G4VProcess*>::const_iterator processIter_elast = m_g4HadrElasticProcesses.find(pdg);
354 
355  if ( (processIter_inelast==m_g4HadrInelasticProcesses.end()) && (processIter_elast==m_g4HadrElasticProcesses.end()) ) {
356  ATH_MSG_DEBUG ( " [ g4sim ] No hadronic interactions registered for current particle type (pdg=" << pdg << ")" );
357  std::scoped_lock lock(processMapMutex);
358  auto this_nc ATLAS_THREAD_SAFE = const_cast<iFatras::G4HadIntProcessor*>(this);
359  this_nc->initProcessPDG(pdg);
360  return chDef; // this interaction aborted but next may go through
361  }
362  //if ( processIter_inelast==m_g4HadrInelasticProcesses.end()) return chDef;
363 
364  ATH_MSG_DEBUG ( " [ g4sim ] Found registered hadronic interactions for current particle type (pdg=" << pdg << ")" );
365 
366  // setup up G4Track ------------------------------------------------------------------------------
367  //
368  const G4ParticleDefinition *g4parDef = G4ParticleTable::GetParticleTable()->FindParticle(pdg);
369  if ( g4parDef==0) {
370  ATH_MSG_WARNING( "[ ---- ] Unable to find G4ParticleDefinition for particle with PID=" << pdg << " --> skipping hadronic interactions" );
371  return chDef;
372  }
373  G4DynamicParticle* inputPar = new G4DynamicParticle();
374  inputPar->SetDefinition( g4parDef);
375  // input momentum - respect upper limits
376  if ( momentum.mag()>1.e08 ) {
377  ATH_MSG_WARNING( "input momentum beyond limit" << momentum.mag() << " --> skipping hadronic interaction" );
378  return chDef;
379  }
380  const G4ThreeVector mom( momentum.x(), momentum.y(), momentum.z() );
381  inputPar->SetMomentum( mom);
382  // position and timing dummy
383  G4Track g4track( inputPar, 0 /* time */, {0, 0, 0} /* position */);
384  //G4TouchableHandle g4touchable(new G4TouchableHistory()); // TODO check memory handling here
385  //g4track->SetTouchableHandle( g4touchable);
386 
387  // setup up G4Material ---------------------------------------------------------------------------
388  unsigned int g4matInd = retrieveG4MaterialIndex(ematprop);
389 
390  if (g4matInd >= m_g4Material.size()) {
391  return chDef;
392  }
393 
394  // further G4 initializations (G4Step, G4MaterialCutsCouple, ...)
395  G4Step g4step;
396  G4StepPoint* g4stepPoint = new G4StepPoint();
397  g4step.SetPreStepPoint( g4stepPoint); // now owned by g4step
398 
399  g4stepPoint->SetMaterial(m_g4Material[g4matInd].second.first);
400  g4stepPoint->SetMaterialCutsCouple(&(m_g4Material[g4matInd].second.second));
401 
402  // preparing G4Step and G4Track
403  g4track.SetStep( &g4step);
404 
405  // by default, the current process is the inelastic hadr. interaction
406  G4VProcess *process = processIter_inelast!=m_g4HadrInelasticProcesses.end() ? processIter_inelast->second : 0;
407 
408  // if elastic interactions are enabled and there is a elastic process
409  // in the m_g4HadrProcesses_Elastic std::map
410  if( m_doElastic && (processIter_elast!=m_g4HadrElasticProcesses.end()) ) {
411  double rand = CLHEP::RandFlat::shoot(m_randomEngine, 0., 1.);
412 
413  // use a 50% chance to use either elastic or inelastic processes : TODO retrieve cross-section
414  if( rand < 0.5) process = processIter_elast->second;
415  }
416 
417  ATH_MSG_VERBOSE ( " [ g4sim ] Computing " << process->GetProcessName() << " process with current particle" );
418 
419  // do the G4VProcess (actually a G4HadronicProcess) ------------------------------------
420  //process->SetVerboseLevel(10);
421  //ATH_MSG_VERBOSE ( "Verbose Level is " << process->GetVerboseLevel() );
422 
423  G4VParticleChange* g4change = process->PostStepDoIt(g4track, g4step);
424  if (!g4change) {
425  ATH_MSG_WARNING( " [ ---- ] Geant4 did not return any hadronic interaction information of particle with pdg=" << pdg );
426  return chDef;
427  }
428 
429  // process the secondaries ------------------------------------------------------------------
430  unsigned int numSecondaries = g4change->GetNumberOfSecondaries();
431  ATH_MSG_DEBUG( "[ g4sim ] Material update created " << numSecondaries << " Geant4 particle (s)." );
432 
433  // green light for secondaries
434  if ( numSecondaries ) {
435 
436  ISF::ISFParticleVector children(numSecondaries);
437  ISF::ISFParticleVector::iterator childrenIt = children.begin();
438  unsigned short numChildren = 0;
439  for ( unsigned int i = 0; i < numSecondaries; i++ ){
440 
441  // get Geant4 created particle (G4Track)
442  G4Track *trk = g4change->GetSecondary(i);
443  const G4DynamicParticle *dynPar = trk->GetDynamicParticle();
444 
445  // drop if below energy threshold
446  if ( dynPar->GetTotalMomentum() < m_minMomentum)
447  continue;
448 
449  // get dynamic particle
450  const G4ParticleDefinition *parDef = trk->GetParticleDefinition();
451 
452  // skip ions
453  if (parDef->GetPDGEncoding()>1.e09) continue; // FIXME add a method to AtlasPID.h for this check
454 
455  //Prepare and build the physics table for secondaries
456  //process->PreparePhysicsTable(*parDef);
457  //process->BuildPhysicsTable(*parDef);
458 
459  ATH_MSG_VERBOSE( " [ g4sim ] Adding child particle to particle stack (pdg=" << parDef->GetPDGEncoding()
460  << " p=" << dynPar->GetTotalMomentum() );
461 
462 
463  // create the particle to be put into ISF stack
464  const G4ThreeVector &momG4 = dynPar->GetMomentum();
465  Amg::Vector3D mom( momG4.x(), momG4.y(), momG4.z() );
466 
467  const int status = 1 + HepMC::SIM_STATUS_THRESHOLD;
468  const int id = HepMC::UNDEFINED_ID;
469  ISF::ISFParticle* cParticle = new ISF::ISFParticle( position,
470  mom,
471  parDef->GetPDGMass(),
472  parDef->GetPDGCharge(),
473  parDef->GetPDGEncoding(),
474  status,
475  time,
476  *parent,
477  id );
478  cParticle->setNextGeoID( parent->nextGeoID() );
479  cParticle->setNextSimID( parent->nextSimID() );
480  // process sampling tool takes care of validation info
481  *childrenIt = cParticle;
482  ++childrenIt; numChildren++;
483  }
484 
485  children.resize(numChildren);
486 
487  // register TruthIncident
488  const int processForTI = 121; // Hadronic interaction
489  ISF::ISFTruthIncident truth( const_cast<ISF::ISFParticle&>(*parent),
490  children,
491  processForTI,
492  parent->nextGeoID(), // inherits from the parent
494  m_truthRecordSvc->registerTruthIncident( truth);
495  // At this point we need to update the properties of the
496  // ISFParticles produced in the interaction
498 
499  // Check that the new ISFParticles have a valid TruthBinding
500  for (auto *childParticle : children) {
501  if (!childParticle->getTruthBinding()) {
502  ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle);
503  }
504  }
505 
506  // free up memory
507  g4change->Clear();
508  return children;
509 
510  }
511 
512  // free up memory
513  g4change->Clear();
514  return chDef;
515 }
516 
517 
518 
520  const Trk::Material *ematprop,
521  Trk::ParticleHypothesis /*particle*/,
522  bool processSecondaries) const
523 {
524  // Called by G4HadIntProcessor::hadronicInteraction and McMaterialEffectsUpdator::interact
525  // get parent particle
526  // @TODO: replace by Fatras internal bookkeeping
528  // something is seriously wrong if there is no parent particle
529  assert(parent);
530 
531  ISF::ISFParticleVector ispVec=getHadState(parent, time, position, momentum, ematprop); // Registers TruthIncident interally
532 
533  if (ispVec.empty()) return false; // FIXME Inconsistent with HadIntProcessorParametric::doHadronicInteraction
534 
535  // push onto ParticleStack
536  if (processSecondaries) {
537  for (auto *childParticle : ispVec) {
538  //Check that the new ISFParticles have a valid TruthBinding
539  if (!childParticle->getTruthBinding()) {
540  ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle);
541  }
542  m_particleBroker->push(childParticle, parent);
543  }
544  }
545 
546  return true;
547 
548 }
549 
551  const Amg::Vector3D& position, const Amg::Vector3D& momentum,
552  const Trk::Material *emat,
553  Trk::ParticleHypothesis /*particle=Trk::pion*/) const
554 {
555 
556  return getHadState(parent, time, position, momentum, emat); // Registers TruthIncident interally
557 
558 }
559 
561 
562  unsigned int nMaterials = m_g4Material.size();
563  unsigned int invalidIndex = nMaterials + 1;
564 
565  if (0==nMaterials) {
566  ATH_MSG_WARNING(" no predefined G4 material available for hadronic interaction " );
567  return (invalidIndex);
568  }
569 
570  // in the absence of detailed material composition, use average Z
571  // if not available on input, take Al
572  float iZ = ematprop ? ematprop->averageZ() : 13 ;
573 
574  // choose from predefined materials
575  unsigned int imat=0;
576 
577  while (imat < nMaterials && iZ > m_g4Material[imat].first ) imat++;
578 
579  unsigned int iSel=imat< nMaterials ? imat : nMaterials-1;
580 
581  if (iSel>0) {
582  // pick randomly to reproduce the average Z
583  //double rnd = CLHEP::RandFlat::shoot(m_randomEngine, 0., 1.);
584  //if (rnd < (iZ-m_g4Material[iSel-1].first)/(m_g4Material[iSel].first-m_g4Material[iSel-1].first)) iSel--;
585  // weighted
586  float dz2 = -pow(m_g4Material[iSel-1].first,2)+pow(m_g4Material[iSel].first,2);
587  double rnd = CLHEP::RandFlat::shoot(m_randomEngine, 0., 1.);
588  if (iZ*iZ+pow(m_g4Material[iSel-1].first,2) < rnd*dz2) iSel--;
589  }
590 
591  return(iSel);
592 
593 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
Trk::Material::averageZ
float averageZ() const
Definition: Material.h:227
ISF::ISFTruthIncident::updateChildParticleProperties
void updateChildParticleProperties()
Update the id and particleLink properties of the child particles (to be called after registerTruthInc...
Definition: ISFTruthIncident.cxx:239
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
iFatras::G4HadIntProcessor::m_doElastic
bool m_doElastic
Definition: G4HadIntProcessor.h:112
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
G4HadIntProcessor.h
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
ISF::ISFParticle::setNextGeoID
void setNextGeoID(AtlasDetDescr::AtlasRegion geoID)
register the next AtlasDetDescr::AtlasRegion
keylayer_zslicemap.pb
pb
Definition: keylayer_zslicemap.py:188
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
FullCPAlgorithmsTest_eljob.flush
flush
Definition: FullCPAlgorithmsTest_eljob.py:168
MaterialProperties.h
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
ISF::ParticleClipboard::getInstance
static ParticleClipboard & getInstance()
get the singleton instance
Definition: ParticleClipboard.h:61
GenVertex.h
IParticleBroker.h
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
Trk::MaterialProperties::thicknessInX0
float thicknessInX0() const
Return the radiationlength fraction.
ParticleClipboard.h
ISF::ISFParticle
Definition: ISFParticle.h:42
ISFTruthIncident.h
Trk::MaterialProperties::thicknessInL0
float thicknessInL0() const
Return the nuclear interaction length fraction.
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
iFatras::G4HadIntProcessor::initialize
StatusCode initialize()
AlgTool initailize method.
Definition: G4HadIntProcessor.cxx:100
iFatras::G4HadIntProcessor::m_randomEngineName
std::string m_randomEngineName
Name of the random number stream.
Definition: G4HadIntProcessor.h:132
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
PlotPulseshapeFromCool.np
np
Definition: PlotPulseshapeFromCool.py:64
iFatras::G4HadIntProcessor::G4HadIntProcessor
G4HadIntProcessor(const std::string &, const std::string &, const IInterface *)
AlgTool constructor for G4HadIntProcessor.
Definition: G4HadIntProcessor.cxx:67
Trk::MaterialProperties::material
const Material & material() const
Return the stored Material.
GenParticle.h
SUSY_SimplifiedModel_PostInclude.process
string process
Definition: SUSY_SimplifiedModel_PostInclude.py:42
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
ISFParticleContainer.h
Trk::MaterialProperties::thickness
float thickness() const
Return the thickness in mm.
iFatras::G4HadIntProcessor::m_truthRecordSvc
ServiceHandle< ISF::ITruthSvc > m_truthRecordSvc
Definition: G4HadIntProcessor.h:128
iFatras::G4HadIntProcessor::~G4HadIntProcessor
virtual ~G4HadIntProcessor()
Destructor.
Definition: G4HadIntProcessor.cxx:95
Trk::ParticleHypothesis
ParticleHypothesis
Definition: ParticleHypothesis.h:25
ISFParticle.h
ParticleGun_EoverP_Config.mom
mom
Definition: ParticleGun_EoverP_Config.py:63
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
LArG4FSStartPointFilter.rand
rand
Definition: LArG4FSStartPointFilter.py:80
ATLAS_NOT_THREAD_SAFE
StatusCode iFatras::G4HadIntProcessor::initG4RunManager ATLAS_NOT_THREAD_SAFE()
Install fatal handler with default options.
Definition: G4HadIntProcessor.cxx:244
ParticleGun_EoverP_Config.momentum
momentum
Definition: ParticleGun_EoverP_Config.py:63
ISF::ISFTruthIncident
Definition: ISFTruthIncident.h:35
IG4RunManagerHelper.h
lumiFormat.i
int i
Definition: lumiFormat.py:92
ret
T ret(T t)
Definition: rootspy.cxx:260
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
iFatras::G4HadIntProcessor
Definition: G4HadIntProcessor.h:62
ISF::ISFParticleVector
std::vector< ISF::ISFParticle * > ISFParticleVector
ISFParticle vector.
Definition: ISFParticleContainer.h:26
iFatras::G4HadIntProcessor::finalize
StatusCode finalize()
AlgTool finalize method.
Definition: G4HadIntProcessor.cxx:135
Trk::geantino
@ geantino
Definition: ParticleHypothesis.h:26
test_pyathena.parent
parent
Definition: test_pyathena.py:15
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
iFatras::G4HadIntProcessor::m_particleBroker
ServiceHandle< ISF::IParticleBroker > m_particleBroker
ISF services & Tools.
Definition: G4HadIntProcessor.h:127
iFatras::G4HadIntProcessor::m_g4RunManagerHelper
ToolHandle< ISF::IG4RunManagerHelper > m_g4RunManagerHelper
steering: enable elastic interactions?
Definition: G4HadIntProcessor.h:109
HepMC::UNDEFINED_ID
constexpr int UNDEFINED_ID
Definition: MagicNumbers.h:55
ParticleUserInformation.h
HepMC::SIM_STATUS_THRESHOLD
constexpr int SIM_STATUS_THRESHOLD
Constant definiting the status threshold for simulated particles, eg. can be used to separate generat...
Definition: MagicNumbers.h:38
MagicNumbers.h
ISF::ISFParticle::setNextSimID
void setNextSimID(SimSvcID simID)
register the next SimSvcID
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
ISF::ParticleClipboard::getParticle
const ISF::ISFParticle * getParticle() const
get the particle from the clipboard
Definition: ParticleClipboard.h:72
Trk::MaterialProperties
Definition: MaterialProperties.h:40
iFatras::G4HadIntProcessor::doHadronicInteraction
bool doHadronicInteraction(double time, const Amg::Vector3D &position, const Amg::Vector3D &momentum, const Trk::Material *ematprop, Trk::ParticleHypothesis particle=Trk::pion, bool processSecondaries=true) const
Definition: G4HadIntProcessor.cxx:519
h
CaloSwCorrections.time
def time(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:242
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
DeMoScan.first
bool first
Definition: DeMoScan.py:534
iFatras::G4HadIntProcessor::m_minMomentum
double m_minMomentum
Geant4 processes <PDGcode, process> TODO : fission, capture.
Definition: G4HadIntProcessor.h:118
python.DecayParser.children
children
Definition: DecayParser.py:32
declareProperty
#define declareProperty(n, p, h)
Definition: BaseFakeBkgTool.cxx:15
iFatras::G4HadIntProcessor::hadronicInteraction
bool hadronicInteraction(const Amg::Vector3D &position, const Amg::Vector3D &momentum, double p, double E, double charge, const Trk::MaterialProperties &mprop, double pathCorrection, Trk::ParticleHypothesis particle=Trk::pion) const
interface for processing of the nuclear interactions
Definition: G4HadIntProcessor.cxx:209
merge.status
status
Definition: merge.py:17
iFatras::G4HadIntProcessor::initProcessPDG
std::map< int, G4VProcess * >::const_iterator initProcessPDG(int pdg)
choose for list of predefined (pure) materials
Definition: G4HadIntProcessor.cxx:142
ITruthSvc.h
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
Trk::Material
Definition: Material.h:116
iFatras::G4HadIntProcessor::getHadState
ISF::ISFParticleVector getHadState(const ISF::ISFParticle *parent, double time, const Amg::Vector3D &position, const Amg::Vector3D &momentum, const Trk::Material *ematprop) const
collect secondaries for layer material update
Definition: G4HadIntProcessor.cxx:323
iFatras::G4HadIntProcessor::doHadIntOnLayer
ISF::ISFParticleVector doHadIntOnLayer(const ISF::ISFParticle *parent, double time, const Amg::Vector3D &position, const Amg::Vector3D &momentum, const Trk::Material *ematprop, Trk::ParticleHypothesis particle=Trk::pion) const
interface for processing of the presampled nuclear interactions on layer
Definition: G4HadIntProcessor.cxx:550
Trk::MaterialProperties::l0
float l0() const
Return the nuclear interaction length.
iFatras::G4HadIntProcessor::retrieveG4MaterialIndex
unsigned int retrieveG4MaterialIndex(const Trk::Material *ematprop) const
random number service
Definition: G4HadIntProcessor.cxx:560
iFatras::G4HadIntProcessor::m_hadIntProbScale
double m_hadIntProbScale
Definition: G4HadIntProcessor.h:115
iFatras::G4HadIntProcessor::m_rndGenSvc
ServiceHandle< IAtRndmGenSvc > m_rndGenSvc
Definition: G4HadIntProcessor.h:107
ISF::fKillsPrimary
@ fKillsPrimary
Definition: ISFTruthIncident.h:25