ATLAS Offline Software
Loading...
Searching...
No Matches
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"
55#include "CLHEP/Random/RandExponential.h"
56#include "CLHEP/Random/RandFlat.h"
57
58// STD
59#include <math.h>
60
61namespace {
63 const double s_projectionFactor = sqrt(2.);
64}
65
66// constructor
67iFatras::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),
73 m_minMomentum(50.0),
74 m_particleBroker("ISF_ParticleBrokerSvc", n),
75 m_truthRecordSvc("ISF_ValidationTruthService", n),
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
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:
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
142std::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,
212 Trk::ParticleHypothesis particle) const
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
244StatusCode 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
519bool iFatras::G4HadIntProcessor::doHadronicInteraction(double time, const Amg::Vector3D& position, const Amg::Vector3D& momentum,
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}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t al
static Double_t sc
static TRandom * rnd
constexpr int pow(int base, int exp) noexcept
#define ATLAS_NOT_THREAD_SAFE
getNoisyStrip() Find noisy strips from hitmaps and write out into xml/db formats
#define ATLAS_THREAD_SAFE
Header file for AthHistogramAlgorithm.
The generic ISF particle definition,.
Definition ISFParticle.h:42
void setNextSimID(SimSvcID simID)
register the next SimSvcID
void setNextGeoID(AtlasDetDescr::AtlasRegion geoID)
register the next AtlasDetDescr::AtlasRegion
Interface class for all truth incidents handled by the ISF.
void updateChildParticleProperties()
Update the id and particleLink properties of the child particles (to be called after registerTruthInc...
static ParticleClipboard & getInstance()
get the singleton instance
const ISF::ISFParticle * getParticle() const
get the particle from the clipboard
Material with information about thickness of material.
float thicknessInX0() const
Return the radiationlength fraction.
float thicknessInL0() const
Return the nuclear interaction length fraction.
const Material & material() const
Return the stored Material.
float l0() const
Return the nuclear interaction length.
float thickness() const
Return the thickness in mm.
A common object to be contained by.
Definition Material.h:117
float averageZ() const
Definition Material.h:228
Wrapper class for multiple scattering, energyloss, hadronic interaction tool from Geant4.
ServiceHandle< ISF::ITruthSvc > m_truthRecordSvc
double m_minMomentum
Geant4 processes <PDGcode, process> TODO : fission, capture.
std::map< int, G4VProcess * > m_g4HadrInelasticProcesses
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
std::vector< std::pair< float, std::pair< G4Material *, G4MaterialCutsCouple > > > m_g4Material
CLHEP::HepRandomEngine * m_randomEngine
Random engine.
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
G4HadIntProcessor(const std::string &, const std::string &, const IInterface *)
AlgTool constructor for G4HadIntProcessor.
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
std::map< int, G4VProcess * > m_g4HadrElasticProcesses
ServiceHandle< IAtRndmGenSvc > m_rndGenSvc
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
ServiceHandle< ISF::IParticleBroker > m_particleBroker
ISF services & Tools.
unsigned int retrieveG4MaterialIndex(const Trk::Material *ematprop) const
random number service
StatusCode finalize()
AlgTool finalize method.
std::map< int, G4VProcess * >::const_iterator initProcessPDG(int pdg)
choose for list of predefined (pure) materials
std::string m_randomEngineName
Name of the random number stream.
virtual ~G4HadIntProcessor()
Destructor.
ToolHandle< ISF::IG4RunManagerHelper > m_g4RunManagerHelper
steering: enable elastic interactions?
StatusCode initialize()
AlgTool initailize method.
const std::string process
Eigen::Matrix< double, 3, 1 > Vector3D
constexpr int UNDEFINED_ID
constexpr int SIM_STATUS_THRESHOLD
Constant definiting the status threshold for simulated particles, eg. can be used to separate generat...
@ fKillsPrimary
std::vector< ISF::ISFParticle * > ISFParticleVector
ISFParticle vector.
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.