]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TGeant4/TG4GeometryServices.cxx
Changes by Massimo Masera to allow Recpoints and Clusters to be written
[u/mrichter/AliRoot.git] / TGeant4 / TG4GeometryServices.cxx
CommitLineData
b68f7176 1// $Id$
2// Category: geometry
3//
e5967ab3 4// Author: I. Hrivnacova
5//
6// Class TG4GeometryServices
7// -------------------------
b68f7176 8// See the class description in the header file.
9
10#include "TG4GeometryServices.h"
e5967ab3 11#include "TG4Limits.h"
12#include "TG4IntMap.h"
13#include "TG4NameMap.h"
c4294cc7 14#include "TG4G3Units.h"
e5967ab3 15#include "TG4G3ControlVector.h"
16#include "TG4Globals.h"
b68f7176 17
b68f7176 18#include <G4LogicalVolumeStore.hh>
19#include <G4LogicalVolume.hh>
20#include <G4Material.hh>
e5967ab3 21#include <G4Element.hh>
e4a64a3a 22#include <G4UserLimits.hh>
b68f7176 23#include <G3toG4.hh>
e5967ab3 24#include <G3EleTable.hh>
25#include <g4std/vector>
fd81f1f5 26#include <g4std/iomanip>
e5967ab3 27
28#include <math.h>
b68f7176 29
30TG4GeometryServices* TG4GeometryServices::fgInstance = 0;
e5967ab3 31const G4double TG4GeometryServices::fgkAZTolerance = 0.001;
32const G4double TG4GeometryServices::fgkDensityTolerance = 0.005;
b68f7176 33
fed0483a 34//_____________________________________________________________________________
e5967ab3 35TG4GeometryServices::TG4GeometryServices(TG4IntMap* mediumMap,
b68f7176 36 TG4NameMap* nameMap)
5b6ecd36 37 : TG4Verbose("geometryServices"),
38 fMediumMap(mediumMap),
364266ea 39 fNameMap(nameMap),
40 fWorld(0)
b68f7176 41{
42//
43 if (fgInstance) {
44 TG4Globals::Exception(
45 "TG4GeometryServices: attempt to create two instances of singleton.");
46 }
47
b68f7176 48 fgInstance = this;
49}
50
fed0483a 51//_____________________________________________________________________________
5b6ecd36 52TG4GeometryServices::TG4GeometryServices()
53 : TG4Verbose("geometryServices") {
b68f7176 54//
55 TG4Globals::Exception(
e5967ab3 56 "TG4GeometryServices default constructor is protected.");
b68f7176 57}
58
59
fed0483a 60//_____________________________________________________________________________
5b6ecd36 61TG4GeometryServices::TG4GeometryServices(const TG4GeometryServices& right)
62 : TG4Verbose("geometryServices") {
b68f7176 63//
64 TG4Globals::Exception(
65 "Attempt to copy TG4GeometryServices singleton.");
66}
67
68
fed0483a 69//_____________________________________________________________________________
b68f7176 70TG4GeometryServices::~TG4GeometryServices() {
71//
72}
73
74//=============================================================================
75//
76// operators
77//
78//=============================================================================
79
fed0483a 80//_____________________________________________________________________________
b68f7176 81TG4GeometryServices&
82TG4GeometryServices::operator=(const TG4GeometryServices& right)
83{
84 // check assignement to self
85 if (this == &right) return *this;
86
87 TG4Globals::Exception(
88 "Attempt to assign TG4GeometryServices singleton.");
89
90 return *this;
91}
92
e5967ab3 93//=============================================================================
94//
95// private methods
96//
97//=============================================================================
98
99//_____________________________________________________________________________
100G4bool TG4GeometryServices::IsG3Volume(const G4String& lvName) const
101{
102// Returns true if the logical volume of given volumeName
103// was not created by Gsposp method with a generic name
104// (name_copyNo).
105// ---
106
107 if (lvName.contains(gSeparator))
108 return false;
109 else
110 return true;
111}
112
113//_____________________________________________________________________________
114G4bool TG4GeometryServices::CompareElement(G4double a, G4double z,
115 const G4Element* element) const
116{
117// Compares given parameters with those of a given element,
118// returns true if they are equal, false otherwise.
119// ---
120
121 G4double ae = element->GetA()/TG4G3Units::AtomicWeight();
122 G4double ze = element->GetZ();
123
124 // g3tog4 can redefine A
7c00fc32 125 G4double ax;
126 if (z<1) {
127 // vacuum
128 ax = 1.01*g/mole;
129 }
130 else
131 ax = G3Ele.GetEle(z)->GetA()/TG4G3Units::AtomicWeight();
e5967ab3 132
133 if (abs(ax - ae) < fgkAZTolerance && abs(z - ze) < fgkAZTolerance)
134 return true;
135 else
136 return false;
137}
138
139//_____________________________________________________________________________
140G4bool TG4GeometryServices::CompareMaterial(G4int nofElements, G4double density,
141 const G4Material* material) const
142{
143// Compares given density with those of a given material,
144// returns true if they are equal, false otherwise.
145// ---
146
147 G4double dm = material->GetDensity()/TG4G3Units::MassDensity();
148 G4int ne = material->GetNumberOfElements();
149
150 // density percentual difference
151 G4double diff = abs(density - dm)/(density + dm)*2.;
152
153 if (nofElements == ne && diff < fgkDensityTolerance)
154 return true;
155 else
156 return false;
157}
158
159//_____________________________________________________________________________
160G4double* TG4GeometryServices::ConvertAtomWeight(G4int nmat,
161 G4double* a, G4double* wmat) const
162{
163// In case of proportions given in atom counts (nmat<0),
164// the wmat[i] are converted to weight fractions.
165// (From g3tog4 G4gsmixt.)
166// The new array has to be delete by client.
167// ---
168
169 G4double* weight = new G4double[abs(nmat)];
170
171 if (nmat<0) {
172 G4double aMol = 0.;
173 G4int i;
174 for (i=0; i<abs(nmat); i++) {
175 // total molecular weight
176 aMol += wmat[i]*a[i];
177 }
178 if (aMol == 0.) {
179 G4String text = "TG4GeometryServices::ConvertAtomWeight:\n";
180 text = text + " Total molecular weight = 0";
181 TG4Globals::Warning(text);
182 }
183 for (G4int i=0; i<abs(nmat); i++) {
184 // weight fractions
185 weight[i] = wmat[i]*a[i]/aMol;
186 }
187 }
188 else
189 for (G4int j=0; j<nmat; j++) weight[j] = wmat[j];
190
191 return weight;
192}
b68f7176 193
194//=============================================================================
195//
196// public methods
197//
198//=============================================================================
199
fed0483a 200//_____________________________________________________________________________
b68f7176 201G4double* TG4GeometryServices::CreateG4doubleArray(Float_t* array,
202 G4int size) const
203{
204// Converts Float_t* array to G4double*,
205// !! The new array has to be deleted by user.
206// ---
207
208 G4double* doubleArray;
209 if (size>0) {
210 doubleArray = new G4double[size];
211 for (G4int i=0; i<size; i++) doubleArray[i] = array[i];
212 }
213 else {
214 doubleArray = 0;
215 }
216 return doubleArray;
217}
218
fed0483a 219//_____________________________________________________________________________
b68f7176 220G4String TG4GeometryServices::CutName(const char* name) const
221{
222// Removes spaces after the name if present.
223// ---
224
225 G4String cutName = name;
226 G4int i = cutName.length();
227 while (cutName(--i) == ' ') cutName = cutName(0,i);
228
229 return cutName;
230}
231
fed0483a 232//_____________________________________________________________________________
e5967ab3 233G4String TG4GeometryServices::CutMaterialName(const char* name) const
234{
235// Removes the $ with precedent spaces at the name if present.
236// ---
237
238 G4String cutName = name;
239 cutName = cutName.substr(0,cutName.find('$'));
240
241 return CutName(cutName);
242}
243
244//_____________________________________________________________________________
245G4String TG4GeometryServices::G4ToG3VolumeName(const G4String& name) const
b68f7176 246{
247// Cuts _copyNo extension added to logical volume name in case
248// the logical volume was created by Gsposp method.
249// ---
250
e5967ab3 251 G4String cutName = name;
252 if (cutName.contains(gSeparator))
253 cutName = cutName(0,cutName.first(gSeparator));
254
255 return cutName;
b68f7176 256}
257
fed0483a 258//_____________________________________________________________________________
e5967ab3 259G4String TG4GeometryServices::GenerateLimitsName(G4int id,
260 const G4String& medName,
261 const G4String& matName) const
e4a64a3a 262{
e5967ab3 263// Generate unique name for user limits composed from the tracking medium id,
264// name and its material name.
265//
266 G4String name = "";
267 TG4Globals::AppendNumberToString(name, id);
268 name = name + "__med_" + medName + "__mat_" + matName;
e4a64a3a 269
e5967ab3 270 return name;
e4a64a3a 271}
b68f7176 272
fed0483a 273//_____________________________________________________________________________
b68f7176 274G4Material* TG4GeometryServices::MixMaterials(G4String name, G4double density,
e5967ab3 275 const TG4StringVector& matNames,
276 const TG4doubleVector& matWeights)
b68f7176 277{
278// Creates a mixture of selected materials
279// ---
280
281 // number of materials to be mixed
e5967ab3 282 G4int nofMaterials = matNames.size();
283 if (nofMaterials != matWeights.size()) {
b68f7176 284 G4String text = "TG4GeometryServices::MixMaterials: ";
285 text = text + "different number of material names and weigths.";
286 TG4Globals::Exception(text);
5b6ecd36 287 }
288
289 if (VerboseLevel() > 1) {
290 G4cout << "Nof of materials to be mixed: " << nofMaterials << G4endl;
291 }
b68f7176 292
293 // fill vector of materials
e5967ab3 294 G4std::vector<G4Material*> matVector;
b68f7176 295 G4int im;
296 for (im=0; im< nofMaterials; im++) {
297 // material
e5967ab3 298 G4Material* material = G4Material::GetMaterial(matNames[im]);
299 matVector.push_back(material);
b68f7176 300 }
301
302 // create the mixed material
303 G4Material* mixture = new G4Material(name, density, nofMaterials);
304 for (im=0; im< nofMaterials; im++) {
305 G4Material* material = matVector[im];
e5967ab3 306 G4double fraction = matWeights[im];
b68f7176 307 mixture->AddMaterial(material, fraction);
308 }
309
310 return mixture;
311}
312
e5967ab3 313//_____________________________________________________________________________
314void TG4GeometryServices::PrintNameMap() const
315{
316// Prints the map of volumes names to second names.
317// ---
318
319 fNameMap->PrintAll();
320}
321
322//_____________________________________________________________________________
323void TG4GeometryServices::PrintLimits(const G4String& name) const
324{
325// Finds the limits with the specified name and prints them.
326// ---
327
328 TG4Limits* limits = FindLimits(name, true);
329
330 if (limits) limits->Print();
331}
332
333//_____________________________________________________________________________
334void TG4GeometryServices::PrintVolumeLimits(const G4String& volumeName) const
335{
336// Finds a logical volume with the specified name and prints
337// its limits.
338// ---
339
340 G4LogicalVolume* lv = FindLogicalVolume(volumeName, false);
341
342 if (lv) {
343 TG4Limits* limits = GetLimits(lv->GetUserLimits());
344 G4cout << volumeName << " ";
345 if (limits)
346 limits->Print();
347 else
348 G4cout << "has not the limits set." << G4endl;
349 }
350}
351
352//_____________________________________________________________________________
353void TG4GeometryServices::PrintStatistics(G4bool open, G4bool close) const
354{
355// Print G4 geometry statistics
356// ---
357
358
359 if (open) TG4Globals::PrintStars(true);
360
361 G4cout << " GEANT4 Geometry statistics: " << G4endl
fd81f1f5 362 << " " << G4std::setw(5) << NofG4LogicalVolumes()
e5967ab3 363 << " logical volumes" << G4endl
364 << " "
fd81f1f5 365 << G4std::setw(5) << NofG4PhysicalVolumes()
e5967ab3 366 << " physical volumes" << G4endl
367 << " "
fd81f1f5 368 << G4std::setw(5) << G4Material::GetNumberOfMaterials()
e5967ab3 369 << " materials" << G4endl
370 << " "
fd81f1f5 371 << G4std::setw(5) << TG4Limits::GetNofLimits()
e5967ab3 372 << " user limits" << G4endl;
373
374 if (close) TG4Globals::PrintStars(false);
375}
376
fd81f1f5 377//_____________________________________________________________________________
378void
379TG4GeometryServices::PrintLogicalVolumeStore() const
380{
381// Prints all logical volumes and their daughters.
382// ---
383
384 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
385
386 G4cout << "Logical volume store: " << G4endl;
387
388 for (G4int i=0; i<lvStore->size(); i++) {
389
390 G4LogicalVolume* lv = (*lvStore)[i];
391
392 G4cout << "Logical volume: " << G4endl;
393 G4cout << " " << G4std::setw(5) << i
394 << " " << lv
395 << " " << lv->GetName()
396 << " " << G4std::setw(5) << lv->GetNoDaughters() << " daughters"
397 << " limits: " << lv->GetUserLimits()
398 << G4endl;
399
400 for (G4int j=0; j<lv->GetNoDaughters(); j++) {
401 G4cout << " Daughter: "
402 << G4std::setw(5) << j
403 << " " << lv->GetDaughter(j)
404 << " " << lv->GetDaughter(j)->GetName()
405 << " of LV: " << lv->GetDaughter(j)->GetLogicalVolume()
406 << " " << lv->GetDaughter(j)->GetLogicalVolume()->GetName()
407 << " copy no: " << lv->GetDaughter(j)->GetCopyNo()
408 << G4endl;
409
410 }
411 }
412}
413
fed0483a 414//_____________________________________________________________________________
415Int_t TG4GeometryServices::NofG3Volumes() const
b68f7176 416{
417// Returns the total number of logical volumes corresponding
418// to G3 volumes. (
419// The logical volume that were created by Gsposp method
420// with a generic name (name_copyNo) are NOT included.
421// ---
422
e5967ab3 423 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
b68f7176 424
425 G4int counter = 0;
e5967ab3 426 for (G4int i=0; i<lvStore->size(); i++) {
427 G4LogicalVolume* lv = (*lvStore)[i];
b68f7176 428 if (IsG3Volume(lv->GetName())) counter++;
429 }
430
431 return counter;
432}
433
fed0483a 434//_____________________________________________________________________________
b68f7176 435Int_t TG4GeometryServices::NofG4LogicalVolumes() const
436{
437// Returns the total number of logical volumes in the geometry.
438// ---
439
e5967ab3 440 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
441 return lvStore->size();
b68f7176 442}
443
fed0483a 444//_____________________________________________________________________________
b68f7176 445Int_t TG4GeometryServices::NofG4PhysicalVolumes() const
446{
447// Returns the total number of physical volumes in the geometry.
448// ---
449
e5967ab3 450 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
b68f7176 451
452 G4int counter = 0;
e5967ab3 453 for (G4int i=0; i<lvStore->size(); i++) {
454 counter += ((*lvStore)[i])->GetNoDaughters();
b68f7176 455 }
456
457 return counter;
458}
459
e5967ab3 460
461//______________________________________________________________________________
462G4bool TG4GeometryServices::IsSpecialControls() const
b68f7176 463{
e5967ab3 464// Returns true if a process control in some limits instance is set.
b68f7176 465// ---
466
e5967ab3 467 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
468
469 for (G4int i=0; i<lvStore->size(); i++) {
470 TG4Limits* limits = GetLimits((*lvStore)[i]->GetUserLimits());
471 if (limits && limits->IsControl()) return true;
472 }
473
474 return false;
b68f7176 475}
476
e5967ab3 477//_____________________________________________________________________________
478TG4Limits* TG4GeometryServices::GetLimits(G4UserLimits* limits) const
479{
480// Checks and converts type of the given limits.
481// ---
482
483 if (!limits) return 0;
484
485 TG4Limits* tg4Limits = dynamic_cast<TG4Limits*> (limits);
486
487 if (!tg4Limits) {
488 G4Exception("TG4GeometryServices::GetLimits: Wrong limits type.");
489 return 0;
490 }
491 else
492 return tg4Limits;
493}
494
fed0483a 495//_____________________________________________________________________________
b68f7176 496const G4String& TG4GeometryServices::GetMapSecond(const G4String& name)
497{
498// Returns the second string associated with the name in
499// the name map.
500// ---
501
502 return fNameMap->GetSecond(name);
503}
504
e5967ab3 505//_____________________________________________________________________________
506G4LogicalVolume*
507TG4GeometryServices::FindLogicalVolume(const G4String& name, G4bool silent) const
508{
509// Finds a logical volume with the specified name in G4LogicalVolumeStore.
510// ---
511
512 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
513
514 for (G4int i=0; i<lvStore->size(); i++) {
515 G4LogicalVolume* lv = (*lvStore)[i];
516 if (lv->GetName() == name) return lv;
517 }
518
519 if (!silent) {
520 G4String text = "TG4GeometryServices:: FindLogicalVolume:\n";
521 text = text + " Logical volume " + name + " does not exist.";
522 TG4Globals::Warning(text);
523 }
524 return 0;
525}
526
fed0483a 527//_____________________________________________________________________________
e5967ab3 528TG4Limits*
529TG4GeometryServices::FindLimits(const G4String& name, G4bool silent) const
530{
531// Finds limits with the specified name.
532// ---
533
534 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
535
536 for (G4int i=0; i<lvStore->size(); i++) {
537 G4LogicalVolume* lv = (*lvStore)[i];
538 TG4Limits* limits = GetLimits(lv->GetUserLimits());
539 if (limits && limits->GetName() == name) return limits;
540 }
541
542 if (!silent) {
543 G4String text = "TG4GeometryServices:: FindLimits:\n";
544 text = text + " Logical volume " + name + " does not exist.";
545 TG4Globals::Warning(text);
546 }
547 return 0;
548}
549
550//_____________________________________________________________________________
551G4int TG4GeometryServices::GetMediumId(G4LogicalVolume* lv) const
b68f7176 552{
553// Returns the second index for materials (having its origin in
554// G4 tracking media concept)
555// ---
556
e5967ab3 557 return fMediumMap->GetSecond(lv->GetName());
b68f7176 558}
559
fed0483a 560//_____________________________________________________________________________
b68f7176 561G4double TG4GeometryServices::GetEffA(G4Material* material) const
562{
563// Returns A or effective A=sum(pi*Ai) (if compound/mixture)
564// of given material.
565// ---
566
567 G4double a = 0.;
568 G4int nofElements = material->GetNumberOfElements();
569 if (nofElements > 1) {
570 G4String text = "Effective A for material mixture (";
571 text = text + material->GetName();
572 text = text + ") is used.";
573 //TG4Globals::Warning(text);
574
575 for (G4int i=0; i<nofElements; i++) {
576 G4double aOfElement = material->GetElement(i)->GetA();
577 G4double massFraction = material->GetFractionVector()[i];
c4294cc7 578 a += aOfElement*massFraction /(TG4G3Units::AtomicWeight());
b68f7176 579 }
580 }
581 else {
582 a = material->GetA();
c4294cc7 583 a /= TG4G3Units::AtomicWeight();
b68f7176 584 }
585 return a;
586}
587
fed0483a 588//_____________________________________________________________________________
b68f7176 589G4double TG4GeometryServices::GetEffZ(G4Material* material) const
590{
591// Returns Z or effective Z=sum(pi*Zi) (if compound/mixture)
592// of given material.
593// ---
594
595 G4double z = 0.;
596 G4int nofElements = material->GetNumberOfElements();
597 if (nofElements > 1) {
598 G4String text = "Effective Z for material mixture (";
599 text = text + material->GetName();
600 text = text + ") is used.";
601 //TG4Globals::Warning(text);
602
603 for (G4int i=0; i<nofElements; i++) {
604 G4double zOfElement = material->GetElement(i)->GetZ();
605 G4double massFraction = material->GetFractionVector()[i];
606 z += zOfElement*massFraction;
607 }
608 }
609 else {
610 z = material->GetZ();
611 }
612 return z;
613}
e5967ab3 614
615//_____________________________________________________________________________
616G4Material* TG4GeometryServices::FindMaterial(G4double a, G4double z,
617 G4double density) const
618{
619// Finds material in G4MaterialTable with specified parameters,
620// returns 0 if not found.
621// ---
622
623 const G4MaterialTable* kpMatTable = G4Material::GetMaterialTable();
624
625 for (G4int i=0; i<G4Material::GetNumberOfMaterials(); i++) {
626
627 G4Material* material = (*kpMatTable)[i];
628
629 if (CompareElement(a, z, material->GetElement(0)) &&
630 CompareMaterial(1, density, material))
631
632 return material;
633 }
634
635 return 0;
636}
637
638//_____________________________________________________________________________
639G4Material* TG4GeometryServices::FindMaterial(G4double* a, G4double* z,
640 G4double density,
641 G4int nmat, G4double* wmat) const
642{
643// Finds material in G4MaterialTable with specified parameters,
644// returns 0 if not found.
645// ---
646
647 G4double* weight = ConvertAtomWeight(nmat, a, wmat);
648
649 // loop over materials
650 G4Material* found = 0;
651 for (G4int i=0; i<G4Material::GetNumberOfMaterials(); i++) {
652
653 G4Material* material = (*G4Material::GetMaterialTable())[i];
654 G4int nm = material->GetNumberOfElements();
655
656 if (CompareMaterial(nm, density, material)) {
657
658 // loop over elements
659 G4bool equal = true;
660 for (G4int ie=0; ie<nm; ie++) {
661
662 G4double we = (material->GetFractionVector())[ie];
663
664 if (!CompareElement(a[ie], z[ie], material->GetElement(ie)) ||
665 abs(weight[ie] - we) > fgkAZTolerance) {
666
667 equal = false;
668 break;
669 }
670 }
671 if (equal) {
672 found = material;
673 break;
674 }
675 }
676 }
677
678 delete [] weight;
679 return found;
680}
681