Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4GeomTestVolume.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//
27// $Id$
28//
29// --------------------------------------------------------------------
30// GEANT 4 class source file
31//
32// G4GeomTestVolume
33//
34// Author: D.C.Williams, UCSC (davidw@scipp.ucsc.edu)
35// --------------------------------------------------------------------
36
37#include <vector>
38#include <set>
39#include <algorithm>
40#include <iomanip>
41
42#include "G4GeomTestVolume.hh"
43
45#include "G4GeomTestLogger.hh"
46#include "G4GeomTestVolPoint.hh"
47#include "G4GeomTestSegment.hh"
48
49#include "G4VPhysicalVolume.hh"
50#include "G4LogicalVolume.hh"
51#include "G4VSolid.hh"
52
53//
54// Constructor
55//
57 G4GeomTestLogger *theLogger,
58 G4double theTolerance )
59 : target(theTarget),
60 logger(theLogger),
61 tolerance(theTolerance),
62 extent(theTarget->GetLogicalVolume()->GetSolid()->GetExtent())
63{;}
64
65//
66// Destructor
67//
69
70//
71// Get error tolerance
72//
74{
75 return tolerance;
76}
77
78//
79// Set error tolerance
80//
82{
83 tolerance = val;
84}
85
86//
87// TestCartGridXYZ
88//
90{
91 TestCartGridX( ny, nz );
92 TestCartGridY( nz, nx );
93 TestCartGridZ( nx, ny );
94}
95
96//
97// TestCartGridX
98//
100{
102 G4ThreeVector(1,0,0), ny, nz );
103}
104
105//
106// TestCartGridY
107//
109{
111 G4ThreeVector(0,1,0), nz, nx );
112}
113
114//
115// TestCartGridZ
116//
118{
120 G4ThreeVector(0,0,1), nx, ny );
121}
122
123//
124// TestRecursiveCartGrid
125//
127 G4int slevel, G4int depth )
128{
129 // If reached requested level of depth (i.e. set to 0), exit.
130 // If not depth specified (i.e. set to -1), visit the whole tree.
131 // If requested initial level of depth is not zero, visit from beginning
132 //
133 if (depth == 0) return;
134 if (depth != -1) depth--;
135 if (slevel != 0) slevel--;
136
137 //
138 // As long as we aren't a replica and we reached the requested
139 // initial level of depth, test ourselves
140 //
141 if ( (!target->IsReplicated()) && (slevel==0) )
142 {
143 TestCartGridXYZ( nx, ny, nz );
144 ReportErrors();
145 }
146
147 //
148 // Loop over unique daughters
149 //
150 std::set<const G4LogicalVolume *> tested;
151
152 const G4LogicalVolume *logical = target->GetLogicalVolume();
153 G4int nDaughter = logical->GetNoDaughters();
154 G4int iDaughter;
155 for( iDaughter=0; iDaughter<nDaughter; ++iDaughter )
156 {
157 const G4VPhysicalVolume *daughter =
158 logical->GetDaughter(iDaughter);
159 const G4LogicalVolume *daughterLogical =
160 daughter->GetLogicalVolume();
161
162 //
163 // Skip empty daughters
164 //
165 if (daughterLogical->GetNoDaughters() == 0) continue;
166
167 //
168 // Tested already?
169 //
170 std::pair<std::set<const G4LogicalVolume *>::iterator,G4bool>
171 there = tested.insert(daughterLogical);
172 if (!there.second) continue;
173
174 //
175 // Recurse
176 //
177 G4GeomTestVolume vTest( daughter, logger, tolerance );
178 vTest.TestRecursiveCartGrid( nx,ny,nz,slevel,depth );
179 }
180}
181
182//
183// TestRecursiveCylinder
184//
185void
187 G4double fracZ, G4double fracRho,
188 G4bool usePhi,
189 G4int slevel, G4int depth )
190{
191 // If reached requested level of depth (i.e. set to 0), exit.
192 // If not depth specified (i.e. set to -1), visit the whole tree.
193 // If requested initial level of depth is not zero, visit from beginning
194 //
195 if (depth == 0) return;
196 if (depth != -1) depth--;
197 if (slevel != 0) slevel--;
198
199 //
200 // As long as we aren't a replica and we reached the requested
201 // initial level of depth, test ourselves
202 //
203 if ( (!target->IsReplicated()) && (slevel==0) )
204 {
205 TestCylinder( nPhi, nZ, nRho, fracZ, fracRho, usePhi );
206 ReportErrors();
207 }
208
209 //
210 // Loop over unique daughters
211 //
212 std::set<const G4LogicalVolume *> tested;
213
214 const G4LogicalVolume *logical = target->GetLogicalVolume();
215 G4int nDaughter = logical->GetNoDaughters();
216 G4int iDaughter;
217 for( iDaughter=0; iDaughter<nDaughter; ++iDaughter )
218 {
219 const G4VPhysicalVolume *daughter =
220 logical->GetDaughter(iDaughter);
221 const G4LogicalVolume *daughterLogical =
222 daughter->GetLogicalVolume();
223
224 //
225 // Skip empty daughters
226 //
227 if (daughterLogical->GetNoDaughters() == 0) continue;
228
229 //
230 // Tested already?
231 //
232 std::pair<std::set<const G4LogicalVolume *>::iterator,G4bool>
233 there = tested.insert(daughterLogical);
234 if (!there.second) continue;
235
236 //
237 // Recurse
238 //
239 G4GeomTestVolume vTest( daughter, logger, tolerance );
240 vTest.TestRecursiveCylinder( nPhi, nZ, nRho,
241 fracZ, fracRho, usePhi,
242 slevel, depth );
243 }
244}
245
246//
247// TestCylinder
248//
250 G4double fracZ, G4double fracRho,
251 G4bool usePhi )
252{
253 //
254 // Get size of our volume
255 //
256 G4double xMax = std::max(extent.GetXmax(),-extent.GetXmin());
257 G4double yMax = std::max(extent.GetYmax(),-extent.GetYmin());
258 G4double rhoMax = std::sqrt(xMax*xMax + yMax*yMax);
259
260 G4double zMax = extent.GetZmax();
261 G4double zMin = extent.GetZmin();
262 G4double zHalfLength = 0.5*(zMax-zMin);
263 G4double z0 = 0.5*(zMax+zMin);
264
265 //
266 // Loop over phi
267 //
268 G4double deltaPhi = 2*pi/G4double(nPhi);
269
270 G4double phi = 0;
271 G4int iPhi = nPhi;
272 if ((iPhi&1) == 0) iPhi++; // Also use odd number phi slices
273 do
274 {
275 G4double cosPhi = std::cos(phi);
276 G4double sinPhi = std::sin(phi);
277 G4ThreeVector vPhi1(sinPhi,-cosPhi,0);
278
279 //
280 // Loop over rho
281 //
282 G4double rho = rhoMax;
283 G4int iRho = nRho;
284 do
285 {
286 G4ThreeVector p(rho*cosPhi,rho*sinPhi,0);
287 static G4ThreeVector v(0,0,1);
288
289 TestOneLine( p, v );
290
291 if (usePhi)
292 {
293 //
294 // Loop over z
295 //
296 G4double zScale = 1.0;
297 G4int iZ=nZ;
298 do
299 {
300 p.setZ( z0 + zScale*zHalfLength );
301 TestOneLine(p,vPhi1);
302 p.setZ( z0 - zScale*zHalfLength );
303 TestOneLine(p,vPhi1);
304 } while( zScale *= fracZ, --iZ );
305 }
306 } while( rho *= fracRho, --iRho );
307
308 //
309 // Loop over z
310 //
311 G4ThreeVector p(0,0,0);
312 G4ThreeVector vPhi2(cosPhi,sinPhi,0);
313
314 G4double zScale = 1.0;
315 G4int iZ=nZ;
316 do
317 {
318 p.setZ( z0 + zScale*zHalfLength );
319
320 TestOneLine(p,vPhi2);
321
322 p.setZ( z0 - zScale*zHalfLength );
323
324 TestOneLine(p,vPhi2);
325 } while( zScale *= fracZ, --iZ );
326
327 } while( phi += deltaPhi, --iPhi );
328}
329
330//
331// TestCartGrid
332//
334 const G4ThreeVector &theG2,
335 const G4ThreeVector &theV,
336 G4int n1, G4int n2 )
337{
338 if (n1 <= 0 || n2 <= 0)
339 G4Exception( "G4GeomTestVolume::TestCartGrid()", "GeomNav0002",
340 FatalException, "Arguments n1 and n2 must be >= 1" );
341
343 extent.GetZmin() );
345 extent.GetZmax() );
346
347 G4ThreeVector g1(theG1.unit());
348 G4ThreeVector g2(theG2.unit());
349 G4ThreeVector v(theV.unit());
350
351 G4double gMin1 = g1.dot(xMin);
352 G4double gMax1 = g1.dot(xMax);
353
354 G4double gMin2 = g2.dot(xMin);
355 G4double gMax2 = g2.dot(xMax);
356
357 G4double delta1 = (gMax1-gMin1)/G4double(n1);
358 G4double delta2 = (gMax2-gMin2)/G4double(n2);
359
360 G4int i1, i2;
361
362 for(i1=0;i1<=n1;++i1)
363 {
364 G4ThreeVector p1 = (gMin1 + G4double(i1)*delta1)*g1;
365
366 for(i2=0;i2<=n2;++i2)
367 {
368 G4ThreeVector p2 = (gMin2 + G4double(i2)*delta2)*g2;
369
370 TestOneLine( p1+p2, v );
371 }
372 }
373}
374
375//
376// TestRecursiveLine
377//
378void
380 const G4ThreeVector& v,
381 G4int slevel, G4int depth )
382{
383 // If reached requested level of depth (i.e. set to 0), exit.
384 // If not depth specified (i.e. set to -1), visit the whole tree.
385 // If requested initial level of depth is not zero, visit from beginning
386 //
387 if (depth == 0) return;
388 if (depth != -1) depth--;
389 if (slevel != 0) slevel--;
390
391 //
392 // As long as we aren't a replica and we reached the requested
393 // initial level of depth, test ourselves
394 //
395 if ( (!target->IsReplicated()) && (slevel==0) )
396 {
397 TestOneLine( p, v );
398 ReportErrors();
399 }
400
401 //
402 // Loop over unique daughters
403 //
404 std::set<const G4LogicalVolume *> tested;
405
406 const G4LogicalVolume *logical = target->GetLogicalVolume();
407 G4int nDaughter = logical->GetNoDaughters();
408 G4int iDaughter;
409 for( iDaughter=0; iDaughter<nDaughter; ++iDaughter )
410 {
411 const G4VPhysicalVolume *daughter =
412 logical->GetDaughter(iDaughter);
413 const G4LogicalVolume *daughterLogical =
414 daughter->GetLogicalVolume();
415
416 //
417 // Skip empty daughters
418 //
419 if (daughterLogical->GetNoDaughters() == 0) continue;
420
421 //
422 // Tested already?
423 //
424 std::pair<std::set<const G4LogicalVolume *>::iterator,G4bool>
425 there = tested.insert(daughterLogical);
426 if (!there.second) continue;
427
428 //
429 // Recurse
430 //
431 G4GeomTestVolume vTest( daughter, logger, tolerance );
432 vTest.TestRecursiveLine( p, v, slevel, depth );
433 }
434}
435
436//
437// TestOneLine
438//
439// Test geometry consistency along a single line
440//
442 const G4ThreeVector &v )
443{
444 //
445 // Keep track of intersection points
446 //
447 std::vector<G4GeomTestVolPoint> points;
448
449 //
450 // Calculate intersections with the mother volume
451 //
453 p, v, logger );
454
455 //
456 // Add them to our list
457 //
458 G4int n = targetSegment.GetNumberPoints();
459 G4int i;
460 for(i=0;i<n;++i)
461 {
462 points.push_back( G4GeomTestVolPoint( targetSegment.GetPoint(i), -1 ) );
463 }
464
465 //
466 // Loop over daughter volumes
467 //
468 const G4LogicalVolume *logical = target->GetLogicalVolume();
469 G4int nDaughter = logical->GetNoDaughters();
470 G4int iDaughter;
471 for( iDaughter=0; iDaughter<nDaughter; ++iDaughter)
472 {
473 const G4VPhysicalVolume *daughter =
474 logical->GetDaughter(iDaughter);
475
476 //
477 // Convert coordinates to daughter local coordinates
478 //
479 const G4RotationMatrix *rotation = daughter->GetFrameRotation();
480 const G4ThreeVector &translation = daughter->GetFrameTranslation();
481
482 G4ThreeVector pLocal = translation + p;
483 G4ThreeVector vLocal = v;
484
485 if (rotation)
486 {
487 pLocal = (*rotation)*pLocal;
488 vLocal = (*rotation)*vLocal;
489 }
490
491 //
492 // Find intersections
493 //
495 daughterSegment( daughter->GetLogicalVolume()->GetSolid(),
496 pLocal, vLocal, logger );
497
498 //
499 // Add them to the list
500 //
501 n = daughterSegment.GetNumberPoints();
502 for(i=0;i<n;++i)
503 {
504 points.push_back( G4GeomTestVolPoint( daughterSegment.GetPoint(i),
505 iDaughter, translation, rotation ) );
506 }
507 }
508
509 //
510 // Now sort the list of intersection points
511 //
512 std::sort( points.begin(), points.end() );
513
514 //
515 // Search for problems:
516 // 1. Overlap daughters will be indicated by intersecting
517 // points that lie within another daughter
518 // 2. Daughter extending outside the mother will be
519 // indicated by intersecting points outside the mother
520 //
521 // The search method is always looking forward when
522 // resolving discrepencies due to roundoff error. Once
523 // one instance of a daughter intersection is analyzed,
524 // it is removed from further consideration
525 //
526 n = points.size();
527
528 //
529 // Set true if this point has been analyzed
530 //
531 std::vector<G4bool> checked( n, false );
532
533 for(i=0;i<n;++i)
534 {
535 if (checked[i]) continue;
536
537 G4int iDaug = points[i].GetDaughterIndex();
538 if (iDaug < 0) continue;
539
540 //
541 // Intersection found. Find matching pair.
542 //
543 G4double iS = points[i].GetDistance();
544 G4int j = i;
545 while(++j<n)
546 {
547 if (iDaug == points[j].GetDaughterIndex()) break;
548 }
549 if (j>=n)
550 {
551 //
552 // Unmatched? This shouldn't happen
553 //
554 logger->SolidProblem( logical->GetDaughter(iDaug)->
555 GetLogicalVolume()->GetSolid(),
556 "Unmatched intersection point",
557 points[i].GetPosition() );
558 continue;
559 }
560
561 checked[j] = true;
562
563 G4double jS = points[j].GetDistance();
564
565 //
566 // Otherwise, we could have a problem
567 //
568 G4int k = i;
569 while(++k<j)
570 {
571 if (checked[k]) continue;
572
573 G4bool kEntering = points[k].Entering();
574 G4double kS = points[k].GetDistance();
575
576
577 //
578 // Problem found: catagorize
579 //
580 G4int kDaug = points[k].GetDaughterIndex();
581 if (kDaug < 0)
582 {
583 //
584 // Ignore small overshoots if they are within tolerance
585 //
586 if (kS-iS < tolerance && kEntering ) continue;
587 if (jS-kS < tolerance && (!kEntering)) continue;
588
589 //
590 // We appear to extend outside the mother volume
591 //
592 std::map<G4long,G4GeomTestOvershootList>::iterator overshoot =
593 overshoots.find(iDaug);
594 if (overshoot == overshoots.end())
595 {
596 std::pair<std::map<G4long,G4GeomTestOvershootList>::iterator,G4bool>
597 result =
598 overshoots.insert( std::pair<const G4long,G4GeomTestOvershootList>
599 (iDaug,G4GeomTestOvershootList(target,iDaug)) );
600 overshoot = result.first;
601 }
602
603 if (kEntering)
604 (*overshoot).second.AddError( points[i].GetPosition(),
605 points[k].GetPosition() );
606 else
607 (*overshoot).second.AddError( points[k].GetPosition(),
608 points[j].GetPosition() );
609 }
610 else
611 {
612 //
613 // Ignore small overlaps if they are within tolerance
614 //
615 if (kS-iS < tolerance && (!kEntering)) continue;
616 if (jS-kS < tolerance && kEntering ) continue;
617
618 //
619 // We appear to overlap with another daughter
620 //
621 G4long key = iDaug < kDaug ?
622 (iDaug*nDaughter + kDaug) : (kDaug*nDaughter + iDaug);
623
624 std::map<G4long,G4GeomTestOverlapList>::iterator overlap =
625 overlaps.find(key);
626 if (overlap == overlaps.end())
627 {
628 std::pair<std::map<G4long,G4GeomTestOverlapList>::iterator,G4bool>
629 result =
630 overlaps.insert( std::pair<const G4long,G4GeomTestOverlapList>
631 (key,G4GeomTestOverlapList(target,iDaug,kDaug)) );
632 overlap = result.first;
633 }
634
635 if (points[k].Entering())
636 (*overlap).second.AddError( points[k].GetPosition(),
637 points[j].GetPosition() );
638 else
639 (*overlap).second.AddError( points[i].GetPosition(),
640 points[k].GetPosition() );
641 }
642 }
643 }
644}
645
646//
647// ReportErrors
648//
650{
651 //
652 // Report overshoots
653 //
654 if (overshoots.empty())
655 logger->NoProblem("GeomTest: no daughter volume extending outside mother detected.");
656 else
657 {
658 std::map<G4long,G4GeomTestOvershootList>::iterator overshoot =
659 overshoots.begin();
660 while( overshoot != overshoots.end() )
661 {
662 logger->OvershootingDaughter( &(*overshoot).second );
663 ++overshoot;
664 }
665 }
666
667 //
668 // Report overlaps
669 //
670 if (overlaps.empty())
671 logger->NoProblem("GeomTest: no overlapping daughters detected.");
672 else
673 {
674 std::map<G4long,G4GeomTestOverlapList>::iterator overlap =
675 overlaps.begin();
676 while( overlap != overlaps.end() )
677 {
678 logger->OverlappingDaughters( &(*overlap).second );
679 ++overlap;
680 }
681 }
682}
683
684//
685// ClearErrors
686//
688{
689 overshoots.clear();
690 overlaps.clear();
691}
@ FatalException
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:64
long G4long
Definition: G4Types.hh:68
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
Hep3Vector unit() const
double dot(const Hep3Vector &) const
void setZ(double)
virtual void OverlappingDaughters(const G4GeomTestOverlapList *)=0
virtual void OvershootingDaughter(const G4GeomTestOvershootList *)=0
virtual void SolidProblem(const G4VSolid *solid, const G4String &message, const G4ThreeVector &point)=0
virtual void NoProblem(const G4String &message)=0
G4int GetNumberPoints() const
const G4GeomTestPoint & GetPoint(G4int i) const
void TestCylinder(G4int nPhi=90, G4int nZ=50, G4int nRho=50, G4double fracZ=0.8, G4double fracRho=0.8, G4bool usePhi=false)
void SetTolerance(G4double tolerance)
std::map< G4long, G4GeomTestOverlapList > overlaps
void TestCartGridY(G4int nz=100, G4int nx=100)
void TestOneLine(const G4ThreeVector &p, const G4ThreeVector &v)
void TestRecursiveLine(const G4ThreeVector &p, const G4ThreeVector &v, G4int sLevel=0, G4int depth=-1)
std::map< G4long, G4GeomTestOvershootList > overshoots
void TestRecursiveCylinder(G4int nPhi=90, G4int nZ=50, G4int nRho=50, G4double fracZ=0.8, G4double fracRho=0.8, G4bool usePhi=false, G4int sLevel=0, G4int depth=-1)
G4GeomTestVolume(const G4VPhysicalVolume *theTarget, G4GeomTestLogger *theLogger, G4double theTolerance=1E-4)
G4double GetTolerance() const
void TestCartGridX(G4int ny=100, G4int nz=100)
void TestRecursiveCartGrid(G4int nx=100, G4int ny=100, G4int nz=100, G4int sLevel=0, G4int depth=-1)
const G4VPhysicalVolume * target
void TestCartGrid(const G4ThreeVector &g1, const G4ThreeVector &g2, const G4ThreeVector &v, G4int n1, G4int n2)
G4GeomTestLogger * logger
void TestCartGridXYZ(G4int nx=100, G4int ny=100, G4int nz=100)
void TestCartGridZ(G4int nx=100, G4int ny=100)
G4VSolid * GetSolid() const
G4int GetNoDaughters() const
G4VPhysicalVolume * GetDaughter(const G4int i) const
virtual G4bool IsReplicated() const =0
G4ThreeVector GetFrameTranslation() const
G4LogicalVolume * GetLogicalVolume() const
const G4RotationMatrix * GetFrameRotation() const
G4double GetYmin() const
Definition: G4VisExtent.hh:91
G4double GetXmax() const
Definition: G4VisExtent.hh:90
G4double GetYmax() const
Definition: G4VisExtent.hh:92
G4double GetZmax() const
Definition: G4VisExtent.hh:94
G4double GetZmin() const
Definition: G4VisExtent.hh:93
G4double GetXmin() const
Definition: G4VisExtent.hh:89
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41