Skip to content

Commit

Permalink
feat: rework Geant4 simulation (2/X) (#977)
Browse files Browse the repository at this point in the history
This PR is the second pull request for the Geant4 simulation and introduces the full simulation for single particles.
It uses the same Geant4Simulation algorithm and establishes a symmetric setup between Fatras and Geant4 simulation.

e.g. Fatras:

./ActsExamplesFatrasDD4hep <args>
and Geant4:

./ActsExamplesGeant4DD4hep <args>
Can now be run with the same argument list.
  • Loading branch information
asalzburger committed Sep 6, 2021
1 parent 2189de2 commit 7172909
Show file tree
Hide file tree
Showing 18 changed files with 823 additions and 17 deletions.
4 changes: 4 additions & 0 deletions Examples/Algorithms/Geant4/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ set(ACTS_EXAMPLES_G4SOURCES
src/GdmlDetectorConstruction.cpp
src/Geant4Options.cpp
src/Geant4Simulation.cpp
src/MagneticFieldWrapper.cpp
src/MaterialPhysicsList.cpp
src/MaterialSteppingAction.cpp
src/ParticleTrackingAction.cpp
src/SensitiveSurfaceMapper.cpp
src/SensitiveSteppingAction.cpp
src/SimParticleTranslation.cpp)

if (ACTS_BUILD_EXAMPLES_DD4HEP)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class G4MagneticField;

namespace ActsExamples {

class Geant4SurfaceMapper;
class SensitiveSurfaceMapper;

/// Algorithm to run Geant4 simulation in the ActsExamples framework
///
Expand Down Expand Up @@ -80,8 +80,12 @@ class Geant4Simulation final : public BareAlgorithm {
/// Detector construction object.
G4VUserDetectorConstruction* detectorConstruction = nullptr;

/// The ACTS Magnetic field provider
/// The (wrapped) ACTS Magnetic field provider as a Geant4 module
G4MagneticField* magneticField = nullptr;

// The ACTS to Geant4 sensitive wrapper
std::shared_ptr<const SensitiveSurfaceMapper> sensitiveSurfaceMapper =
nullptr;
};

/// Constructor with arguments
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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/Utilities/Logger.hpp"

#include <memory>

#include <G4MagneticField.hh>

namespace Acts {
class MagneticFieldProvider;
}

namespace ActsExamples {

/// A magnetic field wrapper for the Acts magnetic field
/// to be used with Geant4.
class MagneticFieldWrapper : public G4MagneticField {
public:
/// Configuration of the Magnetic Field Action
struct Config {
/// Access to the ACTS magnetic field
std::shared_ptr<const Acts::MagneticFieldProvider> magneticField = nullptr;
};

/// Construct the magnetic field action
///
/// @param cfg the configuration struct
/// @param logger the ACTS logging instance
MagneticFieldWrapper(const Config& cfg,
std::unique_ptr<const Acts::Logger> logger =
Acts::getDefaultLogger("MagneticFieldWrapper",
Acts::Logging::INFO));
~MagneticFieldWrapper() override = default;

/// Public get field interface
///
/// @param Point is the field request point
/// @param Bfield [in,out] is the field value
///
void GetFieldValue(const G4double Point[4], G4double* Bfield) const final;

protected:
Config m_cfg;

private:
/// Private access method to the logging instance
const Acts::Logger& logger() const { return *m_logger; }

/// The looging instance
std::unique_ptr<const Acts::Logger> m_logger;
};

} // namespace ActsExamples
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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/Utilities/Logger.hpp"
#include "ActsExamples/EventData/SimParticle.hpp"

#include <memory>
#include <string>

#include <G4Track.hh>
#include <G4UserTrackingAction.hh>

namespace ActsExamples {

/// The G4UserTrackingAction that is called for every track in
/// the simulation process.
///
/// It records the initial and final particle state
class ParticleTrackingAction : public G4UserTrackingAction {
public:
struct Config {};

/// Construct the stepping action
///
/// @param cfg the configuration struct
/// @param logger the ACTS logging instance
ParticleTrackingAction(const Config& cfg,
std::unique_ptr<const Acts::Logger> logger =
Acts::getDefaultLogger("ParticleTrackingAction",
Acts::Logging::INFO));
~ParticleTrackingAction() override = default;

/// Action before the track is processed in the
/// the simulation, this will record the initial particle
///
/// @param aTrack the current Geant4 track
void PreUserTrackingAction(const G4Track* aTrack) final;

/// Action after the track is processed in the
/// the simulation, this will record the final particle
///
/// @param aTrack the current Geant4 track
void PostUserTrackingAction(const G4Track* aTrack) final;

protected:
Config m_cfg;

private:
/// Convert a G4Track to a SimParticle
///
/// @param aTrack the current Geant4 track
SimParticle convert(const G4Track& aTrack) const;

/// Private access method to the logging instance
const Acts::Logger& logger() const { return *m_logger; }

/// The looging instance
std::unique_ptr<const Acts::Logger> m_logger;
};

} // namespace ActsExamples
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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/Utilities/Logger.hpp"

#include <memory>
#include <string>

#include <G4UserSteppingAction.hh>

namespace ActsExamples {

/// The G4SteppingAction that is called for every step in
/// the simulation process.
///
/// It checks whether a sensitive volume is present (via string tag)
/// and records (if necessary) the hit.
class SensitiveSteppingAction : public G4UserSteppingAction {
public:
/// Configuration of the Stepping action
struct Config {
/// Selection for hit recording
bool charged = true;
bool neutral = false;
bool primary = true;
bool secondary = false;
};

/// Construct the stepping action
///
/// @param cfg the configuration struct
/// @param logger the ACTS logging instance
SensitiveSteppingAction(const Config& cfg,
std::unique_ptr<const Acts::Logger> logger =
Acts::getDefaultLogger("SensitiveSteppingAction",
Acts::Logging::INFO));
~SensitiveSteppingAction() override = default;

/// @brief Interface Method doing the step and records the data
/// @param step is the Geant4 step of the particle
void UserSteppingAction(const G4Step* step) final override;

protected:
Config m_cfg;

private:
/// Private access method to the logging instance
const Acts::Logger& logger() const { return *m_logger; }

/// The looging instance
std::unique_ptr<const Acts::Logger> m_logger;
};

} // namespace ActsExamples
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// 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/Utilities/Logger.hpp"

#include <memory>
#include <string>
#include <vector>

class G4VPhysicalVolume;

namespace Acts {
class TrackingGeometry;
}

namespace ActsExamples {

/// This Mapper takes a (non-const) Geant4 geometry and maps
/// it such that name will be containing the mapping prefix
/// and the Acts::GeometryIdentifier of the surface.
///
/// This allows to directly associate Geant4 hits to the sensitive
/// elements of the Acts::TrackingGeoemtry w/o map lookup.
class SensitiveSurfaceMapper {
public:
static constexpr const char* mappingPrefix = "ActsGeoID#";

/// Configuration struct for the surface mapper
struct Config {
std::vector<std::string> materialMappings = {"Silicon"};
std::vector<std::string> volumeMappings = {};

std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry = nullptr;
};

/// Constructor with:
///
/// @param cfg the configuration struct
/// @param logger the logging instance
SensitiveSurfaceMapper(const Config& cfg,
std::unique_ptr<const Acts::Logger> logger =
Acts::getDefaultLogger("SensitiveSurfaceMapper",
Acts::Logging::INFO));
~SensitiveSurfaceMapper() = default;

/// Recursive mapping function that walks through the Geant4
/// hierarchy and applies name remapping to the Physical volumes
/// of the Geant4 geometry.
///
/// @param g4PhysicalVolume the current physical volume in process
/// @param motherPosition the absolute position of the mother
/// @param sCounter a counter of how many volumes have been remapped
void remapSensitiveNames(G4VPhysicalVolume* g4PhysicalVolume,
const Acts::Vector3 motherPosition,
int& sCounter) const;

protected:
/// Configuration object
Config m_cfg;

private:
/// Private access method to the logging instance
const Acts::Logger& logger() const { return *m_logger; }

/// The looging instance
std::unique_ptr<const Acts::Logger> m_logger;
};

} // namespace ActsExamples
14 changes: 14 additions & 0 deletions Examples/Algorithms/Geant4/src/Geant4Simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "Acts/Utilities/Logger.hpp"
#include "ActsExamples/Framework/WhiteBoard.hpp"
#include "ActsExamples/Geant4/EventStoreRegistry.hpp"
#include "ActsExamples/Geant4/SensitiveSurfaceMapper.hpp"

#include <iostream>
#include <stdexcept>
Expand Down Expand Up @@ -88,6 +89,19 @@ ActsExamples::Geant4Simulation::Geant4Simulation(
// Propagate down to all childrend
g4World->GetLogicalVolume()->SetFieldManager(fieldMgr, true);
}

// Map simulation to reconstruction geometry
if (m_cfg.sensitiveSurfaceMapper != nullptr) {
ACTS_INFO(
"Remapping selected volumes from Geant4 to Acts::Surface::GeometryID");

G4VPhysicalVolume* g4World = m_cfg.detectorConstruction->Construct();
int sCounter = 0;
m_cfg.sensitiveSurfaceMapper->remapSensitiveNames(
g4World, Acts::Vector3(0., 0., 0.), sCounter);

ACTS_INFO("Remapping successful for " << sCounter << " selected volumes.");
}
}

ActsExamples::Geant4Simulation::~Geant4Simulation() {}
Expand Down
43 changes: 43 additions & 0 deletions Examples/Algorithms/Geant4/src/MagneticFieldWrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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/.

#include "ActsExamples/Geant4/MagneticFieldWrapper.hpp"

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

#include <G4SystemOfUnits.hh>
#include <G4UnitsTable.hh>

ActsExamples::MagneticFieldWrapper::MagneticFieldWrapper(
const Config& cfg, std::unique_ptr<const Acts::Logger> logger)
: G4MagneticField(), m_cfg(cfg), m_logger(std::move(logger)) {}

void ActsExamples::MagneticFieldWrapper::GetFieldValue(const G4double Point[4],
G4double* Bfield) const {
constexpr double convertLength = CLHEP::mm / Acts::UnitConstants::mm;
constexpr double convertField = CLHEP::tesla / Acts::UnitConstants::T;

auto bCache = m_cfg.magneticField->makeCache(Acts::MagneticFieldContext());

auto fieldRes = m_cfg.magneticField->getField(
{convertLength * Point[0], convertLength * Point[1],
convertLength * Point[2]},
bCache);
if (!fieldRes.ok()) {
ACTS_ERROR("Field lookup error: " << fieldRes.error());
return;
}
// Get the field now
const Acts::Vector3& field = *fieldRes;

Bfield[0] = convertField * field[0];
Bfield[1] = convertField * field[1];
Bfield[2] = convertField * field[2];
}

0 comments on commit 7172909

Please sign in to comment.