Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
InterpolatedBFieldMap.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file InterpolatedBFieldMap.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-2018 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
18 
19 #include <functional>
20 #include <optional>
21 #include <vector>
22 
23 namespace Acts {
24 
26  public:
30  virtual std::vector<size_t> getNBins() const = 0;
31 
35  virtual std::vector<double> getMin() const = 0;
36 
40  virtual std::vector<double> getMax() const = 0;
41 
47  virtual bool isInside(const Vector3& position) const = 0;
48 
54  virtual Vector3 getFieldUnchecked(const Vector3& position) const = 0;
55 };
56 
75 template <typename grid_t>
77  public:
78  using Grid = grid_t;
79  using FieldType = typename Grid::value_type;
80  static constexpr size_t DIM_POS = Grid::DIM;
81 
86  struct FieldCell {
88  static constexpr unsigned int N = 1 << DIM_POS;
89 
90  public:
101  FieldCell(std::array<double, DIM_POS> lowerLeft,
102  std::array<double, DIM_POS> upperRight,
103  std::array<Vector3, N> fieldValues)
104  : m_lowerLeft(std::move(lowerLeft)),
105  m_upperRight(std::move(upperRight)),
106  m_fieldValues(std::move(fieldValues)) {}
107 
115  // defined in Interpolation.hpp
117  }
118 
124  bool isInside(const ActsVector<DIM_POS>& position) const {
125  for (unsigned int i = 0; i < DIM_POS; ++i) {
126  if (position[i] < m_lowerLeft[i] || position[i] >= m_upperRight[i]) {
127  return false;
128  }
129  }
130  return true;
131  }
132 
133  private:
135  std::array<double, DIM_POS> m_lowerLeft;
136 
138  std::array<double, DIM_POS> m_upperRight;
139 
144  std::array<Vector3, N> m_fieldValues;
145  };
146 
147  struct Cache {
151  Cache(const MagneticFieldContext& mctx) { (void)mctx; }
152 
153  std::optional<FieldCell> fieldCell;
154  bool initialized = false;
155  };
156 
158  struct Config {
161  std::function<ActsVector<DIM_POS>(const Vector3&)> transformPos;
162 
166  std::function<Vector3(const FieldType&, const Vector3&)> transformBField;
167 
170 
175  double scale = 1.;
176  };
177 
181  typename Grid::index_t minBin{};
182  minBin.fill(1);
183  m_lowerLeft = m_cfg.grid.lowerLeftBinEdge(minBin);
184  m_upperRight = m_cfg.grid.lowerLeftBinEdge(m_cfg.grid.numLocalBins());
185  }
186 
195  const auto& gridPosition = m_cfg.transformPos(position);
196  const auto& indices = m_cfg.grid.localBinsFromPosition(gridPosition);
197  const auto& lowerLeft = m_cfg.grid.lowerLeftBinEdge(indices);
198  const auto& upperRight = m_cfg.grid.upperRightBinEdge(indices);
199 
200  // loop through all corner points
201  constexpr size_t nCorners = 1 << DIM_POS;
202  std::array<Vector3, nCorners> neighbors;
203  const auto& cornerIndices = m_cfg.grid.closestPointsIndices(gridPosition);
204 
205  if (!isInsideLocal(gridPosition)) {
206  return MagneticFieldError::OutOfBounds;
207  }
208 
209  size_t i = 0;
210  for (size_t index : cornerIndices) {
211  neighbors.at(i++) = m_cfg.transformBField(m_cfg.grid.at(index), position);
212  }
213 
214  assert(i == nCorners);
215 
216  return FieldCell(lowerLeft, upperRight, std::move(neighbors));
217  }
218 
222  std::vector<size_t> getNBins() const final {
223  auto nBinsArray = m_cfg.grid.numLocalBins();
224  return std::vector<size_t>(nBinsArray.begin(), nBinsArray.end());
225  }
226 
230  std::vector<double> getMin() const final {
231  return std::vector<double>(m_lowerLeft.begin(), m_lowerLeft.end());
232  }
233 
237  std::vector<double> getMax() const final {
238  return std::vector<double>(m_upperRight.begin(), m_upperRight.end());
239  }
240 
246  bool isInside(const Vector3& position) const final {
248  }
249 
255  bool isInsideLocal(const ActsVector<DIM_POS>& gridPosition) const {
256  for (unsigned int i = 0; i < DIM_POS; ++i) {
257  if (gridPosition[i] < m_lowerLeft[i] ||
258  gridPosition[i] >= m_upperRight[i]) {
259  return false;
260  }
261  }
262  return true;
263  }
264 
268  const Grid& getGrid() const { return m_cfg.grid; }
269 
272  const MagneticFieldContext& mctx) const final {
273  return MagneticFieldProvider::Cache::make<Cache>(mctx);
274  }
275 
284  const auto gridPosition = m_cfg.transformPos(position);
285  if (!isInsideLocal(gridPosition)) {
286  return Result<Vector3>::failure(MagneticFieldError::OutOfBounds);
287  }
288 
290  m_cfg.transformBField(m_cfg.grid.interpolate(gridPosition), position));
291  }
292 
294  const auto gridPosition = m_cfg.transformPos(position);
295  return m_cfg.transformBField(m_cfg.grid.interpolate(gridPosition),
296  position);
297  }
298 
301  MagneticFieldProvider::Cache& cache) const final {
302  Cache& lcache = cache.get<Cache>();
303  const auto gridPosition = m_cfg.transformPos(position);
304  if (!lcache.fieldCell || !(*lcache.fieldCell).isInside(gridPosition)) {
305  auto res = getFieldCell(position);
306  if (!res.ok()) {
307  return Result<Vector3>::failure(res.error());
308  }
309  lcache.fieldCell = *res;
310  }
311  return Result<Vector3>::success((*lcache.fieldCell).getField(gridPosition));
312  }
313 
320  const Vector3& position, ActsMatrix<3, 3>& derivative,
321  MagneticFieldProvider::Cache& cache) const final {
322  (void)derivative;
323  return getField(position, cache);
324  }
325 
326  private:
328 
331 };
332 
333 } // namespace Acts