Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4PVPlacement.cc
Go to the documentation of this file.
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// Author: Paul Kent (CERN), 24 July 1995 - first non-stub version
29// ----------------------------------------------------------------------
30
31#include "G4PVPlacement.hh"
32#include "G4AffineTransform.hh"
33#include "G4UnitsTable.hh"
34#include "G4LogicalVolume.hh"
35#include "G4VSolid.hh"
36
37// ----------------------------------------------------------------------
38// Constructor
39//
41 const G4ThreeVector& tlate,
42 const G4String& pName,
43 G4LogicalVolume* pLogical,
44 G4VPhysicalVolume* pMother,
45 G4bool pMany,
46 G4int pCopyNo,
47 G4bool pSurfChk )
48 : G4VPhysicalVolume(pRot, tlate, pName, pLogical, pMother),
49 fmany(pMany), fcopyNo(pCopyNo)
50{
51 if (pMother != nullptr)
52 {
53 G4LogicalVolume* motherLogical = pMother->GetLogicalVolume();
54 if (pLogical == motherLogical)
55 {
56 G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
57 FatalException, "Cannot place a volume inside itself!");
58 }
59 SetMotherLogical(motherLogical);
60 motherLogical->AddDaughter(this);
61 if (pSurfChk) { CheckOverlaps(); }
62 }
63}
64
65// ----------------------------------------------------------------------
66// Constructor
67//
69 const G4String& pName,
70 G4LogicalVolume* pLogical,
71 G4VPhysicalVolume* pMother,
72 G4bool pMany,
73 G4int pCopyNo,
74 G4bool pSurfChk )
75 : G4VPhysicalVolume(NewPtrRotMatrix(Transform3D.getRotation().inverse()),
76 Transform3D.getTranslation(), pName, pLogical, pMother),
77 fmany(pMany), fcopyNo(pCopyNo)
78{
79 fallocatedRotM = (GetRotation() != nullptr);
80 if (pMother != nullptr)
81 {
82 G4LogicalVolume* motherLogical = pMother->GetLogicalVolume();
83 if (pLogical == motherLogical)
84 {
85 G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
86 FatalException, "Cannot place a volume inside itself!");
87 }
88 SetMotherLogical(motherLogical);
89 motherLogical->AddDaughter(this);
90 if (pSurfChk) { CheckOverlaps(); }
91 }
92}
93
94// ----------------------------------------------------------------------
95// Constructor
96//
97// The logical volume of the mother is utilised (not the physical)
98//
100 const G4ThreeVector& tlate,
101 G4LogicalVolume* pCurrentLogical,
102 const G4String& pName,
103 G4LogicalVolume* pMotherLogical,
104 G4bool pMany,
105 G4int pCopyNo,
106 G4bool pSurfChk )
107 : G4VPhysicalVolume(pRot, tlate, pName, pCurrentLogical, nullptr),
108 fmany(pMany), fcopyNo(pCopyNo)
109{
110 if (pCurrentLogical == pMotherLogical)
111 {
112 G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
113 FatalException, "Cannot place a volume inside itself!");
114 }
115 SetMotherLogical(pMotherLogical);
116 if (pMotherLogical != nullptr) { pMotherLogical->AddDaughter(this); }
117 if ((pSurfChk) && ((pMotherLogical) != nullptr)) { CheckOverlaps(); }
118}
119
120// ----------------------------------------------------------------------
121// Constructor
122//
124 G4LogicalVolume* pCurrentLogical,
125 const G4String& pName,
126 G4LogicalVolume* pMotherLogical,
127 G4bool pMany,
128 G4int pCopyNo,
129 G4bool pSurfChk )
130 : G4VPhysicalVolume(nullptr, Transform3D.getTranslation(),
131 pName, pCurrentLogical, nullptr),
132 fmany(pMany), fcopyNo(pCopyNo)
133{
134 if (pCurrentLogical == pMotherLogical)
135 {
136 G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
137 FatalException, "Cannot place a volume inside itself!");
138 }
139 SetRotation( NewPtrRotMatrix(Transform3D.getRotation().inverse()) );
140 fallocatedRotM = (GetRotation() != nullptr);
141 SetMotherLogical(pMotherLogical);
142 if (pMotherLogical != nullptr) { pMotherLogical->AddDaughter(this); }
143 if ((pSurfChk) && ((pMotherLogical) != nullptr)) { CheckOverlaps(); }
144}
145
146// ----------------------------------------------------------------------
147// Fake default constructor - sets only member data and allocates memory
148// for usage restricted to object persistency.
149//
152{
153}
154
155// ----------------------------------------------------------------------
156// Destructor
157//
159{
160 if( fallocatedRotM ){ delete this->GetRotation() ; }
161}
162
163// ----------------------------------------------------------------------
164// IsMany
165//
167{
168 return fmany;
169}
170
171// ----------------------------------------------------------------------
172// SetCopyNo
173//
175{
176 fcopyNo = newCopyNo;
177}
178
179// ----------------------------------------------------------------------
180// IsReplicated
181//
183{
184 return false;
185}
186
187// ----------------------------------------------------------------------
188// IsParameterised
189//
191{
192 return false;
193}
194
195// ----------------------------------------------------------------------
196// GetParameterisation
197//
199{
200 return nullptr;
201}
202
203// ----------------------------------------------------------------------
204// GetReplicationData
205//
208{
209 // No-operations
210}
211
212// ----------------------------------------------------------------------
213// IsRegularRepeatedStructure
214//
215// This is for specialised repeated volumes (replicas, parameterised vol.)
216//
218{
219 return false;
220}
221
222// ----------------------------------------------------------------------
223// IsRegularRepeatedStructure
224//
225// This is for specialised repeated volumes (replicas, parameterised vol.)
226//
228{
229 return 0;
230}
231
232// ----------------------------------------------------------------------
233// VolumeType
234//
235// Information to help identify sub-navigator which will be used
236//
238{
239 return kNormal;
240}
241
242// ----------------------------------------------------------------------
243// CheckOverlaps
244//
246 G4bool verbose, G4int maxErr)
247{
248 if (res <= 0) { return false; }
249
250 G4VSolid* solid = GetLogicalVolume()->GetSolid();
251 G4LogicalVolume* motherLog = GetMotherLogical();
252 if (motherLog == nullptr) { return false; }
253
254 G4int trials = 0;
255 G4bool retval = false;
256
257 if (verbose)
258 {
259 G4cout << "Checking overlaps for volume "
260 << GetName() << ':' << GetCopyNo()
261 << " (" << solid->GetEntityType() << ") ... ";
262 }
263
264 // Check that random points are gererated correctly
265 //
266 G4ThreeVector ptmp = solid->GetPointOnSurface();
267 if (solid->Inside(ptmp) != kSurface)
268 {
269 G4String position[3] = { "outside", "surface", "inside" };
270 std::ostringstream message;
271 message << "Sample point is not on the surface !" << G4endl
272 << " The issue is detected for volume "
273 << GetName() << ':' << GetCopyNo()
274 << " (" << solid->GetEntityType() << ")" << G4endl
275 << " generated point " << ptmp
276 << " is " << position[solid->Inside(ptmp)];
277 G4Exception("G4PVPlacement::CheckOverlaps()",
278 "GeomVol1002", JustWarning, message);
279 return false;
280 }
281
282 // Generate random points on the surface of the solid,
283 // transform them into the mother volume coordinate system
284 // and find the bonding box
285 //
286 std::vector<G4ThreeVector> points(res);
287 G4double xmin = kInfinity;
288 G4double ymin = kInfinity;
289 G4double zmin = kInfinity;
290 G4double xmax = -kInfinity;
291 G4double ymax = -kInfinity;
292 G4double zmax = -kInfinity;
294 for (G4int i = 0; i < res; ++i)
295 {
296 points[i] = Tm.TransformPoint(solid->GetPointOnSurface());
297 xmin = std::min(xmin, points[i].x());
298 ymin = std::min(ymin, points[i].y());
299 zmin = std::min(zmin, points[i].z());
300 xmax = std::max(xmax, points[i].x());
301 ymax = std::max(ymax, points[i].y());
302 zmax = std::max(zmax, points[i].z());
303 }
304 G4ThreeVector scenter(0.5*(xmax+xmin), 0.5*(ymax+ymin), 0.5*(zmax+zmin));
305 G4double sradius = 0.5*G4ThreeVector(xmax-xmin, ymax-ymin, zmax-zmin).mag();
306
307 // Check overlap with the mother volume
308 //
309 G4int overlapCount = 0;
310 G4double overlapSize = -kInfinity;
311 G4ThreeVector overlapPoint;
312 G4VSolid* motherSolid = motherLog->GetSolid();
313 for (G4int i = 0; i < res; ++i)
314 {
315 G4ThreeVector mp = points[i];
316 if (motherSolid->Inside(mp) != kOutside) { continue; }
317 G4double distin = motherSolid->DistanceToIn(mp);
318 if (distin < tol) { continue; } // too small overlap
319 ++overlapCount;
320 if (distin <= overlapSize) { continue; }
321 overlapSize = distin;
322 overlapPoint = mp;
323 }
324
325 // Print information on overlap
326 //
327 if (overlapCount > 0)
328 {
329 ++trials;
330 retval = true;
331 std::ostringstream message;
332 message << "Overlap with mother volume !" << G4endl
333 << " Overlap is detected for volume "
334 << GetName() << ':' << GetCopyNo()
335 << " (" << solid->GetEntityType() << ")"
336 << " with its mother volume " << motherLog->GetName()
337 << " (" << motherSolid->GetEntityType() << ")" << G4endl
338 << " protrusion at mother local point " << overlapPoint
339 << " by " << G4BestUnit(overlapSize, "Length")
340 << " (max of " << overlapCount << " cases)";
341 if (trials >= maxErr)
342 {
343 message << G4endl
344 << "NOTE: Reached maximum fixed number -" << maxErr
345 << "- of overlaps reports for this volume !";
346 }
347 G4Exception("G4PVPlacement::CheckOverlaps()",
348 "GeomVol1002", JustWarning, message);
349 if (trials >= maxErr) { return true; }
350 }
351
352 // Checking overlaps with each 'sister' volumes
353 //
354 G4VSolid* previous = nullptr;
355 G4ThreeVector pmin_local(0.,0.,0.);
356 G4ThreeVector pmax_local(0.,0.,0.);
357
358 for (std::size_t k = 0; k < motherLog->GetNoDaughters(); ++k)
359 {
360 G4VPhysicalVolume* daughter = motherLog->GetDaughter((G4int)k);
361 if (daughter == this) { continue; }
362 G4bool check_encapsulation = true;
363
364 G4AffineTransform Td(daughter->GetRotation(), daughter->GetTranslation());
365 G4VSolid* daughterSolid = daughter->GetLogicalVolume()->GetSolid();
366 if (previous != daughterSolid)
367 {
368 daughterSolid->BoundingLimits(pmin_local, pmax_local);
369 previous = daughterSolid;
370 }
371 overlapCount = 0;
372 overlapSize = -kInfinity;
373 if (!Td.IsRotated()) { // no rotation, only translation
375 G4ThreeVector pmin(pmin_local + offset);
376 G4ThreeVector pmax(pmax_local + offset);
377 if (pmin.x() >= xmax) { continue; }
378 if (pmin.y() >= ymax) { continue; }
379 if (pmin.z() >= zmax) { continue; }
380 if (pmax.x() <= xmin) { continue; }
381 if (pmax.y() <= ymin) { continue; }
382 if (pmax.z() <= zmin) { continue; }
383 for (G4int i = 0; i < res; ++i)
384 {
385 G4ThreeVector p = points[i];
386 if (p.x() <= pmin.x()) { continue; }
387 if (p.x() >= pmax.x()) { continue; }
388 if (p.y() <= pmin.y()) { continue; }
389 if (p.y() >= pmax.y()) { continue; }
390 if (p.z() <= pmin.z()) { continue; }
391 if (p.z() >= pmax.z()) { continue; }
392 G4ThreeVector md = p - offset;
393 if (daughterSolid->Inside(md) == kInside)
394 {
395 check_encapsulation = false;
396 G4double distout = daughterSolid->DistanceToOut(md);
397 if (distout < tol) { continue; } // too small overlap
398 ++overlapCount;
399 if (distout <= overlapSize) { continue; }
400 overlapSize = distout;
401 overlapPoint = md;
402 }
403 }
404 }
405 else // transformation with rotation
406 {
407 G4ThreeVector pmin(pmin_local);
408 G4ThreeVector pmax(pmax_local);
409 G4ThreeVector dcenter = Td.TransformPoint(0.5*(pmin + pmax));
410 G4double dradius = 0.5*((pmax - pmin).mag());
411 if ((scenter - dcenter).mag2() >= (sradius + dradius)*(sradius + dradius)) { continue; }
412 if (dcenter.x() - dradius >= xmax) { continue; }
413 if (dcenter.y() - dradius >= ymax) { continue; }
414 if (dcenter.z() - dradius >= zmax) { continue; }
415 if (dcenter.x() + dradius <= xmin) { continue; }
416 if (dcenter.y() + dradius <= ymin) { continue; }
417 if (dcenter.z() + dradius <= zmin) { continue; }
418
419 G4ThreeVector pbox[8] =
420 {
421 G4ThreeVector(pmin.x(), pmin.y(), pmin.z()),
422 G4ThreeVector(pmax.x(), pmin.y(), pmin.z()),
423 G4ThreeVector(pmin.x(), pmax.y(), pmin.z()),
424 G4ThreeVector(pmax.x(), pmax.y(), pmin.z()),
425 G4ThreeVector(pmin.x(), pmin.y(), pmax.z()),
426 G4ThreeVector(pmax.x(), pmin.y(), pmax.z()),
427 G4ThreeVector(pmin.x(), pmax.y(), pmax.z()),
428 G4ThreeVector(pmax.x(), pmax.y(), pmax.z())
429 };
430 G4double dxmin = kInfinity;
431 G4double dymin = kInfinity;
432 G4double dzmin = kInfinity;
433 G4double dxmax = -kInfinity;
434 G4double dymax = -kInfinity;
435 G4double dzmax = -kInfinity;
436 for (const auto & i : pbox)
437 {
439 dxmin = std::min(dxmin, p.x());
440 dymin = std::min(dymin, p.y());
441 dzmin = std::min(dzmin, p.z());
442 dxmax = std::max(dxmax, p.x());
443 dymax = std::max(dymax, p.y());
444 dzmax = std::max(dzmax, p.z());
445 }
446 if (dxmin >= xmax) { continue; }
447 if (dymin >= ymax) { continue; }
448 if (dzmin >= zmax) { continue; }
449 if (dxmax <= xmin) { continue; }
450 if (dymax <= ymin) { continue; }
451 if (dzmax <= zmin) { continue; }
452 for (G4int i = 0; i < res; ++i)
453 {
454 G4ThreeVector p = points[i];
455 if (p.x() >= dxmax) { continue; }
456 if (p.x() <= dxmin) { continue; }
457 if (p.y() >= dymax) { continue; }
458 if (p.y() <= dymin) { continue; }
459 if (p.z() >= dzmax) { continue; }
460 if (p.z() <= dzmin) { continue; }
462 if (daughterSolid->Inside(md) == kInside)
463 {
464 check_encapsulation = false;
465 G4double distout = daughterSolid->DistanceToOut(md);
466 if (distout < tol) { continue; } // too small overlap
467 ++overlapCount;
468 if (distout <= overlapSize) { continue; }
469 overlapSize = distout;
470 overlapPoint = md;
471 }
472 }
473 }
474
475 // Print information on overlap
476 //
477 if (overlapCount > 0)
478 {
479 ++trials;
480 retval = true;
481 std::ostringstream message;
482 message << "Overlap with volume already placed !" << G4endl
483 << " Overlap is detected for volume "
484 << GetName() << ':' << GetCopyNo()
485 << " (" << solid->GetEntityType() << ") with "
486 << daughter->GetName() << ':' << daughter->GetCopyNo()
487 << " (" << daughterSolid->GetEntityType() << ")" << G4endl
488 << " overlap at local point " << overlapPoint
489 << " by " << G4BestUnit(overlapSize, "Length")
490 << " (max of " << overlapCount << " cases)";
491 if (trials >= maxErr)
492 {
493 message << G4endl
494 << "NOTE: Reached maximum fixed number -" << maxErr
495 << "- of overlaps reports for this volume !";
496 }
497 G4Exception("G4PVPlacement::CheckOverlaps()",
498 "GeomVol1002", JustWarning, message);
499 if (trials >= maxErr) { return true; }
500 }
501 else if (check_encapsulation)
502 {
503 // Now checking that 'sister' volume is not totally included
504 // and overlapping. Generate a single point inside of
505 // the 'sister' volume and verify that the point in NOT inside
506 // the current volume
507 //
508 G4ThreeVector pSurface = daughterSolid->GetPointOnSurface();
509 G4ThreeVector normal = daughterSolid->SurfaceNormal(pSurface);
510 G4ThreeVector pInside = pSurface - normal*1.e-4; // move point to inside
511 G4ThreeVector dPoint = (daughterSolid->Inside(pInside) == kInside) ?
512 pInside : pSurface;
513
514 // Transform the generated point to the mother's coordinate system
515 // and then to current volume's coordinate system
516 //
517 G4ThreeVector mp2 = Td.TransformPoint(dPoint);
519
520 if (solid->Inside(msi) == kInside)
521 {
522 ++trials;
523 retval = true;
524 std::ostringstream message;
525 message << "Overlap with volume already placed !" << G4endl
526 << " Overlap is detected for volume "
527 << GetName() << ':' << GetCopyNo()
528 << " (" << solid->GetEntityType() << ")" << G4endl
529 << " apparently fully encapsulating volume "
530 << daughter->GetName() << ':' << daughter->GetCopyNo()
531 << " (" << daughterSolid->GetEntityType() << ")"
532 << " at the same level!";
533 if (trials >= maxErr)
534 {
535 message << G4endl
536 << "NOTE: Reached maximum fixed number -" << maxErr
537 << "- of overlaps reports for this volume !";
538 }
539 G4Exception("G4PVPlacement::CheckOverlaps()",
540 "GeomVol1002", JustWarning, message);
541 if (trials >= maxErr) { return true; }
542 }
543 }
544 }
545
546 if (verbose && trials == 0) { G4cout << "OK! " << G4endl; }
547 return retval;
548}
549
550// ----------------------------------------------------------------------
551// NewPtrRotMatrix
552//
553// Auxiliary function for 2nd & 4th constructors (those with G4Transform3D)
554// Creates a new rotation matrix on the heap (using "new") and copies its
555// argument into it.
556//
557// NOTE: Ownership of the returned pointer is left to the caller !
558// No entity is currently responsible to delete this memory.
559//
561G4PVPlacement::NewPtrRotMatrix(const G4RotationMatrix &RotMat)
562{
563 G4RotationMatrix* pRotMatrix;
564 if ( RotMat.isIdentity() )
565 {
566 pRotMatrix = nullptr;
567 }
568 else
569 {
570 pRotMatrix = new G4RotationMatrix(RotMat);
571 }
572 return pRotMatrix;
573}
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4ThreadLocal T * G4GeomSplitter< T >::offset
CLHEP::HepRotation G4RotationMatrix
#define G4BestUnit(a, b)
CLHEP::Hep3Vector G4ThreeVector
HepGeom::Transform3D G4Transform3D
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
double z() const
double x() const
double y() const
double mag() const
HepRotation inverse() const
bool isIdentity() const
Definition Rotation.cc:167
G4AffineTransform is a class for geometric affine transformations. It supports efficient arbitrary ro...
G4bool IsRotated() const
G4ThreeVector NetTranslation() const
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4ThreeVector InverseTransformPoint(const G4ThreeVector &vec) const
G4LogicalVolume represents a leaf node or unpositioned subtree in the geometry hierarchy....
G4VSolid * GetSolid() const
void AddDaughter(G4VPhysicalVolume *p)
std::size_t GetNoDaughters() const
G4VPhysicalVolume * GetDaughter(const std::size_t i) const
const G4String & GetName() const
G4VPVParameterisation * GetParameterisation() const override
~G4PVPlacement() override
G4bool IsMany() const override
void SetCopyNo(G4int CopyNo) override
G4bool CheckOverlaps(G4int res=1000, G4double tol=0., G4bool verbose=true, G4int maxErr=1) override
G4PVPlacement(G4RotationMatrix *pRot, const G4ThreeVector &tlate, G4LogicalVolume *pCurrentLogical, const G4String &pName, G4LogicalVolume *pMotherLogical, G4bool pMany, G4int pCopyNo, G4bool pSurfChk=false)
EVolume VolumeType() const override
G4int GetRegularStructureId() const override
G4bool IsReplicated() const override
G4int GetCopyNo() const override
void GetReplicationData(EAxis &axis, G4int &nReplicas, G4double &width, G4double &offset, G4bool &consuming) const override
G4bool IsParameterised() const override
G4bool IsRegularStructure() const override
G4VPVParameterisation ia an abstract base class for Parameterisation, able to compute the transformat...
G4LogicalVolume * GetMotherLogical() const
const G4RotationMatrix * GetRotation() const
const G4ThreeVector GetTranslation() const
G4VPhysicalVolume(G4RotationMatrix *pRot, const G4ThreeVector &tlate, const G4String &pName, G4LogicalVolume *pLogical, G4VPhysicalVolume *pMother)
G4LogicalVolume * GetLogicalVolume() const
virtual G4int GetCopyNo() const =0
const G4String & GetName() const
void SetRotation(G4RotationMatrix *)
void SetMotherLogical(G4LogicalVolume *pMother)
G4VSolid is an abstract base class for solids, physical shapes that can be tracked through....
Definition G4VSolid.hh:80
virtual EInside Inside(const G4ThreeVector &p) const =0
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const =0
virtual G4ThreeVector GetPointOnSurface() const
Definition G4VSolid.cc:151
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const =0
virtual void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
Definition G4VSolid.cc:691
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
virtual G4GeometryType GetEntityType() const =0
CLHEP::HepRotation getRotation() const
EAxis
Definition geomdefs.hh:54
@ kInside
Definition geomdefs.hh:70
@ kOutside
Definition geomdefs.hh:68
@ kSurface
Definition geomdefs.hh:69
EVolume
Definition geomdefs.hh:83
@ kNormal
Definition geomdefs.hh:84