CMS 3D CMS Logo

DDG4ProductionCuts.cc
Go to the documentation of this file.
3 
6 
7 #include <DD4hep/Filter.h>
8 #include <DD4hep/SpecParRegistry.h>
9 
10 #include "G4ProductionCuts.hh"
11 #include "G4RegionStore.hh"
12 #include "G4Region.hh"
13 #include "G4LogicalVolume.hh"
14 #include "G4LogicalVolumeStore.hh"
15 
16 #include <algorithm>
17 
18 namespace {
24  bool dd_is_greater(const std::pair<G4LogicalVolume*, DDLogicalPart>& p1,
25  const std::pair<G4LogicalVolume*, DDLogicalPart>& p2) {
26  bool result = false;
27  if (p1.second.name().ns() > p2.second.name().ns()) {
28  result = true;
29  }
30  if (p1.second.name().ns() == p2.second.name().ns()) {
31  if (p1.second.name().name() > p2.second.name().name()) {
32  result = true;
33  }
34  if (p1.second.name().name() == p2.second.name().name()) {
35  if (p1.first->GetName() > p2.first->GetName()) {
36  result = true;
37  }
38  }
39  }
40  return result;
41  }
42 
43  bool sortByName(const std::pair<G4LogicalVolume*, const dd4hep::SpecPar*>& p1,
44  const std::pair<G4LogicalVolume*, const dd4hep::SpecPar*>& p2) {
45  bool result = false;
46  if (p1.first->GetName() > p2.first->GetName()) {
47  result = true;
48  }
49  return result;
50  }
51 } // namespace
52 
54  : map_(map), keywordRegion_("CMSCutsRegion"), verbosity_(verb), protonCut_(pcut) {
55  initialize();
56 }
57 
58 DDG4ProductionCuts::DDG4ProductionCuts(const dd4hep::SpecParRegistry* specPars,
59  const dd4hep::sim::Geant4GeometryMaps::VolumeMap* map,
60  int verb,
61  bool pcut)
62  : dd4hepMap_(map), specPars_(specPars), keywordRegion_("CMSCutsRegion"), verbosity_(verb), protonCut_(pcut) {
64 }
65 
68  // sort all root volumes - to get the same sequence at every run of the application.
69  // (otherwise, the sequence will depend on the pointer (memory address) of the
70  // involved objects, because 'new' does no guarantee that you allways get a
71  // higher (or lower) address when allocating an object of the same type ...
72  sort(vec_.begin(), vec_.end(), &dd_is_greater);
73  if (verbosity_ > 0) {
74  edm::LogVerbatim("Geometry") << " DDG4ProductionCuts : got " << vec_.size() << " region roots.\n"
75  << " DDG4ProductionCuts : List of all roots:";
76  for (auto const& vv : vec_)
77  edm::LogVerbatim("Geometry") << " " << vv.first->GetName() << " : " << vv.second.name();
78  }
79 
80  // Now generate all the regions
81  std::string curName = "";
82  std::string regionName = "";
83  G4Region* region = nullptr;
84  G4RegionStore* store = G4RegionStore::GetInstance();
85  for (auto const& vv : vec_) {
86  unsigned int num = map_->toString(keywordRegion_, vv.second, regionName);
87  edm::LogVerbatim("Geometry") << " num " << num << " regionName: " << regionName << ", the store of size "
88  << store->size();
89  if (num != 1) {
90  throw cms::Exception("SimG4CoreGeometry", " DDG4ProductionCuts::initialize: Problem with Region tags.");
91  return;
92  }
93  if (regionName != curName) {
94  edm::LogVerbatim("Geometry") << "DDG4ProductionCuts : regionName " << regionName << ", the store of size "
95  << store->size();
96  region = store->FindOrCreateRegion(regionName);
97  edm::LogVerbatim("Geometry") << "DDG4ProductionCuts : region " << region->GetName();
98  if (nullptr == region) {
99  throw cms::Exception("SimG4CoreGeometry", " DDG4ProductionCuts::initialize: Problem with Region tags.");
100  return;
101  }
102  curName = regionName;
103  edm::LogVerbatim("Geometry") << "DDG4ProductionCuts : new G4Region " << vv.first->GetName();
104  setProdCuts(vv.second, region);
105  }
106  if (nullptr != region) {
107  region->AddRootLogicalVolume(vv.first);
108  if (verbosity_ > 0)
109  edm::LogVerbatim("Geometry") << " added " << vv.first->GetName() << " to region " << region->GetName();
110  }
111  }
112 }
113 
115  dd4hep::SpecParRefs specs;
116  specPars_->filter(specs, keywordRegion_);
117 
118  // LOOP ON ALL LOGICAL VOLUMES
119  for (auto const& it : *dd4hepMap_) {
120  bool foundMatch = false; // Same behavior as in DDD: when matching SpecPar is found, stop search!
121  // SEARCH ON ALL SPECPARS
122  for (auto const& fit : specs) {
123  for (auto const& pit : fit.second->paths) {
124  const std::string_view selection = dd4hep::dd::noNamespace(dd4hep::dd::realTopName(pit));
125  const std::string_view name = dd4hep::dd::noNamespace(it.first.name());
126  if (!(dd4hep::dd::isRegex(selection))
127  ? dd4hep::dd::compareEqual(name, selection)
128  : std::regex_match(name.begin(), name.end(), std::regex(selection.begin(), selection.end()))) {
129  dd4hepVec_.emplace_back(std::make_pair<G4LogicalVolume*, const dd4hep::SpecPar*>(&*it.second, &*fit.second));
130  foundMatch = true;
131  break;
132  }
133  }
134  if (foundMatch)
135  break;
136  } // Search on all SpecPars
137  } // Loop on all logical volumes
138 
139  // sort all root volumes - to get the same sequence at every run of the application.
140  sort(begin(dd4hepVec_), end(dd4hepVec_), &sortByName);
141 
142  // Now generate all the regions
143  for (auto const& it : dd4hepVec_) {
144  auto regName = it.second->strValue(keywordRegion_);
145  G4Region* region = G4RegionStore::GetInstance()->FindOrCreateRegion({regName.data(), regName.size()});
146 
147  region->AddRootLogicalVolume(it.first);
148  edm::LogVerbatim("Geometry") << it.first->GetName() << ": " << regName;
149  edm::LogVerbatim("Geometry") << " MakeRegions: added " << it.first->GetName() << " to region " << region->GetName();
150 
151  // Also treat reflected volumes
152  const G4String& nonReflectedG4Name = it.first->GetName();
153  const G4String& reflectedG4Name = nonReflectedG4Name + "_refl";
154  const G4LogicalVolumeStore* const allG4LogicalVolumes = G4LogicalVolumeStore::GetInstance();
155  const auto reflectedG4LogicalVolumeIt = std::find_if(
156  allG4LogicalVolumes->begin(), allG4LogicalVolumes->end(), [&](const G4LogicalVolume* const aG4LogicalVolume) {
157  return (aG4LogicalVolume->GetName() == reflectedG4Name);
158  });
159  // If G4 Logical volume has a reflected volume, add it to the region as well.
160  if (reflectedG4LogicalVolumeIt != allG4LogicalVolumes->end()) {
161  region->AddRootLogicalVolume(*reflectedG4LogicalVolumeIt);
162  edm::LogVerbatim("Geometry") << " MakeRegions: added " << (*reflectedG4LogicalVolumeIt)->GetName()
163  << " to region " << region->GetName();
164  }
165 
166  edm::LogVerbatim("Geometry").log([&](auto& log) {
167  for (auto const& sit : it.second->spars) {
168  log << sit.first << " = " << sit.second[0] << "\n";
169  }
170  });
171  setProdCuts(it.second, region);
172  }
173 
174  if (verbosity_ > 0) {
175  edm::LogVerbatim("SimG4CoreGeometry") << " DDG4ProductionCuts (New) : starting\n"
176  << " DDG4ProductionCuts : Got " << dd4hepVec_.size() << " region roots.\n"
177  << " DDG4ProductionCuts : List of all roots:";
178  for (size_t jj = 0; jj < dd4hepVec_.size(); ++jj)
179  edm::LogVerbatim("SimG4CoreGeometry") << " DDG4ProductionCuts : root=" << dd4hepVec_[jj].first->GetName()
180  << " , " << dd4hepVec_[jj].second->paths.at(0);
181  }
182 }
183 
185  //
186  // search for production cuts
187  // you must have four of them: e+ e- gamma proton
188  //
189  double gammacut = 0.0;
190  double electroncut = 0.0;
191  double positroncut = 0.0;
192  double protoncut = 0.0;
193  int temp = map_->toDouble("ProdCutsForGamma", lpart, gammacut);
194  if (temp != 1) {
195  throw cms::Exception(
196  "SimG4CorePhysics",
197  " DDG4ProductionCuts::setProdCuts: Problem with Region tags - no/more than one ProdCutsForGamma.");
198  }
199  temp = map_->toDouble("ProdCutsForElectrons", lpart, electroncut);
200  if (temp != 1) {
201  throw cms::Exception(
202  "SimG4CorePhysics",
203  " DDG4ProductionCuts::setProdCuts: Problem with Region tags - no/more than one ProdCutsForElectrons.");
204  }
205  temp = map_->toDouble("ProdCutsForPositrons", lpart, positroncut);
206  if (temp != 1) {
207  throw cms::Exception(
208  "SimG4CorePhysics",
209  " DDG4ProductionCuts::setProdCuts: Problem with Region tags - no/more than one ProdCutsForPositrons.");
210  }
211  temp = map_->toDouble("ProdCutsForProtons", lpart, protoncut);
212  if (temp == 0) {
213  // There is no ProdCutsForProtons set in XML,
214  // check if it's a legacy geometry scenario without it
215  if (protonCut_) {
216  protoncut = electroncut;
217  } else {
218  protoncut = 0.;
219  }
220  } else if (temp != 1) {
221  throw cms::Exception(
222  "SimG4CorePhysics",
223  " DDG4ProductionCuts::setProdCuts: Problem with Region tags - more than one ProdCutsForProtons.");
224  }
225 
226  //
227  // Create and fill production cuts
228  //
229  G4ProductionCuts* prodCuts = region->GetProductionCuts();
230  if (nullptr == prodCuts) {
231  prodCuts = new G4ProductionCuts();
232  region->SetProductionCuts(prodCuts);
233  }
234  prodCuts->SetProductionCut(gammacut, idxG4GammaCut);
235  prodCuts->SetProductionCut(electroncut, idxG4ElectronCut);
236  prodCuts->SetProductionCut(positroncut, idxG4PositronCut);
237  prodCuts->SetProductionCut(protoncut, idxG4ProtonCut);
238  if (verbosity_ > 0) {
239  edm::LogVerbatim("Geometry") << "DDG4ProductionCuts : Setting cuts for " << region->GetName()
240  << "\n Electrons: " << electroncut << "\n Positrons: " << positroncut
241  << "\n Gamma : " << gammacut << "\n Proton : " << protoncut;
242  }
243 }
244 
245 void DDG4ProductionCuts::setProdCuts(const dd4hep::SpecPar* spec, G4Region* region) {
246  //
247  // Create and fill production cuts
248  //
249  G4ProductionCuts* prodCuts = region->GetProductionCuts();
250  if (!prodCuts) {
251  //
252  // search for production cuts
253  // you must have four of them: e+ e- gamma proton
254  //
255  double gammacut = spec->dblValue("ProdCutsForGamma") / dd4hep::mm; // Convert from DD4hep units to mm
256  double electroncut = spec->dblValue("ProdCutsForElectrons") / dd4hep::mm;
257  double positroncut = spec->dblValue("ProdCutsForPositrons") / dd4hep::mm;
258  double protoncut = spec->dblValue("ProdCutsForProtons") / dd4hep::mm;
259  if (protoncut == 0) {
260  protoncut = electroncut;
261  }
262 
263  prodCuts = new G4ProductionCuts();
264  region->SetProductionCuts(prodCuts);
265 
266  prodCuts->SetProductionCut(gammacut, idxG4GammaCut);
267  prodCuts->SetProductionCut(electroncut, idxG4ElectronCut);
268  prodCuts->SetProductionCut(positroncut, idxG4PositronCut);
269  prodCuts->SetProductionCut(protoncut, idxG4ProtonCut);
270  if (verbosity_ > 0) {
271  edm::LogVerbatim("Geometry") << "DDG4ProductionCuts : Setting cuts for " << region->GetName()
272  << "\n Electrons: " << electroncut << "\n Positrons: " << positroncut
273  << "\n Gamma : " << gammacut << "\n Proton : " << protoncut;
274  }
275  } else {
276  if (verbosity_ > 0) {
277  edm::LogVerbatim("Geometry")
278  << "DDG4ProductionCuts : Cuts are already set for " << region->GetName()
279  << "\n Electrons: " << region->GetProductionCuts()->GetProductionCut(idxG4ElectronCut)
280  << "\n Positrons: " << region->GetProductionCuts()->GetProductionCut(idxG4PositronCut)
281  << "\n Gamma : " << region->GetProductionCuts()->GetProductionCut(idxG4GammaCut)
282  << "\n Proton : " << region->GetProductionCuts()->GetProductionCut(idxG4ProtonCut);
283  }
284  }
285 }
Log< level::Info, true > LogVerbatim
DDG4ProductionCuts(const G4LogicalVolumeToDDLogicalPartMap *, int, bool)
std::vector< std::pair< G4LogicalVolume *, const dd4hep::SpecPar * > > dd4hepVec_
selection
main part
Definition: corrVsCorr.py:100
const dd4hep::SpecParRegistry * specPars_
const std::string keywordRegion_
const G4LogicalVolumeToDDLogicalPartMap * map_
unsigned int toString(const std::string &name, const KeyType &key, std::string &value, unsigned int pos=0) const
same as toDouble but for std::string-valued values of named parameters
Definition: DDMapper.h:172
A DDLogicalPart aggregates information concerning material, solid and sensitveness ...
Definition: DDLogicalPart.h:93
G4LogicalVolumeToDDLogicalPartMap::Vector vec_
void setProdCuts(const DDLogicalPart, G4Region *)
const dd4hep::sim::Geant4GeometryMaps::VolumeMap * dd4hepMap_
Vector all(const std::string &name, const std::string &value) const
get all std::mapped instances which have a specific &#39;name&#39; with value &#39;value&#39;
Definition: DDMapper.h:199
unsigned int toDouble(const std::string &name, const KeyType &key, double &value, unsigned int pos=0) const
returns the number specific parameters named &#39;name&#39; and the corrsponding double
Definition: DDMapper.h:111