// // ******************************************************************** // * 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: testExitNormalNav.cc,v 1.7 2006/06/29 18:58:25 gunter Exp $ // GEANT4 tag $Name: geant4-09-04-ref-00 $ // // Testing the product of Exit Normal of the Navigator for // simple hierarchial geometry. // ( replicas, parameterised volumes currently not included ) // // First version: J. Apostolakis, 18th June 2002 #include #include "ApproxEqual.hh" // Global defs #include "globals.hh" #include "G4LogicalVolume.hh" #include "G4VPhysicalVolume.hh" #include "G4PVPlacement.hh" // #include "G4PVParameterised.hh" // #include "G4VPVParameterisation.hh" #include "G4Box.hh" #include "G4GeometryManager.hh" #include "G4RotationMatrix.hh" #include "G4ThreeVector.hh" // Build simple geometry: // 6 small cubes inside a slab (all G4Boxes) // 3 slabs are positioned inside the world cuboid G4VPhysicalVolume* BuildGeometry() { // Rotations in X G4RotationMatrix *prot90d_X, *prot180d_X, *prot270d_X; prot90d_X = new G4RotationMatrix(); prot180d_X = new G4RotationMatrix(); prot270d_X = new G4RotationMatrix(); prot90d_X->rotateX(pi*0.5); prot180d_X->rotateX(pi); prot270d_X->rotateX(pi*1.5); // Rotations in Y G4RotationMatrix *prot90d_Y, *prot180d_Y, *prot270d_Y; prot90d_Y = new G4RotationMatrix(); prot180d_Y = new G4RotationMatrix(); prot270d_Y = new G4RotationMatrix(); prot90d_Y->rotateY(pi*0.5); prot180d_Y->rotateY(pi); prot270d_Y->rotateY(pi*1.5); // Rotations in Z G4RotationMatrix *prot90d_Z, *prot180d_Z, *prot270d_Z; prot90d_Z = new G4RotationMatrix(); prot180d_Z = new G4RotationMatrix(); prot270d_Z = new G4RotationMatrix(); prot90d_Z->rotateZ(pi*0.5); prot180d_Z->rotateZ(pi); prot270d_Z->rotateZ(-pi*0.5); // Solids G4Box *myBigBox= new G4Box("BigBox-World",200.*cm,200.*cm,200.*cm); G4Box *Slab= new G4Box("slab",17.5*cm,10.*cm,7.5*cm); G4Box *inCube10= new G4Box("Cube ten",5.*cm,5.*cm,5.*cm); G4Box *smallCube= new G4Box("Small cube", 0.5*cm, 0.5*cm, 0.5*cm); // World G4LogicalVolume *worldLog=new G4LogicalVolume(myBigBox,0, "WorldLV",0,0,0); // Logical with no material,field, // sensitive detector or user limits G4PVPlacement *worldPhys=new G4PVPlacement(0,G4ThreeVector(0,0,0), "WorldPV",worldLog, 0,false,0); // Note: no mother pointer set // Slab volume G4LogicalVolume *slabLog=new G4LogicalVolume(Slab, 0, "Slab-logV"); // Inner volume G4LogicalVolume *boxLog= new G4LogicalVolume(inCube10, 0, "Cube10-logV"); // Smallest cube volume G4LogicalVolume *smallLog= new G4LogicalVolume(smallCube, 0, "smallCube1-lV"); // Place small cubes inside Cube ten new G4PVPlacement(prot90d_Y, G4ThreeVector( -4.5*cm, 0.0, 0.0), smallLog, "smallBackX", boxLog, false, 0); new G4PVPlacement(prot180d_Y, G4ThreeVector( 4.5*cm, 0.0, 0.0), smallLog, "smallFrontX", boxLog, false, 1); new G4PVPlacement(prot90d_Z, G4ThreeVector( 0.0, -4.5*cm, 0.0), smallLog, "smallBackY", boxLog, false, 2); new G4PVPlacement(prot90d_X, G4ThreeVector( 0.0, 4.5*cm, 0.0), smallLog, "smallFrontY", boxLog, false, 3); // Fill the slab with inner volumes // G4ThreeVector centerPositionFirst(12.5*cm,-5*cm,0.0); new G4PVPlacement(prot90d_Y, centerPositionFirst, boxLog, "Lower Front", slabLog, false, 0); G4ThreeVector centerPositionSecond(12.5*cm, 5*cm,0.0); new G4PVPlacement(prot180d_Z, centerPositionSecond, boxLog, "Upper Front", slabLog, false, 1); G4ThreeVector centerPositionThird(-12.5*cm, 5*cm,0.0); new G4PVPlacement(prot270d_X, centerPositionThird, boxLog, "Upper Back", slabLog, false, 2); G4ThreeVector centerPositionFourth(-12.0*cm, -5*cm,0.0); new G4PVPlacement(prot180d_Z, centerPositionFourth, boxLog, "Lower Back", slabLog, false, 3); G4ThreeVector centerPositionFifth(-2.5*cm, 5*cm,0.0); new G4PVPlacement(prot90d_Y, centerPositionFifth, boxLog, "Upper Mid-Back", slabLog, false, 4); G4ThreeVector centerPositionSixth( 2.5*cm, -5*cm,0.0); new G4PVPlacement(prot90d_X, centerPositionSixth, boxLog, "Lower Mid-Front", slabLog, false, 5); // Placement of Slabs in World Volume // G4ThreeVector slabPositionOne( -27.5*cm, 0.0,0.0); new G4PVPlacement(prot180d_Y, slabPositionOne, "Back-Slab1", slabLog, worldPhys, false, 1); G4ThreeVector slabPositionTwo( 0.0, 0.0, 0.0); new G4PVPlacement(prot90d_Z, slabPositionTwo, "Upright-Middle-Slab2", slabLog, worldPhys, false, 2); G4ThreeVector slabPositionThree( 27.5*cm, 0.0, 0.0); new G4PVPlacement(prot180d_Z, slabPositionThree, "Front-Slab3", slabLog, worldPhys, false, 3); return worldPhys; } // // Test LocateGlobalPointAndSetup // G4bool testG4Navigator1(G4VPhysicalVolume *pTopNode) { MyNavigator myNav; G4VPhysicalVolume *located; myNav.SetWorldVolume(pTopNode); assert(!myNav.LocateGlobalPointAndSetup(G4ThreeVector(1000*cm,0,0),0,false)); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(1800.0*mm,0,0),0,false); assert(located->GetName()=="WorldPV"); assert(!myNav.LocateGlobalPointAndSetup(G4ThreeVector(1000.*cm,0,0))); return true; // Can add more location checks here, like the old ones below. // Check relative search that causes backup one level and then search down: // Nonrel' finds Target 3, then rel' with point in Target 5 finds Target 5 located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(15.*cm,0,-5.*cm),0,false); assert(located->GetName()=="Upper Front"); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(0,-15.*cm,20.*cm)); assert(located->GetName()=="Target 5"); assert(ApproxEqual(myNav.CurrentLocalCoordinate(),G4ThreeVector(0,0,10))); // Check that outside point causes stack to unwind assert(!myNav.LocateGlobalPointAndSetup(G4ThreeVector(kInfinity,0,0))); return true; } int verbose= 1; // // Test Stepping // G4bool testExitNormal(G4VPhysicalVolume *pTopNode, G4ThreeVector initialPoint, G4ThreeVector direction, G4ThreeVector expectedExitNorm) { MyNavigator myNav; G4VPhysicalVolume *located; G4double Step,physStep,safety; myNav.SetWorldVolume(pTopNode); // // Test location & Step computation // G4ThreeVector initPoint(initialPoint), newPoint(0,0,0); // G4ThreeVector direction= xHat; G4bool valid; if( verbose ){ G4cout << "Initial step " << G4endl; G4cout << "-Initial Point = " << initPoint << G4endl; } located=myNav.LocateGlobalPointAndSetup(initPoint); assert(located->GetName()=="WorldPV"); if( verbose ) G4cout << "-Located: Location before is " << located->GetName() << G4endl; physStep=kInfinity; Step=myNav.ComputeStep(initPoint, direction, physStep, safety); if( verbose ){ G4cout << "-Moved: Step was = " << Step << " expected " << 5.0 * cm << G4endl; G4cout << " safety= " << safety << G4endl; } assert(ApproxEqual(Step,5.0*cm)); // assert(ApproxEqual(safety,50.0)); assert(safety>=0.0); assert(safety<=50.0); newPoint= initPoint + Step * direction; G4ThreeVector localNormal = myNav.GetLocalExitNormal(&valid); assert(valid); G4ThreeVector globalNormal = myNav.GetLocalToGlobalTransform().TransformAxis(localNormal); assert( globalNormal == expectedExitNorm ); myNav.SetGeometricallyLimitedStep(); located=myNav.LocateGlobalPointAndSetup(initPoint); assert(located->GetName()!="WorldPV"); if( verbose ) G4cout << "-Located: Location is " << located->GetName() << G4endl; // Next Steps G4int istep; for ( istep=0; istep < 15; istep++ ){ initPoint= newPoint; if( verbose ){ G4cout << "Sub step " << istep << G4endl; G4cout << "-Initial Point = " << initPoint << G4endl; G4cout << "-Location before is " << located->GetName() << G4endl; } physStep=kInfinity; Step=myNav.ComputeStep(initPoint, direction, physStep, safety); if( verbose ) G4cout << "-Moved: Step was = " << Step << G4endl; assert( Step <= 10.0*cm); assert(ApproxEqual(safety,0.0)); assert(safety>=0); newPoint= initPoint + Step * direction; G4ThreeVector localNormal = myNav.GetLocalExitNormal(&valid); assert(valid); G4ThreeVector globalNormal = myNav.GetLocalToGlobalTransform().TransformAxis(localNormal); if( 0 ) { // globalNormal != G4ThreeVector(1.0,0.0,0.0) ){ G4cout << " **Problem** with pre-relocation normals: " << G4endl; G4cout << " *Point = " << newPoint << G4endl; G4cout << " *localNorm = " << localNormal << G4endl; G4cout << " *globalNorm = " << globalNormal << G4endl; } // assert( globalNormal == G4ThreeVector(1.0,0.0,0.0) ); myNav.SetGeometricallyLimitedStep(); located=myNav.LocateGlobalPointAndSetup(newPoint); // assert(located->GetName()!="WorldPV"); if( verbose ) G4cout << "-Located: Location after is " << located->GetName() << G4endl; localNormal = myNav.GetLocalExitNormal(&valid); assert(valid); globalNormal = myNav.GetLocalToGlobalTransform().TransformAxis(localNormal); if( verbose ) { G4cout << "Post-relocation normals: " << G4endl; G4cout << " Point = " << newPoint << G4endl; G4cout << " Location after is " << located->GetName() << G4endl; G4cout << " localNorm = " << localNormal << G4endl; G4cout << " globalNorm = " << globalNormal << G4endl; G4cout << " expectedExitNorm = " << expectedExitNorm << G4endl; } // assert( ApproxEqual( globalNormal, expectedExitNorm ) ); } return true; } G4bool testExitNormalNav() { G4VPhysicalVolume *myTopNode; const G4ThreeVector xHat(1,0,0),yHat(0,1,0),zHat(0,0,1); const G4ThreeVector mxHat(-1,0,0),myHat(0,-1,0),mzHat(0,0,-1); G4ThreeVector initPointMinusX(-50.0*cm,0.01*cm,0.); G4ThreeVector initPointPluxX(50.0*cm, -0.01*cm,0.); myTopNode=BuildGeometry(); // Build the geometry G4GeometryManager::GetInstance()->CloseGeometry(false); testG4Navigator1(myTopNode); testExitNormal(myTopNode, initPointMinusX, xHat, xHat); testExitNormal(myTopNode, initPointPluxX, mxHat, mxHat); testExitNormal(myTopNode, G4ThreeVector(-50.0*cm,2.0*cm,0.0), xHat, xHat); testExitNormal(myTopNode, G4ThreeVector(-50.0*cm,-2.0*cm,0.0), xHat, xHat); // Repeat tests but with full voxels G4GeometryManager::GetInstance()->OpenGeometry(); G4GeometryManager::GetInstance()->CloseGeometry(true); testG4Navigator1(myTopNode); testExitNormal(myTopNode, initPointMinusX, xHat, xHat); testExitNormal(myTopNode, initPointPluxX, mxHat, mxHat); testExitNormal(myTopNode, G4ThreeVector(-50.0*cm,2.0*cm,0.0), xHat, xHat); testExitNormal(myTopNode, G4ThreeVector(-50.0*cm,-2.0*cm,0.0), xHat, xHat); G4GeometryManager::GetInstance()->OpenGeometry(); return true; } int main() { assert(testExitNormalNav()); return 0; }