Back to home page

sPhenix code displayed by LXR

 
 

    


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