CbmRoot
Loading...
Searching...
No Matches
KfField.h
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#pragma once
11
12#include "KfDefs.h"
13#include "KfFieldRegion.h"
14#include "KfFieldSlice.h"
15
16#include <boost/serialization/access.hpp>
17#include <boost/serialization/split_free.hpp>
18
19#include <array>
20#include <optional>
21#include <set>
22
23namespace cbm::algo::kf
24{
25 namespace detail
26 {
31 template<typename T, EFieldMode FldMode>
32 class alignas(VcMemAlign) FieldBase {
33 };
34
38 template<typename T>
39 class alignas(VcMemAlign) FieldBase<T, EFieldMode::Orig> {
40 template<typename, EFieldMode>
41 friend class FieldBase;
42
43 public:
45 FieldBase() = default;
46
49 template<typename I>
50 FieldBase(const FieldBase<I, EFieldMode::Orig>& other) : fFieldFn(other.fFieldFn)
51 {
52 fvFieldSliceZ.reserve(other.fvFieldSliceZ.size());
53 for (const auto& slice : other.fvFieldSliceZ) {
54 fvFieldSliceZ.emplace_back(utils::simd::Cast<I, T>(slice));
55 }
56 }
57
60 {
61 if (this != &other) {
62 fvFieldSliceZ = other.fvFieldSliceZ;
63 fFieldFn = other.fFieldFn;
64 }
65 return *this;
66 }
67
70 void AddFieldSlice(const T& fieldSliceZref) { fvFieldSliceZ.push_back(fieldSliceZref); }
71
76 FieldValue<T> GetFieldValue(int sliceID, const T& x, const T& y) const
77 {
78 return GlobalField::GetFieldValue(fFieldFn, x, y, fvFieldSliceZ[sliceID]);
79 }
80
82 const FieldFn_t& GetFieldFunction() const { return fFieldFn; }
83
85 int GetNofFieldSlices() const { return fvFieldSliceZ.size(); }
86
89 void RemoveSlice(int iLayer) { fvFieldSliceZ.erase(fvFieldSliceZ.begin() + iLayer); }
90
93 void SetFieldFunction(const FieldFn_t& fieldFn) { fFieldFn = fieldFn; }
94
98 std::string ToString(int indentLevel, int verbose) const;
99
100 private:
101 std::vector<T> fvFieldSliceZ{};
102 FieldFn_t fFieldFn{defs::ZeroFieldFn};
103 };
104
105
109 template<typename T>
110 class alignas(VcMemAlign) FieldBase<T, EFieldMode::Intrpl> {
111 template<typename, EFieldMode>
112 friend class FieldBase;
113
114 using SlicesContainer_t = std::vector<FieldSlice<T>>;
115
116 public:
118 FieldBase() = default;
119
122 template<typename I>
124 {
125 fvFieldSlices.reserve(other.fvFieldSlices.size());
126 for (const auto& slice : other.fvFieldSlices) {
127 fvFieldSlices.emplace_back(FieldSlice<T>(slice));
128 }
129 }
130
133 {
134 if (this != &other) {
135 fvFieldSlices = other.fvFieldSlices;
136 }
137 return *this;
138 }
139
142 void AddFieldSlice(const FieldSlice<T>& fieldSlice) { fvFieldSlices.push_back(fieldSlice); }
143
146 const auto& GetFieldSlice(int sliceID) const { return fvFieldSlices[sliceID]; }
147
152 FieldValue<T> GetFieldValue(int sliceID, const T& x, const T& y) const
153 {
154 return fvFieldSlices[sliceID].GetFieldValue(x, y);
155 }
156
158 int GetNofFieldSlices() const { return fvFieldSlices.size(); }
159
162 void RemoveSlice(int iLayer) { fvFieldSlices.erase(fvFieldSlices.begin() + iLayer); }
163
167 std::string ToString(int indentLevel, int verbose) const;
168
169 protected:
170 SlicesContainer_t fvFieldSlices{};
171
172 private:
174 friend class boost::serialization::access;
175 template<class Archive>
176 void serialize(Archive& ar, const unsigned int)
177 {
178 ar& fvFieldSlices;
179 }
180 };
181 } // namespace detail
182
183
187 template<typename T>
188 class alignas(VcMemAlign) Field {
189 template<typename>
190 friend class Field;
191 friend class FieldFactory;
192 friend class boost::serialization::access;
193
194 public:
197 Field(EFieldMode fldMode, EFieldType fldType)
198 : foFldIntrpl(fldMode == EFieldMode::Intrpl ? std::make_optional(detail::FieldBase<T, EFieldMode::Intrpl>())
199 : std::nullopt)
200 , foFldOrig(fldMode == EFieldMode::Orig ? std::make_optional(detail::FieldBase<T, EFieldMode::Orig>())
201 : std::nullopt)
202 , fPrimVertexField(FieldRegion<T>(fldMode, fldType))
203 , fFieldType(fldType)
204 , fFieldMode(fldMode)
205 {
206 }
207
209 template<typename I>
210 Field(const Field<I>& other)
211 : foFldIntrpl(other.foFldIntrpl.has_value()
212 ? std::make_optional(detail::FieldBase<T, EFieldMode::Intrpl>(*other.foFldIntrpl))
213 : std::nullopt)
214 , foFldOrig(other.foFldOrig.has_value()
215 ? std::make_optional(detail::FieldBase<T, EFieldMode::Orig>(*other.foFldOrig))
216 : std::nullopt)
217 , fPrimVertexField(FieldRegion<I>(other.fPrimVertexField))
218 , fFieldType(other.fFieldType)
219 , fFieldMode(other.fFieldMode)
220 {
221 }
222
224 ~Field() = default;
225
227 Field& operator=(const Field& other)
228 {
229 if (this != &other) {
230 fPrimVertexField = other.fPrimVertexField;
231 foFldIntrpl = other.foFldIntrpl;
232 foFldOrig = other.foFldOrig;
233 fFieldType = other.fFieldType;
234 fFieldMode = other.fFieldMode;
235 }
236 return *this;
237 }
238
243 FieldValue<T> GetFieldValue(int sliceID, const T& x, const T& y) const
244 {
245 return fFieldMode == EFieldMode::Intrpl ? foFldIntrpl->GetFieldValue(sliceID, x, y)
246 : foFldOrig->GetFieldValue(sliceID, x, y);
247 }
248
250 EFieldType GetFieldType() const { return this->fFieldType; }
251
253 const FieldRegion<T>& GetPrimVertexField() const { return fPrimVertexField; }
254
263 FieldRegion<T> GetFieldRegion(const FieldValue<T>& b0, const T& z0, const FieldValue<T>& b1, const T& z1,
264 const FieldValue<T>& b2, const T& z2) const
265 {
266 return (fFieldMode == EFieldMode::Intrpl ? FieldRegion<T>(b0, z0, b1, z1, b2, z2)
267 : FieldRegion<T>(fFieldType, foFldOrig->GetFieldFunction()));
268 }
269
272 void RemoveSlice(int iLayer);
273
277 std::string ToString(int indentLevel, int verbose) const;
278
279 private:
281 Field() = default;
282
284 template<class Archive>
285 void load(Archive& ar, const unsigned int /*version*/)
286 {
288 ar >> field;
289 foFldIntrpl = std::make_optional(field);
290 ar >> fPrimVertexField;
291 ar >> fFieldType;
292 ar >> fFieldMode;
293 foFldOrig = std::nullopt; // Note: original field cannot be serialized
294 }
295
297 template<class Archive>
298 void save(Archive& ar, const unsigned int /*version*/) const
299 {
300 if (fFieldMode == EFieldMode::Intrpl) {
301 ar << (*foFldIntrpl);
302 ar << fPrimVertexField;
303 ar << fFieldType;
304 ar << fFieldMode;
305 }
306 else if (fFieldMode == EFieldMode::Orig) {
307 throw std::logic_error("Attempt to serialize a kf::FieldRegion object with fFieldMode == EFieldMode::Orig");
308 }
309 }
310
312 template<class Archive>
313 void serialize(Archive& ar, const unsigned int version)
314 {
315 boost::serialization::split_member(ar, *this, version);
316 }
317
318 std::optional<detail::FieldBase<T, EFieldMode::Intrpl>> foFldIntrpl{std::nullopt};
319 std::optional<detail::FieldBase<T, EFieldMode::Orig>> foFldOrig{std::nullopt};
321 EFieldType fFieldType{EFieldType::Normal};
323 };
324
325
331 struct SliceRef {
332 double fHalfSizeX{defs::Undef<double>};
333 double fHalfSizeY{defs::Undef<double>};
334 double fRefZ{defs::Undef<double>};
335
340 SliceRef(double halfX, double halfY, double refZ) : fHalfSizeX(halfX), fHalfSizeY(halfY), fRefZ(refZ) {}
341
343 bool operator<(const SliceRef& r) const { return fRefZ < r.fRefZ; }
344 };
345
346 public:
348 FieldFactory() = default;
349
351 FieldFactory(const FieldFactory&) = default;
352
354 ~FieldFactory() = default;
355
358
363 void AddSliceReference(double halfSizeX, double halfSizeY, double refZ);
364
366 EFieldMode GetFieldMode() const { return fFieldMode; }
367
369 EFieldType GetFieldType() const { return fFieldType; }
370
373 template<typename T>
374 Field<T> MakeField() const;
375
377 void Reset() { *this = FieldFactory(); }
378
380 void ResetSliceReferences() { fSliceReferences.clear(); }
381
384 void SetFieldFunction(const FieldFn_t& fieldFn, EFieldType fldType)
385 {
386 fFieldFn = fieldFn;
387 fFieldType = fldType;
388 }
389
391 void SetFieldMode(EFieldMode fldMode) { fFieldMode = fldMode; }
392
395 void SetStep(double step = 2.5) { fTargetStep = step; }
396
401 void SetTarget(double x, double y, double z) { fTarget = {x, y, z}; }
402
403 private:
404 std::set<SliceRef> fSliceReferences;
405 FieldFn_t fFieldFn{defs::ZeroFieldFn};
406 double fTargetStep{2.5};
407 EFieldType fFieldType{EFieldType::Null};
408 EFieldMode fFieldMode{EFieldMode::Intrpl};
409
411 std::array<double, 3> fTarget{{defs::Undef<double>, defs::Undef<double>, defs::Undef<double>}};
412 };
413
414 // -------------------------------------------------------------------------------------------------------------------
415 //
416 template<typename T>
417 Field<T> FieldFactory::MakeField() const
418 {
419 auto field = Field<T>(fFieldMode, fFieldType);
420
421 // Check initialization
422 if (std::any_of(fTarget.begin(), fTarget.end(), [](double x) { return !utils::IsFinite(x); })) {
423 throw std::logic_error("FieldFactory::MakeField: target is undefined");
424 }
425 if (!fSliceReferences.size()) { // TODO: Remove requirement of slice references
426 throw std::logic_error("FieldFactory::MakeField: no slice references were provided");
427 }
428 if (!fFieldFn) {
429 throw std::logic_error("FieldFactory::CreateField: no field function is provided");
430 }
431
432 // Initialize the Field object
433 if (fFieldMode == EFieldMode::Orig) {
434 field.foFldOrig->SetFieldFunction(fFieldFn);
435 field.fPrimVertexField = FieldRegion<T>(fFieldType, fFieldFn);
436 for (const auto& sliceRef : fSliceReferences) {
437 field.foFldOrig->AddFieldSlice(sliceRef.fRefZ);
438 }
439 }
440 else if (fFieldMode == EFieldMode::Intrpl) { // A version with the interpolated field
441 for (const auto& sliceRef : fSliceReferences) {
442 field.foFldIntrpl->AddFieldSlice(
443 FieldSlice<T>(fFieldFn, sliceRef.fHalfSizeX, sliceRef.fHalfSizeY, sliceRef.fRefZ));
444 }
445 {
446 // PV field initialization
447 constexpr size_t nNodes = 3;
448 double z = fTarget[2];
449 std::array<FieldValue<T>, nNodes> fld;
450 std::array<T, nNodes> pos;
451 for (size_t iNode = 0; iNode < nNodes; ++iNode) {
452 pos[iNode] = utils::simd::Cast<double, T>(z);
453 fld[iNode] = GlobalField::GetFieldValue<double>(fFieldFn, fTarget[0], fTarget[1], z);
454 z += fTargetStep;
455 }
456 field.fPrimVertexField = FieldRegion<T>(fld[0], pos[0], fld[1], pos[1], fld[2], pos[2]);
457 // TODO: Provide alternative method for Orig
458 }
459 }
460 return field;
461 }
462} // namespace cbm::algo::kf
std::string ToString(ECbmModuleId modId)
Definition CbmDefs.cxx:70
Common constant definitions for the Kalman Filter library.
Magnetic flux density interpolation along the track vs. z-coordinate (header)
A class for a magnetic field approximation on a transverse plane (source)
A helper class to instantiate a Field object.
Definition KfField.h:328
void SetFieldMode(EFieldMode fldMode)
Sets field mode.
Definition KfField.h:391
FieldFactory()=default
Default constructor.
void SetStep(double step=2.5)
Sets a step for the primary vertex field region estimation.
Definition KfField.h:395
void ResetSliceReferences()
Resets slicer references.
Definition KfField.h:380
void SetTarget(double x, double y, double z)
Sets target.
Definition KfField.h:401
void SetFieldFunction(const FieldFn_t &fieldFn, EFieldType fldType)
Sets magnetic field function.
Definition KfField.h:384
FieldFactory & operator=(const FieldFactory &)=default
Copy assignment operator.
void Reset()
Resets the instance.
Definition KfField.h:377
EFieldMode GetFieldMode() const
Gets field mode.
Definition KfField.h:366
~FieldFactory()=default
Destructor.
std::set< SliceRef > fSliceReferences
Set of slice references.
Definition KfField.h:404
FieldFactory(const FieldFactory &)=default
Copy constructor.
EFieldType GetFieldType() const
Gets field type.
Definition KfField.h:369
Magnetic field region, corresponding to a hit triplet.
A magnetic field approximation on the two-dimensional plane.
Magnetic flux density vector.
Magnetic field manager class.
Definition KfField.h:188
FieldValue< T > GetFieldValue(int sliceID, const T &x, const T &y) const
Creates field value object.
Definition KfField.h:243
void load(Archive &ar, const unsigned int)
Serialization load method.
Definition KfField.h:285
EFieldType fFieldType
Field type.
Definition KfField.h:321
void serialize(Archive &ar, const unsigned int version)
Serialization method.
Definition KfField.h:313
const FieldRegion< T > & GetPrimVertexField() const
Gets field region near primary vertex.
Definition KfField.h:253
Field()=default
Default constructor.
Field & operator=(const Field &other)
Copy assignment operator.
Definition KfField.h:227
FieldRegion< T > fPrimVertexField
Field region near primary vertex (constant field is assumed)
Definition KfField.h:320
FieldRegion< T > GetFieldRegion(const FieldValue< T > &b0, const T &z0, const FieldValue< T > &b1, const T &z1, const FieldValue< T > &b2, const T &z2) const
Makes field region object.
Definition KfField.h:263
~Field()=default
Destructor.
std::optional< detail::FieldBase< T, EFieldMode::Orig > > foFldOrig
Original field.
Definition KfField.h:319
EFieldMode fFieldMode
Field mode.
Definition KfField.h:322
EFieldType GetFieldType() const
Gets field type.
Definition KfField.h:250
Field(EFieldMode fldMode, EFieldType fldType)
Constructor.
Definition KfField.h:197
void save(Archive &ar, const unsigned int) const
Serialization save method.
Definition KfField.h:298
std::optional< detail::FieldBase< T, EFieldMode::Intrpl > > foFldIntrpl
Interpolated field.
Definition KfField.h:318
Field(const Field< I > &other)
Copy constructor.
Definition KfField.h:210
void AddFieldSlice(const FieldSlice< T > &fieldSlice)
Sets a field slice.
Definition KfField.h:142
int GetNofFieldSlices() const
Gets number of field slices in the instance.
Definition KfField.h:158
std::string ToString(int indentLevel, int verbose) const
String representation of the class.
const auto & GetFieldSlice(int sliceID) const
Gets field slice.
Definition KfField.h:146
void serialize(Archive &ar, const unsigned int)
Definition KfField.h:176
FieldBase(const FieldBase< I, EFieldMode::Intrpl > &other)
Copy constructor.
Definition KfField.h:123
void RemoveSlice(int iLayer)
Removes a field slice.
Definition KfField.h:162
FieldBase & operator=(const FieldBase &other)
Copy assignment operator.
Definition KfField.h:132
FieldValue< T > GetFieldValue(int sliceID, const T &x, const T &y) const
Creates field value object.
Definition KfField.h:152
FieldValue< T > GetFieldValue(int sliceID, const T &x, const T &y) const
Creates field value object.
Definition KfField.h:76
void AddFieldSlice(const T &fieldSliceZref)
Sets a field slice (z-ref)
Definition KfField.h:70
std::string ToString(int indentLevel, int verbose) const
String representation of the class.
int GetNofFieldSlices() const
Gets number of field slices in the instance.
Definition KfField.h:85
void RemoveSlice(int iLayer)
Removes a field slice.
Definition KfField.h:89
void SetFieldFunction(const FieldFn_t &fieldFn)
Sets magnetic field function.
Definition KfField.h:93
FieldBase(const FieldBase< I, EFieldMode::Orig > &other)
Copy constructor.
Definition KfField.h:50
FieldBase & operator=(const FieldBase &other)
Copy assignment operator.
Definition KfField.h:59
const FieldFn_t & GetFieldFunction() const
Gets field function.
Definition KfField.h:82
Data members of the Field class (primary template)
Definition KfField.h:32
EFieldMode
Enumiration for the magnetic field representation variants in the track fitting algorithm.
Definition KfDefs.h:27
@ Intrpl
Interpolated magnetic field.
@ Orig
Original magnetic field function.
EFieldType
Magnetic field type in different setup regions.
Definition KfDefs.h:37
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
Hash for CbmL1LinkKey.
A helper structure for field slices initialization.
Definition KfField.h:331
double fRefZ
Reference z-position of the slice [cm].
Definition KfField.h:334
SliceRef(double halfX, double halfY, double refZ)
Constructor.
Definition KfField.h:340
bool operator<(const SliceRef &r) const
Comparision operator.
Definition KfField.h:343