CbmRoot
Loading...
Searching...
No Matches
KfFieldSlice.cxx
Go to the documentation of this file.
1/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko [committer] */
4
9
10#include "KfFieldSlice.h"
11
12#include <iomanip>
13#include <sstream>
14
15#include <fmt/format.h>
16
20
21// ---------------------------------------------------------------------------------------------------------------------
22//
23template<typename T>
24FieldSlice<T>::FieldSlice(const FieldFn_t& fieldFn, double xMax, double yMax, double zRef) : fZref(zRef)
25{
26 // SLE initialization
27 // Augmented matrix N x (N + 3), where N - number of coefficients, defining the polynomial
28 //
29 std::array<std::array<double, kNofCoeff + 3>, kNofCoeff> A = {{}};
30
31 double dx = xMax / kNofCoeff / 10.;
32 double dy = yMax / kNofCoeff / 10.;
33
34 if (dx > 1.) {
35 dx = 1.;
36 }
37 if (dy > 1.) {
38 dy = 1.;
39 }
40
41 // Point and field arrays to access the field
42 std::array<double, 3> field;
43
44 // Monomial values for each coefficient
45 std::array<double, kNofCoeff> m = {{}};
46
47 // Fill the augmented matrix
48 for (double x = -xMax; x <= xMax; x += dx) {
49 for (double y = -yMax; y <= yMax; y += dy) {
50 std::tie(field[0], field[1], field[2]) = fieldFn(x, y, zRef);
51 // Fill the monomial array
52 {
53 m[kNofCoeff - 1] = 1.;
54 for (int i = kNofCoeff - 2; i >= kNofCoeff - 1 - kPolDegree; --i) {
55 m[i] = y * m[i + 1];
56 }
57 double xFactor = x;
58 int k = ((kPolDegree - 1) * (kPolDegree + 2)) / 2; // index of the monomial vector element
59 for (int i = kPolDegree; i > 0; --i) { // loop over y powers
60 for (int j = kNofCoeff - 1; j >= kNofCoeff - i; --j) { // loop over x powers
61 m[k--] = xFactor * m[j];
62 }
63 xFactor *= x;
64 }
65 }
66
67 {
68 double w = 1.; // / (r2 + 1.);
69 for (int i = 0; i < kNofCoeff; ++i) {
70 // Fill the left part
71 for (int j = 0; j < kNofCoeff; ++j) {
72 A[i][j] += w * m[i] * m[j];
73 }
74 // Fill the right part
75 for (int j = 0; j < 3; ++j) {
76 A[i][kNofCoeff + j] += w * field[j] * m[i];
77 }
78 }
79 }
80 }
81 }
82
83 // SLE solution using Gaussian elimination
84 {
85 for (int k = 0; k < kNofCoeff - 1; ++k) {
86 for (int j = k + 1; j < kNofCoeff; ++j) {
87 double factor = A[j][k] / A[k][k];
88 for (int i = 0; i < kNofCoeff + 3; ++i) {
89 A[j][i] -= factor * A[k][i];
90 }
91 }
92 }
93 for (int k = kNofCoeff - 1; k > 0; --k) {
94 for (int j = k - 1; j >= 0; --j) {
95 double factor = A[j][k] / A[k][k];
96 for (int i = k; i < kNofCoeff + 3; ++i) {
97 A[j][i] -= factor * A[k][i];
98 }
99 }
100 }
101 }
102
103 for (int j = 0; j < kNofCoeff; ++j) {
104 fBx[j] = utils::simd::Cast<double, T>(A[j][kNofCoeff] / A[j][j]);
105 fBy[j] = utils::simd::Cast<double, T>(A[j][kNofCoeff + 1] / A[j][j]);
106 fBz[j] = utils::simd::Cast<double, T>(A[j][kNofCoeff + 2] / A[j][j]);
107 }
108}
109
110// ---------------------------------------------------------------------------------------------------------------------
111//
112template<typename T>
113std::string FieldSlice<T>::ToString(int indentLevel, int verbose) const
114{
115 using fmt::format;
116 constexpr char indentChar = '\t';
117 std::stringstream msg;
118 std::string indent(indentLevel, indentChar);
119 auto Cnv = [&](const auto& val) { return utils::simd::Cast<T, Literal_t<T>>(val); }; // alias for the conversion fn
120
121 if (verbose > 0) {
122 msg << indent << format("FieldSlice: zRef = {} cm", Cnv(fZref));
123 if (verbose > 1) {
124 std::array<std::string, kNofCoeff> m;
125 {
126 m[kNofCoeff - 1] = "";
127 for (int i = kNofCoeff - 2; i >= kNofCoeff - 1 - kPolDegree; --i) {
128 m[i] = format("y{}", kNofCoeff - i - 1);
129 }
130 int k = ((kPolDegree - 1) * (kPolDegree + 2)) / 2; // index of the monomial vector element
131 for (int i = kPolDegree; i > 0; --i) { // loop over y powers
132 std::string x = format("x{}", kPolDegree - i + 1);
133 for (int j = kNofCoeff - 1; j >= kNofCoeff - i; --j) { // loop over x powers
134 m[k--] = x + m[j];
135 }
136 }
137 m[kNofCoeff - 1] = "1";
138 }
139 msg << '\n' << indent << format("{:>15} {:>15} {:>15} {:>15}", "Monomial", "Bx", "By", "Bz");
140 for (int i = 0; i < kNofCoeff; ++i) {
141 msg << '\n' << indent << format("{:>15} {:>15} {:>15} {:>15}", m[i], Cnv(fBx[i]), Cnv(fBy[i]), Cnv(fBz[i]));
142 }
143 }
144 }
145 return msg.str();
146}
147
148template<typename T>
150{
151 // Check SIMD data vectors for consistent initialization
152 for (int i = 0; i < kNofCoeff; ++i) {
153 utils::CheckSimdVectorEquality(fBx[i], "FieldSlice: cx");
154 utils::CheckSimdVectorEquality(fBy[i], "FieldSlice: cy");
155 utils::CheckSimdVectorEquality(fBz[i], "FieldSlice: cz");
156 }
157 utils::CheckSimdVectorEquality(fZref, "FieldSlice: z");
158}
159
160namespace cbm::algo::kf
161{
162 template class FieldSlice<float>;
163 template class FieldSlice<double>;
164 template class FieldSlice<fvec>;
165} // namespace cbm::algo::kf
A class for a magnetic field approximation on a transverse plane (source)
A magnetic field approximation on the two-dimensional plane.
void CheckConsistency() const
Consistency checker.
CoeffArray_t fBx
Approximation coefficients for the x-component of the field.
CoeffArray_t fBz
Approximation coefficients for the z-component of the field.
static constexpr int kNofCoeff
Number of coefficients.
static constexpr int kPolDegree
Approximation polynomial degree.
CoeffArray_t fBy
Approximation coefficients for the y-component of the field.
std::string ToString(int indentLevel=0, int verbose=1) const
String representation of the class content.
Magnetic flux density vector.
constexpr double m
DataOut Cast(const DataT &val)
Converts a value of type DataT to type DataOut.
Definition KfUtils.h:212
void CheckSimdVectorEquality(fvec v, const char *name)
Checks, if a SIMD vector horizontally equal TODO: Find this method in the VC!
Definition KfUtils.cxx:29
std::function< std::tuple< double, double, double >(double, double, double)> FieldFn_t
Magnetic field function type Signature: tuple<Bx, By, Bz>(x, y, z);.
Definition KfDefs.h:66