13#include <G4FieldManager.hh>
14#include <G4LogicalVolumeStore.hh>
15#include <G4ProductionCuts.hh>
17#include <G4SDManager.hh>
19#include <G4VUserDetectorConstruction.hh>
25#include "FieldService/G4MagFieldAdapter.h"
26#include "FieldService/IFieldSource.h"
37 ship::IFieldSource
const* field_source_;
39 ship::Energy ke_threshold_;
40 std::vector<std::pair<std::string, ship::Length>>
47 ship::Energy ke_threshold = ship::Energy::zero(),
48 std::vector<std::pair<std::string, ship::Length>> regions = {})
50 field_source_{&field_source},
52 ke_threshold_{ke_threshold},
53 regions_{std::move(regions)} {}
66 for (
auto const& [pattern, cut] : regions_) {
67 auto* region =
new G4Region(pattern);
68 auto* cuts =
new G4ProductionCuts();
70 region->SetProductionCuts(cuts);
72 for (
auto* lv : *G4LogicalVolumeStore::GetInstance()) {
73 if (G4StrUtil::contains(lv->GetName(), std::string_view{pattern})) {
74 region->AddRootLogicalVolume(lv);
79 throw std::runtime_error(
"Production-cut region '" + pattern +
80 "' matches no logical volumes");
90 for (
auto* lv : *G4LogicalVolumeStore::GetInstance()) {
91 for (
int i = 0; i < static_cast<int>(sv_names.size()); ++i) {
92 if (G4StrUtil::contains(lv->GetName(), std::string_view{sv_names[i]})) {
93 detector_ids.emplace(lv, i);
99 G4VSensitiveDetector* sd =
nullptr;
101 sd =
new CrossingSD(
"CrossingSD", detector_ids, ke_threshold_);
103 sd =
new ScoringSD(
"ScoringSD", detector_ids);
105 G4SDManager::GetSDMpointer()->AddNewDetector(sd);
107 for (
auto [lv, _] : detector_ids) {
108 lv->SetSensitiveDetector(sd);
116 for (
auto const& fr : field_source_->regions()) {
117 auto* adapter =
new ship::G4MagFieldAdapter(fr.field);
118 auto* fmgr =
new G4FieldManager(adapter);
119 bool matched =
false;
120 for (
auto* lv : *G4LogicalVolumeStore::GetInstance()) {
121 if (G4StrUtil::contains(lv->GetName(),
122 std::string_view{fr.volume_pattern})) {
123 lv->SetFieldManager(fmgr,
true);
128 throw std::runtime_error(
"Field region '" + fr.name +
129 "': volume_pattern '" + fr.volume_pattern +
130 "' matches no logical volumes");
Definition geometry_source.hpp:20
virtual G4VPhysicalVolume * construct() const =0
Build or return the cached G4 world volume.
virtual std::vector< std::string > const & sensitiveVolumes() const =0
Volume names to assign sensitive detectors to.
Definition detector_construction.hpp:34
ConfigurableDetectorConstruction(IGeometrySource const &source, ship::IFieldSource const &field_source, SDMode sd_mode=SDMode::scoring, ship::Energy ke_threshold=ship::Energy::zero(), std::vector< std::pair< std::string, ship::Length > > regions={})
Definition detector_construction.hpp:44
G4VPhysicalVolume * Construct() override
Definition detector_construction.hpp:57
void ConstructSDandField() override
Definition detector_construction.hpp:86
Definition geant4_sim_core.hpp:76
Definition geant4_sim_core.hpp:53
Definition detector_construction.hpp:30
SDMode
Definition detector_construction.hpp:32
std::unordered_map< G4LogicalVolume *, int > DetectorIdMap
Definition geant4_sim_core.hpp:33
G4double g4(ship::Length l)
Definition clhep_bridge.hpp:51