Skip to content

Commit

Permalink
refactor!: Use inheritance for type-erasure of Magnetic Field Provide…
Browse files Browse the repository at this point in the history
…rs (1/2) (#666)

* mvp

add any cache

fix scalable b field

remove explicit ctor / ass op

doc comments

BFieldBase -> BFieldProvider

gcc9 fix

switch to SBO cache

use static instead of realloc for every instance

fix

remove clone method on handler

format

align array buffer

* compile fix

* fix segfault because of missing move construction

* also add copy construct

* make cache type handle non-copyable caches

* adjust to bfield cache type not being copyable anymore in unit test

* move SBO cache to separate file, remove AnyCache

* rename BFieldProvider to MagneticFieldProvider

* fix a few spots where the rename wasn't done yet

Co-authored-by: Andreas Salzburger <Andreas.Salzburger@cern.ch>
  • Loading branch information
paulgessinger and asalzburger committed Feb 24, 2021
1 parent 3b345dd commit 46309cd
Show file tree
Hide file tree
Showing 23 changed files with 558 additions and 219 deletions.
51 changes: 24 additions & 27 deletions Core/include/Acts/MagneticField/ConstantBField.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#pragma once
#include "Acts/Definitions/Algebra.hpp"
#include "Acts/MagneticField/MagneticFieldContext.hpp"
#include "Acts/MagneticField/MagneticFieldProvider.hpp"

namespace Acts {

Expand All @@ -17,7 +18,7 @@ namespace Acts {
/// This class implements a simple constant magnetic field. The
/// magnetic field value has to be set at creation time, but can
/// be updated later on.
class ConstantBField final {
class ConstantBField final : public MagneticFieldProvider {
public:
struct Cache {
/// @brief constructor with context
Expand All @@ -37,59 +38,55 @@ class ConstantBField final {
ConstantBField(double Bx = 0., double By = 0., double Bz = 0.)
: m_BField(Bx, By, Bz) {}

/// @brief retrieve magnetic field value
///
/// @param [in] position global position
/// @return magnetic field vector
/// @copydoc MagneticFieldProvider::getField(const Vector3&)
///
/// @note The @p position is ignored and only kept as argument to provide
/// a consistent interface with other magnetic field services.
Vector3 getField(const Vector3& /*position*/) const { return m_BField; }
Vector3 getField(const Vector3& /*position*/) const override {
return m_BField;
}

/// @brief retrieve magnetic field value
///
/// @param [in] position global position
/// @param [in] cache Cache object (is ignored)
/// @return magnetic field vector
/// @copydoc MagneticFieldProvider::getField(const
/// Vector3&,MagneticFieldProvider::Cache&)
///
/// @note The @p position is ignored and only kept as argument to provide
/// a consistent interface with other magnetic field services.
Vector3 getField(const Vector3& /*position*/, Cache& /*cache*/) const {
Vector3 getField(const Vector3& /*position*/,
MagneticFieldProvider::Cache& /*cache*/) const override {
return m_BField;
}

/// @brief retrieve magnetic field value & its gradient
///
/// @param [in] position global position
/// @param [out] derivative gradient of magnetic field vector as (3x3) matrix
/// @return magnetic field vector
/// @copydoc MagneticFieldProvider::getFieldGradient(const
/// Vector3&,ActsMatrix<3,3>&)
///
/// @note The @p position is ignored and only kept as argument to provide
/// a consistent interface with other magnetic field services.
/// @note currently the derivative is not calculated
/// @todo return derivative
Vector3 getFieldGradient(const Vector3& /*position*/,
ActsMatrix<3, 3>& /*derivative*/) const {
ActsMatrix<3, 3>& /*derivative*/) const override {
return m_BField;
}

/// @brief retrieve magnetic field value & its gradient
///
/// @param [in] position global position
/// @param [out] derivative gradient of magnetic field vector as (3x3) matrix
/// @param [in] cache Cache object (is ignored)
/// @return magnetic field vector
/// @copydoc MagneticFieldProvider::getFieldGradient(const
/// Vector3&,ActsMatrix<3,3>&,MagneticFieldProvider::Cache&)
///
/// @note The @p position is ignored and only kept as argument to provide
/// a consistent interface with other magnetic field services.
/// @note currently the derivative is not calculated
/// @todo return derivative
Vector3 getFieldGradient(const Vector3& /*position*/,
ActsMatrix<3, 3>& /*derivative*/,
Cache& /*cache*/) const {
Vector3 getFieldGradient(
const Vector3& /*position*/, ActsMatrix<3, 3>& /*derivative*/,
MagneticFieldProvider::Cache& /*cache*/) const override {
return m_BField;
}

/// @copydoc MagneticFieldProvider::makeCache(const MagneticFieldContext&)
Acts::MagneticFieldProvider::Cache makeCache(
const Acts::MagneticFieldContext& mctx) const override {
return Acts::MagneticFieldProvider::Cache::make<Cache>(mctx);
}

/// @brief check whether given 3D position is inside look-up domain
///
/// @param [in] position global 3D position
Expand Down
96 changes: 45 additions & 51 deletions Core/include/Acts/MagneticField/InterpolatedBFieldMap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/MagneticField/MagneticFieldContext.hpp"
#include "Acts/MagneticField/MagneticFieldProvider.hpp"
#include "Acts/Utilities/Interpolation.hpp"
#include "Acts/Utilities/detail/Grid.hpp"

Expand Down Expand Up @@ -228,7 +229,7 @@ struct InterpolatedBFieldMapper {
/// - looking up the magnetic field values on the closest grid points,
/// - doing a linear interpolation of these magnetic field values.
template <typename Mapper_t>
class InterpolatedBFieldMap final {
class InterpolatedBFieldMap final : public MagneticFieldProvider {
public:
/// @brief configuration object for magnetic field interpolation
struct Config {
Expand Down Expand Up @@ -268,82 +269,75 @@ class InterpolatedBFieldMap final {
/// @return copy of the internal configuration object
Config getConfiguration() const { return m_config; }

/// @brief retrieve magnetic field value
/// @brief get global scaling factor for magnetic field
///
/// @param [in] position global 3D position
/// @return global factor for scaling the magnetic field
double getScale() const { return m_config.scale; }

/// @brief convenience method to access underlying field mapper
///
/// @return magnetic field vector at given position
Vector3 getField(const Vector3& position) const {
return m_config.mapper.getField(position);
}
/// @return the field mapper
Mapper_t getMapper() const { return m_config.mapper; }

/// @brief retrieve magnetic field value
/// @brief check whether given 3D position is inside look-up domain
///
/// @param [in] position global 3D position
/// @param [in,out] cache Cache object. Contains field cell used for
/// interpolation
/// @return @c true if position is inside the defined BField map,
/// otherwise @c false
bool isInside(const Vector3& position) const {
return m_config.mapper.isInside(position);
}

/// @brief update configuration
///
/// @return magnetic field vector at given position
Vector3 getField(const Vector3& position, Cache& cache) const {
/// @param [in] config new configuration object
void setConfiguration(const Config& config) { m_config = config; }

public:
/// @copydoc MagneticFieldProvider::makeCache(const MagneticFieldContext&)
MagneticFieldProvider::Cache makeCache(
const MagneticFieldContext& mctx) const override {
return MagneticFieldProvider::Cache::make<Cache>(mctx);
}

/// @copydoc MagneticFieldProvider::getField(const Vector3&)
Vector3 getField(const Vector3& position) const override {
return m_config.mapper.getField(position);
}

/// @copydoc MagneticFieldProvider::getField(const
/// Vector3&,MagneticFieldProvider::Cache&)
Vector3 getField(const Vector3& position,
MagneticFieldProvider::Cache& gcache) const override {
Cache& cache = gcache.get<Cache>();
if (!cache.fieldCell || !(*cache.fieldCell).isInside(position)) {
cache.fieldCell = getFieldCell(position);
}
return (*cache.fieldCell).getField(position);
}

/// @brief retrieve magnetic field value & its gradient
///
/// @param [in] position global 3D position
/// @param [out] derivative gradient of magnetic field vector as (3x3) matrix
/// @return magnetic field vector
/// @copydoc MagneticFieldProvider::getFieldGradient(const
/// Vector3&,ActsMatrix<3,3>&)
///
/// @note currently the derivative is not calculated
/// @todo return derivative
Vector3 getFieldGradient(const Vector3& position,
ActsMatrix<3, 3>& /*derivative*/) const {
ActsMatrix<3, 3>& /*derivative*/) const override {
return m_config.mapper.getField(position);
}

/// @brief retrieve magnetic field value & its gradient
///
/// @param [in] position global 3D position
/// @param [out] derivative gradient of magnetic field vector as (3x3) matrix
/// @param [in,out] cache Cache object. Contains field cell used for
/// @return magnetic field vector
/// @copydoc MagneticFieldProvider::getFieldGradient(const
/// Vector3&,ActsMatrix<3,3>&,MagneticFieldProvider::Cache&)
///
/// @note currently the derivative is not calculated
/// @note Cache is not used currently
/// @todo return derivative
Vector3 getFieldGradient(const Vector3& position,
ActsMatrix<3, 3>& /*derivative*/,
Cache& /*cache*/) const {
Vector3 getFieldGradient(
const Vector3& position, ActsMatrix<3, 3>& /*derivative*/,
MagneticFieldProvider::Cache& /*cache*/) const override {
return m_config.mapper.getField(position);
}

/// @brief get global scaling factor for magnetic field
///
/// @return global factor for scaling the magnetic field
double getScale() const { return m_config.scale; }

/// @brief convenience method to access underlying field mapper
///
/// @return the field mapper
Mapper_t getMapper() const { return m_config.mapper; }

/// @brief check whether given 3D position is inside look-up domain
///
/// @param [in] position global 3D position
/// @return @c true if position is inside the defined BField map,
/// otherwise @c false
bool isInside(const Vector3& position) const {
return m_config.mapper.isInside(position);
}

/// @brief update configuration
///
/// @param [in] config new configuration object
void setConfiguration(const Config& config) { m_config = config; }

private:
/// @brief retrieve field cell for given position
///
Expand Down
66 changes: 66 additions & 0 deletions Core/include/Acts/MagneticField/MagneticFieldProvider.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// This file is part of the Acts project.
//
// Copyright (C) 2021 CERN for the benefit of the Acts project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/MagneticField/MagneticFieldContext.hpp"
#include "Acts/MagneticField/detail/SmallObjectCache.hpp"

#include <array>
#include <memory>

namespace Acts {

/// Base class for all magnetic field providers
class MagneticFieldProvider {
public:
using Cache = detail::SmallObjectCache;

/// @brief Make an opaque cache for the magnetic field
///
/// @param mctx The magnetic field context to generate cache for
/// @return Cache The opaque cache object
virtual Cache makeCache(const MagneticFieldContext& mctx) const = 0;

/// @brief retrieve magnetic field value
///
/// @param [in] position global 3D position
///
/// @return magnetic field vector at given position
virtual Vector3 getField(const Vector3& position, Cache& cache) const = 0;

/// @brief retrieve magnetic field value
///
/// @param [in] position global 3D position
/// @param [in,out] cache Cache object. Contains field cell used for
/// interpolation
///
/// @return magnetic field vector at given position
virtual Vector3 getField(const Vector3& position) const = 0;

/// @brief retrieve magnetic field value & its gradient
///
/// @param [in] position global 3D position
/// @param [out] derivative gradient of magnetic field vector as (3x3) matrix
/// @return magnetic field vector
virtual Vector3 getFieldGradient(const Vector3& position,
ActsMatrix<3, 3>& derivative) const = 0;

/// @brief retrieve magnetic field value & its gradient
///
/// @param [in] position global 3D position
/// @param [out] derivative gradient of magnetic field vector as (3x3) matrix
/// @param [in,out] cache Cache object. Contains field cell used for
/// @return magnetic field vector
virtual Vector3 getFieldGradient(const Vector3& position,
ActsMatrix<3, 3>& derivative,
Cache& cache) const = 0;
};

} // namespace Acts

0 comments on commit 46309cd

Please sign in to comment.