310 lines
9.3 KiB
C++
310 lines
9.3 KiB
C++
//
|
|
// ********************************************************************
|
|
// * 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: G4PVReplica.cc 73250 2013-08-22 13:22:23Z gcosmo $
|
|
//
|
|
//
|
|
// class G4PVReplica Implementation
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
|
|
#include "G4PVReplica.hh"
|
|
#include "G4LogicalVolume.hh"
|
|
|
|
// This static member is thread local. For each thread, it points to the
|
|
// array of G4ReplicaData instances.
|
|
//
|
|
template <class G4ReplicaData> G4ThreadLocal
|
|
G4ReplicaData* G4GeomSplitter<G4ReplicaData>::offset = 0;
|
|
G4PVRManager G4PVReplica::subInstanceManager;
|
|
// This new field helps to use the class G4PVRManager.
|
|
|
|
G4PVReplica::G4PVReplica( const G4String& pName,
|
|
G4LogicalVolume* pLogical,
|
|
G4VPhysicalVolume* pMother,
|
|
const EAxis pAxis,
|
|
const G4int nReplicas,
|
|
const G4double width,
|
|
const G4double offset )
|
|
: G4VPhysicalVolume(0, G4ThreeVector(), pName, pLogical, pMother), fRegularVolsId(0)
|
|
{
|
|
|
|
instanceID = subInstanceManager.CreateSubInstance();
|
|
|
|
G4MT_copyNo = -1;
|
|
|
|
if ((!pMother) || (!pMother->GetLogicalVolume()))
|
|
{
|
|
std::ostringstream message;
|
|
message << "NULL pointer specified as mother volume." << G4endl
|
|
<< "The world volume cannot be sliced or parameterised !";
|
|
G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
|
|
FatalException, message);
|
|
return;
|
|
}
|
|
G4LogicalVolume* motherLogical = pMother->GetLogicalVolume();
|
|
if (pLogical == motherLogical)
|
|
{
|
|
G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
|
|
FatalException, "Cannot place a volume inside itself!");
|
|
return;
|
|
}
|
|
SetMotherLogical(motherLogical);
|
|
motherLogical->AddDaughter(this);
|
|
if (motherLogical->GetNoDaughters() != 1)
|
|
{
|
|
std::ostringstream message;
|
|
message << "Replica or parameterised volume must be the only daughter !"
|
|
<< G4endl
|
|
<< " Mother physical volume: " << pMother->GetName() << G4endl
|
|
<< " Replicated volume: " << pName;
|
|
G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
|
|
FatalException, message);
|
|
return;
|
|
}
|
|
CheckAndSetParameters (pAxis, nReplicas, width, offset);
|
|
}
|
|
|
|
G4PVReplica::G4PVReplica( const G4String& pName,
|
|
G4LogicalVolume* pLogical,
|
|
G4LogicalVolume* pMotherLogical,
|
|
const EAxis pAxis,
|
|
const G4int nReplicas,
|
|
const G4double width,
|
|
const G4double offset )
|
|
: G4VPhysicalVolume(0,G4ThreeVector(),pName,pLogical,0), fRegularVolsId(0)
|
|
{
|
|
|
|
instanceID = subInstanceManager.CreateSubInstance();
|
|
G4MT_copyNo = -1;
|
|
|
|
if (!pMotherLogical)
|
|
{
|
|
std::ostringstream message;
|
|
message << "NULL pointer specified as mother volume for "
|
|
<< pName << ".";
|
|
G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
|
|
FatalException, message);
|
|
return;
|
|
}
|
|
if (pLogical == pMotherLogical)
|
|
{
|
|
G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
|
|
FatalException, "Cannot place a volume inside itself!");
|
|
return;
|
|
}
|
|
pMotherLogical->AddDaughter(this);
|
|
SetMotherLogical(pMotherLogical);
|
|
if (pMotherLogical->GetNoDaughters() != 1)
|
|
{
|
|
std::ostringstream message;
|
|
message << "Replica or parameterised volume must be the only daughter !"
|
|
<< G4endl
|
|
<< " Mother logical volume: " << pMotherLogical->GetName()
|
|
<< G4endl
|
|
<< " Replicated volume: " << pName;
|
|
G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002",
|
|
FatalException, message);
|
|
return;
|
|
}
|
|
CheckAndSetParameters (pAxis, nReplicas, width, offset);
|
|
}
|
|
|
|
void G4PVReplica::CheckAndSetParameters( const EAxis pAxis,
|
|
const G4int nReplicas,
|
|
const G4double width,
|
|
const G4double offset)
|
|
{
|
|
if (nReplicas<1)
|
|
{
|
|
G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002",
|
|
FatalException, "Illegal number of replicas.");
|
|
}
|
|
fnReplicas=nReplicas;
|
|
if (width<0)
|
|
{
|
|
G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002",
|
|
FatalException, "Width must be positive.");
|
|
}
|
|
fwidth = width;
|
|
foffset = offset;
|
|
faxis = pAxis;
|
|
|
|
// Create rotation matrix for phi axis case & check axis is valid
|
|
//
|
|
G4RotationMatrix* pRMat=0;
|
|
switch (faxis)
|
|
{
|
|
case kPhi:
|
|
pRMat=new G4RotationMatrix();
|
|
if (!pRMat)
|
|
{
|
|
G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0003",
|
|
FatalException, "Rotation matrix allocation failed.");
|
|
}
|
|
SetRotation(pRMat);
|
|
break;
|
|
case kRho:
|
|
case kXAxis:
|
|
case kYAxis:
|
|
case kZAxis:
|
|
case kUndefined:
|
|
break;
|
|
default:
|
|
G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002",
|
|
FatalException, "Unknown axis of replication.");
|
|
break;
|
|
}
|
|
}
|
|
|
|
G4PVReplica::G4PVReplica( __void__& a )
|
|
: G4VPhysicalVolume(a), faxis(kZAxis), fnReplicas(0), fwidth(0.),
|
|
foffset(0.), fRegularStructureCode(0), fRegularVolsId(0)
|
|
{
|
|
instanceID = subInstanceManager.CreateSubInstance();
|
|
G4MT_copyNo = -1;
|
|
}
|
|
|
|
G4PVReplica::~G4PVReplica()
|
|
{
|
|
if ( faxis==kPhi )
|
|
{
|
|
delete GetRotation();
|
|
}
|
|
}
|
|
|
|
G4bool G4PVReplica::IsMany() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
G4int G4PVReplica::GetCopyNo() const
|
|
{
|
|
return G4MT_copyNo;
|
|
}
|
|
|
|
void G4PVReplica::SetCopyNo(G4int newCopyNo)
|
|
{
|
|
G4MT_copyNo = newCopyNo;
|
|
}
|
|
|
|
G4bool G4PVReplica::IsReplicated() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
G4bool G4PVReplica::IsParameterised() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
G4VPVParameterisation* G4PVReplica::GetParameterisation() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
G4int G4PVReplica::GetMultiplicity() const
|
|
{
|
|
return fnReplicas;
|
|
}
|
|
|
|
|
|
|
|
void G4PVReplica::GetReplicationData( EAxis& axis,
|
|
G4int& nReplicas,
|
|
G4double& width,
|
|
G4double& offset,
|
|
G4bool& consuming ) const
|
|
{
|
|
axis = faxis;
|
|
nReplicas = fnReplicas;
|
|
width = fwidth;
|
|
offset = foffset;
|
|
consuming = true;
|
|
}
|
|
|
|
G4bool G4PVReplica::IsRegularStructure() const
|
|
{
|
|
return (fRegularVolsId!=0);
|
|
}
|
|
|
|
G4int G4PVReplica::GetRegularStructureId() const
|
|
{
|
|
return fRegularVolsId;
|
|
}
|
|
|
|
void G4PVReplica::SetRegularStructureId( G4int Code )
|
|
{
|
|
fRegularVolsId= Code;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// ********************************************************************
|
|
// GetSubInstanceManager
|
|
//
|
|
// Returns the private data instance manager.
|
|
// *******************************************************************
|
|
const G4PVRManager& G4PVReplica::GetSubInstanceManager()
|
|
{
|
|
return subInstanceManager;
|
|
}
|
|
|
|
|
|
// This method is similar to the constructor. It is used by each worker
|
|
// thread to achieve the same effect as that of the master thread exept
|
|
// to register the new created instance. This method is invoked explicitly.
|
|
// It does not create a new G4PVReplica instance. It only assigns the value
|
|
// for the fields encapsulated by the class G4ReplicaData.
|
|
//
|
|
void G4PVReplica::InitialiseWorker(G4PVReplica *pMasterObject)
|
|
{
|
|
|
|
G4VPhysicalVolume::InitialiseWorker( pMasterObject, 0, G4ThreeVector());
|
|
subInstanceManager.SlaveCopySubInstanceArray();
|
|
G4MT_copyNo = -1;
|
|
CheckAndSetParameters (faxis, fnReplicas, fwidth, foffset);
|
|
}
|
|
|
|
// This method is similar to the destructor. It is used by each worker
|
|
// thread to achieve the partial effect as that of the master thread.
|
|
// For G4PVReplica instances, it destories the rotation matrix.
|
|
//
|
|
void G4PVReplica::TerminateWorker(G4PVReplica* /*pMasterObject*/)
|
|
{
|
|
if ( faxis==kPhi )
|
|
{
|
|
delete GetRotation();
|
|
}
|
|
}
|
|
|
|
|
|
|