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