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 
14 
15 namespace Acts {
16 namespace {
18 using Jacobian = BoundMatrix;
20 using BoundState = std::tuple<BoundTrackParameters, Jacobian, double>;
21 using CurvilinearState =
22  std::tuple<CurvilinearTrackParameters, Jacobian, double>;
23 
29 FreeToBoundMatrix freeToCurvilinearJacobian(const Vector3D& direction) {
30  // Optimized trigonometry on the propagation direction
31  const double x = direction(0); // == cos(phi) * sin(theta)
32  const double y = direction(1); // == sin(phi) * sin(theta)
33  const double z = direction(2); // == cos(theta)
34  // can be turned into cosine/sine
35  const double cosTheta = z;
36  const double sinTheta = sqrt(x * x + y * y);
37  const double invSinTheta = 1. / sinTheta;
38  const double cosPhi = x * invSinTheta;
39  const double sinPhi = y * invSinTheta;
40  // prepare the jacobian to curvilinear
41  FreeToBoundMatrix jacToCurv = FreeToBoundMatrix::Zero();
42  if (std::abs(cosTheta) < s_curvilinearProjTolerance) {
43  // We normally operate in curvilinear coordinates defined as follows
44  jacToCurv(0, 0) = -sinPhi;
45  jacToCurv(0, 1) = cosPhi;
46  jacToCurv(1, 0) = -cosPhi * cosTheta;
47  jacToCurv(1, 1) = -sinPhi * cosTheta;
48  jacToCurv(1, 2) = sinTheta;
49  } else {
50  // Under grazing incidence to z, the above coordinate system definition
51  // becomes numerically unstable, and we need to switch to another one
52  const double c = sqrt(y * y + z * z);
53  const double invC = 1. / c;
54  jacToCurv(0, 1) = -z * invC;
55  jacToCurv(0, 2) = y * invC;
56  jacToCurv(1, 0) = c;
57  jacToCurv(1, 1) = -x * y * invC;
58  jacToCurv(1, 2) = -x * z * invC;
59  }
60  // Time parameter
61  jacToCurv(5, 3) = 1.;
62  // Directional and momentum parameters for curvilinear
63  jacToCurv(2, 4) = -sinPhi * invSinTheta;
64  jacToCurv(2, 5) = cosPhi * invSinTheta;
65  jacToCurv(3, 4) = cosPhi * cosTheta;
66  jacToCurv(3, 5) = sinPhi * cosTheta;
67  jacToCurv(3, 6) = -sinTheta;
68  jacToCurv(4, 7) = 1.;
69 
70  return jacToCurv;
71 }
72 
90 FreeToBoundMatrix surfaceDerivative(
91  std::reference_wrapper<const GeometryContext> geoContext,
92  const FreeVector& parameters, BoundToFreeMatrix& jacobianLocalToGlobal,
93  const FreeVector& derivatives, const Surface& surface) {
94  // Initialize the transport final frame jacobian
95  FreeToBoundMatrix jacToLocal = FreeToBoundMatrix::Zero();
96  // Initalize the jacobian to local, returns the transposed ref frame
97  auto rframeT = surface.initJacobianToLocal(geoContext, jacToLocal,
98  parameters.segment<3>(eFreePos0),
99  parameters.segment<3>(eFreeDir0));
100  // Calculate the form factors for the derivatives
101  const BoundRowVector sVec = surface.derivativeFactors(
102  geoContext, parameters.segment<3>(eFreePos0),
103  parameters.segment<3>(eFreeDir0), rframeT, jacobianLocalToGlobal);
104  jacobianLocalToGlobal -= derivatives * sVec;
105  // Return the jacobian to local
106  return jacToLocal;
107 }
108 
126 const FreeToBoundMatrix surfaceDerivative(
127  const Vector3D& direction, BoundToFreeMatrix& jacobianLocalToGlobal,
128  const FreeVector& derivatives) {
129  // Transport the covariance
130  const ActsRowVectorD<3> normVec(direction);
131  const BoundRowVector sfactors =
132  normVec * jacobianLocalToGlobal.template topLeftCorner<3, eBoundSize>();
133  jacobianLocalToGlobal -= derivatives * sfactors;
134  // Since the jacobian to local needs to calculated for the bound parameters
135  // here, it is convenient to do the same here
136  return freeToCurvilinearJacobian(direction);
137 }
138 
150 void reinitializeJacobians(
151  std::reference_wrapper<const GeometryContext> geoContext,
152  FreeMatrix& transportJacobian, FreeVector& derivatives,
153  BoundToFreeMatrix& jacobianLocalToGlobal, const FreeVector& parameters,
154  const Surface& surface) {
155  using VectorHelpers::phi;
156  using VectorHelpers::theta;
157 
158  // Reset the jacobians
159  transportJacobian = FreeMatrix::Identity();
160  derivatives = FreeVector::Zero();
161  jacobianLocalToGlobal = BoundToFreeMatrix::Zero();
162 
163  // Reset the jacobian from local to global
164  const Vector3D position = parameters.segment<3>(eFreePos0);
165  const Vector3D direction = parameters.segment<3>(eFreeDir0);
166  auto lpResult = surface.globalToLocal(geoContext, position, direction);
167  if (not lpResult.ok()) {
169  Acts::getDefaultLogger("CovarianceEngine", Logging::INFO));
170  ACTS_FATAL(
171  "Inconsistency in global to local transformation during propagation.")
172  }
173  auto loc = lpResult.value();
174  BoundVector pars;
175  pars << loc[eBoundLoc0], loc[eBoundLoc1], phi(direction), theta(direction),
176  parameters[eFreeQOverP], parameters[eFreeTime];
177  surface.initJacobianToGlobal(geoContext, jacobianLocalToGlobal, position,
178  direction, pars);
179 }
180 
190 void reinitializeJacobians(FreeMatrix& transportJacobian,
191  FreeVector& derivatives,
192  BoundToFreeMatrix& jacobianLocalToGlobal,
193  const Vector3D& direction) {
194  // Reset the jacobians
195  transportJacobian = FreeMatrix::Identity();
196  derivatives = FreeVector::Zero();
197  jacobianLocalToGlobal = BoundToFreeMatrix::Zero();
198 
199  // Optimized trigonometry on the propagation direction
200  const double x = direction(0); // == cos(phi) * sin(theta)
201  const double y = direction(1); // == sin(phi) * sin(theta)
202  const double z = direction(2); // == cos(theta)
203  // can be turned into cosine/sine
204  const double cosTheta = z;
205  const double sinTheta = sqrt(x * x + y * y);
206  const double invSinTheta = 1. / sinTheta;
207  const double cosPhi = x * invSinTheta;
208  const double sinPhi = y * invSinTheta;
209 
210  jacobianLocalToGlobal(0, eBoundLoc0) = -sinPhi;
211  jacobianLocalToGlobal(0, eBoundLoc1) = -cosPhi * cosTheta;
212  jacobianLocalToGlobal(1, eBoundLoc0) = cosPhi;
213  jacobianLocalToGlobal(1, eBoundLoc1) = -sinPhi * cosTheta;
214  jacobianLocalToGlobal(2, eBoundLoc1) = sinTheta;
215  jacobianLocalToGlobal(3, eBoundTime) = 1;
216  jacobianLocalToGlobal(4, eBoundPhi) = -sinTheta * sinPhi;
217  jacobianLocalToGlobal(4, eBoundTheta) = cosTheta * cosPhi;
218  jacobianLocalToGlobal(5, eBoundPhi) = sinTheta * cosPhi;
219  jacobianLocalToGlobal(5, eBoundTheta) = cosTheta * sinPhi;
220  jacobianLocalToGlobal(6, eBoundTheta) = -sinTheta;
221  jacobianLocalToGlobal(7, eBoundQOverP) = 1;
222 }
223 } // namespace
224 
225 namespace detail {
226 
227 BoundState boundState(std::reference_wrapper<const GeometryContext> geoContext,
228  Covariance& covarianceMatrix, Jacobian& jacobian,
229  FreeMatrix& transportJacobian, FreeVector& derivatives,
230  BoundToFreeMatrix& jacobianLocalToGlobal,
231  const FreeVector& parameters, bool covTransport,
232  double accumulatedPath, const Surface& surface) {
233  // Covariance transport
234  std::optional<BoundSymMatrix> cov = std::nullopt;
235  if (covTransport) {
236  covarianceTransport(geoContext, covarianceMatrix, jacobian,
237  transportJacobian, derivatives, jacobianLocalToGlobal,
238  parameters, surface);
239  cov = covarianceMatrix;
240  }
241  // Create the bound parameters
242  BoundVector bv =
243  detail::transformFreeToBoundParameters(parameters, surface, geoContext);
244  // Create the bound state
245  return std::make_tuple(
246  BoundTrackParameters(surface.getSharedPtr(), bv, std::move(cov)),
247  jacobian, accumulatedPath);
248 }
249 
250 CurvilinearState curvilinearState(Covariance& covarianceMatrix,
251  Jacobian& jacobian,
252  FreeMatrix& transportJacobian,
253  FreeVector& derivatives,
254  BoundToFreeMatrix& jacobianLocalToGlobal,
255  const FreeVector& parameters,
256  bool covTransport, double accumulatedPath) {
257  const Vector3D& direction = parameters.segment<3>(eFreeDir0);
258 
259  // Covariance transport
260  std::optional<BoundSymMatrix> cov = std::nullopt;
261  if (covTransport) {
262  covarianceTransport(covarianceMatrix, jacobian, transportJacobian,
263  derivatives, jacobianLocalToGlobal, direction);
264  cov = covarianceMatrix;
265  }
266  // Create the curvilinear parameters
267  Vector4D pos4 = Vector4D::Zero();
268  pos4[ePos0] = parameters[eFreePos0];
269  pos4[ePos1] = parameters[eFreePos1];
270  pos4[ePos2] = parameters[eFreePos2];
271  pos4[eTime] = parameters[eFreeTime];
272  CurvilinearTrackParameters curvilinearParams(
273  pos4, direction, parameters[eFreeQOverP], std::move(cov));
274  // Create the curvilinear state
275  return std::make_tuple(std::move(curvilinearParams), jacobian,
276  accumulatedPath);
277 }
278 
279 void covarianceTransport(Covariance& covarianceMatrix, Jacobian& jacobian,
280  FreeMatrix& transportJacobian, FreeVector& derivatives,
281  BoundToFreeMatrix& jacobianLocalToGlobal,
282  const Vector3D& direction) {
283  // Build the full jacobian
284  jacobianLocalToGlobal = transportJacobian * jacobianLocalToGlobal;
285  const FreeToBoundMatrix jacToLocal =
286  surfaceDerivative(direction, jacobianLocalToGlobal, derivatives);
287  const Jacobian jacFull = jacToLocal * jacobianLocalToGlobal;
288 
289  // Apply the actual covariance transport
290  covarianceMatrix = jacFull * covarianceMatrix * jacFull.transpose();
291 
292  // Reinitialize jacobian components
293  reinitializeJacobians(transportJacobian, derivatives, jacobianLocalToGlobal,
294  direction);
295 
296  // Store The global and bound jacobian (duplication for the moment)
297  jacobian = jacFull;
298 }
299 
301  std::reference_wrapper<const GeometryContext> geoContext,
302  Covariance& covarianceMatrix, Jacobian& jacobian,
303  FreeMatrix& transportJacobian, FreeVector& derivatives,
304  BoundToFreeMatrix& jacobianLocalToGlobal, const FreeVector& parameters,
305  const Surface& surface) {
306  // Build the full jacobian
307  jacobianLocalToGlobal = transportJacobian * jacobianLocalToGlobal;
308  const FreeToBoundMatrix jacToLocal = surfaceDerivative(
309  geoContext, parameters, jacobianLocalToGlobal, derivatives, surface);
310  const Jacobian jacFull = jacToLocal * jacobianLocalToGlobal;
311 
312  // Apply the actual covariance transport
313  covarianceMatrix = jacFull * covarianceMatrix * jacFull.transpose();
314 
315  // Reinitialize jacobian components
316  reinitializeJacobians(geoContext, transportJacobian, derivatives,
317  jacobianLocalToGlobal, parameters, surface);
318 
319  // Store The global and bound jacobian (duplication for the moment)
320  jacobian = jacFull;
321 }
322 
323 } // namespace detail
324 } // namespace Acts