ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4PVPlacement.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4PVPlacement.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 // class G4PVPlacement Implementation
27 //
28 // ----------------------------------------------------------------------
29 
30 #include "G4PVPlacement.hh"
31 #include "G4AffineTransform.hh"
32 #include "G4UnitsTable.hh"
33 #include "G4LogicalVolume.hh"
34 #include "G4VSolid.hh"
35 
36 // ----------------------------------------------------------------------
37 // Constructor
38 //
40  const G4ThreeVector& tlate,
41  const G4String& pName,
42  G4LogicalVolume* pLogical,
43  G4VPhysicalVolume* pMother,
44  G4bool pMany,
45  G4int pCopyNo,
46  G4bool pSurfChk )
47  : G4VPhysicalVolume(pRot, tlate, pName, pLogical, pMother),
48  fmany(pMany), fcopyNo(pCopyNo)
49 {
50  if (pMother)
51  {
52  G4LogicalVolume* motherLogical = pMother->GetLogicalVolume();
53  if (pLogical == motherLogical)
54  {
55  G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
56  FatalException, "Cannot place a volume inside itself!");
57  }
58  SetMotherLogical(motherLogical);
59  motherLogical->AddDaughter(this);
60  if (pSurfChk) { CheckOverlaps(); }
61  }
62 }
63 
64 // ----------------------------------------------------------------------
65 // Constructor
66 //
68  const G4String& pName,
69  G4LogicalVolume* pLogical,
70  G4VPhysicalVolume* pMother,
71  G4bool pMany,
72  G4int pCopyNo,
73  G4bool pSurfChk )
74  : G4VPhysicalVolume(NewPtrRotMatrix(Transform3D.getRotation().inverse()),
75  Transform3D.getTranslation(), pName, pLogical, pMother),
76  fmany(pMany), fcopyNo(pCopyNo)
77 {
78  fallocatedRotM = (GetRotation() != 0);
79  if (pMother)
80  {
81  G4LogicalVolume* motherLogical = pMother->GetLogicalVolume();
82  if (pLogical == motherLogical)
83  G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
84  FatalException, "Cannot place a volume inside itself!");
85  SetMotherLogical(motherLogical);
86  motherLogical->AddDaughter(this);
87  if (pSurfChk) { CheckOverlaps(); }
88  }
89 }
90 
91 // ----------------------------------------------------------------------
92 // Constructor
93 //
94 // The logical volume of the mother is utilised (not the physical)
95 //
97  const G4ThreeVector& tlate,
98  G4LogicalVolume* pCurrentLogical,
99  const G4String& pName,
100  G4LogicalVolume* pMotherLogical,
101  G4bool pMany,
102  G4int pCopyNo,
103  G4bool pSurfChk )
104  : G4VPhysicalVolume(pRot, tlate, pName, pCurrentLogical, nullptr),
105  fmany(pMany), fcopyNo(pCopyNo)
106 {
107  if (pCurrentLogical == pMotherLogical)
108  {
109  G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
110  FatalException, "Cannot place a volume inside itself!");
111  }
112  SetMotherLogical(pMotherLogical);
113  if (pMotherLogical) { pMotherLogical->AddDaughter(this); }
114  if ((pSurfChk) && (pMotherLogical)) { CheckOverlaps(); }
115 }
116 
117 
118 // ----------------------------------------------------------------------
119 // Constructor
120 //
122  G4LogicalVolume* pCurrentLogical,
123  const G4String& pName,
124  G4LogicalVolume* pMotherLogical,
125  G4bool pMany,
126  G4int pCopyNo,
127  G4bool pSurfChk )
128  : G4VPhysicalVolume(nullptr, Transform3D.getTranslation(),
129  pName, pCurrentLogical, nullptr),
130  fmany(pMany), fcopyNo(pCopyNo)
131 {
132  if (pCurrentLogical == pMotherLogical)
133  {
134  G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
135  FatalException, "Cannot place a volume inside itself!");
136  }
137  SetRotation( NewPtrRotMatrix(Transform3D.getRotation().inverse()) );
138  fallocatedRotM = (GetRotation() != nullptr);
139  SetMotherLogical(pMotherLogical);
140  if (pMotherLogical) { pMotherLogical->AddDaughter(this); }
141  if ((pSurfChk) && (pMotherLogical)) { CheckOverlaps(); }
142 }
143 
144 // ----------------------------------------------------------------------
145 // Fake default constructor - sets only member data and allocates memory
146 // for usage restricted to object persistency.
147 //
149  : G4VPhysicalVolume(a)
150 {
151 }
152 
153 // ----------------------------------------------------------------------
154 // Destructor
155 //
157 {
158  if( fallocatedRotM ){ delete this->GetRotation() ; }
159 }
160 
161 // ----------------------------------------------------------------------
162 // IsMany
163 //
165 {
166  return fmany;
167 }
168 
169 // ----------------------------------------------------------------------
170 // SetCopyNo
171 //
173 {
174  fcopyNo = newCopyNo;
175 }
176 
177 // ----------------------------------------------------------------------
178 // IsReplicated
179 //
181 {
182  return false;
183 }
184 
185 // ----------------------------------------------------------------------
186 // IsParameterised
187 //
189 {
190  return false;
191 }
192 
193 // ----------------------------------------------------------------------
194 // GetParameterisation
195 //
197 {
198  return nullptr;
199 }
200 
201 // ----------------------------------------------------------------------
202 // GetReplicationData
203 //
204 void G4PVPlacement::
206 {
207  // No-operations
208 }
209 
210 // ----------------------------------------------------------------------
211 // IsRegularRepeatedStructure
212 //
213 // This is for specialised repeated volumes (replicas, parameterised vol.)
214 //
216 {
217  return false;
218 }
219 
220 // ----------------------------------------------------------------------
221 // IsRegularRepeatedStructure
222 //
223 // This is for specialised repeated volumes (replicas, parameterised vol.)
224 //
226 {
227  return 0;
228 }
229 
230 // ----------------------------------------------------------------------
231 // VolumeType
232 //
233 // Information to help identify sub-navigator which will be used
234 //
236 {
237  return kNormal;
238 }
239 
240 // ----------------------------------------------------------------------
241 // CheckOverlaps
242 //
244  G4bool verbose, G4int maxErr)
245 {
246  if (res <= 0) { return false; }
247 
248  G4VSolid* solid = GetLogicalVolume()->GetSolid();
249  G4LogicalVolume* motherLog = GetMotherLogical();
250  if (motherLog == nullptr) { return false; }
251 
252  G4int trials = 0;
253  G4bool retval = false;
254 
255  if (verbose)
256  {
257  G4cout << "Checking overlaps for volume " << GetName()
258  << " (" << solid->GetEntityType() << ") ... ";
259  }
260 
261  // Check that random points are gererated correctly
262  //
263  G4ThreeVector ptmp = solid->GetPointOnSurface();
264  if (solid->Inside(ptmp) != kSurface)
265  {
266  G4String position[3] = { "outside", "surface", "inside" };
267  std::ostringstream message;
268  message << "Sample point is not on the surface !" << G4endl
269  << " The issue is detected for volume "
270  << GetName() << ':' << GetCopyNo()
271  << " (" << solid->GetEntityType() << ")" << G4endl
272  << " generated point " << ptmp
273  << " is " << position[solid->Inside(ptmp)];
274  G4Exception("G4PVPlacement::CheckOverlaps()",
275  "GeomVol1002", JustWarning, message);
276  return false;
277  }
278 
279  // Generate random points on the surface of the solid,
280  // transform them into the mother volume coordinate system
281  // and find the bonding box
282  //
283  std::vector<G4ThreeVector> points(res);
285  G4double xmax = -kInfinity, ymax = -kInfinity, zmax = -kInfinity;
287  for (G4int i = 0; i < res; ++i)
288  {
289  points[i] = Tm.TransformPoint(solid->GetPointOnSurface());
290  xmin = std::min(xmin, points[i].x());
291  ymin = std::min(ymin, points[i].y());
292  zmin = std::min(zmin, points[i].z());
293  xmax = std::max(xmax, points[i].x());
294  ymax = std::max(ymax, points[i].y());
295  zmax = std::max(zmax, points[i].z());
296  }
297 
298  // Check overlap with the mother volume
299  //
300  G4VSolid* motherSolid = motherLog->GetSolid();
301  for (G4int i = 0; i < res; ++i)
302  {
303  G4ThreeVector mp = points[i];
304  if (motherSolid->Inside(mp) != kOutside) continue;
305  G4double distin = motherSolid->DistanceToIn(mp);
306  if (distin > tol)
307  {
308  ++trials;
309  retval = true;
310  std::ostringstream message;
311  message << "Overlap with mother volume !" << G4endl
312  << " Overlap is detected for volume "
313  << GetName() << ':' << GetCopyNo()
314  << " (" << solid->GetEntityType() << ")" << G4endl
315  << " with its mother volume " << motherLog->GetName()
316  << " (" << motherSolid->GetEntityType() << ")" << G4endl
317  << " at mother local point " << mp << ", "
318  << "overlapping by at least: "
319  << G4BestUnit(distin, "Length");
320  if (trials >= maxErr)
321  {
322  message << G4endl
323  << "NOTE: Reached maximum fixed number -" << maxErr
324  << "- of overlaps reports for this volume !";
325  }
326  G4Exception("G4PVPlacement::CheckOverlaps()",
327  "GeomVol1002", JustWarning, message);
328  if (trials >= maxErr) { return true; }
329  break;
330  }
331  }
332 
333  // Checking overlaps with each 'sister' volume
334  //
335  for (size_t k = 0; k < motherLog->GetNoDaughters(); ++k)
336  {
337  G4VPhysicalVolume* daughter = motherLog->GetDaughter(k);
338  if (daughter == this) continue;
339  G4VSolid* daughterSolid = daughter->GetLogicalVolume()->GetSolid();
340  G4AffineTransform Td(daughter->GetRotation(), daughter->GetTranslation());
341 
342  G4double distout = -kInfinity;
343  G4ThreeVector plocal;
344  if (!Td.IsRotated()) {
345  G4ThreeVector offset = Td.NetTranslation();
346  G4ThreeVector pmin, pmax;
347  daughterSolid->BoundingLimits(pmin, pmax);
348  pmin += offset;
349  pmax += offset;
350  if (pmin.x() >= xmax) continue;
351  if (pmin.y() >= ymax) continue;
352  if (pmin.z() >= zmax) continue;
353  if (pmax.x() <= xmin) continue;
354  if (pmax.y() <= ymin) continue;
355  if (pmax.z() <= zmin) continue;
356  for (G4int i = 0; i < res; ++i)
357  {
358  G4ThreeVector p = points[i];
359  if (p.x() <= pmin.x()) continue;
360  if (p.x() >= pmax.x()) continue;
361  if (p.y() <= pmin.y()) continue;
362  if (p.y() >= pmax.y()) continue;
363  if (p.z() <= pmin.z()) continue;
364  if (p.z() >= pmax.z()) continue;
365  G4ThreeVector md = p - offset;
366  if (daughterSolid->Inside(md) == kInside)
367  {
368  G4double dtmp = daughterSolid->DistanceToOut(md);
369  if (dtmp <= tol) continue;
370  distout = dtmp;
371  plocal = md;
372  break;
373  }
374  }
375  } else {
376  G4ThreeVector pmin, pmax;
377  daughterSolid->BoundingLimits(pmin, pmax);
378  G4ThreeVector pbox[8] = {
379  G4ThreeVector(pmin.x(), pmin.y(), pmin.z()),
380  G4ThreeVector(pmax.x(), pmin.y(), pmin.z()),
381  G4ThreeVector(pmin.x(), pmax.y(), pmin.z()),
382  G4ThreeVector(pmax.x(), pmax.y(), pmin.z()),
383  G4ThreeVector(pmin.x(), pmin.y(), pmax.z()),
384  G4ThreeVector(pmax.x(), pmin.y(), pmax.z()),
385  G4ThreeVector(pmin.x(), pmax.y(), pmax.z()),
386  G4ThreeVector(pmax.x(), pmax.y(), pmax.z())
387  };
388  G4double dxmin = kInfinity, dymin = kInfinity, dzmin = kInfinity;
389  G4double dxmax = -kInfinity, dymax = -kInfinity, dzmax = -kInfinity;
390  for (G4int i = 0; i < 8; ++i)
391  {
392  G4ThreeVector p = Td.TransformPoint(pbox[i]);
393  dxmin = std::min(dxmin, p.x());
394  dymin = std::min(dymin, p.y());
395  dzmin = std::min(dzmin, p.z());
396  dxmax = std::max(dxmax, p.x());
397  dymax = std::max(dymax, p.y());
398  dzmax = std::max(dzmax, p.z());
399  }
400  if (dxmin >= xmax) continue;
401  if (dymin >= ymax) continue;
402  if (dzmin >= zmax) continue;
403  if (dxmax <= xmin) continue;
404  if (dymax <= ymin) continue;
405  if (dzmax <= zmin) continue;
406  for (G4int i = 0; i < res; ++i)
407  {
408  G4ThreeVector p = points[i];
409  if (p.x() >= dxmax) continue;
410  if (p.x() <= dxmin) continue;
411  if (p.y() >= dymax) continue;
412  if (p.y() <= dymin) continue;
413  if (p.z() >= dzmax) continue;
414  if (p.z() <= dzmin) continue;
415  G4ThreeVector md = Td.InverseTransformPoint(p);
416  if (daughterSolid->Inside(md) == kInside)
417  {
418  G4double dtmp = daughterSolid->DistanceToOut(md);
419  if (dtmp <= tol) continue;
420  distout = dtmp;
421  plocal = md;
422  break;
423  }
424  }
425  }
426 
427  if (distout > tol)
428  {
429  ++trials;
430  retval = true;
431  std::ostringstream message;
432  message << "Overlap with volume already placed !" << G4endl
433  << " Overlap is detected for volume "
434  << GetName() << ':' << GetCopyNo()
435  << " (" << solid->GetEntityType() << ")" << G4endl
436  << " with " << daughter->GetName()
437  << ':' << daughter->GetCopyNo()
438  << " (" << daughterSolid->GetEntityType() << ")"
439  << " volume's" << G4endl
440  << " local point " << plocal << ", "
441  << "overlapping by at least: "
442  << G4BestUnit(distout, "Length");
443  if (trials >= maxErr)
444  {
445  message << G4endl
446  << "NOTE: Reached maximum fixed number -" << maxErr
447  << "- of overlaps reports for this volume !";
448  }
449  G4Exception("G4PVPlacement::CheckOverlaps()",
450  "GeomVol1002", JustWarning, message);
451  if (trials >= maxErr) { return true; }
452  }
453  else if (distout == kInfinity)
454  {
455  // Now checking that 'sister' volume is not totally included
456  // and overlapping. Generate a single point on the surface of
457  // the 'sister' volume and verify that the point in NOT inside
458  // the current volume
459  //
460  G4ThreeVector dPoint = daughterSolid->GetPointOnSurface();
461 
462  // Transform the generated point to the mother's coordinate system
463  // and then to current volume's coordinate system
464  //
465  G4ThreeVector mp2 = Td.TransformPoint(dPoint);
466  G4ThreeVector msi = Tm.InverseTransformPoint(mp2);
467 
468  if (solid->Inside(msi) == kInside)
469  {
470  ++trials;
471  retval = true;
472  std::ostringstream message;
473  message << "Overlap with volume already placed !" << G4endl
474  << " Overlap is detected for volume "
475  << GetName() << ':' << GetCopyNo()
476  << " (" << solid->GetEntityType() << ")" << G4endl
477  << " apparently fully encapsulating volume "
478  << daughter->GetName() << ':' << daughter->GetCopyNo()
479  << " (" << daughterSolid->GetEntityType() << ")"
480  << " at the same level !";
481  if (trials >= maxErr)
482  {
483  message << G4endl
484  << "NOTE: Reached maximum fixed number -" << maxErr
485  << "- of overlaps reports for this volume !";
486  }
487  G4Exception("G4PVPlacement::CheckOverlaps()",
488  "GeomVol1002", JustWarning, message);
489  if (trials >= maxErr) { return true; }
490  }
491  }
492  }
493 
494  if (verbose && trials == 0) { G4cout << "OK! " << G4endl; }
495  return retval;
496 }
497 
498 // ----------------------------------------------------------------------
499 // NewPtrRotMatrix
500 //
501 // Auxiliary function for 2nd & 4th constructors (those with G4Transform3D)
502 // Creates a new rotation matrix on the heap (using "new") and copies its
503 // argument into it.
504 //
505 // NOTE: Ownership of the returned pointer is left to the caller !
506 // No entity is currently responsible to delete this memory.
507 //
510 {
511  G4RotationMatrix* pRotMatrix;
512  if ( RotMat.isIdentity() )
513  {
514  pRotMatrix = nullptr;
515  }
516  else
517  {
518  pRotMatrix = new G4RotationMatrix(RotMat);
519  }
520  return pRotMatrix;
521 }