![]() |
|
|||
File indexing completed on 2025-08-06 08:10:06
0001 // This file is part of the Acts project. 0002 // 0003 // Copyright (C) 2018-2023 CERN for the benefit of the Acts project 0004 // 0005 // This Source Code Form is subject to the terms of the Mozilla Public 0006 // License, v. 2.0. If a copy of the MPL was not distributed with this 0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/. 0008 0009 #pragma once 0010 0011 #include "Acts/Definitions/Algebra.hpp" 0012 #include "Acts/Definitions/TrackParametrization.hpp" 0013 #include "Acts/Utilities/VectorHelpers.hpp" 0014 0015 #include <array> 0016 0017 namespace Acts { 0018 0019 /// @brief Default evaluater of the k_i's and elements of the transport matrix 0020 /// D of the RKN4 stepping. This is a pure implementation by textbook. 0021 struct DefaultExtension { 0022 using Scalar = ActsScalar; 0023 /// @brief Vector3 replacement for the custom scalar type 0024 using ThisVector3 = Eigen::Matrix<Scalar, 3, 1>; 0025 0026 /// @brief Control function if the step evaluation would be valid 0027 /// 0028 /// @tparam propagator_state_t Type of the state of the propagator 0029 /// @tparam stepper_t Type of the stepper 0030 /// @tparam navigator_t Type of the navigator 0031 /// 0032 /// @return Boolean flag if the step would be valid 0033 template <typename propagator_state_t, typename stepper_t, 0034 typename navigator_t> 0035 int bid(const propagator_state_t& /*state*/, const stepper_t& /*stepper*/, 0036 const navigator_t& /*navigator*/) const { 0037 return 1; 0038 } 0039 0040 /// @brief Evaluater of the k_i's of the RKN4. For the case of i = 0 this 0041 /// step sets up qop, too. 0042 /// 0043 /// @tparam propagator_state_t Type of the state of the propagator 0044 /// @tparam stepper_t Type of the stepper 0045 /// @tparam navigator_t Type of the navigator 0046 /// 0047 /// @param [in] state State of the propagator 0048 /// @param [in] stepper Stepper of the propagation 0049 /// @param [out] knew Next k_i that is evaluated 0050 /// @param [in] bField B-Field at the evaluation position 0051 /// @param [out] kQoP k_i elements of the momenta 0052 /// @param [in] i Index of the k_i, i = [0, 3] 0053 /// @param [in] h Step size (= 0. ^ 0.5 * StepSize ^ StepSize) 0054 /// @param [in] kprev Evaluated k_{i - 1} 0055 /// 0056 /// @return Boolean flag if the calculation is valid 0057 template <typename propagator_state_t, typename stepper_t, 0058 typename navigator_t> 0059 bool k(const propagator_state_t& state, const stepper_t& stepper, 0060 const navigator_t& /*navigator*/, ThisVector3& knew, 0061 const Vector3& bField, std::array<Scalar, 4>& kQoP, const int i = 0, 0062 const double h = 0., const ThisVector3& kprev = ThisVector3::Zero()) { 0063 auto qop = stepper.qOverP(state.stepping); 0064 // First step does not rely on previous data 0065 if (i == 0) { 0066 knew = qop * stepper.direction(state.stepping).cross(bField); 0067 kQoP = {0., 0., 0., 0.}; 0068 } else { 0069 knew = 0070 qop * (stepper.direction(state.stepping) + h * kprev).cross(bField); 0071 } 0072 return true; 0073 } 0074 0075 /// @brief Veto function after a RKN4 step was accepted by judging on the 0076 /// error of the step. Since the textbook does not deliver further vetos, 0077 /// this is a dummy function. 0078 /// 0079 /// @tparam propagator_state_t Type of the state of the propagator 0080 /// @tparam stepper_t Type of the stepper 0081 /// @tparam navigator_t Type of the navigator 0082 /// 0083 /// @param [in] state State of the propagator 0084 /// @param [in] stepper Stepper of the propagation 0085 /// @param [in] h Step size 0086 /// 0087 /// @return Boolean flag if the calculation is valid 0088 template <typename propagator_state_t, typename stepper_t, 0089 typename navigator_t> 0090 bool finalize(propagator_state_t& state, const stepper_t& stepper, 0091 const navigator_t& /*navigator*/, const double h) const { 0092 propagateTime(state, stepper, h); 0093 return true; 0094 } 0095 0096 /// @brief Veto function after a RKN4 step was accepted by judging on the 0097 /// error of the step. Since the textbook does not deliver further vetos, 0098 /// this is just for the evaluation of the transport matrix. 0099 /// 0100 /// @tparam propagator_state_t Type of the state of the propagator 0101 /// @tparam stepper_t Type of the stepper 0102 /// @tparam navigator_t Type of the navigator 0103 /// 0104 /// @param [in] state State of the propagator 0105 /// @param [in] stepper Stepper of the propagation 0106 /// @param [in] h Step size 0107 /// @param [out] D Transport matrix 0108 /// 0109 /// @return Boolean flag if the calculation is valid 0110 template <typename propagator_state_t, typename stepper_t, 0111 typename navigator_t> 0112 bool finalize(propagator_state_t& state, const stepper_t& stepper, 0113 const navigator_t& /*navigator*/, const double h, 0114 FreeMatrix& D) const { 0115 propagateTime(state, stepper, h); 0116 return transportMatrix(state, stepper, h, D); 0117 } 0118 0119 private: 0120 /// @brief Propagation function for the time coordinate 0121 /// 0122 /// @tparam propagator_state_t Type of the state of the propagator 0123 /// @tparam stepper_t Type of the stepper 0124 /// 0125 /// @param [in, out] state State of the propagator 0126 /// @param [in] stepper Stepper of the propagation 0127 /// @param [in] h Step size 0128 template <typename propagator_state_t, typename stepper_t> 0129 void propagateTime(propagator_state_t& state, const stepper_t& stepper, 0130 const double h) const { 0131 /// This evaluation is based on dt/ds = 1/v = 1/(beta * c) with the velocity 0132 /// v, the speed of light c and beta = v/c. This can be re-written as dt/ds 0133 /// = sqrt(m^2/p^2 + c^{-2}) with the mass m and the momentum p. 0134 auto m = stepper.particleHypothesis(state.stepping).mass(); 0135 auto p = stepper.absoluteMomentum(state.stepping); 0136 auto dtds = std::sqrt(1 + m * m / (p * p)); 0137 state.stepping.pars[eFreeTime] += h * dtds; 0138 if (state.stepping.covTransport) { 0139 state.stepping.derivative(3) = dtds; 0140 } 0141 } 0142 0143 /// @brief Calculates the transport matrix D for the jacobian 0144 /// 0145 /// @tparam propagator_state_t Type of the state of the propagator 0146 /// @tparam stepper_t Type of the stepper 0147 /// 0148 /// @param [in] state State of the propagator 0149 /// @param [in] stepper Stepper of the propagation 0150 /// @param [in] h Step size 0151 /// @param [out] D Transport matrix 0152 /// 0153 /// @return Boolean flag if evaluation is valid 0154 template <typename propagator_state_t, typename stepper_t> 0155 bool transportMatrix(propagator_state_t& state, const stepper_t& stepper, 0156 const double h, FreeMatrix& D) const { 0157 /// The calculations are based on ATL-SOFT-PUB-2009-002. The update of the 0158 /// Jacobian matrix is requires only the calculation of eq. 17 and 18. 0159 /// Since the terms of eq. 18 are currently 0, this matrix is not needed 0160 /// in the calculation. The matrix A from eq. 17 consists out of 3 0161 /// different parts. The first one is given by the upper left 3x3 matrix 0162 /// that are calculated by the derivatives dF/dT (called dFdT) and dG/dT 0163 /// (calls dGdT). The second is given by the top 3 lines of the rightmost 0164 /// column. This is calculated by dFdL and dGdL. The remaining non-zero term 0165 /// is calculated directly. The naming of the variables is explained in eq. 0166 /// 11 and are directly related to the initial problem in eq. 7. 0167 /// The evaluation is based by propagating the parameters T and lambda as 0168 /// given in eq. 16 and evaluating the derivations for matrix A. 0169 /// @note The translation for u_{n+1} in eq. 7 is in this case a 0170 /// 3-dimensional vector without a dependency of Lambda or lambda neither in 0171 /// u_n nor in u_n'. The second and fourth eq. in eq. 14 have the constant 0172 /// offset matrices h * Id and Id respectively. This involves that the 0173 /// constant offset does not exist for rectangular matrix dGdu' (due to the 0174 /// missing Lambda part) and only exists for dFdu' in dlambda/dlambda. 0175 0176 auto m = state.stepping.particleHypothesis.mass(); 0177 auto& sd = state.stepping.stepData; 0178 auto dir = stepper.direction(state.stepping); 0179 auto qop = stepper.qOverP(state.stepping); 0180 auto p = stepper.absoluteMomentum(state.stepping); 0181 auto dtds = std::sqrt(1 + m * m / (p * p)); 0182 0183 D = FreeMatrix::Identity(); 0184 0185 double half_h = h * 0.5; 0186 // This sets the reference to the sub matrices 0187 // dFdx is already initialised as (3x3) idendity 0188 auto dFdT = D.block<3, 3>(0, 4); 0189 auto dFdL = D.block<3, 1>(0, 7); 0190 // dGdx is already initialised as (3x3) zero 0191 auto dGdT = D.block<3, 3>(4, 4); 0192 auto dGdL = D.block<3, 1>(4, 7); 0193 0194 ActsMatrix<3, 3> dk1dT = ActsMatrix<3, 3>::Zero(); 0195 ActsMatrix<3, 3> dk2dT = ActsMatrix<3, 3>::Identity(); 0196 ActsMatrix<3, 3> dk3dT = ActsMatrix<3, 3>::Identity(); 0197 ActsMatrix<3, 3> dk4dT = ActsMatrix<3, 3>::Identity(); 0198 0199 Vector3 dk1dL = Vector3::Zero(); 0200 Vector3 dk2dL = Vector3::Zero(); 0201 Vector3 dk3dL = Vector3::Zero(); 0202 Vector3 dk4dL = Vector3::Zero(); 0203 0204 // For the case without energy loss 0205 dk1dL = dir.cross(sd.B_first); 0206 dk2dL = (dir + half_h * sd.k1).cross(sd.B_middle) + 0207 qop * half_h * dk1dL.cross(sd.B_middle); 0208 dk3dL = (dir + half_h * sd.k2).cross(sd.B_middle) + 0209 qop * half_h * dk2dL.cross(sd.B_middle); 0210 dk4dL = 0211 (dir + h * sd.k3).cross(sd.B_last) + qop * h * dk3dL.cross(sd.B_last); 0212 0213 dk1dT(0, 1) = sd.B_first.z(); 0214 dk1dT(0, 2) = -sd.B_first.y(); 0215 dk1dT(1, 0) = -sd.B_first.z(); 0216 dk1dT(1, 2) = sd.B_first.x(); 0217 dk1dT(2, 0) = sd.B_first.y(); 0218 dk1dT(2, 1) = -sd.B_first.x(); 0219 dk1dT *= qop; 0220 0221 dk2dT += half_h * dk1dT; 0222 dk2dT = qop * VectorHelpers::cross(dk2dT, sd.B_middle); 0223 0224 dk3dT += half_h * dk2dT; 0225 dk3dT = qop * VectorHelpers::cross(dk3dT, sd.B_middle); 0226 0227 dk4dT += h * dk3dT; 0228 dk4dT = qop * VectorHelpers::cross(dk4dT, sd.B_last); 0229 0230 dFdT.setIdentity(); 0231 dFdT += h / 6. * (dk1dT + dk2dT + dk3dT); 0232 dFdT *= h; 0233 0234 dFdL = (h * h) / 6. * (dk1dL + dk2dL + dk3dL); 0235 0236 dGdT += h / 6. * (dk1dT + 2. * (dk2dT + dk3dT) + dk4dT); 0237 0238 dGdL = h / 6. * (dk1dL + 2. * (dk2dL + dk3dL) + dk4dL); 0239 0240 D(3, 7) = h * m * m * qop / dtds; 0241 return true; 0242 } 0243 }; 0244 0245 } // namespace Acts
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |