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 > *&hitVectorhitVector, 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 > *&hitVectorhitVector, 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 1233 of file TimedExtrapolator.cxx.

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

◆ 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 2353 of file TimedExtrapolator.cxx.

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

◆ 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 }
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
397 Trk::ArraySpan<const Trk::DetachedTrackingVolume* const> detVols = cache.m_currentStatic->confinedDetachedVolumes();
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
454 cache.m_dense = (cache.m_currentStatic->geometrySignature() == Trk::MS && m_useMuonMatApprox) ||
455 (cache.m_currentStatic->geometrySignature() != Trk::MS && m_useDenseVolumeDescription);
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()) {
571 if (m_robustSampling || cache.m_currentStatic->geometrySignature() == Trk::MS) {
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() ) {
610 if (m_robustSampling || cache.m_currentStatic->geometrySignature() == Trk::MS) {
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
754 if (cache.m_currentStatic->geometrySignature() == Trk::ID || m_caloMsSecondary) {
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
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
776 if (cache.m_currentStatic->geometrySignature() == Trk::ID || m_caloMsSecondary) {
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 }
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,
816 cache.m_currentStatic->geometrySignature(),
817 dir,
818 particle)
819 .release()
820 : nextPar;
821
822 if (!nextPar) {
823 ATH_MSG_VERBOSE(" [+] Update may have killed neutral track - return.");
824 cache.m_parametersAtBoundary.resetBoundaryInformation();
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,
892 cache.m_currentStatic->geometrySignature(), dir,
893 particle).release() : nextPar;
894 if (!nextPar) {
895 ATH_MSG_VERBOSE(" [+] Update may have killed track - return.");
896 cache.m_parametersAtBoundary.resetBoundaryInformation();
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
918 if (!m_robustSampling && cache.m_currentStatic->geometrySignature() != Trk::MS) {
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.
GeometrySignature geometrySignature() const
return the Signature
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< 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:312
@ layer
Definition HitInfo.h:79
std::span< T > ArraySpan
@ active
Definition Layer.h:47
const TrackParameters * trPar

◆ 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(pathvar)
size_t size() const
Number of registered mappings.
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 1225 of file TimedExtrapolator.cxx.

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

◆ 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 static constexpr 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 * const 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 //detParameters && detSurface are non-null here
1109 surfaceHit = detSurface->isOnSurface(detParameters->position());
1110
1111 // check also for start/endSurface on this level
1112
1113 surfaceHit = (surfaceHit && startSurface) ?
1114 ((detParameters->position() - parm.position()).dot(dir * parm.momentum().normalized()) >
1115 0) : surfaceHit;
1116 surfaceHit = (surfaceHit && endSurface) ?
1117 ((detParameters->position() - parsOnLayer.position()).dot(dir * parsOnLayer.momentum().normalized()) <
1118 0) : surfaceHit;
1119
1120 // surface is hit within bounds (or at least with given boundary check directive) -> it counts
1121 // surface hit also survived start/endsurface search
1122 //
1123 // Convention for Fatras: always apply the full update on the last parameters
1124 // of the gathered vector (no pre/post schema)
1125 // don't record a hit on the destination surface
1126 if (surfaceHit &&
1127 detSurface != startSurface) {
1128 ATH_MSG_VERBOSE(" [H] Hit with detector surface recorded ! ");
1129 // push into the temporary vector
1130 detParametersOnLayer.push_back(detParameters);
1131 } else if (detParameters) {
1132 // no hit -> fill into the garbage bin
1133 ATH_MSG_VERBOSE(" [-] Detector surface hit cancelled through bounds check or start/end surface check.");
1134 throwIntoGarbageBin(cache,detParameters);
1135 }
1136 }
1137
1138 // search for the overlap ------------------------------------------------------------------------
1139 if (detParameters) {
1140 // retrieve compatible subsurfaces
1141 std::vector<Trk::SurfaceIntersection> cSurfaces;
1142 size_t ncSurfaces = lay.compatibleSurfaces(cSurfaces, *detParameters, Trk::anyDirection, bcheck, false);
1143
1144 // import from StaticEngine.icc
1145 if (ncSurfaces) {
1146 ATH_MSG_VERBOSE("found " << ncSurfaces << " candidate sensitive surfaces to test.");
1147 // now loop over the surfaces:
1148 // the surfaces will be sorted @TODO integrate pathLength propagation into this
1149 for (auto &csf : cSurfaces) {
1150 // propagate to the compatible surface, return types are (pathLimit failure is excluded by Trk::anyDirection for
1151 // the moment):
1152 const Trk::TrackParameters *overlapParameters = prop.propagate(ctx,
1153 parm,
1154 *(csf.object),
1156 true,
1158 particle).release();
1159
1160 if (overlapParameters) {
1161 ATH_MSG_VERBOSE(" [+] Overlap surface was hit, checking start/end surface condition.");
1162 // check on start / end surface for on-layer navigaiton action
1163 surfaceHit = (startSurface) ?
1164 ((overlapParameters->position() - parm.position()).dot(dir * parm.momentum().normalized()) >
1165 0) : true;
1166 surfaceHit = (surfaceHit && endSurface) ?
1167 ((overlapParameters->position() - parsOnLayer.position()).dot(dir *
1168 parsOnLayer.momentum().normalized())
1169 < 0) : surfaceHit;
1170 if (surfaceHit && csf.object!=detSurface) { //skipping the initial surface on which a hit has already been created
1171 ATH_MSG_VERBOSE(" [H] Hit with detector surface recorded !");
1172 // distinguish whether sorting is needed or not
1173 reorderDetParametersOnLayer = true;
1174 // push back into the temporary vector
1175 detParametersOnLayer.push_back(overlapParameters);
1176 } else { // the parameters have been cancelled by start/end surface
1177 // no hit -> fill into the garbage bin
1178 ATH_MSG_VERBOSE(" [-] Detector surface hit cancelled through start/end surface check.");
1179 throwIntoGarbageBin(cache,overlapParameters);
1180 }
1181 }
1182 } // loop over test surfaces done
1183 } // there are compatible surfaces
1184 } // ---------------------------------------------------------------------------------------------
1185
1186 // push them into the parameters vector
1187 std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIter = detParametersOnLayer.begin();
1188 std::vector<const Trk::TrackParameters *>::const_iterator parsOnLayerIterEnd = detParametersOnLayer.end();
1189
1190 // reorder the track parameters if neccessary, the overlap descriptor did not provide the ordered surfaces
1191 if (reorderDetParametersOnLayer) {
1192 // sort to reference of incoming parameters
1193 Trk::TrkParametersComparisonFunction parameterSorter(parm.position());
1194 sort(detParametersOnLayer.begin(), detParametersOnLayer.end(), parameterSorter);
1195 }
1196
1197 // after sorting : reset the iterators
1198 parsOnLayerIter = detParametersOnLayer.begin();
1199 parsOnLayerIterEnd = detParametersOnLayer.end();
1200 // now fill them into the parameter vector -------> hit creation done <----------------------
1201 for (; parsOnLayerIter != parsOnLayerIterEnd; ++parsOnLayerIter) {
1202 if (cache.m_hitVector) {
1203 cache.m_hitVector->emplace_back(
1204 std::unique_ptr<const Trk::TrackParameters>(*parsOnLayerIter),
1205 time,
1206 0,
1207 0.);
1208 }
1209 }
1210}
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 1213 of file TimedExtrapolator.cxx.

1213 {
1214 std::stringstream outStream;
1215
1216 if (m_printRzOutput) {
1217 outStream << "[r,phi,z] = [ " << pos.perp() << ", " << pos.phi() << ", " << pos.z() << " ]";
1218 } else {
1219 outStream << "[xyz] = [ " << pos.x() << ", " << pos.y() << ", " << pos.z() << " ]";
1220 }
1221 return outStream.str();
1222}
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 >, and AthCheckedComponent<::AthAlgTool >.

◆ 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 2049 of file TimedExtrapolator.cxx.

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

◆ 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 1267 of file TimedExtrapolator.cxx.

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

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

◆ 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 1258 of file TimedExtrapolator.cxx.

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

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: