ATLAS Offline Software
Loading...
Searching...
No Matches
RungeKuttaIntersector.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6// Runge-Kutta method for tracking a particle through a magnetic field
7// (c) ATLAS Detector software
9
10#ifndef TRKEXRUNGEKUTTAINTERSECTOR_RUNGEKUTTAINTERSECTOR_H
11#define TRKEXRUNGEKUTTAINTERSECTOR_RUNGEKUTTAINTERSECTOR_H
12
13#include <atomic>
14
17#include "GaudiKernel/PhysicalConstants.h"
18#include "GaudiKernel/ToolHandle.h"
25
26namespace Trk {
27
28class RungeKuttaIntersector final : public extends<AthAlgTool, IIntersector> {
29
30 public:
31 RungeKuttaIntersector(const std::string& type, const std::string& name,
32 const IInterface* parent);
33 virtual ~RungeKuttaIntersector() = default;
34
35 virtual StatusCode initialize() override;
36 virtual StatusCode finalize() override;
37
39 virtual std::optional<TrackSurfaceIntersection> intersectSurface(
40 const Surface& surface, const TrackSurfaceIntersection& trackIntersection,
41 const double qOverP) const override;
42
44 virtual std::optional<TrackSurfaceIntersection> approachPerigeeSurface(
45 const PerigeeSurface& surface,
46 const TrackSurfaceIntersection& trackIntersection,
47 const double qOverP) const override;
48
51 virtual std::optional<TrackSurfaceIntersection> approachStraightLineSurface(
52 const StraightLineSurface& surface,
53 const TrackSurfaceIntersection& trackIntersection,
54 const double qOverP) const override;
55
58 virtual std::optional<TrackSurfaceIntersection> intersectCylinderSurface(
59 const CylinderSurface& surface,
60 const TrackSurfaceIntersection& trackIntersection,
61 const double qOverP) const override;
62
64 virtual std::optional<TrackSurfaceIntersection> intersectDiscSurface(
65 const DiscSurface& surface,
66 const TrackSurfaceIntersection& trackIntersection,
67 const double qOverP) const override;
68
70 virtual std::optional<TrackSurfaceIntersection> intersectPlaneSurface(
71 const PlaneSurface& surface,
72 const TrackSurfaceIntersection& trackIntersection,
73 const double qOverP) const override;
74
77 virtual bool isValid(Amg::Vector3D /*startPosition*/,
78 Amg::Vector3D /*endPosition*/) const override {
79 return true;
80 }
81
82 private:
83 // private methods
85 double& stepLength) const;
87 const Surface& surface, const double qOverP,
88 const double rStart, const double zStart,
89 const bool trapped) const;
91 const double cylinderRadius,
92 const double offsetRadius,
93 const Amg::Vector3D& offset,
94 double& stepLength) const;
95 double distanceToDisc(const TrackSurfaceIntersection& isect,
96 const double discZ, double& stepLength) const;
97
98 double distanceToLine(const TrackSurfaceIntersection& isect,
99 const Amg::Vector3D& linePosition,
100 const Amg::Vector3D& lineDirection,
101 double& stepLength) const;
102
103 double distanceToPlane(const TrackSurfaceIntersection& isect,
104 const Amg::Vector3D& planePosition,
105 const Amg::Vector3D& planeNormal,
106 double& stepLength) const;
107
108 Amg::Vector3D field(const Amg::Vector3D& point,
109 MagField::AtlasFieldCache& fieldCache) const;
110
111 void initializeFieldCache(MagField::AtlasFieldCache& fieldCache) const;
112
113 std::optional<TrackSurfaceIntersection> newIntersection(
114 TrackSurfaceIntersection&& isect, const Surface& surface,
115 const double qOverP, const double rStart, const double zStart) const;
116
118 const Amg::Vector3D& fieldValue, const double stepLength,
119 const double qOverP) const;
120
121 void step(TrackSurfaceIntersection& isect, Amg::Vector3D& fieldValue,
122 double& stepLength, const double qOverP,
123 MagField::AtlasFieldCache& fieldCache) const;
124
126 this, "AtlasFieldCacheCondObj", "fieldCondObj",
127 "Name of the Magnetic Field conditions object key"};
128
129 // additional configuration
130 BooleanProperty m_productionMode{this, "ProductionMode", true};
131
132 // some precalculated constants:
133 // r min for calo high field gradient region
134 const double m_caloR0 = 1900.*Gaudi::Units::mm;
135 // r max for calo high field gradient region
136 const double m_caloR1 = 2500.*Gaudi::Units::mm;
137 // r min for calo medium field gradient region
138 const double m_caloR2 = 3500.*Gaudi::Units::mm;
139 // r min for calo outer flux return region
140 const double m_caloR3 = 3700.*Gaudi::Units::mm;
141 // r max for calo medium field gradient region
142 const double m_caloR4 = 3800.*Gaudi::Units::mm;
143 // z min for calo medium field gradient region
144 const double m_caloZ0 = 2350.*Gaudi::Units::mm;
145 // z min for calo high field gradient region
146 const double m_caloZ1 = 2600.*Gaudi::Units::mm;
147 // z max for calo high field gradient region
148 const double m_caloZ2 = 3600.*Gaudi::Units::mm;
149 // z min for calo outer flux return region
150 const double m_caloZ3 = 6000.*Gaudi::Units::mm;
151 // end of central barrel near constant field region
152 const double m_inDetR0 = 400.*Gaudi::Units::mm;
153 // inner radius of middle/outer transition region
154 const double m_inDetR1 = 350.*Gaudi::Units::mm;
155 // outer radius of low field gradient field region
156 const double m_inDetR2 = 800.*Gaudi::Units::mm;
157 // end of central barrel near constant field region
158 const double m_inDetZ0 = 350.*Gaudi::Units::mm;
159 // start of well behaved transition region
160 const double m_inDetZ1 = 420.*Gaudi::Units::mm;
161 // start of endcap region
162 const double m_inDetZ2 = 700.*Gaudi::Units::mm;
163 // protection against loopers
164 const double m_momentumThreshold = 1./20.*Gaudi::Units::MeV;
165 // warning threshold for intersection failure
166 const double m_momentumWarnThreshold = 1./450.*Gaudi::Units::MeV;
167 // inner radius of barrel toroid region
168 const double m_muonR0 = 4300.*Gaudi::Units::mm;
169 // start of endcap toroid region
170 const double m_muonZ0 = 6600.*Gaudi::Units::mm;
171 double m_shortStepMax = 3.0*Gaudi::Units::mm;
172 const double m_shortStepMin = 10.*Gaudi::Units::nanometer;
173 // r max after coil (will take small steps near coil)
174 const double m_solenoidR = 1300.*Gaudi::Units::mm;
175 // z end of InDet region
176 const double m_solenoidZ = 3500.*Gaudi::Units::mm;
177 double m_stepMax0 = 8.0*Gaudi::Units::mm;
178 double m_stepMax1 = 40.0*Gaudi::Units::mm;
179 double m_stepMax2 = 80.0*Gaudi::Units::mm;
180 double m_stepMax3 = 160.0*Gaudi::Units::mm;
181 double m_stepMax4 = 320.0*Gaudi::Units::mm;
183 const double m_third = 1./3.;
184 // endcap toroid central field - inner radius
185 const double m_toroidR0 = 1850.0*Gaudi::Units::mm;
186 // endcap toroid central field - outer radius
187 const double m_toroidR1 = 3500.0*Gaudi::Units::mm;
188 // after inner barrel or outer endcap coil
189 const double m_toroidR2 = 6000.0*Gaudi::Units::mm;
190 // toroid region - radius above which long steps OK
191 const double m_toroidR3 = 6500.0*Gaudi::Units::mm;
192 // endcap - near iron structure
193 const double m_toroidZ0 = 7000.0*Gaudi::Units::mm;
194 // endcap - high field gradient
195 const double m_toroidZ1 = 8000.0*Gaudi::Units::mm;
196 // barrel - before coil end loop
197 const double m_toroidZ2 = 8700.0*Gaudi::Units::mm;
198 // barrel - nearing coil end loop
199 const double m_toroidZ3 = 9100.0*Gaudi::Units::mm;
200 // endcap toroid full field and barrel coil regions
201 const double m_toroidZ4 = 9500.0*Gaudi::Units::mm;
202 // endcap toroid central field - inner z
203 const double m_toroidZ5 = 9800.0*Gaudi::Units::mm;
204 // endcap toroid central field - outer z
205 const double m_toroidZ6 = 11400.0*Gaudi::Units::mm;
206 // toroid exit fringe fields
207 const double m_toroidZ7 = 12900.0*Gaudi::Units::mm;
208 // essentially out of any toroid fields
209 const double m_toroidZ8 = 14000.0*Gaudi::Units::mm;
210
211 // counters
212 mutable std::atomic<unsigned long long> m_countExtrapolations = 0;
213 mutable std::atomic<unsigned long long> m_countShortStep = 0;
214 mutable std::atomic<unsigned long long> m_countStep = 0;
215 mutable std::atomic<unsigned long long> m_countStepReduction = 0;
216};
217
218//<<<<<< INLINE PRIVATE MEMBER FUNCTIONS >>>>>>
219
221 const TrackSurfaceIntersection& isect, const double cylinderRadius,
222 const double offsetRadius, const Amg::Vector3D& offset,
223 double& stepLength) const {
224 const Amg::Vector3D& dir = isect.direction();
225
226 double sinThsqinv = 1. / dir.perp2();
227 stepLength = (offset.x() * dir.x() + offset.y() * dir.y()) * sinThsqinv;
228 double deltaRSq = (cylinderRadius - offsetRadius) *
229 (cylinderRadius + offsetRadius) * sinThsqinv +
230 stepLength * stepLength;
231 if (deltaRSq > 0.)
232 stepLength += sqrt(deltaRSq);
233 return std::abs(stepLength);
234}
235
237 const TrackSurfaceIntersection& isect, const double discZ,
238 double& stepLength) const {
239 const Amg::Vector3D& pos = isect.position();
240 const Amg::Vector3D& dir = isect.direction();
241
242 double distance = discZ - pos.z();
243 stepLength = distance / dir.z();
244 return std::abs(distance);
245}
246
248 const TrackSurfaceIntersection& isect, const Amg::Vector3D& linePosition,
249 const Amg::Vector3D& lineDirection, double& stepLength) const {
250 // offset joining track to line is given by
251 // offset = linePosition + a*lineDirection - trackPosition -
252 // b*trackDirection
253 //
254 // offset is perpendicular to both line and track at solution i.e.
255 // lineDirection.dot(offset) = 0
256 // trackDirection.dot(offset) = 0
257 const Amg::Vector3D& pos = isect.position();
258 const Amg::Vector3D& dir = isect.direction();
259
260 double cosAngle = lineDirection.dot(dir);
261 stepLength = (linePosition - pos).dot(dir - lineDirection * cosAngle) /
262 (1. - cosAngle * cosAngle);
263 return std::abs(stepLength);
264}
265
267 const TrackSurfaceIntersection& isect, const Amg::Vector3D& planePosition,
268 const Amg::Vector3D& planeNormal, double& stepLength) const {
269 // take the normal component of the offset from track position to plane
270 // position this is equal to the normal component of the required distance
271 // along the track direction
272 const Amg::Vector3D& pos = isect.position();
273 const Amg::Vector3D& dir = isect.direction();
274
275 double distance = planeNormal.dot(planePosition - pos);
276 stepLength = distance / planeNormal.dot(dir);
277 return std::abs(distance);
278}
279
281 MagField::AtlasFieldCache& fieldCache) const {
284 if (!fieldCondObj.isValid()) {
285 ATH_MSG_FATAL("Failed to get magnetic field conditions data "
287 }
288 fieldCondObj->getInitializedCache(fieldCache);
289}
290
292 const Amg::Vector3D& position,
293 MagField::AtlasFieldCache& fieldCache) const {
294 Amg::Vector3D fieldValue;
295 fieldCache.getField(position.data(), fieldValue.data());
296 return fieldValue;
297}
298
299inline std::optional<TrackSurfaceIntersection> RungeKuttaIntersector::newIntersection(
300 TrackSurfaceIntersection&& isect, const Surface& surface,
301 const double qOverP, const double rStart, const double zStart) const {
302 // ensure intersection is valid (ie. on surface)
303 Intersection SLIntersect = surface.straightLineIntersection(
304 isect.position(), isect.direction(), false, false);
305 if (SLIntersect.valid) {
306 isect.position() = SLIntersect.position;
307 return std::move(isect);
308 }
309
310 // invalid: take care to invalidate cache!
311 if (msgLvl(MSG::DEBUG)){
312 debugFailure(std::move(isect), surface, qOverP, rStart, zStart, false);
313 }
314
315 return std::nullopt;
316}
317
318} // namespace Trk
319
320#endif // TRKEXRUNGEKUTTAINTERSECTOR_RUNGEKUTTAINTERSECTOR_H
#define ATH_MSG_FATAL(x)
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
void getField(const double *ATH_RESTRICT xyz, double *ATH_RESTRICT bxyz, double *ATH_RESTRICT deriv=nullptr)
get B field value at given position xyz[3] is in mm, bxyz[3] is in kT if deriv[9] is given,...
Class for a CylinderSurface in the ATLAS detector.
Class for a DiscSurface in the ATLAS detector.
Definition DiscSurface.h:54
Class describing the Line to which the Perigee refers to.
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
virtual std::optional< TrackSurfaceIntersection > intersectDiscSurface(const DiscSurface &surface, const TrackSurfaceIntersection &trackIntersection, const double qOverP) const override
IIntersector interface method for specific Surface type : DiscSurface.
virtual ~RungeKuttaIntersector()=default
virtual StatusCode initialize() override
std::optional< TrackSurfaceIntersection > newIntersection(TrackSurfaceIntersection &&isect, const Surface &surface, const double qOverP, const double rStart, const double zStart) const
virtual bool isValid(Amg::Vector3D, Amg::Vector3D) const override
IIntersector interface method for validity check over a particular extrapolation range.
virtual std::optional< TrackSurfaceIntersection > approachPerigeeSurface(const PerigeeSurface &surface, const TrackSurfaceIntersection &trackIntersection, const double qOverP) const override
IIntersector interface method for specific Surface type : PerigeeSurface.
void debugFailure(TrackSurfaceIntersection &&isect, const Surface &surface, const double qOverP, const double rStart, const double zStart, const bool trapped) const
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
void step(TrackSurfaceIntersection &isect, Amg::Vector3D &fieldValue, double &stepLength, const double qOverP, MagField::AtlasFieldCache &fieldCache) const
void assignStepLength(const TrackSurfaceIntersection &isect, double &stepLength) const
double distanceToPlane(const TrackSurfaceIntersection &isect, const Amg::Vector3D &planePosition, const Amg::Vector3D &planeNormal, double &stepLength) const
std::atomic< unsigned long long > m_countStepReduction
double distanceToLine(const TrackSurfaceIntersection &isect, const Amg::Vector3D &linePosition, const Amg::Vector3D &lineDirection, double &stepLength) const
std::atomic< unsigned long long > m_countStep
virtual std::optional< TrackSurfaceIntersection > approachStraightLineSurface(const StraightLineSurface &surface, const TrackSurfaceIntersection &trackIntersection, const double qOverP) const override
IIntersector interface method for specific Surface type : StraightLineSurface.
RungeKuttaIntersector(const std::string &type, const std::string &name, const IInterface *parent)
double distanceToCylinder(const TrackSurfaceIntersection &isect, const double cylinderRadius, const double offsetRadius, const Amg::Vector3D &offset, double &stepLength) const
double distanceToDisc(const TrackSurfaceIntersection &isect, const double discZ, double &stepLength) const
std::atomic< unsigned long long > m_countExtrapolations
virtual std::optional< TrackSurfaceIntersection > intersectPlaneSurface(const PlaneSurface &surface, const TrackSurfaceIntersection &trackIntersection, const double qOverP) const override
IIntersector interface method for specific Surface type : PlaneSurface.
virtual std::optional< TrackSurfaceIntersection > intersectSurface(const Surface &surface, const TrackSurfaceIntersection &trackIntersection, const double qOverP) const override
IIntersector interface method for general Surface type.
void initializeFieldCache(MagField::AtlasFieldCache &fieldCache) const
std::atomic< unsigned long long > m_countShortStep
virtual std::optional< TrackSurfaceIntersection > intersectCylinderSurface(const CylinderSurface &surface, const TrackSurfaceIntersection &trackIntersection, const double qOverP) const override
IIntersector interface method for specific Surface type : CylinderSurface.
virtual StatusCode finalize() override
void shortStep(TrackSurfaceIntersection &isect, const Amg::Vector3D &fieldValue, const double stepLength, const double qOverP) const
Amg::Vector3D field(const Amg::Vector3D &point, MagField::AtlasFieldCache &fieldCache) const
Class for a StraightLineSurface in the ATLAS detector to describe dirft tube and straw like detectors...
Abstract Base Class for tracking surfaces.
Intersection straightLineIntersection(const T &pars, bool forceDir=false, const Trk::BoundaryCheck &bchk=false) const
fst straight line intersection schema - templated for charged and neutral parameters
An intersection with a Surface is given by.
const Amg::Vector3D & direction() const
Method to retrieve the direction at the Intersection.
const Amg::Vector3D & position() const
Method to retrieve the position of the Intersection.
Eigen::Matrix< double, 3, 1 > Vector3D
Ensure that the ATLAS eigen extensions are properly loaded.
@ qOverP
perigee
Definition ParamDefs.h:67
Definition dot.py:1
Amg::Vector3D position