27#include <G4LogicalVolumeStore.hh>
28#include <G4ProductionCuts.hh>
29#include <G4RToEConvForElectron.hh>
30#include <G4RToEConvForGamma.hh>
32#include <G4RegionStore.hh>
33#include <G4RunManager.hh>
34#include <G4SystemOfUnits.hh>
35#include <G4UnitsTable.hh>
36#include <G4VUserPhysicsList.hh>
37#include <G4Version.hh>
54 G4double& higherCut, G4double defaultRangeCut, G4double lowEdgeEnergy,
55 G4double highEdgeEnergy, G4int nbin,
56 std::map<G4double, G4double>& energyToRangeMap,
57 std::map<G4double, G4double>::const_iterator& it, G4Material* material,
58 G4VRangeToEnergyConverter& converter)
const
62 G4double step = (higherCut - lowerCut) / nbin;
63 energyToRangeMap.clear();
65 for (G4int i = 0; i <= nbin; i++) {
66 G4double rangeCut = lowerCut + i * step;
67 if (rangeCut < defaultRangeCut)
continue;
68 G4double energy = converter.Convert(rangeCut, material);
70 G4cout << indent <<
"For range: " << rangeCut <<
" mm got energy "
71 << energy / MeV <<
" MeV" << G4endl;
74 if (energy < lowEdgeEnergy) energy = lowEdgeEnergy;
75 if (energy > highEdgeEnergy) energy = highEdgeEnergy;
77 energyToRangeMap.insert(
78 std::pair<G4double, G4double>(energy / MeV, rangeCut));
82 it = energyToRangeMap.lower_bound(energyCut);
84 if (it == energyToRangeMap.end()) {
86 G4cout << indent <<
"Range not found " << G4endl;
92 G4cout << indent <<
"Found range limit: " << it->second <<
" mm"
100std::pair<G4double,G4double>
102 G4Material* material, G4VRangeToEnergyConverter& converter,
103 G4double defaultRangeCut)
const
108 G4double lowEdgeEnergy = converter.GetLowEdgeEnergy();
109 G4double highEdgeEnergy = converter.GetHighEdgeEnergy();
112 std::map<G4double, G4double> energyToRangeMap;
113 G4double energy = converter.Convert(defaultRangeCut, material);
114 if (energy < lowEdgeEnergy) energy = lowEdgeEnergy;
115 if (energy > highEdgeEnergy) energy = highEdgeEnergy;
116 energyToRangeMap.insert(
117 std::pair<G4double, G4double>(energy / MeV, defaultRangeCut));
122 G4String indent(
" ");
124 G4double rangeCut = pow(10., i);
125 if (rangeCut < defaultRangeCut)
continue;
126 energy = converter.Convert(rangeCut, material);
128 G4cout << indent <<
"For range: " << std::setw(5) << rangeCut
129 <<
" mm got energy " << energy / MeV <<
" MeV" << G4endl;
132 if (energy < lowEdgeEnergy) energy = lowEdgeEnergy;
133 if (energy > highEdgeEnergy) energy = highEdgeEnergy;
134 energyToRangeMap.insert(
135 std::pair<G4double, G4double>(energy / MeV, rangeCut));
140 if (energyToRangeMap.rbegin()->first < energyCut) {
142 G4cout << indent <<
"Outside range, return the highest value " << G4endl;
144 return *(energyToRangeMap.rbegin());
149 std::map<G4double, G4double>::const_iterator it =
150 energyToRangeMap.lower_bound(energyCut);
152 if (it == energyToRangeMap.end()) {
154 G4cout << indent <<
"Range not found " << G4endl;
160 G4cout << indent <<
"Found range limit: " << it->second <<
" mm" << G4endl;
167 if (iteration == 0) --nbin;
169 auto higherCutIt = it;
170 auto higherCut = it->second;
172 if (it == energyToRangeMap.begin())
return *higherCutIt;
175 auto lowerCutIt = it;
176 auto lowerCut = it->second;
179 Iterate(energyCut, lowerCut, higherCut, defaultRangeCut, lowEdgeEnergy,
180 highEdgeEnergy, nbin, energyToRangeMap, it, material, converter);
185 if (it == energyToRangeMap.begin())
return *higherCutIt;
196 if (it == energyToRangeMap.begin())
return *it;
203std::pair<G4double,G4double>
205 G4Material* material, G4VRangeToEnergyConverter& converter,
206 G4double defaultRangeCut)
const
211 if (energyCut == DBL_MAX) {
213 G4cout <<
" " << converter.GetParticleType()->GetParticleName()
214 <<
" energy cut not defined, keeping default range" << G4endl;
216 return {converter.GetLowEdgeEnergy(), defaultRangeCut};
220 G4cout <<
" " << converter.GetParticleType()->GetParticleName()
221 <<
": energy cut = " << energyCut <<
" MeV" << G4endl;
227 auto [rangeCut, energyCut] =
228 (converter.GetParticleType() == G4Gamma::Definition()) ?
233 G4cout <<
" " << converter.GetParticleType()->GetParticleName()
234 <<
" loaded range, cut values: "
235 << rangeCut <<
", " << energyCut << G4endl;
237 return {energyCut, rangeCut};
241 G4cout <<
" " << converter.GetParticleType()->GetParticleName()
242 <<
" rangeCut not found, keeping default range" << G4endl;
244 return {converter.GetLowEdgeEnergy(), defaultRangeCut};
248 auto [calcEnergyCut, rangeCut] =
253 G4cout <<
" " << converter.GetParticleType()->GetParticleName()
254 <<
" rangeCut not found, keeping default range" << G4endl;
256 return {converter.GetLowEdgeEnergy(), defaultRangeCut};
259 if (rangeCut < defaultRangeCut) {
261 G4cout <<
" " << converter.GetParticleType()->GetParticleName()
262 <<
" rangeCut found " << rangeCut <<
" mm "
263 <<
" is below default value, it will be ignored" << G4endl;
265 return {converter.GetLowEdgeEnergy(), defaultRangeCut};
268 return {calcEnergyCut, rangeCut};
278 G4cout <<
".. Checking energyCuts approximation, tolerance: "
286 auto vmcIdx = idx + 2;
289 if (fabs(values[idx] - values[vmcIdx]) >
292 G4cout << std::setw(25) << std::left << regionName <<
" " << cutType
293 <<
" cut from range = " << std::scientific << values[idx] / MeV
294 <<
" from limits = " << std::scientific<< values[vmcIdx] / MeV
295 <<
" MeV" <<
" delta: "
296 << fabs(values[idx] - values[vmcIdx]) / values[vmcIdx] * 100.
304 G4cout <<
".. Cuts from ranges in regions are consistent with energy cuts."
305 << G4endl <<
" (precision fgkEnergyTolerance)" << G4endl;
308 G4cout <<
".. Found " << counter
309 <<
" inconsistencies between cut from ranges energy cuts." << G4endl;
320 G4cout <<
"No regions data in the map." << G4endl;
347 G4cout <<
"Converting VMC cuts in regions" << G4endl;
355#if (G4VERSION_NUMBER == 1100 || G4VERSION_NUMBER == 1101 )
357 auto g4ConverterElePtr =
new G4RToEConvForElectron();
358 auto g4ConverterGamPtr =
new G4RToEConvForGamma();
359 auto& g4ConverterEle = *g4ConverterElePtr;
360 auto& g4ConverterGam = *g4ConverterGamPtr;
362 G4RToEConvForElectron g4ConverterEle;
363 G4RToEConvForGamma g4ConverterGam;
367 G4double defaultRangeCutEle =
370 G4double defaultRangeCutPositron =
372 G4double defaultRangeCutProton =
377 G4ProductionCuts* dcuts =
new G4ProductionCuts();
378 dcuts->SetProductionCut(defaultRangeCutGam, 0);
379 dcuts->SetProductionCut(defaultRangeCutEle, 1);
380 dcuts->SetProductionCut(defaultRangeCutPositron, 2);
381 dcuts->SetProductionCut(defaultRangeCutProton, 3);
382 defaultRegion->SetProductionCuts(dcuts);
385 G4LogicalVolume* worldLV =
387 G4Region* worldRegion = worldLV->GetRegion();
393 G4cout <<
"Global cut values: "
394 <<
" CUTELE = " << cutEleGlobal <<
" MeV"
395 <<
" CUTGAM = " << cutGamGlobal <<
" MeV" << G4endl;
399 std::set<G4Material*> processedMaterials;
400 std::set<G4Material*> processedMaterials2;
405 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
407 for (G4int i = 0; i < G4int(lvStore->size()); i++) {
409 G4LogicalVolume* lv = (*lvStore)[i];
410 G4bool isWorld = (lv == worldLV);
414 if (!medium)
continue;
418 G4cout <<
"-- Volume = " << i <<
" " << lv <<
" " << lv->GetName()
419 <<
" material = " << material->GetName() << G4endl;
423 G4String regionName = material->GetName();
425 G4RegionStore::GetInstance()->GetRegion(regionName,
false);
426 if (region && !isWorld) {
429 <<
"adding volume in region = " << regionName << G4endl;
431 if (lv->GetRegion() != region) region->AddRootLogicalVolume(lv);
433 if (processedMaterials2.find(material) != processedMaterials2.end()) {
436 <<
"skipping cuts evaluation in region = " << regionName << G4endl;
447 if (processedMaterials.find(material) != processedMaterials.end() &&
451 <<
"adding volume in the default region" << G4endl;
453 defaultRegion->AddRootLogicalVolume(lv);
463 auto [calcCutEle, rangeEle] =
464 GetRangeCut(cutEle, material, g4ConverterEle, defaultRangeCutEle);
465 auto [calcCutGam, rangeGam] =
466 GetRangeCut(cutGam, material, g4ConverterGam, defaultRangeCutGam);
468 G4cout <<
".. converted in e- rangeCut = " << rangeEle <<
" mm "
469 <<
"gamma rangeCut = " << rangeGam <<
" mm" << G4endl;
472 if (fabs(rangeEle - defaultRangeCutEle) < 1e-03 &&
473 fabs(rangeGam - defaultRangeCutGam) < 1e-03 && !region) {
480 <<
"adding volume in the default region" << G4endl;
482 defaultRegion->AddRootLogicalVolume(lv);
486 processedMaterials.insert(material);
490 G4ProductionCuts* cuts =
new G4ProductionCuts();
493 cuts->SetProductionCut(rangeGam, 0);
496 cuts->SetProductionCut(defaultRangeCutGam, 0);
500 cuts->SetProductionCut(rangeEle, 1);
503 cuts->SetProductionCut(defaultRangeCutEle, 1);
507 cuts->SetProductionCut(rangeEle, 2);
510 cuts->SetProductionCut(defaultRangeCutPositron, 2);
514 cuts->SetProductionCut(rangeEle, 3);
517 cuts->SetProductionCut(defaultRangeCutProton, 2);
523 {rangeGam, rangeEle, calcCutGam, calcCutEle, cutGam, cutEle};
528 worldRegion->SetProductionCuts(cuts);
529 worldRegion->RegionModified(
true);
532 <<
"setting new production cuts to the world region" << G4endl;
539 if (region ==
nullptr) {
540 region =
new G4Region(regionName);
546 <<
"adding volume in " << which <<
"region " << regionName << G4endl;
549 region->SetProductionCuts(cuts);
550 region->AddRootLogicalVolume(lv);
553 processedMaterials2.insert(material);
557 processedMaterials.clear();
558 processedMaterials.clear();
561 G4cout <<
"Number of added regions: " << counter << G4endl;
571 G4cout <<
"going to print/write from G4 Table" << G4endl;
574 G4cout <<
"going to print/write from map" << G4endl;
598 input.open(fileName, std::ios::in);
600 if (! input.is_open()) {
602 "Open input file " + TString(fileName.data()) +
" has failed.");
608 G4cout <<
"Loading regions from file: " << fileName << G4endl;
612 GetLogicalVolume()->GetMaterial()->GetName();
620 std::getline(input, skipLine);
623 while (! input.eof()) {
624 std::getline(input, regionName,
';');
625 for (
auto& value : regionValues) {
630 auto startPos = regionName.find(
'\'') + 1;
631 auto length = regionName.find_last_of(
'\'') - startPos;
632 regionName = regionName.substr(startPos, length);
634 G4cout <<
"Loading " << regionName << G4endl;
650 if (regionName == worldMaterialName) {
652 G4cout <<
"Skipping " << regionName <<
" already in map." << G4endl;
658 "Duplicated region data: " + TString(regionName.data()) +
659 " will be skipped !!!.");
662 auto valuesInMap = it->second;
663 G4cout <<
" Already in map !!!" << G4endl <<
" data in map: ";
665 G4cout <<
" loaded data: ";
674 G4cout <<
"Loaded " << counter <<
" regions from file: " << fileName << G4endl;
684 G4LogicalVolume* lv =
689 G4Region* region = lv->GetRegion();
692 "Region for volume " + TString(volName) +
"not found.");
696 G4ProductionCuts* cuts = region->GetProductionCuts();
700 G4cout <<
" Region name: " << region->GetName() << G4endl;
701 G4cout <<
" Material : " << lv->GetMaterial()->GetName() << G4endl;
702 G4cout <<
" Range cuts : "
703 <<
" gamma " << G4BestUnit(cuts->GetProductionCut(
"gamma"),
"Length")
704 <<
" e- " << G4BestUnit(cuts->GetProductionCut(
"e-"),
"Length")
705 <<
" e+ " << G4BestUnit(cuts->GetProductionCut(
"e+"),
"Length")
706 <<
" proton " << G4BestUnit(cuts->GetProductionCut(
"proton"),
"Length")
710 G4cout <<
" Energy thresholds : ";
712 G4ProductionCutsTable* productionCutsTable =
713 G4ProductionCutsTable::GetProductionCutsTable();
715 const G4MaterialCutsCouple* couple =
716 productionCutsTable->GetMaterialCutsCouple(lv->GetMaterial(), cuts);
719 G4cout <<
" not ready to print" << G4endl;
723 const std::vector<G4double>* energyCutsGam =
724 productionCutsTable->GetEnergyCutsVector(0);
725 const std::vector<G4double>* energyCutsEle =
726 productionCutsTable->GetEnergyCutsVector(1);
727 const std::vector<G4double>* energyCutsPos =
728 productionCutsTable->GetEnergyCutsVector(2);
729 const std::vector<G4double>* energyCutsPro =
730 productionCutsTable->GetEnergyCutsVector(3);
732 G4double cutGam = (*energyCutsGam)[couple->GetIndex()];
733 G4double cutEle = (*energyCutsEle)[couple->GetIndex()];
734 G4double cutPos = (*energyCutsPos)[couple->GetIndex()];
735 G4double cutPro = (*energyCutsPro)[couple->GetIndex()];
737 G4cout <<
" gamma " << G4BestUnit(cutGam,
"Energy") <<
" e- "
738 << G4BestUnit(cutEle,
"Energy") <<
" e+ "
739 << G4BestUnit(cutPos,
"Energy") <<
" proton "
740 << G4BestUnit(cutPro,
"Energy");
743 G4RegionStore* regionStore = G4RegionStore::GetInstance();
744 if (couple->IsUsed()) {
745 G4cout <<
" Region(s) which use this couple : ";
746 std::vector<G4Region*>::iterator it;
747 for (it = regionStore->begin(); it != regionStore->end(); it++) {
749 G4cout <<
" " << (*it)->GetName();
765 "\"Save\" option is active. The input file " +
fFileName +
766 " will be overwritten.");
Definition of the TG4G3CutVector class.
Definition of the TG4G3PhysicsManager class.
Definition of the TG4G3Units class.
Definition of the TG4GeometryServices class.
Definition of the TG4Globals class and basic container types.
Definition of the TG4Limits class.
Definition of the TG4Medium class.
Definition of the TG4PhysicsManager class.
Definition of the TG4RegionsManager class.
Definition of the TG4RegionsMessenger class.
G4VPhysicalVolume * GetWorld() const
G4LogicalVolume * FindLogicalVolume(const G4String &name, G4bool silent=false) const
static TG4GeometryServices * Instance()
TG4MediumMap * GetMediumMap() const
static void Warning(const TString &className, const TString &methodName, const TString &text)
Extended G4UserLimits class.
TG4Medium * GetMedium(G4int mediumID, G4bool warn=true) const
Helper class to keep medium data.
G4Material * GetMaterial() const
G4double GetCutForPositron() const
G4double GetCutForProton() const
static TG4PhysicsManager * Instance()
G4double GetCutForElectron() const
G4double GetCutForGamma() const
void PrintFromMap(std::ostream &output) const
std::pair< G4double, G4double > ConvertEnergyToRange(G4double energyCut, G4Material *material, G4VRangeToEnergyConverter &converter, G4double defaultRangeValue) const
G4int fRangePrecision
the precision for calculating ranges
void DefineRegions() override
void CheckRegionsRanges() const
void SetLoad(G4bool isLoad)
G4double fEnergyTolerance
the tolerance (relative) for comparing energy cut values
std::array< G4double, fgkValuesSize > TG4RegionData
void CheckRegions() const override
G4bool fIsLoad
option to load regions ranges from a file
static constexpr G4int fgkMinRangeOrder
the minimum range order
std::pair< G4double, G4double > GetRangeCut(G4double energyCut, G4Material *material, G4VRangeToEnergyConverter &converter, G4double defaultRangeValue) const
void DumpRegion(const G4String &volName) const
void PrintRegions(std::ostream &output) const override
static constexpr G4int fgkMaxRangeOrder
the maximum range order
std::map< G4String, TG4RegionData > fRegionData
map for computed or loaded regions data
G4bool Iterate(G4double energyCut, G4double &lowerCut, G4double &higherCut, G4double defaultRangeCut, G4double lowEdgeEnergy, G4double highEdgeEnergy, G4int nbin, std::map< G4double, G4double > &map, std::map< G4double, G4double >::const_iterator &it, G4Material *material, G4VRangeToEnergyConverter &converter) const
G4bool fIsG4Table
option to print or save regions from G4 production cuts table
static constexpr G4int fgkNofBins
the number of bins for search range iteration
static constexpr size_t fgkRangeGamIdx
G4bool fApplyForElectron
option to apply cuts for e- (default is true)
G4bool fIsSave
option to save all regions in a file
G4bool fApplyForPositron
option to apply cuts for e+ (default is true)
void PrintLegend(std::ostream &output) const
void PrintRegionData(std::ostream &output, const G4String &matName, const TG4RegionData &values) const
static const G4String fgkDefaultRegionName
the name of the region with default cuts
static const G4String fgkDefaultFileName
the name of the region with default cuts
static constexpr size_t fgkCutGamIdx
G4double GetEnergyCut(TG4Limits *limits, TG4G3Cut cutType, G4double globalCutValue) const
G4bool IsCoupleUsedInTheRegion(const G4MaterialCutsCouple *couple, const G4Region *region) const
G4bool fApplyForGamma
option to apply cuts for gamma (default is true)
static constexpr size_t fgkCutEleIdx
static constexpr size_t fgkVmcCutGamIdx
void PrintFromG4Table(std::ostream &output) const
void CheckRegionsInGeometry() const
G4bool fApplyForProton
option to apply cuts for proton (default is true)
G4double GetGlobalEnergyCut(TG4G3Cut cutType) const
static constexpr size_t fgkRangeEleIdx
G4String fFileName
file name for regions output
static constexpr size_t fgkVmcCutEleIdx
virtual G4int VerboseLevel() const