Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:20:19

0001 #pragma once
0002 
0003 #include "PHField.h"
0004 
0005 #if defined(__GNUC__) && !defined(__clang__)
0006     #pragma GCC diagnostic push
0007     #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0008     #include <Eigen/Dense>
0009     #pragma GCC diagnostic pop
0010 #else
0011     #include <Eigen/Dense>
0012 #endif
0013 
0014 #include <array>
0015 #include <deque>
0016 #include <iostream>
0017 #include <limits>
0018 #include <map>
0019 #include <mutex>
0020 #include <optional>
0021 #include <string>
0022 #include <thread>
0023 
0024 //! Provides a best-fit cubic approximation of the Field
0025 //! In 3D cartesian coordinates
0026 class PHFieldInterpolated : public PHField
0027 {
0028 public:
0029     typedef Eigen::Vector3i Indices_t;
0030     typedef Eigen::Vector3f Point_t;
0031     typedef Eigen::Vector3f Field_t;
0032 
0033     //! constructor
0034     explicit PHFieldInterpolated () = default;
0035 
0036     //! destructor
0037     ~PHFieldInterpolated () override = default;
0038 
0039     //! access field value
0040     //! Follow the convention of G4ElectroMagneticField
0041     //! @param[in]  pointer to double[4] representing (x, y, z, t), where field is to be evaluated (in Geant4/CLHEP units) (cm)
0042     //! @param[out] pointer to double[3] representing (b_x, b_y, b_z), mutated to contain the value of the field (in Geant4/CLHEP units) (T)
0043     void GetFieldValue (double const*, double*) const override;
0044 
0045     //! Returns an O(3) best fit interpolation of the field at the point, updating the cached interpolated parameters as needed
0046     //! Thread-safe top-level access
0047     Field_t get_interpolated (Point_t const&) const;
0048 
0049     //! Loads the fieldmap from a ROOT file, expects specific contents
0050     void load_fieldmap (
0051         std::string const& = "/cvmfs/sphenix.sdcc.bnl.gov/alma9.2-gcc-14.2.0/release/release_ana/ana.499/share/calibrations/Field/Map/sphenix3dtrackingmapxyz.root",
0052         const float& = 1.0
0053     );
0054 
0055     //! prints class info based on verbosity level
0056     //! thread-safe
0057     void print(std::ostream& = std::cout) const;
0058 
0059     //! prints the cached Taylor coefficients
0060     //! thread-safe
0061     void print_coefficients(std::ostream& = std::cout) const;
0062 
0063 private:
0064 
0065     // Threads using the class get their own cache
0066     struct InterpolationCache {
0067 
0068         //! Tracks how "important" this cache is
0069         //! When a thread accesses this class, its corresponding cache is moved to the front of the queue
0070         //! Instances at the end of the "queue" are culled
0071         //! Maximal value allows idential logic to shuffle indexes for existing or new thread accesses
0072         std::size_t m_queue_index{std::numeric_limits<std::size_t>::max()};
0073 
0074         //! The indices of the left-down-back corner of the cell that the interpolation is cached for
0075         //! Initialized out-of-bounds so the coefficients are always computed on first call
0076         Indices_t m_buffered_indices = {-1, -1, -1};
0077 
0078         //! The point about which the field is currently interpolated
0079         Point_t m_center;
0080 
0081         //! The 20 coefficients for an O(3) Taylor expansion of a function in 3D
0082         //! (one per component of the magnetic field)
0083         std::array<Eigen::VectorXf, 3>  m_coefficients;
0084     };
0085 
0086     //! Returns the 20 element row of a design matrix for position point about the stored value m_center
0087     static Eigen::VectorXf get_design_vector (Point_t const&, InterpolationCache const&);
0088 
0089     //! Returns a mutable reference to the interpolation information cached for the calling thread
0090     InterpolationCache& get_cache () const;
0091 
0092     //! Caches the interpolation for the cell containing given point
0093     //! Should really be a member funciton of InterpolationCache
0094     void cache_interpolation (Point_t const&, InterpolationCache&) const;
0095 
0096     //! Gets the 3D grid indices from a 1D deque index
0097     Indices_t get_indices (std::size_t const&) const;
0098     //! Gets the 1D deque index from 3D grid indices
0099     std::size_t get_index (Indices_t const&) const;
0100 
0101     //! return the 3D grid indices of the left-down-back corner of the grid cell containing point
0102     Indices_t get_indices (Point_t const&) const;
0103     //! return point at the left-down-back corner of the grid cell at the given 3D grid indices
0104     Point_t get_point (Indices_t const&) const;
0105 
0106     //! return field at given 1D deque index
0107     Field_t get_field (std::size_t const& index) const { return m_field.at(index); }
0108     //! return field at the left-down-back corner of the grid cell at given 3D grid indices
0109     Field_t get_field (Indices_t const& indices) const { return get_field(get_index(indices)); }
0110     //! return the field at the left-down-back corner of the grid cell containing point
0111     Field_t get_field (Point_t const& point) const { return get_field(get_indices(point)); }
0112 
0113     //! throw if the 3D grid indices are not in the grid and would give an invalid index
0114     void validate_indices (Indices_t const&) const;
0115     //! throw if the point lies outside the grid and would give an invalid index
0116     void validate_point (Point_t const&) const;
0117 
0118     //! The most threads will we accomodate before pruning the cache map between calls
0119     static std::size_t const MAX_THREADS = 8;
0120 
0121     Indices_t m_N; // Number of points along an axis
0122     Point_t m_D; // Grid spacing of an axis
0123     Point_t m_min; // Minimum value of an axis
0124     Point_t m_max; // Maximum value of an axis
0125 
0126     //! The entire fieldmap, loaded into memory (yikes)
0127     //! deque for O(1) access, without requiring contiguous allocation
0128     std::deque<Field_t> m_field;
0129 
0130     // Map of thread ids to caches
0131     typedef std::map<std::thread::id, InterpolationCache> map_t;
0132     mutable map_t m_caches;
0133 
0134     // mutex for access
0135     mutable std::mutex m_mutex;
0136 };