Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-27 08:11:01

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 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 https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Propagator/detail/SympyCovarianceEngine.hpp"
0010 
0011 #include "Acts/Definitions/TrackParametrization.hpp"
0012 #include "Acts/Propagator/detail/JacobianEngine.hpp"
0013 #include "Acts/Propagator/detail/SympyJacobianEngine.hpp"
0014 
0015 #include "codegen/sympy_cov_math.hpp"
0016 
0017 namespace Acts::detail {
0018 
0019 namespace {
0020 
0021 /// Transport a bound covariance, taking the cheaper vacuum kernel where it
0022 /// applies. d(q/p)/d(q/p) is left untouched by a vacuum step, so it is exactly
0023 /// one there and the test is structural rather than numerical.
0024 ///
0025 /// @param jacobian the full bound-to-bound transport jacobian
0026 /// @param in the covariance to transport
0027 /// @param [out] out the transported covariance
0028 void applyBoundCovarianceTransport(const BoundMatrix& jacobian,
0029                                    const BoundMatrix& in, BoundMatrix& out) {
0030   const auto j = std::span<const double, 36>(jacobian.data(), 36);
0031   const auto c = std::span<const double, 36>(in.data(), 36);
0032   const auto o = std::span<double, 36>(out.data(), 36);
0033   if (jacobian(eBoundQOverP, eBoundQOverP) == 1) {
0034     transportCovarianceToBoundVacuumImpl(c, j, o);
0035   } else {
0036     transportCovarianceToBoundDenseImpl(c, j, o);
0037   }
0038 }
0039 
0040 }  // namespace
0041 
0042 /// Some type defs
0043 using Jacobian = BoundMatrix;
0044 using BoundState = std::tuple<BoundTrackParameters, Jacobian, double>;
0045 
0046 Result<BoundState> sympy::boundState(
0047     const GeometryContext& geoContext, const Surface& surface,
0048     BoundMatrix& boundCovariance, BoundMatrix& fullTransportJacobian,
0049     FreeVector& freeToPathDerivatives, BoundToFreeMatrix& boundToFreeJacobian,
0050     const std::optional<FreeMatrix>& additionalFreeCovariance,
0051     FreeVector& freeParameters, const ParticleHypothesis& particleHypothesis,
0052     bool covTransport, double accumulatedPath,
0053     const FreeToBoundCorrection& freeToBoundCorrection) {
0054   // Create the bound parameters
0055   Result<BoundVector> bv =
0056       transformFreeToBoundParameters(freeParameters, surface, geoContext);
0057   if (!bv.ok()) {
0058     return bv.error();
0059   }
0060 
0061   // Covariance transport
0062   std::optional<BoundMatrix> cov = std::nullopt;
0063   if (covTransport) {
0064     // Calculate the jacobian and transport the covarianceMatrix to final local.
0065     // Then reinitialize the transportJacobian, derivatives and the
0066     // boundToFreeJacobian
0067     Result<void> transportRes = transportCovarianceToBound(
0068         geoContext, surface, boundCovariance, fullTransportJacobian,
0069         freeToPathDerivatives, boundToFreeJacobian, additionalFreeCovariance,
0070         freeParameters, freeToBoundCorrection);
0071     if (!transportRes.ok()) {
0072       return transportRes.error();
0073     }
0074     cov = boundCovariance;
0075   }
0076 
0077   // Create the bound state
0078   return std::make_tuple(
0079       BoundTrackParameters(surface.getSharedPtr(), *bv, std::move(cov),
0080                            particleHypothesis),
0081       fullTransportJacobian, accumulatedPath);
0082 }
0083 
0084 BoundState sympy::curvilinearState(
0085     BoundMatrix& boundCovariance, BoundMatrix& fullTransportJacobian,
0086     FreeVector& freeToPathDerivatives, BoundToFreeMatrix& boundToFreeJacobian,
0087     const std::optional<FreeMatrix>& additionalFreeCovariance,
0088     const FreeVector& freeParameters,
0089     const ParticleHypothesis& particleHypothesis, bool covTransport,
0090     double accumulatedPath) {
0091   const Vector3& direction = freeParameters.segment<3>(eFreeDir0);
0092 
0093   // Covariance transport
0094   std::optional<BoundMatrix> cov = std::nullopt;
0095   if (covTransport) {
0096     // Calculate the jacobian and transport the covarianceMatrix to final local.
0097     // Then reinitialize the transportJacobian, derivatives and the
0098     // boundToFreeJacobian
0099     transportCovarianceToCurvilinear(boundCovariance, fullTransportJacobian,
0100                                      freeToPathDerivatives, boundToFreeJacobian,
0101                                      additionalFreeCovariance, direction);
0102     cov = boundCovariance;
0103   }
0104 
0105   // Create the curvilinear parameters
0106   Vector4 pos4 = Vector4::Zero();
0107   pos4[ePos0] = freeParameters[eFreePos0];
0108   pos4[ePos1] = freeParameters[eFreePos1];
0109   pos4[ePos2] = freeParameters[eFreePos2];
0110   pos4[eTime] = freeParameters[eFreeTime];
0111   BoundTrackParameters curvilinearParams =
0112       BoundTrackParameters::createCurvilinear(
0113           pos4, direction, freeParameters[eFreeQOverP], std::move(cov),
0114           particleHypothesis);
0115   // Create the curvilinear state
0116   return {std::move(curvilinearParams), fullTransportJacobian, accumulatedPath};
0117 }
0118 
0119 Result<void> sympy::transportCovarianceToBound(
0120     const GeometryContext& geoContext, const Surface& surface,
0121     BoundMatrix& boundCovariance, BoundMatrix& fullTransportJacobian,
0122     FreeVector& freeToPathDerivatives, BoundToFreeMatrix& boundToFreeJacobian,
0123     const std::optional<FreeMatrix>& additionalFreeCovariance,
0124     FreeVector& freeParameters,
0125     const FreeToBoundCorrection& freeToBoundCorrection) {
0126   FreeToBoundMatrix freeToBoundJacobian;
0127 
0128   // Calculate the full jacobian from local parameters at the start surface to
0129   // current bound parameters
0130   sympy::boundToBoundTransportJacobian(
0131       geoContext, surface, freeParameters, boundToFreeJacobian,
0132       freeToBoundJacobian, freeToPathDerivatives, fullTransportJacobian);
0133 
0134   bool correction = false;
0135   if (freeToBoundCorrection) {
0136     FreeMatrix freeCovariance =
0137         boundToFreeJacobian * boundCovariance * boundToFreeJacobian.transpose();
0138 
0139     auto transformer =
0140         detail::CorrectedFreeToBoundTransformer(freeToBoundCorrection);
0141     auto correctedRes =
0142         transformer(freeParameters, freeCovariance, surface, geoContext);
0143 
0144     if (correctedRes.has_value()) {
0145       auto correctedValue = correctedRes.value();
0146       BoundVector boundParams = std::get<BoundVector>(correctedValue);
0147       // 1. Update the free parameters with the corrected bound parameters
0148       freeParameters =
0149           transformBoundToFreeParameters(surface, geoContext, boundParams);
0150 
0151       // 2. Update the bound covariance
0152       boundCovariance = std::get<BoundMatrix>(correctedValue);
0153 
0154       correction = true;
0155     }
0156   }
0157 
0158   if (!correction) {
0159     // Apply the actual covariance transport to get covariance of the current
0160     // bound parameters
0161     BoundMatrix newBoundCovariance;
0162     applyBoundCovarianceTransport(fullTransportJacobian, boundCovariance,
0163                                   newBoundCovariance);
0164     boundCovariance = newBoundCovariance;
0165   }
0166 
0167   if (additionalFreeCovariance) {
0168     boundCovariance += freeToBoundJacobian * (*additionalFreeCovariance) *
0169                        freeToBoundJacobian.transpose();
0170   }
0171 
0172   // Reinitialize jacobian components:
0173   // ->The derivatives are reinitialized to Zero
0174   // ->The boundToFreeJacobian is initialized to that at the current surface
0175   return reinitializeJacobians(geoContext, surface, freeToPathDerivatives,
0176                                boundToFreeJacobian, freeParameters);
0177 }
0178 
0179 void sympy::transportCovarianceToCurvilinear(
0180     BoundMatrix& boundCovariance, BoundMatrix& fullTransportJacobian,
0181     FreeVector& freeToPathDerivatives, BoundToFreeMatrix& boundToFreeJacobian,
0182     const std::optional<FreeMatrix>& additionalFreeCovariance,
0183     const Vector3& direction) {
0184   FreeToBoundMatrix freeToBoundJacobian;
0185 
0186   // Calculate the full jacobian from local parameters at the start surface to
0187   // current curvilinear parameters
0188   sympy::boundToCurvilinearTransportJacobian(
0189       direction, boundToFreeJacobian, freeToBoundJacobian,
0190       freeToPathDerivatives, fullTransportJacobian);
0191 
0192   // Apply the actual covariance transport to get covariance of the current
0193   // curvilinear parameters
0194   BoundMatrix newBoundCovariance;
0195   applyBoundCovarianceTransport(fullTransportJacobian, boundCovariance,
0196                                 newBoundCovariance);
0197   boundCovariance = newBoundCovariance;
0198 
0199   if (additionalFreeCovariance) {
0200     boundCovariance += freeToBoundJacobian * (*additionalFreeCovariance) *
0201                        freeToBoundJacobian.transpose();
0202   }
0203 
0204   // Reinitialize jacobian components:
0205   // ->The path derivatives are reinitialized to Zero
0206   // ->The boundToFreeJacobian is reinitialized to that at the current
0207   // curvilinear surface
0208   reinitializeJacobians(freeToPathDerivatives, boundToFreeJacobian, direction);
0209 }
0210 
0211 }  // namespace Acts::detail