Skip to content

Commit

Permalink
feat: Add DD4hep field adapter (#2593)
Browse files Browse the repository at this point in the history
This allows querying the DD4hep-provided magnetic field for our purposes.

You can define a constant field like

```xml
<field name="MagnetFields_Constant" type="ConstantField" field="magnetic">
  <strength x="0" y="0" z="2.0*tesla"/>
</field>
```

or for example a solenoid field like

```xml
<field type="solenoid" name="GlobalSolenoid" inner_field="Field_nominal_value"
   outer_field="outerField_nominal_value" zmax="sol_hlength"
   inner_radius="sol_rmin"
   outer_radius="sol_rmax" />
```
  • Loading branch information
paulgessinger authored Nov 16, 2023
1 parent 040a896 commit ecdbde7
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 2 deletions.
1 change: 1 addition & 0 deletions Core/include/Acts/MagneticField/MagneticFieldError.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace Acts {

enum class MagneticFieldError {
OutOfBounds = 1,
NotImplemented = 2,
};

std::error_code make_error_code(Acts::MagneticFieldError e);
Expand Down
2 changes: 2 additions & 0 deletions Core/src/MagneticField/MagneticFieldError.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class MagneticFieldErrorCategory : public std::error_category {
switch (static_cast<MagneticFieldError>(c)) {
case MagneticFieldError::OutOfBounds:
return "Interpolation out of bounds was requested";
case MagneticFieldError::NotImplemented:
return "The requested functionality is not implemented";
default:
return "unknown";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#pragma once

#include "Acts/MagneticField/MagneticFieldProvider.hpp"
#include "Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp"
#include "ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp"

#include <memory>
Expand Down Expand Up @@ -44,6 +46,8 @@ struct DD4hepDetector {
std::pair<TrackingGeometryPtr, ContextDecorators> finalize(
DD4hepGeometryService::Config config,
std::shared_ptr<const Acts::IMaterialDecorator> mdecorator);

std::shared_ptr<Acts::DD4hepFieldAdapter> field() const;
};

} // namespace DD4hep
Expand Down
11 changes: 11 additions & 0 deletions Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@
#include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp"

#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/MagneticField/MagneticFieldProvider.hpp"
#include "Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp"
#include "ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp"

#include <cstddef>
#include <memory>
#include <stdexcept>

#include <DD4hep/Fields.h>
#include <boost/program_options.hpp>

namespace ActsExamples {
Expand Down Expand Up @@ -46,5 +51,11 @@ auto DD4hepDetector::finalize(
std::move(dd4tGeometry), std::move(dd4ContextDecorators));
}

std::shared_ptr<Acts::DD4hepFieldAdapter> DD4hepDetector::field() const {
const auto& detector = geometryService->detector();

return std::make_shared<Acts::DD4hepFieldAdapter>(detector.field());
}

} // namespace DD4hep
} // namespace ActsExamples
10 changes: 9 additions & 1 deletion Examples/Python/src/DD4hepComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// 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/.

#include "Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp"
#include "Acts/Plugins/Python/Utilities.hpp"
#include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp"
#include "ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp"
Expand Down Expand Up @@ -54,13 +55,20 @@ PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) {
patchKwargsConstructor(c);
}

{
py::class_<Acts::DD4hepFieldAdapter, Acts::MagneticFieldProvider,
std::shared_ptr<Acts::DD4hepFieldAdapter>>(m,
"DD4hepFieldAdapter");
}

{
py::class_<DD4hep::DD4hepDetector, std::shared_ptr<DD4hep::DD4hepDetector>>(
m, "DD4hepDetector")
.def(py::init<>())
.def("finalize",
py::overload_cast<DD4hep::DD4hepGeometryService::Config,
std::shared_ptr<const Acts::IMaterialDecorator>>(
&DD4hep::DD4hepDetector::finalize));
&DD4hep::DD4hepDetector::finalize))
.def_property_readonly("field", &DD4hep::DD4hepDetector::field);
}
}
4 changes: 3 additions & 1 deletion Plugins/DD4hep/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ add_library(
src/DD4hepDetectorSurfaceFactory.cpp
src/DD4hepLayerBuilder.cpp
src/DD4hepLayerStructure.cpp
src/DD4hepVolumeBuilder.cpp)
src/DD4hepVolumeBuilder.cpp
src/DD4hepFieldAdapter.cpp)

target_include_directories(
ActsPluginDD4hep
PUBLIC
Expand Down
43 changes: 43 additions & 0 deletions Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// This file is part of the Acts project.
//
// Copyright (C) 2023 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/MagneticField/MagneticFieldProvider.hpp"

#include <memory>

namespace dd4hep {
class OverlayedField;
}

namespace Acts {

class DD4hepFieldAdapter : public Acts::MagneticFieldProvider {
struct Cache {};

public:
DD4hepFieldAdapter(dd4hep::OverlayedField field);

MagneticFieldProvider::Cache makeCache(
const Acts::MagneticFieldContext& mctx) const override;

Result<Vector3> getField(const Vector3& position,
MagneticFieldProvider::Cache& cache) const override;

Result<Vector3> getFieldGradient(
const Vector3& position, ActsMatrix<3, 3>& derivative,
MagneticFieldProvider::Cache& cache) const override;

private:
double m_fieldConversionFactor;
double m_lengthConversionFactor;
std::unique_ptr<dd4hep::OverlayedField> m_field;
};

} // namespace Acts
59 changes: 59 additions & 0 deletions Plugins/DD4hep/src/DD4hepFieldAdapter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// This file is part of the Acts project.
//
// Copyright (C) 2023 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/.

#include "Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp"

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Definitions/Units.hpp"
#include "Acts/MagneticField/MagneticFieldContext.hpp"
#include "Acts/MagneticField/MagneticFieldError.hpp"
#include "Acts/MagneticField/MagneticFieldProvider.hpp"

#include <DD4hep/Fields.h>
#include <DD4hep/Handle.h>
#include <DD4hep/Objects.h>

namespace Acts {

DD4hepFieldAdapter::DD4hepFieldAdapter(dd4hep::OverlayedField field)
: m_field{std::make_unique<dd4hep::OverlayedField>(field)} {
m_fieldConversionFactor =
dd4hep::_toDouble("1/tesla") * Acts::UnitConstants::T;
m_lengthConversionFactor =
dd4hep::_toDouble("1*mm") / Acts::UnitConstants::mm;
}

MagneticFieldProvider::Cache DD4hepFieldAdapter::makeCache(
const Acts::MagneticFieldContext& /*mctx*/) const {
return MagneticFieldProvider::Cache::make<Cache>();
}

Result<Vector3> DD4hepFieldAdapter::getField(
const Vector3& position, MagneticFieldProvider::Cache& /*cache*/) const {
dd4hep::Position dd4hepPosition{position.x(), position.y(), position.z()};

// ACTS mm -> dd4hep mm
dd4hepPosition *= m_lengthConversionFactor;

const auto direction = m_field->combinedMagnetic(dd4hepPosition);

Vector3 result{direction.x(), direction.y(), direction.z()};

// dd4hep tesla -> ACTS tesla
result *= m_fieldConversionFactor;

return Result<Vector3>::success(result);
}

Result<Vector3> DD4hepFieldAdapter::getFieldGradient(
const Vector3& /*position*/, ActsMatrix<3, 3>& /*derivative*/,
MagneticFieldProvider::Cache& /*cache*/) const {
return Result<Vector3>::failure(MagneticFieldError::NotImplemented);
}

} // namespace Acts
9 changes: 9 additions & 0 deletions docs/plugins/dd4hep.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,12 @@ To receive the {class}`Acts::TrackingGeometry` the global function
`DetElement` needs to be handed over. For a valid translation, that all
prerequisites described above are met and that the right `VariantParameters`
are added during the DD4hep construction.


## DD4hep field adapter

The DD4hep plugins ships with an adapter class that connects a DD4hep-defined
field to the {class}`Acts::MagneticFieldProvider` interface:

:::{doxygenclass} Acts::DD4hepFieldAdapter
:::

0 comments on commit ecdbde7

Please sign in to comment.