Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4VUserDetectorConstruction.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4VUserDetectorConstruction implementation
27//
28// Original author: M.Asai, 1999
29// --------------------------------------------------------------------
30
32
33#include "G4FieldManager.hh"
34#include "G4LogicalVolume.hh"
37#include "G4RunManager.hh"
38#include "G4SDManager.hh"
39#include "G4VPhysicalVolume.hh"
42
43#include <cassert>
44#include <map>
45#include <sstream>
46
47// --------------------------------------------------------------------
49{
50 auto pwItr = std::find(parallelWorld.cbegin(), parallelWorld.cend(), aPW);
51 if (pwItr != parallelWorld.cend()) {
52 G4String eM = "A parallel world <";
53 eM += aPW->GetName();
54 eM += "> is already registered to the user detector construction.";
55 G4Exception("G4VUserDetectorConstruction::RegisterParallelWorld", "Run0051",
57 }
58 parallelWorld.push_back(aPW);
59}
60
61// --------------------------------------------------------------------
63{
64 G4int nP = 0;
65 for (const auto& pwItr : parallelWorld) {
66 pwItr->Construct();
67 ++nP;
68 }
69 return nP;
70}
71
72// --------------------------------------------------------------------
74{
75 for (const auto& pwItr : parallelWorld) {
76 pwItr->ConstructSD();
77 }
78}
79
80// --------------------------------------------------------------------
82{
83 return (G4int)parallelWorld.size();
84}
85
86// --------------------------------------------------------------------
88{
89 if (i < 0 || i >= GetNumberOfParallelWorld()) return nullptr;
90 return parallelWorld[i];
91}
92
93// --------------------------------------------------------------------
95
96// --------------------------------------------------------------------
98{
99 using FMtoFMmap = std::map<G4FieldManager*, G4FieldManager*>;
100 using FMpair = std::pair<G4FieldManager*, G4FieldManager*>;
101
102 FMtoFMmap masterToWorker;
104 for (const auto& g4LogicalVolume : *logVolStore) {
105 // Use shadow of master to get instance of FM
106 G4FieldManager* masterFM = nullptr; // g4LogicalVolume->fFieldManager;
107 G4FieldManager* clonedFM = nullptr;
108 if (masterFM != nullptr) {
109 auto fmFound = masterToWorker.find(masterFM);
110 if (fmFound == masterToWorker.cend()) {
111 // First time we see this SD, let's clone and remember...
112 try {
113 auto insertedEl = masterToWorker.insert(FMpair(masterFM, masterFM->Clone()));
114 clonedFM = (insertedEl.first)->second;
115 }
116 catch (...) {
118 msg << "Cloning of G4FieldManager failed."
119 << " But derived class does not implement cloning. Cannot "
120 "continue.";
121 G4Exception("G4VUserDetectorConstruction::CloneSD()", "Run0053", FatalException, msg);
122 }
123 }
124 else {
125 // We have already seen this SD attached to a different LogicalVolume,
126 // let's re-use previous clone
127 clonedFM = (*fmFound).second;
128 }
129 } // masterFM != 0
130 // Note that we do not push FM to daughters (false argument), however, since
131 // we area looping on all logical volumes and we implemented the "trick" of
132 // the map master<->cloned the final effect is the same as using here the
133 // correct Boolean flag: log-volumes that originally were sharing the same
134 // FM they will have cloned ones
135 g4LogicalVolume->SetFieldManager(clonedFM, false);
136 }
137}
138
139// --------------------------------------------------------------------
141{
142 // Loop on ALL logial volumes to search for attached SD
144
145 using SDtoSDmap = std::map<G4VSensitiveDetector*, G4VSensitiveDetector*>;
146 using SDpair = std::pair<G4VSensitiveDetector*, G4VSensitiveDetector*>;
147 SDtoSDmap masterToWorker;
148
149 for (const auto& g4LogicalVolume : *logVolStore) {
150 // Use shadow of master to get the instance of SD
151 G4VSensitiveDetector* masterSD = nullptr;
152 G4VSensitiveDetector* clonedSD = nullptr;
153 if (masterSD != nullptr) {
154 auto sdFound = masterToWorker.find(masterSD);
155 if (sdFound == masterToWorker.cend()) {
156 // First time we see this SD, let's clone and remember...
157 try {
158 auto insertedEl = masterToWorker.insert(SDpair(masterSD, masterSD->Clone()));
159 clonedSD = (insertedEl.first)->second;
160 }
161 catch (...) {
163 msg << "Cloning of G4VSensitiveDetector requested for:" << masterSD->GetName() << "\n"
164#ifndef WIN32
165 << " (full path name: " << masterSD->GetFullPathName() << ").\n"
166#endif
167 << " But derived class does not implement cloning. Cannot "
168 "continue.";
169 G4Exception("G4VUserDetectorConstruction::CloneSD()", "Run0053", FatalException, msg);
170 }
171 }
172 else {
173 // We have already seen this SD attached to a different LogicalVolume,
174 // let's re-use previous clone
175 clonedSD = (*sdFound).second;
176 }
177 } // masterSD!=0
178 g4LogicalVolume->SetSensitiveDetector(clonedSD);
179 }
180}
181
182// --------------------------------------------------------------------
184 G4VSensitiveDetector* aSD, G4bool multi)
185{
186 G4bool found = false;
188 auto volmap = store->GetMap();
189 auto pos = volmap.find(logVolName);
190 if (pos != volmap.cend()) {
191 if ((pos->second.size() > 1) && !multi) {
192 G4String eM = "More than one logical volumes of name <";
193 eM += pos->first;
194 eM += "> are found and thus the sensitive detector <";
195 eM += aSD->GetName();
196 eM += "> cannot be uniquely assigned.";
197 G4Exception("G4VUserDetectorConstruction::SetSensitiveDetector()", "Run0052",
199 }
200 found = true;
201 for (auto& i : pos->second) {
202 SetSensitiveDetector(i, aSD);
203 }
204 }
205 if (!found) {
206 G4String eM2 = "No logical volume of name <";
207 eM2 += logVolName;
208 eM2 += "> is found. The specified sensitive detector <";
209 eM2 += aSD->GetName();
210 eM2 += "> couldn't be assigned to any volume.";
211 G4Exception("G4VUserDetectorConstruction::SetSensitiveDetector()", "Run0053",
213 }
214}
215
216// --------------------------------------------------------------------
219{
220 assert(logVol != nullptr && aSD != nullptr);
221
222 // The aSD has already been added by user to the manager if needed
223 // G4SDManager::GetSDMpointer()->AddNewDetector(aSD);
224
225 // New Logic: allow for "multiple" SDs being attached to a single LV.
226 // To do that we use a special proxy SD called G4MultiSensitiveDetector
227
228 // Get existing SD if already set and check if it is of the special type
229 G4VSensitiveDetector* originalSD = logVol->GetSensitiveDetector();
230 if (originalSD == aSD) {
232 msg << "Attempting to add multiple times the same sensitive detector (\"";
233 msg << originalSD->GetName() << "\") is not allowed, skipping.";
234 G4Exception("G4VUserDetectorConstruction::SetSensitiveDetector", "Run0054", JustWarning, msg);
235 return;
236 }
237 if (originalSD == nullptr) {
238 logVol->SetSensitiveDetector(aSD);
239 }
240 else {
241 auto msd = dynamic_cast<G4MultiSensitiveDetector*>(originalSD);
242 if (msd != nullptr) {
243 msd->AddSD(aSD);
244 }
245 else {
246 std::ostringstream mn;
247 mn << "/MultiSD_" << logVol->GetName() << "_" << logVol;
248 const G4String msdname = mn.str();
249 msd = new G4MultiSensitiveDetector(msdname);
250 // We need to register the proxy to have correct handling of IDs
252 msd->AddSD(originalSD);
253 msd->AddSD(aSD);
254 logVol->SetSensitiveDetector(msd);
255 }
256 }
257}
@ JustWarning
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
virtual G4FieldManager * Clone() const
const std::map< G4String, std::vector< G4LogicalVolume * > > & GetMap() const
static G4LogicalVolumeStore * GetInstance()
G4VSensitiveDetector * GetSensitiveDetector() const
const G4String & GetName() const
void SetSensitiveDetector(G4VSensitiveDetector *pSDetector)
static G4SDManager * GetSDMpointer()
void AddNewDetector(G4VSensitiveDetector *aSD)
virtual G4VSensitiveDetector * Clone() const
G4String GetFullPathName() const
G4VUserParallelWorld * GetParallelWorld(G4int i) const
void RegisterParallelWorld(G4VUserParallelWorld *)
void SetSensitiveDetector(const G4String &logVolName, G4VSensitiveDetector *aSD, G4bool multi=false)
const G4String & GetName()