| Geant4 User's Guide For Application Developers Geometry

## 4.1.4 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.

#### 4.1.4.1 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 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.

#### 4.1.4.2 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:

               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.

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

     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:

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

1. the axis of division, and
2. 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 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.

- `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.

      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.

- `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.

About the authors