ATLAS Offline Software
Loading...
Searching...
No Matches
Trk::TimedExtrapolator Class Referencefinal

The TimedExtrapolator is to be used for the simulation purposes. More...

#include <TimedExtrapolator.h>

Inheritance diagram for Trk::TimedExtrapolator:
Collaboration diagram for Trk::TimedExtrapolator:

Classes

struct  Cache

Public Member Functions

 TimedExtrapolator (const std::string &, const std::string &, const IInterface *)
 Constructor.
virtual ~TimedExtrapolator ()
 Destructor.
virtual StatusCode initialize () override
 AlgTool initailize method.
virtual StatusCode finalize () override
 AlgTool finalize method.
virtual std::unique_ptr< const Trk::TrackParametersextrapolateWithPathLimit (const Trk::TrackParameters &parm, Trk::PathLimit &pathLim, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, std::vector< Trk::HitInfo > *&hitVector, Trk::GeometrySignature &nextGeoID, const Trk::TrackingVolume *boundaryVol=nullptr) const override
 Extrapolation method for charged, possibly unstable particles.
virtual std::unique_ptr< const Trk::TrackParameterstransportNeutralsWithPathLimit (const Trk::TrackParameters &parm, Trk::PathLimit &pathLim, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, std::vector< Trk::HitInfo > *&hitVector, Trk::GeometrySignature &nextGeoId, const Trk::TrackingVolume *boundaryVol=nullptr) const override
 Transport method for neutral, possibly unstable particles.
virtual const TrackingGeometrytrackingGeometry () const override
 Return the TrackingGeometry used by the Extrapolator (forward information from Navigator)
virtual void validationAction () const override
 Validation Action: Can be implemented optionally, outside access to internal validation steps.
ServiceHandle< StoreGateSvc > & evtStore ()
 The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
const ServiceHandle< StoreGateSvc > & detStore () const
 The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.
virtual StatusCode sysInitialize () override
 Perform system initialization for an algorithm.
virtual StatusCode sysStart () override
 Handle START transition.
virtual std::vector< Gaudi::DataHandle * > inputHandles () const override
 Return this algorithm's input handles.
virtual std::vector< Gaudi::DataHandle * > outputHandles () const override
 Return this algorithm's output handles.
Gaudi::Details::PropertyBase & declareProperty (Gaudi::Property< T, V, H > &t)
void updateVHKA (Gaudi::Details::PropertyBase &)
MsgStream & msg () const
bool msgLvl (const MSG::Level lvl) const

Static Public Member Functions

static const InterfaceID & interfaceID ()
 AlgTool interface methods.

Protected Member Functions

void renounceArray (SG::VarHandleKeyArray &handlesArray)
 remove all handles from I/O resolution
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce (T &h)
void extraDeps_update_handler (Gaudi::Details::PropertyBase &ExtraDeps)
 Add StoreName to extra input/output deps as needed.

Private Types

typedef ServiceHandle< StoreGateSvcStoreGateSvc_t

Private Member Functions

std::unique_ptr< const Trk::TrackParametersextrapolateToVolumeWithPathLimit (Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoID, const Trk::TrackingVolume *destVol) const
BoundaryTrackParameters extrapolateInAlignableTV (Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoId, const Trk::AlignableTrackingVolume *aliTV) const
std::unique_ptr< const Trk::TrackParameterstransportToVolumeWithPathLimit (Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoId, const Trk::TrackingVolume *boundaryVol) const
BoundaryTrackParameters transportInAlignableTV (Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoId, const Trk::AlignableTrackingVolume *aliTV) const
const IPropagatorsubPropagator (const TrackingVolume &tvol) const
 Access the subPropagator to the given volume.
const ITimedMatEffUpdatorsubMaterialEffectsUpdator (const TrackingVolume &tvol) const
 Access the subPropagator to the given volume.
void throwIntoGarbageBin (Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters *garbage) const
 Private method for throwing into the GarbageBin.
void emptyGarbageBin (Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters *) const
 Private method for emptying the GarbageBin.
void overlapSearch (Trk::TimedExtrapolator::Cache &cache, const IPropagator &prop, const TrackParameters &parm, const TrackParameters &parsOnLayer, const Layer &lay, float time, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, bool startingLayer=false) const
 Private to search for overlap surfaces.
std::string positionOutput (const Amg::Vector3D &pos) const
 Private method for conversion of the synchronized geometry signature to the natural subdetector ordering.
Gaudi::Details::PropertyBase & declareGaudiProperty (Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
 specialization for handling Gaudi::Property<SG::VarHandleKey>

Static Private Member Functions

static std::string momentumOutput (const Amg::Vector3D &mom)
 For the output - global momentum.

Private Attributes

ToolHandleArray< IPropagatorm_propagators
ToolHandle< IPropagatorm_stepPropagator
ToolHandle< INavigatorm_navigator
ToolHandleArray< ITimedMatEffUpdatorm_updators
ToolHandleArray< IMultipleScatteringUpdatorm_msupdators
ToolHandle< IEnergyLossUpdatorm_elossupdater
std::vector< const IPropagator * > m_subPropagators
 Propagators to chose from (steered by signature)
std::vector< const ITimedMatEffUpdator * > m_subUpdators
 Updators to chose from (steered by signature)
StringArrayProperty m_propNames
StringArrayProperty m_updatNames
UnsignedIntegerProperty m_meotpIndex
unsigned int m_configurationLevel = 10
 see the supported levels of configuration above
BooleanProperty m_includeMaterialEffects
BooleanProperty m_stopWithNavigationBreak
BooleanProperty m_stopWithUpdateZero
BooleanProperty m_skipInitialLayerUpdate
BooleanProperty m_referenceMaterial
UnsignedIntegerProperty m_initialLayerAttempts
UnsignedIntegerProperty m_successiveLayerAttempts
DoubleProperty m_tolerance {this, "Tolerance", 0.002, "surface & volume tolerance"}
BooleanProperty m_caloMsSecondary
BooleanProperty m_robustSampling {this, "RobustSampling", true}
BooleanProperty m_useDenseVolumeDescription
BooleanProperty m_useMuonMatApprox
BooleanProperty m_resolveActive {this, "ResolveMuonStation", false}
BooleanProperty m_resolveMultilayers {this, "ResolveMultilayers", true}
BooleanProperty m_printHelpOutputAtInitialize {this, "HelpOutput", false}
BooleanProperty m_printRzOutput {this, "positionOutput", true}
BooleanProperty m_navigationStatistics
BooleanProperty m_navigationBreakDetails
BooleanProperty m_materialEffectsOnTrackValidation
unsigned int m_maxNavigSurf {}
unsigned int m_maxNavigVol {}
BooleanProperty m_fastField {this, "MagneticFieldProperties", false}
Trk::MagneticFieldProperties m_fieldProperties
StoreGateSvc_t m_evtStore
 Pointer to StoreGate (event store by default)
StoreGateSvc_t m_detStore
 Pointer to StoreGate (detector store by default)
std::vector< SG::VarHandleKeyArray * > m_vhka
bool m_varHandleArraysDeclared

Detailed Description

The TimedExtrapolator is to be used for the simulation purposes.

The output level is as follows: INFO : initialize / finalize information DEBUG : Method call sequence VERBOSE : Method call sequence with values

Author
sarka.nosp@m..tod.nosp@m.orova.nosp@m.@cer.nosp@m.n.ch

Definition at line 161 of file TimedExtrapolator.h.

Member Typedef Documentation

◆ StoreGateSvc_t

typedef ServiceHandle<StoreGateSvc> AthCommonDataStore< AthCommonMsg< AlgTool > >::StoreGateSvc_t
privateinherited

Definition at line 388 of file AthCommonDataStore.h.

Constructor & Destructor Documentation

◆ TimedExtrapolator()

Trk::TimedExtrapolator::TimedExtrapolator ( const std::string & t,
const std::string & n,
const IInterface * p )

Constructor.

Definition at line 56 of file TimedExtrapolator.cxx.

56 :
57 AthAlgTool(t, n, p),
60 declareInterface<ITimedExtrapolator>(this);
61}
AthAlgTool()
Default constructor:
std::vector< const IPropagator * > m_subPropagators
Propagators to chose from (steered by signature)
std::vector< const ITimedMatEffUpdator * > m_subUpdators
Updators to chose from (steered by signature)
@ NumberOfSignatures

◆ ~TimedExtrapolator()

Trk::TimedExtrapolator::~TimedExtrapolator ( )
virtualdefault

Destructor.

Member Function Documentation

◆ declareGaudiProperty()

Gaudi::Details::PropertyBase & AthCommonDataStore< AthCommonMsg< AlgTool > >::declareGaudiProperty ( Gaudi::Property< T, V, H > & hndl,
const SG::VarHandleKeyType &  )
inlineprivateinherited

specialization for handling Gaudi::Property<SG::VarHandleKey>

Definition at line 156 of file AthCommonDataStore.h.

158 {
160 hndl.value(),
161 hndl.documentation());
162
163 }
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)

◆ declareProperty()

Gaudi::Details::PropertyBase & AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty ( Gaudi::Property< T, V, H > & t)
inlineinherited

Definition at line 145 of file AthCommonDataStore.h.

145 {
146 typedef typename SG::HandleClassifier<T>::type htype;
148 }
Gaudi::Details::PropertyBase & declareGaudiProperty(Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
specialization for handling Gaudi::Property<SG::VarHandleKey>

◆ detStore()

const ServiceHandle< StoreGateSvc > & AthCommonDataStore< AthCommonMsg< AlgTool > >::detStore ( ) const
inlineinherited

The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.

Definition at line 95 of file AthCommonDataStore.h.

◆ emptyGarbageBin()

void Trk::TimedExtrapolator::emptyGarbageBin ( Trk::TimedExtrapolator::Cache & cache,
const Trk::TrackParameters * trPar ) const
private

Private method for emptying the GarbageBin.

Definition at line 1234 of file TimedExtrapolator.cxx.

1235 {
1236 // empty the garbage
1237 std::map<const Trk::TrackParameters *, bool>::iterator garbageIter = cache.m_garbageBin.begin();
1238 std::map<const Trk::TrackParameters *, bool>::iterator garbageEnd = cache.m_garbageBin.end();
1239
1240 bool throwCurrent = false;
1241
1242 for (; garbageIter != garbageEnd; ++garbageIter) {
1243 if (garbageIter->first && garbageIter->first != trPar) {
1244 delete (garbageIter->first);
1245 }
1246 if (garbageIter->first && garbageIter->first == trPar) {
1247 throwCurrent = true;
1248 }
1249 }
1250
1251 cache.m_garbageBin.clear();
1252 if (throwCurrent) {
1253 throwIntoGarbageBin(cache,trPar);
1254 }
1255}
void throwIntoGarbageBin(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters *garbage) const
Private method for throwing into the GarbageBin.
std::map< const Trk::TrackParameters *, bool > m_garbageBin
garbage collection during extrapolation

◆ evtStore()

ServiceHandle< StoreGateSvc > & AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore ( )
inlineinherited

The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.

Definition at line 85 of file AthCommonDataStore.h.

◆ extraDeps_update_handler()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::extraDeps_update_handler ( Gaudi::Details::PropertyBase & ExtraDeps)
protectedinherited

Add StoreName to extra input/output deps as needed.

use the logic of the VarHandleKey to parse the DataObjID keys supplied via the ExtraInputs and ExtraOuputs Properties to add the StoreName if it's not explicitly given

◆ extrapolateInAlignableTV()

Trk::BoundaryTrackParameters Trk::TimedExtrapolator::extrapolateInAlignableTV ( Trk::TimedExtrapolator::Cache & cache,
const Trk::TrackParameters & parm,
Trk::TimeLimit & time,
Trk::PropDirection dir,
Trk::ParticleHypothesis particle,
Trk::GeometrySignature & nextGeoId,
const Trk::AlignableTrackingVolume * aliTV ) const
private

Definition at line 2351 of file TimedExtrapolator.cxx.

2357 {
2358 const std::string m = vol ? vol->volumeName():"NULLPTR";
2359 ATH_MSG_DEBUG("M-[" << ++cache.m_methodSequence << "] extrapolateInAlignableTV(...) " << m);
2360
2361 // material loop in sensitive Calo volumes
2362 // extrapolation without target surface returns:
2363 // A) boundary parameters (static volume boundary)
2364 // if target surface:
2365 // B) trPar at target surface
2366 // material collection done by the propagator ( binned material used )
2367
2368 // initialize the return parameters vector
2369 const Trk::TrackParameters *currPar = &parm;
2370 const Trk::AlignableTrackingVolume *staticVol = nullptr;
2371 const Trk::TrackingVolume *currVol = nullptr;
2372 const Trk::TrackingVolume *nextVol = nullptr;
2373 std::vector<unsigned int> solutions;
2374 // double tol = 0.001;
2375 // double path = 0.;
2376 const EventContext& ctx = Gaudi::Hive::currentContext();
2377 if (!cache.m_highestVolume) {
2378 cache.m_highestVolume = m_navigator->highestVolume(ctx);
2379 }
2380
2381 emptyGarbageBin(cache,&parm);
2382
2383 // verify current position
2384 const Amg::Vector3D& gp = parm.position();
2385 if (vol && vol->inside(gp, m_tolerance)) {
2386 staticVol = vol;
2387 } else {
2388 currVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
2389 const Trk::TrackingVolume *nextStatVol = nullptr;
2390 if (m_navigator->atVolumeBoundary(currPar, currVol, dir, nextStatVol, m_tolerance) && nextStatVol != currVol) {
2391 currVol = nextStatVol;
2392 }
2393 if (currVol && currVol != vol) {
2394 const Trk::AlignableTrackingVolume *aliTG = dynamic_cast<const Trk::AlignableTrackingVolume *> (currVol);
2395 if (aliTG) {
2396 staticVol = aliTG;
2397 }
2398 }
2399 }
2400
2401 if (!staticVol) {
2402 ATH_MSG_DEBUG(" [!] failing in retrieval of AlignableTV, return 0");
2403 return {nullptr, nullptr, nullptr};
2404 }
2405
2406 // TODO if volume entry go to entry of misaligned volume
2407
2408 // save volume entry if collection present
2409
2410 if (cache.m_hitVector) {
2411 const Trk::BinnedMaterial *binMat = staticVol->binnedMaterial();
2412 if (binMat) {
2413 const Trk::IdentifiedMaterial *binIDMat = binMat->material(currPar->position());
2414 if (binIDMat->second > 0) {
2415 cache.m_hitVector->emplace_back(currPar->uniqueClone(), timeLim.time, binIDMat->second, 0.);
2416 }
2417 }
2418 }
2419
2420 // navigation surfaces
2421 if (cache.m_navigSurfs.capacity() > m_maxNavigSurf) {
2422 cache.m_navigSurfs.reserve(m_maxNavigSurf);
2423 }
2424 cache.m_navigSurfs.clear();
2425
2426 // assume new static volume, retrieve boundaries
2427 cache.m_currentStatic = staticVol;
2428 cache.m_staticBoundaries.clear();
2429 const auto &bounds = staticVol->boundarySurfaces();
2430 for (unsigned int ib = 0; ib < bounds.size(); ++ib) {
2431 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
2432 cache.m_staticBoundaries.emplace_back(&surf, true);
2433 }
2434
2435 cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_staticBoundaries.begin(), cache.m_staticBoundaries.end());
2436
2437 // current dense
2438 cache.m_currentDense = staticVol;
2439
2440 // ready to propagate
2441 // till: A/ static volume boundary(bcheck=true) , B/ destination surface(bcheck=false)
2442
2443 nextVol = nullptr;
2444 while (currPar) {
2445 std::vector<unsigned int> solutions;
2446 // propagate now
2447 ATH_MSG_DEBUG(" [+] Starting propagation at position " << positionOutput(currPar->position())
2448 << " (current momentum: " << currPar->momentum().mag() <<
2449 ")");
2450 ATH_MSG_DEBUG(" [+] " << cache.m_navigSurfs.size() << " target surfaces in '" << cache.m_currentDense->volumeName() << "'.");
2451 // arguments : inputParameters, vector of navigation surfaces, propagation direction, b field service, particle
2452 // type, result,
2453 // material collection, intersection collection, path limit, switch for use of path limit, switch for
2454 // curvilinear on return, current TG volume
2455 const Trk::TrackParameters* nextPar = m_stepPropagator
2456 ->propagateT(ctx,
2457 *currPar,
2458 cache.m_navigSurfs,
2459 dir,
2461 particle,
2462 solutions,
2463 cache.m_path,
2464 timeLim,
2465 true,
2466 cache.m_currentDense,
2467 cache.m_hitVector)
2468 .release();
2469 ATH_MSG_VERBOSE(" [+] Propagation done. ");
2470 if (nextPar) {
2471 ATH_MSG_DEBUG(" [+] Position after propagation - at " << positionOutput(nextPar->position()));
2472 }
2473
2474 if (nextPar) {
2475 ATH_MSG_DEBUG(" [+] Number of intersection solutions: " << solutions.size());
2476 }
2477 if (nextPar) {
2478 throwIntoGarbageBin(cache,nextPar);
2479 }
2480
2481 // material update has been done already by the propagator
2482 if (cache.m_path.x0Max > 0. &&
2483 ((cache.m_path.process < 100 && cache.m_path.x0Collected >= cache.m_path.x0Max) ||
2484 (cache.m_path.process > 100 && cache.m_path.l0Collected >= cache.m_path.x0Max))) {
2485 // trigger presampled interaction, provide material properties if needed
2486 // process interaction only if creation of secondaries allowed
2488 const Trk::Material *extMprop = cache.m_path.process > 100 ? cache.m_currentDense : nullptr;
2489
2490 const Trk::TrackParameters *iPar = nullptr;
2491 if (nextPar) {
2492 iPar =
2493 m_updators[0]
2494 ->interact(
2495 timeLim.time, nextPar->position(), nextPar->momentum(), particle, cache.m_path.process, extMprop)
2496 .release();
2497 }
2498
2499 if (!iPar) {
2500 return {nullptr, nullptr, nullptr};
2501 }
2502
2503 throwIntoGarbageBin(cache,iPar);
2504
2505 if (iPar && cache.m_path.process == 121) {
2506 ATH_MSG_DEBUG(" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
2507 return {nullptr, nullptr, nullptr};
2508 }
2509
2510 // return transportToVolumeWithPathLimit(*nextPar, timeLim, dir, particle, nextGeoID, destVol);
2511 } else { // kill particle without trace ?
2512 return {nullptr, nullptr, nullptr};
2513 }
2514 }
2515
2516 // decay ?
2517 if (timeLim.tMax > 0. && timeLim.time >= timeLim.tMax) {
2518 // process interaction only if creation of secondaries allowed
2520 // trigger presampled interaction
2521 const Trk::TrackParameters* iPar = m_updators[0]->interact(
2522 timeLim.time, nextPar->position(), nextPar->momentum(), particle, timeLim.process).release();
2523 if (!iPar) {
2524 return {nullptr, nullptr, nullptr};
2525 }
2526
2527 throwIntoGarbageBin(cache,iPar);
2528 ATH_MSG_WARNING("particle decay survival?" << particle << "," << timeLim.process);
2529 return {nullptr, nullptr, nullptr};
2530 } // kill the particle without trace ( some validation info can be included here eventually )
2531 return {nullptr, nullptr, nullptr};
2532
2533 }
2534
2535 if (nextPar) {
2536 unsigned int iSol = 0;
2537 while (iSol < solutions.size()) {
2538 if (solutions[iSol] < cache.m_staticBoundaries.size()) {
2539 // TODO if massive boundary coded, add the material effects here
2540 // static volume boundary; return to the main loop : TODO move from misaligned to static
2541 unsigned int index = solutions[iSol];
2542 // use global coordinates to retrieve attached volume (just for static!)
2543 nextVol = (cache.m_currentStatic->boundarySurfaces())[index]->attachedVolume(
2544 nextPar->position(), nextPar->momentum(), dir);
2545 // double check the next volume
2546 if (nextVol && !(nextVol->inside(nextPar->position() + 0.01 * dir * nextPar->momentum().normalized(), 0.))) {
2548 " [!] WARNING: wrongly assigned static volume ?" << cache.m_currentStatic->volumeName() << "->" <<
2549 nextVol->volumeName());
2550 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2551 nextPar->position() + 0.01 * dir * nextPar->momentum().normalized());
2552 if (nextVol) {
2553 ATH_MSG_DEBUG(" new search yields: " << nextVol->volumeName());
2554 }
2555 }
2556 // end double check - to be removed after validation of the geometry gluing
2557 // lateral exit from calo sample can be handled here
2558 if (cache.m_hitVector) {
2559 const Trk::BinnedMaterial *binMat = staticVol->binnedMaterial();
2560 if (binMat) {
2561 const Trk::IdentifiedMaterial *binIDMat = binMat->material(nextPar->position());
2562 // save only if entry to the sample present, the exit missing and non-zero step in the sample
2563 if (binIDMat && binIDMat->second > 0 && !cache.m_hitVector->empty() &&
2564 cache.m_hitVector->back().detID == binIDMat->second) {
2565 // double s = (nextPar->position()-m_identifiedParameters->back().first->position()).mag();
2566 // if (s>0.001) m_identifiedParameters->push_back(std::pair<const Trk::TrackParameters*,int>
2567 // (nextPar->clone(), -binIDMat->second));
2568 cache.m_hitVector->emplace_back(nextPar->uniqueClone(), timeLim.time, -binIDMat->second, 0.);
2569 }
2570 }
2571 }
2572 // end lateral exit handling
2573
2574 ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '" << cache.m_currentStatic->volumeName() << "'.");
2575 // no next volume found --- end of the world
2576 if (!nextVol) {
2577 ATH_MSG_DEBUG(" [+] World boundary reached - at " << positionOutput(
2578 nextPar->position()) << ", timed at " << cache.m_time);
2580 } else {
2581 ATH_MSG_DEBUG(" [+] Crossing to next volume '" << nextVol->volumeName() << "'");
2582 ATH_MSG_DEBUG(" [+] Crossing position is - at " << positionOutput(nextPar->position()));
2583 }
2584
2585 return {nextPar, nextVol, cache.m_currentStatic};
2586 }
2587 }
2588 }
2589
2590 currPar = nextPar;
2591 }
2592
2593 return {nullptr, nullptr, nullptr};
2594}
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
const BinnedMaterial * binnedMaterial() const
access to binned material
const IdentifiedMaterial * material(const Amg::Vector3D &position) const
access to material/id per bin
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
std::unique_ptr< ParametersBase< DIM, T > > uniqueClone() const
clone method for polymorphic deep copy returning unique_ptr; it is not overriden, but uses the existi...
ToolHandle< INavigator > m_navigator
ToolHandleArray< ITimedMatEffUpdator > m_updators
Trk::MagneticFieldProperties m_fieldProperties
ToolHandle< IPropagator > m_stepPropagator
std::string positionOutput(const Amg::Vector3D &pos) const
Private method for conversion of the synchronized geometry signature to the natural subdetector order...
void emptyGarbageBin(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters *) const
Private method for emptying the GarbageBin.
BooleanProperty m_caloMsSecondary
GeometrySignature geometrySignature() const
return the Signature
std::vector< std::shared_ptr< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
bool inside(const Amg::Vector3D &gp, double tol=0.) const
Inside() method for checks.
Definition Volume.cxx:72
Eigen::Matrix< double, 3, 1 > Vector3D
str index
Definition DeMoScan.py:362
std::pair< std::shared_ptr< Material >, int > IdentifiedMaterial
ParametersBase< TrackParametersDim, Charged > TrackParameters
std::vector< DestSurf > m_staticBoundaries
const Trk::TrackingVolume * m_highestVolume
const Trk::TrackingVolume * m_currentDense
const Trk::TrackingVolume * m_currentStatic
std::vector< std::pair< const Trk::Surface *, Trk::BoundaryCheck > > m_navigSurfs
std::vector< Trk::HitInfo > * m_hitVector
return helper for hit info

◆ extrapolateToVolumeWithPathLimit()

std::unique_ptr< const Trk::TrackParameters > Trk::TimedExtrapolator::extrapolateToVolumeWithPathLimit ( Trk::TimedExtrapolator::Cache & cache,
const Trk::TrackParameters & parm,
Trk::TimeLimit & time,
Trk::PropDirection dir,
Trk::ParticleHypothesis particle,
Trk::GeometrySignature & nextGeoID,
const Trk::TrackingVolume * destVol ) const
private

Definition at line 272 of file TimedExtrapolator.cxx.

279 {
280 // returns:
281 // A) curvilinear track parameters if path limit reached
282 // B) boundary parameters (at destination volume boundary)
283
284 // initialize the return parameters vector
285 std::unique_ptr<const Trk::TrackParameters> returnParameters = nullptr;
286 const Trk::TrackParameters *currPar = &parm;
287 const Trk::TrackingVolume *currVol = nullptr;
288 const Trk::TrackingVolume *nextVol = nullptr;
289 std::vector<unsigned int> solutions;
290 const Trk::TrackingVolume *assocVol = nullptr;
291 unsigned int iDest = 0;
292 const EventContext& ctx = Gaudi::Hive::currentContext();
293 ATH_MSG_DEBUG(" [+] start extrapolateToVolumeWithPathLimit - at " << positionOutput(parm.position())<<" parm="<<&parm);
294 // destination volume boundary ?
295 if (destVol && m_navigator->atVolumeBoundary(currPar, destVol, dir, nextVol, m_tolerance) && nextVol != destVol) {
296 return parm.uniqueClone();
297 }
298
299 if (!cache.m_highestVolume) {
300 cache.m_highestVolume = m_navigator->highestVolume(ctx);
301 }
302
303 emptyGarbageBin(cache,&parm);
304 // navigation surfaces
305 if (cache.m_navigSurfs.capacity() > m_maxNavigSurf) {
306 cache.m_navigSurfs.reserve(m_maxNavigSurf);
307 }
308 cache.m_navigSurfs.clear();
309
310 // target volume may not be part of tracking geometry
311 if (destVol) {
312 const Trk::TrackingVolume *tgVol = m_navigator->trackingGeometry(ctx)->trackingVolume(destVol->volumeName());
313 if (!tgVol || tgVol != destVol) {
314 const auto & bounds = destVol->boundarySurfaces();
315 for (unsigned int ib = 0; ib < bounds.size(); ib++) {
316 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
317 cache.m_navigSurfs.emplace_back(&surf, true);
318 }
319 iDest = bounds.size();
320 }
321 }
322
323 // resolve current position
324 bool updateStatic = false;
325 Amg::Vector3D gp = parm.position();
326
327 if (!cache.m_currentStatic || !cache.m_currentStatic->inside(gp, m_tolerance)) {
328 cache.m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
329 updateStatic = true;
330 }
331 if (m_navigator->atVolumeBoundary(currPar, cache.m_currentStatic, dir, nextVol,
332 m_tolerance) && nextVol != cache.m_currentStatic) {
333 // no next volume found --- end of the world
334 if (!nextVol) {
335 ATH_MSG_DEBUG(" [+] Word boundary reached - at " << positionOutput(currPar->position()));
337 return currPar->uniqueClone();
338 }
339 cache.m_currentStatic = nextVol;
340 updateStatic = true;
341 }
342
343 // current frame volume known-retrieve geoID
344 nextGeoID = cache.m_currentStatic->geometrySignature();
345
346 // resolve active Calo volumes if hit info required
347 if (cache.m_hitVector && nextGeoID == Trk::Calo) {
348 const Trk::AlignableTrackingVolume *alignTV = dynamic_cast<const Trk::AlignableTrackingVolume *> (cache.m_currentStatic);
349 if (alignTV) {
350 Trk::BoundaryTrackParameters boundPar = extrapolateInAlignableTV(cache,*currPar, timeLim, dir, particle, nextGeoID,
351 alignTV);
352 const Trk::TrackParameters *aPar = boundPar.trPar;
353 if (!aPar) {
354 return returnParameters;
355 }
356 throwIntoGarbageBin(cache,aPar);
357 // cache.m_currentStatic = boundPar.exitVol;
358 return extrapolateToVolumeWithPathLimit(cache,*aPar, timeLim, dir, particle, nextGeoID, destVol);
359 }
360 }
361
362 // update if new static volume
363 if (updateStatic) { // retrieve boundaries
364 cache.m_staticBoundaries.clear();
365 const auto& bounds = cache.m_currentStatic->boundarySurfaces();
366 for (unsigned int ib = 0; ib < bounds.size(); ib++) {
367 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
368 cache.m_staticBoundaries.emplace_back(&surf, true);
369 }
370
371 cache.m_detachedVols.clear();
372 cache.m_detachedBoundaries.clear();
373 cache.m_denseVols.clear();
374 cache.m_denseBoundaries.clear();
375 cache.m_layers.clear();
376 cache.m_navigLays.clear();
377
378 // new: ID volumes may have special material layers ( entry layers ) - add them here
379 // if (cache.m_currentStatic->entryLayerProvider()) {
380 // const std::vector<const Trk::Layer*>& entryLays = cache.m_currentStatic->entryLayerProvider()->layers();
381 // for (unsigned int i=0; i < entryLays.size(); i++) {
382 // if (entryLays[i]->layerType()>0 || entryLays[i]->layerMaterialProperties()) {
383 // cache.m_layers.push_back(std::pair<const
384 // Trk::Surface*,Trk::BoundaryCheck>(&(entryLays[i]->surfaceRepresentation()),true));
385 // cache.m_navigLays.push_back(std::pair<const Trk::TrackingVolume*,const Trk::Layer*> (cache.m_currentStatic,entryLays[i])
386 // );
387 // Trk::DistanceSolution distSol = cache.m_layers.back().first->straightLineDistanceEstimate(currPar->position(),
388 //
389 //
390 //
391 // currPar->momentum().normalized());
392 // }
393 // }
394 // }
395
396 // detached volume boundaries
398 if (!detVols.empty()) {
399 Trk::ArraySpan<const Trk::DetachedTrackingVolume* const>::iterator iTer = detVols.begin();
400 for (; iTer != detVols.end(); ++iTer) {
401 // active station ?
402 const Trk::Layer *layR = (*iTer)->layerRepresentation();
403 bool active = layR && layR->layerType();
404 const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
405 if (active) {
406 cache.m_detachedVols.emplace_back(*iTer,
407 detBounds.size());
408 for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
409 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
410 cache.m_detachedBoundaries.emplace_back(&surf, true);
411 }
412 } else if (cache.m_currentStatic->geometrySignature() != Trk::MS ||
414 (*iTer)->name().substr((*iTer)->name().size() - 4, 4) ==
415 "PERM") { // retrieve
416 // inert
417 // detached
418 // objects
419 // only if
420 // needed
421 if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
422 ((*iTer)->trackingVolume()->confinedDenseVolumes().empty())
423 && (*iTer)->trackingVolume()->confinedArbitraryLayers().empty()) {
424 cache.m_denseVols.emplace_back((*iTer)->trackingVolume(), detBounds.size());
425 for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
426 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
427 cache.m_denseBoundaries.emplace_back(&surf, true);
428 }
429 }
430 Trk::ArraySpan<const Trk::Layer* const> confLays = (*iTer)->trackingVolume()->confinedArbitraryLayers();
431 if (!(*iTer)->trackingVolume()->confinedDenseVolumes().empty() || (confLays.size() > detBounds.size())) {
432 cache.m_detachedVols.emplace_back(*iTer, detBounds.size());
433 for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
434 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
435 cache.m_detachedBoundaries.emplace_back(&surf, true);
436 }
437 } else if (!confLays.empty()) {
438 for (const Trk::Layer* const lIt : confLays) {
439 cache.m_layers.emplace_back(&(lIt->surfaceRepresentation()),
440 true);
441 cache.m_navigLays.emplace_back((*iTer)->trackingVolume(), lIt);
442 }
443 }
444 }
445 }
446 }
447 cache.m_denseResolved = std::pair<unsigned int, unsigned int> (cache.m_denseVols.size(), cache.m_denseBoundaries.size());
448 cache.m_layerResolved = cache.m_layers.size();
449 }
450
451 cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_staticBoundaries.begin(), cache.m_staticBoundaries.end());
452
453 // resolve the use of dense volumes
456
457 // reset remaining counters
458 cache.m_currentDense = cache.m_dense ? cache.m_currentStatic : cache.m_highestVolume;
459 cache.m_navigBoundaries.clear();
460 if (cache.m_denseVols.size() > cache.m_denseResolved.first) {
461 cache.m_denseVols.resize(cache.m_denseResolved.first);
462 }
463 while (cache.m_denseBoundaries.size() > cache.m_denseResolved.second) {
464 cache.m_denseBoundaries.pop_back();
465 }
466 if (cache.m_layers.size() > cache.m_layerResolved) {
467 cache.m_navigLays.resize(cache.m_layerResolved);
468 }
469 while (cache.m_layers.size() > cache.m_layerResolved) {
470 cache.m_layers.pop_back();
471 }
472
473 // current detached volumes
474 // collect : subvolume boundaries, ordered/unordered layers, confined dense volumes
476 // const Trk::DetachedTrackingVolume* currentActive = 0;
477 std::vector<std::pair<const Trk::TrackingVolume *, unsigned int> > navigVols;
478
479 gp = currPar->position();
480 std::vector<const Trk::DetachedTrackingVolume *> detVols =
481 m_navigator->trackingGeometry(ctx)->lowestDetachedTrackingVolumes(gp);
482 std::vector<const Trk::DetachedTrackingVolume *>::iterator dIter = detVols.begin();
483 for (; dIter != detVols.end(); ++dIter) {
484 const Trk::Layer *layR = (*dIter)->layerRepresentation();
485 bool active = layR && layR->layerType();
486 if (active && !m_resolveActive) {
487 continue;
488 }
489 if (!active && cache.m_currentStatic->geometrySignature() == Trk::MS &&
490 m_useMuonMatApprox && (*dIter)->name().substr((*dIter)->name().size() - 4, 4) != "PERM") {
491 continue;
492 }
493 const Trk::TrackingVolume *dVol = (*dIter)->trackingVolume();
494 // detached volume exit ?
495 bool dExit = m_navigator->atVolumeBoundary(currPar, dVol, dir, nextVol, m_tolerance) && !nextVol;
496 if (dExit) {
497 continue;
498 }
499 // inert material
500 const auto& confinedDense = dVol->confinedDenseVolumes();
501 const auto& confinedLays = dVol->confinedArbitraryLayers();
502
503 if (!active && confinedDense.empty() && confinedLays.empty()) {
504 continue;
505 }
506 const auto &bounds = dVol->boundarySurfaces();
507 if (!active && confinedDense.empty() && confinedLays.size() <= bounds.size()) {
508 continue;
509 }
510 if (!confinedDense.empty() || !confinedLays.empty()) {
511 navigVols.emplace_back(dVol, bounds.size());
512 for (unsigned int ib = 0; ib < bounds.size(); ib++) {
513 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
514 cache.m_navigBoundaries.emplace_back(&surf, true);
515 }
516 // collect dense volume boundary
517 if (!confinedDense.empty()) {
518 auto vIter = confinedDense.begin();
519 for (; vIter != confinedDense.end(); ++vIter) {
520 const auto& bounds = (*vIter)->boundarySurfaces();
521 cache.m_denseVols.emplace_back(*vIter, bounds.size());
522 for (unsigned int ib = 0; ib < bounds.size(); ib++) {
523 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
524 cache.m_denseBoundaries.emplace_back(&surf, true);
525 }
526 }
527 }
528 // collect unordered layers
529 if (!confinedLays.empty()) {
530 for (const auto *confinedLay : confinedLays) {
531 cache.m_layers.emplace_back(&(confinedLay->surfaceRepresentation()), true);
532 cache.m_navigLays.emplace_back(dVol, confinedLay);
533 }
534 }
535 } else { // active material
536 const Trk::TrackingVolume *detVol = dVol->associatedSubVolume(gp);
537 if (!detVol && dVol->confinedVolumes()) {
538 std::span<Trk::TrackingVolume const * const> subvols = dVol->confinedVolumes()->arrayObjects();
539 for (const auto *subvol : subvols) {
540 if (subvol->inside(gp, m_tolerance)) {
541 detVol = subvol;
542 break;
543 }
544 }
545 }
546
547 if (!detVol) {
548 detVol = dVol;
549 }
550 bool vExit = m_navigator->atVolumeBoundary(currPar, detVol, dir, nextVol, m_tolerance) && nextVol != detVol;
551 if (vExit && nextVol && nextVol->inside(gp, m_tolerance)) {
552 detVol = nextVol;
553 vExit = false;
554 }
555 if (!vExit) {
556 const auto &bounds = detVol->boundarySurfaces();
557 navigVols.emplace_back(detVol, bounds.size());
558 for (unsigned int ib = 0; ib < bounds.size(); ib++) {
559 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
560 cache.m_navigBoundaries.emplace_back(&surf, true);
561 }
562 if (detVol->zOverAtimesRho() != 0.) {
563 cache.m_denseVols.emplace_back(detVol, bounds.size());
564 for (unsigned int ib = 0; ib < bounds.size(); ib++) {
565 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
566 cache.m_denseBoundaries.emplace_back(&surf, true);
567 }
568 }
569 // layers ?
570 if (detVol->confinedLayers()) {
572 std::span<Trk::Layer const * const> cLays = detVol->confinedLayers()->arrayObjects();
573 for (const auto *cLay : cLays) {
574 if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
575 cache.m_layers.emplace_back(&(cLay->surfaceRepresentation()), true);
576 cache.m_navigLays.emplace_back(cache.m_currentStatic,
577 cLay);
578 }
579 }
580 } else {
581 const Trk::Layer *lay = detVol->associatedLayer(gp);
582 // if (lay && ( (*dIter)->layerRepresentation()
583 // &&(*dIter)->layerRepresentation()->layerType()>0 ) ) currentActive=(*dIter);
584 if (lay) {
585 cache.m_layers.emplace_back(&(lay->surfaceRepresentation()),
586 true);
587 cache.m_navigLays.emplace_back(detVol, lay);
588 }
589 const Trk::Layer *nextLayer = detVol->nextLayer(currPar->position(),
590 dir * currPar->momentum().normalized(), true);
591 if (nextLayer && nextLayer != lay) {
592 cache.m_layers.emplace_back(&(nextLayer->surfaceRepresentation()), true);
593 cache.m_navigLays.emplace_back(detVol, nextLayer);
594 }
595 }
596 } else if (!detVol->confinedArbitraryLayers().empty()) {
598 for (const auto *layer : layers) {
599 cache.m_layers.emplace_back(&(layer->surfaceRepresentation()), true);
600 cache.m_navigLays.emplace_back(detVol, layer);
601 }
602 }
603 }
604 }
605 }
606
607 // confined layers
608 if (cache.m_currentStatic->confinedLayers() && updateStatic) {
609 // if ( cache.m_currentStatic->confinedLayers() ) {
611 std::span<Trk::Layer const * const> cLays = cache.m_currentStatic->confinedLayers()->arrayObjects();
612 for (const auto *cLay : cLays) {
613 if (cLay->layerType() > 0 || cLay->layerMaterialProperties()) {
614 cache.m_layers.emplace_back(&(cLay->surfaceRepresentation()),
615 true);
616 cache.m_navigLays.emplace_back(cache.m_currentStatic, cLay);
617 }
618 }
619 } else {
620 // * this does not work - debug !
621 const Trk::Layer *lay = cache.m_currentStatic->associatedLayer(gp);
622 // if (!lay) {
623 // lay = cache.m_currentStatic->associatedLayer(gp+m_tolerance*parm.momentum().normalized());
624 // std::cout<<" find input associated layer, second attempt:"<< lay<< std::endl;
625 // }
626 if (lay) {
627 cache.m_layers.emplace_back(&(lay->surfaceRepresentation()),
628 Trk::BoundaryCheck(false));
629 cache.m_navigLays.emplace_back(cache.m_currentStatic, lay);
630 const Trk::Layer *nextLayer = lay->nextLayer(currPar->position(), dir * currPar->momentum().normalized());
631 if (nextLayer && nextLayer != lay) {
632 cache.m_layers.emplace_back(&(nextLayer->surfaceRepresentation()),
633 Trk::BoundaryCheck(false));
634 cache.m_navigLays.emplace_back(cache.m_currentStatic,
635 nextLayer);
636 }
637 const Trk::Layer *backLayer = lay->nextLayer(currPar->position(), -dir * currPar->momentum().normalized());
638 if (backLayer && backLayer != lay) {
639 cache.m_layers.emplace_back(&(backLayer->surfaceRepresentation()),
640 Trk::BoundaryCheck(false));
641 cache.m_navigLays.emplace_back(cache.m_currentStatic,
642 backLayer);
643 }
644 }
645 }
646 }
647
648 // cache.m_navigSurfs contains destination surface (if it exists), static volume boundaries
649 // complete with TG cache.m_layers/dynamic layers, cache.m_denseBoundaries, cache.m_navigBoundaries, m_detachedBoundaries
650
651 if (!cache.m_layers.empty()) {
652 cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_layers.begin(), cache.m_layers.end());
653 }
654 if (!cache.m_denseBoundaries.empty()) {
655 cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_denseBoundaries.begin(), cache.m_denseBoundaries.end());
656 }
657 if (!cache.m_navigBoundaries.empty()) {
658 cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_navigBoundaries.begin(), cache.m_navigBoundaries.end());
659 }
660 if (!cache.m_detachedBoundaries.empty()) {
661 cache.m_navigSurfs.insert(cache.m_navigSurfs.end(), cache.m_detachedBoundaries.begin(), cache.m_detachedBoundaries.end());
662 }
663
664
665 // current dense
666 cache.m_currentDense = cache.m_highestVolume;
667 if (cache.m_dense && cache.m_denseVols.empty()) {
668 cache.m_currentDense = cache.m_currentStatic;
669 } else {
670 for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
671 const Trk::TrackingVolume *dVol = cache.m_denseVols[i].first;
672 if (dVol->inside(currPar->position(), m_tolerance) && dVol->zOverAtimesRho() != 0.) {
673 if (!m_navigator->atVolumeBoundary(currPar, dVol, dir, nextVol, m_tolerance) || nextVol == dVol) {
674 cache.m_currentDense = dVol;
675 }
676 }
677 }
678 }
679
680 // before propagation, loop over layers and collect hits
681 if (cache.m_hitVector) {
682 for (unsigned int i = 0; i < cache.m_navigLays.size(); i++) {
683 if (cache.m_navigLays[i].second->layerType() > 0 && cache.m_navigLays[i].second->isOnLayer(currPar->position())) {
684 if (cache.m_navigLays[i].second->surfaceArray()) {
685 // perform the overlap Search on this layer
686 ATH_MSG_VERBOSE(" [o] Calling overlapSearch() on input layer.");
687 overlapSearch(cache,*m_subPropagators[0], *currPar, *currPar, *cache.m_navigLays[i].second, timeLim.time, dir, true,
688 particle);
689 } else {
690 ATH_MSG_VERBOSE(" [o] Collecting intersection with active input layer.");
691 cache.m_hitVector->emplace_back(currPar->uniqueClone(), timeLim.time, cache.m_navigLays[i].second->layerType(), 0.);
692 }
693 } // ------------------------------------------------- Fatras mode off -----------------------------------
694 }
695 }
696
697 // ready to propagate
698 // till: A/ static volume boundary(bcheck=true) , B/ material layer(bcheck=true), C/ destination surface(bcheck=false)
699 // update of cache.m_navigSurfs required if I/ entry into new navig volume, II/ exit from currentActive without overlaps
700
701 nextVol = nullptr;
702 while (currPar) {
703 std::vector<unsigned int> solutions;
704 // double time_backup = timeLim.time;
705 // double path_backup = cache.m_path.x0Collected;
706 ATH_MSG_DEBUG(" [+] Starting propagation at position " << positionOutput(currPar->position())
707 << " (current momentum: " << currPar->momentum().mag() <<
708 ")");
709 ATH_MSG_DEBUG(" [+] " << cache.m_navigSurfs.size() << " target surfaces in '" << cache.m_currentDense->volumeName() << "'."); //
710 // verify
711 // that
712 // material
713 // input
714 // makes
715 // sense
716 if (!(cache.m_currentDense->inside(currPar->position(), m_tolerance)
717 || m_navigator->atVolumeBoundary(currPar, cache.m_currentDense, dir, assocVol, m_tolerance))) {
718 cache.m_currentDense = cache.m_highestVolume;
719 }
721 ->propagateT(ctx,
722 *currPar,
723 cache.m_navigSurfs,
724 dir,
726 particle,
727 solutions,
728 cache.m_path,
729 timeLim,
730 true,
731 cache.m_currentDense,
732 cache.m_hitVector)
733 .release();
734 ATH_MSG_VERBOSE(" [+] Propagation done. ");
735 if (nextPar) {
736 ATH_MSG_DEBUG(" [+] Position after propagation - at " << positionOutput(
737 nextPar->position()) << ", timed at " << timeLim.time);
738 }
739
740 if (!nextPar) {
741 ATH_MSG_DEBUG(" [!] Propagation failed, return 0");
742 cache.m_parametersAtBoundary.boundaryInformation(cache.m_currentStatic, nextPar, nextPar);
743 return returnParameters;
744 }
745
746 throwIntoGarbageBin(cache,nextPar);
747
748 // material update has been done already by the propagator
749 if (cache.m_path.x0Max > 0. &&
750 ((cache.m_path.process < 100 && cache.m_path.x0Collected >= cache.m_path.x0Max) ||
751 (cache.m_path.process > 100 && cache.m_path.l0Collected >= cache.m_path.x0Max))) {
752 // trigger presampled interaction, provide material properties if needed
753 // process interaction only if creation of secondaries allowed
755 const Trk::Material *extMprop = cache.m_path.process > 100 ? cache.m_currentDense : nullptr;
756
757 const Trk::TrackParameters* iPar =
758 m_updators[0]
759 ->interact(
760 timeLim.time, nextPar->position(), nextPar->momentum(), particle, cache.m_path.process, extMprop)
761 .release();
762
763 if (!iPar) {
764 return returnParameters;
765 }
766
767 throwIntoGarbageBin(cache,iPar);
768 return extrapolateToVolumeWithPathLimit(cache,*iPar, timeLim, dir, particle, nextGeoID, destVol);
769 } // kill the particle without trace ( some validation info can be included here eventually )
770 return returnParameters;
771
772 }
773 // decay ?
774 if (timeLim.tMax > 0. && timeLim.time >= timeLim.tMax) {
775 // process interaction only if creation of secondaries allowed
777 // trigger presampled interaction
778 const Trk::TrackParameters* iPar =
779 m_updators[0]
780 ->interact(timeLim.time, nextPar->position(), nextPar->momentum(), particle, timeLim.process)
781 .release();
782 if (!iPar) {
783 return returnParameters;
784 }
785 throwIntoGarbageBin(cache,iPar);
786 return extrapolateToVolumeWithPathLimit(cache,*iPar, timeLim, dir, particle, nextGeoID, destVol);
787 } // kill the particle without trace ( some validation info can be included here eventually )
788 return returnParameters;
789
790 }
791
792 // check missing volume boundary
793 if (nextPar && !(cache.m_currentDense->inside(nextPar->position(), m_tolerance)
794 || m_navigator->atVolumeBoundary(nextPar, cache.m_currentDense, dir, assocVol, m_tolerance))) {
795 ATH_MSG_DEBUG(" [!] ERROR: missing volume boundary for volume" << cache.m_currentDense->volumeName());
796 }
797
798
799 ATH_MSG_DEBUG(" [+] Number of intersection solutions: " << solutions.size());
800
801 unsigned int iSol = 0;
802 while (iSol < solutions.size()) {
803 if (solutions[iSol] < iDest) {
804 return nextPar->uniqueClone();
805 } if (solutions[iSol] < iDest + cache.m_staticBoundaries.size()) {
806 // material attached ?
807 const Trk::Layer *mb = cache.m_navigSurfs[solutions[iSol]].first->materialLayer();
808 if (mb && m_includeMaterialEffects) {
809 if (mb->layerMaterialProperties() && mb->layerMaterialProperties()->fullMaterial(nextPar->position())) {
810 const ITimedMatEffUpdator *currentUpdator = subMaterialEffectsUpdator(*cache.m_currentStatic);
811 nextPar = currentUpdator ? currentUpdator
812 ->update(nextPar,
813 *mb,
814 timeLim,
815 cache.m_path,
817 dir,
818 particle)
819 .release()
820 : nextPar;
821
822 if (!nextPar) {
823 ATH_MSG_VERBOSE(" [+] Update may have killed neutral track - return.");
825 return returnParameters;
826 }
827 throwIntoGarbageBin(cache,nextPar);
828 } else { // material layer without material ?
829 ATH_MSG_VERBOSE(" boundary layer without material:" << mb->layerIndex());
830 }
831 }
832
833 // static volume boundary; return to the main loop
834 unsigned int index = solutions[iSol] - iDest;
835
836 // use global coordinates to retrieve attached volume (just for static!)
837 nextVol = (cache.m_currentStatic->boundarySurfaces())[index]->attachedVolume(
838 nextPar->position(), nextPar->momentum(), dir);
839 // double check the next volume
840 if (nextVol && !(nextVol->inside(nextPar->position() + 0.01 * dir * nextPar->momentum().normalized(), 0.))) {
842 " [!] WARNING: wrongly assigned static volume ?" << cache.m_currentStatic->volumeName() << "->" <<
843 nextVol->volumeName());
844 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
845 nextPar->position() + 0.01 * dir * nextPar->momentum().normalized());
846 if (nextVol) {
847 ATH_MSG_DEBUG(" new search yields: " << nextVol->volumeName());
848 }
849 }
850 // end double check - to be removed after validation of the geometry gluing
851 if (nextVol != cache.m_currentStatic) {
852 cache.m_parametersAtBoundary.boundaryInformation(nextVol, nextPar, nextPar);
853 ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '" << cache.m_currentStatic->volumeName() << "'.");
854 if (m_navigator->atVolumeBoundary(nextPar, cache.m_currentStatic, dir, assocVol,
855 m_tolerance) && assocVol != nextVol) {
856 cache.m_currentDense = cache.m_dense ? nextVol : cache.m_highestVolume;
857 }
858 // no next volume found --- end of the world
859 if (!nextVol) {
860 ATH_MSG_DEBUG(" [+] World boundary reached - at " << positionOutput(
861 nextPar->position()) << ", timed at " << timeLim.time);
863 if (!destVol) {
864 return nextPar->uniqueClone();
865 }
866 }
867 // next volume found and parameters are at boundary
868 if (nextVol /*&& nextPar nextPar is dereferenced anyway */) {
869 ATH_MSG_DEBUG(" [+] Crossing to next volume '" << nextVol->volumeName() << "'");
870 ATH_MSG_DEBUG(" [+] Crossing position is - at " << positionOutput(nextPar->position()));
871 if (!destVol && cache.m_currentStatic->geometrySignature() != nextVol->geometrySignature()) {
872 nextGeoID = nextVol->geometrySignature();
873 return nextPar->uniqueClone();
874 }
875 }
876 return extrapolateToVolumeWithPathLimit(cache,*nextPar, timeLim, dir, particle, nextGeoID, destVol);
877 }
878 } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size()) {
879 // next layer; don't return passive material layers unless required
880 unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size();
881 const Trk::Layer *nextLayer = cache.m_navigLays[index].second;
882 // material update ?
883 // bool matUp = nextLayer->layerMaterialProperties() && m_includeMaterialEffects &&
884 // nextLayer->isOnLayer(nextPar->position());
885 bool matUp = nextLayer->fullUpdateMaterialProperties(*nextPar) && m_includeMaterialEffects &&
886 nextLayer->isOnLayer(nextPar->position());
887 // material update
888 const ITimedMatEffUpdator *currentUpdator = subMaterialEffectsUpdator(*cache.m_currentStatic);
889 if (matUp) {
890 double pIn = nextPar->momentum().mag();
891 nextPar = currentUpdator ? currentUpdator->update(nextPar, *nextLayer, timeLim, cache.m_path,
893 particle).release() : nextPar;
894 if (!nextPar) {
895 ATH_MSG_VERBOSE(" [+] Update may have killed track - return.");
897 return returnParameters;
898 }
900 " Layer energy loss:" << nextPar->momentum().mag() - pIn << "at position:" << nextPar->position() << ", current momentum:" <<
901 nextPar->momentum());
902 throwIntoGarbageBin(cache,nextPar);
903
904 }
905 // active surface intersections ( Fatras hits ...)
906 if (cache.m_hitVector && particle != Trk::neutron) {
907 if (nextLayer->surfaceArray()) {
908 // perform the overlap Search on this layer
909 ATH_MSG_VERBOSE(" [o] Calling overlapSearch() on layer.");
910 overlapSearch(cache,*m_subPropagators[0], *currPar, *nextPar, *nextLayer, timeLim.time, dir, true, particle);
911 } else if (nextLayer->layerType() > 0 && nextLayer->isOnLayer(nextPar->position())) {
912 ATH_MSG_VERBOSE(" [o] Collecting intersection with active layer.");
913 cache.m_hitVector->emplace_back(nextPar->uniqueClone(), timeLim.time, nextLayer->layerType(), 0.);
914 }
915 } // ------------------------------------------------- Fatras mode off -----------------------------------
916
917 // TODO : debug the retrieval of next layer
919 if (cache.m_navigLays[index].first && cache.m_navigLays[index].first->confinedLayers()) {
920 const Trk::Layer *newLayer = nextLayer->nextLayer(nextPar->position(),
921 dir * nextPar->momentum().normalized());
922 if (newLayer && newLayer != nextLayer) {
923 bool found = false;
924 int replace = -1;
925 for (unsigned int i = 0; i < cache.m_navigLays.size(); i++) {
926 if (cache.m_navigLays[i].second == newLayer) {
927 found = true;
928 break;
929 }
930 if (cache.m_navigLays[i].second != nextLayer) {
931 replace = i;
932 }
933 }
934 if (!found) {
935 if (replace > -1) {
936 cache.m_navigLays[replace].second = newLayer;
937 cache.m_navigSurfs[solutions[iSol] + replace - index].first = &(newLayer->surfaceRepresentation());
938 } else {
939 // can't insert a surface in middle
940 return extrapolateToVolumeWithPathLimit(cache,*nextPar, timeLim, dir, particle, nextGeoID, destVol);
941 }
942 }
943 }
944 }
945 }
946 currPar = nextPar;
947 } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size() + cache.m_denseBoundaries.size()) {
948 // dense volume boundary
949 unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size() - cache.m_layers.size();
950 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >::iterator dIter = cache.m_denseVols.begin();
951 while (dIter != cache.m_denseVols.end() && index >= (*dIter).second) {
952 index -= (*dIter).second;
953 ++dIter;
954 }
955 if (dIter != cache.m_denseVols.end()) {
956 currVol = (*dIter).first;
957 nextVol = (currVol->boundarySurfaces())[index]->attachedVolume(*nextPar, dir);
958 // the boundary orientation is not reliable
959 Amg::Vector3D tp = nextPar->position() + 2 * m_tolerance * dir * nextPar->momentum().normalized();
960 if (!nextVol || !nextVol->inside(tp, m_tolerance)) { // search for dense volumes
961 cache.m_currentDense = cache.m_highestVolume;
962 if (cache.m_dense && cache.m_denseVols.empty()) {
963 cache.m_currentDense = cache.m_currentStatic;
964 } else {
965 for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
966 const Trk::TrackingVolume *dVol = cache.m_denseVols[i].first;
967 if (dVol->inside(tp, m_tolerance) && dVol->zOverAtimesRho() != 0.) {
968 cache.m_currentDense = dVol;
969 ATH_MSG_DEBUG(" [+] Next dense volume found: '" << cache.m_currentDense->volumeName() << "'.");
970 break;
971 }
972 } // loop over dense volumes
973 }
974 } else {
975 cache.m_currentDense = nextVol;
976 ATH_MSG_DEBUG(" [+] Next dense volume: '" << cache.m_currentDense->volumeName() << "'.");
977 }
978 }
979 } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size() + cache.m_denseBoundaries.size()
980 + cache.m_navigBoundaries.size()) {
981 // navig volume boundary
982 unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size() - cache.m_layers.size() -
983 cache.m_denseBoundaries.size();
984 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >::iterator nIter = navigVols.begin();
985 while (nIter != navigVols.end() && index >= (*nIter).second) {
986 index -= (*nIter).second;
987 ++nIter;
988 }
989 if (nIter != navigVols.end()) {
990 currVol = (*nIter).first;
991 nextVol = ((*nIter).first->boundarySurfaces())[index]->attachedVolume(*nextPar, dir);
992 if (!nextVol) {
993 ATH_MSG_DEBUG(" [+] Navigation volume boundary, leaving volume '"
994 << currVol->volumeName() << "'.");
995 } else {
996 ATH_MSG_DEBUG(" [+] Navigation volume boundary, entering volume '" << nextVol->volumeName() << "'.");
997 }
998 currPar = nextPar;
999 // return only if detached volume boundaries not collected
1000 // if ( nextVol || !detachedBoundariesIncluded )
1001 if (nextVol) {
1002 return extrapolateToVolumeWithPathLimit(cache,*currPar, timeLim, dir, particle, nextGeoID, destVol);
1003 }
1004 }
1005 } else if (solutions[iSol] < iDest + cache.m_staticBoundaries.size() + cache.m_layers.size() + cache.m_denseBoundaries.size()
1006 + cache.m_navigBoundaries.size() + cache.m_detachedBoundaries.size()) {
1007 // detached volume boundary
1008 unsigned int index = solutions[iSol] - iDest - cache.m_staticBoundaries.size() - cache.m_layers.size()
1009 - cache.m_denseBoundaries.size() - cache.m_navigBoundaries.size();
1010 std::vector< std::pair<const Trk::DetachedTrackingVolume *,
1011 unsigned int> >::iterator dIter = cache.m_detachedVols.begin();
1012 while (dIter != cache.m_detachedVols.end() && index >= (*dIter).second) {
1013 index -= (*dIter).second;
1014 ++dIter;
1015 }
1016 if (dIter != cache.m_detachedVols.end()) {
1017 currVol = (*dIter).first->trackingVolume();
1018 nextVol =
1019 ((*dIter).first->trackingVolume()->boundarySurfaces())[index]->attachedVolume(*nextPar, dir);
1020 if (!nextVol) {
1021 ATH_MSG_DEBUG(" [+] Detached volume boundary, leaving volume '" << currVol->volumeName() << "'.");
1022 } else {
1023 ATH_MSG_DEBUG(" [+] Detached volume boundary, entering volume '" << nextVol->volumeName() << "'.");
1024 }
1025 currPar = nextPar;
1026 // if ( nextVol || !detachedBoundariesIncluded)
1027 if (nextVol) {
1028 return extrapolateToVolumeWithPathLimit(cache, *currPar, timeLim, dir, particle, nextGeoID, destVol);
1029 }
1030 }
1031 }
1032 iSol++;
1033 }
1034 currPar = nextPar;
1035 }
1036
1037 return returnParameters;
1038}
virtual std::span< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
int layerType() const
get the Layer coding
virtual const Surface & surfaceRepresentation() const =0
Transforms the layer into a Surface representation for extrapolation.
const MaterialProperties * fullUpdateMaterialProperties(const TrackParameters &par) const
getting the MaterialProperties back - for full update
Definition Layer.cxx:169
virtual bool isOnLayer(const Amg::Vector3D &gp, const BoundaryCheck &bcheck=BoundaryCheck(true)) const
isOnLayer() method, using isOnSurface() with Layer specific tolerance
Definition Layer.cxx:135
const Layer * nextLayer(const Amg::Vector3D &gp, const Amg::Vector3D &udir) const
getting the next/previous Layer if registered - unit for direction vector required
Definition Layer.cxx:161
const SurfaceArray * surfaceArray() const
Return the entire SurfaceArray, returns nullptr if no SurfaceArray.
float zOverAtimesRho() const
access to members
Definition Material.h:226
BooleanProperty m_resolveActive
BooleanProperty m_useDenseVolumeDescription
std::unique_ptr< const Trk::TrackParameters > extrapolateToVolumeWithPathLimit(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoID, const Trk::TrackingVolume *destVol) const
BooleanProperty m_useMuonMatApprox
BooleanProperty m_includeMaterialEffects
BoundaryTrackParameters extrapolateInAlignableTV(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoId, const Trk::AlignableTrackingVolume *aliTV) const
const ITimedMatEffUpdator * subMaterialEffectsUpdator(const TrackingVolume &tvol) const
Access the subPropagator to the given volume.
BooleanProperty m_robustSampling
void overlapSearch(Trk::TimedExtrapolator::Cache &cache, const IPropagator &prop, const TrackParameters &parm, const TrackParameters &parsOnLayer, const Layer &lay, float time, PropDirection dir=anyDirection, const BoundaryCheck &bcheck=true, ParticleHypothesis particle=pion, bool startingLayer=false) const
Private to search for overlap surfaces.
const LayerArray * confinedLayers() const
Return the subLayer array.
const Layer * associatedLayer(const Amg::Vector3D &gp) const
Return the associated Layer.
const TrackingVolumeArray * confinedVolumes() const
Return the subLayer array.
const TrackingVolume * associatedSubVolume(const Amg::Vector3D &gp) const
Return the associated sub Volume, returns THIS if no subVolume exists.
const Layer * nextLayer(const Amg::Vector3D &gp, const Amg::Vector3D &mom, bool asres=true, bool skipNavLayer=false) const
Return the next Layer if existing, NULL if no next layer corresponds.
ArraySpan< DetachedTrackingVolume const *const > confinedDetachedVolumes() const
Return detached subVolumes - not the ownership.
ArraySpan< Layer const *const > confinedArbitraryLayers() const
Return the confined subLayer array.
ArraySpan< TrackingVolume const *const > confinedDenseVolumes() const
Return unordered subVolumes - not the ownership.
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310
layers(flags, cells_name, *args, **kw)
Here we define wrapper functions to set up all of the standard corrections.
@ layer
Definition HitInfo.h:79
std::span< T > ArraySpan
@ active
Definition Layer.h:47
const TrackParameters * trPar
void boundaryInformation(const TrackingVolume *tvol, const TrackParameters *nextPars, const TrackParameters *navPars, BoundarySurfaceFace face=undefinedFace)
reset the boundary information by invalidating it
std::pair< unsigned int, unsigned int > m_denseResolved
std::vector< std::pair< const Trk::TrackingVolume *, const Trk::Layer * > > m_navigLays
std::vector< DestSurf > m_layers
std::vector< std::pair< const Trk::TrackingVolume *, unsigned int > > m_denseVols
std::vector< DestSurf > m_detachedBoundaries
bool m_dense
internal switch for resolved configuration
ParamsNextVolume m_parametersAtBoundary
return helper for parameters and boundary
std::vector< std::pair< const Trk::DetachedTrackingVolume *, unsigned int > > m_detachedVols
std::vector< DestSurf > m_denseBoundaries
std::vector< DestSurf > m_navigBoundaries

◆ extrapolateWithPathLimit()

std::unique_ptr< const Trk::TrackParameters > Trk::TimedExtrapolator::extrapolateWithPathLimit ( const Trk::TrackParameters & parm,
Trk::PathLimit & pathLim,
Trk::TimeLimit & time,
Trk::PropDirection dir,
Trk::ParticleHypothesis particle,
std::vector< Trk::HitInfo > *& hitVector,
Trk::GeometrySignature & nextGeoID,
const Trk::TrackingVolume * boundaryVol = nullptr ) const
overridevirtual

Extrapolation method for charged, possibly unstable particles.

The extrapolation is interrupted at subdetector boundary for surviving/stable particles.

Implements Trk::ITimedExtrapolator.

Definition at line 193 of file TimedExtrapolator.cxx.

200 {
201// extrapolation method intended for simulation of particle decay; collects intersections with active layers
202// possible outcomes:1/ returns curvilinear parameters after reaching the maximal path
203// 2/ returns parameters at destination volume boundary
204// 3/ returns 0 ( particle stopped ) but keeps vector of hits
205
206 Trk::TimedExtrapolator::Cache cache(m_maxNavigSurf);
208 "M-[" << ++cache.m_methodSequence << "] extrapolateWithPathLimit(...) " << pathLim.x0Max << ", from " << parm.position());
210 "M-[" << ++cache.m_methodSequence << "] extrapolateWithPathLimit(...): resolve active layers? " << m_resolveActive);
211
212 if (!m_stepPropagator) {
213 // Get the STEP_Propagator AlgTool
214 if (m_stepPropagator.retrieve().isFailure()) {
215 ATH_MSG_ERROR("Failed to retrieve tool " << m_stepPropagator);
216 ATH_MSG_ERROR("Configure STEP Propagator for extrapolation with path limit");
217 return nullptr;
218 }
219 ATH_MSG_INFO("Retrieved tool " << m_stepPropagator);
220
221 }
222
223 // reset the path ( in x0 !!)
224 cache.m_path = PathLimit(pathLim.x0Max - pathLim.x0Collected, pathLim.process); // collect material locally
225
226 // initialize hit vector
227 cache.m_hitVector = hitInfo;
228
229 // if no input volume, define as highest volume
230 // const Trk::TrackingVolume* destVolume = boundaryVol ? boundaryVol : m_navigator->highestVolume();
231 cache.m_currentStatic = nullptr;
232 if (boundaryVol && !boundaryVol->inside(parm.position(), m_tolerance)) {
233 return nullptr;
234 }
235
236 // extrapolate to destination volume boundary with path limit
237 std::unique_ptr<const Trk::TrackParameters> returnParms =
239 cache, parm, timeLim, dir, particle, nextGeoID, boundaryVol);
240
241 // save actual path on output
242 if (cache.m_path.x0Collected > 0.) {
243 pathLim.updateMat(cache.m_path.x0Collected, cache.m_path.weightedZ / cache.m_path.x0Collected, cache.m_path.l0Collected);
244 }
245
246 if (hitInfo) {
247 ATH_MSG_DEBUG(hitInfo->size() << " identified intersections found");
248 for (auto & ih : *hitInfo) {
249 ATH_MSG_DEBUG("R,z,ID:" << ih.trackParms->position().perp() << ","
250 << ih.trackParms->position().z() << ","
251 << ih.detID);
252 }
253 }
254
255 std::map<const Trk::TrackParameters *, bool>::iterator garbageIter = cache.m_garbageBin.begin();
256 std::map<const Trk::TrackParameters *, bool>::iterator garbageEnd = cache.m_garbageBin.end();
257 for (; garbageIter != garbageEnd; ++garbageIter) if (garbageIter->first) {
258 if(garbageIter->first == returnParms.get()) {
259 auto ret=returnParms->uniqueClone();
260 ATH_MSG_DEBUG(" [+] garbage - at "
261 << positionOutput(garbageIter->first->position())
262 << " parm=" << garbageIter->first
263 << " is the return param. Cloning to" << ret.get());
264 returnParms = std::move(ret);
265 }
266 }
267
268 return returnParms;
269}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
void updateMat(float dX0, float Z, float dL0)
collected material update

◆ finalize()

StatusCode Trk::TimedExtrapolator::finalize ( )
overridevirtual

AlgTool finalize method.

Definition at line 187 of file TimedExtrapolator.cxx.

187 {
188 ATH_MSG_INFO("finalize() successful");
189 return StatusCode::SUCCESS;
190}

◆ initialize()

StatusCode Trk::TimedExtrapolator::initialize ( )
overridevirtual

AlgTool initailize method.

In this method the extrapolator should retrieve the Propagator of highest order which is then passed through the extrapolate method. The Propagator itself should be specified whether to use propagators of a lower hirarchy level or not.

Definition at line 69 of file TimedExtrapolator.cxx.

69 {
70 m_fieldProperties = m_fastField ? Trk::MagneticFieldProperties(Trk::FastField) : Trk::MagneticFieldProperties(
71 Trk::FullField);
72 if (m_propagators.empty()) {
73 m_propagators.push_back("Trk::RungeKuttaPropagator/DefaultPropagator");
74 }
75 if (m_updators.empty()) {
76 m_updators.push_back("Trk::MaterialEffectsUpdator/DefaultMaterialEffectsUpdator");
77 }
78 if (m_msupdators.empty()) {
79 m_msupdators.push_back("Trk::MultipleScatteringUpdator/AtlasMultipleScatteringUpdator");
80 }
81
82
83 if (!m_propagators.empty()) {
84 if (m_propagators.retrieve().isFailure()) {
85 ATH_MSG_FATAL("Failed to retrieve tool " << m_propagators);
86 return StatusCode::FAILURE;
87 }
88 ATH_MSG_INFO("Retrieved tools " << m_propagators);
89
90 }
91
92
93 // from the number of retrieved propagators set the configurationLevel
94 unsigned int validprop = m_propagators.size();
95
96 if (!validprop) {
97 ATH_MSG_WARNING("None of the defined propagators could be retrieved!");
98 ATH_MSG_WARNING(" Extrapolators jumps back in unconfigured mode, only strategy pattern methods can be used.");
99 } else {
100 m_configurationLevel = validprop - 1;
101 ATH_MSG_VERBOSE("Configuration level automatically set to " << m_configurationLevel);
102 }
103
104 // Get the Navigation AlgTools
105 if (m_navigator.retrieve().isFailure()) {
106 ATH_MSG_FATAL("Failed to retrieve tool " << m_navigator);
107 return StatusCode::FAILURE;
108 }
109 ATH_MSG_INFO("Retrieved tool " << m_navigator);
110
111 // Get the Material Updator
112 if (m_includeMaterialEffects && !m_updators.empty()) {
113 if (m_updators.retrieve().isFailure()) {
114 ATH_MSG_FATAL("None of the defined material updatros could be retrieved!");
115 ATH_MSG_FATAL("No multiple scattering and energy loss material update will be done.");
116 return StatusCode::FAILURE;
117 }
118 ATH_MSG_INFO("Retrieved tools: " << m_updators);
119
120 }
121
122 // from the number of retrieved propagators set the configurationLevel
123 unsigned int validmeuts = m_updators.size();
124
125 // -----------------------------------------------------------
126 // Sanity check 1
127
128 if (m_propNames.empty() && !m_propagators.empty()) {
129 ATH_MSG_DEBUG("Inconsistent setup of Extrapolator, no sub-propagators configured, doing it for you. ");
130 m_propNames.value().push_back(m_propagators[0]->name().substr(8, m_propagators[0]->name().size() - 8));
131 }
132
133 if (m_updatNames.empty() && !m_updators.empty()) {
134 ATH_MSG_DEBUG("Inconsistent setup of Extrapolator, no sub-materialupdators configured, doing it for you. ");
135 m_updatNames.value().push_back(m_updators[0]->name().substr(8, m_updators[0]->name().size() - 8));
136 }
137
138 // -----------------------------------------------------------
139 // Sanity check 2
140 // fill the number of propagator names and updator names up with first one
141 while (int(m_propNames.size()) < int(Trk::NumberOfSignatures)) {
142 m_propNames.value().push_back(m_propNames[0]);
143 }
144 while (int(m_updatNames.size()) < int(Trk::NumberOfSignatures)) {
145 m_updatNames.value().push_back(m_updatNames[0]);
146 }
147 if (validprop && validmeuts) {
148 // Per definition: if configured not found, take the lowest one
149 for (unsigned int isign = 0; int(isign) < int(Trk::NumberOfSignatures); ++isign) {
150 unsigned int index = 0;
151
152 for (unsigned int iProp = 0; iProp < m_propagators.size(); iProp++) {
153 std::string pname = m_propagators[iProp]->name().substr(8, m_propagators[iProp]->name().size() - 8);
154 if (m_propNames[isign] == pname) {
155 index = iProp;
156 }
157 }
158 ATH_MSG_DEBUG(" subPropagator:" << isign << " pointing to propagator: " << m_propagators[index]->name());
159 m_subPropagators[isign] = (index < validprop) ? &(*m_propagators[index]) : &(*m_propagators[Trk::Global]);
160
161 index = 0;
162 for (unsigned int iUp = 0; iUp < m_updators.size(); iUp++) {
163 std::string uname = m_updators[iUp]->name().substr(8, m_updators[iUp]->name().size() - 8);
164 if (m_updatNames[isign] == uname) {
165 index = iUp;
166 }
167 }
168 ATH_MSG_DEBUG(" subMEUpdator:" << isign << " pointing to updator: " << m_updators[index]->name());
169 m_subUpdators[isign] = (index < validmeuts) ? &(*m_updators[index]) : &(*m_updators[Trk::Global]);
170 }
171 } else {
172 ATH_MSG_FATAL("Configuration Problem of Extrapolator: "
173 << " -- At least one IPropagator and IMaterialUpdator instance have to be given.! ");
174 }
175
176
177 m_maxNavigSurf = 1000;
178 m_maxNavigVol = 50;
179
180
181 ATH_MSG_INFO("initialize() successful");
182 return StatusCode::SUCCESS;
183}
#define ATH_MSG_FATAL(x)
if(febId1==febId2)
ToolHandleArray< IPropagator > m_propagators
StringArrayProperty m_propNames
ToolHandleArray< IMultipleScatteringUpdator > m_msupdators
unsigned int m_configurationLevel
see the supported levels of configuration above
StringArrayProperty m_updatNames
@ FastField
call the fast field access method of the FieldSvc
@ FullField
Field is set to be realistic, but within a given Volume.

◆ inputHandles()

virtual std::vector< Gaudi::DataHandle * > AthCommonDataStore< AthCommonMsg< AlgTool > >::inputHandles ( ) const
overridevirtualinherited

Return this algorithm's input handles.

We override this to include handle instances from key arrays if they have not yet been declared. See comments on updateVHKA.

◆ interfaceID()

const InterfaceID & Trk::ITimedExtrapolator::interfaceID ( )
inlinestaticinherited

AlgTool interface methods.

Definition at line 47 of file ITimedExtrapolator.h.

47{ return IID_ITimedExtrapolator; }
static const InterfaceID IID_ITimedExtrapolator("ITimedExtrapolator", 1, 0)

◆ momentumOutput()

std::string Trk::TimedExtrapolator::momentumOutput ( const Amg::Vector3D & mom)
staticprivate

For the output - global momentum.

Definition at line 1226 of file TimedExtrapolator.cxx.

1226 {
1227 std::stringstream outStream;
1228
1229 outStream << "[eta,phi] = [ " << mom.eta() << ", " << mom.phi() << " ]";
1230 return outStream.str();
1231}

◆ msg()

MsgStream & AthCommonMsg< AlgTool >::msg ( ) const
inlineinherited

Definition at line 24 of file AthCommonMsg.h.

24 {
25 return this->msgStream();
26 }

◆ msgLvl()

bool AthCommonMsg< AlgTool >::msgLvl ( const MSG::Level lvl) const
inlineinherited

Definition at line 30 of file AthCommonMsg.h.

30 {
31 return this->msgLevel(lvl);
32 }

◆ outputHandles()

virtual std::vector< Gaudi::DataHandle * > AthCommonDataStore< AthCommonMsg< AlgTool > >::outputHandles ( ) const
overridevirtualinherited

Return this algorithm's output handles.

We override this to include handle instances from key arrays if they have not yet been declared. See comments on updateVHKA.

◆ overlapSearch()

void Trk::TimedExtrapolator::overlapSearch ( Trk::TimedExtrapolator::Cache & cache,
const IPropagator & prop,
const TrackParameters & parm,
const TrackParameters & parsOnLayer,
const Layer & lay,
float time,
PropDirection dir = anyDirection,
const BoundaryCheck & bcheck = true,
ParticleHypothesis particle = pion,
bool startingLayer = false ) const
private

Private to search for overlap surfaces.

Definition at line 1041 of file TimedExtrapolator.cxx.

1051 {
1052
1053 const EventContext& ctx = Gaudi::Hive::currentContext();
1054 // indicate destination layer
1055 bool isDestinationLayer = false;
1056 // start and end surface for on-layer navigation
1057 // -> take the start surface if ther parameter surface is owned by detector element
1058 const Trk::Surface *startSurface = ((parm.associatedSurface()).associatedDetectorElement() && startingLayer) ?
1059 &parm.associatedSurface() : nullptr;
1060 const Trk::Surface *endSurface = nullptr;
1061 // - the best detSurface to start from is the one associated to the detector element
1062 const Trk::Surface *detSurface = (parsOnLayer.associatedSurface()).associatedDetectorElement() ?
1063 &parsOnLayer.associatedSurface() : nullptr;
1064
1065 ATH_MSG_VERBOSE(" [o] OverlapSearch called " << (startSurface ? "with " : "w/o ") << "start, "
1066 << (endSurface ? "with " : "w/o ") << "end surface.");
1067
1068 if (!detSurface) {
1069 // of parsOnLayer are different from parm, then local position is safe, because the extrapolation
1070 // to the detector surface has been done !
1071 detSurface = isDestinationLayer ? lay.subSurface(parsOnLayer.localPosition()) : lay.subSurface(
1072 parsOnLayer.position());
1073 if (detSurface) {
1074 ATH_MSG_VERBOSE(" [o] Detector surface found through subSurface() call");
1075 } else {
1076 ATH_MSG_VERBOSE(" [o] No Detector surface found on this layer.");
1077 }
1078 } else {
1079 ATH_MSG_VERBOSE(" [o] Detector surface found through parameter on layer association");
1080 }
1081
1082 // indicate the start layer
1083 bool isStartLayer = (detSurface && detSurface == startSurface);
1084
1085 const Trk::TrackParameters *detParameters = nullptr;
1086 // the temporary vector (might have to be ordered)
1087 std::vector<const Trk::TrackParameters*> detParametersOnLayer;
1088 bool reorderDetParametersOnLayer = false;
1089 // the first test for the detector surface to be hit (false test)
1090 // - only do this if the parameters aren't on the surface
1091 // (i.e. search on the start layer or end layer)
1092 if (isDestinationLayer) {
1093 detParameters = (&parsOnLayer);
1094 } else if (isStartLayer) {
1095 detParameters = (&parm);
1096 } else if (detSurface) {
1097 // detParameters = prop.propagate(parm, *detSurface, dir, false, tvol, particle);
1098 detParameters = prop.propagate(ctx,parm, *detSurface, dir, false, m_fieldProperties, particle).release();
1099 }
1100
1101 // set the surface hit to true, it is anyway overruled
1102 bool surfaceHit = true;
1103 if (detParameters &&
1104 !isStartLayer &&
1105 !isDestinationLayer) {
1106 ATH_MSG_VERBOSE(" [o] First intersection with Detector surface: " << *detParameters);
1107 // for the later use in the overlapSearch
1108 surfaceHit = detParameters && detSurface ? detSurface->isOnSurface(detParameters->position()) : 0; // ,bcheck) -
1109 // creates
1110 // problems on
1111 // start layer;
1112 // check also for start/endSurface on this level
1113
1114 surfaceHit = (surfaceHit && startSurface) ?
1115 ((detParameters->position() - parm.position()).dot(dir * parm.momentum().normalized()) >
1116 0) : surfaceHit;
1117 surfaceHit = (surfaceHit && endSurface) ?
1118 ((detParameters->position() - parsOnLayer.position()).dot(dir * parsOnLayer.momentum().normalized()) <
1119 0) : surfaceHit;
1120
1121 // surface is hit within bounds (or at least with given boundary check directive) -> it counts
1122 // surface hit also survived start/endsurface search
1123 //
1124 // Convention for Fatras: always apply the full update on the last parameters
1125 // of the gathered vector (no pre/post schema)
1126 // don't record a hit on the destination surface
1127 if (surfaceHit &&
1128 detSurface != startSurface) {
1129 ATH_MSG_VERBOSE(" [H] Hit with detector surface recorded ! ");
1130 // push into the temporary vector
1131 detParametersOnLayer.push_back(detParameters);
1132 } else if (detParameters) {
1133 // no hit -> fill into the garbage bin
1134 ATH_MSG_VERBOSE(" [-] Detector surface hit cancelled through bounds check or start/end surface check.");
1135 throwIntoGarbageBin(cache,detParameters);
1136 }
1137 }
1138
1139 // search for the overlap ------------------------------------------------------------------------
1140 if (detParameters) {
1141 // retrieve compatible subsurfaces
1142 std::vector<Trk::SurfaceIntersection> cSurfaces;
1143 size_t ncSurfaces = lay.compatibleSurfaces(cSurfaces, *detParameters, Trk::anyDirection, bcheck, false);
1144
1145 // import from StaticEngine.icc
1146 if (ncSurfaces) {
1147 ATH_MSG_VERBOSE("found " << ncSurfaces << " candidate sensitive surfaces to test.");
1148 // now loop over the surfaces:
1149 // the surfaces will be sorted @TODO integrate pathLength propagation into this
1150 for (auto &csf : cSurfaces) {
1151 // propagate to the compatible surface, return types are (pathLimit failure is excluded by Trk::anyDirection for
1152 // the moment):
1153 const Trk::TrackParameters *overlapParameters = prop.propagate(ctx,
1154 parm,
1155 *(csf.object),
1157 true,
1159 particle).release();
1160
1161 if (overlapParameters) {
1162 ATH_MSG_VERBOSE(" [+] Overlap surface was hit, checking start/end surface condition.");
1163 // check on start / end surface for on-layer navigaiton action
1164 surfaceHit = (startSurface) ?
1165 ((overlapParameters->position() - parm.position()).dot(dir * parm.momentum().normalized()) >
1166 0) : true;
1167 surfaceHit = (surfaceHit && endSurface) ?
1168 ((overlapParameters->position() - parsOnLayer.position()).dot(dir *
1169 parsOnLayer.momentum().normalized())
1170 < 0) : surfaceHit;
1171 if (surfaceHit && csf.object!=detSurface) { //skipping the initial surface on which a hit has already been created
1172 ATH_MSG_VERBOSE(" [H] Hit with detector surface recorded !");
1173 // distinguish whether sorting is needed or not
1174 reorderDetParametersOnLayer = true;
1175 // push back into the temporary vector
1176 detParametersOnLayer.push_back(overlapParameters);
1177 } else { // the parameters have been cancelled by start/end surface
1178 // no hit -> fill into the garbage bin
1179 ATH_MSG_VERBOSE(" [-] Detector surface hit cancelled through start/end surface check.");
1180 throwIntoGarbageBin(cache,overlapParameters);
1181 }
1182 }
1183 } // loop over test surfaces done
1184 } // there are compatible surfaces
1185 } // ---------------------------------------------------------------------------------------------
1186
1187 // push them into the parameters vector
1188 std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIter = detParametersOnLayer.begin();
1189 std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIterEnd = detParametersOnLayer.end();
1190
1191 // reorder the track parameters if neccessary, the overlap descriptor did not provide the ordered surfaces
1192 if (reorderDetParametersOnLayer) {
1193 // sort to reference of incoming parameters
1194 Trk::TrkParametersComparisonFunction parameterSorter(parm.position());
1195 sort(detParametersOnLayer.begin(), detParametersOnLayer.end(), parameterSorter);
1196 }
1197
1198 // after sorting : reset the iterators
1199 parsOnLayerIter = detParametersOnLayer.begin();
1200 parsOnLayerIterEnd = detParametersOnLayer.end();
1201 // now fill them into the parameter vector -------> hit creation done <----------------------
1202 for (; parsOnLayerIter != parsOnLayerIterEnd; ++parsOnLayerIter) {
1203 if (cache.m_hitVector) {
1204 cache.m_hitVector->emplace_back(
1205 std::unique_ptr<const Trk::TrackParameters>(*parsOnLayerIter),
1206 time,
1207 0,
1208 0.);
1209 }
1210 }
1211}
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
@ anyDirection
ComparisonFunction< TrackParameters > TrkParametersComparisonFunction

◆ positionOutput()

std::string Trk::TimedExtrapolator::positionOutput ( const Amg::Vector3D & pos) const
private

Private method for conversion of the synchronized geometry signature to the natural subdetector ordering.

For the output - global position

Definition at line 1214 of file TimedExtrapolator.cxx.

1214 {
1215 std::stringstream outStream;
1216
1217 if (m_printRzOutput) {
1218 outStream << "[r,phi,z] = [ " << pos.perp() << ", " << pos.phi() << ", " << pos.z() << " ]";
1219 } else {
1220 outStream << "[xyz] = [ " << pos.x() << ", " << pos.y() << ", " << pos.z() << " ]";
1221 }
1222 return outStream.str();
1223}
BooleanProperty m_printRzOutput

◆ renounce()

std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > AthCommonDataStore< AthCommonMsg< AlgTool > >::renounce ( T & h)
inlineprotectedinherited

Definition at line 380 of file AthCommonDataStore.h.

381 {
382 h.renounce();
384 }
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)

◆ renounceArray()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::renounceArray ( SG::VarHandleKeyArray & handlesArray)
inlineprotectedinherited

remove all handles from I/O resolution

Definition at line 364 of file AthCommonDataStore.h.

364 {
366 }

◆ subMaterialEffectsUpdator()

const ITimedMatEffUpdator * Trk::TimedExtrapolator::subMaterialEffectsUpdator ( const TrackingVolume & tvol) const
inlineprivate

Access the subPropagator to the given volume.

Definition at line 464 of file TimedExtrapolator.h.

465{
466 return (tvol.geometrySignature() < m_subUpdators.size()) ? m_subUpdators[tvol.geometrySignature()]
467 : nullptr;
468}

◆ subPropagator()

const IPropagator * Trk::TimedExtrapolator::subPropagator ( const TrackingVolume & tvol) const
inlineprivate

Access the subPropagator to the given volume.

Definition at line 451 of file TimedExtrapolator.h.

452{
453 const IPropagator* currentPropagator = (tvol.geometrySignature() < m_subPropagators.size())
454 ? m_subPropagators[tvol.geometrySignature()]
455 : nullptr;
456 if (!currentPropagator) {
457 msg(MSG::ERROR) << "[!] Configuration problem: no Propagator found for volumeSignature: "
458 << tvol.geometrySignature() << endmsg;
459 }
460 return currentPropagator;
461}
#define endmsg
MsgStream & msg() const

◆ sysInitialize()

virtual StatusCode AthCommonDataStore< AthCommonMsg< AlgTool > >::sysInitialize ( )
overridevirtualinherited

Perform system initialization for an algorithm.

We override this to declare all the elements of handle key arrays at the end of initialization. See comments on updateVHKA.

Reimplemented in asg::AsgMetadataTool, AthCheckedComponent< AthAlgTool >, AthCheckedComponent<::AthAlgTool >, and DerivationFramework::CfAthAlgTool.

◆ sysStart()

virtual StatusCode AthCommonDataStore< AthCommonMsg< AlgTool > >::sysStart ( )
overridevirtualinherited

Handle START transition.

We override this in order to make sure that conditions handle keys can cache a pointer to the conditions container.

◆ throwIntoGarbageBin()

void Trk::TimedExtrapolator::throwIntoGarbageBin ( Trk::TimedExtrapolator::Cache & cache,
const Trk::TrackParameters * garbage ) const
inlineprivate

Private method for throwing into the GarbageBin.

Definition at line 471 of file TimedExtrapolator.h.

473{
474 if (pars)
475 cache.m_garbageBin[pars] = true;
476}

◆ trackingGeometry()

const TrackingGeometry * Trk::TimedExtrapolator::trackingGeometry ( ) const
inlineoverridevirtual

Return the TrackingGeometry used by the Extrapolator (forward information from Navigator)

Implements Trk::ITimedExtrapolator.

Definition at line 442 of file TimedExtrapolator.h.

443{
444 if (m_navigator) {
445 return m_navigator->trackingGeometry(Gaudi::Hive::currentContext());
446 }
447 return nullptr;
448}

◆ transportInAlignableTV()

Trk::BoundaryTrackParameters Trk::TimedExtrapolator::transportInAlignableTV ( Trk::TimedExtrapolator::Cache & cache,
const Trk::TrackParameters & parm,
Trk::TimeLimit & time,
Trk::PropDirection dir,
Trk::ParticleHypothesis particle,
Trk::GeometrySignature & nextGeoId,
const Trk::AlignableTrackingVolume * aliTV ) const
private

Definition at line 2047 of file TimedExtrapolator.cxx.

2053 {
2054 const std::string m = aliTV ? aliTV->volumeName() : " NULLPTR!";
2055 ATH_MSG_DEBUG(" [0] starting transport of neutral particle in alignable volume " << m);
2056
2057 // material loop in sensitive Calo volumes
2058 // returns: boundary parameters (static volume boundary)
2059 // material collection / intersection with active layers ( binned material used )
2060
2061 // initialize the return parameters vector
2062 const Trk::TrackParameters *currPar = &parm;
2063 const Trk::TrackingVolume *nextVol = nullptr;
2064 std::vector<Trk::IdentifiedIntersection> iis;
2065
2066 emptyGarbageBin(cache,&parm);
2067
2068 const EventContext& ctx = Gaudi::Hive::currentContext();
2069 if (!aliTV) {
2070 return {nullptr, nullptr, nullptr};
2071 }
2072
2073 // TODO if volume entry go to entry of misaligned volume
2074
2075 // save volume entry if collection present
2076
2077 const Trk::BinnedMaterial *binMat = aliTV->binnedMaterial();
2078
2079 const Trk::IdentifiedMaterial *binIDMat = nullptr;
2080
2081 const Trk::Material *currMat = aliTV; // material to be used
2082
2083
2084 // loop through binned material : save identifier, material, distance
2085
2086 // binned material
2087 if (binMat) {
2088 Amg::Vector3D pos = currPar->position();
2089 Amg::Vector3D pot = currPar->position();
2090 Amg::Vector3D umo = currPar->momentum().normalized();
2091
2092 binIDMat = binMat->material(pos);
2093
2094 if (cache.m_hitVector && binIDMat) {
2095 // std::cout <<"id info at the alignable volume entry:"<<binIDMat->second<<std::endl;
2096 if (binIDMat->second > 0) {
2097 cache.m_hitVector->emplace_back(currPar->uniqueClone(), timeLim.time, binIDMat->second, 0.);
2098 }
2099 }
2100
2101 const Trk::BinUtility *lbu = binMat->layerBinUtility(pos);
2102 if (lbu) {
2103 unsigned int cbin = lbu->bin(pos);
2104 // std::cout <<"layerBinUtility retrieved:"<<lbu->bins()<< std::endl;
2105 std::pair<size_t, float> d2n = lbu->distanceToNext(pos, dir * umo);
2106 // std::cout<<"estimated distance to the next bin:"<<d2n.first<<","<<d2n.second<< std::endl;
2107 float dTot = 0.;
2108 float distTot = 0.;
2109 // std::cout <<"input bin:"<<cbin<<", next: "<<d2n.first<<", at distance:"<<d2n.second<< std::endl;
2110 while (true) {
2111 if (d2n.first == cbin) {
2112 break;
2113 }
2114 dTot += d2n.second;
2115 distTot = dTot;
2116 pos = pos + d2n.second * dir * umo;
2117 if (!aliTV->inside(pos)) {
2118 break; // step outside volume
2119 }
2120 cbin = d2n.first;
2121 d2n = lbu->distanceToNext(pos, dir * umo);
2122 if (d2n.first == cbin && fabs(d2n.second) < 0.002) { // move ahead
2123 pos = pos + 0.002 * dir * umo;
2124 dTot += 0.002;
2125 d2n = lbu->distanceToNext(pos, dir * umo);
2126 }
2127 // std::cout <<"finding next bin?:"<<d2n.first<<","<<dTot<<"+"<<d2n.second<< std::endl;
2128 if (d2n.second > 0.001) { // retrieve material and save bin entry
2129 pot = pos + 0.5 * d2n.second * dir * umo;
2130 binIDMat = binMat->material(pot);
2131 iis.emplace_back(distTot, binIDMat->second, binIDMat->first.get());
2132 // std::cout <<"saving next bin entry:"<< distTot<<","<<binIDMat->second<<std::endl;
2133 }
2134 }
2135 }
2136 }
2137
2138 // resolve exit from the volume
2139
2140 cache.m_trStaticBounds.clear();
2141 const auto &bounds = aliTV->boundarySurfaces();
2142 for (unsigned int ib = 0; ib < bounds.size(); ib++) {
2143 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
2144 Trk::DistanceSolution distSol = surf.straightLineDistanceEstimate(currPar->position(),
2145 dir * currPar->momentum().normalized());
2146 double dist = distSol.first();
2147 // resolve multiple intersection solutions
2148 if (distSol.numberOfSolutions() > 1 && dist < m_tolerance && distSol.second() > dist) {
2149 dist = distSol.second();
2150 }
2151 // boundary check
2152 Amg::Vector3D gp = currPar->position() + dist * dir * currPar->momentum().normalized();
2153 // std::cout<<"alignable volume boundary:"<< ib<<","<<dist<<","<<
2154 // surf.isOnSurface(gp,true,m_tolerance,m_tolerance)<<std::endl;
2155 if (dist > m_tolerance && surf.isOnSurface(gp, true, m_tolerance, m_tolerance)) {
2156 const Trk::TrackingVolume *attachedVol = (bounds[ib])->attachedVolume(gp, currPar->momentum(), dir);
2157
2158 if (attachedVol && !(attachedVol->inside(gp + 0.01 * dir * currPar->momentum().normalized(), m_tolerance))) {
2160 " [!] WARNING: wrongly assigned exit volume ?" << cache.m_currentStatic->volumeName() << "->" <<
2161 attachedVol->volumeName());
2162 attachedVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
2163 gp + 0.01 * dir * currPar->momentum().normalized());
2164 if (attachedVol) {
2165 ATH_MSG_DEBUG(" new search yields: " << attachedVol->volumeName());
2166 }
2167 }
2168
2169 if (attachedVol != cache.m_currentStatic) { // exit
2170 nextVol = attachedVol;
2171 cache.m_trStaticBounds.insert(cache.m_trStaticBounds.begin(), Trk::DestBound(&surf, dist, ib));
2172 } else if (dist > 0.001) {
2173 const Trk::TrackingVolume *testVol = (bounds[ib])->attachedVolume(gp,
2174 currPar->momentum(),
2177 "gluing problem at the exit from alignable volume: " << gp.perp() << "," << gp.z() << ":" <<
2178 cache.m_currentStatic->volumeName());
2179 if (testVol) {
2180 ATH_MSG_DEBUG("inverted direction:" << testVol->volumeName());
2181 }
2182 if (testVol &&
2183 testVol->inside(gp + 0.01 * dir * currPar->momentum().normalized(),
2184 m_tolerance) && testVol != cache.m_currentStatic) {
2186 "next volume resolved to:" << testVol->volumeName() << " at the position(R,Z):" << gp.perp() << "," <<
2187 gp.z());
2188 nextVol = testVol;
2189 cache.m_trStaticBounds.insert(cache.m_trStaticBounds.begin(), Trk::DestBound(&surf, dist, ib));
2190 }
2191 }
2192 }
2193 } // end loop over boundaries
2194
2195 // if (nextVol) std::cout <<"nextVol, number of exit solutions:"<<
2196 // nextVol->volumeName()<<","<<cache.m_trStaticBounds.size()<< std::endl;
2197
2198 if (cache.m_trStaticBounds.empty()) {
2199 ATH_MSG_WARNING("exit from alignable volume " << aliTV->volumeName() << " not resolved, aborting");
2200 return {nullptr, nullptr, nullptr};
2201 } if (cache.m_trStaticBounds.size() > 1) { // hit edge ?
2202 Amg::Vector3D gp = currPar->position() + (cache.m_trStaticBounds[0].distance + 1.) * dir *
2203 currPar->momentum().normalized();
2204 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
2205 ATH_MSG_DEBUG("exit volume reassigned:" << nextVol->volumeName());
2206 }
2207
2208 // exit from the volume may coincide with the last bin boundary - leave 10 microns marge
2209 if (!iis.empty() && cache.m_trStaticBounds[0].distance - iis.back().distance < 0.01) {
2210 iis.pop_back();
2211 }
2212
2213 // add volume exit
2214 iis.emplace_back(cache.m_trStaticBounds[0].distance, 0, nullptr);
2215
2216 // loop over intersection taking into account the material effects
2217
2218 double dist = 0.;
2219 double mom = currPar->momentum().mag();
2220 double beta = mom / sqrt(mom * mom + cache.m_particleMass * cache.m_particleMass) * Gaudi::Units::c_light;
2221 Amg::Vector3D nextPos = currPar->position();
2222
2223 int currLay = 0;
2224
2225 for (unsigned int is = 0; is < iis.size(); is++) {
2226 if (iis[is].distance == 0.) {
2227 continue;
2228 }
2229
2230 double step = iis[is].distance - dist;
2231
2232 nextPos = currPar->position() + dir * currPar->momentum().normalized() * iis[is].distance;
2233
2234 double tDelta = step / beta;
2235
2236 double mDelta = (currMat->zOverAtimesRho() != 0.) ? step / currMat->x0() : 0.;
2237
2238 // in case of hadronic interaction retrieve nuclear interaction properties, too
2239
2240 double frT = 1.;
2241 if (step > 0 && timeLim.tMax > cache.m_time && cache.m_time + tDelta >= timeLim.tMax) {
2242 frT = (timeLim.tMax - cache.m_time) * beta / step;
2243 }
2244
2245 // TODO : compare x0 or l0 according to the process type
2246 double frM = 1.;
2247 if (mDelta > 0 && cache.m_path.x0Max > 0.) {
2248 if (cache.m_path.process < 100 && cache.m_path.x0Collected + mDelta > cache.m_path.x0Max) {
2249 frM = (cache.m_path.x0Max - cache.m_path.x0Collected) / mDelta;
2250 } else { // waiting for hadronic interaction, retrieve nuclear interaction properties
2251 double mDeltaL = currMat->L0 > 0. ? step / currMat->L0 : mDelta / 0.37 / currMat->averageZ();
2252 if (cache.m_path.l0Collected + mDeltaL > cache.m_path.x0Max) {
2253 frM = (cache.m_path.x0Max - cache.m_path.l0Collected) / mDeltaL;
2254 }
2255 }
2256 }
2257
2258 double fr = fmin(frT, frM);
2259
2260 // std::cout << "looping over intersections:"<<is<<","<< cache.m_trSurfs[sols[is]].second<<","<<step << ","<<
2261 // tDelta<<","<<mDelta << std::endl;
2262
2263 if (fr < 1.) { // decay or material interaction during the step
2264 int process = frT < frM ? timeLim.process : cache.m_path.process;
2265 cache.m_time += fr * step / beta;
2266 if (mDelta > 0 && currMat->averageZ() > 0) {
2267 cache.m_path.updateMat(fr * mDelta, currMat->averageZ(), 0.);
2268 }
2269
2270 nextPos = currPar->position() + dir * currPar->momentum().normalized() * (dist + fr * step);
2271
2272 // process interaction only if creation of secondaries allowed
2273 if (m_caloMsSecondary) {
2274 const Trk::TrackParameters* nextPar =
2275 m_updators[0]
2276 ->interact(cache.m_time, nextPos, currPar->momentum(), particle, process, currMat)
2277 .release();
2278 throwIntoGarbageBin(cache, nextPar);
2279
2280 if (nextPar) {
2281 ATH_MSG_DEBUG(" [!] WARNING: particle survives the interaction " << process);
2282 }
2283
2284 if (nextPar && process == 121) {
2285 ATH_MSG_DEBUG(" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
2286 return {nullptr, nullptr, nullptr};
2287 }
2288
2289 if (!nextPar) {
2290 return {nullptr, nullptr, nullptr};
2291 }
2292
2293 // return transportToVolumeWithPathLimit(*nextPar, timeLim, dir, particle, nextGeoID, destVol);
2294 } else { // kill particle without trace ?
2295 return {nullptr, nullptr, nullptr};
2296 }
2297 } // end decay or material interaction during the step
2298
2299 // update
2300 dist = iis[is].distance;
2301 if (mDelta > 0 && currMat->averageZ() > 0) {
2302 cache.m_path.updateMat(mDelta, currMat->averageZ(), 0.);
2303 }
2304 cache.m_time += tDelta;
2305
2306 if (is < iis.size() - 1) { // update bin material info
2307 // binIDMat = binMat->material(nextPos);
2308 // currMat = binIDMat->first;
2309 currMat = iis[is].material;
2310 currLay = iis[is].identifier;
2311
2312 if (cache.m_hitVector && iis[is].identifier > 0) { // save entry to the next layer
2313 ATH_MSG_VERBOSE("active layer entry:" << currLay << " at R,z:" << nextPos.perp() << "," << nextPos.z());
2314 auto nextPar = std::make_unique<Trk::CurvilinearParameters>(nextPos, currPar->momentum(), 0.);
2315 cache.m_hitVector->emplace_back(std::move(nextPar), timeLim.time, iis[is].identifier, 0.);
2316 }
2317 }
2318 } // end loop over intersections
2319
2320 Trk::CurvilinearParameters *nextPar = new Trk::CurvilinearParameters(nextPos, currPar->momentum(), 0.);
2321
2322 if (cache.m_hitVector) { // save volume exit /active layer only ?
2323 ATH_MSG_VERBOSE("active layer/volume exit:" << currLay << " at R,z:" << nextPos.perp() << "," << nextPos.z());
2324 if (binIDMat and(binIDMat->second > 0)) {
2325 cache.m_hitVector->emplace_back(nextPar->uniqueClone(), timeLim.time, currLay, 0.);
2326 }
2327 }
2328
2329 throwIntoGarbageBin(cache,nextPar);
2330
2331
2332
2333 ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '" << cache.m_currentStatic->volumeName() << "'.");
2334
2335 // no next volume found --- end of the world
2336 if (!nextVol) {
2337 ATH_MSG_DEBUG(" [+] World boundary reached - at " << positionOutput(
2338 nextPar->position()) << ", timed at " << cache.m_time);
2340 } else {
2341 ATH_MSG_DEBUG(" [+] Crossing to next volume '" << nextVol->volumeName() << "'");
2342 ATH_MSG_DEBUG(" [+] Crossing position is - at " << positionOutput(nextPar->position()));
2343 }
2344
2345 cache.m_parametersAtBoundary.boundaryInformation(nextVol, nextPar, nextPar);
2346
2347 return {nextPar, nextVol, cache.m_currentStatic};
2348}
std::pair< size_t, float > distanceToNext(const Amg::Vector3D &position, const Amg::Vector3D &direction, size_t ba=0) const
Distance estimate to next bin.
Definition BinUtility.h:154
size_t bin(const Amg::Vector3D &position, size_t ba=0) const
Bin from a 3D vector (already in binning frame)
Definition BinUtility.h:126
const Trk::BinUtility * layerBinUtility(const Amg::Vector3D &position) const
access to layer bin utility
double second() const
Distance to second intersection solution along direction (for a cylinder surface)
int numberOfSolutions() const
Number of intersection solutions.
double first() const
Distance to first intersection solution along direction.
float x0() const
Definition Material.h:227
float averageZ() const
Definition Material.h:228
virtual DistanceSolution straightLineDistanceEstimate(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const =0
fast straight line distance evaluation to Surface
virtual bool isOnSurface(const Amg::Vector3D &glopo, const BoundaryCheck &bchk=true, double tol1=0., double tol2=0.) const
This method returns true if the GlobalPosition is on the Surface for both, within or without check of...
Definition Surface.cxx:123
const std::string process
@ oppositeMomentum
CurvilinearParametersT< TrackParametersDim, Charged, PlaneSurface > CurvilinearParameters
std::vector< Trk::DestBound > m_trStaticBounds

◆ transportNeutralsWithPathLimit()

std::unique_ptr< const Trk::TrackParameters > Trk::TimedExtrapolator::transportNeutralsWithPathLimit ( const Trk::TrackParameters & parm,
Trk::PathLimit & pathLim,
Trk::TimeLimit & time,
Trk::PropDirection dir,
Trk::ParticleHypothesis particle,
std::vector< Trk::HitInfo > *& hitVector,
Trk::GeometrySignature & nextGeoId,
const Trk::TrackingVolume * boundaryVol = nullptr ) const
overridevirtual

Transport method for neutral, possibly unstable particles.

The extrapolation is interrupted at subdetector boundary for surviving/stable particles.

Implements Trk::ITimedExtrapolator.

Definition at line 1268 of file TimedExtrapolator.cxx.

1274 {
1275 Trk::TimedExtrapolator::Cache cache(m_maxNavigSurf);
1276// extrapolation method intended for simulation of particle decay; collects the material up to pre-defined limit and
1277// triggers
1278// material interaction
1279// possible outcomes:1/ returns curvilinear parameters after reaching the maximal path (if to be destroyed)
1280// 2/ returns parameters at destination volume boundary
1281// 3/ returns 0 ( particle stopped ) but keeps material and timing info
1282
1284 "M-[" << ++cache.m_methodSequence << "] transportNeutralsWithPathLimit(...) " << pathLim.x0Max << ", from " <<
1285 parm.position());
1286
1287 // reset the path ( in x0 !!)
1288 cache.m_path = PathLimit(pathLim.x0Max - pathLim.x0Collected, pathLim.process); // collect material locally
1289
1290 // initialize time info
1291 cache.m_time = timeLim.time;
1292
1293 // initialize hit vector
1294 cache.m_hitVector = hitInfo;
1295
1296 cache.m_parametersAtBoundary.resetBoundaryInformation();
1297
1298 // if no input volume, define as highest volume
1299 // const Trk::TrackingVolume* destVolume = boundaryVol ? boundaryVol : m_navigator->highestVolume();
1300 cache.m_currentStatic = nullptr;
1301 if (boundaryVol && !boundaryVol->inside(parm.position(), m_tolerance)) {
1302 return nullptr;
1303 }
1304
1305 cache.m_particleMass = Trk::ParticleMasses::mass[particle];
1306
1307 // extrapolate to destination volume boundary with path limit
1308 std::unique_ptr<const Trk::TrackParameters> returnParms =
1310 cache, parm, timeLim, dir, particle, nextGeoID, boundaryVol);
1311
1312 // save actual path on output
1313 if (cache.m_path.x0Collected > 0.) {
1314 pathLim.updateMat(cache.m_path.x0Collected, cache.m_path.weightedZ / cache.m_path.x0Collected, cache.m_path.l0Collected);
1315 }
1316
1317 // return timing
1318 timeLim.time = cache.m_time;
1319
1320 std::map<const Trk::TrackParameters *, bool>::iterator garbageIter = cache.m_garbageBin.begin();
1321 std::map<const Trk::TrackParameters *, bool>::iterator garbageEnd = cache.m_garbageBin.end();
1322 for (; garbageIter != garbageEnd; ++garbageIter) if (garbageIter->first) {
1323 if(garbageIter->first == returnParms.get()) {
1324 auto ret=returnParms->uniqueClone();
1325 ATH_MSG_DEBUG(" [+] garbage - at "
1326 << positionOutput(garbageIter->first->position())
1327 << " parm=" << garbageIter->first
1328 << " is the return param. Cloning to" << ret.get());
1329 returnParms=std::move(ret);
1330 }
1331 }
1332
1333 return returnParms;
1334}
std::unique_ptr< const Trk::TrackParameters > transportToVolumeWithPathLimit(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoId, const Trk::TrackingVolume *boundaryVol) const
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses

◆ transportToVolumeWithPathLimit()

std::unique_ptr< const Trk::TrackParameters > Trk::TimedExtrapolator::transportToVolumeWithPathLimit ( Trk::TimedExtrapolator::Cache & cache,
const Trk::TrackParameters & parm,
Trk::TimeLimit & time,
Trk::PropDirection dir,
Trk::ParticleHypothesis particle,
Trk::GeometrySignature & nextGeoId,
const Trk::TrackingVolume * boundaryVol ) const
private

Definition at line 1337 of file TimedExtrapolator.cxx.

1345{
1346 // returns:
1347 // A) curvilinear track parameters if path or time limit reached
1348 // B) boundary parameters (at destination volume boundary)
1349
1350 // initialize the return parameters vector
1351 std::unique_ptr<const Trk::TrackParameters> returnParameters = nullptr;
1352 const Trk::TrackParameters *currPar = &parm;
1353 const Trk::TrackingVolume *currVol = nullptr;
1354 const Trk::TrackingVolume *nextVol = nullptr;
1355 const Trk::TrackingVolume *assocVol = nullptr;
1356 // int nEntryLays = 0;
1357 unsigned int iDest = 0;
1358
1359 const EventContext& ctx = Gaudi::Hive::currentContext();
1360 // destination volume boundary ?
1361 if (destVol && m_navigator->atVolumeBoundary(currPar, destVol, dir, nextVol, m_tolerance) && nextVol != destVol) {
1362 return parm.uniqueClone();
1363 }
1364
1365 // bool resolveActive = m_resolveActive;
1366 if (!cache.m_highestVolume) {
1367 cache.m_highestVolume = m_navigator->highestVolume(ctx);
1368 }
1369
1370 emptyGarbageBin(cache,&parm);
1371 // transport surfaces: collect only those with valid intersection (easy to calculate for neutrals)
1372 if (cache.m_trSurfs.capacity() > m_maxNavigSurf) {
1373 cache.m_trSurfs.reserve(m_maxNavigSurf);
1374 }
1375 cache.m_trSurfs.clear();
1376
1377 // target volume may not be part of tracking geometry
1378 if (destVol) {
1379 const Trk::TrackingVolume *tgVol = m_navigator->trackingGeometry(ctx)->trackingVolume(destVol->volumeName());
1380 if (!tgVol || tgVol != destVol) {
1381 const auto& bounds = destVol->boundarySurfaces();
1382 for (unsigned int ib = 0; ib < bounds.size(); ib++) {
1383 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
1384 Trk::DistanceSolution distSol = surf.straightLineDistanceEstimate(currPar->position(),
1385 dir * currPar->momentum().normalized());
1386 if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1387 // boundary check
1388 Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1389 if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1390 iDest++;
1391 cache.m_trSurfs.emplace_back(&surf, distSol.first());
1392 } // valid intersection
1393 } // along path
1394 if (distSol.numberOfSolutions() > 1 && distSol.second() > 0.) {
1395 // boundary check
1396 Amg::Vector3D gp = currPar->position() + distSol.second() * dir * currPar->momentum().normalized();
1397 if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1398 iDest++;
1399 cache.m_trSurfs.emplace_back(&surf, distSol.second());
1400 } // valid intersection
1401 }
1402 } // end loop over boundaries
1403 } // end process external volume
1404 }
1405
1406 // resolve current position
1407 if (cache.m_parametersAtBoundary.nextParameters == currPar) {
1409 } else {
1410 const Amg::Vector3D& gp = parm.position();
1411 if (!cache.m_currentStatic || !cache.m_currentStatic->inside(gp, m_tolerance)) {
1412 cache.m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
1413
1414 if (!cache.m_currentStatic ||
1415 !cache.m_currentStatic->inside(currPar->position() + 0.01 * dir * currPar->momentum().normalized(), 0.)) {
1416 cache.m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(currPar->position()
1417 + 0.01 * dir *
1418 currPar->momentum().normalized());
1419 }
1420 }
1421
1422 if (!cache.m_currentStatic) {
1423 // no next volume found --- end of the world
1424 ATH_MSG_DEBUG(" [+] Word boundary reached - at " << positionOutput(currPar->position()));
1426 return currPar->uniqueClone();
1427 }
1428 }
1429
1430 // current frame volume known-retrieve geoID
1431 nextGeoID = cache.m_currentStatic->geometrySignature();
1432
1433 // resolve active Calo volumes if hit info required
1434 if (cache.m_hitVector && nextGeoID == Trk::Calo) {
1435 const Trk::AlignableTrackingVolume *alignTV = dynamic_cast<const Trk::AlignableTrackingVolume *> (cache.m_currentStatic);
1436 if (alignTV) {
1437 const Trk::TrackParameters *aPar = transportInAlignableTV(cache,parm, timeLim, dir, particle, nextGeoID, alignTV).trPar;
1438 if (!aPar) {
1439 return returnParameters;
1440 }
1441 throwIntoGarbageBin(cache,aPar);
1442 return transportToVolumeWithPathLimit(cache,*aPar, timeLim, dir, particle, nextGeoID, destVol);
1443 }
1444 }
1445
1446 // distance to static volume boundaries recalculated
1447 // retrieve boundaries along path
1448 cache.m_trStaticBounds.clear();
1449 const auto& bounds = cache.m_currentStatic->boundarySurfaces();
1450 for (unsigned int ib = 0; ib < bounds.size(); ++ib) {
1451 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
1452 Trk::DistanceSolution distSol = surf.straightLineDistanceEstimate(currPar->position(),
1453 dir * currPar->momentum().normalized());
1454 if (distSol.numberOfSolutions() > 0 &&
1455 (distSol.currentDistance(false) > m_tolerance || distSol.numberOfSolutions() > 1) &&
1456 distSol.first() > m_tolerance) {
1457 double dist = distSol.first();
1458 // resolve multiple intersection solutions
1459 if (distSol.numberOfSolutions() > 1 && dist < m_tolerance && distSol.second() > dist) {
1460 dist = distSol.second();
1461 }
1462 // boundary check
1463 Amg::Vector3D gp = currPar->position() + dist * dir * currPar->momentum().normalized();
1464 if (surf.isOnSurface(gp, true, m_tolerance, m_tolerance)) {
1465 cache.m_trStaticBounds.insert(cache.m_trStaticBounds.begin(), Trk::DestBound(&surf, dist, ib));
1466 }
1467 } // along path
1468 if (distSol.numberOfSolutions() > 1 && distSol.second() > m_tolerance) {
1469 double dist = distSol.second();
1470 // boundary check
1471 Amg::Vector3D gp = currPar->position() + dist * dir * currPar->momentum().unit();
1472 if (surf.isOnSurface(gp, true, m_tolerance, m_tolerance)) {
1473 if (dist > m_tolerance) { // valid intersection
1474 cache.m_trStaticBounds.insert(cache.m_trStaticBounds.begin(), Trk::DestBound(&surf, dist, ib));
1475 }
1476 }
1477 } // along path
1478 } // end loop over boundaries
1479
1480 if (cache.m_trStaticBounds.empty()) {
1482 " transportToVolumeWithPathLimit() - at " << currPar->position() << ", missing static volume boundary "
1483 << cache.m_currentStatic->volumeName() <<
1484 ": transport interrupted");
1485
1487 "---> particle R,phi,z, momentum:" << currPar->position().perp() << "," << currPar->position().phi() << "," << currPar->position().z() << "," <<
1488 currPar->momentum());
1489 ATH_MSG_DEBUG("---> static volume position:" << cache.m_currentStatic->center());
1490 const Trk::CylinderVolumeBounds *cyl =
1491 dynamic_cast<const Trk::CylinderVolumeBounds *> (&(cache.m_currentStatic->volumeBounds()));
1492 if (cyl) {
1494 "---> cylinder volume dimensions:" << cyl->innerRadius() << "," << cyl->outerRadius() << "," <<
1495 cyl->halflengthZ());
1496 }
1497
1498
1499 for (unsigned int ib = 0; ib < bounds.size(); ib++) {
1500 const Trk::Surface &surf = (bounds[ib])->surfaceRepresentation();
1501 Trk::DistanceSolution distSol = surf.straightLineDistanceEstimate(currPar->position(),
1502 dir * currPar->momentum().unit());
1504 "---> decomposed boundary surface position, normal, estimated distance:" << ib << "," << surf.center() << "," <<
1505 surf.normal());
1507 "---> estimated distance to (first solution):boundary check:" << distSol.numberOfSolutions() << "," << distSol.first() << ":" <<
1508 surf.isOnSurface(currPar->position() + distSol.first() * dir * currPar->momentum().unit(), true,
1510 if (distSol.numberOfSolutions() > 1) {
1511 ATH_MSG_DEBUG("---> estimated distance to (second solution):boundary check:" << distSol.second() << "," <<
1512 surf.isOnSurface(currPar->position() + distSol.second() * dir * currPar->momentum().unit(), true,
1514 }
1515 }
1516
1517 return returnParameters;
1518 } if (cache.m_trStaticBounds[0].distance < m_tolerance) {
1519 // TODO find out why this case (=exit from volume) haven't been handled by Navigator
1520 // ATH_MSG_WARNING( " recovering from glitch at the static volume boundary:"<<cache.m_trStaticBounds[0].distance );
1521
1522 Amg::Vector3D gp = currPar->position() + m_tolerance * dir * currPar->momentum().unit();
1523 cache.m_currentStatic = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(gp);
1524
1525 if (cache.m_currentStatic) {
1526 return transportToVolumeWithPathLimit(cache,parm, timeLim, dir, particle, nextGeoID, destVol);
1527 }
1528 ATH_MSG_DEBUG(" [+] World boundary reached - at " << positionOutput(
1529 currPar->position()) << ", timed at " << cache.m_time);
1531 // if (!destVol) { return currPar;}
1532 return currPar->uniqueClone();
1533
1534 }
1535
1536 cache.m_detachedVols.clear();
1537 cache.m_denseVols.clear();
1538 cache.m_trDenseBounds.clear();
1539 cache.m_trLays.clear();
1540 cache.m_navigLays.clear();
1541
1542 // detached volume boundaries
1544 if (!detVols.empty()) {
1545 Trk::ArraySpan<const Trk::DetachedTrackingVolume* const>::iterator iTer = detVols.begin();
1546 for (; iTer != detVols.end(); ++iTer) {
1547 // active station ?
1548 const Trk::Layer *layR = (*iTer)->layerRepresentation();
1549 bool active = layR && layR->layerType();
1550
1551 if (active) {
1552 if (!m_resolveMultilayers || (*iTer)->multilayerRepresentation().empty()) {
1553 const Trk::Surface &surf = layR->surfaceRepresentation();
1554 Trk::DistanceSolution distSol = surf.straightLineDistanceEstimate(currPar->position(),
1555 dir * currPar->momentum().normalized());
1556 if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1557 // boundary check
1558 Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1559 if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1560 cache.m_trLays.emplace_back(&surf, distSol.first());
1561 cache.m_navigLays.emplace_back((*iTer)->trackingVolume(), layR);
1562 }
1563 }
1564 } else {
1565 const auto& multi = (*iTer)->multilayerRepresentation();
1566 for (const auto *i : multi) {
1567 const Trk::Surface &surf = i->surfaceRepresentation();
1568 Trk::DistanceSolution distSol = surf.straightLineDistanceEstimate(currPar->position(),
1569 dir * currPar->momentum().normalized());
1570 if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1571 // boundary check
1572 Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1573 if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1574 cache.m_trLays.emplace_back(&surf, distSol.first());
1575 cache.m_navigLays.emplace_back((*iTer)->trackingVolume(), i);
1576 }
1577 }
1578 } // end loop over multilayers
1579 } // end unresolved active
1580 } // active done
1582 (*iTer)->name().substr((*iTer)->name().size() - 4, 4) == "PERM") { // retrieve inert detached objects
1583 // only if needed
1584 // dense volume boundaries
1585 if ((*iTer)->trackingVolume()->zOverAtimesRho() != 0. &&
1586 ((*iTer)->trackingVolume()->confinedDenseVolumes().empty())
1587 && ((*iTer)->trackingVolume()->confinedArbitraryLayers().empty())) {
1588 const auto& detBounds = (*iTer)->trackingVolume()->boundarySurfaces();
1589 int newB = 0;
1590 for (unsigned int ibb = 0; ibb < detBounds.size(); ibb++) {
1591 const Trk::Surface &surf = (detBounds[ibb])->surfaceRepresentation();
1592 Trk::DistanceSolution distSol = surf.straightLineDistanceEstimate(currPar->position(),
1593 dir * currPar->momentum().normalized());
1594 if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1595 // boundary check
1596 Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1597 if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1598 cache.m_trDenseBounds.emplace_back(&surf, distSol.first());
1599 newB++;
1600 } // valid intersection
1601 } // along path
1602 } // end loop over boundaries
1603 if (newB > 0) {
1604 cache.m_denseVols.emplace_back((*iTer)->trackingVolume(), newB);
1605 }
1606 }
1607 // subvolumes ?
1608 // if ((*iTer)->trackingVolume()->confinedDenseVolumes() &&
1609 // (*iTer)->trackingVolume()->confinedDenseVolumes()->size())
1610 // ATH_MSG_WARNING( " transportToVolumeWithPathLimit() - at " << currPar->position() <<", unresolved
1611 // subvolumes for "
1612 // << (*iTer)->trackingVolume()->volumeName() );
1613
1614 const auto confinedDense =
1615 (*iTer)->trackingVolume()->confinedDenseVolumes();
1616 if (!confinedDense.empty()) {
1617 auto vIter = confinedDense.begin();
1618 for (; vIter != confinedDense.end(); ++vIter) {
1619 const auto& bounds = (*vIter)->boundarySurfaces();
1620 int newB = 0;
1621 for (unsigned int ibb = 0; ibb < bounds.size(); ibb++) {
1622 const Trk::Surface &surf = (bounds[ibb])->surfaceRepresentation();
1623 Trk::DistanceSolution distSol = surf.straightLineDistanceEstimate(currPar->position(),
1624 dir * currPar->momentum().normalized());
1625 if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1626 // boundary check
1627 Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1628 if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1629 cache.m_trDenseBounds.emplace_back(&surf, distSol.first());
1630 newB++;
1631 } // valid intersection
1632 } // along path
1633 } // end loop over boundaries
1634 if (newB > 0) {
1635 cache.m_denseVols.emplace_back((*vIter), newB);
1636 }
1637 if (!(*vIter)->confinedArbitraryLayers().empty()) {
1639 " transportToVolumeWithPathLimit() - at " << currPar->position() << ", unresolved sublayers/subvolumes for "
1640 << (*vIter)->volumeName());
1641 }
1642 }
1643 }
1644
1645 // confined layers
1646 Trk::ArraySpan<const Trk::Layer* const>confLays = (*iTer)->trackingVolume()->confinedArbitraryLayers();
1647 if (!confLays.empty()) {
1648 for (const Trk::Layer* const lIt: confLays) {
1649 const Trk::Surface &surf = lIt->surfaceRepresentation();
1650 Trk::DistanceSolution distSol = surf.straightLineDistanceEstimate(currPar->position(),
1651 dir * currPar->momentum().normalized());
1652 if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1653 // boundary check
1654 Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1655 if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1656 cache.m_trLays.emplace_back(&surf, distSol.first());
1657 cache.m_navigLays.emplace_back((*iTer)->trackingVolume(), lIt);
1658 } // valid intersection
1659 } // along path
1660 }
1661 } // end confined layers
1662 } // end inert material
1663 }
1664 } // end detached volumes
1665 cache.m_denseResolved = std::pair<unsigned int, unsigned int> (cache.m_denseVols.size(), cache.m_trDenseBounds.size());
1666 cache.m_layerResolved = cache.m_trLays.size();
1667
1668 std::vector< Trk::DestBound >::iterator bIter = cache.m_trStaticBounds.begin();
1669 while (bIter != cache.m_trStaticBounds.end()) {
1670 cache.m_trSurfs.emplace_back((*bIter).surface, (*bIter).distance);
1671 ++bIter;
1672 }
1673
1674 // std::cout <<"navigation in current static:"<< cache.m_trSurfs.size()<<","<<cache.m_trStaticBounds.size()<< std::endl;
1675 // for (unsigned int ib=0; ib<cache.m_trSurfs.size(); ib++) std::cout <<"distance to static:"<<
1676 // ib<<","<<cache.m_trSurfs[ib].second<<std::endl;
1677
1678 // resolve the use of dense volumes
1681
1682 // reset remaining counters
1683 cache.m_currentDense = cache.m_dense ? cache.m_currentStatic : cache.m_highestVolume;
1684 cache.m_navigBoundaries.clear();
1685 if (cache.m_denseVols.size() > cache.m_denseResolved.first) {
1686 cache.m_denseVols.resize(cache.m_denseResolved.first);
1687 cache.m_trDenseBounds.resize(cache.m_denseResolved.second);
1688 }
1689 if (cache.m_layers.size() > cache.m_layerResolved) {
1690 cache.m_trLays.resize(cache.m_layerResolved);
1691 cache.m_navigLays.resize(cache.m_layerResolved);
1692 }
1693
1694 // if (cache.m_currentStatic->entryLayerProvider()) nEntryLays = cache.m_currentStatic->entryLayerProvider()->layers().size();
1695
1696 // confined layers
1697 if (cache.m_currentStatic->confinedLayers()) {
1698 std::span <Trk::Layer const * const> cLays = cache.m_currentStatic->confinedLayers()->arrayObjects();
1699 for (const auto *cLay : cLays) {
1700 if (cLay->layerMaterialProperties()) {
1701 const Trk::Surface &surf = cLay->surfaceRepresentation();
1702 Trk::DistanceSolution distSol = surf.straightLineDistanceEstimate(currPar->position(),
1703 dir * currPar->momentum().normalized());
1704 if (distSol.numberOfSolutions() > 0 && distSol.first() > 0.) {
1705 // boundary check
1706 Amg::Vector3D gp = currPar->position() + distSol.first() * dir * currPar->momentum().normalized();
1707 if (surf.isOnSurface(gp, true, 0.001, 0.001)) {
1708 cache.m_trLays.emplace_back(&surf, distSol.first());
1709 cache.m_navigLays.emplace_back(cache.m_currentStatic,
1710 cLay);
1711 } // valid intersection
1712 } // along path
1713 }
1714 }
1715 }
1716
1717 // cache.m_trSurfs contains destination surface (if it exists), static volume boundaries
1718 // complete with TG cache.m_layers/dynamic layers, cache.m_denseBoundaries, cache.m_navigBoundaries, m_detachedBoundaries
1719
1720 if (!cache.m_trLays.empty()) {
1721 cache.m_trSurfs.insert(cache.m_trSurfs.end(), cache.m_trLays.begin(), cache.m_trLays.end());
1722 }
1723 if (!cache.m_trDenseBounds.empty()) {
1724 cache.m_trSurfs.insert(cache.m_trSurfs.end(), cache.m_trDenseBounds.begin(), cache.m_trDenseBounds.end());
1725 }
1726
1727 // current dense
1728 cache.m_currentDense = cache.m_highestVolume;
1729
1730 for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
1731 const Trk::TrackingVolume *dVol = cache.m_denseVols[i].first;
1732 if (dVol->inside(currPar->position(), m_tolerance) && dVol->zOverAtimesRho() != 0.) {
1733 if (!m_navigator->atVolumeBoundary(currPar, dVol, dir, nextVol, m_tolerance) ||
1734 dVol->inside(currPar->position() + 2 * m_tolerance * currPar->momentum().unit(), m_tolerance)) {
1735 cache.m_currentDense = dVol;
1736 }
1737 }
1738 }
1739
1740 if (cache.m_dense && cache.m_currentDense == cache.m_highestVolume) {
1741 cache.m_currentDense = cache.m_currentStatic;
1742 }
1743
1744 // ready to process
1745 // 1/ order valid intersections ( already in trSurfs )
1746
1747 std::vector<unsigned int> sols;
1748 sols.reserve(cache.m_trSurfs.size());
1749 for (unsigned int i = 0; i < cache.m_trSurfs.size(); ++i) {
1750 sols.push_back(i);
1751 }
1752
1753 if (sols.size() > 1) {
1754 unsigned int itest = 1;
1755 while (itest < sols.size()) {
1756 if (cache.m_trSurfs[sols[itest]].second < cache.m_trSurfs[sols[itest - 1]].second) {
1757 unsigned int iex = sols[itest - 1];
1758 sols[itest - 1] = sols[itest];
1759 sols[itest] = iex;
1760 itest = 1;
1761 } else {
1762 itest++;
1763 }
1764 }
1765 // check ordering
1766 for (unsigned int is = 1; is < sols.size(); is++) {
1767 if (cache.m_trSurfs[sols[is]].second < cache.m_trSurfs[sols[is - 1]].second) {
1768 std::cout << "wrong intersection ordering" << std::endl;
1769 }
1770 }
1771 }
1772
1773
1774 // 2/ check time/material/boundary limit
1775
1776 // update of cache.m_navigSurfs required if I/ entry into new navig volume, II/ exit from currentActive without overlaps
1777
1778 nextVol = nullptr;
1779 const Trk::TrackParameters *nextPar = nullptr;
1780
1781 double dist = 0.;
1782 double mom = currPar->momentum().mag();
1783 double beta = mom / sqrt(mom * mom + cache.m_particleMass * cache.m_particleMass) * Gaudi::Units::c_light;
1784
1785 ATH_MSG_DEBUG(" [0] starting transport of neutral particle in (dense) volume " << cache.m_currentDense->volumeName());
1786
1787 for (unsigned int sol : sols) {
1788 if (cache.m_trSurfs[sol].second == 0.) {
1789 continue;
1790 }
1791
1792 double step = cache.m_trSurfs[sol].second - dist;
1793
1794 Amg::Vector3D nextPos = currPar->position() + dir * currPar->momentum().normalized() * cache.m_trSurfs[sol].second;
1795 // Amg::Vector3D halfStep = nextPos - 0.5*step*dir*currPar->momentum().normalized();
1796
1797 // check missing volume boundary
1798 if (!(cache.m_currentDense->inside(nextPos, m_tolerance))) {
1799 ATH_MSG_DEBUG(" [!] WARNING: missing volume boundary for volume" << cache.m_currentDense->volumeName());
1800 // new search
1801 cache.m_currentDense = cache.m_highestVolume;
1802 for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
1803 const Trk::TrackingVolume *dVol = cache.m_denseVols[i].first;
1804 if (dVol->inside(nextPos, m_tolerance) && dVol->zOverAtimesRho() != 0.) {
1805 cache.m_currentDense = dVol;
1806 }
1807 }
1808 if (cache.m_dense && cache.m_currentDense == cache.m_highestVolume) {
1809 cache.m_currentDense = cache.m_currentStatic;
1810 }
1811
1812 ATH_MSG_DEBUG(" [!] new search for dense volume : " << cache.m_currentDense->volumeName());
1813 }
1814
1815 double tDelta = step / beta;
1816
1817 double mDelta = (cache.m_currentDense->zOverAtimesRho() != 0.) ? step / cache.m_currentDense->x0() : 0.;
1818
1819 // in case of hadronic interaction retrieve nuclear interaction properties, too
1820
1821 double frT = 1.;
1822 if (step > 0 && timeLim.tMax > cache.m_time && cache.m_time + tDelta >= timeLim.tMax) {
1823 frT = (timeLim.tMax - cache.m_time) * beta / step;
1824 }
1825
1826 // TODO : compare x0 or l0 according to the process type
1827 double frM = 1.;
1828 if (mDelta > 0 && cache.m_path.x0Max > 0.) {
1829 if (cache.m_path.process < 100 && cache.m_path.x0Collected + mDelta > cache.m_path.x0Max) {
1830 frM = (cache.m_path.x0Max - cache.m_path.x0Collected) / mDelta;
1831 } else { // waiting for hadronic interaction, retrieve nuclear interaction properties
1832 double mDeltaL = cache.m_currentDense->L0 >
1833 0. ? step / cache.m_currentDense->L0 : mDelta / 0.37 / cache.m_currentDense->averageZ();
1834 if (cache.m_path.l0Collected + mDeltaL > cache.m_path.x0Max) {
1835 frM = (cache.m_path.x0Max - cache.m_path.l0Collected) / mDeltaL;
1836 }
1837 }
1838 }
1839
1840 double fr = fmin(frT, frM);
1841
1842 // std::cout << "looping over intersections:"<<is<<","<< cache.m_trSurfs[sols[is]].second<<","<<step << ","<<
1843 // tDelta<<","<<mDelta << std::endl;
1844
1845 if (fr < 1.) { // decay or material interaction during the step
1846 int process = frT < frM ? timeLim.process : cache.m_path.process;
1847 cache.m_time += fr * step / beta;
1848 if (mDelta > 0 && cache.m_currentDense->averageZ() > 0) {
1849 cache.m_path.updateMat(fr * mDelta, cache.m_currentDense->averageZ(), 0.);
1850 }
1851
1852 nextPos = currPar->position() + dir * currPar->momentum().normalized() * (dist + fr * step);
1853
1854 // process interaction only if creation of secondaries allowed
1856 const Trk::TrackParameters* nextPar =
1857 m_updators[0]
1858 ->interact(cache.m_time, nextPos, currPar->momentum(), particle, process, cache.m_currentDense)
1859 .release();
1860
1861 if (nextPar) {
1862 ATH_MSG_DEBUG(" [!] WARNING: particle survives the interaction " << process);
1863 }
1864
1865 if (nextPar && process == 121) {
1866 ATH_MSG_DEBUG(" [!] WARNING: failed hadronic interaction, killing the input particle anyway");
1867 return returnParameters;
1868 }
1869
1870 if (!nextPar) {
1871 return returnParameters;
1872 }
1873
1874 throwIntoGarbageBin(cache,nextPar);
1875 // return transportToVolumeWithPathLimit(cache,*nextPar, timeLim, dir, particle, nextGeoID, destVol);
1876 } else { // kill particle without trace
1877 return returnParameters;
1878 }
1879 } // end decay or material interaction durign the step
1880
1881 // update
1882 dist = cache.m_trSurfs[sol].second;
1883 if (mDelta > 0 && cache.m_currentDense->averageZ() > 0) {
1884 cache.m_path.updateMat(mDelta, cache.m_currentDense->averageZ(), 0.);
1885 }
1886 cache.m_time += tDelta;
1887
1888 nextPar = new Trk::CurvilinearParameters(nextPos, currPar->momentum(), 1.); // fake charge
1889 throwIntoGarbageBin(cache,nextPar);
1890
1891 if (sol < iDest) { // destination volume (most often, subdetector boundary)
1892 return nextPar->uniqueClone();
1893 } if (sol < iDest + cache.m_trStaticBounds.size()) { // tracking geometry frame
1894 // material attached ?
1895 const Trk::Layer *mb = cache.m_trStaticBounds[sol - iDest].surface->materialLayer();
1896 if (mb && m_includeMaterialEffects) {
1897 if (mb->layerMaterialProperties() && mb->layerMaterialProperties()->fullMaterial(nextPos)) {
1898 const ITimedMatEffUpdator *currentUpdator = subMaterialEffectsUpdator(*cache.m_currentStatic);
1899 nextPar =
1900 currentUpdator
1901 ? currentUpdator
1902 ->update(
1903 nextPar, *mb, timeLim, cache.m_path, cache.m_currentStatic->geometrySignature(), dir, particle)
1904 .release()
1905 : nextPar;
1906
1907 if (!nextPar) {
1908 ATH_MSG_VERBOSE(" [+] Update may have killed neutral track - return.");
1910 return returnParameters;
1911 }
1912 throwIntoGarbageBin(cache,nextPar);
1913
1914 } else { // material layer without material ?
1915 ATH_MSG_VERBOSE(" boundary layer without material:" << mb->layerIndex());
1916 }
1917 }
1918
1919 // static volume boundary; return to the main loop
1920 unsigned int index = cache.m_trStaticBounds[sol - iDest].bIndex;
1921 // use global coordinates to retrieve attached volume (just for static!)
1922 nextVol = (cache.m_currentStatic->boundarySurfaces())[index]->attachedVolume(
1923 nextPar->position(), nextPar->momentum(), dir);
1924 // double check the next volume
1925 if (nextVol && !(nextVol->inside(nextPar->position() + 0.01 * dir * nextPar->momentum().normalized(), 0.))) {
1927 " [!] WARNING: wrongly assigned static volume ?" << cache.m_currentStatic->volumeName() << "->" <<
1928 nextVol->volumeName());
1929 nextVol = m_navigator->trackingGeometry(ctx)->lowestStaticTrackingVolume(
1930 nextPar->position() + 0.01 * dir * nextPar->momentum().normalized());
1931 if (nextVol) {
1932 ATH_MSG_DEBUG(" new search yields: " << nextVol->volumeName());
1933 }
1934 }
1935 // end double check - to be removed after validation of the geometry gluing
1936 if (nextVol != cache.m_currentStatic) {
1937 ATH_MSG_DEBUG(" [+] StaticVol boundary reached of '" << cache.m_currentStatic->volumeName() << "'.");
1938 if (m_navigator->atVolumeBoundary(nextPar, cache.m_currentStatic, dir, assocVol,
1939 m_tolerance) && assocVol != cache.m_currentStatic) {
1940 cache.m_currentDense = cache.m_dense ? nextVol : cache.m_highestVolume;
1941 }
1942 // no next volume found --- end of the world
1943 if (!nextVol) {
1944 ATH_MSG_DEBUG(" [+] World boundary reached - at " << positionOutput(
1945 nextPar->position()) << ", timed at " << cache.m_time);
1947 return nextPar->uniqueClone();
1948 }
1949 // next volume found and parameters are at boundary
1950 if (nextVol /*&& nextPar nextPar is dereferenced anyway*/) {
1951 ATH_MSG_DEBUG(" [+] Crossing to next volume '" << nextVol->volumeName() << "'");
1952 ATH_MSG_DEBUG(" [+] Crossing position is - at " << positionOutput(nextPar->position()));
1953 if (!destVol && cache.m_currentStatic->geometrySignature() != nextVol->geometrySignature()) {
1954 nextGeoID = nextVol->geometrySignature();
1955 return nextPar->uniqueClone();
1956 }
1957 }
1958 cache.m_parametersAtBoundary.boundaryInformation(nextVol, nextPar, nextPar);
1959 return transportToVolumeWithPathLimit(cache,*nextPar, timeLim, dir, particle, nextGeoID, destVol);
1960 }
1961 if (dist > 0.) {
1962 return transportToVolumeWithPathLimit(cache,*nextPar, timeLim, dir, particle, nextGeoID, destVol);
1963 }
1964 } else if (sol < iDest + cache.m_trStaticBounds.size() + cache.m_trLays.size()) { // layer
1965 // material thickness - simple approach
1966 unsigned int index = sol - iDest - cache.m_trStaticBounds.size();
1967 const Trk::Layer *nextLayer = cache.m_navigLays[index].second;
1968
1969 bool matUp = nextLayer->layerMaterialProperties()->fullMaterial(nextPos) && m_includeMaterialEffects;
1970
1971 // material update
1972 if (matUp && m_includeMaterialEffects) {
1973 const ITimedMatEffUpdator *currentUpdator = subMaterialEffectsUpdator(*cache.m_currentStatic);
1974
1975 nextPar = currentUpdator ? currentUpdator
1976 ->update(nextPar,
1977 *nextLayer,
1978 timeLim,
1979 cache.m_path,
1981 dir,
1982 particle)
1983 .release()
1984 : nextPar;
1985
1986 if (!nextPar) {
1987 ATH_MSG_VERBOSE(" [+] Update may have killed neutral track - return.");
1989 return returnParameters;
1990 }
1991 throwIntoGarbageBin(cache,nextPar);
1992
1993 }
1994 } else if (sol < iDest + cache.m_trStaticBounds.size() + cache.m_trLays.size() + cache.m_trDenseBounds.size()) {
1995 // dense volume boundary : no material update here, navigation only ( set cache.m_currentDense for next step )
1996
1997 unsigned int index = sol - iDest - cache.m_trStaticBounds.size() - cache.m_trLays.size();
1998 std::vector< std::pair<const Trk::TrackingVolume *, unsigned int> >::iterator dIter = cache.m_denseVols.begin();
1999 while (dIter != cache.m_denseVols.end() && index >= (*dIter).second) {
2000 index -= (*dIter).second;
2001 ++dIter;
2002 }
2003 if (dIter != cache.m_denseVols.end()) {
2004 currVol = (*dIter).first;
2005
2006 if (Trk::TrackingGeometry::atVolumeBoundary(nextPos, nextPar->momentum(), currVol, assocVol, dir,
2007 m_tolerance)) {
2008 if (assocVol && assocVol->zOverAtimesRho() != 0.) {
2009 cache.m_currentDense = assocVol;
2010 } else if (currVol->inside(nextPos + 0.002 * dir * nextPar->momentum().normalized())) {
2011 cache.m_currentDense = currVol;
2012 } else {
2013 // new search
2014 cache.m_currentDense = cache.m_highestVolume;
2015 if (m_useMuonMatApprox && cache.m_denseVols.empty()) {
2016 cache.m_currentDense = cache.m_currentStatic;
2017 } else {
2018 for (unsigned int i = 0; i < cache.m_denseVols.size(); i++) {
2019 const Trk::TrackingVolume *dVol = cache.m_denseVols[i].first;
2020 if (dVol->inside(nextPos + 0.002 * dir * nextPar->momentum().normalized(),
2021 m_tolerance) && dVol->zOverAtimesRho() != 0.) {
2022 cache.m_currentDense = dVol;
2023 }
2024 }
2025 }
2026 }
2027 }
2028 }
2029 } else { // detached volume bounds - not relevant ?
2030 }
2031
2032 throwIntoGarbageBin(cache,nextPar);
2033 }
2034
2035
2036
2037 if (nextPar) {
2039 " transportToVolumeWithPathLimit() - return from volume " << cache.m_currentStatic->volumeName() << " at position:" <<
2040 nextPar->position());
2041 return nextPar->uniqueClone();
2042 }
2043 return nullptr;
2044}
double innerRadius() const
This method returns the inner radius.
double halflengthZ() const
This method returns the halflengthZ.
double outerRadius() const
This method returns the outer radius.
double currentDistance(bool signedDist=false) const
Current distance to surface (spatial), signed (along/opposite to surface normal) if input argument tr...
virtual const MaterialProperties * fullMaterial(const Amg::Vector3D &gp) const =0
Return method for full material description of the Layer.
const LayerMaterialProperties * layerMaterialProperties() const
getting the LayerMaterialProperties including full/pre/post update
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
BoundaryTrackParameters transportInAlignableTV(Trk::TimedExtrapolator::Cache &cache, const Trk::TrackParameters &parm, Trk::TimeLimit &time, Trk::PropDirection dir, Trk::ParticleHypothesis particle, Trk::GeometrySignature &nextGeoId, const Trk::AlignableTrackingVolume *aliTV) const
BooleanProperty m_resolveMultilayers
static bool atVolumeBoundary(const Amg::Vector3D &gp, const TrackingVolume *vol, double tol)
check position at volume boundary
const Amg::Vector3D & center() const
returns the center of the volume
Definition Volume.h:90
const VolumeBounds & volumeBounds() const
returns the volumeBounds()
Definition Volume.h:96
const TrackingVolume * nextVolume
< the members
const TrackParameters * nextParameters
std::vector< std::pair< const Trk::Surface *, double > > m_trDenseBounds
std::vector< std::pair< const Trk::Surface *, double > > m_trLays
std::vector< std::pair< const Trk::Surface *, double > > m_trSurfs

◆ updateVHKA()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::updateVHKA ( Gaudi::Details::PropertyBase & )
inlineinherited

Definition at line 308 of file AthCommonDataStore.h.

308 {
309 // debug() << "updateVHKA for property " << p.name() << " " << p.toString()
310 // << " size: " << m_vhka.size() << endmsg;
311 for (auto &a : m_vhka) {
313 for (auto k : keys) {
314 k->setOwner(this);
315 }
316 }
317 }
std::vector< SG::VarHandleKeyArray * > m_vhka

◆ validationAction()

void Trk::TimedExtrapolator::validationAction ( ) const
overridevirtual

Validation Action: Can be implemented optionally, outside access to internal validation steps.

Implements Trk::ITimedExtrapolator.

Definition at line 1259 of file TimedExtrapolator.cxx.

1259 {
1260 // record the updator validation information
1261 for (const auto *subUpdator : m_subUpdators) {
1262 subUpdator->validationAction();
1263 }
1264 // record the navigator validation information
1265}

Member Data Documentation

◆ m_caloMsSecondary

BooleanProperty Trk::TimedExtrapolator::m_caloMsSecondary
private
Initial value:
{this, "CaloMsSecondary", false,
"handling of secondaries beyond ID"}

Definition at line 346 of file TimedExtrapolator.h.

346 {this, "CaloMsSecondary", false,
347 "handling of secondaries beyond ID"};

◆ m_configurationLevel

unsigned int Trk::TimedExtrapolator::m_configurationLevel = 10
private

see the supported levels of configuration above

Definition at line 326 of file TimedExtrapolator.h.

◆ m_detStore

StoreGateSvc_t AthCommonDataStore< AthCommonMsg< AlgTool > >::m_detStore
privateinherited

Pointer to StoreGate (detector store by default)

Definition at line 393 of file AthCommonDataStore.h.

◆ m_elossupdater

ToolHandle<IEnergyLossUpdator> Trk::TimedExtrapolator::m_elossupdater
private
Initial value:
{this,
"EnergyLossUpdater", "Trk::EnergyLossUpdator/AtlasEnergyLossUpdator"}

Definition at line 304 of file TimedExtrapolator.h.

304 {this,
305 "EnergyLossUpdater", "Trk::EnergyLossUpdator/AtlasEnergyLossUpdator"};

◆ m_evtStore

StoreGateSvc_t AthCommonDataStore< AthCommonMsg< AlgTool > >::m_evtStore
privateinherited

Pointer to StoreGate (event store by default)

Definition at line 390 of file AthCommonDataStore.h.

◆ m_fastField

BooleanProperty Trk::TimedExtrapolator::m_fastField {this, "MagneticFieldProperties", false}
private

Definition at line 435 of file TimedExtrapolator.h.

435{this, "MagneticFieldProperties", false};

◆ m_fieldProperties

Trk::MagneticFieldProperties Trk::TimedExtrapolator::m_fieldProperties
private

Definition at line 436 of file TimedExtrapolator.h.

◆ m_includeMaterialEffects

BooleanProperty Trk::TimedExtrapolator::m_includeMaterialEffects
private
Initial value:
{this, "ApplyMaterialEffects", true,
"boolean to switch on/off material effects"}

Definition at line 328 of file TimedExtrapolator.h.

328 {this, "ApplyMaterialEffects", true,
329 "boolean to switch on/off material effects"};

◆ m_initialLayerAttempts

UnsignedIntegerProperty Trk::TimedExtrapolator::m_initialLayerAttempts
private
Initial value:
{this, "InitialLayerAttempts", 3,
"allowed layer intersection attempts at the start of a volume"}

Definition at line 338 of file TimedExtrapolator.h.

338 {this, "InitialLayerAttempts", 3,
339 "allowed layer intersection attempts at the start of a volume"};

◆ m_materialEffectsOnTrackValidation

BooleanProperty Trk::TimedExtrapolator::m_materialEffectsOnTrackValidation
private
Initial value:
{this,
"MaterialEffectsOnTrackValidation", false, "mat effects on track validation"}

Definition at line 371 of file TimedExtrapolator.h.

371 {this,
372 "MaterialEffectsOnTrackValidation", false, "mat effects on track validation"};

◆ m_maxNavigSurf

unsigned int Trk::TimedExtrapolator::m_maxNavigSurf {}
private

Definition at line 373 of file TimedExtrapolator.h.

373{};

◆ m_maxNavigVol

unsigned int Trk::TimedExtrapolator::m_maxNavigVol {}
private

Definition at line 374 of file TimedExtrapolator.h.

374{};

◆ m_meotpIndex

UnsignedIntegerProperty Trk::TimedExtrapolator::m_meotpIndex
private
Initial value:
{
this, "MaterialEffectsOnTrackProviderIndex", 0,
"if several meotps are available in a volume steer which one to use"}

Definition at line 323 of file TimedExtrapolator.h.

323 {
324 this, "MaterialEffectsOnTrackProviderIndex", 0,
325 "if several meotps are available in a volume steer which one to use"};

◆ m_msupdators

ToolHandleArray<IMultipleScatteringUpdator> Trk::TimedExtrapolator::m_msupdators
private
Initial value:
{this,
"MultipleScatteringUpdators", {}, " Array of MultipleScattering Updators"}

Definition at line 302 of file TimedExtrapolator.h.

302 {this,
303 "MultipleScatteringUpdators", {}, " Array of MultipleScattering Updators"};

◆ m_navigationBreakDetails

BooleanProperty Trk::TimedExtrapolator::m_navigationBreakDetails
private
Initial value:
{this, "DetailedNavigationOutput", false,
"steer the output for the navigation break details"}

Definition at line 369 of file TimedExtrapolator.h.

369 {this, "DetailedNavigationOutput", false,
370 "steer the output for the navigation break details"};

◆ m_navigationStatistics

BooleanProperty Trk::TimedExtrapolator::m_navigationStatistics
private
Initial value:
{this, "NavigationStatisticsOutput", false,
"steer the output for the navigation statistics"}

Definition at line 367 of file TimedExtrapolator.h.

367 {this, "NavigationStatisticsOutput", false,
368 "steer the output for the navigation statistics"};

◆ m_navigator

ToolHandle<INavigator> Trk::TimedExtrapolator::m_navigator
private
Initial value:
{this,
"Navigator", "Trk::Navigator/AtlasNavigator",
"Navigator for TrackingGeometry and magnetic fiels access"}

Definition at line 297 of file TimedExtrapolator.h.

297 {this,
298 "Navigator", "Trk::Navigator/AtlasNavigator",
299 "Navigator for TrackingGeometry and magnetic fiels access"};

◆ m_printHelpOutputAtInitialize

BooleanProperty Trk::TimedExtrapolator::m_printHelpOutputAtInitialize {this, "HelpOutput", false}
private

Definition at line 362 of file TimedExtrapolator.h.

362{this, "HelpOutput", false};

◆ m_printRzOutput

BooleanProperty Trk::TimedExtrapolator::m_printRzOutput {this, "positionOutput", true}
private

Definition at line 363 of file TimedExtrapolator.h.

363{this, "positionOutput", true};

◆ m_propagators

ToolHandleArray<IPropagator> Trk::TimedExtrapolator::m_propagators
private
Initial value:
{this,
"Propagators", {}, "Array of Propagators"}

Definition at line 293 of file TimedExtrapolator.h.

293 {this,
294 "Propagators", {}, "Array of Propagators"};

◆ m_propNames

StringArrayProperty Trk::TimedExtrapolator::m_propNames
private
Initial value:
{this, "SubPropagators", {},
"configuration of subPropagators"}

Definition at line 316 of file TimedExtrapolator.h.

316 {this, "SubPropagators", {},
317 "configuration of subPropagators"};

◆ m_referenceMaterial

BooleanProperty Trk::TimedExtrapolator::m_referenceMaterial
private
Initial value:
{this, "ReferenceMaterial", false,
"use the reference material for the update"}

Definition at line 336 of file TimedExtrapolator.h.

336 {this, "ReferenceMaterial", false,
337 "use the reference material for the update"};

◆ m_resolveActive

BooleanProperty Trk::TimedExtrapolator::m_resolveActive {this, "ResolveMuonStation", false}
private

Definition at line 357 of file TimedExtrapolator.h.

357{this, "ResolveMuonStation", false};

◆ m_resolveMultilayers

BooleanProperty Trk::TimedExtrapolator::m_resolveMultilayers {this, "ResolveMultilayers", true}
private

Definition at line 358 of file TimedExtrapolator.h.

358{this, "ResolveMultilayers", true};

◆ m_robustSampling

BooleanProperty Trk::TimedExtrapolator::m_robustSampling {this, "RobustSampling", true}
private

Definition at line 351 of file TimedExtrapolator.h.

351{this, "RobustSampling", true};

◆ m_skipInitialLayerUpdate

BooleanProperty Trk::TimedExtrapolator::m_skipInitialLayerUpdate
private
Initial value:
{this, "SkipInitialPostUpdate", false,
"skip the initial post-Update at the layer [Fatras conversion mode]"}

Definition at line 334 of file TimedExtrapolator.h.

334 {this, "SkipInitialPostUpdate", false,
335 "skip the initial post-Update at the layer [Fatras conversion mode]"};

◆ m_stepPropagator

ToolHandle<IPropagator> Trk::TimedExtrapolator::m_stepPropagator
private
Initial value:
{this,
"STEP_Propagator", "Trk::STEP_Propagator/AtlasSTEP_Propagator"}

Definition at line 295 of file TimedExtrapolator.h.

295 {this,
296 "STEP_Propagator", "Trk::STEP_Propagator/AtlasSTEP_Propagator"};

◆ m_stopWithNavigationBreak

BooleanProperty Trk::TimedExtrapolator::m_stopWithNavigationBreak
private
Initial value:
{this, "StopWithNavigationBreak", false,
"return 0 if navigation breaks - for validation reasons"}

Definition at line 330 of file TimedExtrapolator.h.

330 {this, "StopWithNavigationBreak", false,
331 "return 0 if navigation breaks - for validation reasons"};

◆ m_stopWithUpdateZero

BooleanProperty Trk::TimedExtrapolator::m_stopWithUpdateZero
private
Initial value:
{this, "StopWithUpdateKill", false,
"return 0 if update kills the trajectory"}

Definition at line 332 of file TimedExtrapolator.h.

332 {this, "StopWithUpdateKill", false,
333 "return 0 if update kills the trajectory"};

◆ m_subPropagators

std::vector<const IPropagator*> Trk::TimedExtrapolator::m_subPropagators
private

Propagators to chose from (steered by signature)

Definition at line 310 of file TimedExtrapolator.h.

◆ m_subUpdators

std::vector<const ITimedMatEffUpdator*> Trk::TimedExtrapolator::m_subUpdators
private

Updators to chose from (steered by signature)

Definition at line 312 of file TimedExtrapolator.h.

◆ m_successiveLayerAttempts

UnsignedIntegerProperty Trk::TimedExtrapolator::m_successiveLayerAttempts
private
Initial value:
{
this, "SuccessiveLayerAttempts", 1,
"layer intersection attemps after one layer has been hit sucessfully"}

Definition at line 340 of file TimedExtrapolator.h.

340 {
341 this, "SuccessiveLayerAttempts", 1,
342 "layer intersection attemps after one layer has been hit sucessfully"};

◆ m_tolerance

DoubleProperty Trk::TimedExtrapolator::m_tolerance {this, "Tolerance", 0.002, "surface & volume tolerance"}
private

Definition at line 344 of file TimedExtrapolator.h.

344{this, "Tolerance", 0.002, "surface & volume tolerance"};

◆ m_updatNames

StringArrayProperty Trk::TimedExtrapolator::m_updatNames
private
Initial value:
{this, "SubMEUpdators", {},
"configuration of subupdaters"}

Definition at line 318 of file TimedExtrapolator.h.

318 {this, "SubMEUpdators", {},
319 "configuration of subupdaters"};

◆ m_updators

ToolHandleArray<ITimedMatEffUpdator> Trk::TimedExtrapolator::m_updators
private
Initial value:
{this,
"MaterialEffectsUpdators", {}, "Array of Material Updators"}

Definition at line 300 of file TimedExtrapolator.h.

300 {this,
301 "MaterialEffectsUpdators", {}, "Array of Material Updators"};

◆ m_useDenseVolumeDescription

BooleanProperty Trk::TimedExtrapolator::m_useDenseVolumeDescription
private
Initial value:
{
this, "UseDenseVolumeDescription", true,
"use dense volume description when available in ID/Calo"}

Definition at line 352 of file TimedExtrapolator.h.

352 {
353 this, "UseDenseVolumeDescription", true,
354 "use dense volume description when available in ID/Calo"};

◆ m_useMuonMatApprox

BooleanProperty Trk::TimedExtrapolator::m_useMuonMatApprox
private
Initial value:
{this, "UseMuonMatApproximation", false,
"use approximative MS inert material"}

Definition at line 355 of file TimedExtrapolator.h.

355 {this, "UseMuonMatApproximation", false,
356 "use approximative MS inert material"};

◆ m_varHandleArraysDeclared

bool AthCommonDataStore< AthCommonMsg< AlgTool > >::m_varHandleArraysDeclared
privateinherited

Definition at line 399 of file AthCommonDataStore.h.

◆ m_vhka

std::vector<SG::VarHandleKeyArray*> AthCommonDataStore< AthCommonMsg< AlgTool > >::m_vhka
privateinherited

Definition at line 398 of file AthCommonDataStore.h.


The documentation for this class was generated from the following files: