<!-- ******************************************************** -->
<!--                                                          -->
<!--  [History]                                               -->
<!--    Converted to DocBook: Katsuya Amako, Aug-2006         -->
<!--    Changed by: Gabriele Cosmo, 18-Apr-2005               -->
<!--                                                          -->
<!-- ******************************************************** -->


<!-- ******************* Section (Level#2) ****************** -->
<sect2 id="sect.Geom.PhysVol">
<title>
Physical Volumes
</title>

<para>
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.
</para>

<para>
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.
</para>

<para>
<emphasis role="bold">Note</emphasis> - 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.
</para>

<para>
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.
</para>

<!-- ******************* Section (Level#3) ****************** -->
<sect3 id="sect.Geom.PhysVol.PlaceSingle">
<title>
Placements: single positioned copy
</title>

<para>
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.
</para>

<para>
Transformations including reflections are not allowed.
</para>

<para>
To create a Placement one must construct it using:

<informalexample>
<programlisting>
    G4PVPlacement(       G4RotationMatrix*  pRot,
                   const G4ThreeVector&amp;     tlate,
                         G4LogicalVolume*   pCurrentLogical,
                   const G4String&amp;          pName,
                         G4LogicalVolume*   pMotherLogical,
                         G4bool             pMany,
                         G4int              pCopyNo,
                         G4bool             pSurfChk=false )
</programlisting>
</informalexample>

where:

<informaltable>
<tgroup cols="2">
<tbody>
<row>
  <entry>
    <literal>pRot</literal>
  </entry>
  <entry>
    Rotation with respect to its mother volume
  </entry>
</row>
<row>
  <entry>
    <literal>tlate</literal>
  </entry>
  <entry>
    Translation with respect to its mother volume
  </entry>
</row>
<row>
  <entry>
    <literal>pCurrentLogical</literal>
  </entry>
  <entry>
    The associated Logical Volume
  </entry>
</row>
<row>
  <entry>
    <literal>pName</literal>
  </entry>
  <entry>
    String identifier for this placement
  </entry>
</row>
<row>
  <entry>
    <literal>pMotherLogical</literal>
  </entry>
  <entry>
    The associated mother volume
  </entry>
</row>
<row>
  <entry>
    <literal>pMany</literal>
  </entry>
  <entry>
    For future use. Can be set to false
  </entry>
</row>
<row>
  <entry>
    <literal>pCopyNo</literal>
  </entry>
  <entry>
    Integer which identifies this placement
  </entry>
</row>
<row>
  <entry>
    <literal>pSurfChk</literal>
  </entry>
  <entry>
    if true activates check for overlaps with existing volumes
  </entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>

<para>
Care must be taken because the rotation matrix is not copied by
a <literal>G4PVPlacement</literal>. 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.
</para>

<para>
Currently boolean operations are not implemented at the level of
physical volume. So <literal>pMany</literal> 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  <xref linkend="sect.Geom.Solids.BoolOp" />
 above for an explanation of this.
</para>

<para>
The mother volume must be specified for all volumes
<emphasis>except</emphasis> the world volume.
</para>

<para>
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 <emphasis>active</emphasis> method can be utilized using
the following constructor:

<informalexample>
<programlisting>
    G4PVPlacement(       G4Transform3D      solidTransform,
                         G4LogicalVolume*   pCurrentLogical,
                   const G4String&amp;          pName,
                         G4LogicalVolume*   pMotherLogical,
                         G4bool             pMany,
                         G4int              pCopyNo,
                         G4bool             pSurfChk=false )
</programlisting>
</informalexample>
</para>

<para>
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.
</para>

<para>
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.
</para>

</sect3>

<!-- ******************* Section (Level#3) ****************** -->
<sect3 id="sect.Geom.PhysVol.RepeatVol">
<title>
Repeated volumes
</title>

<para>
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. 
</para>

<!-- ******* Bridgehead ******* -->
<bridgehead renderas='sect4'>
Replicas:
</bridgehead>

<para>
Replicas are <emphasis>repeated volumes</emphasis> 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.

<informalexample>
<programlisting>
    G4PVReplica( const G4String&amp;          pName,
                       G4LogicalVolume*   pCurrentLogical,
                       G4LogicalVolume*   pMotherLogical, // OR G4VPhysicalVolume*
                 const EAxis              pAxis,
                 const G4int              nReplicas,
                 const G4double           width,
                 const G4double           offset=0 )
</programlisting>
</informalexample>

where:

<informaltable>
<tgroup cols="2">
<tbody>
<row>
  <entry>
    <literal>pName</literal>
  </entry>
  <entry>
    String identifier for the replicated volume
  </entry>
</row>
<row>
  <entry>
    <literal>pCurrentLogical</literal>
  </entry>
  <entry>
    The associated Logical Volume
   </entry>
</row>
<row>
  <entry>
    <literal>pMotherLogical</literal>
  </entry>
  <entry>
    The associated mother volume
  </entry>
</row>
<row>
  <entry>
    <literal>pAxis</literal>
  </entry>
  <entry>
    The axis along with the replication is applied
  </entry>
</row>
<row>
  <entry>
    <literal>nReplicas</literal>
  </entry>
  <entry>
    The number of replicated volumes
  </entry>
</row>
<row>
  <entry>
    <literal>width</literal>
  </entry>
  <entry>
    The width of a single replica along the axis of replication
  </entry>
</row>
<row>
  <entry>
    <literal>offset</literal>
  </entry>
  <entry>
    Possible offset associated to mother offset along the axis of
    replication
  </entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>

<para>
<literal>G4PVReplica</literal> represents <literal>nReplicas</literal> volumes
differing only in their positioning, and completely <emphasis role="bold">filling</emphasis>
the containing mother volume. Consequently if a
<literal>G4PVReplica</literal> is 'positioned' inside a given mother it
<emphasis role="bold">MUST</emphasis> 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.
</para>

<para>
The replica's positions are calculated by means of a linear
formula. Replication may occur along:

<itemizedlist spacing="compact">
  <listitem><para>
    <emphasis>Cartesian axes <literal>(kXAxis,kYAxis,kZAxis)</literal></emphasis>
    <para>
    The replications, of specified width have coordinates of form
    <literal>(-width*(nReplicas-1)*0.5+n*width,0,0)</literal>
    </para>
    <para>
    where <literal>n=0.. nReplicas-1</literal> for the case of <literal>kXAxis</literal>,
    and are unrotated.
    </para>
  </para></listitem>
  <listitem><para>
    <emphasis>Radial axis (cylindrical polar) <literal>(kRho)</literal></emphasis>
    <para>
    The replications are cons/tubs sections, centred on the origin and
    are unrotated.
    </para>
    <para>
    They have radii of <literal>width*n+offset</literal> to
    <literal>width*(n+1)+offset</literal> where
    <literal>n=0..nReplicas-1</literal>
    </para>
  </para></listitem>
  <listitem><para>
    <emphasis>Phi axis (cylindrical polar) <literal>(kPhi)</literal></emphasis>
    <para>
    The replications are <emphasis>phi sections</emphasis> or 
    <emphasis>wedges</emphasis>, and of cons/tubs form.
    </para>
    <para>
    They have <literal>phi</literal> of <literal>offset+n*width</literal> to
    <literal>offset+(n+1)*width</literal> where 
    <literal>n=0..nReplicas-1</literal>
    </para>
  </para></listitem>
</itemizedlist>
</para>

<para>
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 <literal>phi</literal> 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.
</para>

<para>
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.
</para>

<para>
ex. For X axis replicas in a box, the solid should be another box
with the dimensions of the replications. (same Y &amp; Z dimensions
as mother box, X dimension = mother's X dimension/nReplicas).
</para>

<para>
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.
</para>

<para>
Because of these rules, it is not possible to place any other
volume inside a replication in <literal>radius</literal>.
</para>

<para>
The world volume <emphasis>cannot</emphasis> act as a replica, therefore it
cannot be sliced.
</para>

<para>
During tracking, the translation + rotation associated with each
<literal>G4PVReplica</literal> object is modified according to the currently
'active' replication. The solid is not modified and consequently
has the wrong parameters for the cases of <literal>phi</literal> and
<literal>r</literal> replication and for when the cross-section of the mother
is not constant along the replication.
</para>

<para>
Example:

<example id="programlist_Geom.PhysVol_1">
<title>
An example of simple replicated volumes with <literal>G4PVReplica</literal>.
</title>
<programlisting>
           G4PVReplica repX("Linear Array",
                            pRepLogical,
                            pContainingMother,
                            kXAxis, 5, 10*mm);

           G4PVReplica repR("RSlices",
                            pRepRLogical,
                            pContainingMother,
                            kRho, 5, 10*mm, 0);

           G4PVReplica repRZ("RZSlices",
                             pRepRZLogical,
                             &amp;repR,
                             kZAxis, 5, 10*mm);

           G4PVReplica repRZPhi("RZPhiSlices",
                                pRepRZPhiLogical,
                                &amp;repRZ,
                                kPhi, 4, M_PI*0.5*rad, 0);
</programlisting>
</example>
</para>

<para>
<literal>RepX</literal> is an array of 5 replicas of width 10*mm,
positioned inside and completely filling the volume pointed by
<literal>pContainingMother</literal>. 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]).
</para>

<para>
If the containing mother's solid is a tube of radius 50*mm and
half Z length of 25*mm, <literal>RepR</literal> divides the mother tube into
5 cylinders (hence the solid associated with <literal>pRepRLogical</literal>
must be a tube of radius 10*mm, and half Z length 25*mm);
<literal>repRZ</literal> divides it into 5 shorter cylinders (the solid
associated with <literal>pRepRZLogical</literal> must be a tube of radius
10*mm, and half Z length 5*mm); finally, <literal>repRZPhi</literal> divides
it into 4 tube segments with full angle of 90 degrees (the solid
associated with <literal>pRepRZPhiLogical</literal> must be a tube segment of
radius 10*mm, half Z length 5*mm and delta phi of
M_PI*0.5*rad).
</para>

<para>
No further volumes may be placed inside these replicas. To do so
would result in intersecting boundaries due to the <literal>r</literal>
replications.
</para>

<!-- ******* Bridgehead ******* -->
<bridgehead renderas='sect4'>
Parameterised Volumes:
</bridgehead>

<para>
Parameterised Volumes are <emphasis>repeated volumes</emphasis> 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.
</para>

<para>
An example of creating a parameterised volume (by dimension and
position) exists in novice example N02. The implementation is
provided in the two classes <literal>ExN02DetectorConstruction</literal> and
<literal>ExN02ChamberParameterisation</literal>.
</para>

<para>
To create a parameterised volume, one must first create its
logical volume like <literal>trackerChamberLV</literal> below. Then one must
create his own parameterisation class
(<emphasis>ExN02ChamberParameterisation</emphasis>) and instantiate an object of
this class (<literal>chamberParam</literal>). We will see how to create the
parameterisation below.

<example  id="programlist_Geom.PhysVol_2">
<title>
An example of Parameterised volumes.
</title>
<programlisting>
  //------------------------------
  // 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.
</programlisting>
</example>
</para>

<para>
The general constructor is:

<informalexample>
<programlisting>
    G4PVParameterised( const G4String&amp;              pName,
                             G4LogicalVolume*       pCurrentLogical,
                             G4LogicalVolume*       pMotherLogical, // OR G4VPhysicalVolume*
                       const EAxis                  pAxis,
                       const G4int                  nReplicas,
                             G4VPVParameterisation* pParam,
                             G4bool                 pSurfChk=false )
 
</programlisting>
</informalexample>
</para>

<para>
Note that for a parameterised volume the user must always
specify a mother volume. So the world volume can <emphasis>never</emphasis> be a
parameterised volume, nor it can be sliced. The mother volume can
be specified either as a physical or a logical volume.
</para>

<para>
<literal>pAxis</literal> 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.
</para>

<para>
<literal>pSurfChk</literal> if <literal>true</literal> activates a check for
overlaps with existing volumes or paramaterised instances.
</para>

<para>
The parameterisation mechanism associated to a parameterised
volume is defined in the parameterisation class and its methods.
Every parameterisation must create two methods:

<itemizedlist spacing="compact">
  <listitem><para>
    <literal>ComputeTransformation</literal> defines where one of the copies
    is placed,
  </para></listitem>
  <listitem><para>
    <literal>ComputeDimensions</literal> defines the size of one copy, and
  </para></listitem>
  <listitem><para>
    a constructor that initializes any member variables that are
    required.
  </para></listitem>
</itemizedlist>

<para>
An example is <literal>ExN02ChamberParameterisation</literal> that
parameterises a series of boxes of different sizes

<example id="programlist_Geom.PhysVol_3">
<title>
An example of Parameterised boxes of different sizes.
</title>
<programlisting>
 class ExN02ChamberParameterisation : public G4VPVParameterisation
 {
   ...
   void ComputeTransformation(const G4int       copyNo,
                              G4VPhysicalVolume *physVol) const;

   void ComputeDimensions(G4Box&amp;              trackerLayer,
                          const G4int             copyNo,
                          const G4VPhysicalVolume *physVol) const;
   ...
 }
</programlisting>
</example>
</para>

<para>
These methods works as follows:
</para>

<para>
The <literal>ComputeTransformation</literal> 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:

<informalexample>
<programlisting>
 void ExN02ChamberParameterisation::ComputeTransformation
 (const G4int copyNo,G4VPhysicalVolume *physVol) const
 {
   G4double      Zposition= fStartZ + copyNo * fSpacing;
   G4ThreeVector origin(0,0,Zposition);
   physVol-&gt;SetTranslation(origin);
   physVol-&gt;SetRotation(0);
 }
</programlisting>
</informalexample>
</para>

<para>
Note that the translation and rotation given in this scheme are
those for the frame of coordinates (the <emphasis>passive</emphasis> method).
They are <emphasis role="bold">not</emphasis> for the 
<emphasis>active</emphasis> method, in which the
solid is rotated into the mother frame of coordinates.
</para>

<para>
Similarly the <literal>ComputeDimensions</literal> method is used to set
the size of that copy.

<informalexample>
<programlisting>
 void ExN02ChamberParameterisation::ComputeDimensions
 (G4Box &amp; trackerChamber, const G4int copyNo,
  const G4VPhysicalVolume * physVol) const
 {
   G4double  halfLength= fHalfLengthFirst + (copyNo-1) * fHalfLengthIncr;
   trackerChamber.SetXHalfLength(halfLength);
   trackerChamber.SetYHalfLength(halfLength);
   trackerChamber.SetZHalfLength(fHalfWidth);
 }
</programlisting>
</informalexample> 
</para>

<para>
The user must ensure that the type of the first argument of this
method (in this example <literal>G4Box &amp;</literal>) corresponds to the
type of object the user give to the logical volume of parameterised
physical volume.
</para>

<para>
More advanced usage allows the user:

<itemizedlist spacing="compact">
  <listitem><para>
    to change the type of solid by creating a <literal>ComputeSolid</literal>
    method, or
  </para></listitem>
  <listitem><para>
    to change the material of the volume by creating a
    <literal>ComputeMaterial</literal> method. This method can also utilise
    information from a parent or other ancestor volume (see the Nested
    Parameterisation below.)
  </para></listitem>
</itemizedlist>

for the parameterisation.
</para>

<para>
Example N07 shows a simple parameterisation by material. A more
complex example is provided in
<literal>examples/extended/medical/DICOM</literal>, where a phantom grid of
cells is built using a parameterisation by material defined through
a map.
</para>

<note>
<title>Note</title>
<para>
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.
</para>

<para>
So the full power of parameterised volumes can be used only for
"leaf" volumes, which contain no other volumes.
</para>
</note>


<!-- ******* Bridgehead ******* -->
<bridgehead renderas='sect4'>
Advanced parameterisations for 'nested' parameterised volumes
</bridgehead>

<para>
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.)
</para>

<para>
In such a " nested" parameterisation , the user must provide a
<literal>ComputeMaterial</literal> method that utilises the new argument that
represents the touchable history of the parent volume:

<informalexample>
<programlisting>
// 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;  
};
</programlisting>
</informalexample>  
</para>

<para>
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:

<informalexample>
<programlisting>  
 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-&gt;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-&gt;GetLogicalVolume(); 
    currentLogVol-&gt;SetMaterial( material ); 
    return material;
 }
</programlisting>
</informalexample>  
</para>

<para>
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.
</para>

<!-- ******* Bridgehead ******* -->
<bridgehead renderas='sect4'>
Divisions of Volumes
</bridgehead>

<para>
Divisions in Geant4 are implemented as a specialized type of
parameterised volumes.
</para>

<para>
They serve to divide a volume into identical copies along one of
its axes, providing the possibility to define an <emphasis>offset</emphasis>, 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.
</para>

<para>
To divide a volume it will be necessary to provide:

<orderedlist spacing="compact">
  <listitem><para>
    the axis of division, and
  </para></listitem>
  <listitem><para>
    either
    <itemizedlist spacing="compact">
      <listitem><para>
        the number of divisions (so that the width of each division
        will be automatically calculated), or
      </para></listitem>
      <listitem><para>
        the division width (so that the number of divisions will be
        automatically calculated to fill as much of the mother as
        possible), or
      </para></listitem>
      <listitem><para>
        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).
      </para></listitem>
    </itemizedlist>
  </para></listitem>
</orderedlist>
</para>

<para>
An <emphasis>offset</emphasis> 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.
</para>

<para>
There are three constructors, corresponding to the three input
possibilities described above:

<itemizedlist spacing="compact">
  <listitem><para>
    Giving only the number of divisions:

    <informalexample>
    <programlisting>
     G4PVDivision( const G4String&amp; pName,
                         G4LogicalVolume* pCurrentLogical,
                         G4LogicalVolume* pMotherLogical,
                   const EAxis pAxis,
                   const G4int nDivisions,
                   const G4double offset )
    </programlisting>
    </informalexample>
  </para></listitem>
  <listitem><para>
    Giving only the division width:

    <informalexample>
    <programlisting>
     G4PVDivision( const G4String&amp; pName,
                         G4LogicalVolume* pCurrentLogical,
                         G4LogicalVolume* pMotherLogical,
                   const EAxis pAxis,
                   const G4double width,
                   const G4double offset )
    </programlisting>
    </informalexample>
  </para></listitem>
  <listitem><para>
    Giving the number of divisions and the division width:

    <informalexample>
    <programlisting>
     G4PVDivision( const G4String&amp; pName,
                         G4LogicalVolume* pCurrentLogical,
                         G4LogicalVolume* pMotherLogical,
                   const EAxis pAxis,
                   const G4int nDivisions,
                   const G4double width,
                   const G4double offset )
    </programlisting>
    </informalexample>
  </para></listitem>
</itemizedlist>

where:

<informaltable>
<tgroup cols="2">
<tbody>
<row>
  <entry>
    <literal>pName</literal>
  </entry>
  <entry>
    String identifier for the replicated volume
  </entry>
</row>
<row>
  <entry>
    <literal>pCurrentLogical</literal>
  </entry>
  <entry>
    The associated Logical Volume
  </entry>
</row>
<row>
  <entry>
    <literal>pMotherLogical</literal>
  </entry>
  <entry>
    The associated mother Logical Volume
  </entry>
</row>
<row>
  <entry>
    <literal>pAxis</literal>
  </entry>
  <entry>
    The axis along which the division is applied
  </entry>
</row>
<row>
  <entry>
    <literal>nDivisions</literal>
  </entry>
  <entry>
    The number of divisions
  </entry>
</row>
<row>
  <entry>
    <literal>width</literal>
  </entry>
  <entry>
    The width of a single division along the axis
  </entry>
</row>
<row>
  <entry>
    <literal>offset</literal>
  </entry>
  <entry>
    Possible offset associated to the mother along the axis of division
  </entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>

<para>
The parameterisation is calculated automatically using the
values provided in input. Therefore the dimensions of the solid
associated with <literal>pCurrentLogical</literal> will not be used, but
recomputed through the
<literal>G4VParameterisation::ComputeDimension()</literal> method.
</para>

<para>
Since <literal>G4VPVParameterisation</literal> may have different
<literal>ComputeDimension()</literal> 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.
</para>

<para>
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.
</para>

<para>
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.
</para>

<para>
It is also possible to place other volumes inside a volume where a
division is placed.
</para>

<para>
The list of volumes that currently support divisioning and the
possible division axis are summarised below:

<informaltable>
<tgroup cols="2">
<tbody>
<row>
  <entry>
    <literal>G4Box</literal>
  </entry>
  <entry>
    <literal>kXAxis</literal>, <literal>kYAxis</literal>, <literal>kZAxis</literal>
  </entry>
</row>
<row>
  <entry>
    <literal>G4Tubs</literal>
  </entry>
  <entry>
    <literal>kRho</literal>, <literal>kPhi</literal>, <literal>kZAxis</literal>
  </entry>
</row>
<row>
  <entry>
    <literal>G4Cons</literal>
  </entry>
  <entry>
    <literal>kRho</literal>, <literal>kPhi</literal>, <literal>kZAxis</literal>
  </entry>
</row>
<row>
  <entry>
    <literal>G4Trd</literal>
  </entry>
  <entry>
    <literal>kXAxis</literal>, <literal>kYAxis</literal>, <literal>kZAxis</literal>
  </entry>
</row>
<row>
  <entry>
    <literal>G4Para</literal>
  </entry>
  <entry>
    <literal>kXAxis</literal>, <literal>kYAxis</literal>, <literal>kZAxis</literal>
  </entry>
</row>
<row>
  <entry>
    <literal>G4Polycone</literal>
  </entry>
  <entry>
    <literal>kRho</literal>, <literal>kPhi</literal>, <literal>kZAxis</literal> (*)
  </entry>
</row>
<row>
  <entry>
    <literal>G4Polyhedra</literal>
  </entry>
  <entry>
    <literal>kRho</literal>, <literal>kPhi</literal>, <literal>kZAxis</literal> (**)
  </entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>


<para>
(*) - <literal>G4Polycone</literal>:

<itemizedlist spacing="compact">
  <listitem><para>
    <literal>kZAxis</literal> - the number of divisions has to be the same as
    solid sections, (i.e. <literal>numZPlanes-1</literal>), the width will
    <emphasis>not</emphasis> be taken into account.</para></listitem>
</itemizedlist>
</para>

<para>
(**) - <literal>G4Polyhedra</literal>:

<itemizedlist spacing="compact">
  <listitem><para>
    <literal>kPhi</literal> - the number of divisions has to be the same as
    solid sides, (i.e. <literal>numSides</literal>), the width will 
    <emphasis>not</emphasis> be taken into account.
  </para></listitem>
  <listitem><para>
    <literal>kZAxis</literal> - the number of divisions has to be the same as
    solid sections, (i.e. <literal>numZPlanes-1</literal>), the width will
    <emphasis>not</emphasis> be taken into account.
  </para></listitem>
</itemizedlist>
</para>

<para>
In the case of division along <literal>kRho</literal> of <literal>G4Cons</literal>,
<literal>G4Polycone</literal>, <literal>G4Polyhedra</literal>, if width is provided, it
is taken as the width at the <literal>-Z</literal> radius; the width at other
radii will be scaled to this one.
</para>

<para>
Examples are given below in listings 
<xref linkend="programlist_Geom.PhysVol_3" /> and 
<xref linkend="programlist_Geom.PhysVol_4" />.

<example id="programlist_Geom.PhysVol_4">  
<title>
An example of a box division along different axes, with or without offset.
</title>
<programlisting>
 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);
</programlisting>
</example>

<itemizedlist spacing="compact">
  <listitem><para>
    <literal>divBox1</literal> is a division of a box along its <literal>X</literal>
    axis in 5 equal copies. Each copy will have a dimension in meters
    of <literal>[0.2, 1., 1.]</literal>.
  </para></listitem>
  <listitem><para>
    <literal>divBox2</literal> is a division of the same box along its
    <literal>X</literal> axis with a width of <literal>0.1</literal> meters and
    an offset of <literal>0.5</literal> meters. As the mother dimension along 
    <literal>X</literal> of
    <literal>1</literal> meter (<literal>0.5*m</literal> of halflength), 
    the division will
    be sized in total <literal>1 - 0.45 = 0.55</literal> meters. Therefore,
    there's space for 5 copies, the first extending from <literal>-0.05</literal>
    to <literal>0.05</literal> meters in the mother's frame and the last from
    <literal>0.35</literal> to <literal>0.45</literal> meters.
  </para></listitem>
  <listitem><para>
    <literal>divBox3</literal> is a division of the same box along its
    <literal>X</literal> axis in 3 equal copies of width <literal>0.1</literal> 
    meters and an offset of <literal>0.5</literal> meters. 
    The first copy will extend from
    <literal>0.</literal> to <literal>0.1</literal> meters in the mother's frame 
    and the last from <literal>0.2</literal> to <literal>0.3</literal> 
    meters.
  </para></listitem>
</itemizedlist>
</para>

<example id="programlist_Geom.PhysVol_5">
<title>
An example of division of a polycone.
</title>
<programlisting>
  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);
</programlisting>
</example>

<itemizedlist spacing="compact">
  <listitem><para>
    <literal>divPconePhiW</literal> is a division of a polycone along its
    <literal>phi</literal> 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 <literal>phi</literal> extension of 30
    degrees. They are rotated around the <literal>Z</literal> 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.
  </para></listitem>
  <listitem><para>
    <literal>divPconeZN</literal> is a division of the same polycone along
    its <literal>Z</literal> 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.
  </para></listitem>
</itemizedlist>
</para>


</sect3>
</sect2>
