Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GenericDefaultExtension.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GenericDefaultExtension.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018-2019 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
13 
14 #include <array>
15 
16 namespace Acts {
17 namespace detail {
18 
22 template <typename scalar_t>
24  using Scalar = scalar_t;
26  using ThisVector3 = Eigen::Matrix<Scalar, 3, 1>;
27 
35  template <typename propagator_state_t, typename stepper_t,
36  typename navigator_t>
37  int bid(const propagator_state_t& /*state*/, const stepper_t& /*stepper*/,
38  const navigator_t& /*navigator*/) const {
39  return 1;
40  }
41 
59  template <typename propagator_state_t, typename stepper_t,
60  typename navigator_t>
61  bool k(const propagator_state_t& state, const stepper_t& stepper,
62  const navigator_t& /*navigator*/, ThisVector3& knew,
63  const Vector3& bField, std::array<Scalar, 4>& kQoP, const int i = 0,
64  const double h = 0., const ThisVector3& kprev = ThisVector3::Zero()) {
65  auto qop = stepper.qOverP(state.stepping);
66  // First step does not rely on previous data
67  if (i == 0) {
68  knew = qop * stepper.direction(state.stepping).cross(bField);
69  kQoP = {0., 0., 0., 0.};
70  } else {
71  knew =
72  qop * (stepper.direction(state.stepping) + h * kprev).cross(bField);
73  }
74  return true;
75  }
76 
90  template <typename propagator_state_t, typename stepper_t,
91  typename navigator_t>
92  bool finalize(propagator_state_t& state, const stepper_t& stepper,
93  const navigator_t& navigator, const double h) const {
94  propagateTime(state, stepper, navigator, h);
95  return true;
96  }
97 
112  template <typename propagator_state_t, typename stepper_t,
113  typename navigator_t>
114  bool finalize(propagator_state_t& state, const stepper_t& stepper,
115  const navigator_t& navigator, const double h,
116  FreeMatrix& D) const {
117  propagateTime(state, stepper, navigator, h);
118  return transportMatrix(state, stepper, navigator, h, D);
119  }
120 
121  private:
131  template <typename propagator_state_t, typename stepper_t,
132  typename navigator_t>
133  void propagateTime(propagator_state_t& state, const stepper_t& stepper,
134  const navigator_t& /*navigator*/, const double h) const {
135  // using because of autodiff
136  using std::hypot;
137 
141  auto m = stepper.particleHypothesis(state.stepping).mass();
142  auto p = stepper.absoluteMomentum(state.stepping);
143  auto dtds = hypot(1, m / p);
144  state.stepping.pars[eFreeTime] += h * dtds;
145  if (state.stepping.covTransport) {
146  state.stepping.derivative(3) = dtds;
147  }
148  }
149 
162  template <typename propagator_state_t, typename stepper_t,
163  typename navigator_t>
164  bool transportMatrix(propagator_state_t& state, const stepper_t& stepper,
165  const navigator_t& /*navigator*/, const double h,
166  FreeMatrix& D) const {
185 
186  // using because of autodiff
187  using std::hypot;
188 
189  auto m = state.stepping.particleHypothesis.mass();
190  auto& sd = state.stepping.stepData;
191  auto dir = stepper.direction(state.stepping);
192  auto qop = stepper.qOverP(state.stepping);
193  auto p = stepper.absoluteMomentum(state.stepping);
194  auto dtds = hypot(1, m / p);
195 
196  D = FreeMatrix::Identity();
197 
198  double half_h = h * 0.5;
199  // This sets the reference to the sub matrices
200  // dFdx is already initialised as (3x3) idendity
201  auto dFdT = D.block<3, 3>(0, 4);
202  auto dFdL = D.block<3, 1>(0, 7);
203  // dGdx is already initialised as (3x3) zero
204  auto dGdT = D.block<3, 3>(4, 4);
205  auto dGdL = D.block<3, 1>(4, 7);
206 
211 
212  Vector3 dk1dL = Vector3::Zero();
213  Vector3 dk2dL = Vector3::Zero();
214  Vector3 dk3dL = Vector3::Zero();
215  Vector3 dk4dL = Vector3::Zero();
216 
217  // For the case without energy loss
218  dk1dL = dir.cross(sd.B_first);
219  dk2dL = (dir + half_h * sd.k1).cross(sd.B_middle) +
220  qop * half_h * dk1dL.cross(sd.B_middle);
221  dk3dL = (dir + half_h * sd.k2).cross(sd.B_middle) +
222  qop * half_h * dk2dL.cross(sd.B_middle);
223  dk4dL =
224  (dir + h * sd.k3).cross(sd.B_last) + qop * h * dk3dL.cross(sd.B_last);
225 
226  dk1dT(0, 1) = sd.B_first.z();
227  dk1dT(0, 2) = -sd.B_first.y();
228  dk1dT(1, 0) = -sd.B_first.z();
229  dk1dT(1, 2) = sd.B_first.x();
230  dk1dT(2, 0) = sd.B_first.y();
231  dk1dT(2, 1) = -sd.B_first.x();
232  dk1dT *= qop;
233 
234  dk2dT += half_h * dk1dT;
235  dk2dT = qop * VectorHelpers::cross(dk2dT, sd.B_middle);
236 
237  dk3dT += half_h * dk2dT;
238  dk3dT = qop * VectorHelpers::cross(dk3dT, sd.B_middle);
239 
240  dk4dT += h * dk3dT;
241  dk4dT = qop * VectorHelpers::cross(dk4dT, sd.B_last);
242 
243  dFdT.setIdentity();
244  dFdT += h / 6. * (dk1dT + dk2dT + dk3dT);
245  dFdT *= h;
246 
247  dFdL = (h * h) / 6. * (dk1dL + dk2dL + dk3dL);
248 
249  dGdT += h / 6. * (dk1dT + 2. * (dk2dT + dk3dT) + dk4dT);
250 
251  dGdL = h / 6. * (dk1dL + 2. * (dk2dL + dk3dL) + dk4dL);
252 
253  D(3, 7) = h * m * m * qop / dtds;
254  return true;
255  }
256 };
257 
258 } // namespace detail
259 } // namespace Acts