CORSIKA  @c8_version@
The framework to simulate particle cascades for astroparticle physics
FindXmax.hpp
1 /*
2  * (c) Copyright 2021 CORSIKA Project, corsika-project@lists.kit.edu
3  *
4  * This software is distributed under the terms of the GNU General Public
5  * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
6  * the license.
7  */
8 
9 #pragma once
10 
12 
13 #include <tuple>
14 
15 namespace corsika {
16 
25  class FindXmax {
26 
27  static bool invert3by3(double A[3][3]) {
28  const double kSmall = 1e-80;
29 
30  double determinant = A[0][0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) -
31  A[0][1] * (A[1][0] * A[2][2] - A[1][2] * A[2][0]) +
32  A[0][2] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]);
33 
34  double absDet = fabs(determinant);
35 
36  if (absDet < kSmall) {
37  CORSIKA_LOG_WARN("invert3by3: Error-matrix singular (absDet={})", absDet);
38  return false;
39  }
40 
41  double B[3][3];
42 
43  B[0][0] = A[1][1] * A[2][2] - A[1][2] * A[2][1];
44  B[1][0] = A[1][2] * A[2][0] - A[2][2] * A[1][0];
45  B[2][0] = A[1][0] * A[2][1] - A[1][1] * A[2][0];
46 
47  B[0][1] = A[0][2] * A[2][1] - A[2][2] * A[0][1];
48  B[1][1] = A[0][0] * A[2][2] - A[2][0] * A[0][2];
49  B[2][1] = A[0][1] * A[2][0] - A[0][0] * A[2][1];
50 
51  B[0][2] = A[0][1] * A[1][2] - A[1][1] * A[0][2];
52  B[1][2] = A[0][2] * A[1][0] - A[1][2] * A[0][0];
53  B[2][2] = A[0][0] * A[1][1] - A[0][1] * A[1][0];
54 
55  for (int i = 0; i < 3; i++)
56  for (int j = 0; j < 3; j++) A[i][j] = B[i][j] / determinant;
57 
58  return true;
59  }
60 
61  /****************************************************
62  *
63  * solves linear system
64  *
65  * / y[0] \ / A[0][0] A[0][1] A[0][2] \ / x[0] \
66  * | y[1] | = | A[1][0] A[1][1] A[1][2] | * | x[1] |
67  * \ y[2] / \ A[2][0] A[2][1] A[2][2] / \ x[2] /
68  *
69  *
70  * Input: y[3] and A[3][3]
71  * Output: returns true when succeded (i.e. A is not singular)
72  * A is overwritten with its inverse
73  *
74  * M.Unger 12/1/05
75  *
76  ****************************************************/
77  static bool solve3by3(double y[3], double A[3][3], double x[3]) {
78  if (invert3by3(A)) {
79 
80  for (int i = 0; i < 3; i++)
81  x[i] = A[i][0] * y[0] + A[i][1] * y[1] + A[i][2] * y[2];
82 
83  return true;
84 
85  } else
86  return false;
87  }
88 
89  public:
90  static std::tuple<double, double> interpolateProfile(double x1, double x2, double x3,
91  double y1, double y2,
92  double y3) {
93 
94  // quadratic "fit" around maximum to get dEdXmax and Xmax
95  double x[3] = {x1, x2, x3};
96  double y[3] = {y1, y2, y3};
97 
98  double A[3][3];
99  A[0][0] = x[0] * x[0];
100  A[0][1] = x[0];
101  A[0][2] = 1.;
102  A[1][0] = x[1] * x[1];
103  A[1][1] = x[1];
104  A[1][2] = 1.;
105  A[2][0] = x[2] * x[2];
106  A[2][1] = x[2];
107  A[2][2] = 1.;
108 
109  double a[3];
110 
111  solve3by3(y, A, a);
112 
113  if (a[0] < 0.) {
114  double const Xmax = -a[1] / (2. * a[0]);
115  return std::make_tuple(Xmax, a[0] * Xmax * Xmax + a[1] * Xmax + a[2]);
116  }
117  return std::make_tuple(0, 0);
118  }
119  };
120 } // namespace corsika
CORSIKA8 logging utilities.
`, since they are used everywhere as integral part of the framework.
Interpolates profiles around maximum.
Definition: FindXmax.hpp:25