15#include <G4FieldManager.hh>
16#include <G4LogicalVolumeStore.hh>
17#include <G4ProductionCuts.hh>
19#include <G4SDManager.hh>
21#include <G4VUserDetectorConstruction.hh>
27#include "FieldService/G4MagFieldAdapter.h"
28#include "FieldService/IFieldSource.h"
40 ship::IFieldSource
const* field_source_;
42 ship::Energy ke_threshold_;
43 std::vector<std::pair<std::string, ship::Length>>
53 [[nodiscard]] std::vector<G4LogicalVolume*> detector_volumes()
const {
54 std::vector<G4LogicalVolume*> volumes;
55 for (
auto* lv : *G4LogicalVolumeStore::GetInstance()) {
56 if (scoring_world_ ==
nullptr || !scoring_world_->
contains(lv)) {
57 volumes.push_back(lv);
67 ship::Energy ke_threshold = ship::Energy::zero(),
68 std::vector<std::pair<std::string, ship::Length>> regions = {},
69 std::vector<ScoringPlaneConfig> scoring_planes = {})
71 field_source_{&field_source},
73 ke_threshold_{ke_threshold},
74 regions_{std::move(regions)} {
79 throw std::invalid_argument(
81 " sensitive_volumes patterns are supported (detector id " +
83 " is reserved for scoring planes)");
85 if (!scoring_planes.empty()) {
86 scoring_world_ =
new ScoringParallelWorld(std::move(scoring_planes));
87 RegisterParallelWorld(scoring_world_);
94 return scoring_world_ !=
nullptr;
108 for (
auto const& [pattern, cut] : regions_) {
109 auto* region =
new G4Region(pattern);
110 auto* cuts =
new G4ProductionCuts();
112 region->SetProductionCuts(cuts);
113 bool matched =
false;
114 for (
auto* lv : *G4LogicalVolumeStore::GetInstance()) {
115 if (G4StrUtil::contains(lv->GetName(), std::string_view{pattern})) {
116 region->AddRootLogicalVolume(lv);
121 throw std::runtime_error(
"Production-cut region '" + pattern +
122 "' matches no logical volumes");
133 auto const volumes = detector_volumes();
134 for (
auto* lv : volumes) {
135 for (
int i = 0; std::cmp_less(i, sv_names.size()); ++i) {
136 if (G4StrUtil::contains(lv->GetName(), std::string_view{sv_names[i]})) {
137 detector_ids.emplace(lv, i);
143 G4VSensitiveDetector* sd =
nullptr;
145 sd =
new CrossingSD(
"CrossingSD", detector_ids, ke_threshold_);
147 sd =
new ScoringSD(
"ScoringSD", detector_ids);
149 G4SDManager::GetSDMpointer()->AddNewDetector(sd);
151 for (
auto [lv, _] : detector_ids) {
152 lv->SetSensitiveDetector(sd);
160 for (
auto const& fr : field_source_->regions()) {
161 auto* adapter =
new ship::G4MagFieldAdapter(fr.field);
162 auto* fmgr =
new G4FieldManager(adapter);
163 bool matched =
false;
164 for (
auto* lv : volumes) {
165 if (G4StrUtil::contains(lv->GetName(),
166 std::string_view{fr.volume_pattern})) {
167 lv->SetFieldManager(fmgr,
true);
172 throw std::runtime_error(
"Field region '" + fr.name +
173 "': volume_pattern '" + fr.volume_pattern +
174 "' 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:37
G4VPhysicalVolume * Construct() override
Definition detector_construction.hpp:99
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={}, std::vector< ScoringPlaneConfig > scoring_planes={})
Definition detector_construction.hpp:64
bool has_scoring_planes() const
Whether scoring planes are configured, i.e.
Definition detector_construction.hpp:93
void ConstructSDandField() override
Definition detector_construction.hpp:129
Definition geant4_sim_core.hpp:86
The parallel world holding the scoring planes.
Definition scoring_planes.hpp:515
bool contains(G4LogicalVolume *lv) const
Whether lv belongs to this world (a plane or the world volume), so that detector-geometry patterns (s...
Definition scoring_planes.hpp:543
Definition geant4_sim_core.hpp:61
Definition detector_construction.hpp:33
constexpr std::int32_t kScoringPlaneDetectorId
SimHit::detectorId of every scoring-plane hit.
Definition scoring_plane_id.hpp:21
SDMode
Definition detector_construction.hpp:35
std::unordered_map< G4LogicalVolume *, int > DetectorIdMap
Definition geant4_sim_core.hpp:33
G4double g4(ship::Length l)
Definition clhep_bridge.hpp:51