ATLAS Offline Software
Loading...
Searching...
No Matches
Trk::STEP_Propagator Class Referencefinalabstract

STEP (Simultaneous Track and Error Propagation ) is an algorithm for track parameters propagation through magnetic field. More...

#include <STEP_Propagator.h>

Inheritance diagram for Trk::STEP_Propagator:
Collaboration diagram for Trk::STEP_Propagator:

Classes

struct  Cache
 stuct to pass information to the heavy lifting calculation internal methods More...

Public Member Functions

 STEP_Propagator (const std::string &, const std::string &, const IInterface *)
virtual ~STEP_Propagator ()
virtual StatusCode initialize () override final
 AlgTool initialize method.
virtual StatusCode finalize () override final
 AlgTool finalize method.
virtual std::unique_ptr< Trk::NeutralParameterspropagate (const Trk::NeutralParameters &, const Trk::Surface &, Trk::PropDirection, const Trk::BoundaryCheck &, bool rC=false) const override final
 Main propagation method NeutralParameters.
virtual std::unique_ptr< Trk::TrackParameterspropagate (const EventContext &ctx, const Trk::TrackParameters &trackParameters, const Trk::Surface &targetSurface, Trk::PropDirection propagationDirection, const Trk::BoundaryCheck &boundaryCheck, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, bool returnCurv=false, const Trk::TrackingVolume *tVol=nullptr) const override final
 Propagate parameters and covariance without returning the Jacobian.
virtual std::unique_ptr< Trk::TrackParameterspropagate (const EventContext &ctx, const Trk::TrackParameters &trackParameters, std::vector< Trk::DestSurf > &targetSurfaces, Trk::PropDirection propagationDirection, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, std::vector< unsigned int > &solutions, double &path, bool usePathLimit=false, bool returnCurv=false, const Trk::TrackingVolume *tVol=nullptr) const override final
 Propagate parameters and covariance with search of closest surface.
virtual std::unique_ptr< Trk::TrackParameterspropagateT (const EventContext &ctx, const Trk::TrackParameters &trackParameters, std::vector< Trk::DestSurf > &targetSurfaces, Trk::PropDirection propagationDirection, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, std::vector< unsigned int > &solutions, Trk::PathLimit &path, Trk::TimeLimit &time, bool returnCurv, const Trk::TrackingVolume *tVol, std::vector< Trk::HitInfo > *&hitVector) const override final
 Propagate parameters and covariance with search of closest surface time included.
virtual std::unique_ptr< Trk::TrackParameterspropagateM (const EventContext &ctx, const Trk::TrackParameters &trackParameters, std::vector< Trk::DestSurf > &targetSurfaces, Trk::PropDirection propagationDirection, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, std::vector< unsigned int > &solutions, std::vector< const Trk::TrackStateOnSurface * > *matstates, std::vector< std::pair< std::unique_ptr< Trk::TrackParameters >, int > > *intersections, double &path, bool usePathLimit=false, bool returnCurv=false, const Trk::TrackingVolume *tVol=nullptr, Trk::ExtrapolationCache *=nullptr) const override final
 Propagate parameters and covariance with search of closest surface and material collection.
virtual std::unique_ptr< Trk::TrackParameterspropagate (const EventContext &ctx, const Trk::TrackParameters &trackParameters, const Trk::Surface &targetSurface, Trk::PropDirection propagationDirection, const Trk::BoundaryCheck &boundaryCheck, const MagneticFieldProperties &magneticFieldProperties, std::optional< Trk::TransportJacobian > &jacobian, double &pathLimit, ParticleHypothesis particle, bool returnCurv=false, const Trk::TrackingVolume *tVol=nullptr) const override final
 Propagate parameters and covariance, and return the Jacobian.
virtual std::unique_ptr< Trk::TrackParameterspropagateParameters (const EventContext &ctx, const Trk::TrackParameters &trackParameters, const Trk::Surface &targetSurface, Trk::PropDirection propagationDirection, const Trk::BoundaryCheck &boundaryCheck, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, bool returnCurv=false, const Trk::TrackingVolume *tVol=nullptr) const override final
 Propagate parameters only.
virtual std::unique_ptr< Trk::TrackParameterspropagateParameters (const EventContext &ctx, const Trk::TrackParameters &trackParameters, const Trk::Surface &targetSurface, Trk::PropDirection propagationDirection, const Trk::BoundaryCheck &boundaryCheck, const MagneticFieldProperties &magneticFieldProperties, std::optional< Trk::TransportJacobian > &jacobian, ParticleHypothesis particle, bool returnCurv=false, const Trk::TrackingVolume *tVol=nullptr) const override final
 Propagate parameters and return Jacobian.
virtual std::optional< TrackSurfaceIntersectionintersect (const EventContext &ctx, const Trk::TrackParameters &trackParameters, const Trk::Surface &targetSurface, const Trk::MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, const Trk::TrackingVolume *tVol=nullptr) const override final
 Propagate parameters and return path (Similar to propagateParameters.
virtual std::optional< TrackSurfaceIntersectionintersectSurface (const EventContext &ctx, const Surface &surface, const TrackSurfaceIntersection &trackIntersection, const double qOverP, const MagneticFieldProperties &mft, ParticleHypothesis particle) const override final
 Intersection and propagation:
virtual void globalPositions (const EventContext &ctx, std::deque< Amg::Vector3D > &positionsList, const TrackParameters &trackParameters, const MagneticFieldProperties &magneticFieldProperties, const CylinderBounds &cylinderBounds, double maxStepSize, ParticleHypothesis particle, const Trk::TrackingVolume *tVol=0) const override final
 Return a list of positions along the track.
virtual Trk::MultiComponentState multiStatePropagate (const EventContext &, const MultiComponentState &, const Surface &, const MagneticFieldProperties &, const PropDirection, const BoundaryCheck &, const ParticleHypothesis) const override final
 unimplemented multiStatePropagate
virtual std::unique_ptr< TrackParameterspropagate (const EventContext &ctx, const TrackParameters &parm, const Surface &sf, PropDirection dir, const BoundaryCheck &bcheck, const MagneticFieldProperties &mprop, std::optional< TransportJacobian > &jacob, double &pathLength, ParticleHypothesis particle=pion, bool returnCurv=false, const TrackingVolume *tVol=nullptr) const=0
 Main propagation method with transport jacobian production.
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
virtual std::unique_ptr< TrackParameterspropagateParameters (const EventContext &ctx, const TrackParameters &parm, const Surface &sf, PropDirection dir, const BoundaryCheck &bcheck, const MagneticFieldProperties &mprop, std::optional< TransportJacobian > &jacob, ParticleHypothesis particle=pion, bool returnCurv=false, const TrackingVolume *tVol=nullptr) const =0
 Main propagation method for parameters only with transport jacobian production.

Static Public Member Functions

static const InterfaceID & interfaceID ()
 AlgTool and IAlgTool 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

void setCacheFromProperties (Cache &cache) const
 initialize cache with the variables we need to take from
std::unique_ptr< Trk::TrackParameterspropagateRungeKutta (Cache &cache, bool errorPropagation, const Trk::TrackParameters &trackParameters, std::vector< DestSurf > &targetSurfaces, Trk::PropDirection propagationDirection, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, std::vector< unsigned int > &solutions, double &path, bool returnCurv=false) const
bool propagateWithJacobian (Cache &cache, bool errorPropagation, std::vector< DestSurf > &sfs, double *P, Trk::PropDirection propDir, std::vector< unsigned int > &solutions, double &path, double sumPath) const
void dumpMaterialEffects (Cache &cache, const Trk::CurvilinearParameters *trackParameters, double path) const
void smear (Cache &cache, double &phi, double &theta, const Trk::TrackParameters *parms, double radDist) const
void sampleBrem (Cache &cache, double mom) const
void getFieldCacheObject (Cache &cache, const EventContext &ctx) const
CLHEP::HepRandomEngine * getRandomEngine (const EventContext &ctx) const
Gaudi::Details::PropertyBase & declareGaudiProperty (Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
 specialization for handling Gaudi::Property<SG::VarHandleKey>

Private Attributes

DoubleProperty m_tolerance
BooleanProperty m_materialEffects
BooleanProperty m_includeBgradients
BooleanProperty m_includeGgradient
DoubleProperty m_momentumCutOff
BooleanProperty m_multipleScattering
BooleanProperty m_energyLoss {this, "EnergyLoss", true, "Include energy loss?"}
BooleanProperty m_detailedEloss
BooleanProperty m_straggling
BooleanProperty m_MPV
DoubleProperty m_stragglingScale
DoubleProperty m_scatteringScale
DoubleProperty m_maxPath
IntegerProperty m_maxSteps
DoubleProperty m_layXmax
BooleanProperty m_simulation
ToolHandle< ITimedMatEffUpdatorm_simMatUpdator {this, "SimMatEffUpdator", ""}
 secondary interactions (brem photon emission)
ServiceHandle< IAthRNGSvcm_rndGenSvc
 Random Generator service.
ATHRNG::RNGWrapperm_rngWrapper = nullptr
 Random engine.
StringProperty m_randomEngineName
SG::ReadCondHandleKey< AtlasFieldCacheCondObjm_fieldCacheCondObjInputKey
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

STEP (Simultaneous Track and Error Propagation ) is an algorithm for track parameters propagation through magnetic field.

The algorithm can produce the Jacobian that transports the covariance matrix from one set of track parameters at the initial surface to another set of track parameters at the destination surface. This is useful for Chi2 fitting.

One can choose to perform the transport of the parameters only and omit the transport of the associated covariances (propagateParameters).

The implementation performs the propagation in global coordinates and uses Jacobian matrices (see RungeKuttaUtils) for the transformations between the global frame and local surface-attached coordinate systems.

The STEP_Propagator includes material effects in the equation of motion and applies corrections to the covariance matrices continuously during the parameter transport. It is designed for the propagation of a particle going through a dense block of material (e.g a muon transversing the calorimeter).

1.The first step of the algorithm is track parameters transformation from local presentation for given start surface to global Runge Kutta coordinates.

2.The second step is propagation through magnetic field with or without jacobian.

3.Third step is transformation from global Runge Kutta presentation to local presentation of given output surface.

AtaPlane AtaStraightLine AtaDisc AtaCylinder Perigee | | | | | | | | | |

V V V V V

| Local->Global transformation V Global position (Runge Kutta presentation) | | Propagation to next surface with or without jacobian |

V Global->Local transformation

| | | | | | | | | | V V V V V PlaneSurface StraightLineSurface DiscSurface CylinderSurface PerigeeSurface

For propagation using Runge Kutta method we use global coordinate, direction, inverse momentum and Jacobian of transformation. All this parameters we save in array P[42]. /dL0 /dL1 /dPhi /dThe /dCM X ->P[0] dX / P[ 7] P[14] P[21] P[28] P[35] Y ->P[1] dY / P[ 8] P[15] P[22] P[29] P[36] Z ->P[2] dZ / P[ 9] P[16] P[23] P[30] P[37] Ax ->P[3] dAx/ P[10] P[17] P[24] P[31] P[38] Ay ->P[4] dAy/ P[11] P[18] P[25] P[32] P[39] Az ->P[5] dAz/ P[12] P[19] P[26] P[33] P[40] CM ->P[6] dCM/ P[13] P[20] P[27] P[34] P[41]

where in case local presentation

L0 - first local coordinate (surface dependent) L1 - second local coordinate (surface dependent) Phi - Azimuthal angle The - Polar angle CM - charge/momentum

in case global presentation

X - global x-coordinate = surface dependent Y - global y-coordinate = surface dependent Z - global z-coordinate = sutface dependent Ax - direction cosine to x-axis = Sin(The)*Cos(Phi) Ay - direction cosine to y-axis = Sin(The)*Sin(Phi) Az - direction cosine to z-axis = Cos(The) CM - charge/momentum = local CM

The Runge-Kutta method:

The equations of motion are solved using an embedded pair of Runge-Kutta formulas. This method, Runge-Kutta-Fehlberg, calculates a number of points along the step and adds them up in different ways to get two different solutions, of different order, for the integration. The higher order solution is used for the propagation and the lower order solution for error control. The difference between these solutions is used to estimate the quality of the integration (propagation), and to calculate the step size for the next step. If the quality is below a given tolerance then the step is rejected and repeated with a shorter step length. This propagator uses the TP43 (Tsitouras-Papakostas 4th and 3rd order) Runge-Kutta pair.

The step size algoritm by L.P.Endresen and J.Myrheim was choosen for its low step rejection and effective step size calculation. The low step rejection is achieved by letting the step size oscillate around the optimal value instead of repeating steps every time they fall below the tolerance level.

Units are mm, MeV and kiloGauss.

Author
esben.nosp@m..lun.nosp@m.d@fys.nosp@m..uio.nosp@m..no

Definition at line 163 of file STEP_Propagator.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

◆ STEP_Propagator()

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

Definition at line 1173 of file STEP_Propagator.cxx.

1174 : AthAlgTool(p, n, t)
1175{
1176 declareInterface<Trk::IPropagator>(this);
1177}
AthAlgTool()
Default constructor:

◆ ~STEP_Propagator()

Trk::STEP_Propagator::~STEP_Propagator ( )
virtualdefault

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.

◆ dumpMaterialEffects()

void Trk::STEP_Propagator::dumpMaterialEffects ( Cache & cache,
const Trk::CurvilinearParameters * trackParameters,
double path ) const
private

Definition at line 2702 of file STEP_Propagator.cxx.

2703 {
2704
2705 // kinematics
2706 double mom = parms->momentum().mag();
2707
2708 // first update to make sure all material counted
2709 updateMaterialEffects(cache, mom, sin(parms->momentum().theta()), path);
2710
2711 if (cache.m_extrapolationCache) {
2712 cache.m_extrapolationCache->updateX0(cache.m_combinedThickness);
2713 cache.m_extrapolationCache->updateEloss(
2714 cache.m_combinedEloss.meanIoni(), cache.m_combinedEloss.sigmaIoni(), cache.m_combinedEloss.meanRad(),
2715 cache.m_combinedEloss.sigmaRad());
2716 }
2717 // output
2718 if (cache.m_matstates) {
2719 auto eloss = !m_detailedEloss
2720 ? std::make_unique<Trk::EnergyLoss>(cache.m_combinedEloss.deltaE(),
2721 cache.m_combinedEloss.sigmaDeltaE())
2722 : std::make_unique<Trk::EnergyLoss>(
2723 cache.m_combinedEloss.deltaE(), cache.m_combinedEloss.sigmaDeltaE(),
2724 cache.m_combinedEloss.sigmaDeltaE(), cache.m_combinedEloss.sigmaDeltaE(),
2725 cache.m_combinedEloss.meanIoni(), cache.m_combinedEloss.sigmaIoni(),
2726 cache.m_combinedEloss.meanRad(), cache.m_combinedEloss.sigmaRad(), path);
2727
2728 auto sa = Trk::ScatteringAngles(0., 0., std::sqrt(cache.m_covariance(2, 2)),
2729 std::sqrt(cache.m_covariance(3, 3)));
2730
2731 auto cvlTP = parms->uniqueClone();
2732 auto mefot = std::make_unique<Trk::MaterialEffectsOnTrack>(cache.m_combinedThickness, sa,
2733 std::move(eloss), cvlTP->associatedSurface());
2734
2735 cache.m_matstates->push_back(new TrackStateOnSurface(nullptr, std::move(cvlTP), std::move(mefot)));
2736 }
2737
2738 cache.m_matdump_lastpath = path;
2739
2740 // clean-up
2741 cache.m_combinedCovariance += cache.m_covariance;
2742 cache.m_covariance.setZero();
2743 cache.m_combinedThickness = 0.;
2744 cache.m_combinedEloss.set(0., 0., 0., 0., 0., 0.);
2745}
BooleanProperty m_detailedEloss
path
python interpreter configuration --------------------------------------—
Definition athena.py:128

◆ 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

◆ finalize()

StatusCode Trk::STEP_Propagator::finalize ( )
finaloverridevirtual

AlgTool finalize method.

Definition at line 1214 of file STEP_Propagator.cxx.

1214 {
1215 return StatusCode::SUCCESS;
1216}

◆ getFieldCacheObject()

void Trk::STEP_Propagator::getFieldCacheObject ( Cache & cache,
const EventContext & ctx ) const
private

Definition at line 2800 of file STEP_Propagator.cxx.

2800 {
2801 SG::ReadCondHandle<AtlasFieldCacheCondObj> readHandle{m_fieldCacheCondObjInputKey, ctx};
2802 const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
2803 if (fieldCondObj == nullptr) {
2804 ATH_MSG_ERROR("extrapolate: Failed to retrieve AtlasFieldCacheCondObj with key "
2806 return;
2807 }
2808 fieldCondObj->getInitializedCache(cache.m_fieldCache);
2809}
#define ATH_MSG_ERROR(x)
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey

◆ getRandomEngine()

CLHEP::HepRandomEngine * Trk::STEP_Propagator::getRandomEngine ( const EventContext & ctx) const
private

Definition at line 2812 of file STEP_Propagator.cxx.

2813{
2814 if (!m_simulation || !m_rngWrapper) {
2815 return nullptr;
2816 }
2817 if (m_rngWrapper->evtSeeded(ctx) != ctx.evt()) {
2818 // Ok, the wrappers are unique to this algorithm and a given slot,
2819 // so cannot be accessed concurrently.
2820 ATHRNG::RNGWrapper* wrapper_nc ATLAS_THREAD_SAFE = m_rngWrapper;
2821 wrapper_nc->setSeed (this->name(), ctx);
2822 }
2823 return m_rngWrapper->getEngine (ctx);
2824}
#define ATLAS_THREAD_SAFE
BooleanProperty m_simulation
ATHRNG::RNGWrapper * m_rngWrapper
Random engine.

◆ globalPositions()

void Trk::STEP_Propagator::globalPositions ( const EventContext & ctx,
std::deque< Amg::Vector3D > & positionsList,
const TrackParameters & trackParameters,
const MagneticFieldProperties & magneticFieldProperties,
const CylinderBounds & cylinderBounds,
double maxStepSize,
ParticleHypothesis particle,
const Trk::TrackingVolume * tVol = 0 ) const
finaloverridevirtual

Return a list of positions along the track.

Implements Trk::IPropagator.

Definition at line 1774 of file STEP_Propagator.cxx.

1779 {
1780 Cache cache(ctx);
1781
1782 // Get field cache object
1783 getFieldCacheObject(cache, ctx);
1785 clearMaterialEffects(cache);
1786
1787 cache.m_particle = particle; // Store for later use
1788
1789 // Check for tracking volume (materialproperties)
1790 cache.m_trackingVolume = tVol;
1791 cache.m_material = tVol;
1792 cache.m_matPropOK = tVol != nullptr;
1793
1794 // Check for empty volumes. If x != x then x is not a number.
1795 if (cache.m_matPropOK && ((cache.m_material->zOverAtimesRho() == 0.) || (cache.m_material->x0() == 0.) ||
1796 (cache.m_material->zOverAtimesRho() != cache.m_material->zOverAtimesRho()))) {
1797 cache.m_matPropOK = false;
1798 }
1799
1800 mft.magneticFieldMode() == Trk::FastField ? cache.m_solenoid = true : cache.m_solenoid = false;
1801
1802 // Check inputvalues
1803 if (cache.m_tolerance <= 0.)
1804 return;
1805
1806 double PP[7];
1807 if (!Trk::RungeKuttaUtils::transformLocalToGlobal(false, trackParameters, PP))
1808 return;
1809
1810 double maxPath = cache.m_maxPath; // Max path allowed
1811 double dDir[3] = {0., 0., 0.}; // Start directions derivs. Zero in case of no RK steps
1812 double distanceStepped = 0.;
1813 double BG1[12] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.}; // Bx, By, Bz, dBx/dx, dBx/dy, dBx/dz,
1814 // dBy/dx, dBy/dy, dBy/dz, dBz/dx, dBz/dy, dBz/dz
1815 bool firstStep = true; // Poll B1, else recycle B4
1816 double path = 0.; // path of the trajectory
1817 double radius2Max = cylinderBounds.r() * cylinderBounds.r(); // max. radius**2 of region
1818 double zMax = cylinderBounds.halflengthZ(); // max. Z of region
1819 double radius2 = PP[0] * PP[0] + PP[1] * PP[1]; // Start radius**2
1820 double direction = PP[0] * PP[3] + PP[1] * PP[4]; // Direction
1821 double h = maxStepSize; // max step allowed
1822
1823 // Test position of the track
1824 if ((std::abs(PP[2]) > zMax) || (radius2 > radius2Max))
1825 return;
1826
1827 // Store initial position
1828 Amg::Vector3D initialPosition(PP[0], PP[1], PP[2]);
1829 positionsList.push_back(initialPosition);
1830
1831 bool perigee = false;
1832 if (std::abs(direction) < 0.00001) {
1833 perigee = true;
1834 }
1835
1836 for (int i = 0; i != 2; ++i) {
1837 if (i) {
1838 if (perigee)
1839 return;
1840 h = -h;
1841 }
1842 double p[7] = {PP[0], PP[1], PP[2], PP[3], PP[4], PP[5], PP[6]};
1843
1844 while (std::abs(path) < maxPath) {
1845 // Do the step.
1846 if (!rungeKuttaStep(cache, false, h, p, dDir, BG1, firstStep, distanceStepped))
1847 break;
1848 path = path + distanceStepped;
1849
1850 // Keep h within max stepsize
1851 if (h > maxStepSize) {
1852 h = maxStepSize;
1853 } else if (h < -maxStepSize) {
1854 h = -maxStepSize;
1855 }
1856
1857 // store current step
1858 Amg::Vector3D globalPosition(p[0], p[1], p[2]);
1859 if (!i) {
1860 positionsList.push_back(globalPosition);
1861 } else {
1862 positionsList.push_front(globalPosition);
1863 }
1864
1865 // Test position of the track
1866 radius2 = p[0] * p[0] + p[1] * p[1];
1867 if ((std::abs(p[2]) > zMax) || (radius2 > radius2Max))
1868 break;
1869
1870 // Test perigee
1871 if ((p[0] * p[3] + p[1] * p[4]) * direction < 0.) {
1872 if (i)
1873 return;
1874 perigee = true;
1875 }
1876 }
1877 }
1878}
void setCacheFromProperties(Cache &cache) const
initialize cache with the variables we need to take from
void getFieldCacheObject(Cache &cache, const EventContext &ctx) const
Eigen::Matrix< double, 3, 1 > Vector3D
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
bool transformLocalToGlobal(bool, const Trk::TrackParameters &, double *ATH_RESTRICT)
@ FastField
call the fast field access method of the FieldSvc
stuct to pass information to the heavy lifting calculation internal methods

◆ initialize()

StatusCode Trk::STEP_Propagator::initialize ( )
finaloverridevirtual

AlgTool initialize method.

Definition at line 1187 of file STEP_Propagator.cxx.

1187 {
1188
1189 // Read handle for AtlasFieldCacheCondObj
1191
1192 if (!m_materialEffects) { // override all material interactions
1193 m_multipleScattering = false;
1194 m_energyLoss = false;
1195 m_straggling = false;
1196 } else if (!m_energyLoss) { // override straggling
1197 m_straggling = false;
1198 }
1199
1200 if (m_simulation && m_simMatUpdator.retrieve().isFailure()) {
1201 ATH_MSG_WARNING("Simulation mode requested but material updator not found - no brem photon emission.");
1202 }
1203
1204 if (m_simulation) {
1205 // get the random generator serice
1206 ATH_CHECK(m_rndGenSvc.retrieve());
1207 m_rngWrapper = m_rndGenSvc->getEngine(this, m_randomEngineName);
1208 }
1209
1210 return StatusCode::SUCCESS;
1211}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
ToolHandle< ITimedMatEffUpdator > m_simMatUpdator
secondary interactions (brem photon emission)
BooleanProperty m_materialEffects
StringProperty m_randomEngineName
BooleanProperty m_multipleScattering
BooleanProperty m_straggling
ServiceHandle< IAthRNGSvc > m_rndGenSvc
Random Generator service.
BooleanProperty m_energyLoss

◆ 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::IPropagator::interfaceID ( )
inlinestaticinherited

AlgTool and IAlgTool interface methods.

Definition at line 61 of file IPropagator.h.

61{ return IID_IPropagator; }
static const InterfaceID IID_IPropagator("IPropagator", 1, 0)
Interface ID for IPropagators.

◆ intersect()

std::optional< Trk::TrackSurfaceIntersection > Trk::STEP_Propagator::intersect ( const EventContext & ctx,
const Trk::TrackParameters & trackParameters,
const Trk::Surface & targetSurface,
const Trk::MagneticFieldProperties & magneticFieldProperties,
ParticleHypothesis particle,
const Trk::TrackingVolume * tVol = nullptr ) const
finaloverridevirtual

Propagate parameters and return path (Similar to propagateParameters.

Implements Trk::IPropagator.

Definition at line 1606 of file STEP_Propagator.cxx.

1612 {
1613
1614 Cache cache(ctx);
1615
1616 // Get field cache object
1617 getFieldCacheObject(cache, ctx);
1619 clearMaterialEffects(cache);
1620
1621 cache.m_particle = particle; // Store for later use
1622
1623 // Check for tracking volume (materialproperties)
1624 cache.m_trackingVolume = tVol;
1625 cache.m_material = tVol;
1626 cache.m_matPropOK = tVol != nullptr;
1627
1628 // no identified intersections needed/ no material dump
1629 cache.m_identifiedParameters = nullptr;
1630 cache.m_matstates = nullptr;
1631 cache.m_extrapolationCache = nullptr;
1632 cache.m_hitVector = nullptr;
1633
1634 // Bfield mode
1635 mft.magneticFieldMode() == Trk::FastField ? cache.m_solenoid = true : cache.m_solenoid = false;
1636
1637 // Check inputvalues
1638 if (cache.m_tolerance <= 0.) {
1639 return std::nullopt;
1640 }
1641 if (cache.m_momentumCutOff < 0.) {
1642 return std::nullopt;
1643 }
1644 if (std::abs(1. / trackParameters.parameters()[Trk::qOverP]) <= cache.m_momentumCutOff) {
1645 return std::nullopt;
1646 }
1647
1648 // Check for empty volumes. If x != x then x is not a number.
1649 if (cache.m_matPropOK && ((cache.m_material->zOverAtimesRho() == 0.) || (cache.m_material->x0() == 0.) ||
1650 (cache.m_material->zOverAtimesRho() != cache.m_material->zOverAtimesRho()))) {
1651 cache.m_matPropOK = false;
1652 }
1653
1654 // double P[45];
1655 if (!Trk::RungeKuttaUtils::transformLocalToGlobal(false, trackParameters, cache.m_P)) {
1656 return std::nullopt;
1657 }
1658 double path = 0.;
1659
1660 const Amg::Transform3D& T = targetSurface.transform();
1661 Trk::SurfaceType ty = targetSurface.type();
1662
1664 double s[4];
1665 double d = T(0, 3) * T(0, 2) + T(1, 3) * T(1, 2) + T(2, 3) * T(2, 2);
1666
1667 if (d >= 0.) {
1668 s[0] = T(0, 2);
1669 s[1] = T(1, 2);
1670 s[2] = T(2, 2);
1671 s[3] = d;
1672 } else {
1673 s[0] = -T(0, 2);
1674 s[1] = -T(1, 2);
1675 s[2] = -T(2, 2);
1676 s[3] = -d;
1677 }
1678 if (!propagateWithJacobianImpl(cache, false, ty, s, cache.m_P, path)){
1679 return std::nullopt;
1680 }
1681 }
1682
1683 else if (ty == Trk::SurfaceType::Line) {
1684
1685 double s[6] = {T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2)};
1686 if (!propagateWithJacobianImpl(cache, false, ty, s, cache.m_P, path)) {
1687 return std::nullopt;
1688 }
1689 }
1690
1691 else if (ty == Trk::SurfaceType::Cylinder) {
1692
1693 const Trk::CylinderSurface* cyl = static_cast<const Trk::CylinderSurface*>(&targetSurface);
1694 double s[9] = {
1695 T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2), cyl->bounds().r(), Trk::alongMomentum, 0.};
1696 if (!propagateWithJacobianImpl(cache, false, ty, s, cache.m_P, path)) {
1697 return std::nullopt;
1698 }
1699 }
1700
1701 else if (ty == Trk::SurfaceType::Cone) {
1702
1703 double k = static_cast<const Trk::ConeSurface*>(&targetSurface)->bounds().tanAlpha();
1704 k = k * k + 1.;
1705 double s[9] = {T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2), k, Trk::alongMomentum, 0.};
1706 if (!propagateWithJacobianImpl(cache, false, ty, s, cache.m_P, path)) {
1707 return std::nullopt;
1708 }
1709 }
1710
1711 else if (ty == Trk::SurfaceType::Perigee) {
1712
1713 double s[6] = {T(0, 3), T(1, 3), T(2, 3), 0., 0., 1.};
1714 if (!propagateWithJacobianImpl(cache, false, ty, s, cache.m_P, path)) {
1715 return std::nullopt;
1716 }
1717 }
1718
1719 else { // presumably curvilinear
1720
1721 double s[4];
1722 double d = T(0, 3) * T(0, 2) + T(1, 3) * T(1, 2) + T(2, 3) * T(2, 2);
1723
1724 if (d >= 0.) {
1725 s[0] = T(0, 2);
1726 s[1] = T(1, 2);
1727 s[2] = T(2, 2);
1728 s[3] = d;
1729 } else {
1730 s[0] = -T(0, 2);
1731 s[1] = -T(1, 2);
1732 s[2] = -T(2, 2);
1733 s[3] = -d;
1734 }
1735 if (!propagateWithJacobianImpl(cache, false, ty, s, cache.m_P, path)) {
1736 return std::nullopt;
1737 }
1738 }
1739
1740 Amg::Vector3D globalPosition(cache.m_P[0], cache.m_P[1], cache.m_P[2]);
1741 Amg::Vector3D direction(cache.m_P[3], cache.m_P[4], cache.m_P[5]);
1742 return std::make_optional<Trk::TrackSurfaceIntersection>(globalPosition, direction, path);
1743}
virtual double r() const override final
This method returns the radius.
virtual const CylinderBounds & bounds() const override final
This method returns the CylinderBounds by reference (NoBounds is not possible for cylinder)
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
virtual constexpr SurfaceType type() const =0
Returns the Surface type to avoid dynamic casts.
Eigen::Affine3d Transform3D
unsigned long long T
@ alongMomentum
SurfaceType
This enumerator simplifies the persistency & calculations,.
@ qOverP
perigee
Definition ParamDefs.h:67

◆ intersectSurface()

std::optional< Trk::TrackSurfaceIntersection > Trk::STEP_Propagator::intersectSurface ( const EventContext & ctx,
const Surface & surface,
const TrackSurfaceIntersection & trackIntersection,
const double qOverP,
const MagneticFieldProperties & mft,
ParticleHypothesis particle ) const
finaloverridevirtual

Intersection and propagation:

Implements Trk::IPropagator.

Definition at line 1746 of file STEP_Propagator.cxx.

1750 {
1751
1752 const Amg::Vector3D& origin = trackIntersection.position();
1753 const Amg::Vector3D& direction = trackIntersection.direction();
1754
1755 auto perigeeSurface = PerigeeSurface(origin);
1756 perigeeSurface.setOwner(Trk::userOwn); // tmp ones
1757
1758 auto tmpTrackParameters =
1759 Trk::Perigee(0., 0., direction.phi(), direction.theta(), qOverP, perigeeSurface, std::nullopt);
1760
1761 std::optional<Trk::TrackSurfaceIntersection> solution =
1762 qOverP == 0
1763 ? intersect(ctx, tmpTrackParameters, surface,
1764 Trk::MagneticFieldProperties(Trk::NoField), particle)
1765 : intersect(ctx, tmpTrackParameters, surface, mft, particle, nullptr);
1766
1767 return solution;
1768}
virtual std::optional< TrackSurfaceIntersection > intersect(const EventContext &ctx, const Trk::TrackParameters &trackParameters, const Trk::Surface &targetSurface, const Trk::MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, const Trk::TrackingVolume *tVol=nullptr) const override final
Propagate parameters and return path (Similar to propagateParameters.
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ NoField
Field is set to 0., 0., 0.,.

◆ 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 }

◆ multiStatePropagate()

virtual Trk::MultiComponentState Trk::STEP_Propagator::multiStatePropagate ( const EventContext & ,
const MultiComponentState & ,
const Surface & ,
const MagneticFieldProperties & ,
const PropDirection ,
const BoundaryCheck & ,
const ParticleHypothesis  ) const
inlinefinaloverridevirtual

unimplemented multiStatePropagate

Implements Trk::IPropagator.

Definition at line 325 of file STEP_Propagator.h.

333 {
334 ATH_MSG_ERROR("Call to non-implemented multiStatePropagate");
335 return {};
336 }

◆ 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.

◆ propagate() [1/5]

virtual std::unique_ptr< TrackParameters > Trk::IPropagator::propagate ( const EventContext & ctx,
const TrackParameters & parm,
const Surface & sf,
PropDirection dir,
const BoundaryCheck & bcheck,
const MagneticFieldProperties & mprop,
std::optional< TransportJacobian > & jacob,
double & pathLength,
ParticleHypothesis particle = pion,
bool returnCurv = false,
const TrackingVolume * tVol = nullptr ) const
virtual

Main propagation method with transport jacobian production.

Implements Trk::IPropagator.

◆ propagate() [2/5]

std::unique_ptr< Trk::TrackParameters > Trk::STEP_Propagator::propagate ( const EventContext & ctx,
const Trk::TrackParameters & trackParameters,
const Trk::Surface & targetSurface,
Trk::PropDirection propagationDirection,
const Trk::BoundaryCheck & boundaryCheck,
const MagneticFieldProperties & magneticFieldProperties,
ParticleHypothesis particle,
bool returnCurv = false,
const Trk::TrackingVolume * tVol = nullptr ) const
finaloverridevirtual

Propagate parameters and covariance without returning the Jacobian.

Implements Trk::IPropagator.

Definition at line 1232 of file STEP_Propagator.cxx.

1236 {
1237
1238 // ATH_MSG_WARNING( "[STEP_Propagator] enter 1");
1239
1240 double Jacobian[25];
1241 Cache cache(ctx);
1242
1243 // Get field cache object
1244 getFieldCacheObject(cache, ctx);
1246 clearMaterialEffects(cache);
1247
1248 // Check for tracking volume (materialproperties)
1249 cache.m_trackingVolume = tVol;
1250 cache.m_material = tVol;
1251 cache.m_matPropOK = tVol != nullptr;
1252
1253 cache.m_matupd_lastmom = trackParameters.momentum().mag();
1254 cache.m_matupd_lastpath = 0.;
1255 cache.m_matdump_lastpath = 0.;
1256
1257 // no identified intersections needed/ no material dump / no path cache
1258 cache.m_identifiedParameters = nullptr;
1259 cache.m_matstates = nullptr;
1260 cache.m_extrapolationCache = nullptr;
1261 cache.m_hitVector = nullptr;
1262
1263 return propagateRungeKuttaImpl(cache, true, trackParameters, targetSurface, propagationDirection,
1264 magneticFieldProperties, particle, boundaryCheck, Jacobian, returnCurv);
1265}
const Amg::Vector3D & momentum() const
Access method for the momentum.

◆ propagate() [3/5]

std::unique_ptr< Trk::TrackParameters > Trk::STEP_Propagator::propagate ( const EventContext & ctx,
const Trk::TrackParameters & trackParameters,
const Trk::Surface & targetSurface,
Trk::PropDirection propagationDirection,
const Trk::BoundaryCheck & boundaryCheck,
const MagneticFieldProperties & magneticFieldProperties,
std::optional< Trk::TransportJacobian > & jacobian,
double & pathLimit,
ParticleHypothesis particle,
bool returnCurv = false,
const Trk::TrackingVolume * tVol = nullptr ) const
finaloverridevirtual

Propagate parameters and covariance, and return the Jacobian.

WARNING: Multiple Scattering is not included in the Jacobian!

Definition at line 1464 of file STEP_Propagator.cxx.

1475 {
1476
1477 double Jacobian[25];
1478 Cache cache(ctx);
1479
1480 // Get field cache object
1481 getFieldCacheObject(cache, ctx);
1483 clearMaterialEffects(cache);
1484
1485 // Check for tracking volume (materialproperties)
1486 cache.m_trackingVolume = tVol;
1487 cache.m_material = tVol;
1488 cache.m_matPropOK = tVol != nullptr;
1489
1490 // no identified intersections needed/ no material dump
1491 cache.m_identifiedParameters = nullptr;
1492 cache.m_matstates = nullptr;
1493 cache.m_extrapolationCache = nullptr;
1494 cache.m_hitVector = nullptr;
1495
1496 cache.m_matupd_lastmom = trackParameters.momentum().mag();
1497 cache.m_matupd_lastpath = 0.;
1498 cache.m_matdump_lastpath = 0.;
1499
1500 std::unique_ptr<Trk::TrackParameters> parameters =
1501 propagateRungeKuttaImpl(cache, true, trackParameters, targetSurface, propagationDirection,
1502 magneticFieldProperties, particle, boundaryCheck, Jacobian, returnCurv);
1503
1504 if (parameters) {
1505 Jacobian[24] = Jacobian[20];
1506 Jacobian[23] = 0.;
1507 Jacobian[22] = 0.;
1508 Jacobian[21] = 0.;
1509 Jacobian[20] = 0.;
1510 jacobian = std::make_optional<Trk::TransportJacobian>(Jacobian);
1511 } else {
1512 jacobian.reset();
1513 }
1514
1515 return parameters;
1516}

◆ propagate() [4/5]

std::unique_ptr< Trk::TrackParameters > Trk::STEP_Propagator::propagate ( const EventContext & ctx,
const Trk::TrackParameters & trackParameters,
std::vector< Trk::DestSurf > & targetSurfaces,
Trk::PropDirection propagationDirection,
const MagneticFieldProperties & magneticFieldProperties,
ParticleHypothesis particle,
std::vector< unsigned int > & solutions,
double & path,
bool usePathLimit = false,
bool returnCurv = false,
const Trk::TrackingVolume * tVol = nullptr ) const
finaloverridevirtual

Propagate parameters and covariance with search of closest surface.

Implements Trk::IPropagator.

Definition at line 1271 of file STEP_Propagator.cxx.

1276 {
1277
1278 Cache cache(ctx);
1279
1280 // Get field cache object
1281 getFieldCacheObject(cache, ctx);
1283 clearMaterialEffects(cache);
1284
1285 // Check for tracking volume (materialproperties)
1286 cache.m_trackingVolume = tVol;
1287 cache.m_material = tVol;
1288 cache.m_matPropOK = tVol != nullptr;
1289
1290 // no identified intersections needed/ no material dump
1291 cache.m_identifiedParameters = nullptr;
1292 cache.m_matstates = nullptr;
1293 cache.m_extrapolationCache = nullptr;
1294 cache.m_hitVector = nullptr;
1295
1296 cache.m_matupd_lastmom = trackParameters.momentum().mag();
1297 cache.m_matupd_lastpath = 0.;
1298 cache.m_matdump_lastpath = 0.;
1299
1300 // resolve path limit input
1301 if (path > 0.) {
1302 cache.m_propagateWithPathLimit = usePathLimit ? 1 : 0;
1303 cache.m_pathLimit = path;
1304 path = 0.;
1305 } else {
1306 cache.m_propagateWithPathLimit = 0;
1307 cache.m_pathLimit = -1.;
1308 path = 0.;
1309 }
1310 if (particle == Trk::neutron || particle == Trk::photon || particle == Trk::pi0 || particle == Trk::k0)
1311 return propagateNeutral(trackParameters, targetSurfaces, propagationDirection, solutions, path,
1312 usePathLimit, returnCurv);
1313
1314 return propagateRungeKutta(cache, true, trackParameters, targetSurfaces, propagationDirection,
1315 magneticFieldProperties, particle, solutions, path, returnCurv);
1316}
std::unique_ptr< Trk::TrackParameters > propagateRungeKutta(Cache &cache, bool errorPropagation, const Trk::TrackParameters &trackParameters, std::vector< DestSurf > &targetSurfaces, Trk::PropDirection propagationDirection, const MagneticFieldProperties &magneticFieldProperties, ParticleHypothesis particle, std::vector< unsigned int > &solutions, double &path, bool returnCurv=false) const

◆ propagate() [5/5]

std::unique_ptr< Trk::NeutralParameters > Trk::STEP_Propagator::propagate ( const Trk::NeutralParameters & ,
const Trk::Surface & ,
Trk::PropDirection ,
const Trk::BoundaryCheck & ,
bool rC = false ) const
finaloverridevirtual

Main propagation method NeutralParameters.

It is not implemented for STEP propagator.

Use StraightLinePropagator for neutrals

Implements Trk::IPropagator.

Definition at line 1219 of file STEP_Propagator.cxx.

1223 {
1224 ATH_MSG_WARNING("[STEP_Propagator] STEP_Propagator does not handle neutral track parameters."
1225 << "Use the StraightLinePropagator instead.");
1226 return nullptr;
1227}

◆ propagateM()

std::unique_ptr< Trk::TrackParameters > Trk::STEP_Propagator::propagateM ( const EventContext & ctx,
const Trk::TrackParameters & trackParameters,
std::vector< Trk::DestSurf > & targetSurfaces,
Trk::PropDirection propagationDirection,
const MagneticFieldProperties & magneticFieldProperties,
ParticleHypothesis particle,
std::vector< unsigned int > & solutions,
std::vector< const Trk::TrackStateOnSurface * > * matstates,
std::vector< std::pair< std::unique_ptr< Trk::TrackParameters >, int > > * intersections,
double & path,
bool usePathLimit = false,
bool returnCurv = false,
const Trk::TrackingVolume * tVol = nullptr,
Trk::ExtrapolationCache * extrapCache = nullptr ) const
finaloverridevirtual

Propagate parameters and covariance with search of closest surface and material collection.

Implements Trk::IPropagator.

Definition at line 1408 of file STEP_Propagator.cxx.

1415 {
1416
1417 Cache cache(ctx);
1418
1419 // Get field cache object
1420 getFieldCacheObject(cache, ctx);
1422 clearMaterialEffects(cache);
1423
1424 // Check for tracking volume (materialproperties)
1425 cache.m_trackingVolume = tVol;
1426 cache.m_material = tVol;
1427 cache.m_matPropOK = tVol != nullptr;
1428
1429 cache.m_matstates = matstates;
1430 cache.m_identifiedParameters = intersections;
1431 cache.m_extrapolationCache = extrapCache;
1432 cache.m_hitVector = nullptr;
1433
1434 cache.m_matupd_lastmom = trackParameters.momentum().mag();
1435 cache.m_matupd_lastpath = 0.;
1436 cache.m_matdump_lastpath = 0.;
1437 cache.m_extrapolationCache = extrapCache;
1438
1439 // switch on the detailed energy loss
1440 if (cache.m_extrapolationCache) {
1441 cache.m_detailedElossFlag = true;
1442 }
1443 // resolve path limit input
1444 if (path > 0.) {
1445 cache.m_propagateWithPathLimit = usePathLimit ? 1 : 0;
1446 cache.m_pathLimit = path;
1447 path = 0.;
1448 } else {
1449 cache.m_propagateWithPathLimit = 0;
1450 cache.m_pathLimit = -1.;
1451 path = 0.;
1452 }
1453 if (particle == Trk::neutron || particle == Trk::photon || particle == Trk::pi0 || particle == Trk::k0) {
1454 return propagateNeutral(trackParameters, targetSurfaces, propagationDirection, solutions, path,
1455 usePathLimit, returnCurv);
1456 }
1457 return propagateRungeKutta(cache, true, trackParameters, targetSurfaces, propagationDirection,
1458 magneticFieldProperties, particle, solutions, path, returnCurv);
1459}

◆ propagateParameters() [1/3]

virtual std::unique_ptr< TrackParameters > Trk::IPropagator::propagateParameters ( const EventContext & ctx,
const TrackParameters & parm,
const Surface & sf,
PropDirection dir,
const BoundaryCheck & bcheck,
const MagneticFieldProperties & mprop,
std::optional< TransportJacobian > & jacob,
ParticleHypothesis particle = pion,
bool returnCurv = false,
const TrackingVolume * tVol = nullptr ) const
pure virtualinherited

Main propagation method for parameters only with transport jacobian production.

Implemented in Trk::IntersectorWrapper, and Trk::RungeKuttaPropagator.

◆ propagateParameters() [2/3]

std::unique_ptr< Trk::TrackParameters > Trk::STEP_Propagator::propagateParameters ( const EventContext & ctx,
const Trk::TrackParameters & trackParameters,
const Trk::Surface & targetSurface,
Trk::PropDirection propagationDirection,
const Trk::BoundaryCheck & boundaryCheck,
const MagneticFieldProperties & magneticFieldProperties,
ParticleHypothesis particle,
bool returnCurv = false,
const Trk::TrackingVolume * tVol = nullptr ) const
finaloverridevirtual

Propagate parameters only.

Implements Trk::IPropagator.

Definition at line 1522 of file STEP_Propagator.cxx.

1526 {
1527
1528 double Jacobian[25];
1529 Cache cache(ctx);
1530
1531 // Get field cache object
1532 getFieldCacheObject(cache, ctx);
1534 clearMaterialEffects(cache);
1535
1536 // Check for tracking volume (materialproperties)
1537 cache.m_trackingVolume = tVol;
1538 cache.m_material = tVol;
1539 cache.m_matPropOK = tVol != nullptr;
1540
1541 // no identified intersections needed/ no material dump
1542 cache.m_identifiedParameters = nullptr;
1543 cache.m_matstates = nullptr;
1544 cache.m_hitVector = nullptr;
1545
1546 return propagateRungeKuttaImpl(cache, false, trackParameters, targetSurface, propagationDirection,
1547 magneticFieldProperties, particle, boundaryCheck, Jacobian, returnCurv);
1548}

◆ propagateParameters() [3/3]

std::unique_ptr< Trk::TrackParameters > Trk::STEP_Propagator::propagateParameters ( const EventContext & ctx,
const Trk::TrackParameters & trackParameters,
const Trk::Surface & targetSurface,
Trk::PropDirection propagationDirection,
const Trk::BoundaryCheck & boundaryCheck,
const MagneticFieldProperties & magneticFieldProperties,
std::optional< Trk::TransportJacobian > & jacobian,
ParticleHypothesis particle,
bool returnCurv = false,
const Trk::TrackingVolume * tVol = nullptr ) const
finaloverridevirtual

Propagate parameters and return Jacobian.

WARNING: Multiple Scattering is not included in the Jacobian!

Definition at line 1553 of file STEP_Propagator.cxx.

1563 {
1564
1565 double Jacobian[25];
1566
1567 Cache cache(ctx);
1568
1569 // Get field cache object
1570 getFieldCacheObject(cache, ctx);
1572 clearMaterialEffects(cache);
1573
1574 // Check for tracking volume (materialproperties)
1575 cache.m_trackingVolume = tVol;
1576 cache.m_material = tVol;
1577 cache.m_matPropOK = tVol != nullptr;
1578
1579 // no identified intersections needed/ no material dump
1580 cache.m_identifiedParameters = nullptr;
1581 cache.m_matstates = nullptr;
1582 cache.m_extrapolationCache = nullptr;
1583 cache.m_hitVector = nullptr;
1584
1585 std::unique_ptr<Trk::TrackParameters> parameters =
1586 propagateRungeKuttaImpl(cache, true, trackParameters, targetSurface, propagationDirection,
1587 magneticFieldProperties, particle, boundaryCheck, Jacobian, returnCurv);
1588
1589 if (parameters) {
1590 Jacobian[24] = Jacobian[20];
1591 Jacobian[23] = 0.;
1592 Jacobian[22] = 0.;
1593 Jacobian[21] = 0.;
1594 Jacobian[20] = 0.;
1595 jacobian = std::make_optional<Trk::TransportJacobian>(Jacobian);
1596 } else {
1597 jacobian.reset();
1598 }
1599
1600 return parameters;
1601}

◆ propagateRungeKutta()

std::unique_ptr< Trk::TrackParameters > Trk::STEP_Propagator::propagateRungeKutta ( Cache & cache,
bool errorPropagation,
const Trk::TrackParameters & trackParameters,
std::vector< DestSurf > & targetSurfaces,
Trk::PropDirection propagationDirection,
const MagneticFieldProperties & magneticFieldProperties,
ParticleHypothesis particle,
std::vector< unsigned int > & solutions,
double & path,
bool returnCurv = false ) const
private

Check first that the jacobian does not have crazy entries

Definition at line 1884 of file STEP_Propagator.cxx.

1888 {
1889 // Store for later use
1890 cache.m_particle = particle;
1891 cache.m_charge = inputTrackParameters.charge();
1892 cache.m_inputThetaVariance = 0.;
1893
1894 std::unique_ptr<Trk::TrackParameters> trackParameters{};
1895
1896 // Bfield mode
1897 mft.magneticFieldMode() == Trk::FastField ? cache.m_solenoid = true : cache.m_solenoid = false;
1898
1899 // Check inputvalues
1900 if (cache.m_tolerance <= 0.)
1901 return nullptr;
1902 if (cache.m_momentumCutOff < 0.)
1903 return nullptr;
1904
1905 // Set momentum to 1e10 (straight line) and charge to + if q/p is zero
1906 if (inputTrackParameters.parameters()[Trk::qOverP] == 0) {
1907 trackParameters = createStraightLine(&inputTrackParameters);
1908 if (!trackParameters) {
1909 return nullptr;
1910 }
1911 } else {
1912 trackParameters.reset(inputTrackParameters.clone());
1913 }
1914
1915 if (std::abs(1. / trackParameters->parameters()[Trk::qOverP]) <= cache.m_momentumCutOff) {
1916 return nullptr;
1917 }
1918
1919 // Check for empty volumes. If x != x then x is not a number.
1920 if (cache.m_matPropOK && ((cache.m_material->zOverAtimesRho() == 0.) || (cache.m_material->x0() == 0.) ||
1921 (cache.m_material->zOverAtimesRho() != cache.m_material->zOverAtimesRho()))) {
1922 cache.m_matPropOK = false;
1923 }
1924
1925 if (errorPropagation && !trackParameters->covariance()) {
1926 errorPropagation = false;
1927 }
1928
1929 if (cache.m_matPropOK && errorPropagation && cache.m_straggling)
1930 cache.m_stragglingVariance = 0.;
1931 cache.m_combinedCovariance.setZero();
1932 cache.m_covariance.setZero();
1933
1934 if (errorPropagation || cache.m_matstates) {
1935 // this needs debugging
1936 cache.m_inputThetaVariance = trackParameters->covariance() ? (*trackParameters->covariance())(3, 3) : 0.;
1937 cache.m_combinedEloss.set(0., 0., 0., 0., 0., 0.);
1938 cache.m_combinedThickness = 0.;
1939 }
1940
1941 // double P[45]; // Track parameters and jacobian
1942 if (!Trk::RungeKuttaUtils::transformLocalToGlobal(errorPropagation, *trackParameters, cache.m_P)) {
1943 return nullptr;
1944 }
1945
1946 double path = 0.;
1947
1948 // activate brem photon emission if required
1949 cache.m_brem = m_simulation && particle == Trk::electron && m_simMatUpdator;
1950
1951 // loop while valid solutions
1952 bool validStep = true;
1953 totalPath = 0.;
1954 cache.m_timeOfFlight = 0.;
1955 // Common transformation for all surfaces (angles and momentum)
1956 double localp[5];
1957 double Jacobian[21];
1958 while (validStep) {
1959 // propagation to next surface
1960 validStep = propagateWithJacobian(cache, errorPropagation, targetSurfaces, cache.m_P,
1961 propagationDirection, solutions, path, totalPath);
1962 if (!validStep) {
1963 return nullptr;
1964 }
1965 if (propagationDirection * path <= 0.) {
1966 return nullptr;
1967 }
1968 totalPath += path;
1969 cache.m_timeOfFlight += cache.m_timeStep;
1970 if (cache.m_propagateWithPathLimit > 1 || cache.m_binMat) {
1971 // make sure that for sliding surfaces the result does not get distorted
1972 // return curvilinear parameters
1973 std::unique_ptr<Trk::CurvilinearParameters> cPar = nullptr;
1975 if (!errorPropagation) {
1976 cPar = std::make_unique<Trk::CurvilinearParameters>(
1977 Amg::Vector3D(cache.m_P[0], cache.m_P[1], cache.m_P[2]), localp[2], localp[3], localp[4]);
1978 } else {
1979 double useless[2];
1980 Trk::RungeKuttaUtils::transformGlobalToCurvilinear(true, cache.m_P, useless, Jacobian);
1981 AmgSymMatrix(5) measurementCovariance =
1982 Trk::RungeKuttaUtils::newCovarianceMatrix(Jacobian, *trackParameters->covariance());
1983 // Calculate multiple scattering and straggling covariance contribution.
1984 if (cache.m_matPropOK && (cache.m_multipleScattering || cache.m_straggling) &&
1985 std::abs(totalPath) > 0.) {
1986 covarianceContribution(cache, trackParameters.get(), totalPath, std::abs(1. / cache.m_P[6]),
1987 measurementCovariance);
1988 }
1989 cPar = std::make_unique<Trk::CurvilinearParameters>(
1990 Amg::Vector3D(cache.m_P[0], cache.m_P[1], cache.m_P[2]), localp[2], localp[3], localp[4],
1991 std::move(measurementCovariance));
1992 }
1993 // material collection : first iteration, bin material averaged
1994 // collect material
1995 if (cache.m_binMat && (cache.m_matstates || (errorPropagation && cache.m_extrapolationCache)) &&
1996 std::abs(totalPath - cache.m_matdump_lastpath) > 1.) {
1997 dumpMaterialEffects(cache, cPar.get(), totalPath);
1998 }
1999 return cPar;
2000 }
2001 if (cache.m_propagateWithPathLimit > 0)
2002 cache.m_pathLimit -= path;
2003 // boundary check
2004 // take into account that there may be many identical surfaces with different boundaries
2005 Amg::Vector3D gp(cache.m_P[0], cache.m_P[1], cache.m_P[2]);
2006 bool solution = false;
2007 std::vector<unsigned int> valid_solutions;
2008 valid_solutions.reserve(solutions.size());
2009
2010 std::vector<unsigned int>::iterator iSol = solutions.begin();
2011 while (iSol != solutions.end()) {
2012 if (targetSurfaces[*iSol].first->isOnSurface(gp, targetSurfaces[*iSol].second, 0.001, 0.001)) {
2013 if (!solution) {
2015 if (returnCurv || targetSurfaces[*iSol].first->type() == Trk::SurfaceType::Cone) {
2016 Trk::RungeKuttaUtils::transformGlobalToCurvilinear(errorPropagation, cache.m_P, localp, Jacobian);
2017 } else
2018 Trk::RungeKuttaUtils::transformGlobalToLocal(targetSurfaces[*iSol].first, errorPropagation,
2019 cache.m_P, localp, Jacobian);
2020 solution = true;
2021 }
2022 valid_solutions.push_back(*iSol);
2023 }
2024 ++iSol;
2025 }
2026 solutions = std::move(valid_solutions);
2027 if (solution)
2028 break;
2029 }
2030
2031 if (solutions.empty()) {
2032 return nullptr;
2033 }
2034
2035 // simulation mode : smear momentum
2036 if (m_simulation && cache.m_matPropOK) {
2037 double radDist = totalPath / cache.m_material->x0();
2038 smear(cache, localp[2], localp[3], trackParameters.get(), radDist);
2039 }
2040
2041 std::unique_ptr<Trk::TrackParameters> onTargetSurf =
2042 (returnCurv || targetSurfaces[solutions[0]].first->type() == Trk::SurfaceType::Cone)
2043 ? nullptr
2044 : targetSurfaces[solutions[0]].first->createUniqueTrackParameters(
2045 localp[0], localp[1], localp[2], localp[3], localp[4], std::nullopt);
2046
2047 if (!errorPropagation) {
2048 if (returnCurv || targetSurfaces[solutions[0]].first->type() == Trk::SurfaceType::Cone) {
2049 Amg::Vector3D gp(cache.m_P[0], cache.m_P[1], cache.m_P[2]);
2050 return std::make_unique<Trk::CurvilinearParameters>(gp, localp[2], localp[3], localp[4]);
2051 }
2052 return onTargetSurf;
2053 }
2054
2055 // Errormatrix is included. Use Jacobian to calculate new covariance
2057 for (double i : Jacobian) {
2059 return nullptr;
2060 }
2061 }
2062
2063 AmgSymMatrix(5) measurementCovariance =
2064 Trk::RungeKuttaUtils::newCovarianceMatrix(Jacobian, *trackParameters->covariance());
2065 if (!Amg::hasPositiveOrZeroDiagElems(measurementCovariance))
2066 return nullptr;
2067
2068 // Calculate multiple scattering and straggling covariance contribution.
2069 if (cache.m_matPropOK && (cache.m_multipleScattering || cache.m_straggling) && std::abs(totalPath) > 0.) {
2070 if (returnCurv || targetSurfaces[solutions[0]].first->type() == Trk::SurfaceType::Cone) {
2071 covarianceContribution(cache, trackParameters.get(), totalPath, std::abs(1. / cache.m_P[6]),
2072 measurementCovariance);
2073 } else {
2074 covarianceContribution(cache, trackParameters.get(), totalPath, onTargetSurf.get(),
2075 measurementCovariance);
2076 }
2077 }
2078
2079 if (returnCurv || targetSurfaces[solutions[0]].first->type() == Trk::SurfaceType::Cone) {
2080 Amg::Vector3D gp(cache.m_P[0], cache.m_P[1], cache.m_P[2]);
2081 return std::make_unique<Trk::CurvilinearParameters>(gp, localp[2], localp[3], localp[4],
2082 std::move(measurementCovariance));
2083 }
2084
2085 // delete onTargetSurf; // the covariance matrix can be just added instead of recreating ?
2086 return targetSurfaces[solutions[0]].first->createUniqueTrackParameters(
2087 localp[0], localp[1], localp[2], localp[3], localp[4], std::move(measurementCovariance));
2088}
#define AmgSymMatrix(dim)
if(febId1==febId2)
std::optional< AmgSymMatrix(DIM)> m_covariance
charge definition for this track
void smear(Cache &cache, double &phi, double &theta, const Trk::TrackParameters *parms, double radDist) const
void dumpMaterialEffects(Cache &cache, const Trk::CurvilinearParameters *trackParameters, double path) const
bool propagateWithJacobian(Cache &cache, bool errorPropagation, std::vector< DestSurf > &sfs, double *P, Trk::PropDirection propDir, std::vector< unsigned int > &solutions, double &path, double sumPath) const
bool saneCovarianceElement(double ele)
A covariance matrix formally needs to be positive semi definite.
bool first
Definition DeMoScan.py:534
void transformGlobalToCurvilinear(bool, double *ATH_RESTRICT, double *ATH_RESTRICT, double *ATH_RESTRICT)
void transformGlobalToLocal(double *ATH_RESTRICT, double *ATH_RESTRICT)

◆ propagateT()

std::unique_ptr< Trk::TrackParameters > Trk::STEP_Propagator::propagateT ( const EventContext & ctx,
const Trk::TrackParameters & trackParameters,
std::vector< Trk::DestSurf > & targetSurfaces,
Trk::PropDirection propagationDirection,
const MagneticFieldProperties & magneticFieldProperties,
ParticleHypothesis particle,
std::vector< unsigned int > & solutions,
Trk::PathLimit & path,
Trk::TimeLimit & time,
bool returnCurv,
const Trk::TrackingVolume * tVol,
std::vector< Trk::HitInfo > *& hitVector ) const
finaloverridevirtual

Propagate parameters and covariance with search of closest surface time included.

Implements Trk::IPropagator.

Definition at line 1322 of file STEP_Propagator.cxx.

1327 {
1328
1329 Cache cache(ctx);
1330
1331 // Get field cache object
1332 getFieldCacheObject(cache, ctx);
1334 clearMaterialEffects(cache);
1335
1336 // cache particle mass
1337 cache.m_particleMass = Trk::ParticleMasses::mass[particle]; // Get particle mass from ParticleHypothesis
1338
1339 // cache input timing - for secondary track emission
1340 cache.m_timeIn = timeLim.time;
1341
1342 // Check for tracking volume (materialproperties)
1343 cache.m_trackingVolume = tVol;
1344 cache.m_material = tVol;
1345 cache.m_matPropOK = tVol != nullptr;
1346
1347 // no identified intersections needed/ no material dump
1348 cache.m_identifiedParameters = nullptr;
1349 cache.m_matstates = nullptr;
1350 cache.m_extrapolationCache = nullptr;
1351 cache.m_hitVector = hitVector;
1352
1353 cache.m_matupd_lastmom = trackParameters.momentum().mag();
1354 cache.m_matupd_lastpath = 0.;
1355 cache.m_matdump_lastpath = 0.;
1356
1357 // convert time/path limits into trajectory limit (in mm)
1358 double dMat = pathLim.x0Max - pathLim.x0Collected;
1359 double path =
1360 dMat > 0 && cache.m_matPropOK && cache.m_material->x0() > 0. ? dMat * cache.m_material->x0() : -1.;
1361
1362 double dTim = timeLim.tMax - timeLim.time;
1363 double beta = 1.;
1364 if (dTim > 0.) {
1365 double mom = trackParameters.momentum().mag();
1366 beta = mom / std::sqrt(mom * mom + cache.m_particleMass * cache.m_particleMass);
1367 }
1368 double timMax = dTim > 0 ? dTim * beta * Gaudi::Units::c_light : -1.;
1369
1370 if (timMax > 0. && timMax < path)
1371 path = timMax;
1372 bool usePathLimit = (path > 0.);
1373
1374 // resolve path limit input
1375 if (path > 0.) {
1376 cache.m_propagateWithPathLimit = usePathLimit ? 1 : 0;
1377 cache.m_pathLimit = path;
1378 path = 0.;
1379 } else {
1380 cache.m_propagateWithPathLimit = 0;
1381 cache.m_pathLimit = -1.;
1382 path = 0.;
1383 }
1384
1385 std::unique_ptr<Trk::TrackParameters> nextPar{};
1386
1387 if (particle == Trk::neutron || particle == Trk::photon || particle == Trk::pi0 || particle == Trk::k0) {
1388 nextPar = propagateNeutral(trackParameters, targetSurfaces, propagationDirection, solutions, path,
1389 usePathLimit, returnCurv);
1390 } else {
1391 nextPar = propagateRungeKutta(cache, true, trackParameters, targetSurfaces, propagationDirection,
1392 magneticFieldProperties, particle, solutions, path, returnCurv);
1393 }
1394 // update material path
1395 if (cache.m_matPropOK && cache.m_material->x0() > 0. && path > 0.) {
1396 pathLim.updateMat(path / cache.m_material->x0(), cache.m_material->averageZ(), 0.);
1397 }
1398 // return value
1399 timeLim.time += cache.m_timeOfFlight;
1400 return nextPar;
1401}
std::vector< FPGATrackSimHit > hitVector
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses

◆ propagateWithJacobian()

bool Trk::STEP_Propagator::propagateWithJacobian ( Cache & cache,
bool errorPropagation,
std::vector< DestSurf > & sfs,
double * P,
Trk::PropDirection propDir,
std::vector< unsigned int > & solutions,
double & path,
double sumPath ) const
private

Definition at line 2094 of file STEP_Propagator.cxx.

2098 {
2099 double maxPath = cache.m_maxPath; // Max path allowed
2100 double* pos = &P[0]; // Start coordinates
2101 double* dir = &P[3]; // Start directions
2102 double dDir[3] = {0., 0., 0.}; // Start directions derivs. Zero in case of no RK steps
2103 // int targetPassed = 0; // how many times have we passed the target?
2104 double previousDistance = 0.;
2105 double distanceStepped = 0.;
2106 double BG1[12] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.}; // Bx, By, Bz, dBx/dx, dBx/dy, dBx/dz,
2107 // dBy/dx, dBy/dy, dBy/dz, dBz/dx, dBz/dy, dBz/dz at first point
2108 bool firstStep = true; // Poll BG1, else recycle BG4
2109 int steps = 0;
2110 path = 0.; // path of the trajectory
2111 cache.m_timeStep = 0.; // time separation corresponding to the trajectory
2112 double mom = 0.; // need momentum and beta for timing
2113 double beta = 1.; // need momentum and beta for timing
2114
2115 // factor to stabilize iteration for soft tracks
2116 double helpSoft = 1.;
2117
2118 // limit number of recovery attempts
2119 int restartLimit = 10;
2120
2121 Amg::Vector3D position(P[0], P[1], P[2]);
2122 Amg::Vector3D direction0(P[3], P[4], P[5]);
2123
2124 // binned material ?
2125 cache.m_binMat = nullptr;
2126 if (cache.m_trackingVolume && cache.m_trackingVolume->isAlignable()) {
2127 const Trk::AlignableTrackingVolume* aliTV =
2128 static_cast<const Trk::AlignableTrackingVolume*>(cache.m_trackingVolume);
2129 cache.m_binMat = aliTV->binnedMaterial();
2130 }
2131
2132 // closest distance estimate
2133 // maintain count of oscilations and previous distance for each surface;
2134 // skip initial trivial solutions (input parameters at surface) - should be treated before call to the
2135 // propagator
2136 // !
2137 double tol = 0.001;
2138 solutions.clear();
2139 double distanceToTarget = propDir * maxPath;
2140 cache.m_currentDist.resize(sfs.size()); // keep size through the call
2141
2142 int nextSf = sfs.size();
2143 int nextSfCand = nextSf;
2144 std::vector<DestSurf>::iterator sIter = sfs.begin();
2145 std::vector<DestSurf>::iterator sBeg = sfs.begin();
2146 unsigned int numSf = 0;
2147 unsigned int iCurr = 0; // index for m_currentDist
2148 int startSf = -99;
2149 for (; sIter != sfs.end(); ++sIter) {
2150 Trk::DistanceSolution distSol = (*sIter).first->straightLineDistanceEstimate(position, direction0);
2151 double distEst = -propDir * maxPath;
2152 double dist1Est = distEst;
2153 if (distSol.numberOfSolutions() > 0) {
2154 distEst = distSol.first();
2155 dist1Est = distSol.first();
2156 if (distSol.numberOfSolutions() > 1 &&
2157 (std::abs(distEst) < tol || (propDir * distEst < -tol && propDir * distSol.second() > tol)))
2158 distEst = distSol.second();
2159 }
2160 // select input surfaces;
2161 // do not accept trivial solutions (at the surface)
2162 // but include them into further distance estimate (aca return to the same surface)
2163 if (distEst * propDir > -tol) {
2164 if (distSol.currentDistance() > 500.) {
2165 cache.m_currentDist[iCurr] = std::pair<int, std::pair<double, double>>(
2166 0, std::pair<double, double>(distEst, distSol.currentDistance(true)));
2167 } else {
2168 cache.m_currentDist[iCurr] = std::pair<int, std::pair<double, double>>(
2169 1, std::pair<double, double>(distEst, distSol.currentDistance(true)));
2170 }
2171 if (tol < propDir * distEst && propDir * distEst < propDir * distanceToTarget) {
2172 distanceToTarget = distEst;
2173 nextSf = iCurr;
2174 }
2175 ++numSf;
2176 } else {
2177 // save the nearest distance to surface
2178 cache.m_currentDist[iCurr] = std::pair<int, std::pair<double, double>>(
2179 -1, std::pair<double, double>(distSol.currentDistance(), distSol.currentDistance(true)));
2180 }
2181 if (std::abs(dist1Est) < tol)
2182 startSf = (int)iCurr;
2183 ++iCurr;
2184 }
2185
2186 if (distanceToTarget == maxPath || numSf == 0)
2187 return false;
2188
2189 // these do not change
2190 std::vector<std::pair<int, std::pair<double, double>>>::iterator vsBeg = cache.m_currentDist.begin();
2191 std::vector<std::pair<int, std::pair<double, double>>>::iterator vsEnd = cache.m_currentDist.end();
2192 const int num_vs_dist = cache.m_currentDist.size();
2193
2194 // Set initial step length to 100mm or the distance to the target surface.
2195 double h = 0;
2196 double absPath = 0.;
2197 distanceToTarget > 100. ? h = 100. : distanceToTarget < -100. ? h = -100. : h = distanceToTarget;
2198
2199 const Trk::IdentifiedMaterial* binIDMat = nullptr;
2200 // Adapt step size to the material binning : change of bin layer triggers dump of material effects
2201 if (cache.m_binMat) {
2202 const Trk::BinUtility* lbu = cache.m_binMat->layerBinUtility(position);
2203 if (lbu) {
2204 cache.m_currentLayerBin = cache.m_binMat->layerBin(position);
2205 binIDMat = cache.m_binMat->material(position);
2206 std::pair<size_t, float> dist2next = lbu->distanceToNext(position, propDir * direction0);
2207 if (dist2next.first < lbu->bins() && std::abs(dist2next.second) > 1. &&
2208 std::abs(dist2next.second) < std::abs(h)) {
2209 h = dist2next.second * propDir;
2210 }
2211 if (binIDMat)
2212 cache.m_material = binIDMat->first.get();
2213 }
2214 }
2215
2216 // Step to within distanceTolerance, then do the rest as a Taylor expansion.
2217 // Keep distanceTolerance within [1 nanometer, 10 microns].
2218 // This means that no final Taylor expansions beyond 10 microns and no
2219 // Runge-Kutta steps less than 1 nanometer are allowed.
2220 double distanceTolerance = std::min(std::max(std::abs(distanceToTarget) * cache.m_tolerance, 1e-6), 1e-2);
2221
2222 // bremstrahlung : sample if activated
2223 if (cache.m_brem) {
2224 mom = std::abs(1. / P[6]);
2225 sampleBrem(cache, mom);
2226 }
2227
2228 while (numSf > 0 && (std::abs(distanceToTarget) > distanceTolerance ||
2229 std::abs(path + distanceStepped) < tol)) { // Step until within tolerance
2230 // Do the step. Stop the propagation if the energy goes below m_momentumCutOff
2231 if (!rungeKuttaStep(cache, errorPropagation, h, P, dDir, BG1, firstStep, distanceStepped)) {
2232 // emit brem photon before stopped ?
2233 if (cache.m_brem) {
2234 if (m_momentumCutOff < cache.m_bremEmitThreshold && m_simMatUpdator) {
2235 Amg::Vector3D position(P[0], P[1], P[2]);
2236 Amg::Vector3D direction(P[3], P[4], P[5]);
2237 m_simMatUpdator->recordBremPhoton(cache.m_timeIn + cache.m_timeOfFlight + cache.m_timeStep,
2238 m_momentumCutOff, cache.m_bremMom, position, direction,
2239 cache.m_particle);
2240 // the recoil can be skipped here
2241 for (int i = 0; i < 3; ++i)
2242 P[3 + i] = direction[i];
2243 // end recoil ( momentum not adjusted here ! continuous energy loss maintained for the moment)
2244 }
2245 }
2246 // collect material and update timing
2247 path = path + distanceStepped;
2248 // timing
2249 mom = std::abs(1. / P[6]);
2250 beta = mom / std::sqrt(mom * mom + cache.m_particleMass * cache.m_particleMass);
2251 cache.m_timeStep += distanceStepped / beta / Gaudi::Units::c_light;
2252
2253 if (std::abs(distanceStepped) > 0.001) {
2254 cache.m_sigmaIoni = cache.m_sigmaIoni - cache.m_kazL * log(std::abs(distanceStepped));
2255 }
2256 // update straggling covariance
2257 if (errorPropagation && cache.m_straggling) {
2258 // 15% of the Radition moves the MOP value thus only 85% is accounted for by the Mean-MOP shift
2259 double sigTot2 = cache.m_sigmaIoni * cache.m_sigmaIoni + cache.m_sigmaRad * cache.m_sigmaRad;
2260 // /(beta*beta*p*p*p*p) transforms Var(E) to Var(q/p)
2261 double bp2 = beta * mom * mom;
2262 cache.m_stragglingVariance += sigTot2 / (bp2 * bp2) * distanceStepped * distanceStepped;
2263 }
2264 if (cache.m_matstates || errorPropagation) {
2265 cache.m_combinedEloss.update(
2266 cache.m_delIoni * distanceStepped, cache.m_sigmaIoni * std::abs(distanceStepped),
2267 cache.m_delRad * distanceStepped, cache.m_sigmaRad * std::abs(distanceStepped), cache.m_MPV);
2268 }
2269 if (cache.m_material && cache.m_material->x0() != 0.) {
2270 cache.m_combinedThickness += propDir * distanceStepped / cache.m_material->x0();
2271 }
2272
2273 return false;
2274 }
2275 path = path + distanceStepped;
2276 absPath += std::abs(distanceStepped);
2277
2278 // timing
2279 mom = std::abs(1. / P[6]);
2280 beta = mom / std::sqrt(mom * mom + cache.m_particleMass * cache.m_particleMass);
2281 cache.m_timeStep += distanceStepped / beta / Gaudi::Units::c_light;
2282
2283 if (std::abs(distanceStepped) > 0.001)
2284 cache.m_sigmaIoni = cache.m_sigmaIoni - cache.m_kazL * log(std::abs(distanceStepped));
2285 // update straggling covariance
2286 if (errorPropagation && cache.m_straggling) {
2287 // 15% of the Radition moves the MOP value thus only 85% is accounted for by the Mean-MOP shift
2288 double sigTot2 = cache.m_sigmaIoni * cache.m_sigmaIoni + cache.m_sigmaRad * cache.m_sigmaRad;
2289 // /(beta*beta*p*p*p*p) transforms Var(E) to Var(q/p)
2290 double bp2 = beta * mom * mom;
2291 cache.m_stragglingVariance += sigTot2 / (bp2 * bp2) * distanceStepped * distanceStepped;
2292 }
2293 if (cache.m_matstates || errorPropagation) {
2294 cache.m_combinedEloss.update(
2295 cache.m_delIoni * distanceStepped, cache.m_sigmaIoni * std::abs(distanceStepped),
2296 cache.m_delRad * distanceStepped, cache.m_sigmaRad * std::abs(distanceStepped), cache.m_MPV);
2297 }
2298 if (cache.m_material && cache.m_material->x0() != 0.) {
2299 cache.m_combinedThickness += propDir * distanceStepped / cache.m_material->x0();
2300 }
2301
2302 if (absPath > maxPath)
2303 return false;
2304
2305 // path limit implemented
2306 if (cache.m_propagateWithPathLimit > 0 && cache.m_pathLimit <= path) {
2307 ++cache.m_propagateWithPathLimit;
2308 return true;
2309 }
2310
2311 bool restart = false;
2312 // in case of problems, make shorter steps
2313 if (propDir * path < -tol || absPath - std::abs(path) > 10.) {
2314 helpSoft = std::abs(path) / absPath > 0.5 ? std::abs(path) / absPath : 0.5;
2315 }
2316
2317 Amg::Vector3D position(P[0], P[1], P[2]);
2318 Amg::Vector3D direction(P[3], P[4], P[5]);
2319
2320 // Adapt step size to the material binning : change of bin layer triggers dump of material effects
2321 float distanceToNextBin = h; // default
2322 if (cache.m_binMat) {
2323 const Trk::BinUtility* lbu = cache.m_binMat->layerBinUtility(position);
2324 if (lbu) {
2325 size_t layerBin = cache.m_binMat->layerBin(position);
2326 const Trk::IdentifiedMaterial* iMat = cache.m_binMat->material(position);
2327 std::pair<size_t, float> dist2next = lbu->distanceToNext(position, propDir * direction);
2328 distanceToNextBin = dist2next.second;
2329 if (layerBin != cache.m_currentLayerBin) { // step into new bin
2330 // check the overshoot
2331 std::pair<size_t, float> dist2previous = lbu->distanceToNext(position, -propDir * direction);
2332 float stepOver = dist2previous.second;
2333 double localp[5];
2335 auto cPar = std::make_unique<Trk::CurvilinearParameters>(Amg::Vector3D(P[0], P[1], P[2]), localp[2],
2336 localp[3], localp[4]);
2337 if (cache.m_identifiedParameters) {
2338 if (binIDMat && binIDMat->second > 0 && !iMat) { // exit from active layer
2339 cache.m_identifiedParameters->emplace_back(cPar->clone(), -binIDMat->second);
2340 } else if (binIDMat && binIDMat->second > 0 &&
2341 (iMat->second == 0 || iMat->second == binIDMat->second)) { // exit from active layer
2342 cache.m_identifiedParameters->emplace_back(cPar->clone(), -binIDMat->second);
2343 } else if (iMat && iMat->second > 0) { // entry active layer
2344 cache.m_identifiedParameters->emplace_back(cPar->clone(), iMat->second);
2345 }
2346 }
2347 if (cache.m_hitVector) {
2348 double hitTiming = cache.m_timeIn + cache.m_timeOfFlight + cache.m_timeStep;
2349 if (binIDMat && binIDMat->second > 0 && !iMat) { // exit from active layer
2350 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2351 } else if (binIDMat && binIDMat->second > 0 &&
2352 (iMat->second == 0 || iMat->second == binIDMat->second)) { // exit from active layer
2353 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2354 } else if (iMat && iMat->second > 0) { // entry active layer
2355 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, iMat->second, 0.);
2356 }
2357 }
2358
2359 cache.m_currentLayerBin = layerBin;
2360 binIDMat = iMat;
2361 if (binIDMat) {
2362 // change of material triggers update of the cache
2363 // @TODO Coverity complains about a possible NULL pointer dereferencing here
2364 // because the code above does not explicitly forbid m_material to be NULL and m_material is used
2365 // unchecked inside updateMaterialEffects.
2366 // Can m_material be NULL at this point ?
2367 if (cache.m_material) {
2368 updateMaterialEffects(cache, mom, sin(direction.theta()), sumPath + path - stepOver);
2369 }
2370 cache.m_material = binIDMat->first.get();
2371 }
2372 // recalculate distance to next bin
2373 if (distanceToNextBin < h) {
2374 Amg::Vector3D probe = position + (distanceToNextBin + h) * propDir * direction;
2375 std::pair<size_t, float> d2n = lbu->distanceToNext(probe, propDir * direction);
2376 distanceToNextBin += d2n.second + h;
2377 }
2378 } else if (dist2next.first < lbu->bins() && std::abs(distanceToNextBin) < 0.01 &&
2379 h > 0.01) { // tolerance 10 microns ?
2380 double localp[5];
2382 auto cPar = std::make_unique<Trk::CurvilinearParameters>(Amg::Vector3D(P[0], P[1], P[2]), localp[2],
2383 localp[3], localp[4]);
2384
2385 const Trk::IdentifiedMaterial* nextMat = binIDMat;
2386 // need to know what comes next
2387 Amg::Vector3D probe = position + (distanceToNextBin + 0.01) * propDir * direction.normalized();
2388 nextMat = cache.m_binMat->material(probe);
2389
2390 if (cache.m_identifiedParameters) {
2391 if (binIDMat && binIDMat->second > 0 && !nextMat) { // exit from active layer
2392 cache.m_identifiedParameters->emplace_back(cPar->clone(), -binIDMat->second);
2393 } else if (binIDMat && binIDMat->second > 0 &&
2394 (nextMat->second == 0 || nextMat->second == binIDMat->second)) {
2395 // exit from active layer
2396 cache.m_identifiedParameters->emplace_back(cPar->clone(), -binIDMat->second);
2397 } else if (nextMat && nextMat->second > 0) { // entry active layer
2398 cache.m_identifiedParameters->emplace_back(cPar->clone(), nextMat->second);
2399 }
2400 }
2401 if (cache.m_hitVector) {
2402 double hitTiming = cache.m_timeIn + cache.m_timeOfFlight + cache.m_timeStep;
2403 if (binIDMat && binIDMat->second > 0 && !nextMat) { // exit from active layer
2404 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2405 } else if (binIDMat && binIDMat->second > 0 &&
2406 (nextMat->second == 0 ||
2407 nextMat->second == binIDMat->second)) { // exit from active layer
2408 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, -binIDMat->second, 0.);
2409 } else if (nextMat && nextMat->second > 0) { // entry active layer
2410 cache.m_hitVector->emplace_back(cPar->uniqueClone(), hitTiming, nextMat->second, 0.);
2411 }
2412 }
2413
2414 cache.m_currentLayerBin = dist2next.first;
2415 if (binIDMat != nextMat) { // change of material triggers update of the cache
2416 binIDMat = nextMat;
2417 if (binIDMat) {
2418 assert(cache.m_material);
2419 updateMaterialEffects(cache, mom, sin(direction.theta()), sumPath + path);
2420 cache.m_material = binIDMat->first.get();
2421 }
2422 }
2423 // recalculate distance to next bin
2424 std::pair<size_t, float> d2n = lbu->distanceToNext(probe, propDir * direction.normalized());
2425 distanceToNextBin += d2n.second + 0.01;
2426 }
2427 // TODO: trigger the update of material properties and recalculation of distance to the target sliding
2428 // surface
2429 }
2430 }
2431
2432 // Calculate new distance to targets
2433 bool flipDirection = false;
2434 numSf = 0;
2435 nextSfCand = nextSf;
2436 double dev = direction0.dot(direction);
2437 std::vector<DestSurf>::iterator sIter = sBeg;
2438 std::vector<std::pair<int, std::pair<double, double>>>::iterator vsIter = vsBeg;
2439 int ic = 0;
2440 int numRestart = 0;
2441
2442 if (cache.m_brem) {
2443 if (mom < cache.m_bremEmitThreshold && m_simMatUpdator) {
2444 // ST : strictly speaking, the emission point should be shifted backwards a bit
2445 // (mom-m_bremEmitThreshold) this seems to be a minor point
2446 m_simMatUpdator->recordBremPhoton(cache.m_timeIn + cache.m_timeOfFlight + cache.m_timeStep, mom,
2447 cache.m_bremMom, position, direction, cache.m_particle);
2448 cache.m_bremEmitThreshold = 0.;
2449 }
2450 if (mom < cache.m_bremSampleThreshold)
2451 sampleBrem(cache, cache.m_bremSampleThreshold);
2452 }
2453
2454 for (; vsIter != vsEnd; ++vsIter) {
2455 if (restart) {
2456 ++numRestart;
2457 if (numRestart > restartLimit)
2458 return false;
2459
2460 vsIter = vsBeg;
2461 ic = 0;
2462 sIter = sBeg;
2463 distanceToTarget = propDir * maxPath;
2464 nextSf = -1;
2465 nextSfCand = -1;
2466 restart = false;
2467 helpSoft = 1.;
2468 }
2469 if ((*vsIter).first != -1 &&
2470 (ic == nextSf || (*vsIter).first == 1 || nextSf < 0 || std::abs((*vsIter).second.first) < 500. ||
2471 std::abs(path) > 0.5 * std::abs((*vsIter).second.second))) {
2472 previousDistance = (*vsIter).second.first;
2473 Trk::DistanceSolution distSol =
2474 (*sIter).first->straightLineDistanceEstimate(position, propDir * direction);
2475 double distanceEst = -propDir * maxPath;
2476 if (distSol.numberOfSolutions() > 0) {
2477 distanceEst = distSol.first();
2478 if (distSol.numberOfSolutions() > 1 &&
2479 std::abs(distSol.first() * propDir + distanceStepped - previousDistance) >
2480 std::abs(distSol.second() * propDir + distanceStepped - previousDistance)) {
2481 distanceEst = distSol.second();
2482 }
2483 // Peter Kluit: avoid jumping into other (distSol.first->second) distance solution for start surface
2484 // with negative distance solution
2485 // negative distanceEst will trigger flipDirection = true and will iterate to the start
2486 // surface this will lead to very similar positions for multiple propagator calls and
2487 // many tiny X0 scatterers
2488 if (ic == startSf && distanceEst < 0 && distSol.first() > 0)
2489 distanceEst = distSol.first();
2490 }
2491 // eliminate close surface if path too small
2492 if (ic == nextSf && std::abs(distanceEst) < tol && std::abs(path) < tol) {
2493 (*vsIter).first = -1;
2494 vsIter = vsBeg;
2495 restart = true;
2496 distanceToTarget = maxPath;
2497 nextSf = -1;
2498 continue;
2499 }
2500
2501 // If h and distance are in opposite directions, target is passed. Flip propagation direction
2502 // Verify if true intersection
2503 // if ( h * propDir * distanceEst < 0. && std::abs(distanceEst)>distanceTolerance ) {
2504 if ((*vsIter).second.first * propDir * distanceEst < 0. &&
2505 std::abs(distanceEst) > distanceTolerance) {
2506 // verify change of sign in signedDistance ( after eliminating situations where this is meaningless
2507 // )
2508 if (!distSol.signedDistance() || std::abs(distSol.currentDistance(true)) < tol ||
2509 std::abs((*vsIter).second.second) < tol ||
2510 (*vsIter).second.second * distSol.currentDistance(true) < 0) { // true intersection
2511 if (ic == nextSf) {
2512 ((*vsIter).first)++;
2513 // eliminate surface if diverging
2514 if ((*vsIter).first > 3) {
2515 helpSoft = fmax(0.05, 1. - 0.05 * (*vsIter).first);
2516 if ((*vsIter).first > 20)
2517 helpSoft = 1. / (*vsIter).first;
2518 }
2519 // take care of eliminating when number of flips even - otherwise it may end up at the start !
2520 if ((*vsIter).first > 50 && h * propDir > 0) {
2521 // std::abs(distanceEst) >= std::abs(previousDistance) ) {
2522 (*vsIter).first = -1;
2523 vsIter = vsBeg;
2524 restart = true;
2525 continue;
2526 }
2527 if ((*vsIter).first != -1)
2528 flipDirection = true;
2529 } else if (std::abs((*vsIter).second.second) > tol &&
2530 std::abs(distSol.currentDistance(true)) > tol) {
2531 // here we need to compare with distance from current closest
2532 if (ic > nextSf && nextSf != -1) { // easy case, already calculated
2533 if (propDir * distanceEst < (cache.m_currentDist.at(nextSf)).second.first - tol) {
2534 if ((*vsIter).first != -1) {
2535 ((*vsIter).first)++;
2536 flipDirection = true;
2537 nextSf = ic;
2538 }
2539 }
2540 } else if (distanceToTarget >
2541 0.) { // set as nearest (if not iterating already), will be rewritten later
2542 if ((*vsIter).first != -1) {
2543 ((*vsIter).first)++;
2544 flipDirection = true;
2545 nextSf = ic;
2546 }
2547 }
2548 }
2549 } else if (ic == nextSf) {
2550 vsIter = vsBeg;
2551 restart = true;
2552 continue;
2553 }
2554 }
2555
2556 // save current distance to surface
2557 (*vsIter).second.first = propDir * distanceEst;
2558 (*vsIter).second.second = distSol.currentDistance(true);
2559
2560 // find closest surface: the step may have been beyond several surfaces
2561 // from all surfaces with 'negative' distance, consider only the one currently designed as 'closest'
2562 // mw if ((*vsIter).first!=-1 && ( distanceEst>-tol || ic==nextSf ) ) {
2563 if ((*vsIter).first != -1 && (distanceEst > 0. || ic == nextSf)) {
2564 ++numSf;
2565 if (distanceEst < std::abs(distanceToTarget)) {
2566 distanceToTarget = propDir * distanceEst;
2567 nextSfCand = ic;
2568 }
2569 }
2570 } else if (std::abs(path) > std::abs((*vsIter).second.second) || dev < 0.985 ||
2571 nextSf < 0) { // keep an eye on surfaces with negative distance; tracks are curved !
2572 Trk::DistanceSolution distSol =
2573 (*sIter).first->straightLineDistanceEstimate(position, propDir * direction);
2574 double distanceEst = -propDir * maxPath;
2575 if (distSol.numberOfSolutions() > 0) {
2576 distanceEst = distSol.first();
2577 }
2578 // save current distance to surface
2579 (*vsIter).second.first = propDir * distanceEst;
2580 (*vsIter).second.second = distSol.currentDistance(true);
2581 // reactivate surface
2582 if (distanceEst > tol && distanceEst < maxPath) {
2583 (*vsIter).first = 0;
2584 } else {
2585 (*vsIter).second.first = distSol.currentDistance() + std::abs(path);
2586 }
2587 if ((*vsIter).first != -1 && distanceEst > 0.) {
2588 ++numSf;
2589 if (distanceEst < std::abs(distanceToTarget)) {
2590 distanceToTarget = propDir * distanceEst;
2591 nextSfCand = ic;
2592 }
2593 }
2594 }
2595 // additional protection - return to the same surface
2596 // eliminate the surface and restart the search
2597 // 04/10/10 ST:infinite loop due to distanceTolerance>tol fixed;
2598 if (std::abs(distanceToTarget) <= distanceTolerance && path * propDir < distanceTolerance) {
2599 (*vsIter).first = -1;
2600 vsIter = vsBeg;
2601 restart = true;
2602 continue;
2603 }
2604 ++sIter;
2605 ++ic;
2606 }
2607 // if next closest not found, propagation failed
2608 if (nextSf < 0 && nextSfCand < 0)
2609 return false;
2610 // flip direction
2611 if (flipDirection) {
2612 // Out of bounds protection
2613 if (nextSf < 0 || nextSf >= num_vs_dist)
2614 return false;
2615 distanceToTarget = (*(vsBeg + nextSf)).second.first;
2616 h = -h;
2617 } else if (nextSfCand != nextSf) {
2618 nextSf = nextSfCand;
2619 // Out of bounds protection
2620 if (nextSf < 0 || nextSf >= num_vs_dist)
2621 return false;
2622 if (cache.m_currentDist[nextSf].first < 3)
2623 helpSoft = 1.;
2624 }
2625
2626 // don't step beyond surfaces - adjust step
2627 if (std::abs(h) > std::abs(distanceToTarget))
2628 h = distanceToTarget;
2629
2630 // don't step beyond bin boundary - adjust step
2631 if (cache.m_binMat && std::abs(h) > std::abs(distanceToNextBin) + 0.001) {
2632 if (distanceToNextBin > 0) { // TODO : investigate source of negative distance in BinningData
2633 h = distanceToNextBin * propDir;
2634 }
2635 }
2636
2637 if (helpSoft < 1.)
2638 h *= helpSoft;
2639
2640 // don't step much beyond path limit
2641 if (cache.m_propagateWithPathLimit > 0 && h > cache.m_pathLimit)
2642 h = cache.m_pathLimit + tol;
2643
2644 // Abort if maxPath is reached
2645 if (std::abs(path) > maxPath)
2646 return false;
2647
2648 if (steps++ > cache.m_maxSteps)
2649 return false; // Too many steps, something is wrong
2650 }
2651
2652 if (!numSf)
2653 return false;
2654
2655 // Use Taylor expansions to step the remaining distance (typically microns).
2656 path = path + distanceToTarget;
2657
2658 // timing
2659 mom = std::abs(1. / P[6]);
2660 beta = mom / std::sqrt(mom * mom + cache.m_particleMass * cache.m_particleMass);
2661 cache.m_timeStep += distanceToTarget / beta / Gaudi::Units::c_light;
2662
2663 // pos = pos + h*dir + 1/2*h*h*dDir. Second order Taylor expansion.
2664 pos[0] = pos[0] + distanceToTarget * (dir[0] + 0.5 * distanceToTarget * dDir[0]);
2665 pos[1] = pos[1] + distanceToTarget * (dir[1] + 0.5 * distanceToTarget * dDir[1]);
2666 pos[2] = pos[2] + distanceToTarget * (dir[2] + 0.5 * distanceToTarget * dDir[2]);
2667
2668 // dir = dir + h*dDir. First order Taylor expansion (Euler).
2669 dir[0] = dir[0] + distanceToTarget * dDir[0];
2670 dir[1] = dir[1] + distanceToTarget * dDir[1];
2671 dir[2] = dir[2] + distanceToTarget * dDir[2];
2672
2673 // Normalize dir
2674 double norm = 1. / std::sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
2675 dir[0] = norm * dir[0];
2676 dir[1] = norm * dir[1];
2677 dir[2] = norm * dir[2];
2678 P[42] = dDir[0];
2679 P[43] = dDir[1];
2680 P[44] = dDir[2];
2681
2682 // collect all surfaces with distance below tolerance
2683 std::vector<std::pair<int, std::pair<double, double>>>::iterator vsIter = vsBeg;
2684
2685 int index = 0;
2686 for (; vsIter != vsEnd; ++vsIter) {
2687 if ((*vsIter).first != -1 && propDir * (*vsIter).second.first >= propDir * distanceToTarget - tol &&
2688 propDir * (*vsIter).second.first < 0.01 && index != nextSf) {
2689 solutions.push_back(index);
2690 }
2691 if (index == nextSf)
2692 solutions.push_back(index);
2693 ++index;
2694 }
2695
2696 return true;
2697}
static Double_t P(Double_t *tt, Double_t *par)
const BinnedMaterial * binnedMaterial() const
access to binned material
size_t bins(size_t ba=0) const
Number of bins.
Definition BinUtility.h:221
std::pair< size_t, float > distanceToNext(const Amg::Vector3D &position, const Amg::Vector3D &direction, size_t ba=0) const
Distance estimate to next bin.
Definition BinUtility.h:154
double second() const
Distance to second intersection solution along direction (for a cylinder surface)
double currentDistance(bool signedDist=false) const
Current distance to surface (spatial), signed (along/opposite to surface normal) if input argument tr...
int numberOfSolutions() const
Number of intersection solutions.
bool signedDistance() const
This method indicates availability of signed current distance (false for Perigee and StraighLineSurfa...
double first() const
Distance to first intersection solution along direction.
DoubleProperty m_momentumCutOff
void sampleBrem(Cache &cache, double mom) const
str index
Definition DeMoScan.py:362
std::pair< std::shared_ptr< Material >, int > IdentifiedMaterial
int ic
Definition grepfile.py:33

◆ 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 }

◆ sampleBrem()

void Trk::STEP_Propagator::sampleBrem ( Cache & cache,
double mom ) const
private

Definition at line 2786 of file STEP_Propagator.cxx.

2786 {
2787 if (!cache.m_randomEngine) {
2788 cache.m_randomEngine = getRandomEngine(cache.m_ctx);
2789 }
2790 double rndx = CLHEP::RandFlat::shoot(cache.m_randomEngine);
2791 double rnde = CLHEP::RandFlat::shoot(cache.m_randomEngine);
2792
2793 // sample visible fraction of the mother momentum taken according to 1/f
2794 double eps = cache.m_momentumCutOff / mom;
2795 cache.m_bremMom = pow(eps, pow(rndx, exp(1.))) * mom; // adjustment here ?
2796 cache.m_bremSampleThreshold = mom - cache.m_bremMom;
2797 cache.m_bremEmitThreshold = mom - rnde * cache.m_bremMom;
2798}
constexpr int pow(int base, int exp) noexcept
CLHEP::HepRandomEngine * getRandomEngine(const EventContext &ctx) const

◆ setCacheFromProperties()

void Trk::STEP_Propagator::setCacheFromProperties ( Cache & cache) const
inlineprivate

initialize cache with the variables we need to take from

Definition at line 421 of file STEP_Propagator.h.

422 {
423 cache.m_includeBgradients = m_includeBgradients;
424 cache.m_includeGgradient = m_includeGgradient;
425 cache.m_energyLoss = m_energyLoss;
426 cache.m_detailedElossFlag = m_detailedEloss;
427 cache.m_MPV = m_MPV;
428 cache.m_multipleScattering = m_multipleScattering;
429 cache.m_straggling = m_straggling;
430 cache.m_tolerance = m_tolerance;
431 cache.m_momentumCutOff = m_momentumCutOff;
432 cache.m_scatteringScale = m_scatteringScale;
433 cache.m_maxPath = m_maxPath;
434 cache.m_maxSteps = m_maxSteps;
435 cache.m_layXmax = m_layXmax;
436 }
DoubleProperty m_tolerance
IntegerProperty m_maxSteps
BooleanProperty m_MPV
BooleanProperty m_includeGgradient
DoubleProperty m_maxPath
DoubleProperty m_layXmax
BooleanProperty m_includeBgradients
DoubleProperty m_scatteringScale

◆ smear()

void Trk::STEP_Propagator::smear ( Cache & cache,
double & phi,
double & theta,
const Trk::TrackParameters * parms,
double radDist ) const
private

Definition at line 2749 of file STEP_Propagator.cxx.

2750 {
2751 if (cache.m_particle == Trk::geantino)
2752 return;
2753 if (!parms)
2754 return;
2755
2756 if (!cache.m_randomEngine) {
2757 cache.m_randomEngine = getRandomEngine(cache.m_ctx);
2758 }
2759
2760 // Calculate polar angle
2761 double particleMass = Trk::ParticleMasses::mass[cache.m_particle]; // Get particle mass from
2762 // ParticleHypothesis
2763 double momentum = parms->momentum().mag();
2764 double energy = std::sqrt(momentum * momentum + particleMass * particleMass);
2765 double beta = momentum / energy;
2766 double th = std::sqrt(2.) * 15. * std::sqrt(radDist) / (beta * momentum) *
2767 CLHEP::RandGauss::shoot(cache.m_randomEngine); // Moliere
2768 // double th = (sqrt(2.)*13.6*std::sqrt(radDist)/(beta*momentum)) *
2769 // (1.+0.038*log(radDist/(beta*beta))) * m_gaussian->shoot(); //Highland
2770
2771 // Calculate azimuthal angle
2772 double ph = 2. * M_PI * CLHEP::RandFlat::shoot(cache.m_randomEngine);
2773
2775 Amg::AngleAxis3D(-phi, Amg::Vector3D(0., 0., 1.)));
2776 Amg::Vector3D dir0(0., 0., 1.);
2777 Amg::Vector3D rotated = rot.inverse() * Amg::AngleAxis3D(ph, Amg::Vector3D(0., 0., 1.)) *
2778 Amg::AngleAxis3D(th, Amg::Vector3D(0., 1., 0.)) * dir0;
2779
2780 theta = rotated.theta();
2781 phi = rotated.phi();
2782}
#define M_PI
Eigen::AngleAxisd AngleAxis3D
@ theta
Definition ParamDefs.h:66
@ phi
Definition ParamDefs.h:75

◆ sysInitialize()

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

Perform system initialization for an algorithm.

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

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

◆ sysStart()

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

Handle START transition.

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

◆ 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

Member Data Documentation

◆ m_detailedEloss

BooleanProperty Trk::STEP_Propagator::m_detailedEloss
private
Initial value:
{this, "DetailedEloss", true,
"Provide the extended EnergyLoss object with MopIonization etc."}

Definition at line 499 of file STEP_Propagator.h.

499 {this, "DetailedEloss", true,
500 "Provide the extended EnergyLoss object with MopIonization etc."};

◆ 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_energyLoss

BooleanProperty Trk::STEP_Propagator::m_energyLoss {this, "EnergyLoss", true, "Include energy loss?"}
private

Definition at line 498 of file STEP_Propagator.h.

498{this, "EnergyLoss", true, "Include energy loss?"};

◆ 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_fieldCacheCondObjInputKey

SG::ReadCondHandleKey<AtlasFieldCacheCondObj> Trk::STEP_Propagator::m_fieldCacheCondObjInputKey
private
Initial value:
{
this,
"AtlasFieldCacheCondObj",
"fieldCondObj",
"Name of the Magnetic Field conditions object key"
}

Definition at line 531 of file STEP_Propagator.h.

531 {
532 this,
533 "AtlasFieldCacheCondObj",
534 "fieldCondObj",
535 "Name of the Magnetic Field conditions object key"
536 };

◆ m_includeBgradients

BooleanProperty Trk::STEP_Propagator::m_includeBgradients
private
Initial value:
{this, "IncludeBgradients", true,
"Include B-field gradients in the error propagation"}

Definition at line 490 of file STEP_Propagator.h.

490 {this, "IncludeBgradients", true,
491 "Include B-field gradients in the error propagation"};

◆ m_includeGgradient

BooleanProperty Trk::STEP_Propagator::m_includeGgradient
private
Initial value:
{this, "IncludeGgradient", false,
"Include dg/dlambda into the error propagation? Only relevant when energy loss is true."}

Definition at line 492 of file STEP_Propagator.h.

492 {this, "IncludeGgradient", false,
493 "Include dg/dlambda into the error propagation? Only relevant when energy loss is true."};

◆ m_layXmax

DoubleProperty Trk::STEP_Propagator::m_layXmax
private
Initial value:
{this, "MSstepMax", 1.,
"maximal layer thickness for multiple scattering calculations"}

Definition at line 513 of file STEP_Propagator.h.

513 {this, "MSstepMax", 1.,
514 "maximal layer thickness for multiple scattering calculations"};

◆ m_materialEffects

BooleanProperty Trk::STEP_Propagator::m_materialEffects
private
Initial value:
{this, "MaterialEffects", true,
"Switch material effects on or off"}

Definition at line 488 of file STEP_Propagator.h.

488 {this, "MaterialEffects", true,
489 "Switch material effects on or off"};

◆ m_maxPath

DoubleProperty Trk::STEP_Propagator::m_maxPath
private
Initial value:
{this, "MaxPath", 100000.,
"Maximum propagation length in mm."}

Definition at line 509 of file STEP_Propagator.h.

509 {this, "MaxPath", 100000.,
510 "Maximum propagation length in mm."};

◆ m_maxSteps

IntegerProperty Trk::STEP_Propagator::m_maxSteps
private
Initial value:
{this, "MaxSteps", 10000,
"Maximum number of allowed steps (to avoid infinite loops)."}

Definition at line 511 of file STEP_Propagator.h.

511 {this, "MaxSteps", 10000,
512 "Maximum number of allowed steps (to avoid infinite loops)."};

◆ m_momentumCutOff

DoubleProperty Trk::STEP_Propagator::m_momentumCutOff
private
Initial value:
{this, "MomentumCutOff", 50.,
"Stop propagation below this momentum in MeV"}

Definition at line 494 of file STEP_Propagator.h.

494 {this, "MomentumCutOff", 50.,
495 "Stop propagation below this momentum in MeV"};

◆ m_MPV

BooleanProperty Trk::STEP_Propagator::m_MPV
private
Initial value:
{this, "MostProbableEnergyLoss", false,
"Use the most probable value of the energy loss, else use the mean energy loss."}

Definition at line 503 of file STEP_Propagator.h.

503 {this, "MostProbableEnergyLoss", false,
504 "Use the most probable value of the energy loss, else use the mean energy loss."};

◆ m_multipleScattering

BooleanProperty Trk::STEP_Propagator::m_multipleScattering
private
Initial value:
{this, "MultipleScattering", true,
"Add multiple scattering to the covariance matrix?"}

Definition at line 496 of file STEP_Propagator.h.

496 {this, "MultipleScattering", true,
497 "Add multiple scattering to the covariance matrix?"};

◆ m_randomEngineName

StringProperty Trk::STEP_Propagator::m_randomEngineName
private
Initial value:
{this, "RandomStreamName", "FatrasRnd",
"Name of the random number stream"}

Definition at line 527 of file STEP_Propagator.h.

527 {this, "RandomStreamName", "FatrasRnd",
528 "Name of the random number stream"};

◆ m_rndGenSvc

ServiceHandle<IAthRNGSvc> Trk::STEP_Propagator::m_rndGenSvc
private
Initial value:
{this, "RandomNumberService", "AthRNGSvc",
"Random number generator"}

Random Generator service.

Definition at line 523 of file STEP_Propagator.h.

523 {this, "RandomNumberService", "AthRNGSvc",
524 "Random number generator"};

◆ m_rngWrapper

ATHRNG::RNGWrapper* Trk::STEP_Propagator::m_rngWrapper = nullptr
private

Random engine.

Definition at line 526 of file STEP_Propagator.h.

◆ m_scatteringScale

DoubleProperty Trk::STEP_Propagator::m_scatteringScale
private
Initial value:
{this, "MultipleScatteringScale", 1.,
"Scale for adjusting the multiple scattering contribution to the covariance matrix."}

Definition at line 507 of file STEP_Propagator.h.

507 {this, "MultipleScatteringScale", 1.,
508 "Scale for adjusting the multiple scattering contribution to the covariance matrix."};

◆ m_simMatUpdator

ToolHandle<ITimedMatEffUpdator> Trk::STEP_Propagator::m_simMatUpdator {this, "SimMatEffUpdator", ""}
private

secondary interactions (brem photon emission)

Definition at line 521 of file STEP_Propagator.h.

521{this, "SimMatEffUpdator", ""};

◆ m_simulation

BooleanProperty Trk::STEP_Propagator::m_simulation
private
Initial value:
{this, "SimulationMode", false,
"flag for simulation mode"}

Definition at line 518 of file STEP_Propagator.h.

518 {this, "SimulationMode", false,
519 "flag for simulation mode"};

◆ m_straggling

BooleanProperty Trk::STEP_Propagator::m_straggling
private
Initial value:
{this, "Straggling", true,
"Add energy loss fluctuations (straggling) to the covariance matrix?"}

Definition at line 501 of file STEP_Propagator.h.

501 {this, "Straggling", true,
502 "Add energy loss fluctuations (straggling) to the covariance matrix?"};

◆ m_stragglingScale

DoubleProperty Trk::STEP_Propagator::m_stragglingScale
private
Initial value:
{this, "StragglingScale", 1.,
"Scale for adjusting the width of the energy loss fluctuations."}

Definition at line 505 of file STEP_Propagator.h.

505 {this, "StragglingScale", 1.,
506 "Scale for adjusting the width of the energy loss fluctuations."};

◆ m_tolerance

DoubleProperty Trk::STEP_Propagator::m_tolerance
private
Initial value:
{this, "Tolerance", 1e-05,
"Error tolerance. Low tolerance gives igh accuracy"}

Definition at line 486 of file STEP_Propagator.h.

486 {this, "Tolerance", 1e-05,
487 "Error tolerance. Low tolerance gives igh accuracy"};

◆ 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: