// // ******************************************************************** // * 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: testG4ParameterisedSolid1.cc,v 1.13 2006/06/29 18:58:43 gunter Exp $ // GEANT4 tag $Name: geant4-09-04-ref-00 $ // // // // Define geometry with parameterised volumes that parameterise solid type // // Test the Navigation in this geometry // (which also include rotations as well as translations). // #include #include "G4ios.hh" #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 "G4Sphere.hh" #include "G4GeometryManager.hh" #include "G4RotationMatrix.hh" #include "G4ThreeVector.hh" // Sample Parameterisation class BoxesAndSpheres : public G4VPVParameterisation { public: BoxesAndSpheres(G4double twistAngle, G4int noBoxes, G4int noSpheres) { fRotationVec= new G4RotationMatrix(); fTwistAngle= twistAngle; fNumBoxes= noBoxes; fNumSpheres= noSpheres; fBox= new G4Box("Test Box",10.,10.,10.); fSphere= new G4Sphere("Test Sphere",0.,1.,0*deg,180*deg,0*deg,90*deg); } virtual ~BoxesAndSpheres() { // delete fRotationVec; // delete fBox; // delete fSphere; } G4double GetTwistAngle() { return fTwistAngle; } void SetTwistAngle(G4double newAngle ) { fTwistAngle= newAngle; } virtual G4VSolid* ComputeSolid(const G4int n, G4VPhysicalVolume*) { G4VSolid* mySolid=0; if( n < fNumBoxes ) { if( n >= 0 ) { mySolid = fBox; }else{ G4Exception(" Your Boxes+Spheres replica number was out of range"); } }else{ if( n < fNumBoxes + fNumSpheres ) { mySolid = fSphere; }else{ G4Exception(" Your Boxes+Spheres replica number was out of range"); } } return mySolid; } virtual void ComputeTransformation(const G4int n, G4VPhysicalVolume* pRep) const { pRep->SetTranslation(G4ThreeVector(n*100*mm,0.,0.)); *fRotationVec = G4RotationMatrix(); // Unit matrix fRotationVec->rotateZ( n * fTwistAngle ); pRep->SetRotation( fRotationVec ); } virtual void ComputeDimensions(G4Box &pBox, const G4int, const G4VPhysicalVolume*) const { if( &pBox != fBox ){ G4cerr << " Got another Box in ComputeDimensions(G4Box, , )" << G4endl; } pBox.SetXHalfLength(10*mm); pBox.SetYHalfLength(10*mm); pBox.SetZHalfLength(10*mm); } virtual void ComputeDimensions(G4Sphere &pSphere, const G4int n, const G4VPhysicalVolume*) const { if( &pSphere != fSphere ) { G4cerr << " Got another sphere in ComputeDimensions(G4Sphere, , )" << G4endl; } G4int nrad= std::min(5, n-fNumBoxes+1); pSphere.SetInsideRadius( nrad * 5. * mm); pSphere.SetOuterRadius ( nrad * 10. * mm); pSphere.SetStartPhiAngle (0.); pSphere.SetDeltaPhiAngle (2*pi); pSphere.SetStartThetaAngle(0); pSphere.SetDeltaThetaAngle(pi); } virtual void ComputeDimensions(G4Tubs &, const G4int , const G4VPhysicalVolume*) const {} virtual void ComputeDimensions(G4Trd &, const G4int, const G4VPhysicalVolume*) const {} virtual void ComputeDimensions(G4Cons &, const G4int , const G4VPhysicalVolume*) const {} virtual void ComputeDimensions(G4Trap &, const G4int , const G4VPhysicalVolume*) const {} virtual void ComputeDimensions(G4Hype &, const G4int , const G4VPhysicalVolume*) const {} virtual void ComputeDimensions(G4Orb &, const G4int , const G4VPhysicalVolume*) const {} virtual void ComputeDimensions(G4Torus &, const G4int , const G4VPhysicalVolume*) const {} virtual void ComputeDimensions(G4Para &, const G4int , const G4VPhysicalVolume*) const {} virtual void ComputeDimensions(G4Polycone &, const G4int , const G4VPhysicalVolume*) const {} virtual void ComputeDimensions(G4Polyhedra &, const G4int , const G4VPhysicalVolume*) const {} private: G4RotationMatrix *fRotationVec; G4double fTwistAngle; G4int fNumBoxes; G4int fNumSpheres; G4Box* fBox; G4Sphere* fSphere; }; G4double angle1= 15.0*deg; // pi/180. ; BoxesAndSpheres myParam(angle1,3,4); // Build simple geometry: // 4 small cubes (G4Boxes) are positioned inside a larger cuboid G4VPhysicalVolume* BuildGeometry() { // The world volume // G4Box *myBigBox= new G4Box ("Big Cube", 1000*mm, 1000*mm, 1000*mm); G4LogicalVolume *worldLog=new G4LogicalVolume(myBigBox,0, "World",0,0,0); // Logical with no material,field, // sensitive detector or user limits G4PVPlacement *worldPhys=new G4PVPlacement(0,G4ThreeVector(0,0,0), "World",worldLog, 0,false,0); // Note: no mother pointer set // A set of boxes G4Box *myBox=new G4Box("cube",10,10,10); G4LogicalVolume *boxLog=new G4LogicalVolume(myBox,0, "Rotating Box",0,0,0); // G4PVParameterised *paramP= new G4PVParameterised("Rotating Block Or Sphere", boxLog, worldPhys, //OR worldLog, kXAxis, 7, &myParam); // Copies 0, 1 & 2 will exist return worldPhys; } // // Test LocateGlobalPointAndSetup // G4bool testG4Navigator1(G4VPhysicalVolume *pTopNode) { MyNavigator myNav; G4VPhysicalVolume *located; myNav.SetWorldVolume(pTopNode); assert(!myNav.LocateGlobalPointAndSetup(G4ThreeVector(kInfinity,0,0),0,false)); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(100,100,100),0,false); assert(located->GetName()=="World"); assert(!myNav.LocateGlobalPointAndSetup(G4ThreeVector(kInfinity,0,0))); // located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(0,-5,-5),0,false); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetCopyNo()== 0); assert(ApproxEqual(myNav.CurrentLocalCoordinate(),G4ThreeVector(0,-5,-5))); G4cout << " Local coords = " << myNav.CurrentLocalCoordinate() << G4endl; located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(100,0,5)); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetCopyNo()== 1); assert(ApproxEqual(myNav.CurrentLocalCoordinate(), G4ThreeVector(0. ,0., 5))); // Check that the rotation is correct // located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(105,0,0)); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetCopyNo()== 1); #if 0 // G4cout << " Local coords = " << myNav.GetCurrentLocalCoordinate() << G4endl; G4ThreeVector ExpectedPosition(5*std::cos(angle1),-5.*std::sin(angle1),0.); G4cout << " Expected = " << ExpectedPosition << G4endl; assert(ApproxEqual(myNav.CurrentLocalCoordinate(),ExpectedPosition )); if(!ApproxEqual(myNav.CurrentLocalCoordinate(),ExpectedPosition )) { G4cout << " Error: The coordinates do not match " << G4endl; } #endif // Check that outside point causes stack to unwind assert(!myNav.LocateGlobalPointAndSetup(G4ThreeVector(kInfinity,0,0))); // Check parameterised volumes // Replication 0 located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(5,0,5)); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Box"); assert(located->GetCopyNo()== 0); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(0,15,15)); assert(located->GetName()=="World"); // Replication 1 located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(105,0,5)); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Box"); assert(located->GetCopyNo()== 1); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(0,0,-17)); assert(located->GetName()=="World"); // Replication 2 located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(205,0,5)); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Box"); assert(located->GetCopyNo()== 2); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(15,15,-18)); assert(located->GetName()=="World"); // Replication 3 // Sphere 1, radii: inner/outer= 5 to 10 located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(307.5,0.0,0.0)); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Sphere"); assert(located->GetCopyNo()== 3); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(315,15,-18)); assert(located->GetName()=="World"); // Replication 4 // Sphere 2, radii: inner/outer= 10 to 20 located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(410.,10.,10.)); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Sphere"); assert(located->GetCopyNo()== 4); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(315,15,-18)); assert(located->GetName()=="World"); // Replication 5 // Sphere 3, radii: inner/outer= 15 to 30 located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(510.0,10.0,10.0)); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Sphere"); assert(located->GetCopyNo()== 5); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(500,35,-10)); assert(located->GetName()=="World"); // Replication 6 // Sphere 4, radii: inner/outer= 20 to 40 located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(622.5,22.5,22.5)); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Sphere"); assert(located->GetCopyNo()== 6); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(600,45,-10)); assert(located->GetName()=="World"); return true; } // // Test Stepping // G4bool testG4Navigator2(G4VPhysicalVolume *pTopNode) { MyNavigator myNav; G4VPhysicalVolume *located; G4double Step,physStep,safety; G4ThreeVector xHat(1,0,0),yHat(0,1,0),zHat(0,0,1); G4ThreeVector mxHat(-1,0,0),myHat(0,-1,0),mzHat(0,0,-1); myNav.SetWorldVolume(pTopNode); // // Test location & Step computation // G4ThreeVector StartPoint(-50*mm,0,-5*mm); located=myNav.LocateGlobalPointAndSetup( StartPoint ); assert(located->GetName()=="World"); physStep=kInfinity; Step=myNav.ComputeStep( StartPoint, mxHat,physStep,safety); // -x dir assert(ApproxEqual(Step,950*mm)); // assert(ApproxEqual(safety,40*mm)); // assert(safety>=0); StartPoint= G4ThreeVector(-15*mm,0,-5*mm); located=myNav.LocateGlobalPointAndSetup( StartPoint ); assert(located->GetName()=="World"); physStep=kInfinity; Step=myNav.ComputeStep( StartPoint,xHat,physStep,safety); // +x dir assert(ApproxEqual(Step,5)); // assert(ApproxEqual(safety,5)); assert(safety>=0); myNav.SetGeometricallyLimitedStep(); G4ThreeVector EndPoint = StartPoint + Step * xHat; located=myNav.LocateGlobalPointAndSetup(EndPoint,0,true); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Box"); assert(located->GetCopyNo()== 0); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(0,0,-40)); assert(located->GetName()=="World"); physStep=kInfinity; Step=myNav.ComputeStep(G4ThreeVector(0,0,-40),zHat,physStep,safety); // +z assert(ApproxEqual(Step,30)); assert(safety>=0); // Now locate the endpoint myNav.SetGeometricallyLimitedStep(); EndPoint = StartPoint + Step * xHat; located=myNav.LocateGlobalPointAndSetup(EndPoint,0,true); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Box"); assert(located->GetCopyNo()== 0); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(0,0, 40)); assert(located->GetName()=="World"); physStep=kInfinity; Step=myNav.ComputeStep(G4ThreeVector(0,0,40),mzHat,physStep,safety); assert(ApproxEqual(Step,30)); // assert(ApproxEqual(safety,5)); assert(safety>=0); // // Test moving through series of volumes // StartPoint= G4ThreeVector(-20,0,0); located=myNav.LocateGlobalPointAndSetup(G4ThreeVector(-20,0,0)); assert(located->GetName()=="World"); // Replication 0 block // physStep=kInfinity; Step=myNav.ComputeStep(StartPoint,xHat,physStep,safety); assert(ApproxEqual(Step,10)); EndPoint= StartPoint + Step * xHat; // Should be -10, 0, 0 assert( ApproxEqual( EndPoint, G4ThreeVector(-10,0,0) ) ); assert(safety<=10); myNav.SetGeometricallyLimitedStep(); located=myNav.LocateGlobalPointAndSetup(EndPoint) ; assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Box"); assert(located->GetCopyNo()== 0); Step=myNav.ComputeStep(EndPoint,xHat,physStep,safety); // +x assert(ApproxEqual(Step,20)); assert(ApproxEqual(safety,0)); myNav.SetGeometricallyLimitedStep(); EndPoint += Step * xHat; // Should be +10, 0, 0 assert(ApproxEqual( EndPoint, G4ThreeVector(10,0,0) )); located=myNav.LocateGlobalPointAndSetup( EndPoint ); assert(located->GetName()=="World"); // Replication 1 block // StartPoint= EndPoint; physStep=kInfinity; Step=myNav.ComputeStep(StartPoint,xHat,physStep,safety); assert(ApproxEqual(Step,90.-10./std::cos(angle1))); EndPoint= StartPoint + Step * xHat; // Should be near 90, 0, 0 assert(safety==0.); myNav.SetGeometricallyLimitedStep(); located=myNav.LocateGlobalPointAndSetup(EndPoint) ; assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Box"); assert(located->GetCopyNo()== 1); StartPoint= EndPoint; physStep=kInfinity; Step=myNav.ComputeStep(StartPoint,xHat,physStep,safety); assert(ApproxEqual(Step,20./std::cos(angle1))); assert(ApproxEqual(safety,0)); myNav.SetGeometricallyLimitedStep(); EndPoint += Step * xHat; // Should be near 110, 0, 0 assert(ApproxEqual(EndPoint,G4ThreeVector(100.+10./std::cos(angle1),0,0))); located=myNav.LocateGlobalPointAndSetup( EndPoint ); assert(located->GetName()=="World"); // Replication 2 block // StartPoint= EndPoint; physStep=kInfinity; Step=myNav.ComputeStep(StartPoint,xHat,physStep,safety); assert(ApproxEqual(Step,100.-10.*(1./std::cos(angle1)+1./std::cos(2.*angle1)))); EndPoint= StartPoint + Step * xHat; // Should near 0, 190, 0 assert(safety<=Step); myNav.SetGeometricallyLimitedStep(); located=myNav.LocateGlobalPointAndSetup(EndPoint); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Box"); assert(located->GetCopyNo()== 2); StartPoint= EndPoint; physStep=kInfinity; Step=myNav.ComputeStep(StartPoint,xHat,physStep,safety); assert(ApproxEqual(Step,20./std::cos(2.*angle1))); assert(ApproxEqual(safety,0)); myNav.SetGeometricallyLimitedStep(); EndPoint += Step * xHat; // Should be near 210, 0, 0 assert(ApproxEqual(EndPoint,G4ThreeVector(200.+10./std::cos(2.*angle1),0,0))); located=myNav.LocateGlobalPointAndSetup( EndPoint ); assert(located->GetName()=="World"); // Replication 3 : sphere #1 // StartPoint= EndPoint; physStep=kInfinity; Step=myNav.ComputeStep(StartPoint,xHat,physStep,safety); assert(ApproxEqual(Step,(100.-10./std::cos(2.*angle1)-10.)*mm)); EndPoint= StartPoint + Step * xHat; // Should be 290, 0, 0 assert(ApproxEqual(EndPoint,G4ThreeVector(290.*mm,0,0))); assert(safety==0.); // Started from a surface myNav.SetGeometricallyLimitedStep(); located=myNav.LocateGlobalPointAndSetup(EndPoint); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Sphere"); assert(located->GetCopyNo()== 3); StartPoint= EndPoint; physStep=kInfinity; Step=myNav.ComputeStep(StartPoint,xHat,physStep,safety); assert(ApproxEqual(Step,5.)); assert(ApproxEqual(safety,0.)); myNav.SetGeometricallyLimitedStep(); EndPoint += Step * xHat; // Should be near 295, 0, 0 assert(ApproxEqual(EndPoint,G4ThreeVector(295*mm,0,0))); // Now Hit inner surface of spherical shell located=myNav.LocateGlobalPointAndSetup( EndPoint ); assert(located->GetName()=="World"); // Cross "empty" inner sphere // StartPoint= EndPoint; physStep=kInfinity; Step=myNav.ComputeStep(StartPoint,xHat,physStep,safety); assert(ApproxEqual(Step,(10.*mm))); EndPoint= StartPoint + Step * xHat; // Should be 290, 0, 0 assert(ApproxEqual(EndPoint,G4ThreeVector(305.*mm,0,0))); assert(ApproxEqual(safety,0.)); // Started from a surface myNav.SetGeometricallyLimitedStep(); located=myNav.LocateGlobalPointAndSetup(EndPoint); assert(located->GetName()=="Rotating Block Or Sphere"); assert(located->GetLogicalVolume()->GetSolid()->GetName()=="Test Sphere"); assert(located->GetCopyNo()== 3); // Now Hit outer surface of spherical shell StartPoint= EndPoint; physStep=kInfinity; Step=myNav.ComputeStep(StartPoint,xHat,physStep,safety); assert(ApproxEqual(Step,5.)); assert(ApproxEqual(safety,0.)); myNav.SetGeometricallyLimitedStep(); EndPoint += Step * xHat; // Should be near 310, 0, 0 assert(ApproxEqual(EndPoint,G4ThreeVector(310*mm,0,0))); located=myNav.LocateGlobalPointAndSetup( EndPoint ); assert(located->GetName()=="World"); // Continue the test later ... return true; } int main() { G4VPhysicalVolume *myTopNode; myTopNode=BuildGeometry(); // Build the geometry G4GeometryManager::GetInstance()->CloseGeometry(false); testG4Navigator1(myTopNode); testG4Navigator2(myTopNode); // Repeat tests but with full voxels G4GeometryManager::GetInstance()->OpenGeometry(); G4GeometryManager::GetInstance()->CloseGeometry(true); testG4Navigator1(myTopNode); testG4Navigator2(myTopNode); G4GeometryManager::GetInstance()->OpenGeometry(); return 0; }