Geant4 User's Guide
For Application Developers Geometry |
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.
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 Section 4.1.2.2 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.
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:
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:
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); |
Source listing 4.1.2 An example of simple replicated volumes with G4PVReplica. |
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.
//------------------------------ // 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. |
Source listing 4.1.3 An example of Parameterised volumes. |
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:
An example is ExN02ChamberParameterisation that parameterises a series of 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; ... } |
Source listing 4.1.4 An example of Parameterised boxes of different sizes. |
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:
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:
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:
G4PVDivision( const G4String& pName, G4LogicalVolume* pCurrentLogical, G4LogicalVolume* pMotherLogical, const EAxis pAxis, const G4int nDivisions, const G4double offset )
G4PVDivision( const G4String& pName, G4LogicalVolume* pCurrentLogical, G4LogicalVolume* pMotherLogical, const EAxis pAxis, const G4double width, const G4double offset )
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:
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 4.1.4 and 4.1.5.
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); |
Source listing 4.1.5 An example of a box division along different axes, with or without offset. |
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); |
Source listing 4.1.6 An example of division of a polycone. |