G4AssemblyVolume.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 // $Id$
00028 //
00029 // 
00030 // Class G4AssemblyVolume - implementation
00031 //
00032 // ----------------------------------------------------------------------
00033 
00034 #include "G4AssemblyVolume.hh"
00035 #include "G4PVPlacement.hh"
00036 #include "G4RotationMatrix.hh"
00037 #include "G4AffineTransform.hh"
00038 #include "G4LogicalVolume.hh"
00039 #include "G4VPhysicalVolume.hh"
00040 #include "G4ReflectionFactory.hh"
00041 
00042 #include <sstream>
00043 
00044 unsigned int G4AssemblyVolume::fsInstanceCounter = 0;
00045 
00046 // Default constructor
00047 //
00048 G4AssemblyVolume::G4AssemblyVolume()
00049   : fAssemblyID( 0 )
00050 {
00051   InstanceCountPlus();
00052   SetAssemblyID( GetInstanceCount() );
00053   SetImprintsCount( 0 );
00054 }
00055 
00056 // Composing constructor
00057 //
00058 G4AssemblyVolume::G4AssemblyVolume( G4LogicalVolume* volume,
00059                                     G4ThreeVector& translation,
00060                                     G4RotationMatrix* rotation )
00061   : fAssemblyID( 0 )
00062 {
00063   InstanceCountPlus();
00064   SetAssemblyID( GetInstanceCount() );
00065   SetImprintsCount( 0 );
00066   AddPlacedVolume(volume, translation, rotation);
00067 }
00068 
00069 // Destructor
00070 //
00071 G4AssemblyVolume::~G4AssemblyVolume()
00072 {
00073   unsigned int howmany = fTriplets.size();
00074   if( howmany != 0 )
00075   {
00076     for( unsigned int i = 0; i < howmany; i++ )
00077     {
00078       G4RotationMatrix* pRotToClean = fTriplets[i].GetRotation();
00079       if( pRotToClean != 0 )
00080       {
00081         delete pRotToClean;
00082       }
00083     }
00084   }
00085   fTriplets.clear();
00086   
00087   howmany = fPVStore.size();
00088   if( howmany != 0 )
00089   {
00090     for( unsigned int j = 0; j < howmany; j++ )
00091     {
00092       delete fPVStore[j];
00093     }
00094   }
00095   fPVStore.clear();
00096   InstanceCountMinus();
00097 }
00098 
00099 // Add and place the given volume according to the specified
00100 // translation and rotation.
00101 //
00102 // The rotation matrix passed in can be 0 = identity or an address even of an
00103 // object on the upper stack frame. During assembly imprint, it creates anyway
00104 // a new matrix and keeps track of it so it can delete it later at destruction
00105 // time.
00106 // This policy has been adopted since user has no control on the way the
00107 // rotations are combined.
00108 //
00109 void G4AssemblyVolume::AddPlacedVolume( G4LogicalVolume*  pVolume,
00110                                         G4ThreeVector&    translation,
00111                                         G4RotationMatrix* pRotation )
00112 {
00113   G4RotationMatrix*  toStore  = new G4RotationMatrix;
00114   
00115   if( pRotation != 0 )  { *toStore = *pRotation; }
00116   
00117   G4AssemblyTriplet toAdd( pVolume, translation, toStore );
00118   fTriplets.push_back( toAdd );
00119 }
00120 
00121 // Add and place the given volume according to the specified transformation
00122 //
00123 void G4AssemblyVolume::AddPlacedVolume( G4LogicalVolume*  pVolume,
00124                                         G4Transform3D&    transformation )
00125 {
00126   // Decompose transformation
00127   G4Scale3D     scale;
00128   G4Rotate3D    rotation;
00129   G4Translate3D translation;
00130   transformation.getDecomposition(scale, rotation, translation);
00131 
00132   G4ThreeVector      v = translation.getTranslation();
00133   G4RotationMatrix*  r = new G4RotationMatrix;
00134                     *r = rotation.getRotation();
00135   
00136   G4bool isReflection = false;
00137   if (scale(0,0)*scale(1,1)*scale(2,2) < 0.)  { isReflection = true; }
00138 
00139   G4AssemblyTriplet toAdd( pVolume, v, r, isReflection );
00140   fTriplets.push_back( toAdd );
00141 }
00142 
00143 // Add and place the given assembly volume according to the specified
00144 // translation and rotation.
00145 //
00146 void G4AssemblyVolume::AddPlacedAssembly( G4AssemblyVolume* pAssembly,
00147                                           G4ThreeVector&    translation,
00148                                           G4RotationMatrix* pRotation )
00149 {
00150   G4RotationMatrix*  toStore  = new G4RotationMatrix;
00151   
00152   if( pRotation != 0 )  { *toStore = *pRotation; }
00153   
00154   G4AssemblyTriplet toAdd( pAssembly, translation, toStore );
00155   fTriplets.push_back( toAdd );
00156 }
00157 
00158 // Add and place the given assembly volume according to the specified 
00159 // transformation
00160 //
00161 void G4AssemblyVolume::AddPlacedAssembly( G4AssemblyVolume* pAssembly,
00162                                           G4Transform3D&    transformation )
00163 {
00164   // Decompose transformation
00165   //
00166   G4Scale3D     scale;
00167   G4Rotate3D    rotation;
00168   G4Translate3D translation;
00169   transformation.getDecomposition(scale, rotation, translation);
00170 
00171   G4ThreeVector      v = translation.getTranslation();
00172   G4RotationMatrix*  r = new G4RotationMatrix;
00173                     *r = rotation.getRotation();
00174   
00175   G4bool isReflection = false;
00176   if (scale(0,0)*scale(1,1)*scale(2,2) < 0.)  { isReflection = true; }
00177   
00178   G4AssemblyTriplet toAdd( pAssembly, v, r, isReflection );
00179   fTriplets.push_back( toAdd );
00180 }
00181 
00182 // Create an instance of an assembly volume inside of the specified
00183 // mother volume. This works analogically to making stamp imprints.
00184 // This method makes use of the Geant4 affine transformation class.
00185 // The algorithm is defined as follows:
00186 //  
00187 // Having rotation matrix Rm and translation vector Tm to be applied
00188 // inside the mother and rotation matrix Ra and translation vector Ta
00189 // to be applied inside the assembly itself for each of the participating
00190 // volumes the resulting transformation is
00191 //  
00192 // Tfinal = Ta * Tm
00193 //  
00194 // where Ta and Tm are constructed as
00195 //  
00196 //        -1                                     -1
00197 // Ta = Ra  * Ta           and            Tm = Rm  * Tm
00198 //  
00199 // which in words means that we create first the affine transformations
00200 // by inverse rotation matrices and translations for mother and assembly.
00201 // The resulting final transformation to be applied to each of the
00202 // participating volumes is their product.
00203 //
00204 // IMPORTANT NOTE!
00205 // The order of multiplication is reversed when comparing to CLHEP 3D
00206 // transformation matrix(G4Transform3D class).
00207 //  
00208 // The rotation matrix passed in can be 0 = identity or an address even of an
00209 // object on the upper stack frame. During assembly imprint, it creates anyway
00210 // a new matrix and keeps track of it so it can delete it later at destruction
00211 // time.
00212 // This policy has been adopted since user has no control on the way the
00213 // rotations are combined.
00214 // 
00215 // If the assembly volume contains assembly (a'), the function is called
00216 // recursively with composed transformation:
00217 //
00218 // Tanew =  Ta * Ta'
00219 //
00220 void G4AssemblyVolume::MakeImprint( G4AssemblyVolume* pAssembly,
00221                                     G4LogicalVolume*  pMotherLV,
00222                                     G4Transform3D&    transformation,
00223                                     G4int copyNumBase,
00224                                     G4bool surfCheck )
00225 {
00226   unsigned int  numberOfDaughters;
00227   
00228   if( copyNumBase == 0 )
00229   {
00230     numberOfDaughters = pMotherLV->GetNoDaughters();
00231   }
00232   else
00233   {
00234     numberOfDaughters = copyNumBase;
00235   }
00236 
00237   // We start from the first available index
00238   //
00239   numberOfDaughters++;
00240 
00241   ImprintsCountPlus();
00242   
00243   std::vector<G4AssemblyTriplet> triplets = pAssembly->fTriplets;
00244 
00245   for( unsigned int   i = 0; i < triplets.size(); i++ )
00246   {
00247     G4Transform3D Ta( *(triplets[i].GetRotation()),
00248                       triplets[i].GetTranslation() );
00249     if ( triplets[i].IsReflection() )  { Ta = Ta * G4ReflectZ3D(); }
00250 
00251     G4Transform3D Tfinal = transformation * Ta;
00252     
00253     if ( triplets[i].GetVolume() )
00254     {
00255       // Generate the unique name for the next PV instance
00256       // The name has format:
00257       //
00258       // av_WWW_impr_XXX_YYY_ZZZ
00259       // where the fields mean:
00260       // WWW - assembly volume instance number
00261       // XXX - assembly volume imprint number
00262       // YYY - the name of a log. volume we want to make a placement of
00263       // ZZZ - the log. volume index inside the assembly volume
00264       //
00265       std::stringstream pvName;
00266       pvName << "av_"
00267              << GetAssemblyID()
00268              << "_impr_"
00269              << GetImprintsCount()
00270              << "_"
00271              << triplets[i].GetVolume()->GetName().c_str()
00272              << "_pv_"
00273              << i
00274              << std::ends;
00275 
00276       // Generate a new physical volume instance inside a mother
00277       // (as we allow 3D transformation use G4ReflectionFactory to 
00278       //  take into account eventual reflection)
00279       //
00280       G4PhysicalVolumesPair pvPlaced
00281         = G4ReflectionFactory::Instance()->Place( Tfinal,
00282                                                   pvName.str().c_str(),
00283                                                   triplets[i].GetVolume(),
00284                                                   pMotherLV,
00285                                                   false,
00286                                                   numberOfDaughters + i,
00287                                                   surfCheck );
00288 
00289       // Register the physical volume created by us so we can delete it later
00290       //
00291       fPVStore.push_back( pvPlaced.first );
00292       if ( pvPlaced.second )  { fPVStore.push_back( pvPlaced.second ); }
00293     }
00294     else if ( triplets[i].GetAssembly() )
00295     {
00296       // Place volumes in this assembly with composed transformation
00297       //
00298       MakeImprint( triplets[i].GetAssembly(), pMotherLV,
00299                    Tfinal, i*100+copyNumBase, surfCheck ); 
00300     }
00301     else
00302     {
00303       G4Exception("G4AssemblyVolume::MakeImprint(..)",
00304                   "GeomVol0003", FatalException,
00305                   "Triplet has no volume and no assembly");
00306     }  
00307   }  
00308 }    
00309 
00310 void G4AssemblyVolume::MakeImprint( G4LogicalVolume*  pMotherLV,
00311                                     G4ThreeVector&    translationInMother,
00312                                     G4RotationMatrix* pRotationInMother,
00313                                     G4int copyNumBase,
00314                                     G4bool surfCheck )
00315 {
00316   // If needed user can specify explicitely the base count from which to start
00317   // off for the generation of phys. vol. copy numbers.
00318   // The old behaviour is preserved when copyNumBase == 0, e.g. the generated
00319   // copy numbers start from the count equal to current number of daughter
00320   // volumes before an imprint is made
00321 
00322   // Compose transformation
00323   //
00324   if( pRotationInMother == 0 )
00325   {
00326     // Make it by default an indentity matrix
00327     //
00328     pRotationInMother =
00329       const_cast<G4RotationMatrix*>( &G4RotationMatrix::IDENTITY );
00330   }
00331 
00332   G4Transform3D transform( *pRotationInMother,
00333                             translationInMother );
00334   MakeImprint(this, pMotherLV, transform, copyNumBase, surfCheck);
00335 }
00336 
00337 void G4AssemblyVolume::MakeImprint( G4LogicalVolume*  pMotherLV,
00338                                     G4Transform3D&    transformation,
00339                                     G4int copyNumBase,
00340                                     G4bool surfCheck )
00341 {
00342   // If needed user can specify explicitely the base count from which to start
00343   // off for the generation of phys. vol. copy numbers.
00344   // The old behaviour is preserved when copyNumBase == 0, e.g. the generated
00345   // copy numbers start from the count equal to current number of daughter
00346   // volumes before a imprint is made
00347 
00348   MakeImprint(this, pMotherLV, transformation, copyNumBase, surfCheck);
00349 }
00350 
00351 unsigned int G4AssemblyVolume::GetInstanceCount() const
00352 {
00353   return G4AssemblyVolume::fsInstanceCounter;
00354 }
00355 
00356 void         G4AssemblyVolume::SetInstanceCount( unsigned int value )
00357 {
00358   G4AssemblyVolume::fsInstanceCounter = value;
00359 }
00360 
00361 void         G4AssemblyVolume::InstanceCountPlus()
00362 {
00363   G4AssemblyVolume::fsInstanceCounter++;
00364 }
00365 
00366 void         G4AssemblyVolume::InstanceCountMinus()
00367 {
00368   G4AssemblyVolume::fsInstanceCounter--;
00369 }

Generated on Mon May 27 17:47:41 2013 for Geant4 by  doxygen 1.4.7