Geant4 10.7.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// ----------------------------------------------------------------------
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//
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//
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);
284 G4double xmin = kInfinity, ymin = kInfinity, zmin = kInfinity;
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 G4ThreeVector scenter(0.5*(xmax+xmin), 0.5*(ymax+ymin), 0.5*(zmax+zmin));
298 G4double sradius = 0.5*G4ThreeVector(xmax-xmin, ymax-ymin, zmax-zmin).mag();
299
300 // Check overlap with the mother volume
301 //
302 G4VSolid* motherSolid = motherLog->GetSolid();
303 for (G4int i = 0; i < res; ++i)
304 {
305 G4ThreeVector mp = points[i];
306 if (motherSolid->Inside(mp) != kOutside) continue;
307 G4double distin = motherSolid->DistanceToIn(mp);
308 if (distin > tol)
309 {
310 ++trials;
311 retval = true;
312 std::ostringstream message;
313 message << "Overlap with mother volume !" << G4endl
314 << " Overlap is detected for volume "
315 << GetName() << ':' << GetCopyNo()
316 << " (" << solid->GetEntityType() << ")" << G4endl
317 << " with its mother volume " << motherLog->GetName()
318 << " (" << motherSolid->GetEntityType() << ")" << G4endl
319 << " at mother local point " << mp << ", "
320 << "overlapping by at least: "
321 << G4BestUnit(distin, "Length");
322 if (trials >= maxErr)
323 {
324 message << G4endl
325 << "NOTE: Reached maximum fixed number -" << maxErr
326 << "- of overlaps reports for this volume !";
327 }
328 G4Exception("G4PVPlacement::CheckOverlaps()",
329 "GeomVol1002", JustWarning, message);
330 if (trials >= maxErr) { return true; }
331 break;
332 }
333 }
334
335 // Checking overlaps with each 'sister' volume
336 //
337 G4VSolid* previous = nullptr;
338 G4ThreeVector pmin_local(0.,0.,0.), pmax_local(0.,0.,0.);
339
340 for (size_t k = 0; k < motherLog->GetNoDaughters(); ++k)
341 {
342 G4VPhysicalVolume* daughter = motherLog->GetDaughter(k);
343 if (daughter == this) continue;
344
345 G4AffineTransform Td(daughter->GetRotation(), daughter->GetTranslation());
346 G4VSolid* daughterSolid = daughter->GetLogicalVolume()->GetSolid();
347 if (previous != daughterSolid)
348 {
349 daughterSolid->BoundingLimits(pmin_local, pmax_local);
350 previous = daughterSolid;
351 }
352 G4double distout = -kInfinity;
353 G4ThreeVector plocal;
354 if (!Td.IsRotated()) {
355 G4ThreeVector offset = Td.NetTranslation();
356 G4ThreeVector pmin(pmin_local + offset);
357 G4ThreeVector pmax(pmax_local + offset);
358 if (pmin.x() >= xmax) continue;
359 if (pmin.y() >= ymax) continue;
360 if (pmin.z() >= zmax) continue;
361 if (pmax.x() <= xmin) continue;
362 if (pmax.y() <= ymin) continue;
363 if (pmax.z() <= zmin) continue;
364 for (G4int i = 0; i < res; ++i)
365 {
366 G4ThreeVector p = points[i];
367 if (p.x() <= pmin.x()) continue;
368 if (p.x() >= pmax.x()) continue;
369 if (p.y() <= pmin.y()) continue;
370 if (p.y() >= pmax.y()) continue;
371 if (p.z() <= pmin.z()) continue;
372 if (p.z() >= pmax.z()) continue;
373 G4ThreeVector md = p - offset;
374 if (daughterSolid->Inside(md) == kInside)
375 {
376 G4double dtmp = daughterSolid->DistanceToOut(md);
377 if (dtmp <= tol) continue;
378 distout = dtmp;
379 plocal = md;
380 break;
381 }
382 }
383 }
384 else
385 {
386 G4ThreeVector pmin(pmin_local), pmax(pmax_local);
387 G4ThreeVector dcenter = Td.TransformPoint(0.5*(pmin + pmax));
388 G4double dradius = 0.5*((pmax - pmin).mag());
389 if ((scenter - dcenter).mag2() >= (sradius + dradius)*(sradius + dradius)) continue;
390 if (dcenter.x() - dradius >= xmax) continue;
391 if (dcenter.y() - dradius >= ymax) continue;
392 if (dcenter.z() - dradius >= zmax) continue;
393 if (dcenter.x() + dradius <= xmin) continue;
394 if (dcenter.y() + dradius <= ymin) continue;
395 if (dcenter.z() + dradius <= zmin) continue;
396
397 G4ThreeVector pbox[8] = {
398 G4ThreeVector(pmin.x(), pmin.y(), pmin.z()),
399 G4ThreeVector(pmax.x(), pmin.y(), pmin.z()),
400 G4ThreeVector(pmin.x(), pmax.y(), pmin.z()),
401 G4ThreeVector(pmax.x(), pmax.y(), pmin.z()),
402 G4ThreeVector(pmin.x(), pmin.y(), pmax.z()),
403 G4ThreeVector(pmax.x(), pmin.y(), pmax.z()),
404 G4ThreeVector(pmin.x(), pmax.y(), pmax.z()),
405 G4ThreeVector(pmax.x(), pmax.y(), pmax.z())
406 };
407 G4double dxmin = kInfinity, dymin = kInfinity, dzmin = kInfinity;
408 G4double dxmax = -kInfinity, dymax = -kInfinity, dzmax = -kInfinity;
409 for (G4int i = 0; i < 8; ++i)
410 {
411 G4ThreeVector p = Td.TransformPoint(pbox[i]);
412 dxmin = std::min(dxmin, p.x());
413 dymin = std::min(dymin, p.y());
414 dzmin = std::min(dzmin, p.z());
415 dxmax = std::max(dxmax, p.x());
416 dymax = std::max(dymax, p.y());
417 dzmax = std::max(dzmax, p.z());
418 }
419 if (dxmin >= xmax) continue;
420 if (dymin >= ymax) continue;
421 if (dzmin >= zmax) continue;
422 if (dxmax <= xmin) continue;
423 if (dymax <= ymin) continue;
424 if (dzmax <= zmin) continue;
425 for (G4int i = 0; i < res; ++i)
426 {
427 G4ThreeVector p = points[i];
428 if (p.x() >= dxmax) continue;
429 if (p.x() <= dxmin) continue;
430 if (p.y() >= dymax) continue;
431 if (p.y() <= dymin) continue;
432 if (p.z() >= dzmax) continue;
433 if (p.z() <= dzmin) continue;
435 if (daughterSolid->Inside(md) == kInside)
436 {
437 G4double dtmp = daughterSolid->DistanceToOut(md);
438 if (dtmp <= tol) continue;
439 distout = dtmp;
440 plocal = md;
441 break;
442 }
443 }
444 }
445
446 if (distout > tol)
447 {
448 ++trials;
449 retval = true;
450 std::ostringstream message;
451 message << "Overlap with volume already placed !" << G4endl
452 << " Overlap is detected for volume "
453 << GetName() << ':' << GetCopyNo()
454 << " (" << solid->GetEntityType() << ")" << G4endl
455 << " with " << daughter->GetName()
456 << ':' << daughter->GetCopyNo()
457 << " (" << daughterSolid->GetEntityType() << ")"
458 << " volume's" << G4endl
459 << " local point " << plocal << ", "
460 << "overlapping by at least: "
461 << G4BestUnit(distout, "Length");
462 if (trials >= maxErr)
463 {
464 message << G4endl
465 << "NOTE: Reached maximum fixed number -" << maxErr
466 << "- of overlaps reports for this volume !";
467 }
468 G4Exception("G4PVPlacement::CheckOverlaps()",
469 "GeomVol1002", JustWarning, message);
470 if (trials >= maxErr) { return true; }
471 }
472 else if (distout == kInfinity)
473 {
474 // Now checking that 'sister' volume is not totally included
475 // and overlapping. Generate a single point on the surface of
476 // the 'sister' volume and verify that the point in NOT inside
477 // the current volume
478 //
479 G4ThreeVector dPoint = daughterSolid->GetPointOnSurface();
480
481 // Transform the generated point to the mother's coordinate system
482 // and then to current volume's coordinate system
483 //
484 G4ThreeVector mp2 = Td.TransformPoint(dPoint);
486
487 if (solid->Inside(msi) == kInside)
488 {
489 ++trials;
490 retval = true;
491 std::ostringstream message;
492 message << "Overlap with volume already placed !" << G4endl
493 << " Overlap is detected for volume "
494 << GetName() << ':' << GetCopyNo()
495 << " (" << solid->GetEntityType() << ")" << G4endl
496 << " apparently fully encapsulating volume "
497 << daughter->GetName() << ':' << daughter->GetCopyNo()
498 << " (" << daughterSolid->GetEntityType() << ")"
499 << " at the same level !";
500 if (trials >= maxErr)
501 {
502 message << G4endl
503 << "NOTE: Reached maximum fixed number -" << maxErr
504 << "- of overlaps reports for this volume !";
505 }
506 G4Exception("G4PVPlacement::CheckOverlaps()",
507 "GeomVol1002", JustWarning, message);
508 if (trials >= maxErr) { return true; }
509 }
510 }
511 }
512
513 if (verbose && trials == 0) { G4cout << "OK! " << G4endl; }
514 return retval;
515}
516
517// ----------------------------------------------------------------------
518// NewPtrRotMatrix
519//
520// Auxiliary function for 2nd & 4th constructors (those with G4Transform3D)
521// Creates a new rotation matrix on the heap (using "new") and copies its
522// argument into it.
523//
524// NOTE: Ownership of the returned pointer is left to the caller !
525// No entity is currently responsible to delete this memory.
526//
528G4PVPlacement::NewPtrRotMatrix(const G4RotationMatrix &RotMat)
529{
530 G4RotationMatrix* pRotMatrix;
531 if ( RotMat.isIdentity() )
532 {
533 pRotMatrix = nullptr;
534 }
535 else
536 {
537 pRotMatrix = new G4RotationMatrix(RotMat);
538 }
539 return pRotMatrix;
540}
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
CLHEP::HepRotation G4RotationMatrix
#define G4BestUnit(a, b)
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
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
G4bool IsRotated() const
G4ThreeVector NetTranslation() const
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4ThreeVector InverseTransformPoint(const G4ThreeVector &vec) const
G4VSolid * GetSolid() const
void AddDaughter(G4VPhysicalVolume *p)
size_t GetNoDaughters() const
G4VPhysicalVolume * GetDaughter(const G4int i) const
const G4String & GetName() const
EVolume VolumeType() const
G4bool IsRegularStructure() const
G4bool IsParameterised() const
void SetCopyNo(G4int CopyNo)
G4VPVParameterisation * GetParameterisation() const
G4PVPlacement(G4RotationMatrix *pRot, const G4ThreeVector &tlate, G4LogicalVolume *pCurrentLogical, const G4String &pName, G4LogicalVolume *pMotherLogical, G4bool pMany, G4int pCopyNo, G4bool pSurfChk=false)
G4bool IsReplicated() const
void GetReplicationData(EAxis &axis, G4int &nReplicas, G4double &width, G4double &offset, G4bool &consuming) const
G4int GetRegularStructureId() const
G4int GetCopyNo() const
virtual ~G4PVPlacement()
G4bool IsMany() const
G4bool CheckOverlaps(G4int res=1000, G4double tol=0., G4bool verbose=true, G4int maxErr=1)
G4LogicalVolume * GetMotherLogical() const
const G4RotationMatrix * GetRotation() const
const G4ThreeVector GetTranslation() const
G4LogicalVolume * GetLogicalVolume() const
virtual G4int GetCopyNo() const =0
const G4String & GetName() const
void SetRotation(G4RotationMatrix *)
void SetMotherLogical(G4LogicalVolume *pMother)
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:140
virtual void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
Definition: G4VSolid.cc:653
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