Back to home page

EIC code displayed by LXR

 
 

    


Warning, /acts/docs/core/magnetic_field.md is written in an unsupported language. File is not indexed.

0001 (magnetic-field-core)=
0002 # Magnetic field
0003 
0004 The magnetic field component of ACTS provides functionality to describe
0005 arbitrary magnetic field configurations in an experiment. It is implemented in
0006 a generic way and can be extended to connect to an experiment specific upstream
0007 source of field data.
0008 
0009 Algorithms which need magnetic field information (e.g.
0010 {class}`Acts::AtlasStepper`, {class}`Acts::EigenStepper`) accept the magnetic
0011 field as an explicit argument.
0012 
0013 ## Provider interface
0014 
0015 All magnetic field implementations inherit and implement the interface {class}`Acts::MagneticFieldProvider`:
0016 
0017 
0018 It provides a generic interface over different implementations. To speed up
0019 magnetic field lookup, each implementation can have a *cache* object. The cache
0020 object can for example be used to store a local interpolation domain, to speed
0021 up nearby field lookups. The client is expected to pass into lookup calls:
0022 
0023 :::{doxygentypedef} Acts::MagneticFieldProvider::Cache
0024 :::
0025 
0026 The implementation is then free to use and update this cache instance as
0027 needed. Before a client can issue field lookup calls, it needs to obtain an
0028 initialized instance of this cache object. This can be achieved generically for
0029 all implementations by using {func}`Acts::MagneticFieldProvider::makeCache`.
0030 This function accepts an instance of {class}`Acts::MagneticFieldContext`, see
0031 [](#magnetic-field-context) for details.
0032 
0033 The main lookup method of {class}`Acts::MagneticFieldProvider` is
0034 
0035 :::{doxygenfunction} Acts::MagneticFieldProvider::getField
0036 :outline:
0037 :::
0038 
0039 Aside from the lookup position as a global position vector, it accepts an
0040 instance of the opaque cache object mentioned before. The return value is a
0041 {class}`Acts::Result` object. It either contains the field value at the
0042 requested location, or an {enum}`Acts::MagneticFieldError` in case of a lookup
0043 failure, like an out-of-bounds lookup position.
0044 
0045 Below is an example of how a client can interact with an instance of
0046 {class}`Acts::MagneticFieldProvider`.
0047 
0048 ```cpp
0049 // in event context
0050 auto fieldContext = getExperimentFieldContext();
0051 const Acts::MagneticFieldProvider& fieldProvider = getFieldProvider();
0052 auto cache = fieldProvider.makeCache(fieldContext);
0053 
0054 auto lookupResult = fieldProvider.getField(Acts::Vector3{10, 10, 10}, cache);
0055 if(!lookupResult.ok()) {
0056    throw std::runtime_error{"Field lookup failure"};
0057 }
0058 
0059 Acts::Vector3 fieldValue = *lookupResult;
0060 ```
0061 
0062 ## Magnetic field context
0063 
0064 :::{doxygenclass} Acts::MagneticFieldContext
0065 :outline:
0066 :::
0067 
0068 The magnetic field context is an opaque type which contains experiment specific
0069 event context information. This can be used to supply event dependent data to
0070 the magnetic field instance, in case it is needed to provide correct field
0071 values. The library itself does not make any assumptions on the content of this
0072 context type (it is implemented using `std::any`), but passes a reference
0073 through the call-chain to the field implementation. An experiment specific
0074 field implementation is then expected to performa cast to the concrete type,
0075 and use the contents.
0076 
0077 An example use case of the context could be to look up conditions data /
0078 records for the value of the magnetic field at the time of the event.
0079 
0080 ## Field provider implementations in Core
0081 
0082 There are a number of field provider implementations found in core which serve different purposes.
0083 
0084 ### Constant magnetic field
0085 
0086 The simplest implementation is a constant field, which returns the same field
0087 values at every queried location. It is implemented in the
0088 {class}`Acts::ConstantBField` class.
0089 
0090 :::{doxygenclass} Acts::ConstantBField
0091 :members: ConstantBField
0092 :::
0093 
0094 As seen above, the class is constructed from a three-dimensional field vector,
0095 which is returned unmodified to every call to
0096 {func}`Acts::ConstantBField::getField`.
0097 
0098 ### Interpolated magnetic field
0099 
0100 For more complex magnetic field implementations
0101 {class}`Acts::InterpolatedMagneticField` can be used. The idea here is to calculate
0102 an interpolated value of the magnetic field from a grid of known field values.
0103 In 3D, this means the interpolation is done from the 8 corner points of a *field
0104 cell*. The field cell can be retrieved for any given position. Since during
0105 typical access patterns, e.g. the propagation, subsequent steps are relatively
0106 likely to not cross the field cell boundary, the field cell can be cached.
0107 
0108 :::{figure} figures/bfield/field_cell.svg
0109 :width: 300
0110 :align: center
0111 Illustration of the field cell concept. Subsequent steps are clustered in the
0112 same field cell. The field cell only needs to be refetched when the propagation
0113 crosses into the next grid region.
0114 :::
0115 
0116 {class}`Acts::InterpolatedMagneticField` extends the
0117 {class}`Acts::MagneticFieldProvider` interface to add a number of additional
0118 methods:
0119 
0120 :::{doxygenclass} Acts::InterpolatedMagneticField
0121 :::
0122 
0123 This intermediate interface is again implemented by
0124 {class}`Acts::InterpolatedBFieldMap`, which is a template class that depends on
0125 an instance of {class}`Acts::Grid`. Varying configurations are possible,
0126 like a 2D field map that exploits $rz$ symmetry, or a plain 3D grid.
0127 
0128 :::{doxygenclass} Acts::InterpolatedBFieldMap
0129 :members: false
0130 :::
0131 
0132 
0133 The class constructor accepts a single configuration struct that
0134 contains the grid instance, a scale factor and optional conversion function for
0135 the lookup positions and the returned field values.
0136 
0137 :::{doxygenstruct} Acts::InterpolatedBFieldMap::Config
0138 :::
0139 
0140 Internally, {class}`Acts::InterpolatedBFieldMap` uses a *field interpolation
0141 cell* to speed up lookups. This cell contains the interpolation points so the
0142 grid does not have to be consulted for each lookup. Explicit methods to create
0143 such a field cell are provided, but field cell creation is automatically
0144 handled by {func}`Acts::InterpolatedBFieldMap::makeCache`, opaque to the
0145 client.
0146 
0147 Helpers to construct an interpolated field map from text and ROOT file inputs
0148 are provided:
0149 
0150 :::{doxygenfunction} Acts::fieldMapRZ
0151 :::
0152 
0153 :::{doxygenfunction} Acts::fieldMapXYZ
0154 :::
0155 
0156 
0157 ### Analytical solenoid magnetic field
0158 
0159 :::{warning}
0160 The analytical solenoid field is **slow**. See {func}`Acts::solenoidFieldMap`
0161 to speed it up.
0162 :::
0163 
0164 ACTS also provides a field provider that calculates the field vectors
0165 analytically for a [solenoid](https://en.wikipedia.org/wiki/Solenoid) field.
0166 
0167 :::{figure} figures/bfield/quiver.png
0168 :width: 600
0169 :align: center
0170 Picture of a solenoid field in rz, with arrows indicating the direction of the
0171 field, and their size denoting the strength. The field is almost homogeneous in
0172 the center.
0173 :::
0174 
0175 The implementation has configurable solenoid parameters:
0176 
0177 :::{doxygenstruct} Acts::SolenoidBField::Config
0178 :::
0179 
0180 :::{note}
0181 A configuration of
0182 ```cpp
0183 SolenoidBField::Config cfg;
0184 cfg.length = 5.8_m;
0185 cfg.radius = (2.56 + 2.46) * 0.5 * 0.5_m;
0186 cfg.nCoils = 1154;
0187 cfg.bMagCenter = 2_T;
0188 SolenoidBField bField(cfg);
0189 ```
0190 roughly corresponds to the solenoid wrapping the Inner Detector in ATLAS.
0191 :::
0192 
0193 #### Implementation
0194 
0195 The calculation uses two special functions:
0196 
0197 - $E_1(k^2)$ is the complete elliptic integral of the 1st kind
0198 - $E_2(k^2)$ is the complete elliptic integral of the 2nd kind
0199 
0200 $E_1(k^2)$ and $E_2(k^2)$ are usually indicated as $K(k^2)$ and $E(k^2)$ in literature, respectively:
0201 
0202 $$
0203 E_1(k^2) = \int_0^{\pi/2} \left( 1 - k^2 \sin^2{\theta} \right )^{-1/2} \mathop{}\!\mathrm{d}\theta
0204 $$
0205 
0206 $$
0207 E_2(k^2) = \int_0^{\pi/2}\sqrt{1 - k^2 \sin^2{\theta}} \mathop{}\!\mathrm{d}\theta
0208 $$
0209 
0210 $k^2$ is a function of the point $(r, z)$ and of the radius of the coil $R$
0211 
0212 $$
0213 k^2 = \frac{4Rr}{(R+r)^2 + z^2}
0214 $$
0215 
0216 Using these, you can evaluate the two components $B_r$ and $B_z$ of the magnetic field:
0217 
0218 $$
0219 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 ]
0220 $$
0221 
0222 $$
0223 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 ]
0224 $$
0225 
0226 In the implementation the factor of $(\mu_0\cdot I)$ is defined to be a scaling
0227 factor. It is evaluated and defined as the magnetic field in the center of the
0228 coil, i.e. the scale set in {member}`Acts::SolenoidBField::Config::bMagCenter`.
0229 
0230 As the evaluation of $E_1(k^2)$ and $E_2(k^2)$ is **slow**. The
0231 {class}`Acts::InterpolatedBFieldMap` easily outperforms
0232 {class}`Acts::SolenoidBField`. A helper is provided that builds a map from the
0233 analytical implementation and is much faster to lookup:
0234 
0235 :::{doxygenfunction} Acts::solenoidFieldMap
0236 :::
0237 
0238 ### Multi-range constant field
0239 
0240 The multi-range constant field allows modelling cases where a magnetic field
0241 can be described as multiple (potentially overlapping) regions, each of which
0242 has its own constant magnetic field. This provides more flexibility than the
0243 {class}`Acts::ConstantBField` while providing higher performance than
0244 {class}`Acts::InterpolatedBFieldMap`.
0245 
0246 This magnetic field provider is configured using a list of pairs, where each
0247 pair defines a region in three-dimensional space as well as a field vector.
0248 Magnetic field lookup then proceeds by finding the _last_ region in the
0249 user-provided list that contains the requested coordinate and returning the
0250 corresponding field vector.
0251 
0252 The implementation uses a simple caching mechanism to store the last matched
0253 region, providing improved performance for consecutive lookups within the same
0254 region. This is thread-safe when each thread uses its own cache instance. The
0255 field configuration itself is immutable after construction.
0256 
0257 :::{doxygenclass} Acts::MultiRangeBField
0258 :::
0259 
0260 ## Full provider interface
0261 
0262 :::{doxygenclass} Acts::MagneticFieldProvider
0263 :::