]>
Commit | Line | Data |
---|---|---|
2817d3e2 | 1 | // $Id$ |
2 | // Category: geometry | |
3 | // | |
4 | // C++ interface to Geant3 basic routines | |
5 | // for building Geant4 geometry | |
6 | // | |
7 | // by V. Berejnoi, 25.2.1999 | |
8 | // materials, tracking media support | |
9 | // added by I.Hrivnacova, 27.5.1999 | |
10 | ||
11 | #include "TG4GeometryManager.h" | |
12 | #include "TG4GeometryOutputManager.h" | |
13 | #include "TG4PhysicsManager.h" | |
14 | #include "TG4VSensitiveDetector.h" | |
15 | #include "TG4Limits.h" | |
16 | #include "TG4Globals.h" | |
17 | #include "TG3Units.h" | |
18 | ||
19 | #include <G3toG4.hh> | |
20 | #include <G3toG4BuildTree.hh> | |
21 | #include <G3VolTable.hh> | |
22 | #include <G3RotTable.hh> | |
23 | #include <G3EleTable.hh> | |
24 | #include <G3MatTable.hh> | |
25 | #include <G3MedTable.hh> | |
26 | #include <G3SensVolVector.hh> | |
27 | ||
2817d3e2 | 28 | #include <G4VSensitiveDetector.hh> |
29 | #include <G4LogicalVolumeStore.hh> | |
30 | #include <G4PVPlacement.hh> | |
31 | #include <G4Material.hh> | |
32 | #include <G4MaterialPropertiesTable.hh> | |
33 | #include <G4Element.hh> | |
34 | ||
2817d3e2 | 35 | // extern global method from g3tog4 |
36 | void G3CLRead(G4String &, char *); | |
37 | ||
38 | TG4GeometryManager* TG4GeometryManager::fgInstance = 0; | |
39 | ||
40 | TG4GeometryManager::TG4GeometryManager() | |
41 | : fMediumCounter(0), | |
42 | fMaterialCounter(0), | |
43 | fMatrixCounter(0), | |
44 | fUseG3TMLimits(false), | |
45 | fWriteGeometry(true) | |
46 | { | |
47 | // | |
48 | if (fgInstance) { | |
49 | TG4Globals::Exception( | |
50 | "TG4GeometryManager: attempt to create two instances of singleton."); | |
51 | } | |
52 | ||
53 | fOutputManager = new TG4GeometryOutputManager(); | |
54 | ||
55 | fgInstance = this; | |
56 | ||
57 | // instantiate the default element table | |
58 | //TG4ElementTable::Instance(); | |
59 | } | |
60 | ||
61 | TG4GeometryManager::TG4GeometryManager(const TG4GeometryManager& right) { | |
62 | // | |
63 | TG4Globals::Exception( | |
64 | "Attempt to copy TG4GeometryManager singleton."); | |
65 | } | |
66 | ||
67 | ||
68 | TG4GeometryManager::~TG4GeometryManager() { | |
69 | // | |
70 | delete fOutputManager; | |
71 | } | |
72 | ||
73 | //==================================================================== ========= | |
74 | // | |
75 | // operators | |
76 | // | |
77 | //==================================================================== ========= | |
78 | ||
79 | TG4GeometryManager& | |
80 | TG4GeometryManager::operator=(const TG4GeometryManager& right) | |
81 | { | |
82 | // check assignement to self | |
83 | if (this == &right) return *this; | |
84 | ||
85 | TG4Globals::Exception( | |
86 | "Attempt to assign TG4GeometryManager singleton."); | |
87 | ||
88 | return *this; | |
89 | } | |
90 | ||
91 | ||
92 | //============================================================================= | |
93 | // | |
94 | // private methods | |
95 | // | |
96 | //============================================================================= | |
97 | ||
98 | ||
99 | G4double* TG4GeometryManager::CreateG4doubleArray(Float_t* array, | |
100 | G4int size) const | |
101 | { | |
102 | // Converts Float_t* array to G4double*, | |
103 | // !! The new array has to be deleted by user. | |
104 | // --- | |
105 | ||
106 | G4double* doubleArray; | |
107 | if (size>0) { | |
108 | doubleArray = new G4double[size]; | |
109 | for (G4int i=0; i<size; i++) doubleArray[i] = array[i]; | |
110 | } | |
111 | else { | |
112 | doubleArray = 0; | |
113 | } | |
114 | return doubleArray; | |
115 | } | |
116 | ||
117 | ||
118 | G4String TG4GeometryManager::CutName(const char* name) const | |
119 | { | |
120 | // Removes spaces after the name if present. | |
121 | // --- | |
122 | ||
123 | G4String cutName = name; | |
124 | G4int i = cutName.length(); | |
125 | while (cutName(--i) == ' ') cutName = cutName(0,i); | |
126 | ||
127 | return cutName; | |
128 | } | |
129 | ||
130 | ||
131 | void TG4GeometryManager::GstparCut(G4int itmed, TG3Cut par, G4double parval) | |
132 | { | |
133 | // Sets special tracking medium parameter. | |
134 | // It is applied to all logical volumes that use the specified | |
135 | // tracking medium. | |
136 | // --- | |
137 | ||
138 | // get medium from table | |
139 | G3MedTableEntry* medium = G3Med.get(itmed); | |
140 | if (!medium) { | |
141 | G4String text = "TG4GeometryManager::GstparCut: \n"; | |
142 | text = text + " Medium not found."; | |
143 | G4Exception(text); | |
144 | } | |
145 | ||
146 | // get/create user limits | |
147 | G4UserLimits* limits = medium->GetLimits(); | |
148 | TG4Limits* tg4Limits; | |
149 | if (limits) { | |
150 | tg4Limits = dynamic_cast<TG4Limits*> (limits); | |
151 | if (!tg4Limits) | |
152 | G4Exception("TG4GeometryManager::GstparCut: Wrong limits type."); | |
153 | } | |
154 | else { | |
155 | tg4Limits = new TG4Limits(); | |
156 | medium->SetLimits(tg4Limits); | |
157 | // add verbose | |
158 | G4cout << "TG4GeometryManager::GstparCut: new TG4Limits() for medium " | |
3c7cd15a | 159 | << itmed << " has been created." << G4endl; |
2817d3e2 | 160 | } |
161 | // set parameter | |
162 | tg4Limits->SetG3Cut(par, parval*GeV); | |
163 | } | |
164 | ||
165 | ||
166 | void TG4GeometryManager::GstparFlag(G4int itmed, TG3Flag par, G4double parval) | |
167 | { | |
168 | // Sets special tracking medium parameter. | |
169 | // It is applied to all logical volumes that use the specified | |
170 | // tracking medium. | |
171 | // --- | |
172 | ||
173 | // get medium from table | |
174 | G3MedTableEntry* medium = G3Med.get(itmed); | |
175 | if (!medium) { | |
176 | G4String text = "TG4GeometryManager::GstparFlag: \n"; | |
177 | text = text + " Medium not found."; | |
178 | G4Exception(text); | |
179 | } | |
180 | ||
181 | // get/create user limits | |
182 | G4UserLimits* limits = medium->GetLimits(); | |
183 | TG4Limits* tg4Limits; | |
184 | if (limits) { | |
185 | tg4Limits = dynamic_cast<TG4Limits*> (limits); | |
186 | if (!tg4Limits) | |
187 | G4Exception("TG4GeometryManager::GstparFlag: Wrong limits type."); | |
188 | } | |
189 | else { | |
190 | tg4Limits = new TG4Limits(); | |
191 | medium->SetLimits(tg4Limits); | |
192 | // add verbose | |
193 | G4cout << "TG4GeometryManager::GstparFlag: new TG4Limits() for medium " | |
3c7cd15a | 194 | << itmed << " has been created." << G4endl; |
2817d3e2 | 195 | } |
196 | // set parameter | |
197 | tg4Limits->SetG3Flag(par, parval); | |
198 | } | |
199 | ||
200 | ||
201 | void TG4GeometryManager::FillMediumIdVector() | |
202 | { | |
203 | // The second index for materials (having its origin in | |
204 | // G4 tracking media concept) is stored in a vector of G4int | |
205 | // parallel to G4MaterialTable. | |
206 | // --- | |
207 | ||
208 | // initialize vector | |
209 | G4int nofMaterials = G4Material::GetNumberOfMaterials(); | |
210 | G4int i; | |
211 | for (i=0; i<nofMaterials; i++) | |
212 | fMediumIdVector.push_back(0); | |
213 | ||
214 | // fill vector | |
215 | for (i=0; i<fMediumCounter; i++) { | |
216 | // material index (index in G4Material table) | |
217 | G3MedTableEntry* mte = G3Med.get(i+1); | |
218 | G4int materialIndex = mte->GetMaterial()->GetIndex(); | |
219 | ||
220 | // medium index (ID of G3MedTableEntry) | |
221 | G4int mediumIndex = mte->GetID(); | |
222 | ||
223 | // store medium index in the vector | |
224 | fMediumIdVector[materialIndex] = mediumIndex; | |
225 | } | |
226 | ||
227 | // add verbose | |
3c7cd15a | 228 | G4cout << "Total nof materials: " << nofMaterials << G4endl; |
229 | G4cout << "Total nof tracking medias: " << fMediumCounter << G4endl; | |
2817d3e2 | 230 | } |
231 | ||
232 | ||
233 | //============================================================================= | |
234 | // | |
235 | // public methods - AliMC implementation | |
236 | // | |
237 | //============================================================================= | |
238 | ||
239 | ||
240 | void TG4GeometryManager::Material(Int_t& kmat, const char* name, Float_t a, | |
241 | Float_t z, Float_t dens, Float_t radl, Float_t absl, Float_t* buf, | |
242 | Int_t nwbuf) | |
243 | { | |
244 | // Creates G4Material. | |
245 | // !! Parameters radl, absl, buf, nwbuf are ignored in G4gsmate | |
246 | // Comment: | |
247 | // absl - this parameter is ignored by GEANT3, too | |
248 | // --- | |
249 | ||
250 | kmat = ++fMaterialCounter; | |
251 | G4double* bufin = CreateG4doubleArray(buf, nwbuf); | |
252 | ||
253 | // write token to the output file | |
254 | if (fWriteGeometry) | |
255 | fOutputManager->WriteGsmate(kmat, name, a, z, dens, radl, nwbuf, bufin); | |
256 | ||
257 | G4gsmate(kmat, name, a, z, dens, radl, nwbuf, bufin); | |
258 | ||
259 | delete [] bufin; | |
260 | ||
261 | if (nwbuf > 0) { | |
262 | G4String matName = name; | |
263 | G4String text | |
264 | = "TG4GeometryManager: user defined parameters for material "; | |
265 | text = text + matName; | |
266 | text = text + " are ignored by Geant4."; | |
267 | TG4Globals::Warning(text); | |
268 | } | |
269 | } | |
270 | ||
271 | ||
272 | void TG4GeometryManager::Mixture(Int_t& kmat, const char *name, Float_t *a, | |
273 | Float_t *z, Float_t dens, Int_t nlmat, Float_t *wmat) | |
274 | { | |
275 | // Creates G4Material composed of more elements. | |
276 | // !! Parameters radl, absl, buf, nwbuf are ignored in G4gsmate | |
277 | // Comment: | |
278 | // absl - this parameter is ignored by GEANT3, too | |
279 | // --- | |
280 | ||
281 | Int_t npar = abs(nlmat); | |
282 | G4double *ain = CreateG4doubleArray(a, npar); | |
283 | G4double *zin = CreateG4doubleArray(z, npar); | |
284 | G4double *wmatin = CreateG4doubleArray(wmat, npar); | |
285 | ||
286 | kmat = ++fMaterialCounter; | |
287 | ||
288 | // write token to the output file | |
289 | if (fWriteGeometry) | |
290 | fOutputManager->WriteGsmixt(kmat, name, ain, zin, dens, nlmat, wmatin); | |
291 | ||
292 | G4gsmixt(kmat, name, ain, zin, dens, nlmat, wmatin); | |
293 | ||
294 | // !!! in Geant3: | |
295 | // After a call with ratios by number (negative number of elements), | |
296 | // the ratio array is changed to the ratio by weight, so all successive | |
297 | // calls with the same array must specify the number of elements as | |
298 | // positive | |
299 | ||
300 | // wmatin may be modified | |
301 | for (G4int i=0; i<npar; i++) wmat[i] = wmatin[i]; | |
302 | ||
303 | delete [] ain; | |
304 | delete [] zin; | |
305 | delete [] wmatin; | |
306 | } | |
307 | ||
308 | void TG4GeometryManager::Medium(Int_t& kmed, const char *name, Int_t nmat, | |
309 | Int_t isvol, Int_t ifield, Float_t fieldm, Float_t tmaxfd, | |
310 | Float_t stemax, Float_t deemax, Float_t epsil, | |
311 | Float_t stmin, Float_t* ubuf, Int_t nbuf) | |
312 | { | |
313 | // Creates a temporary "medium" that is used for | |
314 | // assigning corresponding parameters to G4 objects: | |
315 | // NTMED is stored as a second material index; | |
316 | // ISVOL is used for builing TG3SensVolVector; | |
317 | // STEMAX is passed in TG4Limits (if fUseG3TMLimits is set true); | |
318 | // !! The other parameters (IFIELD, FIELDM, TMAXFD, DEEMAX, EPSIL, STMIN) | |
319 | // are ignored by Geant4. | |
320 | // --- | |
321 | ||
322 | // Geant3 desription: | |
323 | // ================== | |
324 | // NTMED Tracking medium number | |
325 | // NAME Tracking medium name | |
326 | // NMAT Material number | |
327 | // ISVOL Sensitive volume flag | |
328 | // IFIELD Magnetic field | |
329 | // FIELDM Max. field value (Kilogauss) | |
330 | // TMAXFD Max. angle due to field (deg/step) | |
331 | // STEMAX Max. step allowed | |
332 | // DEEMAX Max. fraction of energy lost in a step | |
333 | // EPSIL Tracking precision (cm) | |
334 | // STMIN Min. step due to continuos processes (cm) | |
335 | // | |
336 | // IFIELD = 0 if no magnetic field; IFIELD = -1 if user decision in GUSWIM; | |
337 | // IFIELD = 1 if tracking performed with GRKUTA; IFIELD = 2 if tracking | |
338 | // performed with GHELIX; IFIELD = 3 if tracking performed with GHELX3. | |
339 | // --- | |
340 | ||
341 | kmed = ++fMediumCounter; | |
342 | ||
343 | // write token to the output file | |
344 | if (fWriteGeometry) | |
345 | fOutputManager->WriteGstmed(kmed, name, nmat, isvol, ifield, fieldm, tmaxfd, | |
346 | stemax, deemax, epsil, stmin, 0, 0); | |
347 | ||
348 | G4gstmed(kmed, name, nmat, isvol, ifield, fieldm, tmaxfd, stemax, deemax, | |
349 | epsil, stmin, 0, fUseG3TMLimits); | |
350 | // !! instead of the nbuf argument the bool fIsG3Default is passed | |
351 | ||
352 | if (nbuf > 0) { | |
353 | G4String medName = name; | |
354 | G4String text | |
355 | = "TG4GeometryManager: user defined parameters for medium "; | |
356 | text = text + medName; | |
357 | text = text + " are ignored by Geant4."; | |
358 | TG4Globals::Warning(text); | |
359 | } | |
360 | } | |
361 | ||
362 | ||
363 | void TG4GeometryManager::Matrix(Int_t& krot, Float_t thetaX, Float_t phiX, | |
364 | Float_t thetaY, Float_t phiY, Float_t thetaZ, Float_t phiZ) | |
365 | { | |
366 | // Creates G4RotationMatrix. | |
367 | // --- | |
368 | ||
369 | krot = ++fMatrixCounter; | |
370 | ||
371 | // write token to the output file | |
372 | if (fWriteGeometry) | |
373 | fOutputManager->WriteGsrotm(krot, thetaX, phiX, thetaY, phiY, thetaZ, phiZ); | |
374 | ||
375 | G4gsrotm(krot, thetaX, phiX, thetaY, phiY, thetaZ, phiZ); | |
376 | } | |
377 | ||
378 | ||
379 | G4Material* TG4GeometryManager::MixMaterials(G4String name, G4double density, | |
380 | TG4StringVector* matNames, TG4doubleVector* matWeights) | |
381 | { | |
382 | // Creates a mixture of selected materials | |
383 | // --- | |
384 | ||
385 | // number of materials to be mixed | |
386 | G4int nofMaterials = matNames->entries(); | |
387 | if (nofMaterials != matWeights->entries()) { | |
388 | G4String text = "TG4GeometryManager::MixMaterials: "; | |
389 | text = text + "different number of material names and weigths."; | |
390 | TG4Globals::Exception(text); | |
391 | } | |
392 | // add verbose | |
3c7cd15a | 393 | // G4cout << "Nof of materials to be mixed: " << nofMaterials << G4endl; |
2817d3e2 | 394 | |
395 | // fill vector of materials | |
396 | TG4MaterialVector matVector; | |
397 | G4int im; | |
398 | for (im=0; im< nofMaterials; im++) { | |
399 | // material | |
400 | G4Material* material = G4Material::GetMaterial((*matNames)[im]); | |
401 | matVector.insert(material); | |
402 | } | |
403 | ||
404 | // create the mixed material | |
405 | G4Material* mixture = new G4Material(name, density, nofMaterials); | |
406 | for (im=0; im< nofMaterials; im++) { | |
407 | G4Material* material = matVector[im]; | |
408 | G4double fraction = (*matWeights)[im]; | |
409 | mixture->AddMaterial(material, fraction); | |
410 | } | |
411 | ||
412 | return mixture; | |
413 | } | |
414 | ||
415 | ||
416 | void TG4GeometryManager::Ggclos() | |
417 | { | |
418 | // Sets the top VTE in temporary G3 volume table. | |
419 | // Close geometry output file (if fWriteGeometry is set true). | |
420 | // | |
421 | // Geant3 desription: | |
422 | // ================== | |
423 | // close out the geometry | |
424 | // --- | |
425 | ||
426 | if (fWriteGeometry) fOutputManager->WriteGgclos(); | |
427 | ||
428 | G4ggclos(); | |
429 | } | |
430 | ||
431 | ||
432 | void TG4GeometryManager::Gfmate(Int_t imat, char *name, Float_t &a, | |
433 | Float_t &z, Float_t &dens, Float_t &radl, Float_t &absl, | |
434 | Float_t* ubuf, Int_t& nbuf) | |
435 | { | |
436 | // Geant3 desription: | |
437 | // ================== | |
438 | // Return parameters for material IMAT | |
439 | // --- | |
440 | ||
441 | G4Material* material = G3Mat.get(imat); | |
442 | ||
443 | if (material) { | |
444 | // to do: change this correctly | |
445 | // !! unsafe conversion | |
446 | const char* chName = material->GetName(); | |
447 | name = (char*)chName; | |
448 | a = GetEffA(material); | |
449 | z = GetEffZ(material); | |
450 | ||
451 | dens = material->GetDensity(); | |
452 | dens /= TG3Units::MassDensity(); | |
453 | ||
454 | radl = material->GetRadlen(); | |
455 | radl /= TG3Units::Length(); | |
456 | ||
457 | // the following parameters are not defined in Geant4 | |
458 | absl = 0.; | |
459 | ubuf = 0; | |
460 | nbuf = 0; | |
461 | } | |
462 | else { | |
463 | TG4Globals::Exception( | |
464 | "TG4GeometryManager::Gfmate: material has not been found."); | |
465 | } | |
466 | } | |
467 | ||
468 | ||
469 | void TG4GeometryManager::Gstpar(Int_t itmed, const char *param, | |
470 | Float_t parval) | |
471 | { | |
472 | // Passes the tracking medium parameter to TG4Limits. | |
473 | // The tracking medium parameter is set only in case | |
474 | // its value is different from the "global" physics setup. | |
475 | // (If: CheckCut/FlagWithG3Defaults is used checking | |
476 | // is performed with respect to G3 default values.) | |
477 | // When any cut/flag parameter is set in limits | |
478 | // the physics manager is locked and the physics setup | |
479 | // cannot be changed. | |
480 | // Applying this TG4Limits to particles and physical | |
481 | // processes is still in development. | |
482 | // | |
483 | // Geant3 desription: | |
484 | // ================== | |
485 | // To change the value of cut or mechanism "CHPAR" | |
486 | // to a new value PARVAL for tracking medium ITMED | |
487 | // The data structure JTMED contains the standard tracking | |
488 | // parameters (CUTS and flags to control the physics processes) which | |
489 | // are used by default for all tracking media. It is possible to | |
490 | // redefine individually with GSTPAR any of these parameters for a | |
491 | // given tracking medium. | |
492 | // ITMED tracking medium number | |
493 | // CHPAR is a character string (variable name) | |
494 | // PARVAL must be given as a floating point. | |
495 | // --- | |
496 | ||
497 | // write token to the output file | |
498 | if (fWriteGeometry) | |
499 | fOutputManager->WriteGstpar(itmed, param, parval); | |
500 | ||
501 | // get physics setup | |
502 | TG4PhysicsManager* physicsManager = TG4PhysicsManager::Instance(); | |
503 | //TG4CutVector* cutVector = physicsManager->GetCutVector(); | |
504 | //TG4FlagVector* flagVector = physicsManager->GetFlagVector(); | |
505 | ||
506 | G4String name = CutName(param); | |
507 | TG3Cut g3Cut; | |
508 | if (physicsManager->CheckCutWithCutVector(name, parval, g3Cut)) { | |
509 | GstparCut(itmed, g3Cut, parval); | |
510 | physicsManager->Lock(); | |
511 | } | |
512 | else { | |
513 | TG3Flag g3Flag; | |
514 | if (physicsManager->CheckFlagWithFlagVector(name, parval, g3Flag)) { | |
515 | GstparFlag(itmed, g3Flag, parval); | |
516 | physicsManager->Lock(); | |
517 | } | |
518 | else if (g3Cut==kNoG3Cuts && g3Flag==kNoG3Flags) { | |
519 | G4String text = "TG4GeometryManager::Gstpar:"; | |
520 | text = text + name; | |
521 | text = text + " parameter is not yet implemented."; | |
522 | TG4Globals::Warning(text); | |
523 | } | |
524 | } | |
525 | } | |
526 | ||
527 | ||
528 | void TG4GeometryManager::Gsckov(Int_t itmed, Int_t npckov, Float_t* ppckov, | |
529 | Float_t* absco, Float_t* effic, Float_t* rindex) | |
530 | { | |
531 | // | |
532 | // Geant3 desription: | |
533 | // ================== | |
534 | // | |
535 | // Stores the tables for UV photon tracking in medium ITMED | |
536 | // Please note that it is the user's responsability to | |
537 | // provide all the coefficients: | |
538 | // | |
539 | // | |
540 | // ITMED Tracking medium number | |
541 | // NPCKOV Number of bins of each table | |
542 | // PPCKOV Value of photon momentum (in GeV) | |
543 | // ABSCO Absorbtion coefficients | |
544 | // dielectric: absorbtion length in cm | |
545 | // metals : absorbtion fraction (0<=x<=1) | |
546 | // EFFIC Detection efficiency for UV photons | |
547 | // RINDEX Refraction index (if=0 metal) | |
548 | // --- | |
549 | ||
550 | G4double* ppckovDbl = CreateG4doubleArray(ppckov, npckov); | |
551 | G4double* abscoDbl = CreateG4doubleArray(absco, npckov); | |
552 | G4double* efficDbl = CreateG4doubleArray(effic, npckov); | |
553 | G4double* rindexDbl = CreateG4doubleArray(rindex, npckov); | |
554 | ||
555 | // add units | |
556 | G4int i; | |
557 | for (i=0; i<npckov; i++) { | |
558 | ppckovDbl[i] = ppckovDbl[i]*TG3Units::Energy(); | |
559 | abscoDbl[i] = abscoDbl[i]*TG3Units::Length(); | |
560 | } | |
561 | ||
562 | // create material properties table | |
563 | G4MaterialPropertiesTable* table = new G4MaterialPropertiesTable(); | |
564 | table->AddProperty("ABSLENGTH", ppckovDbl, abscoDbl, npckov); | |
565 | // used in G4OpAbsorption process | |
566 | table->AddProperty("EFFICIENCY", ppckovDbl, efficDbl, npckov); | |
567 | // used in G4OpBoundary process | |
568 | table->AddProperty("RINDEX", ppckovDbl, rindexDbl, npckov); | |
569 | // used in G4Cerenkov, G4OpRayleigh, G4OpBoundary | |
570 | ||
571 | // get material of medium from table | |
572 | G3MedTableEntry* medium = G3Med.get(itmed); | |
573 | if (!medium) { | |
574 | G4String text = "TG4GeometryManager::Gsckov: \n"; | |
575 | text = text + " Medium not found."; | |
576 | G4Exception(text); | |
577 | } | |
578 | G4Material* material = medium->GetMaterial(); | |
579 | ||
580 | // set material properties table | |
581 | material->SetMaterialPropertiesTable(table); | |
582 | ||
583 | G4cout << "The tables for UV photon tracking set for " | |
3c7cd15a | 584 | << material->GetName() << G4endl; |
2817d3e2 | 585 | for (i=0; i<npckov; i++) |
3c7cd15a | 586 | G4cout << ppckovDbl[i] << " " << rindexDbl[i] << G4endl; |
2817d3e2 | 587 | |
588 | delete ppckovDbl; | |
589 | delete abscoDbl; | |
590 | delete efficDbl; | |
591 | delete rindexDbl; | |
592 | } | |
593 | ||
594 | ||
595 | void TG4GeometryManager::Gsdvn(const char *name, const char *mother, | |
596 | Int_t ndiv, Int_t iaxis) | |
597 | { | |
598 | // Geant3 desription: | |
599 | // ================== | |
600 | // NAME Volume name | |
601 | // MOTHER Mother volume name | |
602 | // NDIV Number of divisions | |
603 | // IAXIS Axis value | |
604 | // | |
605 | // X,Y,Z of CAXIS will be translated to 1,2,3 for IAXIS. | |
606 | // It divides a previously defined volume. | |
607 | // --- | |
608 | ||
609 | // write token to the output file | |
610 | if (fWriteGeometry) | |
611 | fOutputManager->WriteGsdvn(name, mother, ndiv, iaxis); | |
612 | ||
613 | G4gsdvn(CutName(name), CutName(mother), ndiv, iaxis); | |
614 | ||
615 | // register name in name map | |
616 | fNameMap.AddName(CutName(name)); | |
617 | } | |
618 | ||
619 | ||
620 | void TG4GeometryManager::Gsdvn2(const char *name, const char *mother, | |
621 | Int_t ndiv, Int_t iaxis, Float_t c0i, Int_t numed) | |
622 | { | |
623 | // Geant3 desription: | |
624 | // ================== | |
625 | // DIVIDES MOTHER INTO NDIV DIVISIONS CALLED NAME | |
626 | // ALONG AXIS IAXIS STARTING AT COORDINATE VALUE C0. | |
627 | // THE NEW VOLUME CREATED WILL BE MEDIUM NUMBER NUMED. | |
628 | // --- | |
629 | ||
630 | // write token to the output file | |
631 | if (fWriteGeometry) | |
632 | fOutputManager->WriteGsdvn2(name, mother, ndiv, iaxis, c0i, numed); | |
633 | ||
634 | G4gsdvn2(CutName(name),CutName(mother), ndiv, iaxis, c0i, numed); | |
635 | ||
636 | // register name in name map | |
637 | fNameMap.AddName(CutName(name)); | |
638 | } | |
639 | ||
640 | ||
641 | void TG4GeometryManager::Gsdvt(const char *name, const char *mother, | |
642 | Float_t step, Int_t iaxis, Int_t numed, Int_t ndvmx) | |
643 | { | |
644 | // Geant3 desription: | |
645 | // ================== | |
646 | // Divides MOTHER into divisions called NAME along | |
647 | // axis IAXIS in steps of STEP. If not exactly divisible | |
648 | // will make as many as possible and will centre them | |
649 | // with respect to the mother. Divisions will have medium | |
650 | // number NUMED. If NUMED is 0, NUMED of MOTHER is taken. | |
651 | // NDVMX is the expected maximum number of divisions | |
652 | // (If 0, no protection tests are performed) | |
653 | // --- | |
654 | ||
655 | // write token to the output file | |
656 | if (fWriteGeometry) | |
657 | fOutputManager->WriteGsdvt(name, mother, step, iaxis, numed, ndvmx); | |
658 | ||
659 | G4gsdvt(CutName(name), CutName(mother), step, iaxis, numed, ndvmx); | |
660 | ||
661 | // register name in name map | |
662 | fNameMap.AddName(CutName(name)); | |
663 | } | |
664 | ||
665 | ||
666 | void TG4GeometryManager::Gsdvt2(const char *name, const char *mother, | |
667 | Float_t step, Int_t iaxis, Float_t c0, Int_t numed, Int_t ndvmx) | |
668 | { | |
669 | // Geant3 desription: | |
670 | // ================== | |
671 | // Create a new volume by dividing an existing one | |
672 | // | |
673 | // Divides MOTHER into divisions called NAME along | |
674 | // axis IAXIS starting at coordinate value C0 with step | |
675 | // size STEP. | |
676 | // The new volume created will have medium number NUMED. | |
677 | // If NUMED is 0, NUMED of mother is taken. | |
678 | // NDVMX is the expected maximum number of divisions | |
679 | // (If 0, no protection tests are performed) | |
680 | // --- | |
681 | ||
682 | // write token to the output file | |
683 | if (fWriteGeometry) | |
684 | fOutputManager->WriteGsdvt2(name, mother, step, iaxis, c0, numed, ndvmx); | |
685 | ||
686 | G4gsdvt2(CutName(name), CutName(mother), step, iaxis, c0, numed, ndvmx); | |
687 | ||
688 | // register name in name map | |
689 | fNameMap.AddName(CutName(name)); | |
690 | } | |
691 | ||
692 | ||
693 | void TG4GeometryManager::Gsord(const char *name, Int_t iax) | |
694 | { | |
695 | // No corresponding action in G4. | |
696 | // | |
697 | // Geant3 desription: | |
698 | // ================== | |
699 | // Flags volume CHNAME whose contents will have to be ordered | |
700 | // along axis IAX, by setting the search flag to -IAX | |
701 | // IAX = 1 X axis | |
702 | // IAX = 2 Y axis | |
703 | // IAX = 3 Z axis | |
704 | // IAX = 4 Rxy (static ordering only -> GTMEDI) | |
705 | // IAX = 14 Rxy (also dynamic ordering -> GTNEXT) | |
706 | // IAX = 5 Rxyz (static ordering only -> GTMEDI) | |
707 | // IAX = 15 Rxyz (also dynamic ordering -> GTNEXT) | |
708 | // IAX = 6 PHI (PHI=0 => X axis) | |
709 | // IAX = 7 THETA (THETA=0 => Z axis) | |
710 | // --- | |
711 | ||
712 | TG4Globals::Warning("TG4GeometryManager::Gsord: dummy method."); | |
713 | } | |
714 | ||
715 | ||
716 | void TG4GeometryManager::Gspos(const char *vname, Int_t num, | |
717 | const char *vmoth, Float_t x, Float_t y, Float_t z, Int_t irot, | |
718 | const char *vonly) | |
719 | { | |
720 | // Geant3 desription: | |
721 | // ================== | |
722 | // Position a volume into an existing one | |
723 | // | |
724 | // NAME Volume name | |
725 | // NUMBER Copy number of the volume | |
726 | // MOTHER Mother volume name | |
727 | // X X coord. of the volume in mother ref. sys. | |
728 | // Y Y coord. of the volume in mother ref. sys. | |
729 | // Z Z coord. of the volume in mother ref. sys. | |
730 | // IROT Rotation matrix number w.r.t. mother ref. sys. | |
731 | // ONLY ONLY/MANY flag | |
732 | // | |
733 | // It positions a previously defined volume in the mother. | |
734 | // --- | |
735 | ||
736 | // write token to the output file | |
737 | if (fWriteGeometry) | |
738 | fOutputManager->WriteGspos(vname, num, vmoth, x, y, z, irot, vonly); | |
739 | ||
740 | G4gspos(CutName(vname), num, CutName(vmoth), x, y, z, irot, vonly); | |
741 | ||
742 | // register name in name map | |
743 | fNameMap.AddName(CutName(vname)); | |
744 | } | |
745 | ||
746 | ||
747 | void TG4GeometryManager::Gsposp(const char *name, Int_t nr, | |
748 | const char *mother, Float_t x, Float_t y, Float_t z, Int_t irot, | |
749 | const char *konly, Float_t *upar, Int_t np ) | |
750 | { | |
751 | // Geant3 desription: | |
752 | // ================== | |
753 | // Place a copy of generic volume NAME with user number | |
754 | // NR inside MOTHER, with its parameters UPAR(1..NP) | |
755 | // --- | |
756 | ||
757 | G4double* parin = CreateG4doubleArray(upar, np); | |
758 | ||
759 | // write token to the output file | |
760 | if (fWriteGeometry) | |
761 | fOutputManager->WriteGsposp(name, nr, mother, x, y, z, irot, konly, parin, np); | |
762 | ||
763 | G4gsposp(CutName(name), nr, CutName(mother), x, y, z, irot, konly, | |
764 | parin, np); | |
765 | ||
766 | delete [] parin; | |
767 | ||
768 | // register name in name map | |
769 | fNameMap.AddName(CutName(name)); | |
770 | } | |
771 | ||
772 | ||
773 | Int_t TG4GeometryManager::Gsvolu(const char *name, const char *shape, | |
774 | Int_t nmed, Float_t *upar, Int_t npar) | |
775 | { | |
776 | // Geant3 desription: | |
777 | // ================== | |
778 | // NAME Volume name | |
779 | // SHAPE Volume type | |
780 | // NUMED Tracking medium number | |
781 | // NPAR Number of shape parameters | |
782 | // UPAR Vector containing shape parameters | |
783 | // | |
784 | // It creates a new volume in the JVOLUM data structure. | |
785 | // --- | |
786 | ||
787 | G4double* parin = CreateG4doubleArray(upar, npar); | |
788 | ||
789 | // write token to the output file | |
790 | if (fWriteGeometry) | |
791 | fOutputManager->WriteGsvolu(name, shape, nmed, parin, npar); | |
792 | ||
793 | G4gsvolu(CutName(name), CutName(shape), nmed, parin, npar); | |
794 | ||
795 | delete [] parin; | |
796 | ||
797 | // register name in name map | |
798 | fNameMap.AddName(CutName(name)); | |
799 | ||
800 | return 0; | |
801 | } | |
802 | ||
803 | ||
57f88f6f | 804 | void TG4GeometryManager::WriteEuclid(const char* fileName, |
805 | const char* topVolName, Int_t number, Int_t nlevel) | |
2817d3e2 | 806 | { |
807 | // Geant3 desription: | |
808 | // ================== | |
809 | // | |
810 | // ****************************************************************** | |
811 | // * * | |
812 | // * Write out the geometry of the detector in EUCLID file format * | |
813 | // * * | |
814 | // * filnam : will be with the extension .euc * | |
815 | // * topvol : volume name of the starting node * | |
816 | // * number : copy number of topvol (relevant for gsposp) * | |
817 | // * nlevel : number of levels in the tree structure * | |
818 | // * to be written out, starting from topvol * | |
819 | // * * | |
820 | // * Author : M. Maire * | |
821 | // * * | |
822 | // ****************************************************************** | |
823 | // | |
824 | // File filnam.tme is written out with the definitions of tracking | |
825 | // medias and materials. | |
826 | // As to restore original numbers for materials and medias, program | |
827 | // searches in the file euc_medi.dat and comparing main parameters of | |
828 | // the mat. defined inside geant and the one in file recognizes them | |
829 | // and is able to take number from file. If for any material or medium, | |
830 | // this procedure fails, ordering starts from 1. | |
831 | // Arrays IOTMED and IOMATE are used for this procedure | |
832 | // --- | |
833 | ||
834 | TG4Globals::Warning( | |
835 | "TG4GeometryManager::WriteEuclid(..) is not yet implemented."); | |
836 | } | |
837 | ||
838 | ||
839 | Int_t TG4GeometryManager::VolId(const Text_t* volName) const | |
840 | { | |
841 | // Returns the sensitive detector identifier. | |
842 | // !! Gives exception in case logical volume is not associated with | |
843 | // a sensitive detector. | |
844 | // --- | |
845 | ||
846 | G4String g4VolName = CutName(volName); | |
847 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
848 | ||
849 | for (G4int i=0; i<pLVStore->entries(); i++) { | |
850 | G4LogicalVolume* lv = pLVStore->at(i); | |
851 | G4VSensitiveDetector* sd = lv->GetSensitiveDetector(); | |
852 | ||
853 | if ((sd) && (sd->GetName()==g4VolName)) { | |
854 | TG4VSensitiveDetector* tsd = dynamic_cast<TG4VSensitiveDetector*>(sd); | |
855 | if (tsd) | |
856 | return tsd->GetID(); | |
857 | else { | |
858 | TG4Globals::Exception( | |
859 | "TG4GeometryManager::VolId: Unknown sensitive detector type"); | |
860 | return 0; | |
3c7cd15a | 861 | } |
2817d3e2 | 862 | } |
863 | } | |
864 | ||
865 | G4String text = "TG4GeometryManager::VolId: Sensitive detector "; | |
866 | text = text + g4VolName; | |
867 | text = text + " is not defined.\n"; | |
75dcb77f | 868 | TG4Globals::Warning(text); |
2817d3e2 | 869 | return 0; |
870 | } | |
871 | ||
872 | ||
873 | const char* TG4GeometryManager::VolName(Int_t id) const | |
874 | { | |
875 | // Returns the name of the sensitive detector with the given identifier. | |
876 | // !! Gives exception in case logical volume is not associated with | |
877 | // a sensitive detector. | |
878 | // --- | |
879 | ||
880 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
881 | ||
882 | for (G4int i=0; i<pLVStore->entries(); i++) { | |
883 | G4LogicalVolume* lv = pLVStore->at(i); | |
884 | G4VSensitiveDetector* sd = lv->GetSensitiveDetector(); | |
885 | ||
886 | if (sd) { | |
887 | G4int sdID; | |
888 | TG4VSensitiveDetector* tsd = dynamic_cast<TG4VSensitiveDetector*>(sd); | |
889 | if (tsd) | |
890 | sdID = tsd->GetID(); | |
891 | else { | |
892 | TG4Globals::Exception( | |
893 | "TG4GeometryManager::VolId: Unknown sensitive detector type"); | |
894 | return 0; | |
3c7cd15a | 895 | } |
2817d3e2 | 896 | if (sdID == id) return sd->GetName(); |
897 | } | |
898 | } | |
899 | ||
900 | G4String text = "TG4GeometryManager::VolName:\n"; | |
901 | text = text + " Sensitive detector with given id is not defined. \n"; | |
75dcb77f | 902 | TG4Globals::Warning(text); |
2817d3e2 | 903 | return ""; |
904 | } | |
905 | ||
906 | ||
907 | Int_t TG4GeometryManager::NofVolumes() const | |
908 | { | |
909 | // Returns the total number of sensitive detectors. | |
910 | // --- | |
911 | ||
912 | return NofSensitiveDetectors(); | |
913 | } | |
914 | ||
915 | ||
916 | void TG4GeometryManager::ReadG3Geometry(G4String filePath) | |
917 | { | |
918 | // Processes g3calls.dat file and fills G3 tables. | |
919 | // --- | |
920 | ||
921 | // add verbose | |
3c7cd15a | 922 | G4cout << "Reading the call list file " << filePath << "..." << G4endl; |
2817d3e2 | 923 | G3CLRead(filePath, NULL); |
3c7cd15a | 924 | G4cout << "Call list file read completed. Build geometry" << G4endl; |
2817d3e2 | 925 | } |
926 | ||
927 | ||
928 | //============================================================================= | |
929 | // | |
930 | // public methods - Geant4 only | |
931 | // | |
932 | //============================================================================= | |
933 | ||
934 | ||
935 | G4VPhysicalVolume* TG4GeometryManager::CreateG4Geometry() | |
936 | { | |
937 | // Creates G4 geometry objects according to the G3VolTable | |
938 | // and returns the top physical volume in case it was created | |
939 | // (return zero otherwise). | |
940 | // --- | |
941 | ||
942 | // set the first entry in the G3Vol table | |
943 | Ggclos(); | |
944 | G3VolTableEntry* first = G3Vol.GetFirstVTE(); | |
2817d3e2 | 945 | |
946 | // create G4 geometry | |
947 | G3toG4BuildTree(first,0); | |
948 | ||
949 | // print G3 volume table statistics | |
950 | G3Vol.VTEStat(); | |
951 | ||
952 | // print G4 geometry statistics | |
953 | G4cout << "G4 Stat: instantiated " | |
954 | << NofG4LogicalVolumes() << " logical volumes \n" | |
955 | << " " | |
3c7cd15a | 956 | << NofG4PhysicalVolumes() << " physical volumes" << G4endl; |
2817d3e2 | 957 | |
958 | // position the first entry | |
959 | // (in Geant3 the top volume cannot be positioned) | |
960 | // | |
961 | G4VPhysicalVolume* top = 0; | |
962 | if (first->GetLV()->GetNoDaughters() == 0) { | |
963 | top = new G4PVPlacement(0, G4ThreeVector(), first->GetName(), | |
964 | first->GetLV(), 0, false, 0); | |
965 | } | |
966 | return top; | |
967 | } | |
968 | ||
969 | ||
970 | void TG4GeometryManager::UseG3TrackingMediaLimits() | |
971 | { | |
972 | // Sets fUseG3TMLimits option. | |
973 | // !! This method has to be called only before starting | |
974 | // creating geometry. | |
975 | // --- | |
976 | ||
977 | if (fMediumCounter == 0) { | |
978 | fUseG3TMLimits = true; | |
979 | } | |
980 | else { | |
981 | G4String text = "TG4GeometryManager::UseG3TMLimits: \n"; | |
982 | text = text + " It is too late to set G3 defaults. \n"; | |
983 | text = text + " Some media has been already processed."; | |
984 | TG4Globals::Exception(text); | |
985 | } | |
986 | } | |
987 | ||
988 | ||
989 | void TG4GeometryManager::ClearG3Tables() | |
990 | { | |
991 | // Clears G3 volumes, materials, rotations(?) tables | |
992 | // and sensitive volumes vector. | |
993 | // The top volume is kept in the vol table. | |
994 | // --- | |
995 | ||
996 | // clear volume table | |
997 | // but keep the top volume in the table | |
998 | G3VolTableEntry* top = G3Vol.GetFirstVTE(); | |
999 | G4String name = top->GetName(); | |
1000 | G4String shape = top->GetShape(); | |
1001 | G3VolTableEntry* keep | |
1002 | = new G3VolTableEntry(name, shape, top->GetRpar(), top->GetNpar(), | |
1003 | top->GetNmed(), top->GetSolid(), false); | |
1004 | keep->SetLV(top->GetLV()); | |
1005 | G3Vol.Clear(); | |
1006 | G3Vol.PutVTE(keep); | |
1007 | ||
1008 | // clear other tables | |
1009 | G3Mat.Clear(); | |
1010 | //G3Rot.Clear(); | |
1011 | G3SensVol.clear(); | |
1012 | } | |
1013 | ||
1014 | ||
1015 | void TG4GeometryManager::ClearG3TablesFinal() | |
1016 | { | |
1017 | // Clears G3 medias and volumes tables | |
1018 | // (the top volume is removed from the vol table) | |
1019 | // --- | |
1020 | ||
1021 | // fill medium id vector | |
1022 | FillMediumIdVector(); | |
1023 | ||
1024 | G3Med.Clear(); | |
1025 | G3Vol.Clear(); | |
1026 | ||
1027 | // reset medium counter | |
1028 | //fMaterialCounter = 0; | |
1029 | fMediumCounter = 0; | |
1030 | } | |
1031 | ||
1032 | ||
1033 | void TG4GeometryManager::OpenOutFile(G4String filePath) | |
1034 | { | |
1035 | // Opens output file. | |
1036 | // --- | |
1037 | ||
1038 | fOutputManager->OpenFile(filePath); | |
1039 | } | |
1040 | ||
1041 | ||
08b8559d | 1042 | void TG4GeometryManager::CloseOutFile() |
1043 | { | |
1044 | // Closes output file. | |
1045 | // --- | |
1046 | ||
1047 | fOutputManager->CloseFile(); | |
1048 | } | |
1049 | ||
1050 | ||
2817d3e2 | 1051 | void TG4GeometryManager::PrintNameMap() |
1052 | { | |
1053 | // Prints the map of volumes names to second names. | |
1054 | // --- | |
1055 | ||
1056 | fNameMap.PrintAll(); | |
1057 | } | |
1058 | ||
1059 | ||
1060 | void TG4GeometryManager::SetWriteGeometry(G4bool writeGeometry) | |
1061 | { | |
1062 | // Controls geometry output. | |
1063 | // --- | |
1064 | ||
1065 | fWriteGeometry = writeGeometry; | |
1066 | } | |
1067 | ||
1068 | ||
1069 | void TG4GeometryManager::SetMapSecond(const G4String& name) | |
1070 | { | |
1071 | // Sets the second name for the map of volumes names. | |
1072 | // --- | |
1073 | ||
1074 | fNameMap.SetSecond(name); | |
1075 | } | |
1076 | ||
1077 | ||
1078 | Int_t TG4GeometryManager::NofG3Volumes() const | |
1079 | { | |
1080 | // Returns the total number of logical volumes corresponding | |
1081 | // to G3 volumes. ( | |
1082 | // The logical volume that were created by Gsposp method | |
1083 | // with a generic name (name_copyNo) are NOT included. | |
1084 | // --- | |
1085 | ||
1086 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
1087 | ||
1088 | G4int counter = 0; | |
1089 | for (G4int i=0; i<pLVStore->entries(); i++) { | |
1090 | G4LogicalVolume* lv = (*pLVStore)[i]; | |
1091 | if (IsG3Volume(lv->GetName())) counter++; | |
1092 | } | |
1093 | ||
1094 | return counter; | |
1095 | } | |
1096 | ||
1097 | ||
1098 | Int_t TG4GeometryManager::NofG4LogicalVolumes() const | |
1099 | { | |
1100 | // Returns the total number of logical volumes in the geometry. | |
1101 | // --- | |
1102 | ||
1103 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
1104 | return pLVStore->entries(); | |
1105 | } | |
1106 | ||
1107 | ||
1108 | Int_t TG4GeometryManager::NofG4PhysicalVolumes() const | |
1109 | { | |
1110 | // Returns the total number of physical volumes in the geometry. | |
1111 | // --- | |
1112 | ||
1113 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
1114 | ||
1115 | G4int counter = 0; | |
1116 | for (G4int i=0; i<pLVStore->entries(); i++) { | |
1117 | counter += ((*pLVStore)[i])->GetNoDaughters(); | |
1118 | } | |
1119 | ||
1120 | return counter; | |
1121 | } | |
1122 | ||
1123 | ||
1124 | Int_t TG4GeometryManager::NofSensitiveDetectors() const | |
1125 | { | |
1126 | // Returns the total number of sensitive detectors. | |
1127 | // --- | |
1128 | ||
1129 | return TG4VSensitiveDetector::GetTotalNofSensitiveDetectors(); | |
1130 | } | |
1131 | ||
1132 | ||
1133 | G4bool TG4GeometryManager::IsG3Volume(G4String lvName) const | |
1134 | { | |
1135 | // Returns true if the logical volume of given volumeName | |
1136 | // was not created by Gsposp method with a generic name | |
1137 | // (name_copyNo). | |
1138 | // --- | |
1139 | ||
1140 | if (lvName.contains(gSeparator)) | |
1141 | return false; | |
1142 | else | |
1143 | return true; | |
1144 | } | |
1145 | ||
1146 | ||
1147 | void TG4GeometryManager::G4ToG3VolumeName(G4String& name) const | |
1148 | { | |
1149 | // Cuts _copyNo extension added to logical volume name in case | |
1150 | // the logical volume was created by Gsposp method. | |
1151 | // --- | |
1152 | ||
1153 | if (name.contains(gSeparator)) | |
1154 | name = name(0,name.first(gSeparator)); | |
1155 | } | |
1156 | ||
1157 | ||
1158 | const G4String& TG4GeometryManager::GetMapSecond(const G4String& name) | |
1159 | { | |
1160 | // Returns the second string associated with the name in | |
1161 | // the name map. | |
1162 | // --- | |
1163 | ||
1164 | return fNameMap.GetSecond(name); | |
1165 | } | |
1166 | ||
1167 | ||
1168 | G4int TG4GeometryManager::GetMediumId(G4Material* material) const | |
1169 | { | |
1170 | // Returns the second index for materials (having its origin in | |
1171 | // G4 tracking media concept) | |
1172 | // --- | |
1173 | ||
1174 | return fMediumIdVector[material->GetIndex()]; | |
1175 | } | |
1176 | ||
1177 | ||
1178 | G4double TG4GeometryManager::GetEffA(G4Material* material) const | |
1179 | { | |
1180 | // Returns A or effective A=sum(pi*Ai) (if compound/mixture) | |
1181 | // of given material. | |
1182 | // --- | |
1183 | ||
1184 | G4double a = 0.; | |
1185 | G4int nofElements = material->GetNumberOfElements(); | |
1186 | if (nofElements > 1) { | |
1187 | G4String text = "Effective A for material mixture ("; | |
1188 | text = text + material->GetName(); | |
1189 | text = text + ") is used."; | |
1190 | //TG4Globals::Warning(text); | |
1191 | ||
1192 | for (G4int i=0; i<nofElements; i++) { | |
1193 | G4double aOfElement = material->GetElement(i)->GetA(); | |
1194 | G4double massFraction = material->GetFractionVector()[i]; | |
1195 | a += aOfElement*massFraction /(TG3Units::AtomicWeight()); | |
1196 | } | |
1197 | } | |
1198 | else { | |
1199 | a = material->GetA(); | |
1200 | a /= TG3Units::AtomicWeight(); | |
1201 | } | |
1202 | return a; | |
1203 | } | |
1204 | ||
1205 | ||
1206 | G4double TG4GeometryManager::GetEffZ(G4Material* material) const | |
1207 | { | |
1208 | // Returns Z or effective Z=sum(pi*Zi) (if compound/mixture) | |
1209 | // of given material. | |
1210 | // --- | |
1211 | ||
1212 | G4double z = 0.; | |
1213 | G4int nofElements = material->GetNumberOfElements(); | |
1214 | if (nofElements > 1) { | |
1215 | G4String text = "Effective Z for material mixture ("; | |
1216 | text = text + material->GetName(); | |
1217 | text = text + ") is used."; | |
1218 | //TG4Globals::Warning(text); | |
1219 | ||
1220 | for (G4int i=0; i<nofElements; i++) { | |
1221 | G4double zOfElement = material->GetElement(i)->GetZ(); | |
1222 | G4double massFraction = material->GetFractionVector()[i]; | |
1223 | z += zOfElement*massFraction; | |
1224 | } | |
1225 | } | |
1226 | else { | |
1227 | z = material->GetZ(); | |
1228 | } | |
1229 | return z; | |
1230 | } |