// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // // $Id: G4GeomTestVolume.cc,v 1.6 2007/11/16 09:39:14 gcosmo Exp $ // GEANT4 tag $Name: geant4-09-02-cand-01 $ // // -------------------------------------------------------------------- // GEANT 4 class source file // // G4GeomTestVolume // // Author: D.C.Williams, UCSC (davidw@scipp.ucsc.edu) // -------------------------------------------------------------------- #include "G4GeomTestVolume.hh" #include "G4GeomTestLogger.hh" #include "G4GeomTestVolPoint.hh" #include "G4GeomTestSegment.hh" #include "G4VPhysicalVolume.hh" #include "G4LogicalVolume.hh" #include "G4VSolid.hh" #include #include #include #include // // Constructor // G4GeomTestVolume::G4GeomTestVolume( const G4VPhysicalVolume *theTarget, G4GeomTestLogger *theLogger, G4double theTolerance ) : target(theTarget), logger(theLogger), tolerance(theTolerance), extent(theTarget->GetLogicalVolume()->GetSolid()->GetExtent()) {;} // // Destructor // G4GeomTestVolume::~G4GeomTestVolume() {;} // // Get error tolerance // G4double G4GeomTestVolume::GetTolerance() const { return tolerance; } // // Set error tolerance // void G4GeomTestVolume::SetTolerance(G4double val) { tolerance = val; } // // TestCartGridXYZ // void G4GeomTestVolume::TestCartGridXYZ( G4int nx, G4int ny, G4int nz ) { TestCartGridX( ny, nz ); TestCartGridY( nz, nx ); TestCartGridZ( nx, ny ); } // // TestCartGridX // void G4GeomTestVolume::TestCartGridX( G4int ny, G4int nz ) { TestCartGrid( G4ThreeVector(0,1,0), G4ThreeVector(0,0,1), G4ThreeVector(1,0,0), ny, nz ); } // // TestCartGridY // void G4GeomTestVolume::TestCartGridY( G4int nz, G4int nx ) { TestCartGrid( G4ThreeVector(0,0,1), G4ThreeVector(1,0,0), G4ThreeVector(0,1,0), nz, nx ); } // // TestCartGridZ // void G4GeomTestVolume::TestCartGridZ( G4int nx, G4int ny ) { TestCartGrid( G4ThreeVector(1,0,0), G4ThreeVector(0,1,0), G4ThreeVector(0,0,1), nx, ny ); } // // TestRecursiveCartGrid // void G4GeomTestVolume::TestRecursiveCartGrid( G4int nx, G4int ny, G4int nz, G4int slevel, G4int depth ) { // If reached requested level of depth (i.e. set to 0), exit. // If not depth specified (i.e. set to -1), visit the whole tree. // If requested initial level of depth is not zero, visit from beginning // if (depth == 0) return; if (depth != -1) depth--; if (slevel != 0) slevel--; // // As long as we aren't a replica and we reached the requested // initial level of depth, test ourselves // if ( (!target->IsReplicated()) && (slevel==0) ) { TestCartGridXYZ( nx, ny, nz ); ReportErrors(); } // // Loop over unique daughters // std::set tested; const G4LogicalVolume *logical = target->GetLogicalVolume(); G4int nDaughter = logical->GetNoDaughters(); G4int iDaughter; for( iDaughter=0; iDaughterGetDaughter(iDaughter); const G4LogicalVolume *daughterLogical = daughter->GetLogicalVolume(); // // Skip empty daughters // if (daughterLogical->GetNoDaughters() == 0) continue; // // Tested already? // std::pair::iterator,G4bool> there = tested.insert(daughterLogical); if (!there.second) continue; // // Recurse // G4GeomTestVolume vTest( daughter, logger, tolerance ); vTest.TestRecursiveCartGrid( nx,ny,nz,slevel,depth ); } } // // TestRecursiveCylinder // void G4GeomTestVolume::TestRecursiveCylinder( G4int nPhi, G4int nZ, G4int nRho, G4double fracZ, G4double fracRho, G4bool usePhi, G4int slevel, G4int depth ) { // If reached requested level of depth (i.e. set to 0), exit. // If not depth specified (i.e. set to -1), visit the whole tree. // If requested initial level of depth is not zero, visit from beginning // if (depth == 0) return; if (depth != -1) depth--; if (slevel != 0) slevel--; // // As long as we aren't a replica and we reached the requested // initial level of depth, test ourselves // if ( (!target->IsReplicated()) && (slevel==0) ) { TestCylinder( nPhi, nZ, nRho, fracZ, fracRho, usePhi ); ReportErrors(); } // // Loop over unique daughters // std::set tested; const G4LogicalVolume *logical = target->GetLogicalVolume(); G4int nDaughter = logical->GetNoDaughters(); G4int iDaughter; for( iDaughter=0; iDaughterGetDaughter(iDaughter); const G4LogicalVolume *daughterLogical = daughter->GetLogicalVolume(); // // Skip empty daughters // if (daughterLogical->GetNoDaughters() == 0) continue; // // Tested already? // std::pair::iterator,G4bool> there = tested.insert(daughterLogical); if (!there.second) continue; // // Recurse // G4GeomTestVolume vTest( daughter, logger, tolerance ); vTest.TestRecursiveCylinder( nPhi, nZ, nRho, fracZ, fracRho, usePhi, slevel, depth ); } } // // TestCylinder // void G4GeomTestVolume::TestCylinder( G4int nPhi, G4int nZ, G4int nRho, G4double fracZ, G4double fracRho, G4bool usePhi ) { // // Get size of our volume // G4double xMax = std::max(extent.GetXmax(),-extent.GetXmin()); G4double yMax = std::max(extent.GetYmax(),-extent.GetYmin()); G4double rhoMax = std::sqrt(xMax*xMax + yMax*yMax); G4double zMax = extent.GetZmax(); G4double zMin = extent.GetZmin(); G4double zHalfLength = 0.5*(zMax-zMin); G4double z0 = 0.5*(zMax+zMin); // // Loop over phi // G4double deltaPhi = 2*pi/G4double(nPhi); G4double phi = 0; G4int iPhi = nPhi; if ((iPhi&1) == 0) iPhi++; // Also use odd number phi slices do { G4double cosPhi = std::cos(phi); G4double sinPhi = std::sin(phi); G4ThreeVector vPhi1(sinPhi,-cosPhi,0); // // Loop over rho // G4double rho = rhoMax; G4int iRho = nRho; do { G4ThreeVector p(rho*cosPhi,rho*sinPhi,0); static G4ThreeVector v(0,0,1); TestOneLine( p, v ); if (usePhi) { // // Loop over z // G4double zScale = 1.0; G4int iZ=nZ; do { p.setZ( z0 + zScale*zHalfLength ); TestOneLine(p,vPhi1); p.setZ( z0 - zScale*zHalfLength ); TestOneLine(p,vPhi1); } while( zScale *= fracZ, --iZ ); } } while( rho *= fracRho, --iRho ); // // Loop over z // G4ThreeVector p(0,0,0); G4ThreeVector vPhi2(cosPhi,sinPhi,0); G4double zScale = 1.0; G4int iZ=nZ; do { p.setZ( z0 + zScale*zHalfLength ); TestOneLine(p,vPhi2); p.setZ( z0 - zScale*zHalfLength ); TestOneLine(p,vPhi2); } while( zScale *= fracZ, --iZ ); } while( phi += deltaPhi, --iPhi ); } // // TestCartGrid // void G4GeomTestVolume::TestCartGrid( const G4ThreeVector &theG1, const G4ThreeVector &theG2, const G4ThreeVector &theV, G4int n1, G4int n2 ) { if (n1 <= 0 || n2 <= 0) G4Exception( "G4GeomTestVolume::TestCartGrid()", "WrongArgumentValue", FatalException, "Arguments n1 and n2 must be >= 1" ); G4ThreeVector xMin( extent.GetXmin(), extent.GetYmin(), extent.GetZmin() ); G4ThreeVector xMax( extent.GetXmax(), extent.GetYmax(), extent.GetZmax() ); G4ThreeVector g1(theG1.unit()); G4ThreeVector g2(theG2.unit()); G4ThreeVector v(theV.unit()); G4double gMin1 = g1.dot(xMin); G4double gMax1 = g1.dot(xMax); G4double gMin2 = g2.dot(xMin); G4double gMax2 = g2.dot(xMax); G4double delta1 = (gMax1-gMin1)/G4double(n1); G4double delta2 = (gMax2-gMin2)/G4double(n2); G4int i1, i2; for(i1=0;i1<=n1;++i1) { G4ThreeVector p1 = (gMin1 + G4double(i1)*delta1)*g1; for(i2=0;i2<=n2;++i2) { G4ThreeVector p2 = (gMin2 + G4double(i2)*delta2)*g2; TestOneLine( p1+p2, v ); } } } // // TestRecursiveLine // void G4GeomTestVolume::TestRecursiveLine( const G4ThreeVector& p, const G4ThreeVector& v, G4int slevel, G4int depth ) { // If reached requested level of depth (i.e. set to 0), exit. // If not depth specified (i.e. set to -1), visit the whole tree. // If requested initial level of depth is not zero, visit from beginning // if (depth == 0) return; if (depth != -1) depth--; if (slevel != 0) slevel--; // // As long as we aren't a replica and we reached the requested // initial level of depth, test ourselves // if ( (!target->IsReplicated()) && (slevel==0) ) { TestOneLine( p, v ); ReportErrors(); } // // Loop over unique daughters // std::set tested; const G4LogicalVolume *logical = target->GetLogicalVolume(); G4int nDaughter = logical->GetNoDaughters(); G4int iDaughter; for( iDaughter=0; iDaughterGetDaughter(iDaughter); const G4LogicalVolume *daughterLogical = daughter->GetLogicalVolume(); // // Skip empty daughters // if (daughterLogical->GetNoDaughters() == 0) continue; // // Tested already? // std::pair::iterator,G4bool> there = tested.insert(daughterLogical); if (!there.second) continue; // // Recurse // G4GeomTestVolume vTest( daughter, logger, tolerance ); vTest.TestRecursiveLine( p, v, slevel, depth ); } } // // TestOneLine // // Test geometry consistency along a single line // void G4GeomTestVolume::TestOneLine( const G4ThreeVector &p, const G4ThreeVector &v ) { // // Keep track of intersection points // std::vector points; // // Calculate intersections with the mother volume // G4GeomTestSegment targetSegment( target->GetLogicalVolume()->GetSolid(), p, v, logger ); // // Add them to our list // G4int n = targetSegment.GetNumberPoints(); G4int i; for(i=0;iGetLogicalVolume(); G4int nDaughter = logical->GetNoDaughters(); G4int iDaughter; for( iDaughter=0; iDaughterGetDaughter(iDaughter); // // Convert coordinates to daughter local coordinates // const G4RotationMatrix *rotation = daughter->GetFrameRotation(); const G4ThreeVector &translation = daughter->GetFrameTranslation(); G4ThreeVector pLocal = translation + p; G4ThreeVector vLocal = v; if (rotation) { pLocal = (*rotation)*pLocal; vLocal = (*rotation)*vLocal; } // // Find intersections // G4GeomTestSegment daughterSegment( daughter->GetLogicalVolume()->GetSolid(), pLocal, vLocal, logger ); // // Add them to the list // n = daughterSegment.GetNumberPoints(); for(i=0;i checked( n, false ); for(i=0;i=n) { // // Unmatched? This shouldn't happen // logger->SolidProblem( logical->GetDaughter(iDaug)-> GetLogicalVolume()->GetSolid(), "Unmatched intersection point", points[i].GetPosition() ); continue; } checked[j] = true; G4double jS = points[j].GetDistance(); // // Otherwise, we could have a problem // G4int k = i; while(++k::iterator overshoot = overshoots.find(iDaug); if (overshoot == overshoots.end()) { std::pair::iterator,G4bool> result = overshoots.insert( std::pair (iDaug,G4GeomTestOvershootList(target,iDaug)) ); assert(result.second); overshoot = result.first; } if (kEntering) (*overshoot).second.AddError( points[i].GetPosition(), points[k].GetPosition() ); else (*overshoot).second.AddError( points[k].GetPosition(), points[j].GetPosition() ); } else { // // Ignore small overlaps if they are within tolerance // if (kS-iS < tolerance && (!kEntering)) continue; if (jS-kS < tolerance && kEntering ) continue; // // We appear to overlap with another daughter // G4long key = iDaug < kDaug ? (iDaug*nDaughter + kDaug) : (kDaug*nDaughter + iDaug); std::map::iterator overlap = overlaps.find(key); if (overlap == overlaps.end()) { std::pair::iterator,G4bool> result = overlaps.insert( std::pair (key,G4GeomTestOverlapList(target,iDaug,kDaug)) ); assert(result.second); overlap = result.first; } if (points[k].Entering()) (*overlap).second.AddError( points[k].GetPosition(), points[j].GetPosition() ); else (*overlap).second.AddError( points[i].GetPosition(), points[k].GetPosition() ); } } } } // // ReportErrors // void G4GeomTestVolume::ReportErrors() { // // Report overshoots // if (overshoots.empty()) logger->NoProblem("GeomTest: no daughter volume extending outside mother detected."); else { std::map::iterator overshoot = overshoots.begin(); while( overshoot != overshoots.end() ) { logger->OvershootingDaughter( &(*overshoot).second ); ++overshoot; } } // // Report overlaps // if (overlaps.empty()) logger->NoProblem("GeomTest: no overlapping daughters detected."); else { std::map::iterator overlap = overlaps.begin(); while( overlap != overlaps.end() ) { logger->OverlappingDaughters( &(*overlap).second ); ++overlap; } } } // // ClearErrors // void G4GeomTestVolume::ClearErrors() { overshoots.clear(); overlaps.clear(); }