File: | scratch/gluex/scan-build-work/hdgeant4/src/GlueXDetectorConstruction.cc |
Location: | line 164, column 7 |
Description: | Value stored to 'docEl' is never read |
1 | // |
2 | // GlueXDetectorConstruction class implementation |
3 | // |
4 | // author: richard.t.jones at uconn.edu |
5 | // version: may 12, 2012 |
6 | |
7 | #include "GlueXDetectorConstruction.hh" |
8 | #include "GlueXDetectorMessenger.hh" |
9 | #include "GlueXMagneticField.hh" |
10 | #include "HddmOutput.hh" |
11 | |
12 | #include "GlueXSensitiveDetectorCDC.hh" |
13 | #include "GlueXSensitiveDetectorFDC.hh" |
14 | #include "GlueXSensitiveDetectorSTC.hh" |
15 | #include "GlueXSensitiveDetectorBCAL.hh" |
16 | #include "GlueXSensitiveDetectorFCAL.hh" |
17 | #include "GlueXSensitiveDetectorFCALinsert.hh" |
18 | #include "GlueXSensitiveDetectorGCAL.hh" |
19 | #include "GlueXSensitiveDetectorCCAL.hh" |
20 | #include "GlueXSensitiveDetectorFTOF.hh" |
21 | #include "GlueXSensitiveDetectorDIRC.hh" |
22 | #include "GlueXSensitiveDetectorCERE.hh" |
23 | #include "GlueXSensitiveDetectorFMWPC.hh" |
24 | #include "GlueXSensitiveDetectorUPV.hh" |
25 | #include "GlueXSensitiveDetectorPSC.hh" |
26 | #include "GlueXSensitiveDetectorPS.hh" |
27 | #include "GlueXSensitiveDetectorTPOL.hh" |
28 | #include "GlueXSensitiveDetectorCTOF.hh" |
29 | |
30 | |
31 | #include "G4Version.hh" |
32 | #include "G4LogicalVolume.hh" |
33 | #include "G4PVPlacement.hh" |
34 | #include "G4SDManager.hh" |
35 | #include "G4RunManager.hh" |
36 | #include "G4LogicalVolumeStore.hh" |
37 | #include "G4TransportationManager.hh" |
38 | #include "G4MagIntegratorDriver.hh" |
39 | #include "G4ChordFinder.hh" |
40 | #include "G4Mag_UsualEqRhs.hh" |
41 | #include "G4ExactHelixStepper.hh" |
42 | #include "G4HelixMixedStepper.hh" |
43 | #include "G4ClassicalRK4.hh" |
44 | |
45 | #include "G4SystemOfUnits.hh" |
46 | |
47 | #include "G4VisAttributes.hh" |
48 | |
49 | #include "G4ios.hh" |
50 | |
51 | #include <xercesc/util/PlatformUtils.hpp> |
52 | #include <xercesc/util/XMLString.hpp> |
53 | #include <xercesc/util/XMLStringTokenizer.hpp> |
54 | #include <xercesc/sax/SAXParseException.hpp> |
55 | #include <xercesc/parsers/XercesDOMParser.hpp> |
56 | #include <xercesc/framework/LocalFileFormatTarget.hpp> |
57 | #include <xercesc/dom/DOM.hpp> |
58 | #include <xercesc/util/XercesDefs.hpp> |
59 | #include <xercesc/sax/ErrorHandler.hpp> |
60 | |
61 | using namespace xercesc; |
62 | |
63 | #include "XString.hpp" |
64 | #include "XParsers.hpp" |
65 | |
66 | #include <string.h> |
67 | #include <libgen.h> |
68 | #include <errno(*__errno_location ()).h> |
69 | |
70 | #define X(str)XString(str).unicode_str() XString(str).unicode_str() |
71 | #define S(str)str.c_str() str.c_str() |
72 | |
73 | #define APP_NAME"HDGeant4" "HDGeant4" |
74 | |
75 | G4Mutex GlueXDetectorConstruction::fMutex = G4MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } }; |
76 | std::list<GlueXDetectorConstruction*> GlueXDetectorConstruction::fInstance; |
77 | |
78 | GlueXDetectorConstruction::GlueXDetectorConstruction(G4String hddsFile) |
79 | : fMaxStep(0), |
80 | fUniformField(0), |
81 | fpMagneticField(0), |
82 | fGeometryXML(0) |
83 | { |
84 | G4AutoLock barrier(&fMutex); |
85 | fInstance.push_back(this); |
86 | |
87 | // Initialize the class that implements custom interactive |
88 | // commands under the command prefix /hdgeant4/. |
89 | |
90 | fpDetectorMessenger = new GlueXDetectorMessenger(this); |
91 | |
92 | // Read the geometry description from a HDDS document |
93 | // (Hall D Detector Specification) and build a Geant4 |
94 | // model of it in memory. |
95 | |
96 | try |
97 | { |
98 | XMLPlatformUtils::Initialize(); |
99 | } |
100 | catch (const XMLException& toCatch) |
101 | { |
102 | XString message(toCatch.getMessage()); |
103 | G4cerr(*G4cerr_p) << APP_NAME"HDGeant4" << " - error during xercesc initialization!" |
104 | << G4endlstd::endl << S(message)message.c_str() << G4endlstd::endl; |
105 | exit(1); |
106 | } |
107 | |
108 | DOMDocument* document; |
109 | if (hddsFile.size() > 0) |
110 | { |
111 | int size=100; |
112 | char *saved_cwd = new char[size]; |
113 | while (getcwd(saved_cwd, size) == 0) |
114 | { |
115 | delete [] saved_cwd; |
116 | saved_cwd = new char[size *= 2]; |
117 | } |
118 | XString xmlFile = hddsFile.c_str(); |
119 | char *dirpath = new char[hddsFile.size() + 2]; |
120 | chdir(dirname(strcpy(dirpath, hddsFile.c_str()))); |
121 | document = buildDOMDocument(xmlFile,false); |
122 | chdir(saved_cwd); |
123 | delete [] saved_cwd; |
124 | delete [] dirpath; |
125 | } |
126 | else if (getenv("JANA_GEOMETRY_URL")) |
127 | { |
128 | #ifndef FORCE_HDDS_FILES_PARSING |
129 | std::string url = getenv("JANA_GEOMETRY_URL"); |
130 | int run = HddmOutput::getRunNo(); |
131 | fGeometryXML = new HddsGeometryXML(url, run); |
132 | last_md5_checksum = fGeometryXML->GetChecksum(); |
133 | document = fGeometryXML->getDocument(); |
134 | #else |
135 | int size=100; |
136 | char *saved_cwd = new char[size]; |
137 | while (getcwd(saved_cwd, size) == 0) |
138 | { |
139 | delete [] saved_cwd; |
140 | saved_cwd = new char[size *= 2]; |
141 | } |
142 | XString hddsdir = getenv("HDDS_HOME"); |
143 | chdir(hddsdir.c_str()); |
144 | XString xmlFile = "main_HDDS.xml"; |
145 | document = buildDOMDocument(xmlFile,false); |
146 | chdir(saved_cwd); |
147 | delete [] saved_cwd; |
148 | #endif |
149 | } |
150 | else { |
151 | G4cerr(*G4cerr_p) << APP_NAME"HDGeant4" << " - no hdds geometry file specified!" |
152 | << " Cannot continue" << G4endlstd::endl; |
153 | exit(9); |
154 | } |
155 | if (document == 0) |
156 | { |
157 | G4cerr(*G4cerr_p) << APP_NAME"HDGeant4" << " - error parsing HDDS document, " |
158 | << "cannot continue" << G4endlstd::endl; |
159 | exit(9); |
160 | } |
161 | |
162 | DOMNode* docEl; |
163 | try { |
164 | docEl = document->getDocumentElement(); |
Value stored to 'docEl' is never read | |
165 | } |
166 | catch (DOMException& e) { |
167 | G4cerr(*G4cerr_p) << APP_NAME"HDGeant4" << " - Woops " << e.msg << G4endlstd::endl; |
168 | exit(9); |
169 | } |
170 | |
171 | DOMElement* rootEl = document->getElementById(X("everything")XString("everything").unicode_str()); |
172 | if (rootEl == 0) |
173 | { |
174 | G4cerr(*G4cerr_p) << APP_NAME"HDGeant4" << " - error scanning HDDS document, " << G4endlstd::endl |
175 | << " no element named \"everything\" found, " |
176 | << "cannot continue" << G4endlstd::endl; |
177 | exit(9); |
178 | } |
179 | |
180 | try { |
181 | fHddsBuilder.translate(rootEl); |
182 | } |
183 | catch (const DOMException &e) { |
184 | G4cerr(*G4cerr_p) << APP_NAME"HDGeant4" << " - error scanning HDDS document, " |
185 | << XString(e.getMessage()) << G4endlstd::endl; |
186 | exit(1); |
187 | } |
188 | |
189 | XMLPlatformUtils::Terminate(); |
190 | } |
191 | |
192 | GlueXDetectorConstruction:: |
193 | GlueXDetectorConstruction(const GlueXDetectorConstruction &src) |
194 | : fHddsBuilder(src.fHddsBuilder) |
195 | { |
196 | G4AutoLock barrier(&fMutex); |
197 | fInstance.push_back(this); |
198 | fMaxStep = src.fMaxStep; |
199 | fUniformField = src.fUniformField; |
200 | fpMagneticField = src.fpMagneticField; // shallow copy, sharing magfield |
201 | fpDetectorMessenger = src.fpDetectorMessenger; // shallow copy, sharing |
202 | } |
203 | |
204 | GlueXDetectorConstruction::~GlueXDetectorConstruction() |
205 | { |
206 | G4AutoLock barrier(&fMutex); |
207 | fInstance.remove(this); |
208 | delete fpDetectorMessenger; |
209 | } |
210 | |
211 | const GlueXDetectorConstruction *GlueXDetectorConstruction::GetInstance() |
212 | { |
213 | // Generally one only needs a single instance of this object |
214 | // per process, and this static method lets any component in the |
215 | // application obtain the primary instance, if any. If none has |
216 | // yet been constructed, it returns zero. |
217 | |
218 | G4AutoLock barrier(&fMutex); |
219 | if (fInstance.size() > 0) |
220 | return *fInstance.begin(); |
221 | return 0; |
222 | } |
223 | |
224 | const HddsG4Builder *GlueXDetectorConstruction::GetBuilder() |
225 | { |
226 | // Return a const pointer to the internal HddsG4Builder object. |
227 | |
228 | G4AutoLock barrier(&fMutex); |
229 | if (fInstance.size() > 0) |
230 | return &(*fInstance.begin())->fHddsBuilder; |
231 | return 0; |
232 | } |
233 | |
234 | void GlueXDetectorConstruction::SetUniformField(G4double field_T) |
235 | { |
236 | // This method embeds the entire Hall D (spectrometer + beam line) |
237 | // in an external uniform magnetic field. Used only for testing, |
238 | // this is not how to simulate the GlueX spectrometer field! |
239 | |
240 | fUniformField = field_T; |
241 | G4cout(*G4cout_p) << "setting up a new field manager with a uniform field " |
242 | << " of " << field_T << " Tesla." << G4endlstd::endl; |
243 | G4ThreeVector B(0,0,fUniformField); |
244 | G4AffineTransform xform; |
245 | fpMagneticField = new GlueXUniformMagField(B,tesla,xform); |
246 | } |
247 | |
248 | void GlueXDetectorConstruction::SetMaxStep(G4double step_mm) |
249 | { |
250 | fMaxStep = (step_mm > 0.)? step_mm*mm : 0; |
251 | } |
252 | |
253 | G4VPhysicalVolume* GlueXDetectorConstruction::Construct() |
254 | { |
255 | G4LogicalVolume *worldvol = fHddsBuilder.getWorldVolume(); |
256 | G4cout(*G4cout_p) << "Root geometry volume " << worldvol->GetName(); |
257 | worldvol->SetName("World"); |
258 | G4cout(*G4cout_p) << " configured as " << worldvol->GetName() << G4endlstd::endl; |
259 | worldvol->SetVisAttributes(new G4VisAttributes(false)); |
260 | return new G4PVPlacement(0, G4ThreeVector(), worldvol, "World", 0, 0, 0); |
261 | } |
262 | |
263 | void GlueXDetectorConstruction::ConstructSDandField() |
264 | { |
265 | G4RunManager::RMType rmtype = G4RunManager::GetRunManager()-> |
266 | GetRunManagerType(); |
267 | |
268 | // Magnetic field objects that were created during geometry building |
269 | // will need to be reconstructed here in order to be properly |
270 | // configured to run in multithreaded mode. |
271 | if (rmtype != G4RunManager::sequentialRM) |
272 | CloneF(); |
273 | |
274 | G4SDManager* SDman = G4SDManager::GetSDMpointer(); |
275 | GlueXSensitiveDetectorCDC* cdcHandler = 0; |
276 | GlueXSensitiveDetectorFDC* fdcHandler = 0; |
277 | GlueXSensitiveDetectorSTC* stcHandler = 0; |
278 | GlueXSensitiveDetectorBCAL* bcalHandler = 0; |
279 | GlueXSensitiveDetectorFCAL* fcalHandler = 0; |
280 | GlueXSensitiveDetectorFCALinsert* fcalInsertHandler = 0; |
281 | GlueXSensitiveDetectorGCAL* gcalHandler = 0; |
282 | GlueXSensitiveDetectorCCAL* ccalHandler = 0; |
283 | GlueXSensitiveDetectorFTOF* ftofHandler = 0; |
284 | GlueXSensitiveDetectorDIRC* dircHandler = 0; |
285 | GlueXSensitiveDetectorCERE* cereHandler = 0; |
286 | GlueXSensitiveDetectorFMWPC* fmwpcHandler = 0; |
287 | GlueXSensitiveDetectorUPV* upvHandler = 0; |
288 | GlueXSensitiveDetectorPSC* pscHandler = 0; |
289 | GlueXSensitiveDetectorPS* psHandler = 0; |
290 | GlueXSensitiveDetectorTPOL* tpolHandler = 0; |
291 | GlueXSensitiveDetectorCTOF* ctofHandler = 0; |
292 | |
293 | // During geometry building, certain logical volumes were marked as |
294 | // sensitive by adding them to a list. Now we need to go down that |
295 | // list and pick out an explicit sensitive volume class to handle |
296 | // each one. If any are missing, report error. |
297 | const std::map<int, G4LogicalVolume*> |
298 | svolMap = fHddsBuilder.getSensitiveVolumes(); |
299 | std::map<int, G4LogicalVolume*>::const_iterator iter; |
300 | for (iter = svolMap.begin(); iter != svolMap.end(); ++iter) { |
301 | G4String volname = iter->second->GetName(); |
302 | if (volname == "STLA" || volname == "STRA") { |
303 | if (cdcHandler == 0) { |
304 | cdcHandler = new GlueXSensitiveDetectorCDC("cdc"); |
305 | SDman->AddNewDetector(cdcHandler); |
306 | } |
307 | iter->second->SetSensitiveDetector(cdcHandler); |
308 | } |
309 | else if (volname == "FDA1" || volname == "FDA2" || |
310 | volname == "FDA3" || volname == "FDA4") |
311 | { |
312 | if (fdcHandler == 0) { |
313 | fdcHandler = new GlueXSensitiveDetectorFDC("fdc"); |
314 | SDman->AddNewDetector(fdcHandler); |
315 | } |
316 | iter->second->SetSensitiveDetector(fdcHandler); |
317 | } |
318 | else if (volname == "STRC") { |
319 | if (stcHandler == 0) { |
320 | stcHandler = new GlueXSensitiveDetectorSTC("stc"); |
321 | SDman->AddNewDetector(stcHandler); |
322 | } |
323 | iter->second->SetSensitiveDetector(stcHandler); |
324 | } |
325 | else if (volname == "BM01" || volname == "BM02" || |
326 | volname == "BM03" || volname == "BM04" || |
327 | volname == "BM05" || volname == "BM06" || |
328 | volname == "BMF7" || volname == "BMF8" || |
329 | volname == "BMF9" || volname == "BMFA") |
330 | { |
331 | if (bcalHandler == 0) { |
332 | bcalHandler = new GlueXSensitiveDetectorBCAL("bcal"); |
333 | SDman->AddNewDetector(bcalHandler); |
334 | // Also add support beam BCL0 as a "sensitive" element |
335 | // to catch incident particles as they enter the BCAL |
336 | G4LogicalVolume *bcl0 = GlueXDetectorConstruction::GetBuilder()-> |
337 | getVolume("BCL0"); |
338 | if (bcl0 != 0) { |
339 | bcl0->SetSensitiveDetector(bcalHandler); |
340 | } |
341 | else { |
342 | G4cerr(*G4cerr_p) << "Warning from GlueXDetectorConstruction" |
343 | << "::ConstructSDandField - " |
344 | << "special BCal volume BCL0 not found" |
345 | << " in geometry definition, bcalTruthShower" |
346 | << " information will not be generated." |
347 | << G4endlstd::endl; |
348 | } |
349 | } |
350 | iter->second->SetSensitiveDetector(bcalHandler); |
351 | } |
352 | else if (volname == "LGBL" || volname == "LGLG") { |
353 | if (fcalHandler == 0) { |
354 | fcalHandler = new GlueXSensitiveDetectorFCAL("fcal"); |
355 | SDman->AddNewDetector(fcalHandler); |
356 | } |
357 | iter->second->SetSensitiveDetector(fcalHandler); |
358 | } |
359 | else if (volname == "LTB1") { |
360 | if (fcalHandler == 0) { |
361 | fcalInsertHandler = new GlueXSensitiveDetectorFCALinsert("fcalinsert"); |
362 | SDman->AddNewDetector(fcalInsertHandler); |
363 | } |
364 | iter->second->SetSensitiveDetector(fcalInsertHandler); |
365 | } |
366 | else if (volname == "GCAL") { |
367 | if (gcalHandler == 0) { |
368 | gcalHandler = new GlueXSensitiveDetectorGCAL("gcal"); |
369 | SDman->AddNewDetector(gcalHandler); |
370 | } |
371 | iter->second->SetSensitiveDetector(gcalHandler); |
372 | } |
373 | else if (volname == "LTBL") { |
374 | if (ccalHandler == 0) { |
375 | ccalHandler = new GlueXSensitiveDetectorCCAL("ccal"); |
376 | SDman->AddNewDetector(ccalHandler); |
377 | } |
378 | iter->second->SetSensitiveDetector(ccalHandler); |
379 | } |
380 | else if (volname == "FTOC" || volname == "FTOX" || |
381 | volname == "FTOH" || volname == "FTOL") |
382 | { |
383 | if (ftofHandler == 0) { |
384 | ftofHandler = new GlueXSensitiveDetectorFTOF("ftof"); |
385 | SDman->AddNewDetector(ftofHandler); |
386 | } |
387 | iter->second->SetSensitiveDetector(ftofHandler); |
388 | } |
389 | else if (volname == "CTOF") |
390 | { |
391 | if (ctofHandler == 0) { |
392 | ctofHandler = new GlueXSensitiveDetectorCTOF("ctof"); |
393 | SDman->AddNewDetector(ctofHandler); |
394 | } |
395 | iter->second->SetSensitiveDetector(ctofHandler); |
396 | } |
397 | // radiator volume: BNNM (NN = bar number 0-47 and M is sub-bar character A-D) |
398 | else if (volname == "PIXV" || |
399 | (volname[0] == 'B' && |
400 | 10*((int)volname[1]-48)+(int)volname[2]-48 >= 0 && |
401 | 10*((int)volname[1]-48)+(int)volname[2]-48 < 48)) |
402 | { // this is nasty, but it works |
403 | if (dircHandler == 0) { |
404 | dircHandler = new GlueXSensitiveDetectorDIRC("dirc"); |
405 | SDman->AddNewDetector(dircHandler); |
406 | } |
407 | iter->second->SetSensitiveDetector(dircHandler); |
408 | } |
409 | else if (volname == "WM1N" || volname == "WM2N" || volname == "WM1S" || volname == "WM2S" || |
410 | volname == "FTMN" || volname == "FTMS" || |
411 | volname == "TM1N" || volname == "TM2N" || volname == "TM3N" || |
412 | volname == "TM1S" || volname == "TM2S" || volname == "TM3S" || |
413 | volname == "SM1N" || volname == "SM2N" || volname == "SM1S" || volname == "SM2S" || |
414 | volname == "OWDG" || volname(0,2) == "AG" ) |
415 | { |
416 | if (dircHandler == 0) { |
417 | dircHandler = new GlueXSensitiveDetectorDIRC("dirc"); |
418 | SDman->AddNewDetector(dircHandler); |
419 | } |
420 | iter->second->SetSensitiveDetector(dircHandler); |
421 | } |
422 | else if (volname == "CERW" || volname == "CPPC") { |
423 | if (cereHandler == 0) { |
424 | cereHandler = new GlueXSensitiveDetectorCERE("cere"); |
425 | SDman->AddNewDetector(cereHandler); |
426 | } |
427 | iter->second->SetSensitiveDetector(cereHandler); |
428 | } |
429 | else if (volname == "CPPG") { |
430 | if (fmwpcHandler == 0) { |
431 | fmwpcHandler = new GlueXSensitiveDetectorFMWPC("fmwpc"); |
432 | SDman->AddNewDetector(fmwpcHandler); |
433 | } |
434 | iter->second->SetSensitiveDetector(fmwpcHandler); |
435 | } |
436 | else if (volname == "UPVP" || volname == "UPVC") { |
437 | if (upvHandler == 0) { |
438 | upvHandler = new GlueXSensitiveDetectorUPV("upv"); |
439 | SDman->AddNewDetector(upvHandler); |
440 | } |
441 | iter->second->SetSensitiveDetector(upvHandler); |
442 | } |
443 | else if (volname == "PSCO") { |
444 | if (pscHandler == 0) { |
445 | pscHandler = new GlueXSensitiveDetectorPSC("psc"); |
446 | SDman->AddNewDetector(pscHandler); |
447 | } |
448 | iter->second->SetSensitiveDetector(pscHandler); |
449 | } |
450 | else if (volname(0,3) == "PTS") { |
451 | if (tpolHandler == 0) { |
452 | tpolHandler = new GlueXSensitiveDetectorTPOL("tpol"); |
453 | SDman->AddNewDetector(tpolHandler); |
454 | } |
455 | iter->second->SetSensitiveDetector(tpolHandler); |
456 | } |
457 | else if (volname == "PSF1" || volname == "PSF2") { |
458 | if (psHandler == 0) { |
459 | psHandler = new GlueXSensitiveDetectorPS("ps"); |
460 | SDman->AddNewDetector(psHandler); |
461 | } |
462 | iter->second->SetSensitiveDetector(psHandler); |
463 | } |
464 | else { |
465 | G4cerr(*G4cerr_p) << "Warning from GlueXDetectorConstruction" |
466 | << "::ConstructSDandField - " |
467 | << "unsupported sensitive volume " << volname |
468 | << " found in geometry definition." |
469 | << G4endlstd::endl; |
470 | } |
471 | } |
472 | } |
473 | |
474 | void GlueXDetectorConstruction::CloneF() |
475 | { |
476 | typedef std::map<G4FieldManager*,G4FieldManager*> FMtoFMmap; |
477 | FMtoFMmap masterToWorker; |
478 | G4LogicalVolumeStore* const logVolStore = G4LogicalVolumeStore::GetInstance(); |
479 | assert(logVolStore != NULL)((logVolStore != __null) ? static_cast<void> (0) : __assert_fail ("logVolStore != __null", "src/GlueXDetectorConstruction.cc" , 479, __PRETTY_FUNCTION__)); |
480 | for (G4LogicalVolumeStore::const_iterator iter = logVolStore->begin(); |
481 | iter != logVolStore->end(); |
482 | ++iter) |
483 | { |
484 | G4LogicalVolume *lvol = *iter; |
485 | G4FieldManager* masterFM = lvol->GetFieldManager(); |
486 | G4FieldManager* clonedFM = 0; |
487 | if (masterFM) { |
488 | FMtoFMmap::iterator fmFound = masterToWorker.find(masterFM); |
489 | if (fmFound == masterToWorker.end()) { |
490 | |
491 | // First time we see this FM, let's clone and remember... |
492 | |
493 | G4ChordFinder *cfinder = masterFM->GetChordFinder(); |
494 | #if G4VERSION_NUMBER1042 >= 1040 |
495 | G4VIntegrationDriver *midriver = cfinder->GetIntegrationDriver(); |
496 | double stepMinimum = 1e-2; |
497 | #else |
498 | G4MagInt_Driver *midriver = cfinder->GetIntegrationDriver(); |
499 | double stepMinimum = midriver->GetHmin(); |
500 | #endif |
501 | G4MagIntegratorStepper *stepper = midriver->GetStepper(); |
502 | const G4Field *field = masterFM->GetDetectorField(); |
503 | |
504 | G4MagneticField *field_copy; |
505 | if (dynamic_cast<const GlueXUniformMagField*>(field)) { |
506 | GlueXUniformMagField &orig = *(GlueXUniformMagField*)field; |
507 | field_copy = new GlueXUniformMagField(orig); |
508 | } |
509 | else if (dynamic_cast<const GlueXMappedMagField*>(field)) { |
510 | GlueXMappedMagField &orig = *(GlueXMappedMagField*)field; |
511 | field_copy = new GlueXMappedMagField(orig); |
512 | } |
513 | else if (dynamic_cast<const GlueXComputedMagField*>(field)) { |
514 | GlueXComputedMagField &orig = *(GlueXComputedMagField*)field; |
515 | field_copy = new GlueXComputedMagField(orig); |
516 | } |
517 | else if (dynamic_cast<const G4UniformMagField*>(field)) { |
518 | G4UniformMagField &orig = *(G4UniformMagField*)field; |
519 | field_copy = new G4UniformMagField(orig); |
520 | } |
521 | else { |
522 | G4cerr(*G4cerr_p) << "GlueXDetectorConstruction::CloneF error - " |
523 | << "unknown G4MagneticField class found " |
524 | << "attached to detector volume " << lvol->GetName() |
525 | << ", cannot continue!" << G4endlstd::endl; |
526 | exit(1); |
527 | } |
528 | G4Mag_UsualEqRhs *eqn_copy = new G4Mag_UsualEqRhs(field_copy); |
529 | G4MagIntegratorStepper *stepper_copy; |
530 | if (dynamic_cast<const G4ExactHelixStepper*>(stepper)) { |
531 | stepper_copy = new G4ExactHelixStepper(eqn_copy); |
532 | } |
533 | else if (dynamic_cast<const G4ClassicalRK4*>(stepper)) { |
534 | stepper_copy = new G4ClassicalRK4(eqn_copy); |
535 | } |
536 | else if (dynamic_cast<const G4HelixMixedStepper*>(stepper)) { |
537 | stepper_copy = new G4HelixMixedStepper(eqn_copy); |
538 | } |
539 | else { |
540 | G4cerr(*G4cerr_p) << "GlueXDetectorConstruction::CloneF error - " |
541 | << "unknown G4MagIntegratorStepper class found " |
542 | << "attached to detector volume " << lvol->GetName() |
543 | << ", cannot continue!" << G4endlstd::endl; |
544 | exit(1); |
545 | } |
546 | G4ChordFinder *cfinder_copy = new G4ChordFinder(field_copy, |
547 | stepMinimum, |
548 | stepper_copy); |
549 | clonedFM = new G4FieldManager(field_copy, cfinder_copy); |
550 | masterToWorker[masterFM] = clonedFM; |
551 | } |
552 | else { |
553 | |
554 | // We have already seen this FM attached to a different |
555 | // LogicalVolume, let's re-use the previous clone |
556 | |
557 | clonedFM = (*fmFound).second; |
558 | } |
559 | lvol->SetFieldManager(clonedFM, false); |
560 | } |
561 | } |
562 | } |
563 | |
564 | int GlueXDetectorConstruction::GetParallelWorldCount() const |
565 | { |
566 | for (int worlds=0; ; ++worlds) { |
567 | if (fHddsBuilder.getWorldVolume(worlds) == 0) { |
568 | return --worlds; |
569 | } |
570 | } |
571 | return 0; |
572 | } |
573 | |
574 | G4String GlueXDetectorConstruction::GetParallelWorldName(int paraIndex) const |
575 | { |
576 | std::stringstream worldStr; |
577 | worldStr << "ParallelWorld" << paraIndex; |
578 | return worldStr.str(); |
579 | } |
580 | |
581 | G4LogicalVolume* |
582 | GlueXDetectorConstruction::GetParallelWorldVolume(int paraIndex) const |
583 | { |
584 | return fHddsBuilder.getWorldVolume(paraIndex); |
585 | } |
586 | |
587 | G4ThreeVector |
588 | GlueXDetectorConstruction::GetMagneticField(G4ThreeVector pos, double unit) |
589 | const |
590 | { |
591 | // Utility function for use by other simulation components, |
592 | // returns the magnetic field at an arbitrary location in |
593 | // the geometry. If geometry has not yet been constructed |
594 | // the value returned is always zero. |
595 | |
596 | G4TransportationManager *tmanager; |
597 | G4Navigator *navigator; |
598 | G4VPhysicalVolume *pvol; |
599 | G4LogicalVolume *lvol; |
600 | G4FieldManager *fieldmgr; |
601 | const G4Field *field; |
602 | if ((tmanager = G4TransportationManager::GetTransportationManager()) && |
603 | (navigator = tmanager->GetNavigatorForTracking()) && |
604 | (pvol = navigator->LocateGlobalPointAndSetup(pos)) && |
605 | (lvol = pvol->GetLogicalVolume()) && |
606 | (fieldmgr = lvol->GetFieldManager()) && |
607 | (field = fieldmgr->GetDetectorField()) ) |
608 | { |
609 | double Bfield[3]; |
610 | double xglob[4] = {pos[0], pos[1], pos[2], 0}; |
611 | field->GetFieldValue(xglob, Bfield); |
612 | G4ThreeVector B(Bfield[0], Bfield[1], Bfield[2]); |
613 | return B / unit; |
614 | } |
615 | return G4ThreeVector(); |
616 | } |
617 | |
618 | |
619 | |
620 | GlueXParallelWorld::GlueXParallelWorld(const GlueXParallelWorld &src) |
621 | : G4VUserParallelWorld(src.fWorldName), fTopVolume(src.fTopVolume) |
622 | { } |
623 | |
624 | GlueXParallelWorld::~GlueXParallelWorld() { } |
625 | |
626 | void GlueXParallelWorld::Construct() |
627 | { |
628 | G4VPhysicalVolume* ghostWorld = GetWorld(); |
629 | G4LogicalVolume* worldLogical = ghostWorld->GetLogicalVolume(); |
630 | for (int child = fTopVolume->GetNoDaughters() - 1; child >= 0; --child) { |
631 | G4VPhysicalVolume* pvol = fTopVolume->GetDaughter(child); |
632 | fTopVolume->RemoveDaughter(pvol); |
633 | worldLogical->AddDaughter(pvol); |
634 | } |
635 | if (worldLogical->GetNoDaughters()) { |
636 | G4cout(*G4cout_p) << "Additional geometry layer configured as " |
637 | << ghostWorld->GetName() << G4endlstd::endl; |
638 | } |
639 | else { |
640 | G4cout(*G4cout_p) << "Additional geometry layer configured as " |
641 | << ghostWorld->GetName() << " is EMPTY!" << G4endlstd::endl |
642 | << "This is probably due to a geometry bug -- " |
643 | << "PLEASE REPORT THIS TO THE AUTHORS" << G4endlstd::endl; |
644 | } |
645 | } |