diff --git a/algo/kf/core/geo/KfField.cxx b/algo/kf/core/geo/KfField.cxx index 888971655eea6e73566e0a7f148e390000cdd79c..29ecaebb24bdef96f7d74d818b829b4238b0a4c6 100644 --- a/algo/kf/core/geo/KfField.cxx +++ b/algo/kf/core/geo/KfField.cxx @@ -20,34 +20,61 @@ using cbm::algo::kf::detail::FieldBase; // --------------------------------------------------------------------------------------------------------------------- // -template<typename T, EFieldMode FldMode> -std::string Field<T, FldMode>::ToString(int indentLevel, int verbose) const +template<typename T> +std::string FieldBase<T, EFieldMode::Intrpl>::ToString(int indentLevel, int verbose) const +{ + constexpr char IndentChar = '\t'; + std::stringstream msg; + std::string indent(indentLevel, IndentChar); + msg << indent << "Field slices:"; + for (int iSlice = 0; iSlice < GetNofFieldSlices(); ++iSlice) { + const auto& fldSlice = fvFieldSlices[iSlice]; + msg << indent << "\n - " << fldSlice.ToString(indentLevel + 1, verbose); + } + return msg.str(); +} + +// --------------------------------------------------------------------------------------------------------------------- +// +template<typename T> +std::string FieldBase<T, EFieldMode::Orig>::ToString(int indentLevel, int verbose) const +{ + constexpr char IndentChar = '\t'; + std::stringstream msg; + std::string indent(indentLevel, IndentChar); + msg << indent << "Original field function"; + msg << indent << "Field slice z-positions: "; + for (int iSlice = 0; iSlice < GetNofFieldSlices(); ++iSlice) { + msg << indent << "\n " << iSlice << ") " << fvFieldSliceZ[iSlice]; + } + return msg.str(); +} + +// --------------------------------------------------------------------------------------------------------------------- +// +template<typename T> +std::string Field<T>::ToString(int indentLevel, int verbose) const { constexpr char IndentChar = '\t'; std::stringstream msg; std::string indent(indentLevel, IndentChar); msg << indent << "Field near primary vertex:\n" << this->fPrimVertexField.ToString(indentLevel + 1, verbose) << '\n'; msg << indent << "Field type: " << static_cast<int>(this->fFieldType) << '\n'; - if constexpr (FldMode == EFieldMode::Orig) { - //msg << indent << "Original field function"; + msg << indent << "Field mode: " << static_cast<int>(this->fFieldMode) << '\n'; + if (fFieldMode == EFieldMode::Orig) { + msg << foFldOrig->ToString(indentLevel, verbose); } - else if constexpr (FldMode == EFieldMode::Intrpl) { - msg << indent << "Field slices:"; - for (const auto& fldSlice : this->fvFieldSlices) { - msg << indent << "\n - " << fldSlice.ToString(indentLevel + 1, verbose); - } + else if (fFieldMode == EFieldMode::Intrpl) { + msg << foFldIntrpl->ToString(indentLevel, verbose); } return msg.str(); } namespace cbm::algo::kf { - template class Field<float, EFieldMode::Orig>; - template class Field<float, EFieldMode::Intrpl>; - template class Field<double, EFieldMode::Orig>; - template class Field<double, EFieldMode::Intrpl>; - template class Field<fvec, EFieldMode::Orig>; - template class Field<fvec, EFieldMode::Intrpl>; + template class Field<float>; + template class Field<double>; + template class Field<fvec>; } // namespace cbm::algo::kf diff --git a/algo/kf/core/geo/KfField.h b/algo/kf/core/geo/KfField.h index c0bb840be05b85ad8df200e2a59f0130d3bdd63a..1e07c1afb20a1ca60fb63d3533c13a205b4f11e7 100644 --- a/algo/kf/core/geo/KfField.h +++ b/algo/kf/core/geo/KfField.h @@ -13,7 +13,11 @@ #include "KfFieldRegion.h" #include "KfFieldSlice.h" +#include <boost/serialization/access.hpp> +#include <boost/serialization/split_free.hpp> + #include <array> +#include <optional> #include <set> namespace cbm::algo::kf @@ -37,17 +41,6 @@ namespace cbm::algo::kf friend class FieldBase; public: - using FieldRegion_t = FieldRegion<T, EFieldMode::Orig>; - using FieldValue_t = FieldValue<T>; - - /// \brief Sets magnetic field function - /// \param fieldFn Magnetic field function (KF-format) - void SetFieldFunction(const FieldFn_t& fieldFn) { fFieldFn = fieldFn; } - - /// \brief Creates field region object - FieldRegion_t MakeFieldRegion() const { return FieldRegion_t(fFieldType, fFieldFn); } - - protected: /// \brief Default constructor FieldBase() = default; @@ -56,22 +49,56 @@ namespace cbm::algo::kf template<typename I> FieldBase(const FieldBase<I, EFieldMode::Orig>& other) : fFieldFn(other.fFieldFn) { + fvFieldSliceZ.reserve(other.fvFieldSliceZ.size()); + for (const auto& slice : other.fvFieldSliceZ) { + fvFieldSliceZ.emplace_back(utils::simd::Cast<I, T>(slice)); + } } /// \brief Copy assignment operator - FieldBase& operator=(const FieldBase& other) = default; + FieldBase& operator=(const FieldBase& other) + { + if (this != &other) { + fvFieldSliceZ = other.fvFieldSliceZ; + fFieldFn = other.fFieldFn; + } + return *this; + } - FieldFn_t fFieldFn{defs::ZeroFieldFn}; ///< Field function: (x,y,z) [cm] -> (Bx,By,Bz) [kG] - EFieldType fFieldType{EFieldType::Null}; ///< Field type + /// \brief Sets a field slice (z-ref) + /// \param fieldSliceZref Reference z-coordinate of a field slice + void AddFieldSlice(const T& fieldSliceZref) { fvFieldSliceZ.push_back(fieldSliceZref); } - private: - /// Serialization function - friend class boost::serialization::access; - template<class Archive> - void serialize(Archive& ar, const unsigned int) + /// \brief Creates field value object + /// \param sliceID Index of slice + /// \param x x-coordinate of the point [cm] + /// \param y y-coordinate of the point [cm] + FieldValue<T> GetFieldValue(int sliceID, const T& x, const T& y) const { - ar& fFieldType; + return GlobalField::GetFieldValue(fFieldFn, x, y, fvFieldSliceZ[sliceID]); } + + /// \brief Gets field function + const FieldFn_t& GetFieldFunction() const { return fFieldFn; } + + /// \brief Gets number of field slices in the instance + int GetNofFieldSlices() const { return fvFieldSliceZ.size(); } + + /// \brief Makes field region + FieldRegion<T> MakeFieldRegion(EFieldType fldType) const { return FieldRegion(fldType, fFieldFn); } + + /// \brief Sets magnetic field function + /// \param fieldFn Magnetic field function (KF-format) + void SetFieldFunction(const FieldFn_t& fieldFn) { fFieldFn = fieldFn; } + + /// \brief String representation of the class + /// \param indentLevel Indent level of the string output + /// \param verbose Verbosity level + std::string ToString(int indentLevel, int verbose) const; + + private: + std::vector<T> fvFieldSliceZ{}; ///< z-positions of field slices to emulate functionality + FieldFn_t fFieldFn{defs::ZeroFieldFn}; ///< Field function: (x,y,z) [cm] -> (Bx,By,Bz) [kG] }; @@ -86,8 +113,28 @@ namespace cbm::algo::kf using SlicesContainer_t = std::vector<FieldSlice<T>>; public: - using FieldRegion_t = FieldRegion<T, EFieldMode::Intrpl>; - using FieldValue_t = FieldValue<T>; + /// \brief Default constructor + FieldBase() = default; + + /// \brief Copy constructor + /// \tparam I Underlying floating type of the source + template<typename I> + FieldBase(const FieldBase<I, EFieldMode::Intrpl>& other) + { + fvFieldSlices.reserve(other.fvFieldSlices.size()); + for (const auto& slice : other.fvFieldSlices) { + fvFieldSlices.emplace_back(FieldSlice<T>(slice)); + } + } + + /// \brief Copy assignment operator + FieldBase& operator=(const FieldBase& other) + { + if (this != &other) { + fvFieldSlices = other.fvFieldSlices; + } + return *this; + } /// \brief Sets a field slice /// \param fieldSlice Field slice object @@ -97,7 +144,7 @@ namespace cbm::algo::kf /// \param sliceID Index of slice /// \param x x-coordinate of the point [cm] /// \param y y-coordinate of the point [cm] - FieldValue_t GetFieldValue(int sliceID, const T& x, const T& y) const + FieldValue<T> GetFieldValue(int sliceID, const T& x, const T& y) const { return fvFieldSlices[sliceID].GetFieldValue(x, y); } @@ -106,39 +153,26 @@ namespace cbm::algo::kf int GetNofFieldSlices() const { return fvFieldSlices.size(); } /// \brief Creates field region object + /// \brief fldType FieldType /// \param b0 Field value in the first node [kG] /// \param z0 First node z-coordinate [cm] /// \param b1 Field value in the first node [kG] /// \param z1 Second node z-coordinate [cm] /// \param b2 Field value in the first node [kG] /// \param z2 Third node z-coordinate [cm] - FieldRegion_t MakeFieldRegion(const FieldValue_t& b0, const T& z0, const FieldValue_t& b1, const T& z1, - const FieldValue_t& b2, const T& z2) const + FieldRegion<T> MakeFieldRegion(EFieldType fldType, const FieldValue<T>& b0, const T& z0, const FieldValue<T>& b1, + const T& z1, const FieldValue<T>& b2, const T& z2) const { - return FieldRegion_t(fFieldType, b0, z0, b1, z1, b2, z2); + return FieldRegion<T>(fldType, b0, z0, b1, z1, b2, z2); } - protected: - /// \brief Default constructor - FieldBase() = default; + /// \brief String representation of the class + /// \param indentLevel Indent level of the string output + /// \param verbose Verbosity level + std::string ToString(int indentLevel, int verbose) const; - /// \brief Copy constructor - /// \tparam I Underlying floating type of the source - template<typename I> - FieldBase(const FieldBase<I, EFieldMode::Intrpl>& other) - { - fvFieldSlices.clear(); - fvFieldSlices.reserve(other.fvFieldSlices.size()); - for (const auto& slice : other.fvFieldSlices) { - fvFieldSlices.emplace_back(FieldSlice<T>(slice)); - } - } - - /// \brief Copy assignment operator - FieldBase& operator=(const FieldBase& other) = default; - - SlicesContainer_t fvFieldSlices; ///< Array of field slices - EFieldType fFieldType{EFieldType::Null}; ///< Field type + protected: + SlicesContainer_t fvFieldSlices{}; ///< Array of field slices private: /// \brief Serialization function @@ -147,7 +181,6 @@ namespace cbm::algo::kf void serialize(Archive& ar, const unsigned int) { ar& fvFieldSlices; - ar& fFieldType; } }; } // namespace detail @@ -156,25 +189,39 @@ namespace cbm::algo::kf /// \class Field /// \brief Magnetic field manager class /// \tparam T Underlying floating point type (float/double/fvec) - template<typename T, EFieldMode FldMode> - class alignas(VcMemAlign) Field : public detail::FieldBase<T, FldMode> { - template<typename, EFieldMode> + template<typename T> + class alignas(VcMemAlign) Field { + template<typename> friend class Field; + friend class FieldFactory; + friend class boost::serialization::access; public: - static constexpr EFieldMode FieldType = FldMode; - - using FieldRegion_t = FieldRegion<T, FldMode>; - using Real_t = T; - - /// \brief Default constructor - Field() = default; + /// \brief Constructor + /// \param fldMode Field mode + Field(EFieldMode fldMode, EFieldType fldType) + : foFldIntrpl(fldMode == EFieldMode::Intrpl ? std::make_optional(detail::FieldBase<T, EFieldMode::Intrpl>()) + : std::nullopt) + , foFldOrig(fldMode == EFieldMode::Orig ? std::make_optional(detail::FieldBase<T, EFieldMode::Orig>()) + : std::nullopt) + , fPrimVertexField(FieldRegion<T>(fldMode, fldType)) + , fFieldType(EFieldType::Normal) + , fFieldMode(fldMode) + { + } /// \brief Copy constructor template<typename I> - Field(const Field<I, FldMode>& other) - : detail::FieldBase<T, FldMode>(other) - , fPrimVertexField(FieldRegion<I, FldMode>(other.fPrimVertexField)) + Field(const Field<I>& other) + : foFldIntrpl(other.foFldIntrpl.has_value() + ? std::make_optional(detail::FieldBase<T, EFieldMode::Intrpl>(*other.foFldIntrpl)) + : std::nullopt) + , foFldOrig(other.foFldOrig.has_value() + ? std::make_optional(detail::FieldBase<T, EFieldMode::Orig>(*other.foFldOrig)) + : std::nullopt) + , fPrimVertexField(FieldRegion<I>(other.fPrimVertexField)) + , fFieldType(other.fFieldType) + , fFieldMode(other.fFieldMode) { } @@ -182,24 +229,48 @@ namespace cbm::algo::kf ~Field() = default; /// \brief Copy assignment operator - Field& operator=(const Field& other) = default; + Field& operator=(const Field& other) + { + if (this != &other) { + fPrimVertexField = other.fPrimVertexField; + foFldIntrpl = other.foFldIntrpl; + foFldOrig = other.foFldOrig; + fFieldType = other.fFieldType; + fFieldMode = other.fFieldMode; + } + return *this; + } + + /// \brief Creates field value object + /// \param sliceID Index of slice + /// \param x x-coordinate of the point [cm] + /// \param y y-coordinate of the point [cm] + FieldValue<T> GetFieldValue(int sliceID, const T& x, const T& y) const + { + return fFieldMode == EFieldMode::Intrpl ? foFldIntrpl->GetFieldValue(sliceID, x, y) + : foFldOrig->GetFieldValue(sliceID, x, y); + } /// \brief Gets field type EFieldType GetFieldType() const { return this->fFieldType; } /// \brief Gets field region near primary vertex - const FieldRegion_t& GetPrimVertexField() const { return fPrimVertexField; } - - /// \brief Sets field type - /// \param fieldType Field type - // TODO: SZh 21.08.2024: - // The concept of the field type depending on the z-regions should be developed. At the moment the full setup can - // have either EFieldType::Null (mCBM), or something else (CBM). - void SetFieldType(EFieldType fieldType) { this->fFieldType = fieldType; } - - /// \brief Sets field region near primary vertex - /// \param fld Field region near vertex - void SetPrimVertexField(const FieldRegion_t& primVertexField) { fPrimVertexField = primVertexField; } + const FieldRegion<T>& GetPrimVertexField() const { return fPrimVertexField; } + + /// \brief Makes field region object + /// \param b0 Field value in the first node [kG] + /// \param z0 First node z-coordinate [cm] + /// \param b1 Field value in the first node [kG] + /// \param z1 Second node z-coordinate [cm] + /// \param b2 Field value in the first node [kG] + /// \param z2 Third node z-coordinate [cm] + /// \note Parameters b0-b2, z0-z2 are ignored, if fFieldMode == EFieldMode::Orig + 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 + { + return (fFieldMode == EFieldMode::Intrpl ? FieldRegion<T>(fFieldType, b0, z0, b1, z1, b2, z2) + : FieldRegion<T>(fFieldType, foFldOrig->GetFieldFunction())); + } /// \brief String representation of the class /// \param indentLevel Indent level of the string output @@ -207,16 +278,49 @@ namespace cbm::algo::kf std::string ToString(int indentLevel, int verbose) const; private: - /// \brief Serialization function - friend class boost::serialization::access; + /// \brief Default constructor + Field() = default; + + /// \brief Serialization load method + template<class Archive> + void load(Archive& ar, const unsigned int /*version*/) + { + auto field = detail::FieldBase<T, EFieldMode::Intrpl>{}; + ar >> field; + foFldIntrpl = std::make_optional(field); + ar >> fPrimVertexField; + ar >> fFieldType; + ar >> fFieldMode; + foFldOrig = std::nullopt; // Note: original field cannot be serialized + } + + /// \brief Serialization save method template<class Archive> - void serialize(Archive& ar, const unsigned int) + void save(Archive& ar, const unsigned int /*version*/) const { - ar& boost::serialization::base_object<detail::FieldBase<T, FldMode>>(*this); - ar& fPrimVertexField; + if (fFieldMode == EFieldMode::Intrpl) { + ar << (*foFldIntrpl); + ar << fPrimVertexField; + ar << fFieldType; + ar << fFieldMode; + } + else if (fFieldMode == EFieldMode::Orig) { + throw std::logic_error("Attempt to serialize a kf::FieldRegion object with fFieldMode == EFieldMode::Orig"); + } } - FieldRegion_t fPrimVertexField; ///< Field region near primary vertex (constant field is assumed) + /// \brief Serialization method + template<class Archive> + void serialize(Archive& ar, const unsigned int version) + { + boost::serialization::split_member(ar, *this, version); + } + + std::optional<detail::FieldBase<T, EFieldMode::Intrpl>> foFldIntrpl{std::nullopt}; ///< Interpolated field + std::optional<detail::FieldBase<T, EFieldMode::Orig>> foFldOrig{std::nullopt}; ///< Original field + FieldRegion<T> fPrimVertexField; ///< Field region near primary vertex (constant field is assumed) + EFieldType fFieldType{EFieldType::Normal}; ///< Field type + EFieldMode fFieldMode; ///< Field mode }; @@ -259,25 +363,34 @@ namespace cbm::algo::kf /// \param refZ Reference z-position of the slice [cm] void AddSliceReference(double halfSizeX, double halfSizeY, double refZ); + /// \brief Gets field mode + EFieldMode GetFieldMode() const { return fFieldMode; } + /// \brief Gets field type EFieldType GetFieldType() const { return fFieldType; } - /// \brief Create field manager - /// \tparam T Underlying floating-point data type - /// \tparam OrigField If orig field is used - template<typename T, EFieldMode FldMode> - Field<T, FldMode> MakeField() const; + /// \brief Create field + /// \tparam T Underlying floating-point data type + template<typename T> + Field<T> MakeField() const; /// \brief Resets the instance void Reset() { *this = FieldFactory(); } /// \brief Sets magnetic field function /// \param fieldFn Magnetic field function (KF-format) - void SetFieldFunction(const FieldFn_t& fieldFn) { fFieldFn = fieldFn; } + void SetFieldFunction(const FieldFn_t& fieldFn, EFieldType fldType) + { + fFieldFn = fieldFn; + fFieldType = fldType; + } - /// \brief Sets field type - /// \param fieldType Field type - void SetFieldType(EFieldType fieldType) { fFieldType = fieldType; } + /// \brief Sets field mode + void SetFieldMode(EFieldMode fldMode) { fFieldMode = fldMode; } + + /// \brief Sets a step for the primary vertex field region estimation + /// \param step A step between nodal points in z-axis direction [cm] + void SetStep(double step = 2.5) { fTargetStep = step; } /// \brief Sets target /// \param x x-coordinate of the target position [cm] @@ -285,15 +398,12 @@ namespace cbm::algo::kf /// \param z z-coordinate of the target position [cm] void SetTarget(double x, double y, double z) { fTarget = {x, y, z}; } - /// \brief Sets a step for the primary vertex field region estimation - /// \param step A step between nodal points in z-axis direction [cm] - void SetStep(double step = 2.5) { fTargetStep = step; } - private: std::set<SliceRef> fSliceReferences; ///< Set of slice references FieldFn_t fFieldFn{defs::ZeroFieldFn}; ///< Field function (x, y, z) [cm] -> (Bx, By, Bz) [kG] double fTargetStep{2.5}; ///< Step between nodal points for the primary vertex field estimation EFieldType fFieldType{EFieldType::Null}; ///< Field type + EFieldMode fFieldMode{EFieldMode::Intrpl}; ///< FieldMode /// \brief Target position std::array<double, 3> fTarget{{defs::Undef<double>, defs::Undef<double>, defs::Undef<double>}}; @@ -301,10 +411,10 @@ namespace cbm::algo::kf // ------------------------------------------------------------------------------------------------------------------- // - template<typename T, EFieldMode FldMode> - Field<T, FldMode> FieldFactory::MakeField() const + template<typename T> + Field<T> FieldFactory::MakeField() const { - auto field = Field<T, FldMode>{}; + auto field = Field<T>(fFieldMode, fFieldType); // Check initialization if (std::any_of(fTarget.begin(), fTarget.end(), [](double x) { return !utils::IsFinite(x); })) { @@ -318,14 +428,17 @@ namespace cbm::algo::kf } // Initialize the Field object - field.SetFieldType(fFieldType); - if constexpr (FldMode == EFieldMode::Orig) { - field.SetFieldFunction(fFieldFn); - field.SetPrimVertexField(field.MakeFieldRegion()); + if (fFieldMode == EFieldMode::Orig) { + field.foFldOrig->SetFieldFunction(fFieldFn); + field.fPrimVertexField = FieldRegion<T>(fFieldType, fFieldFn); + for (const auto& sliceRef : fSliceReferences) { + field.foFldOrig->AddFieldSlice(sliceRef.fRefZ); + } } - else if constexpr (FldMode == EFieldMode::Intrpl) { // A version with the interpolated field + else if (fFieldMode == EFieldMode::Intrpl) { // A version with the interpolated field for (const auto& sliceRef : fSliceReferences) { - field.AddFieldSlice(FieldSlice<T>(fFieldFn, sliceRef.fHalfSizeX, sliceRef.fHalfSizeY, sliceRef.fRefZ)); + field.foFldIntrpl->AddFieldSlice( + FieldSlice<T>(fFieldFn, sliceRef.fHalfSizeX, sliceRef.fHalfSizeY, sliceRef.fRefZ)); } { // PV field initialization @@ -338,7 +451,8 @@ namespace cbm::algo::kf fld[iNode] = GlobalField::GetFieldValue<double>(fFieldFn, fTarget[0], fTarget[1], z); z += fTargetStep; } - field.SetPrimVertexField(field.MakeFieldRegion(fld[0], pos[0], fld[1], pos[1], fld[2], pos[2])); + field.fPrimVertexField = FieldRegion<T>(fFieldType, fld[0], pos[0], fld[1], pos[1], fld[2], pos[2]); + // TODO: Provide alternative method for Orig } } return field; diff --git a/algo/kf/core/geo/KfFieldRegion.cxx b/algo/kf/core/geo/KfFieldRegion.cxx index fc892352463994563cd665a5adca6256732a1b8d..1f824eef447606d404b5c0d695d398520b222c81 100644 --- a/algo/kf/core/geo/KfFieldRegion.cxx +++ b/algo/kf/core/geo/KfFieldRegion.cxx @@ -55,6 +55,20 @@ void FieldRegionBase<T, EFieldMode::Intrpl>::Set(const FieldValue<T>& b0, const } } +// --------------------------------------------------------------------------------------------------------------------- +// +template<typename T> +FieldValue<T> FieldRegionBase<T, EFieldMode::Intrpl>::Get(const T& x, const T& y, const T& z) const +{ + if (defs::dbg::ForceOriginalField) { + return GlobalField::GetFieldValue(GlobalField::gOriginalField, x, y, z); + } + auto dz = z - this->fZfirst; + return FieldValue<T>{this->fCoeff[0][0] + dz * (this->fCoeff[0][1] + dz * this->fCoeff[0][2]), + this->fCoeff[1][0] + dz * (this->fCoeff[1][1] + dz * this->fCoeff[1][2]), + this->fCoeff[2][0] + dz * (this->fCoeff[2][1] + dz * this->fCoeff[2][2])}; +} + // --------------------------------------------------------------------------------------------------------------------- // template<typename T> @@ -70,66 +84,94 @@ void FieldRegionBase<T, EFieldMode::Intrpl>::Shift(const T& z) fZfirst = z; } +// --------------------------------------------------------------------------------------------------------------------- +// +template<typename T> +std::string FieldRegionBase<T, EFieldMode::Intrpl>::ToString(int indentLevel, int) const +{ + constexpr char IndentChar = '\t'; + std::stringstream msg; + std::string indent(indentLevel, IndentChar); + using fmt::format; + auto Cnv = [&](const auto& val) { return utils::simd::Cast<T, Literal_t<T>>(val); }; // alias for the conversion fn + const auto& coeff = this->fCoeff; + msg << indent << format("Field Region: dz = z - ({})", Cnv(this->fZfirst)); + msg << '\n' + << indent << IndentChar + << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[0][0]), Cnv(coeff[0][1]), Cnv(coeff[0][2])); + msg << '\n' + << indent << IndentChar + << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[1][0]), Cnv(coeff[1][1]), Cnv(coeff[1][2])); + msg << '\n' + << indent << IndentChar + << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[2][0]), Cnv(coeff[2][1]), Cnv(coeff[2][2])); + if constexpr (defs::dbg::ForceOriginalField) { + msg << indent << "\nWARNING: the defs::dbg::ForceOriginalField is enabled, so the magnetic field interpolation " + << indent + << "\nis replaced with the global magnetic function for debugging purposes. If you see this message and are " + << indent + << "\nnot sure, what is going on, please set the defs::dbg::ForceOriginalField to false and re-run the routine"; + } + return msg.str(); +} + +// --------------------------------------------------------------------------------------------------------------------- +// +template<typename T> +std::string FieldRegionBase<T, EFieldMode::Orig>::ToString(int indentLevel, int) const +{ + constexpr char IndentChar = '\t'; + std::stringstream msg; + std::string indent(indentLevel, IndentChar); + msg << indent << "Field region: created from the original field function"; + return msg.str(); +} + + namespace cbm::algo::kf::detail { template class FieldRegionBase<float, EFieldMode::Intrpl>; template class FieldRegionBase<double, EFieldMode::Intrpl>; template class FieldRegionBase<fvec, EFieldMode::Intrpl>; + template class FieldRegionBase<float, EFieldMode::Orig>; + template class FieldRegionBase<double, EFieldMode::Orig>; + template class FieldRegionBase<fvec, EFieldMode::Orig>; } // namespace cbm::algo::kf::detail + // --------------------------------------------------------------------------------------------------------------------- // -template<typename T, EFieldMode FldMode> -FieldValue<T> FieldRegion<T, FldMode>::Get(const T& x, const T& y, const T& z) const +template<typename T> +void FieldRegion<T>::Set(const FieldValue<T>& b0, const T& z0, const FieldValue<T>& b1, const T& z1, + const FieldValue<T>& b2, const T& z2) { - if constexpr (FldMode == EFieldMode::Intrpl) { - if constexpr (defs::dbg::ForceOriginalField) { - return GlobalField::GetFieldValue(GlobalField::gOriginalField, x, y, z); - } - auto dz = z - this->fZfirst; - return FieldValue<T>{this->fCoeff[0][0] + dz * (this->fCoeff[0][1] + dz * this->fCoeff[0][2]), - this->fCoeff[1][0] + dz * (this->fCoeff[1][1] + dz * this->fCoeff[1][2]), - this->fCoeff[2][0] + dz * (this->fCoeff[2][1] + dz * this->fCoeff[2][2])}; + if (fFieldMode == EFieldMode::Intrpl) { + foFldIntrpl->Set(b0, z0, b1, z1, b2, z2); } - else if constexpr (FldMode == EFieldMode::Orig) { - return GlobalField::GetFieldValue(this->fFieldFn, x, y, z); +} + +// --------------------------------------------------------------------------------------------------------------------- +// +template<typename T> +void FieldRegion<T>::Shift(const T& z) +{ + if (fFieldMode == EFieldMode::Intrpl) { + foFldIntrpl->Shift(z); } } // --------------------------------------------------------------------------------------------------------------------- // -template<typename T, EFieldMode FldMode> -std::string FieldRegion<T, FldMode>::ToString(int indentLevel, int) const +template<typename T> +std::string FieldRegion<T>::ToString(int indentLevel, int) const { constexpr char IndentChar = '\t'; std::stringstream msg; std::string indent(indentLevel, IndentChar); - if constexpr (FldMode == EFieldMode::Intrpl) { - using fmt::format; - auto Cnv = [&](const auto& val) { return utils::simd::Cast<T, Literal_t<T>>(val); }; // alias for the conversion fn - const auto& coeff = this->fCoeff; - msg << indent << format("Field Region: dz = z - ({})", Cnv(this->fZfirst)); - msg << '\n' - << indent << IndentChar - << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[0][0]), Cnv(coeff[0][1]), Cnv(coeff[0][2])); - msg << '\n' - << indent << IndentChar - << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[1][0]), Cnv(coeff[1][1]), Cnv(coeff[1][2])); - msg << '\n' - << indent << IndentChar - << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[2][0]), Cnv(coeff[2][1]), Cnv(coeff[2][2])); - if constexpr (defs::dbg::ForceOriginalField) { - msg - << indent << "\nWARNING: the defs::dbg::ForceOriginalField is enabled, so the magnetic field interpolation " - << indent - << "\nis replaced with the global magnetic function for debugging purposes. If you see this message and are " - << indent - << "\nnot sure, what is going on, please set the defs::dbg::ForceOriginalField to false and re-run the routine"; - } - } - else if constexpr (FldMode == EFieldMode::Orig) { - msg << indent << "Field region: created from the original field function"; - } + msg << indent << "FieldType: " << static_cast<int>(fFieldType) << '\n'; + msg << indent << "FieldMode: " << static_cast<int>(fFieldMode) << '\n'; + msg << indent + << (fFieldMode == EFieldMode::Intrpl ? foFldIntrpl->ToString(indentLevel) : foFldOrig->ToString(indentLevel)); return msg.str(); } @@ -147,10 +189,7 @@ std::tuple<double, double, double> GlobalField::UndefField(double, double, doubl namespace cbm::algo::kf { - template class FieldRegion<float, EFieldMode::Orig>; - template class FieldRegion<float, EFieldMode::Intrpl>; - template class FieldRegion<double, EFieldMode::Orig>; - template class FieldRegion<double, EFieldMode::Intrpl>; - template class FieldRegion<fvec, EFieldMode::Orig>; - template class FieldRegion<fvec, EFieldMode::Intrpl>; + template class FieldRegion<float>; + template class FieldRegion<double>; + template class FieldRegion<fvec>; } // namespace cbm::algo::kf diff --git a/algo/kf/core/geo/KfFieldRegion.h b/algo/kf/core/geo/KfFieldRegion.h index 9e8ceec5e44f2744a66fc03b480992f8c8a52ceb..e31f1ce5af3655dba7f2c0bd1611bfbc3bd07b97 100644 --- a/algo/kf/core/geo/KfFieldRegion.h +++ b/algo/kf/core/geo/KfFieldRegion.h @@ -17,9 +17,11 @@ #include <boost/serialization/access.hpp> #include <boost/serialization/array.hpp> -#include <boost/serialization/base_object.hpp> +#include <boost/serialization/optional.hpp> +#include <boost/serialization/split_free.hpp> #include <array> +#include <optional> #include <string> #include <type_traits> @@ -63,7 +65,6 @@ namespace cbm::algo::kf class alignas(VcMemAlign) FieldRegionBase { }; - /// \class FieldRegionBase<T, EFieldMode::Orig> /// \brief Data members and specific methods of the FieldRegion with the original magnetic field /// \tparam T Underlying floating point type (float/double/fvec) @@ -73,8 +74,6 @@ namespace cbm::algo::kf friend class FieldRegionBase; public: - using FieldValue_t = FieldValue<T>; - /// \brief Default constructor FieldRegionBase() = default; @@ -94,16 +93,23 @@ namespace cbm::algo::kf /// \brief Copy assignment operator FieldRegionBase& operator=(const FieldRegionBase& other) = default; - protected: - FieldFn_t fFieldFn{defs::ZeroFieldFn}; ///< Field function: (x,y,z) [cm] -> (Bx,By,Bz) [kG] - - private: - /// \brief Serialization function - friend class boost::serialization::access; - template<class Archive> - void serialize(Archive&, const unsigned int) + /// \brief Gets the field value in a spatial point on the track + /// \param x x-coordinate of the point [cm] + /// \param y y-coordinate of the point [cm] + /// \param z z-coordinate of the point [cm] + /// \note The x and y coordinates are ignored, if the interpolated field is used + FieldValue<T> Get(const T& x, const T& y, const T& z) const { + return GlobalField::GetFieldValue(fFieldFn, x, y, z); } + + /// \brief String representation of the class content + /// \param intdentLevel Indent level + /// \param verbose Verbosity level + std::string ToString(int indentLevel = 0, int verbose = 1) const; + + protected: + FieldFn_t fFieldFn{defs::ZeroFieldFn}; ///< Field function: (x,y,z) [cm] -> (Bx,By,Bz) [kG] }; @@ -154,6 +160,12 @@ namespace cbm::algo::kf /// \brief Copy assignment operator FieldRegionBase& operator=(const FieldRegionBase& other) = default; + /// \brief Gets the field value in a spatial point on the track + /// \param x x-coordinate of the point [cm] + /// \param y y-coordinate of the point [cm] + /// \param z z-coordinate of the point [cm] + FieldValue<T> Get(const T& x, const T& y, const T& z) const; + /// \brief Gets the first z-coordinate of the interpolation const T& GetZfirst() const { return fZfirst; } @@ -172,6 +184,11 @@ namespace cbm::algo::kf /// \param z new z-coordinate [cm] void Shift(const T& z); + /// \brief String representation of the class content + /// \param intdentLevel Indent level + /// \param verbose Verbosity level + std::string ToString(int indentLevel = 0, int verbose = 1) const; + protected: CoeffArray_t fCoeff{{T(0.)}}; ///< Approximation coefficients T fZfirst{Literal_t<T>()}; ///< Reference z-coordinate of the field region @@ -192,35 +209,56 @@ namespace cbm::algo::kf /// \class FieldRegion /// \brief Magnetic field region, corresponding to a hit triplet /// \tparam T Underlying data-type - /// \tparam FldMode Field type - template<typename T, EFieldMode FldMode> - class alignas(VcMemAlign) FieldRegion : public detail::FieldRegionBase<T, FldMode> { - template<typename, EFieldMode> + template<typename T> + class alignas(VcMemAlign) FieldRegion { + template<typename> friend class FieldRegion; public: - static constexpr EFieldMode FieldType = FldMode; - - using FieldValue_t = FieldValue<T>; - using Real_t = T; - - /// \brief Default constructor - FieldRegion() = default; + /// \brief Constructor of the generic field + FieldRegion(EFieldMode fldMode, EFieldType fldType) + : foFldIntrpl(fldMode == EFieldMode::Intrpl ? std::make_optional<detail::FieldRegionBase<T, EFieldMode::Intrpl>>() + : std::nullopt) + , foFldOrig(fldMode == EFieldMode::Orig ? std::make_optional<detail::FieldRegionBase<T, EFieldMode::Orig>>() + : std::nullopt) + , fFieldType(fldType) + , fFieldMode(fldMode) + { + } /// \brief Copy constructor /// \tparam I Underlying floating point type of the source template<typename I> - FieldRegion(const FieldRegion<I, FldMode>& other) : detail::FieldRegionBase<T, FldMode>(other) + FieldRegion(const FieldRegion<I>& other) + : foFldIntrpl(other.foFldIntrpl.has_value() + ? std::make_optional(detail::FieldRegionBase<T, EFieldMode::Intrpl>(*other.foFldIntrpl)) + : std::nullopt) + , foFldOrig(other.foFldOrig.has_value() + ? std::make_optional(detail::FieldRegionBase<T, EFieldMode::Orig>(*other.foFldOrig)) + : std::nullopt) + , fFieldType(other.fFieldType) + , fFieldMode(other.fFieldMode) { } - /// \brief Constructor from the arguments + /// \brief Constructor for the interpolated field region /// \param fieldType Type of the field - /// \param args Arguments, which have to be passed to the base class constructors - template<typename... Args> - FieldRegion(EFieldType fieldType, Args... args) - : detail::FieldRegionBase<T, FldMode>(args...) + FieldRegion(EFieldType fieldType, const FieldValue<T>& b0, const T& z0, const FieldValue<T>& b1, const T& z1, + const FieldValue<T>& b2, const T& z2) + : foFldIntrpl(std::make_optional<detail::FieldRegionBase<T, EFieldMode::Intrpl>>(b0, z0, b1, z1, b2, z2)) + , foFldOrig(std::nullopt) , fFieldType(fieldType) + , fFieldMode(EFieldMode::Intrpl) + { + } + + /// \brief Constructor for the field region with the original field function + /// \param fieldType Type of the field + FieldRegion(EFieldType fieldType, const FieldFn_t& fieldFn) + : foFldIntrpl(std::nullopt) + , foFldOrig(std::make_optional<detail::FieldRegionBase<T, EFieldMode::Orig>>(fieldFn)) + , fFieldType(fieldType) + , fFieldMode(EFieldMode::Orig) { } @@ -235,28 +273,83 @@ namespace cbm::algo::kf /// \param y y-coordinate of the point [cm] /// \param z z-coordinate of the point [cm] /// \note The x and y coordinates are ignored, if the interpolated field is used - FieldValue_t Get(const T& x, const T& y, const T& z) const; + FieldValue<T> Get(const T& x, const T& y, const T& z) const + { + return fFieldMode == EFieldMode::Intrpl ? foFldIntrpl->Get(x, y, z) : foFldOrig->Get(x, y, z); + } + + /// \brief Gets field mode + EFieldMode GetFieldMode() const { return fFieldMode; } /// \brief Gets the field type EFieldType GetFieldType() const { return fFieldType; } + /// \brief Interpolates the field by three nodal points with the second order polynomial + /// \note The interpolation is carried out vs. z-coordinates of the space points of the field values + /// \param b0 Field value at z0 [kG] + /// \param z0 First nodal point in z-axis direction [cm] + /// \param b1 Field value at z1 [kG] + /// \param z1 Second nodal point in z-axis direction [cm] + /// \param b2 Field value at z2 [kG] + /// \param z2 Third nodal point in z-axis direction [cm] + void Set(const FieldValue<T>& b0, const T& z0, const FieldValue<T>& b1, const T& z1, const FieldValue<T>& b2, + const T& z2); + + /// \brief Sets the field type + void SetFieldType(EFieldType fldType) { fFieldType = fldType; } + + /// \brief Shifts the coefficients to another first z-coordinate + /// \param z new z-coordinate [cm] + void Shift(const T& z); + /// \brief String representation of the class content /// \param intdentLevel Indent level /// \param verbose Verbosity level std::string ToString(int indentLevel = 0, int verbose = 1) const; private: - /// \brief Serialization method friend class boost::serialization::access; + + /// \brief Default constructor + FieldRegion() = default; + + /// \brief Serialization load method template<class Archive> - void serialize(Archive& ar, const unsigned int) + void load(Archive& ar, const unsigned int /*version*/) { - using boost::serialization::base_object; - ar& base_object<detail::FieldRegionBase<T, FldMode>>(*this); - ar& fFieldType; + auto field = detail::FieldRegionBase<T, EFieldMode::Intrpl>{}; + ar >> field; + foFldIntrpl = std::make_optional(field); + ar >> fFieldType; + ar >> fFieldMode; + foFldOrig = std::nullopt; // Note: original field cannot be serialized } + /// \brief Serialization save method + template<class Archive> + void save(Archive& ar, const unsigned int /*version*/) const + { + if (fFieldMode == EFieldMode::Intrpl) { + ar << (*foFldIntrpl); + ar << fFieldType; + ar << fFieldMode; + } + else if (fFieldMode == EFieldMode::Orig) { + throw std::logic_error("Attempt to serialize a kf::FieldRegion object with fFieldMode == EFieldMode::Orig"); + } + } + + /// \brief Serialization method + template<class Archive> + void serialize(Archive& ar, const unsigned int version) + { + boost::serialization::split_member(ar, *this, version); + } + + std::optional<detail::FieldRegionBase<T, EFieldMode::Intrpl>> foFldIntrpl{std::nullopt}; + std::optional<detail::FieldRegionBase<T, EFieldMode::Orig>> foFldOrig{std::nullopt}; EFieldType fFieldType{EFieldType::Null}; ///< Field type in a given region + EFieldMode fFieldMode; ///< Field mode }; @@ -265,8 +358,8 @@ namespace cbm::algo::kf template<typename T> inline FieldValue<T> GlobalField::GetFieldValue(const FieldFn_t& fieldFn, const T& x, const T& y, const T& z) { - using utils::simd::Cast; FieldValue<T> B; + using utils::simd::Cast; for (size_t i = 0; i < utils::simd::Size<T>(); ++i) { auto [bx, by, bz] = fieldFn(Cast<T, double>(x, i), Cast<T, double>(y, i), Cast<T, double>(z, i)); B.SetSimdEntry(bx, by, bz, i); diff --git a/algo/kf/core/geo/KfFieldSlice.h b/algo/kf/core/geo/KfFieldSlice.h index 295051c2423da08d86d1fe574f0b18f876ea65bc..6be46bad7ce19241551da0f348dea12fecc890e7 100644 --- a/algo/kf/core/geo/KfFieldSlice.h +++ b/algo/kf/core/geo/KfFieldSlice.h @@ -90,7 +90,7 @@ namespace cbm::algo::kf } /// \brief Gets reference z-coordinate of the slice [cm] - const T& GetZref() { return fZref; } + const T& GetZref() const { return fZref; } /// \brief String representation of the class content /// \param intdentLevel Indent level diff --git a/algo/kf/core/geo/KfSetup.cxx b/algo/kf/core/geo/KfSetup.cxx index ec8862775685506164e4325da359e7d930ba9096..dd4fa54a174614b424df709588116575d3458434 100644 --- a/algo/kf/core/geo/KfSetup.cxx +++ b/algo/kf/core/geo/KfSetup.cxx @@ -31,13 +31,7 @@ std::string Setup<T>::ToString(int verbosity, int indentLevel) const for (const auto& layer : fvMaterialLayers) { msg << layer.ToString(indentLevel + 1, verbosity) << '\n'; } - msg << indent << "\nINTERPOLATED MAGNETIC FIELD:\n" << fIntrplField.ToString(indentLevel + 1, verbosity); - if (foOrigField) { - msg << indent << "\nORIGINAL MAGNETIC FIELD:\n" << foOrigField->ToString(indentLevel + 1, verbosity); - } - else { - msg << indent << "\nORIGINAL MANGETIC FIELD: not provided"; - } + msg << indent << "\nMAGNETIC FIELD:\n" << fField.ToString(indentLevel + 1, verbosity); } return msg.str(); } diff --git a/algo/kf/core/geo/KfSetup.h b/algo/kf/core/geo/KfSetup.h index 75829aa2e64b4f53d9b0a2938a60d1a9c175e7c4..2f1a8a3d846024352d9ca5b04fe495ba5554c17f 100644 --- a/algo/kf/core/geo/KfSetup.h +++ b/algo/kf/core/geo/KfSetup.h @@ -37,8 +37,14 @@ namespace cbm::algo::kf public: - /// \brief Default constructor - Setup() = default; + /// \brief Constructor + /// \param fldMode Field mode + Setup(EFieldMode fldMode) + : fvMaterialLayers({}) + , fField(Field<T>(fldMode, EFieldType::Normal)) + , fTarget(Target<T>()) + { + } /// \brief Destructor ~Setup() = default; @@ -48,8 +54,7 @@ namespace cbm::algo::kf template<typename I> Setup(const Setup<I>& other) : fvMaterialLayers(other.fvMaterialLayers) - , fIntrplField(other.fIntrplField) - , foOrigField(other.foOrigField.has_value() ? std::make_optional(*other.foOrigField) : std::nullopt) + , fField(other.fField) , fTarget(other.fTarget) { } @@ -68,10 +73,8 @@ namespace cbm::algo::kf void AddMaterial(const MaterialMap& map) { fvMaterialLayers.emplace_back(map); } /// \brief Makes an instance of the field depending on the template parameter - /// \tparam FldMode Field mode of the returned instance /// \throw std::logic_error If the particular field member is undefined (nullopt) - template<EFieldMode FldMode> - const Field<T, FldMode>& GetField() const; + const Field<T>& GetField() const { return fField; } /// \brief Gets material layer /// \param iLayer Index of layer @@ -89,8 +92,7 @@ namespace cbm::algo::kf std::string ToString(int verbosity = 1, int indentLevel = 0) const; /// \brief Sets field - template<EFieldMode FldMode> - void SetField(const Field<double, FldMode>& field); + void SetField(const Field<double>& field) { fField = Field<T>(field); } /// \brief Sets target (moves from the source) /// \param target Target instance @@ -102,22 +104,16 @@ namespace cbm::algo::kf void load(Archive& ar, const unsigned int /*version*/) { ar >> fvMaterialLayers; - ar >> fvMaterialLayerIds; ar >> fTarget; - ar >> fIntrplField; - foOrigField = std::nullopt; - - // NOTE: The original field cannot be serialized, because it contains a pointer to the external magnetic field - // function. + ar >> fField; } template<class Archive> void save(Archive& ar, const unsigned int /*version*/) const { ar << fvMaterialLayers; - ar << fvMaterialLayerIds; ar << fTarget; - ar << fIntrplField; + ar << fField; } template<class Archive> @@ -127,45 +123,8 @@ namespace cbm::algo::kf } std::vector<MaterialMap> fvMaterialLayers = {}; ///< Container of the material maps - std::vector<int> fvMaterialLayerIds = {}; ///< Map of the layer ids: original -> actual - Field<T, EFieldMode::Intrpl> fIntrplField; ///< Interpolated field (NOTE: maybe make optional) - std::optional<Field<T, EFieldMode::Orig>> foOrigField{std::nullopt}; ///< Optional original field - Target<T> fTarget; ///< Target layer + Field<T> fField; ///< Interpolated field (NOTE: maybe make optional) + Target<T> fTarget; ///< Target layer }; - // ------------------------------------------------------------------------------------------------------------------- - // - template<typename T> - template<EFieldMode FldMode> - const Field<T, FldMode>& Setup<T>::GetField() const - { - if constexpr (FldMode == EFieldMode::Orig) { - if (foOrigField) { - return *foOrigField; - } - else { - throw std::logic_error("kf::Setup::MakeField(): attempt to create a Field instance in the original field mode " - "in the unsuitable scenario (for example, in the online reconstruction code). Please, " - "use the interpolated magnetic field calling Setup::MakeField<T, EFieldMode::Intrpl>() " - "instead."); - } - } - else if constexpr (FldMode == EFieldMode::Intrpl) { - return fIntrplField; - } - } - - // ------------------------------------------------------------------------------------------------------------------- - // - template<typename T> - template<EFieldMode FldMode> - void Setup<T>::SetField(const Field<double, FldMode>& field) - { - if constexpr (FldMode == EFieldMode::Intrpl) { - fIntrplField = field; - } - else if constexpr (FldMode == EFieldMode::Orig) { - foOrigField = std::make_optional(field); - } - } } // namespace cbm::algo::kf diff --git a/algo/kf/core/geo/KfSetupInitializer.h b/algo/kf/core/geo/KfSetupInitializer.h index 7fb84e9f6bd413d0da7eafe3c2393eabf79dff46..1f2f51e51c2f01ed03a7fb3a90da3a9778c94a61 100644 --- a/algo/kf/core/geo/KfSetupInitializer.h +++ b/algo/kf/core/geo/KfSetupInitializer.h @@ -65,20 +65,20 @@ namespace cbm::algo::kf virtual bool InitProperties() { return false; } /// \brief Creates a setup instance - /// \param bProvideOrigField Flag: true - defines optional variable of the original field template<typename T> - Setup<T> MakeSetup(bool bProvideOrigField = true) const; + Setup<T> MakeSetup() const; /// \brief Resets the instance void Reset(); /// \brief Sets magnetic field function + /// \param fieldMode Magnetic field mode: /// \param fieldFn Magnetic field function /// \param fieldType Magnetic field type - void SetFieldFunction(const FieldFn_t& fieldFn, EFieldType fieldType) + void SetFieldProperty(EFieldMode fieldMode, const FieldFn_t& fieldFn, EFieldType fieldType) { - fFieldFactory.SetFieldFunction(fieldFn); - fFieldFactory.SetFieldType(fieldType); + fFieldFactory.SetFieldFunction(fieldFn, fieldType); + fFieldFactory.SetFieldMode(fieldMode); } /// \brief Sets target initialization properties @@ -120,17 +120,14 @@ namespace cbm::algo::kf // --------------------------------------------------------------------------------------------------------------------- // template<typename T> - Setup<T> SetupInitializer::MakeSetup(bool bProvideOrigField) const + Setup<T> SetupInitializer::MakeSetup() const { - Setup<T> setup; + Setup<T> setup(fFieldFactory.GetFieldMode()); // Target initialization setup.SetTarget(fTarget); // Field initialization - setup.SetField(fFieldFactory.MakeField<double, EFieldMode::Intrpl>()); - if (bProvideOrigField) { - setup.SetField(fFieldFactory.MakeField<double, EFieldMode::Orig>()); - } + setup.SetField(fFieldFactory.MakeField<double>()); // Material layers initialization for (const auto& material : fMaterialLayers) { @@ -145,7 +142,7 @@ namespace cbm::algo::kf template<typename T> Setup<T> SetupInitializer::Load(const std::string& fileName) { - Setup<double> setup; + Setup<double> setup(EFieldMode::Intrpl); std::ifstream ifs(fileName, std::ios::binary); if (!ifs) { std::stringstream msg; diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx index d8e95834592e437f43167b4676b04ee25200e423..09568aa6a63e73ceb9afcd13a15e11dc4c1dc795 100644 --- a/reco/L1/CbmL1.cxx +++ b/reco/L1/CbmL1.cxx @@ -28,6 +28,7 @@ #include "CbmStsTrackingInterface.h" #include "CbmTofTrackingInterface.h" #include "CbmTrdTrackingInterface.h" +#include "KfDefs.h" #include <boost/filesystem.hpp> // TODO: include of CbmSetup.h creates problems on Mac @@ -544,7 +545,7 @@ try { auto pSetupInitializer = std::make_unique<TrackingSetupInitializer>(); pSetupInitializer->Use(fUseMVD, fUseSTS, fUseMUCH, fUseTRD, fUseTOF); pSetupInitializer->InitProperties(); - auto trackerSetup = pSetupInitializer->MakeSetup<double>(/*provide original field*/ true); + auto trackerSetup = pSetupInitializer->MakeSetup<double>(); LOG(info) << "!!!!\n!!!!\n!!!!\n!!!! KF SETUP:\n" << trackerSetup.ToString(0) << "\n!!!!\n!!!!\n!!!!"; // Storing setup @@ -558,12 +559,13 @@ try { { // TEST: magnetic field - const auto& fld = trackerSetupVec.GetField<cbm::algo::kf::EFieldMode::Intrpl>(); + const auto& fld = trackerSetupVec.GetField(); struct Node { int iSt; fvec x; fvec y; }; + { Node n{.iSt = 1, .x = 2.3, .y = 1.2}; auto kfFldValue = fld.GetFieldValue(n.iSt, n.x, n.y); @@ -583,6 +585,27 @@ try { LOG(info) << "B: " << kfFldValue.ToString() << " --- " << caFldValue.ToString(); } + // TEST: field region building + { + using cbm::algo::kf::EFieldType; + fvec x = 1.2; + fvec y = 1.3; + fvec z0 = -32.; + fvec z1 = -28.; + fvec z2 = -24.; + auto kfFldVal_0 = fld.GetFieldValue(0, x, y); + auto kfFldVal_1 = fld.GetFieldValue(1, x, y); + auto kfFldVal_2 = fld.GetFieldValue(2, x, y); + auto kfFldReg = fld.GetFieldRegion(kfFldVal_0, z0, kfFldVal_1, z1, kfFldVal_2, z2); + auto caFldVal_0 = fpParameters->GetStation(0).fieldSlice.GetFieldValue(x, y); + auto caFldVal_1 = fpParameters->GetStation(1).fieldSlice.GetFieldValue(x, y); + auto caFldVal_2 = fpParameters->GetStation(2).fieldSlice.GetFieldValue(x, y); + auto caFldReg = cbm::algo::ca::FieldRegion<fvec>{}; + caFldReg.Set(caFldVal_0, z0, caFldVal_1, z1, caFldVal_2, z2); + LOG(info) << "CA ----> " << caFldReg.ToString(); + LOG(info) << "KF ----> " << kfFldReg.ToString(); + } + // TEST: material maps { Node n{.iSt = 1, .x = 2.3, .y = 1.2}; diff --git a/reco/kfnew/CbmKfTrackingSetupInitializer.cxx b/reco/kfnew/CbmKfTrackingSetupInitializer.cxx index 9650ac15884b69c2976eda0f5f5553d516acaa75..b93a1306112883c814397a94ca6e3ba81342942e 100644 --- a/reco/kfnew/CbmKfTrackingSetupInitializer.cxx +++ b/reco/kfnew/CbmKfTrackingSetupInitializer.cxx @@ -32,6 +32,7 @@ using kf::tools::MaterialMapCreator; // bool TrackingSetupInitializer::InitProperties() try { + using cbm::algo::kf::EFieldMode; using cbm::algo::kf::EFieldType; // Check, if a subsystem exists in the setup @@ -43,11 +44,10 @@ try { // Magnetic field initialization if (FairRunAna::Instance()->GetField()) { - this->SetFieldFunction(OriginalField(), EFieldType::Normal); + this->SetFieldProperty(EFieldMode::Intrpl, OriginalField(), EFieldType::Normal); } else { - //this->SetFieldFunction(cbm::algo::kf::defs::ZeroFieldFn, EFieldType::Null); - this->SetFieldFunction(ZeroField(), EFieldType::Null); + this->SetFieldProperty(EFieldMode::Intrpl, ZeroField(), EFieldType::Null); } // Tracking station property initialization