QwAnalysis
QwRayTracer Class Reference

#include <QwRayTracer.h>

+ Inheritance diagram for QwRayTracer:
+ Collaboration diagram for QwRayTracer:

Public Member Functions

 QwRayTracer (QwOptions &options)
 Default constructor. More...
 
virtual ~QwRayTracer ()
 Destructor. More...
 
void ProcessOptions (QwOptions &options)
 Process command line and config file options. More...
 
bool LoadMagneticFieldMap (QwOptions &options)
 Load the magnetic field based on config file options. More...
 
double GetMagneticFieldCurrent () const
 Get magnetic field current. More...
 
void SetMagneticFieldCurrent (const double current)
 Set magnetic field current. More...
 
const QwTrackBridge (const QwPartialTrack *front, const QwPartialTrack *back)
 Bridge from the front to back partial track. More...
 
int IntegrateRK (const TMatrixD &A, const TMatrixD &b, TVector3 &r, TVector3 &v, const double p, const double z, const double h, const double epsilon)
 Runge-Kutta numerical integration by Butcher tableau. More...
 
int IntegrateRK (TVector3 &r, TVector3 &v, const double p, const double z, const int order, const double h)
 Runge-Kutta numerical integration. More...
 
- Public Member Functions inherited from VQwBridgingMethod
 VQwBridgingMethod ()
 Default constructor. More...
 
virtual ~VQwBridgingMethod ()
 Destructor. More...
 

Static Public Member Functions

static void DefineOptions (QwOptions &options)
 Define command line and config file options. More...
 

Private Member Functions

double GetOptimizationVariable (const TVector3 &position, const TVector3 &direction) const
 Optimization variable from position and direction. More...
 

Private Attributes

int fIntegrationOrder
 Runge-Kutta method order. More...
 
double fIntegrationStep
 Runge-Kutta fixed step size for order 4 or less. More...
 
double fIntegrationMinimumStep
 Runge-Kutta minimum and maximum step size for adaptive step. More...
 
double fIntegrationMaximumStep
 Maximum step size. More...
 
double fIntegrationTolerance
 Allowable truncation error in adaptive step. More...
 
int fOptimizationVariable
 Newton's method optimization variable. More...
 
double fOptimizationResolution
 
double fMomentumStep
 Newton's method step size in momentum. More...
 
double fInitialMomentum
 Newton's method initial momentum. More...
 
double fStartPosition
 Starting position for magnetic field swimming. More...
 
double fEndPosition
 Ending position for magnetic field swimming. More...
 
Double_t fBdl
 scalar field integrals More...
 
Double_t fBdlx
 x component of the field integral More...
 
Double_t fBdly
 y component of the field integral More...
 
Double_t fBdlz
 z component of the field integral More...
 

Static Private Attributes

static QwMagneticFieldfBfield = 0
 Magnetic field (static) More...
 

Additional Inherited Members

- Protected Member Functions inherited from VQwBridgingMethod
virtual double EstimateInitialMomentum (const TVector3 &direction) const
 Estimate the momentum based only on the direction. More...
 

Detailed Description

Definition at line 43 of file QwRayTracer.h.

Constructor & Destructor Documentation

QwRayTracer::QwRayTracer ( QwOptions options)

Default constructor.

Constructor: set all member field to zero

Definition at line 48 of file QwRayTracer.cc.

References fBdl, fBdlx, fBdly, fBdlz, LoadMagneticFieldMap(), and ProcessOptions().

50 {
51  fBdl = 0.0;
52  fBdlx = 0.0;
53  fBdly = 0.0;
54  fBdlz = 0.0;
55 
56  // Process command line options
57  ProcessOptions(options);
58 
59  // Load magnetic field
60  LoadMagneticFieldMap(options);
61 }
bool LoadMagneticFieldMap(QwOptions &options)
Load the magnetic field based on config file options.
Definition: QwRayTracer.cc:77
Double_t fBdly
y component of the field integral
Definition: QwRayTracer.h:137
Double_t fBdl
scalar field integrals
Definition: QwRayTracer.h:135
void ProcessOptions(QwOptions &options)
Process command line and config file options.
Definition: QwRayTracer.cc:150
Double_t fBdlx
x component of the field integral
Definition: QwRayTracer.h:136
VQwBridgingMethod()
Default constructor.
Double_t fBdlz
z component of the field integral
Definition: QwRayTracer.h:138

+ Here is the call graph for this function:

QwRayTracer::~QwRayTracer ( )
virtual

Destructor.

Destructor

Definition at line 66 of file QwRayTracer.cc.

References fBfield.

67 {
68  // Delete the magnetic field
69  delete fBfield;
70 }
static QwMagneticField * fBfield
Magnetic field (static)
Definition: QwRayTracer.h:96

Member Function Documentation

const QwTrack * QwRayTracer::Bridge ( const QwPartialTrack front,
const QwPartialTrack back 
)
virtual

Bridge from the front to back partial track.

Bridge the front and back partial tracks using the ray-tracing technique

Parameters
frontFront partial track
backBack partial track
Returns
List of reconstructed tracks

Implements VQwBridgingMethod.

Definition at line 178 of file QwRayTracer.cc.

References QwLog::endl(), fBdl, fBdlx, fBdly, fBdlz, QwTrack::fChi, QwPartialTrack::fChi, QwTrack::fDirectionDiff, QwTrack::fDirectionPhioff, QwTrack::fDirectionThetaoff, QwTrack::fDirectionXoff, QwTrack::fDirectionYoff, QwTrack::fDirectionZoff, QwTrack::fEndDirectionActual, QwTrack::fEndDirectionActualRK4, QwTrack::fEndDirectionActualRKF45, QwTrack::fEndDirectionGoal, fEndPosition, QwTrack::fEndPositionActual, QwTrack::fEndPositionActualRK4, QwTrack::fEndPositionActualRKF45, QwTrack::fEndPositionGoal, fInitialMomentum, fIntegrationOrder, fIntegrationStep, QwTrack::fIterationsNewton, QwTrack::fIterationsRK4, QwTrack::fIterationsRKF45, QwTrack::fIterationsRungeKutta, QwTrack::fMomentum, fMomentumStep, fOptimizationResolution, QwTrack::fPositionDiff, QwTrack::fPositionPhioff, QwTrack::fPositionRoff, QwTrack::fPositionThetaoff, QwTrack::fPositionXoff, QwTrack::fPositionYoff, QwTrack::fStartDirection, QwTrack::fStartPosition, fStartPosition, QwPartialTrack::GetMomentumDirection(), VQwTrackingElement::GetOctant(), GetOptimizationVariable(), VQwTrackingElement::GetPackage(), QwPartialTrack::GetPosition(), IntegrateRK(), MAX_ITERATIONS_NEWTON, QwMessage, QwVerbose, QwTrack::SetMagneticFieldIntegral(), VQwTrackingElement::SetOctant(), and VQwTrackingElement::SetPackage().

Referenced by main(), and QwTrackingWorker::ProcessEvent().

181 {
182  // No track found yet
183  QwTrack* track = 0;
184 
185  // Estimate initial momentum from front track
186  //Double_t momentum = EstimateInitialMomentum(front->GetMomentumDirection());
187 
188  // Start iteration from a smaller momentum than initial guess,
189  // to avoid the gap in the momentum spectrum
190  // if(momentum > 0.50 * Qw::GeV)
191  // momentum = momentum - 0.30 * Qw::GeV;
192  // else
193  // momentum = 0.20 * Qw::GeV;
194  //
195  Double_t momentum = fInitialMomentum;
196 
197  // Front track position and direction
198  TVector3 start_position = front->GetPosition(fStartPosition);
199  TVector3 start_direction = front->GetMomentumDirection();
200 
201  // Back track position and direction
202  TVector3 end_position = back->GetPosition(fEndPosition);
203  TVector3 end_direction = back->GetMomentumDirection();
204 
205  // Position and direction after swimming from front track position and direction
206  TVector3 position = start_position;
207  TVector3 direction = start_direction;
208  IntegrateRK(position, direction, momentum, end_position.Z(), fIntegrationOrder, fIntegrationStep);
209 
210  // Difference to optimize on
211  double difference = GetOptimizationVariable(position,direction) - GetOptimizationVariable(end_position,end_direction);
212 
213  // Count the number of iterations in the Newton's method and Runge-Kutta method
214  int iterations_newton = 0;
215  int iterations_rungekutta = 0;
216 
217  // Loop until we get blow the resolution required (or give up)
218  while (fabs(difference) >= fOptimizationResolution
219  && iterations_newton < MAX_ITERATIONS_NEWTON) {
220 
221  // Increment number of iterations
222  iterations_newton++;
223 
224  // Evaluation optimization variable on both side of current momentum
225  Double_t r[2] = {0.0, 0.0};
226 
227  // momentum - dp
228  position = start_position;
229  direction = start_direction;
230  IntegrateRK(position, direction, momentum - fMomentumStep, end_position.Z(), fIntegrationOrder, fIntegrationStep);
231  r[0] = GetOptimizationVariable(position,direction);
232 
233  // momentum + dp
234  position = start_position;
235  direction = start_direction;
236  IntegrateRK(position, direction, momentum + fMomentumStep, end_position.Z(), fIntegrationOrder, fIntegrationStep);
237  r[1] = GetOptimizationVariable(position,direction);
238 
239  // Correction = f(momentum)
240  if (r[0] != r[1]) {
241  momentum = momentum - fMomentumStep * (r[0] + r[1] - 2.0 * GetOptimizationVariable(end_position,end_direction)) / (r[1] - r[0]);
242  }
243 
244  // Update momentum
245  position = start_position;
246  direction = start_direction;
247  iterations_rungekutta = IntegrateRK(position, direction, momentum, end_position.Z(), fIntegrationOrder, fIntegrationStep);
248 
249  // Update the difference
250  difference = GetOptimizationVariable(position,direction) - GetOptimizationVariable(end_position,end_direction);
251  }
252 
253 
254  if (iterations_newton < MAX_ITERATIONS_NEWTON) {
255 
256  QwVerbose << "Converged after " << iterations_newton << " iterations." << QwLog::endl;
257 
258  /* The following restrictions can now be achieved through bridging filters
259 
260  if (fMomentum < 0.980 * Qw::GeV || fMomentum > 1.165 * Qw::GeV) {
261  QwMessage << "Out of momentum range: determined momentum by shooting: "
262  << fMomentum / Qw::GeV << " GeV" << std::endl;
263  return -1;
264  }
265 
266  if (fabs(fPositionPhiOff) > 10*Qw::deg) {
267  QwMessage << "Out of position Phi-matching range: dPhi by shooting: "
268  << fPositionPhiOff / Qw::deg << " deg" << std::endl;
269  return -1;
270  }
271 
272  if (fabs(fDirectionPhiOff) > 10*Qw::deg) {
273  QwMessage << "Out of direction phi-matching range: dphi by shooting: "
274  << fDirectionPhiOff / Qw::deg << " deg" << std::endl;
275  return -1;
276  }
277 
278  */
279 
280  // Create a new track
281  track = new QwTrack(front,back);
282 
283  // Reconstructed momentum
284  track->fMomentum = momentum;
285  track->fIterationsNewton = iterations_newton;
286  track->fIterationsRungeKutta = iterations_rungekutta;
287 
288  // Runge-Kutta 4th order
289  position = start_position;
290  direction = start_direction;
291  track->fIterationsRK4 = IntegrateRK(position, direction, momentum, end_position.Z(), 4, fIntegrationStep);
292  track->fEndPositionActualRK4 = position;
293  track->fEndDirectionActualRK4 = direction;
294 
295  // Runge-Kutta-Fehlberg 4th-5th order
296  position = start_position;
297  direction = start_direction;
298  track->fIterationsRKF45 = IntegrateRK(position, direction, momentum, end_position.Z(), 5, fIntegrationStep);
299  track->fEndPositionActualRKF45 = position;
300  track->fEndDirectionActualRKF45 = direction;
301 
302  // Let front partial track determine the package and octant
303  track->SetPackage(front->GetPackage());
304  track->SetOctant(front->GetOctant());
305 
306  // Chi2 is sum of front and back partial tracks
307  track->fChi = front->fChi + back->fChi;
308 
309  // Position differences at matching plane
310  TVector3 position_diff = position - end_position;
311  track->fPositionDiff = position_diff;
312  track->fPositionXoff = position_diff.X();
313  track->fPositionYoff = position_diff.Y();
314  track->fPositionRoff = position.Perp() - end_position.Perp();
315  track->fPositionPhioff = position.Phi() - end_position.Phi();
316  track->fPositionThetaoff = position.Theta() - end_position.Theta();
317 
318  // Direction differences at matching plane
319  TVector3 direction_diff = direction - end_direction;
320  track->fDirectionDiff = direction_diff;
321  track->fDirectionXoff = direction_diff.X();
322  track->fDirectionYoff = direction_diff.Y();
323  track->fDirectionZoff = direction_diff.Z();
324  track->fDirectionPhioff = direction.Phi() - end_direction.Phi();
325  track->fDirectionThetaoff = direction.Theta() - end_direction.Theta();
326 
327  track->fStartPosition = start_position;
328  track->fStartDirection = start_direction;
329  track->fEndPositionGoal = end_position;
330  track->fEndDirectionGoal = end_direction;
331  track->fEndPositionActual = position;
332  track->fEndDirectionActual = direction;
333 
334  // Magnetic field integrals
336 
337  } else {
338  QwMessage << "Couldn't converge after " << iterations_newton << " iterations." << QwLog::endl;
339  }
340 
341  return track;
342 }
double fDirectionYoff
Difference in Y momentum at matching plane.
Definition: QwTrack.h:115
#define QwMessage
Predefined log drain for regular messages.
Definition: QwLog.h:50
double fChi
Combined chi, i.e. the sum of the chi for front and back partial track.
Definition: QwTrack.h:99
int fIterationsRungeKutta
Number of iterations in Runge-Kutta method.
Definition: QwTrack.h:103
double fDirectionThetaoff
Difference in momentum polar angle at matching plane.
Definition: QwTrack.h:118
double fOptimizationResolution
Definition: QwRayTracer.h:122
Double_t fBdly
y component of the field integral
Definition: QwRayTracer.h:137
double fPositionPhioff
Difference in azimuthal angle phi at matching plane.
Definition: QwTrack.h:111
int fIterationsRK4
Number of iterations using Runge-Kutta 4th order.
Definition: QwTrack.h:132
int fIterationsNewton
Number of iterations in Newton&#39;s method.
Definition: QwTrack.h:102
double fStartPosition
Starting position for magnetic field swimming.
Definition: QwRayTracer.h:131
double fIntegrationStep
Runge-Kutta fixed step size for order 4 or less.
Definition: QwRayTracer.h:101
TVector3 fStartPosition
Position and direction before and after swimming.
Definition: QwTrack.h:123
int GetOctant() const
Get the octant number.
TVector3 fEndPositionActualRK4
Actual position of track at back plane using Runge-Kutta 4th order.
Definition: QwTrack.h:133
#define QwVerbose
Predefined log drain for verbose messages.
Definition: QwLog.h:55
TVector3 fDirectionDiff
Difference in momentum at matching plane.
Definition: QwTrack.h:113
Double_t fChi
combined chi square
#define MAX_ITERATIONS_NEWTON
Definition: QwRayTracer.cc:35
void SetPackage(EQwDetectorPackage package)
Set the package.
const TVector3 GetPosition(const double z) const
Return the vertex at position z.
Double_t fBdl
scalar field integrals
Definition: QwRayTracer.h:135
double fDirectionPhioff
Difference in momentum azimuthal angle at matching plane.
Definition: QwTrack.h:117
double fPositionRoff
Difference in radial position at matching plane.
Definition: QwTrack.h:110
void SetMagneticFieldIntegral(double bdl, double bdlx, double bdly, double bdlz)
Set magnetic field integral.
Definition: QwTrack.h:76
TVector3 fEndDirectionActual
Actual direction of track at back plane.
Definition: QwTrack.h:130
TVector3 fStartDirection
Start direction of front track.
Definition: QwTrack.h:124
const TVector3 GetMomentumDirection() const
Return the direction.
TVector3 fEndPositionActual
Actual position of track at back plane.
Definition: QwTrack.h:129
Contains the complete track as a concatenation of partial tracks.
Definition: QwTrack.h:30
double fDirectionXoff
Difference in X momentum at matching plane.
Definition: QwTrack.h:114
double fInitialMomentum
Newton&#39;s method initial momentum.
Definition: QwRayTracer.h:128
void SetOctant(int octant)
Set the octant number.
double fDirectionZoff
Difference in Z momentum at matching plane.
Definition: QwTrack.h:116
TVector3 fEndPositionActualRKF45
Actual position of track at back plane using Runge-Kutta-Fehlberg.
Definition: QwTrack.h:137
TVector3 fPositionDiff
Matching of front and back track position and direction at matching plane.
Definition: QwTrack.h:107
Double_t fBdlx
x component of the field integral
Definition: QwRayTracer.h:136
TVector3 fEndDirectionGoal
Goal direction of back track.
Definition: QwTrack.h:127
int fIterationsRKF45
Number of iterations using Runge-Kutta-Fehlberg.
Definition: QwTrack.h:136
static std::ostream & endl(std::ostream &)
End of the line.
Definition: QwLog.cc:299
TVector3 fEndPositionGoal
Goal position of back track.
Definition: QwTrack.h:126
double fPositionXoff
Difference in X position at matching plane.
Definition: QwTrack.h:108
int fIntegrationOrder
Runge-Kutta method order.
Definition: QwRayTracer.h:99
double fEndPosition
Ending position for magnetic field swimming.
Definition: QwRayTracer.h:133
TVector3 fEndDirectionActualRK4
Actual direction of track at back plane using Runge-Kutta 4th order.
Definition: QwTrack.h:134
double fPositionYoff
Difference in Y position at matching plane.
Definition: QwTrack.h:109
TVector3 fEndDirectionActualRKF45
Actual direction of track at back plane using Runge-Kutta-Fehlberg.
Definition: QwTrack.h:138
double fPositionThetaoff
Difference in polar angle theta at matching plane.
Definition: QwTrack.h:112
double GetOptimizationVariable(const TVector3 &position, const TVector3 &direction) const
Optimization variable from position and direction.
Definition: QwRayTracer.h:110
double fMomentum
Spectrometer momentum.
Definition: QwTrack.h:100
double fMomentumStep
Newton&#39;s method step size in momentum.
Definition: QwRayTracer.h:125
int IntegrateRK(const TMatrixD &A, const TMatrixD &b, TVector3 &r, TVector3 &v, const double p, const double z, const double h, const double epsilon)
Runge-Kutta numerical integration by Butcher tableau.
Definition: QwRayTracer.cc:510
Double_t fBdlz
z component of the field integral
Definition: QwRayTracer.h:138
EQwDetectorPackage GetPackage() const
Get the package.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void QwRayTracer::DefineOptions ( QwOptions options)
static

Define command line and config file options.

Define command line and config file options

Parameters
optionsoptions object

Definition at line 93 of file QwRayTracer.cc.

References QwOptions::AddOptions(), and Qw::e.

Referenced by DefineOptionsTracking().

94 {
95  // Order of the Runge-Kutta method
96  options.AddOptions("Momentum reconstruction")("QwRayTracer.order",
97  po::value<int>(0)->default_value(5),
98  "Runge-Kutta method order (higher than 4 implies adaptive step)");
99  // Step size of Runge-Kutta method for fixed steps (order 4 or less)
100  options.AddOptions("Momentum reconstruction")("QwRayTracer.step",
101  po::value<float>(0)->default_value(1.0),
102  "Runge-Kutta fixed step size (for order 4 or less) [cm]");
103  // Minimum step size of Runge-Kutta method for adaptive step
104  options.AddOptions("Momentum reconstruction")("QwRayTracer.min_step",
105  po::value<float>(0)->default_value(0.1),
106  "Runge-Kutta minimum step size (for adaptive step) [cm]");
107  // Maximum step size of Runge-Kutta method for adaptive step
108  options.AddOptions("Momentum reconstruction")("QwRayTracer.max_step",
109  po::value<float>(0)->default_value(10.0),
110  "Runge-Kutta maximum step size (for adaptive step) [cm]");
111  // Maximum step size of Runge-Kutta method for adaptive step
112  options.AddOptions("Momentum reconstruction")("QwRayTracer.tolerance",
113  po::value<float>(0)->default_value(1e-10),
114  "Runge-Kutta adaptive step maximum allowable truncation error");
115  // Step size of Newton's method in momentum
116  options.AddOptions("Momentum reconstruction")("QwRayTracer.momentum_step",
117  po::value<float>(0)->default_value(30.0),
118  "Newton's method momentum step [MeV]");
119 
120  // Starting momentum of Newton's method
121  // Note: Start iteration from a higher momentum limit (1.250 GeV)
122  // as suggested by David Armstrong, to avoid possible bias
123  options.AddOptions("Momentum reconstruction")("QwRayTracer.initial_momemtum",
124  po::value<float>(0)->default_value(1.25),
125  "Newton's method position step [GeV]");
126 
127  // Starting position for magnetic field swimming
128  options.AddOptions("Momentum reconstruction")("QwRayTracer.start_position",
129  po::value<float>(0)->default_value(-250.0),
130  "Magnetic field swimming start position [cm]");
131  // Ending position for magnetic field swimming
132  options.AddOptions("Momentum reconstruction")("QwRayTracer.end_position",
133  po::value<float>(0)->default_value(+577.0),
134  "Magnetic field swimming end position [cm]");
135 
136  // Newton's method optimization variable
137  options.AddOptions("Momentum reconstruction")("QwRayTracer.optim_variable",
138  po::value<int>(0)->default_value(0),
139  "Newton's method optimization variable: 0 for position.Perp(), 1 for direction.Theta()");
140  // Newton's method optimization cut-off resolution
141  options.AddOptions("Momentum reconstruction")("QwRayTracer.optim_resolution",
142  po::value<float>(0)->default_value(0.3),
143  "Newton's method optimization cut-off resolution [cm for position, rad for angles]");
144 }
static const double e
Definition: QwUnits.h:91
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
Definition: QwOptions.h:164

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

double QwRayTracer::GetMagneticFieldCurrent ( ) const
inline

Get magnetic field current.

Definition at line 61 of file QwRayTracer.h.

References fBfield, and QwMagneticField::GetActualCurrent().

Referenced by QwTrackingWorker::GetMagneticFieldCurrent().

61  {
62  if (fBfield) return fBfield->GetActualCurrent();
63  else return 0.0;
64  }
static QwMagneticField * fBfield
Magnetic field (static)
Definition: QwRayTracer.h:96
double GetActualCurrent() const
Get the actual current.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

double QwRayTracer::GetOptimizationVariable ( const TVector3 &  position,
const TVector3 &  direction 
) const
inlineprivate

Optimization variable from position and direction.

Definition at line 110 of file QwRayTracer.h.

References fOptimizationVariable.

Referenced by Bridge().

110  {
111  switch (fOptimizationVariable) {
112  case 0: return position.Perp(); // perpendicular position at matching plane
113  case 1: return direction.Theta(); // polar angle of direction at matching plane
114  // since direction is normalized, sin(direction.Theta()) == direction.Perp()
115  default: return position.Perp(); // case 0 is default
116  }
117  }
int fOptimizationVariable
Newton&#39;s method optimization variable.
Definition: QwRayTracer.h:108

+ Here is the caller graph for this function:

int QwRayTracer::IntegrateRK ( const TMatrixD &  A,
const TMatrixD &  b,
TVector3 &  r,
TVector3 &  v,
const double  p,
const double  z,
const double  step,
const double  tolerance 
)

Runge-Kutta numerical integration by Butcher tableau.

Integrate using the Runge-Kutta algorithm

RK integration for trajectory and field integral. beta = qc/E = -0.2998 / E[GeV] [coul.(m/s)/j] = -0.2998 / E[MeV] [coul.(mm/s)/j]

The coupled differential equations are : dx/ds = vx dy/ds = vy dz/ds = vz dvx/ds = beta * (vy*bz - vz*by) dvy/ds = beta * (vz*bx - vx*bz) dvz/ds = beta * (vx*by - vy*bx) where ds is the displacement along the trajectory (= h, the integration step)

If the endpoint is at upstream and startpoint is at downstream, the electron will swim backward

Ref: https://en.wikipedia.org/wiki/Runge-Kutta_methods#Explicit_Runge.E2.80.93Kutta_methods

Parameters
ARunge-Kutta matrix
bWeight vector (first row is lowest order)
rInitial position (reference to final position)
vInitial momentum direction (reference to final direction)
pInitial momentum magnitude
zFinal position
stepStep size
epsilonAllowed truncation error per step
Returns
Number of iterations

Definition at line 510 of file QwRayTracer.cc.

References Qw::c, Qw::e, fBfield, fIntegrationMaximumStep, fIntegrationMinimumStep, QwMagneticField::GetCartesianFieldValue(), and MAX_ITERATIONS_RUNGEKUTTA.

Referenced by Bridge(), IntegrateRK(), and QwMatrixLookup::WriteTrajMatrix().

519 {
520  // Order
521  const int s = A.GetNrows();
522 
523  // Adaptive step if q > 1
524  const int q = b.GetNrows();
525  const double h_min = fIntegrationMinimumStep;
526  const double h_max = fIntegrationMaximumStep;
527  double h = step;
528 
529  // Determine c
530  TVectorD c(s);
531  for (int i = 0; i < s; i++)
532  for (int j = 0; j < s; j++)
533  c[i] += A[i][j];
534 
535  // Beta factor
536  const double beta = - Qw::c * Qw::e / p;
537 
538  // Initial conditions
539  TVector3 r_new[2], r_old[2];
540  TVector3 v_new[2], v_old[2];
541  r_old[0] = r_old[1] = r;
542  v_old[0] = v_old[1] = v;
543 
544  // Loop
545  int iterations = 0;
546  bool last_iteration = false;
547  while (! last_iteration && iterations < MAX_ITERATIONS_RUNGEKUTTA) {
548  iterations++;
549 
550  // Last step to end up at z
551  if (fabs(r_old[0].Z() - z) < h) {
552  TVector3 r_diff = (r_old[0].Z() - z) / v_old[0].Z() * v_old[0];
553  h = r_diff.Mag();
554  last_iteration = true;
555  }
556 
557  // Determine k
558  TVector3 k_r[s];
559  TVector3 k_v[s];
560  TVector3 point, B;
561  for (int i = 0; i < s; i++) {
562  r_new[0] = r_old[0];
563  v_new[0] = v_old[0];
564  for (int j = 0; j < i; j++) {
565  r_new[0] += A[i][j] * k_r[j];
566  v_new[0] += A[i][j] * k_v[j];
567  }
568  fBfield->GetCartesianFieldValue(r_new[0], B);
569 
570  k_r[i] = h * v_new[0];
571  k_v[i] = beta * k_r[i].Cross(B);
572  }
573 
574  // New values
575  for (int p = 0; p < q; p++) {
576  r_new[p] = r_old[p];
577  v_new[p] = v_old[p];
578  for (int i = 0; i < s; i++) {
579  r_new[p] += b[p][i] * k_r[i];
580  v_new[p] += b[p][i] * k_v[i];
581  }
582 
583  }
584 
585  // Adaptive step
586  // Ref: http://mathfaculty.fullerton.edu/mathews//n2003/rungekuttafehlberg/RungeKuttaFehlbergProof.pdf
587  // Ref: http://pauli.uni-muenster.de/tp/fileadmin/lehre/NumMethoden/SoSe10/Skript/RKM.pdf
588  if (q == 2) {
589  TVector3 r_diff = r_new[0] - r_new[1];
590  h *= pow(tolerance * h / (2 * r_diff.Mag()), 0.25);
591  if (h < h_min) h = h_min;
592  if (h > h_max) h = h_max;
593  }
594 
595  // Take lowest order, that's the one for which the error is minimized
596  r_old[0] = r_old[1] = r_new[0];
597  v_old[0] = v_old[1] = v_new[0];
598 
599  } // end of loop
600 
601  // Return arguments
602  r = r_new[0];
603  v = v_new[0];
604 
605  if (iterations == MAX_ITERATIONS_RUNGEKUTTA) return -1;
606  else return iterations;
607 }
static QwMagneticField * fBfield
Magnetic field (static)
Definition: QwRayTracer.h:96
static const double e
Definition: QwUnits.h:91
void GetCartesianFieldValue(const double point_xyz[3], double field_xyz[3]) const
Get the cartesian components of the field value.
double fIntegrationMaximumStep
Maximum step size.
Definition: QwRayTracer.h:104
#define MAX_ITERATIONS_RUNGEKUTTA
Definition: QwRayTracer.cc:37
double fIntegrationMinimumStep
Runge-Kutta minimum and maximum step size for adaptive step.
Definition: QwRayTracer.h:103
static const double c
Physical constants.
Definition: QwUnits.h:118

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int QwRayTracer::IntegrateRK ( TVector3 &  r,
TVector3 &  v,
const double  p,
const double  z,
const int  order,
const double  h 
)

Runge-Kutta numerical integration.

Definition at line 345 of file QwRayTracer.cc.

References fIntegrationTolerance, and IntegrateRK().

346 {
347  // Tolerance per step
348  const double tolerance = fIntegrationTolerance;
349 
350  if (order == 2) {
351  // Butcher tableau RK2
352  // Ref: https://en.wikipedia.org/wiki/Runge-Kutta_methods
353  const int s = 2;
354  const int q = 1;
355  const double alpha = 0.5; // 0.5, 1.0, 1.5
356  // Define A
357  TMatrixD A(s,s); A.Zero();
358  A[1][0] = alpha;
359  // Define b
360  TMatrixD b(q,s); b.Zero();
361  b[0][0] = 1.0 - 1.0 / (2.0 * alpha);
362  b[0][1] = 1.0 / (2.0 * alpha);
363 
364  return IntegrateRK(A, b, r, v, p, z, h, tolerance);
365  }
366 
367  if (order == 4) {
368  // Butcher tableau RK4
369  // Ref: https://en.wikipedia.org/wiki/Runge-Kutta_methods
370  const int s = 4;
371  const int q = 1;
372  // Define A
373  TMatrixD A(s,s); A.Zero();
374  A[1][0] = A[2][1] = 1.0 / 2.0;
375  A[3][2] = 1.0;
376  // Define b
377  TMatrixD b(q,s); b.Zero();
378  b[0][0] = b[0][3] = 1.0 / 6.0;
379  b[0][1] = b[0][2] = 1.0 / 3.0;
380 
381  return IntegrateRK(A, b, r, v, p, z, h, tolerance);
382  }
383 
384  if (order == 5) {
385  // Butcher tableau RKF4(5)
386  // Ref: https://en.wikipedia.org/wiki/Runge-Kutta-Fehlberg_method
387  const int s = 6;
388  const int q = 2;
389  // Define A
390  TMatrixD A(s,s); A.Zero();
391  A[1][0] = 1.0 / 4.0;
392  A[2][0] = 3.0 / 32.0; A[2][1] = 9.0 / 32.0;
393  A[3][0] = 1932.0 / 2197.0; A[3][1] = -7200.0 / 2197.0; A[3][2] = 7296.0 / 2197.0;
394  A[4][0] = 439.0 / 216.0; A[4][1] = -8.0; A[4][2] = 3680.0 / 513.0; A[4][3] = -845.0 / 4104.0;
395  A[5][0] = -8.0 / 27.0; A[5][1] = 2.0; A[5][2] = -3544.0 / 2565.0; A[5][3] = 1859.0 / 4104.0; A[5][4] = -11.0 / 40.0;
396  // Define b
397  TMatrixD b(q,s); b.Zero();
398  b[0][0] = 16.0 / 135.0;
399  b[0][2] = 6656.0 / 12825.0;
400  b[0][3] = 28561.0 / 56430.0;
401  b[0][4] = -9.0 / 50.0;
402  b[0][5] = 2.0 / 55.0;
403  b[1][0] = 25.0 / 216.0;
404  b[1][2] = 1408.0 / 2565.0;
405  b[1][3] = 2197.0 / 4104.0;
406  b[1][4] = -1.0 / 5.0;
407 
408  return IntegrateRK(A, b, r, v, p, z, h, tolerance);
409  }
410 
411  if (order == 6) {
412  // From J.C. Butcher Numerical Methods for Ordinary Differential Equations, 2nd edition, paragraph 335.
413  const int s = 7;
414  const int q = 2;
415  // Define A
416  TMatrixD A(s,s); A.Zero();
417  A[1][0] = 1.0 / 6.0;
418  A[2][0] = 4.0 / 75.0; A[2][1] = 16.0 / 75.0;
419  A[3][0] = 5.0 / 6.0; A[3][1] = -8.0 / 3.0; A[3][2] = 5.0 / 2.0;
420  A[4][0] = -8.0 / 5.0; A[4][1] = 144.0 / 25.0; A[4][2] = -4.0; A[4][3] = 16.0 / 25.0;
421  A[5][0] = 361.0 / 320.0; A[5][1] = -18.0 / 5.0; A[5][2] = 407.0 / 128.0; A[5][3] = -11.0 / 80.0; A[5][4] = 55.0 / 128.0;
422  A[6][0] = -11.0 / 640.0; A[6][1] = 0.0; A[6][2] = 11.0 / 256.0; A[6][3] = -11.0 / 160.0; A[6][4] = 11.0 / 256.0; A[6][5] = 0.0;
423  A[7][0] = 93.0 / 640.0; A[7][1] = -18.0 / 5.0; A[7][2] = 803.0 / 256.0; A[7][3] = -11.0 / 160.0; A[7][4] = 99.0 / 256.0; A[7][5] = 0.0; A[7][6] = 1.0;
424  // Define b
425  TMatrixD b(q,s); b.Zero();
426  b[0][0] = 31.0 / 384.0;
427  b[0][2] = 1125.0 / 2816.0;
428  b[0][3] = 9.0 / 32.0;
429  b[0][4] = 125.0 / 768.0;
430  b[0][5] = 5.0 / 66.0;
431  b[1][0] = 7.0 / 1408.0;
432  b[1][2] = 1125.0 / 2816.0;
433  b[1][3] = 9.0 / 32.0;
434  b[1][4] = 125.0 / 768.0;
435  b[1][6] = 5.0 / 66.0;
436  b[1][7] = 5.0 / 66.0;
437  }
438 
439  if (order == 11) {
440  // From J.C. Butcher Numerical Methods for Ordinary Differential Equations, 2nd edition, paragraph 335.
441  const int s = 12;
442  const int q = 2;
443  // Define A
444  TMatrixD A(s,s); A.Zero();
445  A[1][0] = 2.0 / 27.0;
446  A[2][0] = 1.0 / 36.0; A[2][1] = 1.0 / 12.0;
447  A[3][0] = 1.0 / 24.0; A[3][1] = 0.0; A[3][2] = 1.0 / 8.0;
448  A[4][0] = 5.0 / 12.0; A[4][1] = 0.0; A[4][2] = -25.0 / 16.0; A[4][3] = 25.0 / 16.0;
449  A[5][0] = 1.0 / 20.0; A[5][1] = 0.0; A[5][2] = 0.0; A[5][3] = 1.0 / 4.0; A[5][4] = 1.0 / 5.0;
450  A[6][0] = -25.0 / 108.0; A[6][1] = 0.0; A[6][2] = 0.0; A[6][3] = 125.0 / 108.0; A[6][4] = -65.0 / 27.0; A[6][5] = 125.0 / 54.0;
451  A[7][0] = 31.0 / 300.0; A[7][1] = 0.0; A[7][2] = 0.0; A[7][3] = 0.0; A[7][4] = 61.0 / 225.0; A[7][5] = -2.0 / 9.0; A[7][6] = 13.0 / 900.0;
452  A[8][0] = 2.0; A[8][1] = 0.0; A[8][2] = 0.0; A[8][3] = -53.0 / 6.0; A[8][4] = 704.0 / 45.0; A[8][5] = -107.0 / 9.0; A[8][6] = 67.0 / 90.0; A[8][7] = 3.0;
453  A[9][0] = -91.0 / 108.0; A[9][1] = 0.0; A[9][2] = 0.0; A[9][3] = 23.0 / 108.0; A[9][4] = -976.0 / 135.0; A[9][5] = 311.0 / 54.0; A[9][6] = -19.0 / 60.0; A[9][7] = 17.0 / 6.0; A[9][9] = -1.0 / 12.0;
454  A[10][0] = 2383.0 / 4100.0; A[10][1] = 0.0; A[10][2] = 0.0; A[10][3] = -341.0 / 164.0; A[10][4] = 4496.0 / 1025.0; A[10][5] = -301.0 / 82.0; A[10][6] = 2133.0 / 4100.0; A[10][7] = 45.0 / 82.0; A[10][8] = 45.0 / 164.0; A[10][9] = 18.0 / 41.0;
455  A[11][0] = 3.0 / 205.0; A[11][1] = 0.0; A[11][2] = 0.0; A[11][3] = 0.0; A[11][4] = 0.0; A[11][5] = -6.0 / 41.0; A[11][6] = -3.0 / 205.0; A[11][7] = -3.0 / 41.0; A[11][8] = 3.0 / 41.0; A[11][9] = 6.0 / 41.0; A[11][10] = 0.0;
456  A[12][0] = -1777.0 / 4100.0; A[12][1] = 0.0; A[12][2] = 0.0; A[12][3] = -341.0 / 164.0; A[12][4] = 4496.0 / 1025.0; A[12][5] = -289.0 / 82.0; A[12][6] = 2193.0 / 4100.0; A[12][7] = 51.0 / 82.0; A[12][8] = 33.0 / 164.0; A[12][9] = 12.0 / 41.0; A[12][10] = 0.0; A[12][11] = 1.0;
457  // Define b
458  TMatrixD b(q,s); b.Zero();
459  b[0][0] = 41.0 / 840.0;
460  b[0][5] = 34.0 / 105.0;
461  b[0][6] = 9.0 / 35.0;
462  b[0][7] = 9.0 / 35.0;
463  b[0][8] = 9.0 / 280.0;
464  b[0][9] = 9.0 / 280.0;
465  b[0][10] = 41.0 / 840.0;
466  b[1][5] = 34.0 / 105.0;
467  b[1][6] = 9.0 / 35.0;
468  b[1][7] = 9.0 / 35.0;
469  b[1][8] = 9.0 / 280.0;
470  b[1][9] = 9.0 / 280.0;
471  b[1][11] = 41.0 / 840.0;
472  b[1][12] = 41.0 / 840.0;
473  }
474 
475  // Return zero iterations if no matching Runge-Kutta algorithm
476  return 0;
477 }
double fIntegrationTolerance
Allowable truncation error in adaptive step.
Definition: QwRayTracer.h:105
int IntegrateRK(const TMatrixD &A, const TMatrixD &b, TVector3 &r, TVector3 &v, const double p, const double z, const double h, const double epsilon)
Runge-Kutta numerical integration by Butcher tableau.
Definition: QwRayTracer.cc:510

+ Here is the call graph for this function:

bool QwRayTracer::LoadMagneticFieldMap ( QwOptions options)

Load the magnetic field based on config file options.

Load the magnetic field map

Parameters
optionsOptions object
Returns
True if the field map was successfully loaded

Definition at line 77 of file QwRayTracer.cc.

References fBfield, and QwMagneticField::TestFieldMap().

Referenced by QwRayTracer().

78 {
79  // If the field has already been loaded, return successfully
80  if (fBfield) return true;
81 
82  // Otherwise reload the field map
83  fBfield = new QwMagneticField(options);
84 
85  // Test magnetic field validity
86  return fBfield->TestFieldMap();
87 }
static QwMagneticField * fBfield
Magnetic field (static)
Definition: QwRayTracer.h:96
Magnetic field map object.
bool TestFieldMap()
Test the field map.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void QwRayTracer::ProcessOptions ( QwOptions options)

Process command line and config file options.

Process command line and config file options

Parameters
optionsoptions object

Definition at line 150 of file QwRayTracer.cc.

References Qw::cm, fEndPosition, fInitialMomentum, fIntegrationMaximumStep, fIntegrationMinimumStep, fIntegrationOrder, fIntegrationStep, fIntegrationTolerance, fMomentumStep, fOptimizationResolution, fOptimizationVariable, fStartPosition, QwOptions::GetValue(), Qw::GeV, Qw::MeV, and Qw::rad.

Referenced by QwRayTracer().

151 {
152  fIntegrationOrder = options.GetValue<int>("QwRayTracer.order");
153  fIntegrationStep = Qw::cm * options.GetValue<float>("QwRayTracer.step");
154  fIntegrationMinimumStep = Qw::cm * options.GetValue<float>("QwRayTracer.min_step");
155  fIntegrationMaximumStep = Qw::cm * options.GetValue<float>("QwRayTracer.max_step");
156  fIntegrationTolerance = options.GetValue<float>("QwRayTracer.tolerance");
157 
158  fMomentumStep = Qw::MeV * options.GetValue<float>("QwRayTracer.momentum_step");
159  fInitialMomentum = Qw::GeV * options.GetValue<float>("QwRayTracer.initial_momemtum");
160  fStartPosition = Qw::cm * options.GetValue<float>("QwRayTracer.start_position");
161  fEndPosition = Qw::cm * options.GetValue<float>("QwRayTracer.end_position");
162 
163  fOptimizationVariable = options.GetValue<int>("QwRayTracer.optim_variable");
164  fOptimizationResolution = options.GetValue<float>("QwRayTracer.optim_resolution");
165  switch (fOptimizationVariable) {
166  case 0: fOptimizationResolution *= Qw::cm; // position.Perp()
167  case 1: fOptimizationResolution *= Qw::rad; // direction.Theta()
168  default: fOptimizationResolution *= Qw::cm; // position.Perp()
169  }
170 }
double fOptimizationResolution
Definition: QwRayTracer.h:122
double fStartPosition
Starting position for magnetic field swimming.
Definition: QwRayTracer.h:131
double fIntegrationStep
Runge-Kutta fixed step size for order 4 or less.
Definition: QwRayTracer.h:101
int fOptimizationVariable
Newton&#39;s method optimization variable.
Definition: QwRayTracer.h:108
static const double rad
Definition: QwUnits.h:105
T GetValue(const std::string &key)
Get a templated value.
Definition: QwOptions.h:240
double fIntegrationMaximumStep
Maximum step size.
Definition: QwRayTracer.h:104
double fInitialMomentum
Newton&#39;s method initial momentum.
Definition: QwRayTracer.h:128
static const double GeV
Definition: QwUnits.h:95
int fIntegrationOrder
Runge-Kutta method order.
Definition: QwRayTracer.h:99
double fEndPosition
Ending position for magnetic field swimming.
Definition: QwRayTracer.h:133
double fIntegrationMinimumStep
Runge-Kutta minimum and maximum step size for adaptive step.
Definition: QwRayTracer.h:103
static const double MeV
Definition: QwUnits.h:94
double fIntegrationTolerance
Allowable truncation error in adaptive step.
Definition: QwRayTracer.h:105
double fMomentumStep
Newton&#39;s method step size in momentum.
Definition: QwRayTracer.h:125
static const double cm
Length units: base unit is mm.
Definition: QwUnits.h:61

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void QwRayTracer::SetMagneticFieldCurrent ( const double  current)
inline

Set magnetic field current.

Definition at line 66 of file QwRayTracer.h.

References fBfield, and QwMagneticField::SetActualCurrent().

Referenced by QwTrackingWorker::SetMagneticFieldCurrent().

66  {
67  if (fBfield) fBfield->SetActualCurrent(current);
68  }
static QwMagneticField * fBfield
Magnetic field (static)
Definition: QwRayTracer.h:96
void SetActualCurrent(const double current)
Set the actual current.

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Field Documentation

Double_t QwRayTracer::fBdl
private

scalar field integrals

Definition at line 135 of file QwRayTracer.h.

Referenced by Bridge(), and QwRayTracer().

Double_t QwRayTracer::fBdlx
private

x component of the field integral

Definition at line 136 of file QwRayTracer.h.

Referenced by Bridge(), and QwRayTracer().

Double_t QwRayTracer::fBdly
private

y component of the field integral

Definition at line 137 of file QwRayTracer.h.

Referenced by Bridge(), and QwRayTracer().

Double_t QwRayTracer::fBdlz
private

z component of the field integral

Definition at line 138 of file QwRayTracer.h.

Referenced by Bridge(), and QwRayTracer().

QwMagneticField * QwRayTracer::fBfield = 0
staticprivate

Magnetic field (static)

Definition at line 96 of file QwRayTracer.h.

Referenced by GetMagneticFieldCurrent(), IntegrateRK(), LoadMagneticFieldMap(), SetMagneticFieldCurrent(), and ~QwRayTracer().

double QwRayTracer::fEndPosition
private

Ending position for magnetic field swimming.

Definition at line 133 of file QwRayTracer.h.

Referenced by Bridge(), and ProcessOptions().

double QwRayTracer::fInitialMomentum
private

Newton's method initial momentum.

Definition at line 128 of file QwRayTracer.h.

Referenced by Bridge(), and ProcessOptions().

double QwRayTracer::fIntegrationMaximumStep
private

Maximum step size.

Definition at line 104 of file QwRayTracer.h.

Referenced by IntegrateRK(), and ProcessOptions().

double QwRayTracer::fIntegrationMinimumStep
private

Runge-Kutta minimum and maximum step size for adaptive step.

Minimum step size

Definition at line 103 of file QwRayTracer.h.

Referenced by IntegrateRK(), and ProcessOptions().

int QwRayTracer::fIntegrationOrder
private

Runge-Kutta method order.

Definition at line 99 of file QwRayTracer.h.

Referenced by Bridge(), and ProcessOptions().

double QwRayTracer::fIntegrationStep
private

Runge-Kutta fixed step size for order 4 or less.

Definition at line 101 of file QwRayTracer.h.

Referenced by Bridge(), and ProcessOptions().

double QwRayTracer::fIntegrationTolerance
private

Allowable truncation error in adaptive step.

Definition at line 105 of file QwRayTracer.h.

Referenced by IntegrateRK(), and ProcessOptions().

double QwRayTracer::fMomentumStep
private

Newton's method step size in momentum.

Definition at line 125 of file QwRayTracer.h.

Referenced by Bridge(), and ProcessOptions().

double QwRayTracer::fOptimizationResolution
private

Newton's method optimization resolution: continue optimization until the difference between optimization variable after swimming and optimization variable of target partial track in back chamber is below this value

Definition at line 122 of file QwRayTracer.h.

Referenced by Bridge(), and ProcessOptions().

int QwRayTracer::fOptimizationVariable
private

Newton's method optimization variable.

Definition at line 108 of file QwRayTracer.h.

Referenced by GetOptimizationVariable(), and ProcessOptions().

double QwRayTracer::fStartPosition
private

Starting position for magnetic field swimming.

Definition at line 131 of file QwRayTracer.h.

Referenced by Bridge(), and ProcessOptions().


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