Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-02 07:32:05

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0013 #include "Acts/MagneticField/MagneticFieldProvider.hpp"
0014 #include "Acts/Utilities/Result.hpp"
0015 
0016 #include <cstddef>
0017 
0018 namespace Acts {
0019 
0020 /// @class SolenoidBField
0021 /// @brief Analytical solenoid magnetic field implementation
0022 ///
0023 /// @ingroup magnetic_field
0024 ///
0025 /// @section Concept
0026 ///
0027 /// This class implements a multi-coil solenoid magnetic field. On every call,
0028 /// the field is evaluated at that exact position. The field has radially
0029 /// symmetry, the field vectors point in +z direction. The config exposes a
0030 /// target field value in the center. This value is used to empirically
0031 /// determine a scale factor which reproduces this field value in the center.
0032 ///
0033 /// @image html bfield/quiver.png "Picture of a solenoid field in rz, with arrows indicating the direction of the field, and their size denoting the strength. The field is almost homogeneous in the center." width=100%
0034 ///
0035 /// @note
0036 /// A configuration of
0037 /// ```cpp
0038 /// SolenoidBField::Config cfg;
0039 /// cfg.length = 5.8_m;
0040 /// cfg.radius = (2.56 + 2.46) * 0.5 * 0.5_m;
0041 /// cfg.nCoils = 1154;
0042 /// cfg.bMagCenter = 2_T;
0043 /// SolenoidBField bField(cfg);
0044 /// ```
0045 /// roughly corresponds to the solenoid wrapping the Inner Detector in ATLAS!
0046 ///
0047 /// @warning
0048 /// As the evaluation of @f$E_1(k^2)@f$ and @f$E_2(k^2)@f$ is **slow**. The
0049 /// @ref Acts::InterpolatedBFieldMap easily outperforms
0050 /// @ref Acts::SolenoidBField. A helper is provided that builds a map from the
0051 /// analytical implementation and is much faster to lookup:
0052 /// @ref Acts::solenoidFieldMap.
0053 ///
0054 /// @section Implementation
0055 ///
0056 /// - @f$E_1(k^2)@f$ = complete elliptic integral of the 1st kind
0057 /// - @f$E_2(k^2)@f$ = complete elliptic integral of the 2nd kind
0058 ///
0059 /// @f$E_1(k^2)@f$ and @f$E_2(k^2)@f$ are usually indicated as @f$K(k^2)@f$ and @f$E(k^2)@f$ in
0060 /// literature,
0061 /// respectively
0062 ///
0063 /// @f[
0064 /// E_1(k^2) = \int_0^{\pi/2} \left( 1 - k^2 \sin^2{\theta} \right )^{-1/2} \mathrm{d}\theta
0065 /// @f]
0066 ///
0067 /// @f[
0068 /// E_2(k^2) = \int_0^{\pi/2}\sqrt{1 - k^2 \sin^2{\theta}} \mathrm{d}\theta
0069 /// @f]
0070 ///
0071 /// @f$k^2@f$ is a function of the point @f$(r, z)@f$ and of the radius of the coil @f$R@f$
0072 ///
0073 /// @f[
0074 /// k^2 = \frac{4Rr}{(R+r)^2 + z^2}
0075 /// @f]
0076 ///
0077 /// Using these, you can evaluate the two components @f$B_r@f$ and @f$B_z@f$ of the
0078 /// magnetic field:
0079 ///
0080 /// @f[
0081 /// B_r(r, z) = \frac{\mu_0 I}{4\pi} \frac{kz}{\sqrt{Rr^3}} \left[ \left(\frac{2-k^2}{2-2k^2}\right)E_2(k^2) - E_1(k^2) \right ]
0082 /// @f]
0083 ///
0084 /// @f[
0085 /// B_z(r,z) = \frac{\mu_0 I}{4\pi} \frac{k}{\sqrt{Rr}} \left[ \left( \frac{(R+r)k^2-2r}{2r(1-k^2)} \right ) E_2(k^2) + E_1(k^2) \right ]
0086 /// @f]
0087 ///
0088 ///
0089 /// In the implementation the factor of @f$(\mu_0\cdot I)@f$ is defined to be a scaling
0090 /// factor. It is evaluated and defined as the magnetic field in the center of
0091 /// the
0092 /// coil, i.e. the scale set in @ref Acts::SolenoidBField::Config::bMagCenter.
0093 ///
0094 class SolenoidBField final : public MagneticFieldProvider {
0095  public:
0096   /// Cache payload for magnetic field evaluation.
0097   struct Cache {
0098     /// @brief Constructor with magnetic field context
0099     explicit Cache(const MagneticFieldContext& /*mctx*/) {}
0100   };
0101 
0102   /// Config struct for the SolenoidBfield.
0103   struct Config {
0104     /// Radius at which the coils are located.
0105     double radius;
0106     /// Extent of the solenoid in z. It goes from
0107     /// -length/2 to +length/2 by convention
0108     double length;
0109     /// The number of coils that make up the solenoid
0110     std::size_t nCoils;
0111     /// The target magnetic field strength at the center.
0112     /// This will be used to scale coefficients
0113     double bMagCenter;
0114   };
0115 
0116   /// @brief the constructor with a shared pointer
0117   /// @note since it is a shared field, we enforce it to be const
0118   /// @tparam bField is the shared BField to be stored
0119   /// @param config Configuration struct containing solenoid parameters
0120   explicit SolenoidBField(Config config);
0121 
0122   /// @brief Retrieve magnetic field value in local (r,z) coordinates
0123   ///
0124   /// @param [in] position local 2D position
0125   /// @return Magnetic field vector in local (r,z) coordinates
0126   Vector2 getField(const Vector2& position) const;
0127 
0128   /// @copydoc MagneticFieldProvider::makeCache(const MagneticFieldContext&) const
0129   MagneticFieldProvider::Cache makeCache(
0130       const MagneticFieldContext& mctx) const override;
0131 
0132   /// @brief Get the B field at a position
0133   ///
0134   /// @param position The position to query at
0135   /// @return Magnetic field vector in global coordinates
0136   Vector3 getField(const Vector3& position) const;
0137 
0138   /// @copydoc MagneticFieldProvider::getField(const Vector3&,MagneticFieldProvider::Cache&) const
0139   Result<Vector3> getField(const Vector3& position,
0140                            MagneticFieldProvider::Cache& cache) const override;
0141 
0142  private:
0143   Config m_cfg;
0144   double m_scale;
0145   double m_dz;
0146   double m_R2;
0147 
0148   Vector2 multiCoilField(const Vector2& pos, double scale) const;
0149 
0150   Vector2 singleCoilField(const Vector2& pos, double scale) const;
0151 
0152   double B_r(const Vector2& pos, double scale) const;
0153 
0154   double B_z(const Vector2& pos, double scale) const;
0155 
0156   double k2(double r, double z) const;
0157 };
0158 
0159 }  // namespace Acts