// // ******************************************************************** // * 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: G4PVDivision.cc,v 1.24 2010/09/06 09:28:24 gcosmo Exp $ // GEANT4 tag $Name: geant4-09-04-ref-00 $ // // class G4PVDivision Implementation file // // 26.05.03 - P.Arce Initial version // -------------------------------------------------------------------- #include "G4PVDivision.hh" #include "G4LogicalVolume.hh" #include "G4VSolid.hh" #include "G4ReflectedSolid.hh" #include "G4ParameterisationBox.hh" #include "G4ParameterisationTubs.hh" #include "G4ParameterisationCons.hh" #include "G4ParameterisationTrd.hh" #include "G4ParameterisationPara.hh" #include "G4ParameterisationPolycone.hh" #include "G4ParameterisationPolyhedra.hh" //-------------------------------------------------------------------------- G4PVDivision::G4PVDivision(const G4String& pName, G4LogicalVolume* pLogical, G4LogicalVolume* pMotherLogical, const EAxis pAxis, const G4int nDivs, const G4double width, const G4double offset ) : G4VPhysicalVolume(0,G4ThreeVector(),pName,pLogical,0), fcopyNo(-1) { if (!pMotherLogical) { G4String message_1 = "NULL pointer specified as mother,\n for volume: " + pName; G4Exception("G4PVDivision::G4PVDivision()", "InvalidSetup", FatalException, message_1); return; } if (pLogical == pMotherLogical) { G4String message_2 = "Cannot place a volume inside itself! Volume: "+ pName; G4Exception("G4PVDivision::G4PVDivision()", "InvalidSetup", FatalException, message_2); } pMotherLogical->AddDaughter(this); SetMotherLogical(pMotherLogical); SetParameterisation(pMotherLogical, pAxis, nDivs, width, offset, DivNDIVandWIDTH); CheckAndSetParameters (pAxis, nDivs, width, offset, DivNDIVandWIDTH, pMotherLogical); } //-------------------------------------------------------------------------- G4PVDivision::G4PVDivision(const G4String& pName, G4LogicalVolume* pLogical, G4LogicalVolume* pMotherLogical, const EAxis pAxis, const G4int nDivs, const G4double offset ) : G4VPhysicalVolume(0,G4ThreeVector(),pName,pLogical,0), fcopyNo(-1) { if (!pMotherLogical) { G4String message_1 = "NULL pointer specified as mother! Volume: " + pName; G4Exception("G4PVDivision::G4PVDivision()", "InvalidSetup", FatalException, message_1); return; } if (pLogical == pMotherLogical) { G4String message_2 = "Cannot place a volume inside itself! Volume: "+ pName; G4Exception("G4PVDivision::G4PVDivision()", "InvalidSetup", FatalException, message_2); } pMotherLogical->AddDaughter(this); SetMotherLogical(pMotherLogical); SetParameterisation(pMotherLogical, pAxis, nDivs, 0., offset, DivNDIV); CheckAndSetParameters (pAxis, nDivs, 0., offset, DivNDIV, pMotherLogical); } //-------------------------------------------------------------------------- G4PVDivision::G4PVDivision(const G4String& pName, G4LogicalVolume* pLogical, G4LogicalVolume* pMotherLogical, const EAxis pAxis, const G4double width, const G4double offset ) : G4VPhysicalVolume(0,G4ThreeVector(),pName,pLogical,0), fcopyNo(-1) { if (!pMotherLogical) { G4String message_1 = "NULL pointer specified as mother! Volume: " + pName; G4Exception("G4PVDivision::G4PVDivision()", "InvalidSetup", FatalException, message_1); return; } if (pLogical == pMotherLogical) { G4String message_2 = "Cannot place a volume inside itself! Volume: "+ pName; G4Exception("G4PVDivision::G4PVDivision()", "InvalidSetup", FatalException, message_2); } pMotherLogical->AddDaughter(this); SetMotherLogical(pMotherLogical); SetParameterisation(pMotherLogical, pAxis, 0, width, offset, DivWIDTH); CheckAndSetParameters (pAxis, 0, width, offset, DivWIDTH, pMotherLogical); } //-------------------------------------------------------------------------- void G4PVDivision::CheckAndSetParameters( const EAxis pAxis, const G4int nDivs, const G4double width, const G4double offset, DivisionType divType, const G4LogicalVolume* pMotherLogical ) { if( divType == DivWIDTH ) { fnReplicas = fparam->GetNoDiv(); } else { fnReplicas = nDivs; } if (fnReplicas < 1 ) { G4Exception("G4PVDivision::G4PVDivision()", "IllegalConstruct", FatalException, "Illegal number of replicas!"); } if( divType != DivNDIV) { fwidth = fparam->GetWidth(); } else { fwidth = width; } if( fwidth < 0 ) { G4Exception("G4PVDivision::G4PVDivision()", "IllegalConstruct", FatalException, "Width must be positive!"); } foffset = offset; fdivAxis = pAxis; //!!!!! axis has to be x/y/z in G4VoxelLimits::GetMinExtent // if( pAxis == kRho || pAxis == kRadial3D || pAxis == kPhi ) { faxis = kZAxis; } else { faxis = pAxis; } // Create rotation matrix: for phi axis it will be changed // in G4VPVParameterisation::ComputeTransformation, for others // it will stay the unity // G4RotationMatrix *pRMat = new G4RotationMatrix(); SetRotation(pRMat); switch (faxis) { case kPhi: break; case kRho: case kXAxis: case kYAxis: case kZAxis: break; default: G4Exception("G4PVDivision::G4PVDivision()", "IllegalConstruct", FatalException, "Unknown axis of replication."); break; } //----- Check that mother solid is of the same type than // daughter solid (otherwise, the corresponding // Parameterisation::ComputeDimension() will not be called) // G4String msolType = pMotherLogical->GetSolid()->GetEntityType(); G4String dsolType = GetLogicalVolume()->GetSolid()->GetEntityType(); if( msolType != dsolType && ( msolType != "G4Trd" || dsolType != "G4Trap" ) ) { G4String message = "Incorrect solid type for division of volume " + GetName() + " It is: " + msolType + ", while it should be: " + dsolType; G4Exception("G4PVDivision::CheckAndSetParameters()", "IllegalConstruct", FatalException, message ); } } //-------------------------------------------------------------------------- G4PVDivision::~G4PVDivision() { delete GetRotation(); } //-------------------------------------------------------------------------- EAxis G4PVDivision::GetDivisionAxis() const { return fdivAxis; } //-------------------------------------------------------------------------- G4bool G4PVDivision::IsParameterised() const { return true; } //-------------------------------------------------------------------------- G4bool G4PVDivision::IsMany() const { return false; } //-------------------------------------------------------------------------- G4int G4PVDivision::GetCopyNo() const { return fcopyNo; } //-------------------------------------------------------------------------- void G4PVDivision::SetCopyNo(G4int newCopyNo) { fcopyNo= newCopyNo; } //-------------------------------------------------------------------------- G4bool G4PVDivision::IsReplicated() const { return true; } //-------------------------------------------------------------------------- G4VPVParameterisation* G4PVDivision::GetParameterisation() const { return fparam; } //-------------------------------------------------------------------------- void G4PVDivision::GetReplicationData(EAxis& axis, G4int& nDivs, G4double& width, G4double& offset, G4bool& consuming ) const { axis=faxis; nDivs=fnReplicas; width=fwidth; offset=foffset; consuming=false; } //-------------------------------------------------------------------------- //TODO: this method should check that the child lv is of the correct type, // else the ComputeDimensions will never be called void G4PVDivision::SetParameterisation( G4LogicalVolume* motherLogical, const EAxis axis, const G4int nDivs, const G4double width, const G4double offset, DivisionType divType ) { // Check that solid is compatible with mother solid and axis of division // CheckSolid( solid, motherSolid ); // G4cout << " Axis " << axis << G4endl; G4VSolid* mSolid = motherLogical->GetSolid(); G4String mSolidType = mSolid->GetEntityType(); // If the solid is a reflected one, update type to its // real constituent solid. // if (mSolidType == "G4ReflectedSolid") { mSolidType = ((G4ReflectedSolid*)mSolid)->GetConstituentMovedSolid() ->GetEntityType(); } // Parameterisation type depend of mother solid type and axis of division // if( mSolidType == "G4Box" ) { switch( axis ) { case kXAxis: fparam = new G4ParameterisationBoxX( axis, nDivs, width, offset, mSolid, divType ); break; case kYAxis: fparam = new G4ParameterisationBoxY( axis, nDivs, width, offset, mSolid, divType ); break; case kZAxis: fparam = new G4ParameterisationBoxZ( axis, nDivs, width, offset, mSolid, divType ); break; default: ErrorInAxis( axis, mSolid ); break; } } else if( mSolidType == "G4Tubs" ) { switch( axis ) { case kRho: fparam = new G4ParameterisationTubsRho( axis, nDivs, width, offset, mSolid, divType ); break; case kPhi: fparam = new G4ParameterisationTubsPhi( axis, nDivs, width, offset, mSolid, divType ); break; case kZAxis: fparam = new G4ParameterisationTubsZ( axis, nDivs, width, offset, mSolid, divType ); break; default: ErrorInAxis( axis, mSolid ); break; } } else if( mSolidType == "G4Cons" ) { switch( axis ) { case kRho: fparam = new G4ParameterisationConsRho( axis, nDivs, width, offset, mSolid, divType ); break; case kPhi: fparam = new G4ParameterisationConsPhi( axis, nDivs, width, offset, mSolid, divType ); break; case kZAxis: fparam = new G4ParameterisationConsZ( axis, nDivs, width, offset, mSolid, divType ); break; default: ErrorInAxis( axis, mSolid ); break; } } else if( mSolidType == "G4Trd" ) { switch( axis ) { case kXAxis: fparam = new G4ParameterisationTrdX( axis, nDivs, width, offset, mSolid, divType ); break; case kYAxis: fparam = new G4ParameterisationTrdY( axis, nDivs, width, offset, mSolid, divType ); break; case kZAxis: fparam = new G4ParameterisationTrdZ( axis, nDivs, width, offset, mSolid, divType ); break; default: ErrorInAxis( axis, mSolid ); break; } } else if( mSolidType == "G4Para" ) { switch( axis ) { case kXAxis: fparam = new G4ParameterisationParaX( axis, nDivs, width, offset, mSolid, divType ); break; case kYAxis: fparam = new G4ParameterisationParaY( axis, nDivs, width, offset, mSolid, divType ); break; case kZAxis: fparam = new G4ParameterisationParaZ( axis, nDivs, width, offset, mSolid, divType ); break; default: ErrorInAxis( axis, mSolid ); break; } } // else if( mSolidType == "G4Trap" ) // { // } else if( mSolidType == "G4Polycone" ) { switch( axis ) { case kRho: fparam = new G4ParameterisationPolyconeRho( axis, nDivs, width, offset, mSolid, divType ); break; case kPhi: fparam = new G4ParameterisationPolyconePhi( axis, nDivs, width, offset, mSolid, divType ); break; case kZAxis: fparam = new G4ParameterisationPolyconeZ( axis, nDivs, width, offset, mSolid, divType ); break; default: ErrorInAxis( axis, mSolid ); break; } } else if( mSolidType == "G4Polyhedra" ) { switch( axis ) { case kRho: fparam = new G4ParameterisationPolyhedraRho( axis, nDivs, width, offset, mSolid, divType ); break; case kPhi: fparam = new G4ParameterisationPolyhedraPhi( axis, nDivs, width, offset, mSolid, divType ); break; case kZAxis: fparam = new G4ParameterisationPolyhedraZ( axis, nDivs, width, offset, mSolid, divType ); break; default: ErrorInAxis( axis, mSolid ); break; } } else { G4cerr << "ERROR - G4PVDivision::SetParameterisation()" << G4endl << " Divisions for " << mSolidType << " not implemented." << G4endl; G4String message = "Solid type not supported: " + mSolidType; G4Exception("G4PVDivision::SetParameterisation()", "IllegalConstruct", FatalException, message); } } //-------------------------------------------------------------------------- void G4PVDivision::ErrorInAxis( EAxis axis, G4VSolid* solid ) { G4String error = "Trying to divide solid " + solid->GetName() + " of type " + solid->GetEntityType() + " along axis "; switch( axis ) { case kXAxis: error += "X."; break; case kYAxis: error += "Y."; break; case kZAxis: error += "Z."; break; case kRho: error += "Rho."; break; case kRadial3D: error += "Radial3D."; break; case kPhi: error += "Phi."; break; default: break; } G4Exception("G4PVDivision::ErrorInAxis()", "IllegalConstruct", FatalException, error); } // The next methods are for specialised repeated volumes // (replicas, parameterised vol.) which are completely regular. // Currently this is not applicable to divisions ( J.A. Nov 2005 ) // ---------------------------------------------------------------------- // IsRegularRepeatedStructure() // G4bool G4PVDivision::IsRegularStructure() const { return false; } // ---------------------------------------------------------------------- // IsRegularRepeatedStructure() // G4int G4PVDivision::GetRegularStructureId() const { return 0; } // This is for specialised repeated volumes (replicas, parameterised vol.)