Physical Volumes
Physical volumes represent the spatial positioning of the
volumes describing the detector elements. Several techniques can be
used. They range from the simple placement of a single copy to the
repeated positioning using either a simple linear formula or a user
specified function.
The simple placement involves the definition of a transformation
matrix for the volume to be positioned. Repeated positioning is
defined using the number of times a volume should be replicated at
a given distance along a given direction. Finally it is possible to
define a parameterised formula to specify the position of multiple
copies of a volume. Details about these methods are given
below.
Note - For geometries which vary between runs and for
which components of the old geometry setup are explicitely
-deleted-, it is required to consider the proper order of deletion
(which is the exact inverse of the actual construction, i.e., first
delete physical volumes and then logical volumes). Deleting a
logical volume does NOT delete its daughter volumes.
It is not necessary to delete the geometry setup at the end of a
job, the system will take care to free the volume and solid stores
at the end of the job. The user has to take care of the deletion of
any additional transformation or rotation matrices allocated
dinamically in his/her own application.
Placements: single positioned copy
In this case, the Physical Volume is created by associating a
Logical Volume with a Rotation Matrix and a Translation vector. The
Rotation Matrix represents the rotation of the reference frame of
the considered volume relatively to its mother volume's reference
frame. The Translation Vector represents the translation of the
current volume in the reference frame of its mother volume.
Transformations including reflections are not allowed.
To create a Placement one must construct it using:
G4PVPlacement( G4RotationMatrix* pRot,
const G4ThreeVector& tlate,
G4LogicalVolume* pCurrentLogical,
const G4String& pName,
G4LogicalVolume* pMotherLogical,
G4bool pMany,
G4int pCopyNo,
G4bool pSurfChk=false )
where:
pRot
Rotation with respect to its mother volume
tlate
Translation with respect to its mother volume
pCurrentLogical
The associated Logical Volume
pName
String identifier for this placement
pMotherLogical
The associated mother volume
pMany
For future use. Can be set to false
pCopyNo
Integer which identifies this placement
pSurfChk
if true activates check for overlaps with existing volumes
Care must be taken because the rotation matrix is not copied by
a G4PVPlacement. So the user must not modify it after
creating a Placement that uses it. However the same rotation matrix
can be re-used for many volumes.
Currently boolean operations are not implemented at the level of
physical volume. So pMany must be false. However, an
alternative implementation of boolean operations exists. In this
approach a solid can be created from the union, intersection or
subtraction of two solids. See
above for an explanation of this.
The mother volume must be specified for all volumes
except the world volume.
An alternative way to specify a Placement utilizes a different
method to place the volume. The solid itself is moved by rotating
and translating it to bring it into the system of coordinates of
the mother volume. This active method can be utilized using
the following constructor:
G4PVPlacement( G4Transform3D solidTransform,
G4LogicalVolume* pCurrentLogical,
const G4String& pName,
G4LogicalVolume* pMotherLogical,
G4bool pMany,
G4int pCopyNo,
G4bool pSurfChk=false )
An alternative method to specify the mother volume is to specify
its placed physical volume. It can be used in either of the above
methods of specifying the placement's position and rotation. The
effect will be exactly the same as for using the mother logical
volume.
Note that a Placement Volume can still represent multiple
detector elements. This can happen if several copies exist of the
mother logical volume. Then different detector elements will belong
to different branches of the tree of the hierarchy of geometrical
volumes.
Repeated volumes
In this case, a single Physical Volume represents multiple copies
of a volume within its mother volume, allowing to save memory. This
is normally done when the volumes to be positioned follow a well
defined rotational or translational symmetry along a Cartesian or
cylindrical coordinate. The Repeated Volumes technique is available
for volumes described by CSG solids.
Replicas:
Replicas are repeated volumes in the case when the
multiple copies of the volume are all identical. The coordinate
axis and the number of replicas need to be specified for the
program to compute at run time the transformation matrix
corresponding to each copy.
G4PVReplica( const G4String& pName,
G4LogicalVolume* pCurrentLogical,
G4LogicalVolume* pMotherLogical, // OR G4VPhysicalVolume*
const EAxis pAxis,
const G4int nReplicas,
const G4double width,
const G4double offset=0 )
where:
pName
String identifier for the replicated volume
pCurrentLogical
The associated Logical Volume
pMotherLogical
The associated mother volume
pAxis
The axis along with the replication is applied
nReplicas
The number of replicated volumes
width
The width of a single replica along the axis of replication
offset
Possible offset associated to mother offset along the axis of
replication
G4PVReplica represents nReplicas volumes
differing only in their positioning, and completely filling
the containing mother volume. Consequently if a
G4PVReplica is 'positioned' inside a given mother it
MUST be the mother's only daughter volume. Replica's
correspond to divisions or slices that completely fill the mother
volume and have no offsets. For Cartesian axes, slices are
considered perpendicular to the axis of replication.
The replica's positions are calculated by means of a linear
formula. Replication may occur along:
Cartesian axes (kXAxis,kYAxis,kZAxis)
The replications, of specified width have coordinates of form
(-width*(nReplicas-1)*0.5+n*width,0,0)
where n=0.. nReplicas-1 for the case of kXAxis,
and are unrotated.
Radial axis (cylindrical polar) (kRho)
The replications are cons/tubs sections, centred on the origin and
are unrotated.
They have radii of width*n+offset to
width*(n+1)+offset where
n=0..nReplicas-1
Phi axis (cylindrical polar) (kPhi)
The replications are phi sections or
wedges, and of cons/tubs form.
They have phi of offset+n*width to
offset+(n+1)*width where
n=0..nReplicas-1
The coordinate system of the replicas is at the centre of each
replica for the cartesian axis. For the radial case, the coordinate
system is unchanged from the mother. For the phi axis, the
new coordinate system is rotated such that the X axis bisects the
angle made by each wedge, and Z remains parallel to the mother's Z
axis.
The solid associated via the replicas' logical volume should
have the dimensions of the first volume created and must be of the
correct symmetry/type, in order to assist in good
visualisation.
ex. For X axis replicas in a box, the solid should be another box
with the dimensions of the replications. (same Y & Z dimensions
as mother box, X dimension = mother's X dimension/nReplicas).
Replicas may be placed inside other replicas, provided the above
rule is observed. Normal placement volumes may be placed inside
replicas, provided that they do not intersect the mother's or any
previous replica's boundaries. Parameterised volumes may not be
placed inside.
Because of these rules, it is not possible to place any other
volume inside a replication in radius.
The world volume cannot act as a replica, therefore it
cannot be sliced.
During tracking, the translation + rotation associated with each
G4PVReplica object is modified according to the currently
'active' replication. The solid is not modified and consequently
has the wrong parameters for the cases of phi and
r replication and for when the cross-section of the mother
is not constant along the replication.
Example:
An example of simple replicated volumes with G4PVReplica.
G4PVReplica repX("Linear Array",
pRepLogical,
pContainingMother,
kXAxis, 5, 10*mm);
G4PVReplica repR("RSlices",
pRepRLogical,
pContainingMother,
kRho, 5, 10*mm, 0);
G4PVReplica repRZ("RZSlices",
pRepRZLogical,
&repR,
kZAxis, 5, 10*mm);
G4PVReplica repRZPhi("RZPhiSlices",
pRepRZPhiLogical,
&repRZ,
kPhi, 4, M_PI*0.5*rad, 0);
RepX is an array of 5 replicas of width 10*mm,
positioned inside and completely filling the volume pointed by
pContainingMother. The mother's X length must be
5*10*mm=50*mm (for example, if the mother's solid were a Box of
half lengths [25,25,25] then the replica's solid must be a box of
half lengths [25,25,5]).
If the containing mother's solid is a tube of radius 50*mm and
half Z length of 25*mm, RepR divides the mother tube into
5 cylinders (hence the solid associated with pRepRLogical
must be a tube of radius 10*mm, and half Z length 25*mm);
repRZ divides it into 5 shorter cylinders (the solid
associated with pRepRZLogical must be a tube of radius
10*mm, and half Z length 5*mm); finally, repRZPhi divides
it into 4 tube segments with full angle of 90 degrees (the solid
associated with pRepRZPhiLogical must be a tube segment of
radius 10*mm, half Z length 5*mm and delta phi of
M_PI*0.5*rad).
No further volumes may be placed inside these replicas. To do so
would result in intersecting boundaries due to the r
replications.
Parameterised Volumes:
Parameterised Volumes are repeated volumes in the case in
which the multiple copies of a volume can be different in size,
solid type, or material. The solid's type, its dimensions, the
material and the transformation matrix can all be parameterised in
function of the copy number, both when a strong symmetry exist and
when it does not. The user implements the desired parameterisation
function and the program computes and updates automatically at run
time the information associated to the Physical Volume.
An example of creating a parameterised volume (by dimension and
position) exists in novice example N02. The implementation is
provided in the two classes ExN02DetectorConstruction and
ExN02ChamberParameterisation.
To create a parameterised volume, one must first create its
logical volume like trackerChamberLV below. Then one must
create his own parameterisation class
(ExN02ChamberParameterisation) and instantiate an object of
this class (chamberParam). We will see how to create the
parameterisation below.
An example of Parameterised volumes.
//------------------------------
// Tracker segments
//------------------------------
// An example of Parameterised volumes
// dummy values for G4Box -- modified by parameterised volume
G4VSolid * solidChamber =
new G4Box("chamberBox", 10.*cm, 10.*cm, 10.*cm);
G4LogicalVolume * trackerChamberLV
= new G4LogicalVolume(solidChamber, Aluminum, "trackerChamberLV");
G4VPVParameterisation * chamberParam
= new ExN02ChamberParameterisation(
6, // NoChambers,
-240.*cm, // Z of centre of first
80*cm, // Z spacing of centres
20*cm, // Width Chamber,
50*cm, // lengthInitial,
trackerSize*2.); // lengthFinal
G4VPhysicalVolume *trackerChamber_phys
= new G4PVParameterised("TrackerChamber_parameterisedPV",
trackerChamberLV, // Its logical volume
logicTracker, // Mother logical volume
kUndefined, // Allow default voxelising -- no axis
6, // Number of chambers
chamberParam); // The parameterisation
// "kUndefined" is the suggested choice, giving 3D voxelisation (i.e. along the three
// cartesian axes, as is applied for placements.
//
// Note: In some cases where volume have clear separation along a single axis,
// this axis (eg kZAxis) can be used to choose (force) optimisation only along
// this axis in geometrical calculations.
// When an axis is given it forces the use of one-dimensional voxelisation.
The general constructor is:
G4PVParameterised( const G4String& pName,
G4LogicalVolume* pCurrentLogical,
G4LogicalVolume* pMotherLogical, // OR G4VPhysicalVolume*
const EAxis pAxis,
const G4int nReplicas,
G4VPVParameterisation* pParam,
G4bool pSurfChk=false )
Note that for a parameterised volume the user must always
specify a mother volume. So the world volume can never be a
parameterised volume, nor it can be sliced. The mother volume can
be specified either as a physical or a logical volume.
pAxis specifies the tracking optimisation algorithm to
apply: if a valid axis (the axis along which the parameterisation
is performed) is specified, a simple one-dimensional voxelisation
algorithm is applied; if "kUndefined" is specified instead, the
default three-dimensional voxelisation algorithm applied for normal
placements will be activated. In the latter case, more voxels will
be generated, therefore a greater amount of memory will be consumed
by the optimisation algorithm.
pSurfChk if true activates a check for
overlaps with existing volumes or paramaterised instances.
The parameterisation mechanism associated to a parameterised
volume is defined in the parameterisation class and its methods.
Every parameterisation must create two methods:
ComputeTransformation defines where one of the copies
is placed,
ComputeDimensions defines the size of one copy, and
a constructor that initializes any member variables that are
required.
An example is ExN02ChamberParameterisation that
parameterises a series of boxes of different sizes
An example of Parameterised boxes of different sizes.
class ExN02ChamberParameterisation : public G4VPVParameterisation
{
...
void ComputeTransformation(const G4int copyNo,
G4VPhysicalVolume *physVol) const;
void ComputeDimensions(G4Box& trackerLayer,
const G4int copyNo,
const G4VPhysicalVolume *physVol) const;
...
}
These methods works as follows:
The ComputeTransformation method is called with a copy
number for the instance of the parameterisation under
consideration. It must compute the transformation for this copy,
and set the physical volume to utilize this transformation:
void ExN02ChamberParameterisation::ComputeTransformation
(const G4int copyNo,G4VPhysicalVolume *physVol) const
{
G4double Zposition= fStartZ + copyNo * fSpacing;
G4ThreeVector origin(0,0,Zposition);
physVol->SetTranslation(origin);
physVol->SetRotation(0);
}
Note that the translation and rotation given in this scheme are
those for the frame of coordinates (the passive method).
They are not for the
active method, in which the
solid is rotated into the mother frame of coordinates.
Similarly the ComputeDimensions method is used to set
the size of that copy.
void ExN02ChamberParameterisation::ComputeDimensions
(G4Box & trackerChamber, const G4int copyNo,
const G4VPhysicalVolume * physVol) const
{
G4double halfLength= fHalfLengthFirst + (copyNo-1) * fHalfLengthIncr;
trackerChamber.SetXHalfLength(halfLength);
trackerChamber.SetYHalfLength(halfLength);
trackerChamber.SetZHalfLength(fHalfWidth);
}
The user must ensure that the type of the first argument of this
method (in this example G4Box &) corresponds to the
type of object the user give to the logical volume of parameterised
physical volume.
More advanced usage allows the user:
to change the type of solid by creating a ComputeSolid
method, or
to change the material of the volume by creating a
ComputeMaterial method. This method can also utilise
information from a parent or other ancestor volume (see the Nested
Parameterisation below.)
for the parameterisation.
Example N07 shows a simple parameterisation by material. A more
complex example is provided in
examples/extended/medical/DICOM, where a phantom grid of
cells is built using a parameterisation by material defined through
a map.
Note
Currently for many cases it is not possible to add
daughter volumes to a parameterised volume. Only parameterised
volumes all of whose solids have the same size are allowed to
contain daughter volumes. When the size or type of solid varies,
adding daughters is not supported.
So the full power of parameterised volumes can be used only for
"leaf" volumes, which contain no other volumes.
Advanced parameterisations for 'nested' parameterised volumes
A new type of parameterisation enables a user to have the
daughter's material also depend on the copy number of the parent
when a parameterised volume (daughter) is located inside another
(parent) repeated volume. The parent volume can be a replica, a
parameterised volume, or a division if the key feature of modifying
its contents is utilised. (Note: a 'nested' parameterisation inside
a placement volume is not supported, because all copies of a
placement volume must be identical at all levels.)
In such a " nested" parameterisation , the user must provide a
ComputeMaterial method that utilises the new argument that
represents the touchable history of the parent volume:
// Sample Parameterisation
class SampleNestedParameterisation : public G4VNestedParameterisation
{
public:
// .. other methods ...
// Mandatory method, required and reason for this class
virtual G4Material* ComputeMaterial(G4VPhysicalVolume *currentVol,
const G4int no_lev,
const G4VTouchable *parentTouch);
private:
G4Material *material1, *material2;
};
The implementation of the method can utilise any information
from a parent or other ancestor volume of its parameterised
physical volume, but typically it will use only the copy
number:
G4Material*
SampleNestedParameterisation::ComputeMaterial(G4VPhysicalVolume *currentVol,
const G4int no_lev,
const G4VTouchable *parentTouchable)
{
G4Material *material=0;
// Get the information about the parent volume
G4int no_parent= parentTouchable->GetReplicaNumber();
G4int no_total= no_parent + no_lev;
// A simple 'checkerboard' pattern of two materials
if( no_total / 2 == 1 ) material= material1;
else material= material2;
// Set the material to the current logical volume
G4LogicalVolume* currentLogVol= currentVol->GetLogicalVolume();
currentLogVol->SetMaterial( material );
return material;
}
Nested parameterisations are suitable for the case of regular,
'voxel' geometries in which a large number of 'equal' volumes are
required, and their only difference is in their material. By
creating two (or more) levels of parameterised physical volumes it
is possible to divide space, while requiring only limited
additional memory for very fine-level optimisation. This provides
fast navigation. Alternative implementations, taking into account
the regular structure of such geometries in navigation are under
study.
Divisions of Volumes
Divisions in Geant4 are implemented as a specialized type of
parameterised volumes.
They serve to divide a volume into identical copies along one of
its axes, providing the possibility to define an offset, and
without the limitation that the daugthers have to fill the mother
volume as it is the case for the replicas. In the case, for
example, of a tube divided along its radial axis, the copies are
not strictly identical, but have increasing radii, although their
widths are constant.
To divide a volume it will be necessary to provide:
the axis of division, and
either
the number of divisions (so that the width of each division
will be automatically calculated), or
the division width (so that the number of divisions will be
automatically calculated to fill as much of the mother as
possible), or
both the number of divisions and the division width (this is
especially designed for the case where the copies do not fully fill
the mother).
An offset can be defined so that the first copy will
start at some distance from the mother wall. The dividing copies
will be then distributed to occupy the rest of the volume.
There are three constructors, corresponding to the three input
possibilities described above:
Giving only the number of divisions:
G4PVDivision( const G4String& pName,
G4LogicalVolume* pCurrentLogical,
G4LogicalVolume* pMotherLogical,
const EAxis pAxis,
const G4int nDivisions,
const G4double offset )
Giving only the division width:
G4PVDivision( const G4String& pName,
G4LogicalVolume* pCurrentLogical,
G4LogicalVolume* pMotherLogical,
const EAxis pAxis,
const G4double width,
const G4double offset )
Giving the number of divisions and the division width:
G4PVDivision( const G4String& pName,
G4LogicalVolume* pCurrentLogical,
G4LogicalVolume* pMotherLogical,
const EAxis pAxis,
const G4int nDivisions,
const G4double width,
const G4double offset )
where:
pName
String identifier for the replicated volume
pCurrentLogical
The associated Logical Volume
pMotherLogical
The associated mother Logical Volume
pAxis
The axis along which the division is applied
nDivisions
The number of divisions
width
The width of a single division along the axis
offset
Possible offset associated to the mother along the axis of division
The parameterisation is calculated automatically using the
values provided in input. Therefore the dimensions of the solid
associated with pCurrentLogical will not be used, but
recomputed through the
G4VParameterisation::ComputeDimension() method.
Since G4VPVParameterisation may have different
ComputeDimension() methods for each solid type, the user
must provide a solid that is of the same type as of the one
associated to the mother volume.
As for any replica, the coordinate system of the divisions is
related to the centre of each division for the cartesian axis. For
the radial axis, the coordinate system is the same of the mother
volume. For the phi axis, the new coordinate system is rotated such
that the X axis bisects the angle made by each wedge, and Z remains
parallel to the mother's Z axis.
As divisions are parameterised volumes with constant dimensions,
they may be placed inside other divisions, except in the case of
divisions along the radial axis.
It is also possible to place other volumes inside a volume where a
division is placed.
The list of volumes that currently support divisioning and the
possible division axis are summarised below:
G4Box
kXAxis, kYAxis, kZAxis
G4Tubs
kRho, kPhi, kZAxis
G4Cons
kRho, kPhi, kZAxis
G4Trd
kXAxis, kYAxis, kZAxis
G4Para
kXAxis, kYAxis, kZAxis
G4Polycone
kRho, kPhi, kZAxis (*)
G4Polyhedra
kRho, kPhi, kZAxis (**)
(*) - G4Polycone:
kZAxis - the number of divisions has to be the same as
solid sections, (i.e. numZPlanes-1), the width will
not be taken into account.
(**) - G4Polyhedra:
kPhi - the number of divisions has to be the same as
solid sides, (i.e. numSides), the width will
not be taken into account.
kZAxis - the number of divisions has to be the same as
solid sections, (i.e. numZPlanes-1), the width will
not be taken into account.
In the case of division along kRho of G4Cons,
G4Polycone, G4Polyhedra, if width is provided, it
is taken as the width at the -Z radius; the width at other
radii will be scaled to this one.
Examples are given below in listings
and
.
An example of a box division along different axes, with or without offset.
G4Box* motherSolid = new G4Box("motherSolid", 0.5*m, 0.5*m, 0.5*m);
G4LogicalVolume* motherLog = new G4LogicalVolume(motherSolid, material, "mother",0,0,0);
G4Para* divSolid = new G4Para("divSolid", 0.512*m, 1.21*m, 1.43*m);
G4LogicalVolume* childLog = new G4LogicalVolume(divSolid, material, "child",0,0,0);
G4PVDivision divBox1("division along X giving nDiv",
childLog, motherLog, kXAxis, 5, 0.);
G4PVDivision divBox2("division along X giving width and offset",
childLog, motherLog, kXAxis, 0.1*m, 0.45*m);
G4PVDivision divBox3("division along X giving nDiv, width and offset",
childLog, motherLog, kXAxis, 3, 0.1*m, 0.5*m);
divBox1 is a division of a box along its X
axis in 5 equal copies. Each copy will have a dimension in meters
of [0.2, 1., 1.].
divBox2 is a division of the same box along its
X axis with a width of 0.1 meters and
an offset of 0.5 meters. As the mother dimension along
X of
1 meter (0.5*m of halflength),
the division will
be sized in total 1 - 0.45 = 0.55 meters. Therefore,
there's space for 5 copies, the first extending from -0.05
to 0.05 meters in the mother's frame and the last from
0.35 to 0.45 meters.
divBox3 is a division of the same box along its
X axis in 3 equal copies of width 0.1
meters and an offset of 0.5 meters.
The first copy will extend from
0. to 0.1 meters in the mother's frame
and the last from 0.2 to 0.3
meters.
An example of division of a polycone.
G4double* zPlanem = new G4double[3];
zPlanem[0]= -1.*m;
zPlanem[1]= -0.25*m;
zPlanem[2]= 1.*m;
G4double* rInnerm = new G4double[3];
rInnerm[0]=0.;
rInnerm[1]=0.1*m;
rInnerm[2]=0.5*m;
G4double* rOuterm = new G4double[3];
rOuterm[0]=0.2*m;
rOuterm[1]=0.4*m;
rOuterm[2]=1.*m;
G4Polycone* motherSolid = new G4Polycone("motherSolid", 20.*deg, 180.*deg,
3, zPlanem, rInnerm, rOuterm);
G4LogicalVolume* motherLog = new G4LogicalVolume(motherSolid, material, "mother",0,0,0);
G4double* zPlaned = new G4double[3];
zPlaned[0]= -3.*m;
zPlaned[1]= -0.*m;
zPlaned[2]= 1.*m;
G4double* rInnerd = new G4double[3];
rInnerd[0]=0.2;
rInnerd[1]=0.4*m;
rInnerd[2]=0.5*m;
G4double* rOuterd = new G4double[3];
rOuterd[0]=0.5*m;
rOuterd[1]=0.8*m;
rOuterd[2]=2.*m;
G4Polycone* divSolid = new G4Polycone("divSolid", 0.*deg, 10.*deg,
3, zPlaned, rInnerd, rOuterd);
G4LogicalVolume* childLog = new G4LogicalVolume(divSolid, material, "child",0,0,0);
G4PVDivision divPconePhiW("division along phi giving width and offset",
childLog, motherLog, kPhi, 30.*deg, 60.*deg);
G4PVDivision divPconeZN("division along Z giving nDiv and offset",
childLog, motherLog, kZAxis, 2, 0.1*m);
divPconePhiW is a division of a polycone along its
phi axis in equal copies of width 30 degrees with an
offset of 60 degrees. As the mother extends from 0 to 180 degrees,
there's space for 4 copies. All the copies have a starting angle of
20 degrees (as for the mother) and a phi extension of 30
degrees. They are rotated around the Z axis by 60 and 30
degrees, so that the first copy will extend from 80 to 110 and the
last from 170 to 200 degrees.
divPconeZN is a division of the same polycone along
its Z axis. As the mother polycone has two sections, it
will be divided in two one-section polycones, the first one
extending from -1 to -0.25 meters, the second from -0.25 to 1
meters. Although specified, the offset will not be used.