ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CovarianceEngine.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CovarianceEngine.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019-2020 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 
10 
11 namespace Acts {
12 namespace {
14 using Jacobian = BoundMatrix;
16 using BoundState = std::tuple<BoundParameters, Jacobian, double>;
17 using CurvilinearState = std::tuple<CurvilinearParameters, Jacobian, double>;
18 
24 FreeToBoundMatrix freeToCurvilinearJacobian(const Vector3D& direction) {
25  // Optimized trigonometry on the propagation direction
26  const double x = direction(0); // == cos(phi) * sin(theta)
27  const double y = direction(1); // == sin(phi) * sin(theta)
28  const double z = direction(2); // == cos(theta)
29  // can be turned into cosine/sine
30  const double cosTheta = z;
31  const double sinTheta = sqrt(x * x + y * y);
32  const double invSinTheta = 1. / sinTheta;
33  const double cosPhi = x * invSinTheta;
34  const double sinPhi = y * invSinTheta;
35  // prepare the jacobian to curvilinear
36  FreeToBoundMatrix jacToCurv = FreeToBoundMatrix::Zero();
37  if (std::abs(cosTheta) < s_curvilinearProjTolerance) {
38  // We normally operate in curvilinear coordinates defined as follows
39  jacToCurv(0, 0) = -sinPhi;
40  jacToCurv(0, 1) = cosPhi;
41  jacToCurv(1, 0) = -cosPhi * cosTheta;
42  jacToCurv(1, 1) = -sinPhi * cosTheta;
43  jacToCurv(1, 2) = sinTheta;
44  } else {
45  // Under grazing incidence to z, the above coordinate system definition
46  // becomes numerically unstable, and we need to switch to another one
47  const double c = sqrt(y * y + z * z);
48  const double invC = 1. / c;
49  jacToCurv(0, 1) = -z * invC;
50  jacToCurv(0, 2) = y * invC;
51  jacToCurv(1, 0) = c;
52  jacToCurv(1, 1) = -x * y * invC;
53  jacToCurv(1, 2) = -x * z * invC;
54  }
55  // Time parameter
56  jacToCurv(5, 3) = 1.;
57  // Directional and momentum parameters for curvilinear
58  jacToCurv(2, 4) = -sinPhi * invSinTheta;
59  jacToCurv(2, 5) = cosPhi * invSinTheta;
60  jacToCurv(3, 4) = cosPhi * cosTheta;
61  jacToCurv(3, 5) = sinPhi * cosTheta;
62  jacToCurv(3, 6) = -sinTheta;
63  jacToCurv(4, 7) = 1.;
64 
65  return jacToCurv;
66 }
67 
85 FreeToBoundMatrix surfaceDerivative(
86  std::reference_wrapper<const GeometryContext> geoContext,
87  const FreeVector& parameters, BoundToFreeMatrix& jacobianLocalToGlobal,
88  const FreeVector& derivatives, const Surface& surface) {
89  // Initialize the transport final frame jacobian
90  FreeToBoundMatrix jacToLocal = FreeToBoundMatrix::Zero();
91  // Initalize the jacobian to local, returns the transposed ref frame
92  auto rframeT = surface.initJacobianToLocal(geoContext, jacToLocal,
93  parameters.segment<3>(eFreePos0),
94  parameters.segment<3>(eFreeDir0));
95  // Calculate the form factors for the derivatives
96  const BoundRowVector sVec = surface.derivativeFactors(
97  geoContext, parameters.segment<3>(eFreePos0),
98  parameters.segment<3>(eFreeDir0), rframeT, jacobianLocalToGlobal);
99  jacobianLocalToGlobal -= derivatives * sVec;
100  // Return the jacobian to local
101  return jacToLocal;
102 }
103 
121 const FreeToBoundMatrix surfaceDerivative(
122  const Vector3D& direction, BoundToFreeMatrix& jacobianLocalToGlobal,
123  const FreeVector& derivatives) {
124  // Transport the covariance
125  const ActsRowVectorD<3> normVec(direction);
126  const BoundRowVector sfactors =
127  normVec *
128  jacobianLocalToGlobal.template topLeftCorner<3, eBoundParametersSize>();
129  jacobianLocalToGlobal -= derivatives * sfactors;
130  // Since the jacobian to local needs to calculated for the bound parameters
131  // here, it is convenient to do the same here
132  return freeToCurvilinearJacobian(direction);
133 }
134 
146 void reinitializeJacobians(
147  std::reference_wrapper<const GeometryContext> geoContext,
148  FreeMatrix& transportJacobian, FreeVector& derivatives,
149  BoundToFreeMatrix& jacobianLocalToGlobal, const FreeVector& parameters,
150  const Surface& surface) {
151  using VectorHelpers::phi;
152  using VectorHelpers::theta;
153 
154  // Reset the jacobians
155  transportJacobian = FreeMatrix::Identity();
156  derivatives = FreeVector::Zero();
157  jacobianLocalToGlobal = BoundToFreeMatrix::Zero();
158 
159  // Reset the jacobian from local to global
160  Vector2D loc{0., 0.};
161  const Vector3D position = parameters.segment<3>(eFreePos0);
162  const Vector3D direction = parameters.segment<3>(eFreeDir0);
163  surface.globalToLocal(geoContext, position, direction, loc);
164  BoundVector pars;
165  pars << loc[eLOC_0], loc[eLOC_1], phi(direction), theta(direction),
166  parameters[eFreeQOverP], parameters[eFreeTime];
167  surface.initJacobianToGlobal(geoContext, jacobianLocalToGlobal, position,
168  direction, pars);
169 }
170 
180 void reinitializeJacobians(FreeMatrix& transportJacobian,
181  FreeVector& derivatives,
182  BoundToFreeMatrix& jacobianLocalToGlobal,
183  const Vector3D& direction) {
184  // Reset the jacobians
185  transportJacobian = FreeMatrix::Identity();
186  derivatives = FreeVector::Zero();
187  jacobianLocalToGlobal = BoundToFreeMatrix::Zero();
188 
189  // Optimized trigonometry on the propagation direction
190  const double x = direction(0); // == cos(phi) * sin(theta)
191  const double y = direction(1); // == sin(phi) * sin(theta)
192  const double z = direction(2); // == cos(theta)
193  // can be turned into cosine/sine
194  const double cosTheta = z;
195  const double sinTheta = sqrt(x * x + y * y);
196  const double invSinTheta = 1. / sinTheta;
197  const double cosPhi = x * invSinTheta;
198  const double sinPhi = y * invSinTheta;
199 
200  jacobianLocalToGlobal(0, eLOC_0) = -sinPhi;
201  jacobianLocalToGlobal(0, eLOC_1) = -cosPhi * cosTheta;
202  jacobianLocalToGlobal(1, eLOC_0) = cosPhi;
203  jacobianLocalToGlobal(1, eLOC_1) = -sinPhi * cosTheta;
204  jacobianLocalToGlobal(2, eLOC_1) = sinTheta;
205  jacobianLocalToGlobal(3, eT) = 1;
206  jacobianLocalToGlobal(4, ePHI) = -sinTheta * sinPhi;
207  jacobianLocalToGlobal(4, eTHETA) = cosTheta * cosPhi;
208  jacobianLocalToGlobal(5, ePHI) = sinTheta * cosPhi;
209  jacobianLocalToGlobal(5, eTHETA) = cosTheta * sinPhi;
210  jacobianLocalToGlobal(6, eTHETA) = -sinTheta;
211  jacobianLocalToGlobal(7, eQOP) = 1;
212 }
213 } // namespace
214 
215 namespace detail {
216 
217 BoundState boundState(std::reference_wrapper<const GeometryContext> geoContext,
218  Covariance& covarianceMatrix, Jacobian& jacobian,
219  FreeMatrix& transportJacobian, FreeVector& derivatives,
220  BoundToFreeMatrix& jacobianLocalToGlobal,
221  const FreeVector& parameters, bool covTransport,
222  double accumulatedPath, const Surface& surface) {
223  // Covariance transport
224  std::optional<BoundSymMatrix> cov = std::nullopt;
225  if (covTransport) {
226  covarianceTransport(geoContext, covarianceMatrix, jacobian,
227  transportJacobian, derivatives, jacobianLocalToGlobal,
228  parameters, surface);
229  cov = covarianceMatrix;
230  }
231  // Create the bound parameters
232  const Vector3D& position = parameters.segment<3>(eFreePos0);
233  const Vector3D momentum =
234  std::abs(1. / parameters[eFreeQOverP]) * parameters.segment<3>(eFreeDir0);
235  const double charge = std::copysign(1., parameters[eFreeQOverP]);
236  const double time = parameters[eFreeTime];
237  BoundParameters boundParameters(geoContext, cov, position, momentum, charge,
238  time, surface.getSharedPtr());
239  // Create the bound state
240  return std::make_tuple(std::move(boundParameters), jacobian, accumulatedPath);
241  ;
242 }
243 
244 CurvilinearState curvilinearState(Covariance& covarianceMatrix,
245  Jacobian& jacobian,
246  FreeMatrix& transportJacobian,
247  FreeVector& derivatives,
248  BoundToFreeMatrix& jacobianLocalToGlobal,
249  const FreeVector& parameters,
250  bool covTransport, double accumulatedPath) {
251  const Vector3D& direction = parameters.segment<3>(eFreeDir0);
252 
253  // Covariance transport
254  std::optional<BoundSymMatrix> cov = std::nullopt;
255  if (covTransport) {
256  covarianceTransport(covarianceMatrix, jacobian, transportJacobian,
257  derivatives, jacobianLocalToGlobal, direction);
258  cov = covarianceMatrix;
259  }
260  // Create the curvilinear parameters
261  const Vector3D& position = parameters.segment<3>(eFreePos0);
262  const Vector3D momentum = std::abs(1. / parameters[eFreeQOverP]) * direction;
263  const double charge = std::copysign(1., parameters[eFreeQOverP]);
264  const double time = parameters[eFreeTime];
265  CurvilinearParameters curvilinearParameters(cov, position, momentum, charge,
266  time);
267  // Create the curvilinear state
268  return std::make_tuple(std::move(curvilinearParameters), jacobian,
269  accumulatedPath);
270 }
271 
272 void covarianceTransport(Covariance& covarianceMatrix, Jacobian& jacobian,
273  FreeMatrix& transportJacobian, FreeVector& derivatives,
274  BoundToFreeMatrix& jacobianLocalToGlobal,
275  const Vector3D& direction) {
276  // Build the full jacobian
277  jacobianLocalToGlobal = transportJacobian * jacobianLocalToGlobal;
278  const FreeToBoundMatrix jacToLocal =
279  surfaceDerivative(direction, jacobianLocalToGlobal, derivatives);
280  const Jacobian jacFull = jacToLocal * jacobianLocalToGlobal;
281 
282  // Apply the actual covariance transport
283  covarianceMatrix = jacFull * covarianceMatrix * jacFull.transpose();
284 
285  // Reinitialize jacobian components
286  reinitializeJacobians(transportJacobian, derivatives, jacobianLocalToGlobal,
287  direction);
288 
289  // Store The global and bound jacobian (duplication for the moment)
290  jacobian = jacFull;
291 }
292 
294  std::reference_wrapper<const GeometryContext> geoContext,
295  Covariance& covarianceMatrix, Jacobian& jacobian,
296  FreeMatrix& transportJacobian, FreeVector& derivatives,
297  BoundToFreeMatrix& jacobianLocalToGlobal, const FreeVector& parameters,
298  const Surface& surface) {
299  // Build the full jacobian
300  jacobianLocalToGlobal = transportJacobian * jacobianLocalToGlobal;
301  const FreeToBoundMatrix jacToLocal = surfaceDerivative(
302  geoContext, parameters, jacobianLocalToGlobal, derivatives, surface);
303  const Jacobian jacFull = jacToLocal * jacobianLocalToGlobal;
304 
305  // Apply the actual covariance transport
306  covarianceMatrix = jacFull * covarianceMatrix * jacFull.transpose();
307 
308  // Reinitialize jacobian components
309  reinitializeJacobians(geoContext, transportJacobian, derivatives,
310  jacobianLocalToGlobal, parameters, surface);
311 
312  // Store The global and bound jacobian (duplication for the moment)
313  jacobian = jacFull;
314 }
315 } // namespace detail
316 } // namespace Acts