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


<!-- ******************* Section (Level#2) ****************** -->
<sect2 id="sect.Geom.Assemb">
<title>
Creating an Assembly of Volumes
</title>

<para>
<literal>G4AssemblyVolume</literal> is a helper class which allows several
logical volumes to be combined together in an arbitrary way in 3D
space. The result is a placement of a normal logical volume, but
where final physical volumes are many.
</para>

<para>
However, an <emphasis>assembly</emphasis> volume does not act as a real mother
volume, being an envelope for its daughter volumes. Its role is
over at the time the placement of the logical assembly volume is
done. The physical volume objects become independent copies of each
of the assembled logical volumes.
</para>

<para>
This class is particularly useful when there is a need to create
a regular pattern in space of a complex component which consists of
different shapes and can't be obtained by using replicated volumes
or parametrised volumes (see also <xref linkend="fig.Geom.Assem_1" /> 
reful usage of <literal>G4AssemblyVolume</literal> must be considered 
though, in order to avoid cases of "proliferation" of physical volumes 
all placed in the same mother.
</para>

<figure id="fig.Geom.Assem_1">
<title>
Examples of <emphasis>assembly</emphasis> of volumes.
</title>
<mediaobject>
  <imageobject role="fo">
    <imagedata fileref="./AllResources/Detector/geometry.src/avex1and2.jpg" 
               format="JPG" contentwidth="8.0cm" align="center" />
  </imageobject>
  <imageobject role="html">
    <imagedata fileref="./AllResources/Detector/geometry.src/avex1and2.jpg" 
               format="JPG" align="center" />
  </imageobject>
  <textobject>
    <phrase>Assembly volumes</phrase>
  </textobject>
</mediaobject>
</figure>

<!-- ******************* Section (Level#3) ****************** -->
<sect3 id="sect.Geom.Assemb.Fill">
<title>
Filling an assembly volume with its "daughters"
</title>

<para>
Participating logical volumes are represented as a triplet of
&lt;logical volume, translation, rotation&gt;
(<literal>G4AssemblyTriplet</literal> class).
</para>

<para>
The adopted approach is to place each participating logical volume
with respect to the assembly's coordinate system, according to the
specified translation and rotation.
</para>

</sect3>

<!-- ******************* Section (Level#3) ****************** -->
<sect3 id="sect.Geom.Assemb.Place">
<title>
Assembly volume placement
</title>

<para>
An assembly volume object is composed of a set of logical
volumes; imprints of it can be made inside a mother logical
volume.
</para>

<para>
Since the assembly volume class generates physical volumes
during each imprint, the user has no way to specify identifiers for
these. An internal counting mechanism is used to compose uniquely
the names of the physical volumes created by the invoked
<literal>MakeImprint(...)</literal> method(s).
</para>

<para>
The name for each of the physical volume is generated with
the following format:

<informalexample>
<programlisting>
    av_<emphasis role="bold">WWW</emphasis>_impr_<emphasis role="bold">XXX</emphasis>_<emphasis role="bold">YYY</emphasis>_<emphasis role="bold">ZZZ</emphasis>
</programlisting>
</informalexample>

where:

<itemizedlist spacing="compact">
  <listitem><para>
    <emphasis role="bold">WWW</emphasis> - assembly volume instance number
  </para></listitem>
  <listitem><para>
    <emphasis role="bold">XXX</emphasis> - assembly volume imprint number
  </para></listitem>
  <listitem><para>
    <emphasis role="bold">YYY</emphasis> - the name of the placed logical
    volume
  </para></listitem>
  <listitem><para>
    <emphasis role="bold">ZZZ</emphasis> - the logical volume index inside the assembly
    volume
  </para></listitem>
</itemizedlist>
</para>

<para>
It is however possible to access the constituent physical volumes
of an assembly and eventually customise ID and copy-number.
</para>

</sect3>

<!-- ******************* Section (Level#3) ****************** -->
<sect3 id="sect.Geom.Assemb.Destruct">
<title>
Destruction of an assembly volume
</title>

<para>
At destruction all the generated physical volumes and associated
rotation matrices of the imprints will be destroyed. A list of
physical volumes created by <literal>MakeImprint()</literal> method is kept,
in order to be able to cleanup the objects when not needed anymore.
This requires the user to keep the assembly objects in memory
during the whole job or during the life-time of the
<literal>G4Navigator</literal>, logical volume store and physical volume
store may keep pointers to physical volumes generated by the
assembly volume.
</para>

<para>
The <literal>MakeImprint()</literal> method will operate correctly also on
transformations including reflections and can be applied also to
recursive assemblies (i.e., it is possible to generate imprints of
assemblies including other assemblies).
Giving <literal>true</literal> as the last argument of the 
<literal>MakeImprint()</literal> method,
it is possible to activate the volumes overlap check for the assembly's
constituents (the default is <literal>false</literal>).
</para>

<para>
At destruction of a <literal>G4AssemblyVolume</literal>, all its generated
physical volumes and rotation matrices will be freed.
</para>

</sect3>

<!-- ******************* Section (Level#3) ****************** -->
<sect3 id="sect.Geom.Assemb.Example">
<title>
Example
</title>

<para>
This example shows how to use the <literal>G4AssemblyVolume</literal>
class. It implements a layered detector where each layer consists
of 4 plates.
</para>

<para>
In the code below, at first the world volume is defined, then
solid and logical volume for the plate are created, followed by the
definition of the assembly volume for the layer.
</para>

<para>
The assembly volume for the layer is then filled by the plates in
the same way as normal physical volumes are placed inside a mother
volume.
</para>

<para>
Finally the layers are placed inside the world volume as the
imprints of the assembly volume (see <xref linkend="programlist_Geom.Assem_1" />).

<example id="programlist_Geom.Assem_1">
<title>
An example of usage of the <literal>G4AssemblyVolume</literal> class.
</title>
<programlisting>
 static unsigned int layers = 5;

 void TstVADetectorConstruction::ConstructAssembly()
 {
   // Define world volume
   G4Box* WorldBox = new G4Box( "WBox", worldX/2., worldY/2., worldZ/2. );
   G4LogicalVolume*   worldLV  = new G4LogicalVolume( WorldBox, selectedMaterial, "WLog", 0, 0, 0);
   G4VPhysicalVolume* worldVol = new G4PVPlacement(0, G4ThreeVector(), "WPhys",worldLV,
                                                   0, false, 0);

   // Define a plate
   G4Box* PlateBox = new G4Box( "PlateBox", plateX/2., plateY/2., plateZ/2. );
   G4LogicalVolume* plateLV = new G4LogicalVolume( PlateBox, Pb, "PlateLV", 0, 0, 0 );

   // Define one layer as one assembly volume
   G4AssemblyVolume* assemblyDetector = new G4AssemblyVolume();

   // Rotation and translation of a plate inside the assembly
   G4RotationMatrix Ra;
   G4ThreeVector Ta;
   G4Transform3D Tr;

   // Rotation of the assembly inside the world
   G4RotationMatrix Rm;

   // Fill the assembly by the plates
   Ta.setX( caloX/4. ); Ta.setY( caloY/4. ); Ta.setZ( 0. );
   Tr = G4Transform3D(Ra,Ta);
   assemblyDetector-&gt;AddPlacedVolume( plateLV, Tr );

   Ta.setX( -1*caloX/4. ); Ta.setY( caloY/4. ); Ta.setZ( 0. );
   Tr = G4Transform3D(Ra,Ta);
   assemblyDetector-&gt;AddPlacedVolume( plateLV, Tr );

   Ta.setX( -1*caloX/4. ); Ta.setY( -1*caloY/4. ); Ta.setZ( 0. );
   Tr = G4Transform3D(Ra,Ta);
   assemblyDetector-&gt;AddPlacedVolume( plateLV, Tr );

   Ta.setX( caloX/4. ); Ta.setY( -1*caloY/4. ); Ta.setZ( 0. );
   Tr = G4Transform3D(Ra,Ta);
   assemblyDetector-&gt;AddPlacedVolume( plateLV, Tr );

   // Now instantiate the layers
   for( unsigned int i = 0; i &lt; layers; i++ )
   {
     // Translation of the assembly inside the world
     G4ThreeVector Tm( 0,0,i*(caloZ + caloCaloOffset) - firstCaloPos );
     Tr = G4Transform3D(Rm,Tm);
     assemblyDetector-&gt;MakeImprint( worldLV, Tr );
   }
}
</programlisting>
</example>
</para>

<para>
The resulting detector will look as in <xref linkend="fig.Geom.Assem_2" />, 
below:

<figure id="fig.Geom.Assem_2">
<title>
The geometry corresponding to <xref linkend="programlist_Geom.Assem_1" />.
</title>
<mediaobject>
  <imageobject role="fo">
    <imagedata fileref="AllResources/Detector/geometry.src/avpic.jpg" 
               format="JPG" contentwidth="5.0cm" align="center" />
  </imageobject>
  <imageobject role="html">
    <imagedata fileref="AllResources/Detector/geometry.src/avpic.jpg" 
               format="JPG" align="center" />
  </imageobject>


  <imageobject>
    <imagedata fileref="./AllResources/Detector/geometry.src/avpic.jpg" 
               format="JPG" width="10.0cm" depth="10.0cm" align="center" />
  </imageobject>
  <textobject>
    <phrase>Assembly volume detector</phrase>
  </textobject>
</mediaobject>
</figure>
</para>


</sect3>
</sect2>
