ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4ProductionCutsTable.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4ProductionCutsTable.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 //
28 //
29 // --------------------------------------------------------------
30 // GEANT 4 class implementation file/ History:
31 // 06/Oct. 2002, M.Asai : First implementation
32 // 02/Mar. 2008, H.Kurashige : Add messenger
33 // --------------------------------------------------------------
34 
35 #include "G4ProductionCutsTable.hh"
36 #include "G4ProductionCuts.hh"
39 #include "G4ParticleDefinition.hh"
40 #include "G4ParticleTable.hh"
41 #include "G4RegionStore.hh"
42 #include "G4LogicalVolume.hh"
43 #include "G4VPhysicalVolume.hh"
44 #include "G4RToEConvForElectron.hh"
45 #include "G4RToEConvForGamma.hh"
46 #include "G4RToEConvForPositron.hh"
47 #include "G4RToEConvForProton.hh"
48 #include "G4MaterialTable.hh"
49 #include "G4Material.hh"
50 #include "G4UnitsTable.hh"
51 
52 #include "G4Timer.hh"
53 #include "G4SystemOfUnits.hh"
54 #include "G4ios.hh"
55 #include <iomanip>
56 #include <fstream>
57 
58 
60 
63 {
64  static G4ProductionCutsTable theProductionCutsTable;
66  fG4ProductionCutsTable = &theProductionCutsTable;
67  }
69 }
70 
73  : firstUse(true),verboseLevel(1),fMessenger(nullptr)
74 {
75  for(size_t i=0;i< NumberOfG4CutIndex;i++)
76  {
79  rangeDoubleVector[i] = nullptr;
80  energyDoubleVector[i] = nullptr;
81  converters[i] = nullptr;
82  }
85 
86  // add messenger for UI
88 }
89 
92 {
93  fMessenger = nullptr;
94  defaultProductionCuts = nullptr;
95  fG4RegionStore = nullptr;
96 }
97 
100 {
101  if (defaultProductionCuts != nullptr) {
102  delete defaultProductionCuts;
103  defaultProductionCuts =nullptr;
104  }
105 
106  for(CoupleTableIterator itr=coupleTable.begin();itr!=coupleTable.end();itr++){
107  delete (*itr);
108  }
109  coupleTable.clear();
110 
111  for(size_t i=0;i< NumberOfG4CutIndex;i++){
112  delete rangeCutTable[i];
113  delete energyCutTable[i];
114  delete converters[i];
115  if(rangeDoubleVector[i] != nullptr) delete [] rangeDoubleVector[i];
116  if(energyDoubleVector[i] != nullptr) delete [] energyDoubleVector[i];
117  rangeCutTable[i] = nullptr;
118  energyCutTable[i] = nullptr;
119  converters[i] = nullptr;
120  rangeDoubleVector[i] = nullptr;
121  energyDoubleVector[i] = nullptr;
122  }
123  fG4ProductionCutsTable = nullptr;
124 
125  if (fMessenger != nullptr) delete fMessenger;
126  fMessenger = nullptr;
127 }
128 
130 {
131  if(firstUse){
132  if(G4ParticleTable::GetParticleTable()->FindParticle("gamma")){
133  converters[0] = new G4RToEConvForGamma();
135  }
136  if(G4ParticleTable::GetParticleTable()->FindParticle("e-")){
137  converters[1] = new G4RToEConvForElectron();
139  }
140  if(G4ParticleTable::GetParticleTable()->FindParticle("e+")){
141  converters[2] = new G4RToEConvForPositron();
143  }
144  if(G4ParticleTable::GetParticleTable()->FindParticle("proton")){
145  converters[3] = new G4RToEConvForProton();
147  }
148  firstUse = false;
149  }
150 
151  // Reset "used" flags of all couples
152  for(CoupleTableIterator CoupleItr=coupleTable.begin();
153  CoupleItr!=coupleTable.end();CoupleItr++)
154  {
155  (*CoupleItr)->SetUseFlag(false);
156  }
157 
158  // Update Material-Cut-Couple
159  typedef std::vector<G4Region*>::iterator regionIterator;
160  for(regionIterator rItr=fG4RegionStore->begin();
161  rItr!=fG4RegionStore->end();rItr++)
162  {
163  // Material scan is to be done only for the regions appear in the
164  // current tracking world.
165 // if((*rItr)->GetWorldPhysical()!=currentWorld) continue;
166  if((*rItr)->IsInMassGeometry() || (*rItr)->IsInParallelGeometry())
167  {
168 
169  G4ProductionCuts* fProductionCut = (*rItr)->GetProductionCuts();
170  std::vector<G4Material*>::const_iterator mItr =
171  (*rItr)->GetMaterialIterator();
172  size_t nMaterial = (*rItr)->GetNumberOfMaterials();
173  (*rItr)->ClearMap();
174 
175  for(size_t iMate=0;iMate<nMaterial;iMate++){
176  //check if this material cut couple has already been made
177  G4bool coupleAlreadyDefined = false;
178  G4MaterialCutsCouple* aCouple;
179  for(CoupleTableIterator cItr=coupleTable.begin();
180  cItr!=coupleTable.end();cItr++){
181  if( (*cItr)->GetMaterial()==(*mItr) &&
182  (*cItr)->GetProductionCuts()==fProductionCut){
183  coupleAlreadyDefined = true;
184  aCouple = *cItr;
185  break;
186  }
187  }
188 
189  // If this combination is new, cleate and register a couple
190  if(!coupleAlreadyDefined){
191  aCouple = new G4MaterialCutsCouple((*mItr),fProductionCut);
192  coupleTable.push_back(aCouple);
193  aCouple->SetIndex(coupleTable.size()-1);
194  }
195 
196  // Register this couple to the region
197  (*rItr)->RegisterMaterialCouplePair((*mItr),aCouple);
198 
199  // Set the couple to the proper logical volumes in that region
200  aCouple->SetUseFlag();
201 
202  std::vector<G4LogicalVolume*>::iterator rootLVItr
203  = (*rItr)->GetRootLogicalVolumeIterator();
204  size_t nRootLV = (*rItr)->GetNumberOfRootVolumes();
205  for(size_t iLV=0;iLV<nRootLV;iLV++) {
206  //Set the couple to the proper logical volumes in that region
207  G4LogicalVolume* aLV = *rootLVItr;
208  G4Region* aR = *rItr;
209 
210  ScanAndSetCouple(aLV,aCouple,aR);
211 
212  // Proceed to the next root logical volume in this region
213  rootLVItr++;
214  }
215 
216  // Proceed to next material in this region
217  mItr++;
218  }
219  }
220  }
221 
222  // Check if sizes of Range/Energy cuts tables are equal to the size of
223  // the couple table
224  // If new couples are made during the previous procedure, nCouple becomes
225  // larger then nTable
226  size_t nCouple = coupleTable.size();
227  size_t nTable = energyCutTable[0]->size();
228  G4bool newCoupleAppears = nCouple>nTable;
229  if(newCoupleAppears) {
230  for(size_t n=nCouple-nTable;n>0;n--) {
231  for(size_t nn=0;nn< NumberOfG4CutIndex;nn++){
232  rangeCutTable[nn]->push_back(-1.);
233  energyCutTable[nn]->push_back(-1.);
234  }
235  }
236  }
237 
238  // Update RangeEnergy cuts tables
239  size_t idx = 0;
240  G4Timer timer;
241  if (verboseLevel>2) {
242  timer.Start();
243  }
244  for(CoupleTableIterator cItr=coupleTable.begin();
245  cItr!=coupleTable.end();cItr++){
246  G4ProductionCuts* aCut = (*cItr)->GetProductionCuts();
247  const G4Material* aMat = (*cItr)->GetMaterial();
248  if((*cItr)->IsRecalcNeeded()) {
249  for(size_t ptcl=0;ptcl< NumberOfG4CutIndex;ptcl++){
250  G4double rCut = aCut->GetProductionCut(ptcl);
251  (*(rangeCutTable[ptcl]))[idx] = rCut;
252  // if(converters[ptcl] && (*cItr)->IsUsed())
253  if(converters[ptcl]) {
254  (*(energyCutTable[ptcl]))[idx] = converters[ptcl]->Convert(rCut,aMat);
255  } else {
256  (*(energyCutTable[ptcl]))[idx] = -1.;
257  }
258  }
259  }
260  idx++;
261  }
262  if (verboseLevel>2) {
263  timer.Stop();
264  G4cout << "G4ProductionCutsTable::UpdateCoupleTable "
265  << " elapsed time for calculation of energy cuts " << G4endl;
266  G4cout << timer <<G4endl;
267  }
268 
269  // resize Range/Energy cuts double vectors if new couple is made
270  if(newCoupleAppears){
271  for(size_t ix=0;ix<NumberOfG4CutIndex;ix++){
272  G4double* rangeVOld = rangeDoubleVector[ix];
273  G4double* energyVOld = energyDoubleVector[ix];
274  if(rangeVOld) delete [] rangeVOld;
275  if(energyVOld) delete [] energyVOld;
276  rangeDoubleVector[ix] = new G4double[(*(rangeCutTable[ix])).size()];
277  energyDoubleVector[ix] = new G4double[(*(energyCutTable[ix])).size()];
278  }
279  }
280 
281  // Update Range/Energy cuts double vectors
282  for(size_t ix=0;ix<NumberOfG4CutIndex;ix++) {
283  for(size_t ixx=0;ixx<(*(rangeCutTable[ix])).size();ixx++) {
284  rangeDoubleVector[ix][ixx] = (*(rangeCutTable[ix]))[ixx];
285  energyDoubleVector[ix][ixx] = (*(energyCutTable[ix]))[ixx];
286  }
287  }
288 }
289 
290 
294  const G4Material* material,
295  G4double range
296  )
297 {
298  // This method gives energy corresponding to range value
299 
300  // protection against premature call
301  if(firstUse)
302  {
303 #ifdef G4VERBOSE
304  if(verboseLevel>0)
305  {
307  ed << "G4ProductionCutsTable::ConvertRangeToEnergy is invoked prematurely "
308  << "before it is fully initialized.";
309  G4Exception("G4ProductionCutsTable::ConvertRangeToEnergy","CUTS0100",
310  JustWarning,ed);
311  }
312 #endif
313  return -1.0;
314  }
315 
316  // check material
317  if (material ==nullptr) return -1.0;
318 
319  // check range
320  if (range ==0.0) return 0.0;
321  if (range <0.0) return -1.0;
322 
323  // check particle
324  G4int index = G4ProductionCuts::GetIndex(particle);
325 
326  if (index<0 || converters[index] == nullptr) {
327 #ifdef G4VERBOSE
328  if(verboseLevel>0)
329  {
331  ed << "G4ProductionCutsTable::ConvertRangeToEnergy is invoked ";
332  if(particle != nullptr)
333  { ed << "for particle <" << particle->GetParticleName() << ">."; }
334  else
335  { ed << "without valid particle pointer."; }
336  G4Exception("G4ProductionCutsTable::ConvertRangeToEnergy","CUTS0101",
337  JustWarning,ed);
338  }
339 #endif
340  return -1.0;
341  }
342 
343  return converters[index]->Convert(range, material);
344 
345 }
346 
349 {
350  for(size_t i=0;i< NumberOfG4CutIndex;i++){
351  if (converters[i]!=0) converters[i]->Reset();
352  }
353 }
354 
355 
358 {
360 }
361 
364 {
366 }
367 
370 {
372 }
373 
374 
377  G4MaterialCutsCouple* aCouple,
378  G4Region* aRegion)
379 {
380  //Check whether or not this logical volume belongs to the same region
381  if((aRegion!=nullptr) && aLV->GetRegion()!=aRegion) return;
382 
383  //Check if this particular volume has a material matched to the couple
384  if(aLV->GetMaterial()==aCouple->GetMaterial()) {
385  aLV->SetMaterialCutsCouple(aCouple);
386  }
387 
388  size_t noDaughters = aLV->GetNoDaughters();
389  if(noDaughters==0) return;
390 
391  //Loop over daughters with same region
392  for(size_t i=0;i<noDaughters;i++){
393  G4LogicalVolume* daughterLVol = aLV->GetDaughter(i)->GetLogicalVolume();
394  ScanAndSetCouple(daughterLVol,aCouple,aRegion);
395  }
396 }
397 
400 {
401  G4cout << G4endl;
402  G4cout << "========= Table of registered couples =============================="
403  << G4endl;
404  for(CoupleTableIterator cItr=coupleTable.begin();
405  cItr!=coupleTable.end();cItr++) {
406  G4MaterialCutsCouple* aCouple = (*cItr);
407  G4ProductionCuts* aCut = aCouple->GetProductionCuts();
408  G4cout << G4endl;
409  G4cout << "Index : " << aCouple->GetIndex()
410  << " used in the geometry : ";
411  if(aCouple->IsUsed()) G4cout << "Yes";
412  else G4cout << "No ";
416  G4cout << G4endl;
417  G4cout << " Material : " << aCouple->GetMaterial()->GetName() << G4endl;
418  G4cout << " Range cuts : "
419  << " gamma " << G4BestUnit(aCut->GetProductionCut("gamma"),"Length")
420  << " e- " << G4BestUnit(aCut->GetProductionCut("e-"),"Length")
421  << " e+ " << G4BestUnit(aCut->GetProductionCut("e+"),"Length")
422  << " proton " << G4BestUnit(aCut->GetProductionCut("proton"),"Length")
423  << G4endl;
424  G4cout << " Energy thresholds : " ;
428  G4cout << " gamma " << G4BestUnit((*(energyCutTable[0]))[aCouple->GetIndex()],"Energy")
429  << " e- " << G4BestUnit((*(energyCutTable[1]))[aCouple->GetIndex()],"Energy")
430  << " e+ " << G4BestUnit((*(energyCutTable[2]))[aCouple->GetIndex()],"Energy")
431  << " proton " << G4BestUnit((*(energyCutTable[3]))[aCouple->GetIndex()],"Energy");
433  G4cout << G4endl;
434 
435  if(aCouple->IsUsed()) {
436  G4cout << " Region(s) which use this couple : " << G4endl;
437  typedef std::vector<G4Region*>::iterator regionIterator;
438  for(regionIterator rItr=fG4RegionStore->begin();
439  rItr!=fG4RegionStore->end();rItr++) {
440  if (IsCoupleUsedInTheRegion(aCouple, *rItr) ){
441  G4cout << " " << (*rItr)->GetName() << G4endl;
442  }
443  }
444  }
445  }
446  G4cout << G4endl;
447  G4cout << "====================================================================" << G4endl;
448  G4cout << G4endl;
449 }
450 
451 
453 // Store cuts and material information in files under the specified directory.
455  G4bool ascii)
456 {
457  if (!StoreMaterialInfo(dir, ascii)) return false;
458  if (!StoreMaterialCutsCoupleInfo(dir, ascii)) return false;
459  if (!StoreCutsInfo(dir, ascii)) return false;
460 
461 #ifdef G4VERBOSE
462  if (verboseLevel >2) {
463  G4cout << "G4ProductionCutsTable::StoreCutsTable " ;
464  G4cout << " Material/Cuts information have been successfully stored ";
465  if (ascii) {
466  G4cout << " in Ascii mode ";
467  }else{
468  G4cout << " in Binary mode ";
469  }
470  G4cout << " under " << dir << G4endl;
471  }
472 #endif
473  return true;
474 }
475 
478  G4bool ascii)
479 {
480  if (!CheckForRetrieveCutsTable(dir, ascii)) return false;
481  if (!RetrieveCutsInfo(dir, ascii)) return false;
482 #ifdef G4VERBOSE
483  if (verboseLevel >2) {
484  G4cout << "G4ProductionCutsTable::RetrieveCutsTable " ;
485  G4cout << " Material/Cuts information have been successfully retrieved ";
486  if (ascii) {
487  G4cout << " in Ascii mode ";
488  }else{
489  G4cout << " in Binary mode ";
490  }
491  G4cout << " under " << dir << G4endl;
492  }
493 #endif
494  return true;
495 }
496 
498 // check stored material and cut values are consistent
499 // with the current detector setup.
500 //
501 G4bool
503  G4bool ascii)
504 {
505  G4cerr << "G4ProductionCutsTable::CheckForRetrieveCutsTable!!"<< G4endl;
506  // isNeedForRestoreCoupleInfo = false;
507  if (!CheckMaterialInfo(directory, ascii)) return false;
508  if (verboseLevel >2) {
509  G4cerr << "G4ProductionCutsTable::CheckMaterialInfo passed !!"<< G4endl;
510  }
511  if (!CheckMaterialCutsCoupleInfo(directory, ascii)) return false;
512  if (verboseLevel >2) {
513  G4cerr << "G4ProductionCutsTable::CheckMaterialCutsCoupleInfo passed !!"<< G4endl;
514  }
515  return true;
516 }
517 
519 // Store material information in files under the specified directory.
520 //
522  G4bool ascii)
523 {
524  const G4String fileName = directory + "/" + "material.dat";
525  const G4String key = "MATERIAL-V3.0";
526  std::ofstream fOut;
527 
528  // open output file //
529  if (!ascii )
530  fOut.open(fileName,std::ios::out|std::ios::binary);
531  else
532  fOut.open(fileName,std::ios::out);
533 
534 
535  // check if the file has been opened successfully
536  if (!fOut) {
537 #ifdef G4VERBOSE
538  if (verboseLevel>0) {
539  G4cerr << "G4ProductionCutsTable::StoreMaterialInfo ";
540  G4cerr << " Can not open file " << fileName << G4endl;
541  }
542 #endif
543  G4Exception( "G4ProductionCutsTable::StoreMaterialInfo()",
544  "ProcCuts102",
545  JustWarning, "Can not open file ");
546  return false;
547  }
548 
549  const G4MaterialTable* matTable = G4Material::GetMaterialTable();
550  // number of materials in the table
551  G4int numberOfMaterial = matTable->size();
552 
553  if (ascii) {
555  // key word
556  fOut << key << G4endl;
557 
558  // number of materials in the table
559  fOut << numberOfMaterial << G4endl;
560 
561  fOut.setf(std::ios::scientific);
562 
563  // material name and density
564  for (size_t idx=0; static_cast<G4int>(idx)<numberOfMaterial; ++idx){
565  fOut << std::setw(FixedStringLengthForStore)
566  << ((*matTable)[idx])->GetName();
567  fOut << std::setw(FixedStringLengthForStore)
568  << ((*matTable)[idx])->GetDensity()/(g/cm3) << G4endl;
569  }
570 
571  fOut.unsetf(std::ios::scientific);
572 
573  } else {
575  char temp[FixedStringLengthForStore];
576  size_t i;
577 
578  // key word
579  for (i=0; i<FixedStringLengthForStore; ++i){
580  temp[i] = '\0';
581  }
582  for (i=0; i<key.length() && i<FixedStringLengthForStore-1; ++i){
583  temp[i]=key[i];
584  }
585  fOut.write(temp, FixedStringLengthForStore);
586 
587  // number of materials in the table
588  fOut.write( (char*)(&numberOfMaterial), sizeof (G4int));
589 
590  // material name and density
591  for (size_t imat=0; static_cast<G4int>(imat)<numberOfMaterial; ++imat){
592  G4String name = ((*matTable)[imat])->GetName();
593  G4double density = ((*matTable)[imat])->GetDensity();
594  for (i=0; i<FixedStringLengthForStore; ++i) temp[i] = '\0';
595  for (i=0; i<name.length() && i<FixedStringLengthForStore-1; ++i)
596  temp[i]=name[i];
597  fOut.write(temp, FixedStringLengthForStore);
598  fOut.write( (char*)(&density), sizeof (G4double));
599  }
600  }
601 
602  fOut.close();
603  return true;
604 }
605 
607 // check stored material is consistent with the current detector setup.
609  G4bool ascii)
610 {
611  const G4String fileName = directory + "/" + "material.dat";
612  const G4String key = "MATERIAL-V3.0";
613  std::ifstream fIn;
614 
615  // open input file //
616  if (!ascii )
617  fIn.open(fileName,std::ios::in|std::ios::binary);
618  else
619  fIn.open(fileName,std::ios::in);
620 
621  // check if the file has been opened successfully
622  if (!fIn) {
623 #ifdef G4VERBOSE
624  if (verboseLevel >0) {
625  G4cerr << "G4ProductionCutsTable::CheckMaterialInfo ";
626  G4cerr << " Can not open file " << fileName << G4endl;
627  }
628 #endif
629  G4Exception( "G4ProductionCutsTable::CheckMaterialInfo()",
630  "ProcCuts102",
631  JustWarning, "Can not open file ");
632  return false;
633  }
634 
635  char temp[FixedStringLengthForStore];
636 
637  // key word
638  G4String keyword;
639  if (ascii) {
640  fIn >> keyword;
641  } else {
642  fIn.read(temp, FixedStringLengthForStore);
643  keyword = (const char*)(temp);
644  }
645  if (key!=keyword) {
646 #ifdef G4VERBOSE
647  if (verboseLevel >0) {
648  G4cerr << "G4ProductionCutsTable::CheckMaterialInfo ";
649  G4cerr << " Key word in " << fileName << "= " << keyword ;
650  G4cerr <<"( should be "<< key << ")" <<G4endl;
651  }
652 #endif
653  G4Exception( "G4ProductionCutsTable::CheckMaterialInfo()",
654  "ProcCuts103",
655  JustWarning, "Bad Data Format");
656  return false;
657  }
658 
659  // number of materials in the table
660  G4int nmat;
661  if (ascii) {
662  fIn >> nmat;
663  } else {
664  fIn.read( (char*)(&nmat), sizeof (G4int));
665  }
666  if ((nmat<=0) || (nmat >100000)){
667  G4Exception( "G4ProductionCutsTable::CheckMaterialInfo()",
668  "ProcCuts108",JustWarning,
669  "Number of materials is less than zero or too big");
670  return false;
671  }
672 
673  // list of material
674  for (G4int idx=0; idx<nmat ; ++idx){
675  // check eof
676  if(fIn.eof()) {
677 #ifdef G4VERBOSE
678  if (verboseLevel >0) {
679  G4cout << "G4ProductionCutsTable::CheckMaterialInfo ";
680  G4cout << " encountered End of File " ;
681  G4cout << " at " << idx+1 << "th material "<< G4endl;
682  }
683 #endif
684  fIn.close();
685  return false;
686  }
687 
688  // check material name and density
690  double density;
691  if (ascii) {
692  fIn >> name >> density;
693  density *= (g/cm3);
694 
695  } else {
696  fIn.read(name, FixedStringLengthForStore);
697  fIn.read((char*)(&density), sizeof (G4double));
698  }
699  if (fIn.fail()) {
700 #ifdef G4VERBOSE
701  if (verboseLevel >0) {
702  G4cerr << "G4ProductionCutsTable::CheckMaterialInfo ";
703  G4cerr << " Bad data format ";
704  G4cerr << " at " << idx+1 << "th material "<< G4endl;
705  }
706 #endif
707  G4Exception( "G4ProductionCutsTable::CheckMaterialInfo()",
708  "ProcCuts103",
709  JustWarning, "Bad Data Format");
710  fIn.close();
711  return false;
712  }
713 
714  G4Material* aMaterial = G4Material::GetMaterial(name);
715  if (aMaterial == nullptr ) continue;
716 
717  G4double ratio = std::fabs(density/aMaterial->GetDensity() );
718  if ((0.999>ratio) || (ratio>1.001) ){
719 #ifdef G4VERBOSE
720  if (verboseLevel >0) {
721  G4cerr << "G4ProductionCutsTable::CheckMaterialInfo ";
722  G4cerr << " Inconsistent material density" << G4endl;;
723  G4cerr << " at " << idx+1 << "th material "<< G4endl;
724  G4cerr << "Name: " << name << G4endl;
725  G4cerr << "Density:" << std::setiosflags(std::ios::scientific) << density / (g/cm3) ;
726  G4cerr << "(should be " << aMaterial->GetDensity()/(g/cm3)<< ")" << " [g/cm3]"<< G4endl;
727  G4cerr << std::resetiosflags(std::ios::scientific);
728  }
729 #endif
730  G4Exception( "G4ProductionCutsTable::CheckMaterialInfo()",
731  "ProcCuts104",
732  JustWarning, "Inconsitent matrial density");
733  fIn.close();
734  return false;
735  }
736 
737  }
738 
739  fIn.close();
740  return true;
741 
742 }
743 
744 
746 // Store materialCutsCouple information in files under the specified directory.
747 //
748 G4bool
750  G4bool ascii)
751 {
752  const G4String fileName = directory + "/" + "couple.dat";
753  const G4String key = "COUPLE-V3.0";
754  std::ofstream fOut;
755  char temp[FixedStringLengthForStore];
756 
757  // open output file //
758  if (!ascii )
759  fOut.open(fileName,std::ios::out|std::ios::binary);
760  else
761  fOut.open(fileName,std::ios::out);
762 
763 
764  // check if the file has been opened successfully
765  if (!fOut) {
766 #ifdef G4VERBOSE
767  if (verboseLevel >0) {
768  G4cerr << "G4ProductionCutsTable::StoreMaterialCutsCoupleInfo ";
769  G4cerr << " Can not open file " << fileName << G4endl;
770  }
771 #endif
772  G4Exception( "G4ProductionCutsTable::StoreMaterialCutsCoupleInfo()",
773  "ProcCuts102",
774  JustWarning, "Can not open file ");
775  return false;
776  }
777  G4int numberOfCouples = coupleTable.size();
778  if (ascii) {
780  // key word
781  fOut << std::setw(FixedStringLengthForStore) << key << G4endl;
782 
783  // number of couples in the table
784  fOut << numberOfCouples << G4endl;
785  } else {
787  // key word
788  size_t i;
789  for (i=0; i<FixedStringLengthForStore; ++i) temp[i] = '\0';
790  for (i=0; i<key.length() && i<FixedStringLengthForStore-1; ++i)
791  temp[i]=key[i];
792  fOut.write(temp, FixedStringLengthForStore);
793 
794  // number of couples in the table
795  fOut.write( (char*)(&numberOfCouples), sizeof (G4int));
796  }
797 
798 
799  // Loop over all couples
800  CoupleTableIterator cItr;
801  for (cItr=coupleTable.begin();cItr!=coupleTable.end();cItr++){
802  G4MaterialCutsCouple* aCouple = (*cItr);
803  G4int index = aCouple->GetIndex();
804  // cut value
805  G4ProductionCuts* aCut = aCouple->GetProductionCuts();
806  G4double cutValues[NumberOfG4CutIndex];
807  for (size_t idx=0; idx <NumberOfG4CutIndex; idx++) {
808  cutValues[idx] = aCut->GetProductionCut(idx);
809  }
810  // material/region info
811  G4String materialName = aCouple->GetMaterial()->GetName();
812  G4String regionName = "NONE";
813  if (aCouple->IsUsed()){
814  typedef std::vector<G4Region*>::iterator regionIterator;
815  for(regionIterator rItr=fG4RegionStore->begin();
816  rItr!=fG4RegionStore->end();rItr++){
817  if (IsCoupleUsedInTheRegion(aCouple, *rItr) ){
818  regionName = (*rItr)->GetName();
819  break;
820  }
821  }
822  }
823 
824  if (ascii) {
826  // index number
827  fOut << index << G4endl;
828 
829  // material name
830  fOut << std::setw(FixedStringLengthForStore) << materialName<< G4endl;
831 
832  // region name
833  fOut << std::setw(FixedStringLengthForStore) << regionName<< G4endl;
834 
835  fOut.setf(std::ios::scientific);
836  // cut values
837  for (size_t idx=0; idx< NumberOfG4CutIndex; idx++) {
838  fOut << std::setw(FixedStringLengthForStore) << cutValues[idx]/(mm)
839  << G4endl;
840  }
841  fOut.unsetf(std::ios::scientific);
842 
843  } else {
845  // index
846  fOut.write( (char*)(&index), sizeof (G4int));
847 
848  // material name
849  size_t i;
850  for (i=0; i<FixedStringLengthForStore; ++i) temp[i] = '\0';
851  for (i=0; i<materialName.length() && i<FixedStringLengthForStore-1; ++i) {
852  temp[i]=materialName[i];
853  }
854  fOut.write(temp, FixedStringLengthForStore);
855 
856  // region name
857  for (i=0; i<FixedStringLengthForStore; ++i) temp[i] = '\0';
858  for (i=0; i<regionName.length() && i<FixedStringLengthForStore-1; ++i) {
859  temp[i]=regionName[i];
860  }
861  fOut.write(temp, FixedStringLengthForStore);
862 
863  // cut values
864  for (size_t idx=0; idx< NumberOfG4CutIndex; idx++) {
865  fOut.write( (char*)(&(cutValues[idx])), sizeof (G4double));
866  }
867  }
868  }
869 
870  fOut.close();
871  return true;
872 }
873 
874 
876 // check stored materialCutsCouple is consistent
877 // with the current detector setup.
878 //
879 G4bool
881  G4bool ascii )
882 {
883  const G4String fileName = directory + "/" + "couple.dat";
884  const G4String key = "COUPLE-V3.0";
885  std::ifstream fIn;
886 
887  // open input file //
888  if (!ascii )
889  fIn.open(fileName,std::ios::in|std::ios::binary);
890  else
891  fIn.open(fileName,std::ios::in);
892 
893  // check if the file has been opened successfully
894  if (!fIn) {
895 #ifdef G4VERBOSE
896  if (verboseLevel >0) {
897  G4cerr << "G4ProductionCutTable::CheckMaterialCutsCoupleInfo ";
898  G4cerr << " Can not open file " << fileName << G4endl;
899  }
900 #endif
901  G4Exception( "G4ProductionCutsTable::CheckMaterialCutsCoupleInfo()",
902  "ProcCuts102",
903  JustWarning, "Can not open file ");
904  return false;
905  }
906 
907  char temp[FixedStringLengthForStore];
908 
909  // key word
910  G4String keyword;
911  if (ascii) {
912  fIn >> keyword;
913  } else {
914  fIn.read(temp, FixedStringLengthForStore);
915  keyword = (const char*)(temp);
916  }
917  if (key!=keyword) {
918 #ifdef G4VERBOSE
919  if (verboseLevel >0) {
920  G4cerr << "G4ProductionCutTable::CheckMaterialCutsCoupleInfo ";
921  G4cerr << " Key word in " << fileName << "= " << keyword ;
922  G4cerr <<"( should be "<< key << ")" <<G4endl;
923  }
924 #endif
925  G4Exception( "G4ProductionCutsTable::CheckMaterialCutsCoupleInfo()",
926  "ProcCuts103",
927  JustWarning, "Bad Data Format");
928  fIn.close();
929  return false;
930  }
931 
932  // numberOfCouples
933  G4int numberOfCouples;
934  if (ascii) {
935  fIn >> numberOfCouples;
936  } else {
937  fIn.read( (char*)(&numberOfCouples), sizeof (G4int));
938  }
939 
940  // Reset MCCIndexConversionTable
941  mccConversionTable.Reset(numberOfCouples);
942 
943  // Read in couple information
944  for (G4int idx=0; idx<numberOfCouples; idx+=1){
945  // read in index
946  G4int index;
947  if (ascii) {
948  fIn >> index;
949  } else {
950  fIn.read( (char*)(&index), sizeof (G4int));
951  }
952  // read in index material name
953  char mat_name[FixedStringLengthForStore];
954  if (ascii) {
955  fIn >> mat_name;
956  } else {
957  fIn.read(mat_name, FixedStringLengthForStore);
958  }
959  // read in index and region name
960  char region_name[FixedStringLengthForStore];
961  if (ascii) {
962  fIn >> region_name;
963  } else {
964  fIn.read(region_name, FixedStringLengthForStore);
965  }
966  // cut value
967  G4double cutValues[NumberOfG4CutIndex];
968  for (size_t i=0; i< NumberOfG4CutIndex; i++) {
969  if (ascii) {
970  fIn >> cutValues[i];
971  cutValues[i] *= (mm);
972  } else {
973  fIn.read( (char*)(&(cutValues[i])), sizeof (G4double));
974  }
975  }
976 
977  // Loop over all couples
978  CoupleTableIterator cItr;
979  G4bool fOK = false;
980  G4MaterialCutsCouple* aCouple = nullptr;
981  for (cItr=coupleTable.begin();cItr!=coupleTable.end();cItr++){
982  aCouple = (*cItr);
983  // check material name
984  if ( mat_name != aCouple->GetMaterial()->GetName() ) continue;
985  // check cut values
986  G4ProductionCuts* aCut = aCouple->GetProductionCuts();
987  G4bool fRatio = true;
988  for (size_t j=0; j< NumberOfG4CutIndex; j++) {
989  // check ratio only if values are not the same
990  if (cutValues[j] != aCut->GetProductionCut(j)) {
991  G4double ratio = cutValues[j]/aCut->GetProductionCut(j);
992  fRatio = fRatio && (0.999<ratio) && (ratio<1.001) ;
993  }
994  }
995  if (!fRatio) continue;
996  // MCC matched
997  fOK = true;
998  mccConversionTable.SetNewIndex(index, aCouple->GetIndex());
999  break;
1000  }
1001 
1002  if (fOK) {
1003 #ifdef G4VERBOSE
1004  // debug information
1005  if (verboseLevel >1) {
1006  G4String regionname(region_name);
1007  G4Region* fRegion = nullptr;
1008  if ( regionname != "NONE" ) {
1009  fRegion = fG4RegionStore->GetRegion(region_name);
1010  if (fRegion == nullptr) {
1011  G4cout << "G4ProductionCutTable::CheckMaterialCutsCoupleInfo ";
1012  G4cout << "Region " << regionname << " is not found ";
1013  G4cout << index << ": in " << fileName << G4endl;
1014  }
1015  }
1016  if ( ( (regionname == "NONE") && (aCouple->IsUsed()) ) ||
1017  ( (fRegion != nullptr) && !IsCoupleUsedInTheRegion(aCouple, fRegion) ) ) {
1018  G4cout << "G4ProductionCutTable::CheckMaterialCutsCoupleInfo ";
1019  G4cout << "A Couple is used differnt region in the current setup ";
1020  G4cout << index << ": in " << fileName << G4endl;
1021  G4cout << " material: " << mat_name ;
1022  G4cout << " region: " << region_name << G4endl;
1023  for (size_t ii=0; ii< NumberOfG4CutIndex; ii++) {
1024  G4cout << "cut[" << ii << "]=" << cutValues[ii]/mm;
1025  G4cout << " mm : ";
1026  }
1027  G4cout << G4endl;
1028  } else if ( index != aCouple->GetIndex() ) {
1029  G4cout << "G4ProductionCutTable::CheckMaterialCutsCoupleInfo ";
1030  G4cout << "Index of couples was modified "<< G4endl;
1031  G4cout << aCouple->GetIndex() << ":" <<aCouple->GetMaterial()->GetName();
1032  G4cout <<" is defined as " ;
1033  G4cout << index << ":" << mat_name << " in " << fileName << G4endl;
1034  } else {
1035  G4cout << "G4ProductionCutTable::CheckMaterialCutsCoupleInfo ";
1036  G4cout << index << ":" << mat_name << " in " << fileName ;
1037  G4cout << " is consistent with current setup" << G4endl;
1038  }
1039  }
1040 #endif
1041  } else {
1042 #ifdef G4VERBOSE
1043  if (verboseLevel >0) {
1044  G4cout << "G4ProductionCutTable::CheckMaterialCutsCoupleInfo ";
1045  G4cout << "Couples is not defined in the current detector setup ";
1046  G4cout << index << ": in " << fileName << G4endl;
1047  G4cout << " material: " << mat_name ;
1048  G4cout << " region: " << region_name << G4endl;
1049  for (size_t ii=0; ii< NumberOfG4CutIndex; ii++) {
1050  G4cout << "cut[" << ii << "]=" << cutValues[ii]/mm;
1051  G4cout << " mm : ";
1052  }
1053  G4cout << G4endl;
1054  }
1055 #endif
1056  }
1057 
1058  }
1059  fIn.close();
1060  return true;
1061 }
1062 
1063 
1065 // Store cut values information in files under the specified directory.
1066 //
1068  G4bool ascii)
1069 {
1070  const G4String fileName = directory + "/" + "cut.dat";
1071  const G4String key = "CUT-V3.0";
1072  std::ofstream fOut;
1073  char temp[FixedStringLengthForStore];
1074 
1075  // open output file //
1076  if (!ascii )
1077  fOut.open(fileName,std::ios::out|std::ios::binary);
1078  else
1079  fOut.open(fileName,std::ios::out);
1080 
1081 
1082  // check if the file has been opened successfully
1083  if (!fOut) {
1084  if(verboseLevel>0) {
1085  G4cerr << "G4ProductionCutsTable::StoreCutsInfo ";
1086  G4cerr << " Can not open file " << fileName << G4endl;
1087  }
1088  G4Exception( "G4ProductionCutsTable::StoreCutsInfo()",
1089  "ProcCuts102",
1090  JustWarning, "Can not open file");
1091  return false;
1092  }
1093 
1094  G4int numberOfCouples = coupleTable.size();
1095  if (ascii) {
1097  // key word
1098  fOut << key << G4endl;
1099 
1100  // number of couples in the table
1101  fOut << numberOfCouples << G4endl;
1102  } else {
1104  // key word
1105  size_t i;
1106  for (i=0; i<FixedStringLengthForStore; ++i) temp[i] = '\0';
1107  for (i=0; i<key.length() && i<FixedStringLengthForStore-1; ++i)
1108  temp[i]=key[i];
1109  fOut.write(temp, FixedStringLengthForStore);
1110 
1111  // number of couples in the table
1112  fOut.write( (char*)(&numberOfCouples), sizeof (G4int));
1113  }
1114 
1115 
1116  for (size_t idx=0; idx <NumberOfG4CutIndex; idx++) {
1117  const std::vector<G4double>* fRange = GetRangeCutsVector(idx);
1118  const std::vector<G4double>* fEnergy = GetEnergyCutsVector(idx);
1119  size_t i=0;
1120  // Loop over all couples
1121  CoupleTableIterator cItr;
1122  for (cItr=coupleTable.begin();cItr!=coupleTable.end();cItr++, i++){
1123  if (ascii) {
1125  fOut.setf(std::ios::scientific);
1126  fOut << std::setw(20) << (*fRange)[i]/mm ;
1127  fOut << std::setw(20) << (*fEnergy)[i]/keV << G4endl;
1128  fOut.unsetf(std::ios::scientific);
1129  } else {
1131  G4double cut = (*fRange)[i];
1132  fOut.write((char*)(&cut), sizeof (G4double));
1133  cut = (*fEnergy)[i];
1134  fOut.write((char*)(&cut), sizeof (G4double));
1135  }
1136  }
1137  }
1138  fOut.close();
1139  return true;
1140 }
1141 
1143 // Retrieve cut values information in files under the specified directory.
1144 //
1146  G4bool ascii)
1147 {
1148  const G4String fileName = directory + "/" + "cut.dat";
1149  const G4String key = "CUT-V3.0";
1150  std::ifstream fIn;
1151 
1152  // open input file //
1153  if (!ascii )
1154  fIn.open(fileName,std::ios::in|std::ios::binary);
1155  else
1156  fIn.open(fileName,std::ios::in);
1157 
1158  // check if the file has been opened successfully
1159  if (!fIn) {
1160  if (verboseLevel >0) {
1161  G4cerr << "G4ProductionCutTable::RetrieveCutsInfo ";
1162  G4cerr << " Can not open file " << fileName << G4endl;
1163  }
1164  G4Exception( "G4ProductionCutsTable::RetrieveCutsInfo()",
1165  "ProcCuts102",
1166  JustWarning, "Can not open file");
1167  return false;
1168  }
1169 
1170  char temp[FixedStringLengthForStore];
1171 
1172  // key word
1173  G4String keyword;
1174  if (ascii) {
1175  fIn >> keyword;
1176  } else {
1177  fIn.read(temp, FixedStringLengthForStore);
1178  keyword = (const char*)(temp);
1179  }
1180  if (key!=keyword) {
1181  if (verboseLevel >0) {
1182  G4cerr << "G4ProductionCutTable::RetrieveCutsInfo ";
1183  G4cerr << " Key word in " << fileName << "= " << keyword ;
1184  G4cerr <<"( should be "<< key << ")" <<G4endl;
1185  }
1186  G4Exception( "G4ProductionCutsTable::RetrieveCutsInfo()",
1187  "ProcCuts103",
1188  JustWarning, "Bad Data Format");
1189  return false;
1190  }
1191 
1192  // numberOfCouples
1193  G4int numberOfCouples;
1194  if (ascii) {
1195  fIn >> numberOfCouples;
1196  if (fIn.fail()) {
1197  G4Exception( "G4ProductionCutsTable::RetrieveCutsInfo()",
1198  "ProcCuts103",
1199  JustWarning, "Bad Data Format");
1200  return false;
1201  }
1202  } else {
1203  fIn.read( (char*)(&numberOfCouples), sizeof (G4int));
1204  }
1205 
1206  if (numberOfCouples > static_cast<G4int>(mccConversionTable.size()) ){
1207  G4Exception( "G4ProductionCutsTable::RetrieveCutsInfo()",
1208  "ProcCuts109", JustWarning,
1209  "Number of Couples in the file exceeds defined couples ");
1210  }
1211  numberOfCouples = mccConversionTable.size();
1212 
1213  for (size_t idx=0; static_cast<G4int>(idx) <NumberOfG4CutIndex; idx++) {
1216  fRange->clear();
1217  fEnergy->clear();
1218 
1219  // Loop over all couples
1220  for (size_t i=0; static_cast<G4int>(i)< numberOfCouples; i++){
1221  G4double rcut, ecut;
1222  if (ascii) {
1223  fIn >> rcut >> ecut;
1224  if (fIn.fail()) {
1225  G4Exception( "G4ProductionCutsTable::RetrieveCutsInfo()",
1226  "ProcCuts103",
1227  JustWarning, "Bad Data Format");
1228  return false;
1229  }
1230  rcut *= mm;
1231  ecut *= keV;
1232  } else {
1233  fIn.read((char*)(&rcut), sizeof (G4double));
1234  fIn.read((char*)(&ecut), sizeof (G4double));
1235  }
1236  if (!mccConversionTable.IsUsed(i)) continue;
1237  size_t new_index = mccConversionTable.GetIndex(i);
1238  (*fRange)[new_index] = rcut;
1239  (*fEnergy)[new_index] = ecut;
1240  }
1241  }
1242  return true;
1243 }
1244 
1246 // Set Verbose Level
1247 // set same verbosity to all registered RangeToEnergyConverters
1249 {
1250  verboseLevel = value;
1251  for (int ip=0; ip< NumberOfG4CutIndex; ip++) {
1252  if (converters[ip] !=0 ){
1253  converters[ip]->SetVerboseLevel(value);
1254  }
1255  }
1256 }
1257 
1260 {
1262 }
1263 
1264 
1267 {
1269 }