EDepSimVConstrainedPositionGenerator.cc
Go to the documentation of this file.
2 #include "EDepSimException.hh"
3 
4 #include <G4UnitsTable.hh>
5 #include <G4TransportationManager.hh>
6 #include <G4Navigator.hh>
7 #include <G4ThreeVector.hh>
8 #include <G4RotationMatrix.hh>
9 #include <G4VPhysicalVolume.hh>
10 #include <G4LogicalVolume.hh>
11 #include <G4Material.hh>
12 #include <G4VisExtent.hh>
13 #include <Randomize.hh>
14 #include <G4SystemOfUnits.hh>
15 
16 #include <queue>
17 
19  const G4String& name)
20  : EDepSim::VPositionGenerator(name), fSampleVolume("Cryostat"),
21  fLimitsFound(false) {
22  fMaximumCorner.set(1000000*meter,1000000*meter,1000000*meter);
23  fMinimumCorner.set(-1000000*meter,-1000000*meter,-1000000*meter);
24 }
25 
27 
29  return true;
30 }
31 
33  const G4LorentzVector& vtx) {
35  test != fPositionTests.end();
36  ++test) {
37  if (!(*test)->Apply(vtx)) return false;
38  }
39  return true;
40 }
41 
42 namespace {
43  // Check that the vertex is in a volume of a particular name.
44  class InternalVolumeName
46  public:
47  InternalVolumeName(const G4String& name): fName(name) {};
48  virtual ~InternalVolumeName() {};
49  virtual bool Apply(const G4LorentzVector& vtx) {
50  // Get the navigator.
51  G4Navigator* navigator
52  = G4TransportationManager::GetTransportationManager()
53  ->GetNavigatorForTracking();
54 
55  // Get the volume that contains the point.
56  G4VPhysicalVolume* volume
57  = navigator->LocateGlobalPointAndSetup(vtx);
58 
59  if (!volume) return false;
60 
61  // Check that the point is inside the named volume.
62  if (!volume->GetName().contains(fName)) {
63  return false;
64  }
65  return true;
66  }
67  private:
68  G4String fName;
69  };
70 
71  // Check that the vertex is NOT in a volume of a particular name.
72  class InternalNotVolumeName
73  : public InternalVolumeName {
74  public:
75  InternalNotVolumeName(const G4String& name)
76  : InternalVolumeName(name) {};
77  virtual ~InternalNotVolumeName() {};
78  virtual bool Apply(const G4LorentzVector& vtx) {
79  return !InternalVolumeName::Apply(vtx);
80  }
81  };
82 
83  // Check that the vertex is in a volume of a particular material.
84  class InternalVolumeMaterial
86  public:
87  InternalVolumeMaterial(const G4String& name): fMater(name) {};
88  virtual ~InternalVolumeMaterial() {};
89  virtual bool Apply(const G4LorentzVector& vtx) {
90  // Get the navigator.
91  G4Navigator* navigator
92  = G4TransportationManager::GetTransportationManager()
93  ->GetNavigatorForTracking();
94 
95  // Get the volume that contains the point.
96  G4VPhysicalVolume* volume
97  = navigator->LocateGlobalPointAndSetup(vtx);
98 
99  if (!volume) return false;
100 
101  G4String matter = volume->GetLogicalVolume()
102  ->GetMaterial()->GetName();
103 
104  // Check that the point is inside the named material.
105  if (!matter.contains(fMater)) return false;
106  return true;
107  }
108  private:
109  G4String fMater;
110  };
111 
112  // Check that the vertex is NOT in a volume of a particular material.
113  class InternalNotVolumeMaterial
114  : public InternalVolumeMaterial {
115  public:
116  InternalNotVolumeMaterial(const G4String& name)
117  : InternalVolumeMaterial(name) {};
118  virtual ~InternalNotVolumeMaterial() {};
119  virtual bool Apply(const G4LorentzVector& vtx) {
120  return !InternalVolumeMaterial::Apply(vtx);
121  }
122  };
123 
124  // Check that the coordinate is greater than a value.
125  class InternalMinimumCoordinate
127  public:
128  InternalMinimumCoordinate(int coord, double minimum):
129  fCoordinate(coord), fValue(minimum) {};
130  virtual ~InternalMinimumCoordinate() {};
131  virtual bool Apply(const G4LorentzVector& vtx) {
132  if (vtx[fCoordinate] < fValue) return false;
133  return true;
134  }
135  private:
136  int fCoordinate;
137  double fValue;
138  };
139 
140  // Check that the coordinate is less than a value.
141  class InternalMaximumCoordinate
143  public:
144  InternalMaximumCoordinate(int coord, double maximum):
145  fCoordinate(coord), fValue(maximum) {};
146  virtual ~InternalMaximumCoordinate() {};
147  virtual bool Apply(const G4LorentzVector& vtx) {
148  if (fValue < vtx[fCoordinate]) return false;
149  return true;
150  }
151  private:
152  int fCoordinate;
153  double fValue;
154  };
155 
156 }
157 
159  const G4String& name) {
160  fPositionTests.push_back(new InternalVolumeName(name));
161 }
162 
164  const G4String& name) {
165  fPositionTests.push_back(new InternalNotVolumeName(name));
166 }
167 
169  const G4String& name) {
170  fPositionTests.push_back(new InternalVolumeMaterial(name));
171 }
172 
174  const G4String& name) {
175  fPositionTests.push_back(new InternalNotVolumeMaterial(name));
176 }
177 
179  if (fMinimumCorner.x() < x) fMinimumCorner.setX(x);
180  fPositionTests.push_back(new InternalMinimumCoordinate(0,x));
181 }
182 
184  if (fMinimumCorner.y() < y) fMinimumCorner.setY(y);
185  fPositionTests.push_back(new InternalMinimumCoordinate(1,y));
186 }
187 
189  if (fMinimumCorner.z() < z) fMinimumCorner.setZ(z);
190  fPositionTests.push_back(new InternalMinimumCoordinate(2,z));
191 }
192 
194  if (fMaximumCorner.x() > x) fMaximumCorner.setX(x);
195  fPositionTests.push_back(new InternalMaximumCoordinate(0,x));
196 }
197 
199  if (fMaximumCorner.y() > y) fMaximumCorner.setY(y);
200  fPositionTests.push_back(new InternalMaximumCoordinate(1,y));
201 }
202 
204  if (fMaximumCorner.z() > z) fMaximumCorner.setZ(z);
205  fPositionTests.push_back(new InternalMaximumCoordinate(2,z));
206 }
207 
208 namespace {
209  class QueueElement {
210  public:
211  QueueElement(G4VPhysicalVolume* v,
212  const G4ThreeVector& t,
213  const G4RotationMatrix& r)
214  : volume(v), translation(t), rotation(r) {}
215  G4VPhysicalVolume* volume;
216  G4ThreeVector translation;
217  G4RotationMatrix rotation;
218  };
219 }
220 
222  if (fLimitsFound) return;
223  fLimitsFound = true;
224 
225  if (fSampleVolume == "") {
226  EDepSimError("EDepSim::VConstrainedPositionGenerator:: "
227  "The sample volume must be set");
228  }
229 
230  // Find the volume for sampling by something that is big enough to cover
231  // all of the possible vertex locations.
232  G4Navigator* navigator
233  = G4TransportationManager::GetTransportationManager()
234  ->GetNavigatorForTracking();
235 
236  std::queue<QueueElement> volumes;
237  volumes.push(QueueElement(navigator->GetWorldVolume(),
238  G4ThreeVector(0,0,0),
239  G4RotationMatrix()));
240  while (!volumes.empty()) {
241  G4VPhysicalVolume* phyVolume = volumes.front().volume;
242  G4ThreeVector translation
243  = volumes.front().translation + phyVolume->GetObjectTranslation();
244  G4RotationMatrix rotation = volumes.front().rotation;
245  rotation.transform(phyVolume->GetObjectRotationValue());
246  volumes.pop();
247 
248  if (phyVolume->GetName().find(fSampleVolume) != std::string::npos) {
249  G4VisExtent volExtent
250  = phyVolume->GetLogicalVolume()->GetSolid()->GetExtent();
251  G4ThreeVector volMin;
252  G4ThreeVector volMax;
253  volMin.set(volExtent.GetXmin(),
254  volExtent.GetYmin(),
255  volExtent.GetZmin());
256  volMax.set(volExtent.GetXmax(),
257  volExtent.GetYmax(),
258  volExtent.GetZmax());
259  volMin = rotation*volMin + translation;
260  volMax = rotation*volMax + translation;
261  if (fMaximumCorner.x()>volMax.x()) fMaximumCorner.setX(volMax.x());
262  if (fMaximumCorner.y()>volMax.y()) fMaximumCorner.setY(volMax.y());
263  if (fMaximumCorner.z()>volMax.z()) fMaximumCorner.setZ(volMax.z());
264  if (fMinimumCorner.x()<volMin.x()) fMinimumCorner.setX(volMin.x());
265  if (fMinimumCorner.y()<volMin.y()) fMinimumCorner.setY(volMin.y());
266  if (fMinimumCorner.z()<volMin.z()) fMinimumCorner.setZ(volMin.z());
267  break;
268  }
269 
270  G4LogicalVolume* logVolume = phyVolume->GetLogicalVolume();
271  for (std::size_t i=0; i< logVolume->GetNoDaughters(); ++i) {
272  volumes.push(QueueElement(logVolume->GetDaughter(i),
273  translation,
274  rotation));
275  }
276  }
277 
278  EDepSimLog("Sampling volume extent:");
279  EDepSimLog(" X: " << G4BestUnit(fMinimumCorner[0],"Length")
280  << "to " << G4BestUnit(fMaximumCorner[0],"Length"));
281  EDepSimLog(" Y: " << G4BestUnit(fMinimumCorner[1],"Length")
282  << "to " << G4BestUnit(fMaximumCorner[1],"Length"));
283  EDepSimLog(" Z: " << G4BestUnit(fMinimumCorner[2],"Length")
284  << "to " << G4BestUnit(fMaximumCorner[2],"Length"));
285 }
286 
288  FindLimits();
289  G4LorentzVector vtx;
290  for (int i=0; i<3; ++i) {
291  vtx[i] = (fMaximumCorner[i] - fMinimumCorner[i])*G4UniformRand()
292  + fMinimumCorner[i];
293  }
294  vtx[3] = 0;
295  return vtx;
296 }
static QCString name
Definition: declinfo.cpp:673
#define EDepSimLog(outStream)
Definition: EDepSimLog.hh:717
G4ThreeVector fMinimumCorner
The lower boundary of the volume to be sampled for the vertex.
virtual bool ValidPosition(const G4LorentzVector &vtx)
Return true if the vertex is valid. This is used in the derived class.
intermediate_table::iterator iterator
void CheckMaxZ(double z)
Check that the vertex Z position is less than some value.
G4String fSampleVolume
The name of the volume to be sampled.
auto coord(Vector &v, unsigned int n) noexcept
Returns an object to manage the coordinate n of a vector.
static const std::string volume[nvol]
void FindLimits()
Find the limits of the volume to be sampled for a good vertex.
G4String fName
The name of the generator.
bool fLimitsFound
True if the limits have been initialized.
G4LorentzVector TrialPosition()
Generate a trial position uniformly in the sample box.
Construct a module from components.
Definition: TG4HitSegment.h:10
void CheckMaxX(double x)
Check that the vertex X position is less than some value.
void CheckMinY(double y)
Check that the vertex Y position is greater than some value.
void CheckVolumeMaterial(const G4String &name)
Check that the vertex is inside of a material specified by name.
meter_as<> meter
Type of space stored in meters, in double precision.
Definition: spacetime.h:400
G4ThreeVector fMaximumCorner
The upper boundary of the volume to be sampled for the vertex.
void CheckMaxY(double y)
Check that the vertex Y position is less than some value.
#define EDepSimError(outStream)
Definition: EDepSimLog.hh:503
void CheckMinX(double x)
Check that the vertex X position is greater than some value.
PositionTests fPositionTests
The vertex tests to apply.
list x
Definition: train.py:276
void CheckMinZ(double z)
Check that the vertex Z position is greater than some value.
void CheckNotVolumeMaterial(const G4String &name)
Check that the vertex is not inside of a material specified by name.