//This file is a part of G4MICE // //G4MICE is free software: you can redistribute it and/or modify //it under the terms of the GNU General Public License as published by //the Free Software Foundation, either version 3 of the License, or //(at your option) any later version. // //G4MICE is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with G4MICE in the doc folder. If not, see //. #include "gtest/gtest.h" #include "Geant4/G4Box.hh" #include "Geant4/G4Tubs.hh" #include "Geant4/G4Trd.hh" #include "Geant4/G4Sphere.hh" #include "Geant4/G4Polycone.hh" #include "Geant4/G4Torus.hh" #include "Geant4/G4EllipticalCone.hh" #include "Geant4/G4UnionSolid.hh" #include "Geant4/G4SubtractionSolid.hh" #include "Geant4/G4IntersectionSolid.hh" #include "Geant4/G4VSolid.hh" #include "Geant4/G4AffineTransform.hh" #include "EngModel/MiceModToG4Solid.hh" #include "Utils/Exception.hh" //MiceModToG4SolidTest //Check that we can build each volume and try to check that we can't get any G4 exceptions //i.e. that we catch all exceptions in G4MICE before G4 can get to them, and hopefully //produce more polite error messages (that, for example, list the module name that saw the //error.) // //TODO: boolean logical volume is not tested - needs external files; I think I would prefer to // rework the way boolean logical volume works... need to think about it // namespace { class MiceModToG4SolidTest : public ::testing::Test { protected: MiceModToG4SolidTest () {} virtual ~MiceModToG4SolidTest() {} virtual void SetUp () {} virtual void TearDown() {} }; TEST_F(MiceModToG4SolidTest, checkDimTest) { MiceModule mod; mod.setProperty("Dimensions", CLHEP::Hep3Vector(1.,1.,0.) ); ASSERT_THROW ( MiceModToG4Solid::checkDim(&mod, 3), MAUS::Exceptions::Exception ); ASSERT_NO_THROW( MiceModToG4Solid::checkDim(&mod, 2) ); } TEST_F(MiceModToG4SolidTest, buildWedgeTest) { MiceModule mod; mod.setProperty("Dimensions",CLHEP::Hep3Vector(1.,2.,3.) ); G4VSolid* sol=NULL; ASSERT_NO_THROW( sol = MiceModToG4Solid::buildWedge(&mod) ); ASSERT_FALSE(sol==NULL); EXPECT_DOUBLE_EQ(((G4Trd*)sol)->GetXHalfLength1(), 0.5); //half length of wedge width at bottom EXPECT_DOUBLE_EQ(((G4Trd*)sol)->GetXHalfLength2(), 0.5); //half length of wedge width at top EXPECT_DOUBLE_EQ(((G4Trd*)sol)->GetYHalfLength1(), 2.0); EXPECT_NEAR (((G4Trd*)sol)->GetYHalfLength2(), 0.0, 1e-9); EXPECT_DOUBLE_EQ(((G4Trd*)sol)->GetZHalfLength (), 1.5); if (sol!=NULL) delete sol; sol=NULL; mod.setProperty("Dimensions",CLHEP::Hep3Vector(0., 1., 1.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildWedge(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(1., 0., 1.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildWedge(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(1., 1., 0.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildWedge(&mod), MAUS::Exceptions::Exception ); } MiceModule trapezoid_module( double aX1, double aX2, double aY1, double aY2, double aZ ) { MiceModule mod; try{ mod.setProperty("Dimensions",CLHEP::Hep3Vector(10.,20.,30.) ); mod.addPropertyDouble( "TrapezoidWidthX1", aX1 ); mod.addPropertyDouble( "TrapezoidWidthX2", aX2 ); mod.addPropertyDouble( "TrapezoidHeightY1", aY1 ); mod.addPropertyDouble( "TrapezoidHeightY2", aY2 ); mod.addPropertyDouble( "TrapezoidLengthZ", aZ ); return mod; } catch( MAUS::Exceptions::Exception exc ){ std::string error = exc.GetMessage(); std::cerr << "Exception in trapezoid_module: " << error << std::endl; throw( MAUS::Exceptions::Exception( MAUS::Exceptions::recoverable, "Error in MiceModToG4Test: " + error + "\'", "trapezoid_module")); } } TEST_F(MiceModToG4SolidTest, buildTrapezoidTest) { // double x1 = 1.0, x2 = 2.0, y1 = 3.0, y2 = 4.0, z = 5.0; MiceModule mod = trapezoid_module( x1, x2, y1, y2, z ); G4VSolid* sol=NULL; ASSERT_NO_THROW( sol = MiceModToG4Solid::buildTrapezoid( &mod ) ); ASSERT_FALSE(sol==NULL); EXPECT_DOUBLE_EQ(((G4Trd*)sol)->GetXHalfLength1(), x1 ); EXPECT_DOUBLE_EQ(((G4Trd*)sol)->GetXHalfLength2(), x2 ); EXPECT_DOUBLE_EQ(((G4Trd*)sol)->GetYHalfLength1(), y1 ); EXPECT_DOUBLE_EQ(((G4Trd*)sol)->GetYHalfLength2(), y2 ); EXPECT_DOUBLE_EQ(((G4Trd*)sol)->GetZHalfLength (), z ); if (sol!=NULL) delete sol; sol=NULL; } TEST_F(MiceModToG4SolidTest, buildBoxTest) { MiceModule mod; mod.setProperty("Dimensions",CLHEP::Hep3Vector(1.,2.,3.) ); G4VSolid* sol=NULL; ASSERT_NO_THROW( sol = MiceModToG4Solid::buildBox(&mod) ); ASSERT_FALSE(sol==NULL); EXPECT_DOUBLE_EQ(((G4Box*)sol)->GetXHalfLength(), 0.5); EXPECT_DOUBLE_EQ(((G4Box*)sol)->GetYHalfLength(), 1.0); EXPECT_DOUBLE_EQ(((G4Box*)sol)->GetZHalfLength(), 1.5); if (sol!=NULL) delete sol; sol=NULL; mod.setProperty("Dimensions",CLHEP::Hep3Vector(0., 1., 1.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildBox(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(1., 0., 1.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildBox(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(1., 1., 0.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildBox(&mod), MAUS::Exceptions::Exception ); } TEST_F(MiceModToG4SolidTest, buildCylinderTest) { MiceModule mod; mod.setProperty("Dimensions",CLHEP::Hep3Vector(1.,2.,-1.) ); G4VSolid* sol=NULL; ASSERT_NO_THROW( sol = MiceModToG4Solid::buildCylinder(&mod) ); ASSERT_FALSE(sol==NULL); EXPECT_NEAR (((G4Tubs*)sol)->GetInnerRadius(), 0.0, 1e-9); EXPECT_DOUBLE_EQ(((G4Tubs*)sol)->GetOuterRadius(), 1.0); EXPECT_DOUBLE_EQ(((G4Tubs*)sol)->GetZHalfLength(), 1.0); if (sol!=NULL) delete sol; sol=NULL; mod.setProperty("Dimensions",CLHEP::Hep3Vector(0., 1., 1.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildCylinder(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(1., 0., 1.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildCylinder(&mod), MAUS::Exceptions::Exception ); } TEST_F(MiceModToG4SolidTest, buildTubeTest) { MiceModule mod; mod.setProperty("Dimensions",CLHEP::Hep3Vector(1.,2.,3.) ); G4VSolid* sol=NULL; ASSERT_NO_THROW( sol = MiceModToG4Solid::buildTube(&mod) ); ASSERT_FALSE(sol==NULL); EXPECT_DOUBLE_EQ(((G4Tubs*)sol)->GetInnerRadius(), 1.0); EXPECT_DOUBLE_EQ(((G4Tubs*)sol)->GetOuterRadius(), 2.0); EXPECT_DOUBLE_EQ(((G4Tubs*)sol)->GetZHalfLength(), 1.5); if (sol!=NULL) delete sol; sol=NULL; //Check we catch errors before G4 throws mod.setProperty("Dimensions",CLHEP::Hep3Vector(2., 1., 1.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildTube(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(0., 1., 1.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildTube(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(1., 0., 1.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildTube(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(1., 1., 0.) ); ASSERT_THROW ( sol = MiceModToG4Solid::buildTube(&mod), MAUS::Exceptions::Exception ); } TEST_F(MiceModToG4SolidTest, buildSphereTest) { MiceModule mod; mod.setProperty("Dimensions",CLHEP::Hep3Vector(1.,2.,-1.) ); G4VSolid* sol=NULL; ASSERT_NO_THROW( sol = MiceModToG4Solid::buildSphere(&mod) ); ASSERT_FALSE(sol==NULL); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetInnerRadius(), 1.0); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetOuterRadius(), 2.0); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetStartPhiAngle(), 0.0); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetDeltaPhiAngle(), 360.0*deg); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetStartThetaAngle(), 0.0); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetDeltaThetaAngle(), 180.0*deg); delete sol; sol=NULL; mod.addPropertyHep3Vector("Phi", CLHEP::Hep3Vector(5.*deg, 10.*deg,-1.)); //radians < 2pi mod.addPropertyHep3Vector("Theta", CLHEP::Hep3Vector(15.*deg,20.*deg,-1.)); //radians < pi ASSERT_NO_THROW( sol = MiceModToG4Solid::buildSphere(&mod) ); ASSERT_FALSE(sol==NULL); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetInnerRadius(), 1.0); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetOuterRadius(), 2.0); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetStartPhiAngle(), 5.*deg); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetDeltaPhiAngle(), 10.*deg); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetStartThetaAngle(), 15.*deg); EXPECT_DOUBLE_EQ(((G4Sphere*)sol)->GetDeltaThetaAngle(), 20.0*deg); delete sol; sol=NULL; //Check we catch errors before G4 throws mod.setProperty("Dimensions",CLHEP::Hep3Vector(2.,1.,-1.) ); ASSERT_THROW( sol = MiceModToG4Solid::buildSphere(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(1.,-1.,-1.) ); ASSERT_THROW( sol = MiceModToG4Solid::buildSphere(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(-1.,1.,-1.) ); ASSERT_THROW( sol = MiceModToG4Solid::buildSphere(&mod), MAUS::Exceptions::Exception ); mod.setProperty("Dimensions",CLHEP::Hep3Vector(1.,2.,-1.) ); //G4 throws if delta angle is negative, otherwise seems ok - but I want to force users to make valid input mod.addPropertyHep3Vector("Phi", CLHEP::Hep3Vector(100.*deg, -10.*deg,-1.)); ASSERT_THROW( sol = MiceModToG4Solid::buildSphere(&mod), MAUS::Exceptions::Exception ); mod.addPropertyHep3Vector("Phi", CLHEP::Hep3Vector(500.*deg, 10.*deg,-1.)); ASSERT_THROW( sol = MiceModToG4Solid::buildSphere(&mod), MAUS::Exceptions::Exception ); mod.addPropertyHep3Vector("Phi", CLHEP::Hep3Vector(5.*deg, 500.*deg,-1.)); ASSERT_THROW( sol = MiceModToG4Solid::buildSphere(&mod), MAUS::Exceptions::Exception ); mod.addPropertyHep3Vector("Phi", CLHEP::Hep3Vector(5.*deg, 10.*deg,-1.)); mod.addPropertyHep3Vector("Theta", CLHEP::Hep3Vector(100.*deg, -10.*deg,-1.)); ASSERT_THROW( sol = MiceModToG4Solid::buildSphere(&mod), MAUS::Exceptions::Exception ); mod.addPropertyHep3Vector("Theta", CLHEP::Hep3Vector(500.*deg, 10.*deg,-1.)); ASSERT_THROW( sol = MiceModToG4Solid::buildSphere(&mod), MAUS::Exceptions::Exception ); mod.addPropertyHep3Vector("Theta", CLHEP::Hep3Vector(5.*deg, 500.*deg,-1.)); ASSERT_THROW( sol = MiceModToG4Solid::buildSphere(&mod), MAUS::Exceptions::Exception ); } TEST_F(MiceModToG4SolidTest, buildPolyconeTest) { MiceModule mod; ASSERT_THROW(MiceModToG4Solid::buildPolycone(&mod), MAUS::Exceptions::Exception); //test properly in polycone.hh } TEST_F(MiceModToG4SolidTest, buildMultipoleTest) { MiceModule mod; ASSERT_THROW(MiceModToG4Solid::buildMultipole(&mod), MAUS::Exceptions::Exception); //test properly in multipole.hh } MiceModule torus_module(double in_r, double out_r, double q_s, double q_e, double r_curv) { MiceModule mod; mod.addPropertyDouble("TorusInnerRadius", in_r); mod.addPropertyDouble("TorusOuterRadius", out_r); mod.addPropertyDouble("TorusAngleStart", q_s); mod.addPropertyDouble("TorusOpeningAngle", q_e); mod.addPropertyDouble("TorusRadiusOfCurvature", r_curv); return mod; } TEST_F(MiceModToG4SolidTest, buildTorusTest) { MiceModule mod = torus_module(0.5, 1.0, 5.*deg, 10.*deg, 2.0); G4Torus* sol=NULL; ASSERT_NO_THROW(sol = (G4Torus*)MiceModToG4Solid::buildTorus(&mod)); ASSERT_FALSE(sol==NULL); EXPECT_DOUBLE_EQ(sol->GetRmin(), 0.5 ); EXPECT_DOUBLE_EQ(sol->GetRmax(), 1.0 ); EXPECT_DOUBLE_EQ(sol->GetRtor(), 2.0 ); EXPECT_DOUBLE_EQ(sol->GetSPhi(), 5.*deg ); EXPECT_DOUBLE_EQ(sol->GetDPhi(), 10.*deg ); MiceModule mod1 = torus_module(1.5, 1.0, 5.*deg, 10.*deg, 2.0); ASSERT_THROW(sol = (G4Torus*)MiceModToG4Solid::buildTorus(&mod1), MAUS::Exceptions::Exception); MiceModule mod2 = torus_module(-0.1, 1.0, 5.*deg, 10.*deg, 2.0); ASSERT_THROW(sol = (G4Torus*)MiceModToG4Solid::buildTorus(&mod2), MAUS::Exceptions::Exception); MiceModule mod3 = torus_module(0.5, 3.0, 5.*deg, 10.*deg, 2.0); ASSERT_THROW(sol = (G4Torus*)MiceModToG4Solid::buildTorus(&mod3), MAUS::Exceptions::Exception); MiceModule mod4 = torus_module(0.5, 0.25, 5.*deg, 10.*deg, 2.0); ASSERT_THROW(sol = (G4Torus*)MiceModToG4Solid::buildTorus(&mod4), MAUS::Exceptions::Exception); MiceModule mod5 = torus_module(0.5, 1.0, -1.*deg, 10.*deg, 2.0); ASSERT_THROW(sol = (G4Torus*)MiceModToG4Solid::buildTorus(&mod5), MAUS::Exceptions::Exception); MiceModule mod6 = torus_module(0.5, 1.0, 361.*deg, 10.*deg, 2.0); ASSERT_THROW(sol = (G4Torus*)MiceModToG4Solid::buildTorus(&mod6), MAUS::Exceptions::Exception); MiceModule mod7 = torus_module(0.5, 1.0, 5.*deg, -1.*deg, 2.0); ASSERT_THROW(sol = (G4Torus*)MiceModToG4Solid::buildTorus(&mod7), MAUS::Exceptions::Exception); MiceModule mod8 = torus_module(0.5, 1.0, 5.*deg, 361.*deg, 2.0); ASSERT_THROW(sol = (G4Torus*)MiceModToG4Solid::buildTorus(&mod8), MAUS::Exceptions::Exception); } TEST_F(MiceModToG4SolidTest, buildEllipticalConeTest) { MiceModule mod; mod.addPropertyDouble("ZCut", 1.0) ; mod.setProperty("Dimensions",CLHEP::Hep3Vector(2.0, 3.0, 4.0)); G4EllipticalCone* sol=NULL; ASSERT_NO_THROW(sol = (G4EllipticalCone*)MiceModToG4Solid::buildEllipticalCone(&mod)); ASSERT_FALSE(sol==NULL); EXPECT_DOUBLE_EQ(sol->GetZTopCut(), 1.0); EXPECT_DOUBLE_EQ(sol->GetSemiAxisMax(), 3.0/4.0); MiceModule mod2; mod2.addPropertyDouble("ZCut", -1.0) ; mod2.setProperty("Dimensions",CLHEP::Hep3Vector(2.0, 3.0, 4.0)); ASSERT_THROW(sol = (G4EllipticalCone*)MiceModToG4Solid::buildEllipticalCone(&mod2), MAUS::Exceptions::Exception); MiceModule mod3; mod3.setProperty("Dimensions",CLHEP::Hep3Vector(-1.0, 3.0, 4.0)); ASSERT_THROW(sol = (G4EllipticalCone*)MiceModToG4Solid::buildEllipticalCone(&mod2), MAUS::Exceptions::Exception); mod3.setProperty("Dimensions",CLHEP::Hep3Vector(1.0, -3.0, 4.0)); ASSERT_THROW(sol = (G4EllipticalCone*)MiceModToG4Solid::buildEllipticalCone(&mod2), MAUS::Exceptions::Exception); mod3.setProperty("Dimensions",CLHEP::Hep3Vector(1.0, 3.0, -4.0)); ASSERT_THROW(sol = (G4EllipticalCone*)MiceModToG4Solid::buildEllipticalCone(&mod2), MAUS::Exceptions::Exception); } };