Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/advanced/ChargeExchangeMC/src/CexmcSetup.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 /*
 27  * =============================================================================
 28  *
 29  *       Filename:  CexmcSetup.cc
 30  *
 31  *    Description:  physical setup
 32  *
 33  *        Version:  1.0
 34  *        Created:  10.10.2009 23:00:50
 35  *       Revision:  none
 36  *       Compiler:  gcc
 37  *
 38  *         Author:  Alexey Radkov (), 
 39  *        Company:  PNPI
 40  *
 41  * =============================================================================
 42  */
 43 
 44 #include <G4GDMLParser.hh>
 45 #include <G4MultiFunctionalDetector.hh>
 46 #include <G4SDManager.hh>
 47 #include <G4LogicalVolume.hh>
 48 #include <G4VPhysicalVolume.hh>
 49 #include <G4PhysicalVolumeStore.hh>
 50 #include <G4Box.hh>
 51 #include <G4LogicalVolumeStore.hh>
 52 #include <G4Region.hh>
 53 #include <G4RegionStore.hh>
 54 #include <G4ProductionCuts.hh>
 55 #include <G4VUserPhysicsList.hh>
 56 #include <G4SystemOfUnits.hh>
 57 #include "CexmcSetup.hh"
 58 #include "CexmcPrimitiveScorer.hh"
 59 #include "CexmcTrackPoints.hh"
 60 #include "CexmcTrackPointsInLeftRightSet.hh"
 61 #include "CexmcTrackPointsInCalorimeter.hh"
 62 #include "CexmcTrackPointsFilter.hh"
 63 #include "CexmcSimpleEnergyDeposit.hh"
 64 #include "CexmcEnergyDepositInLeftRightSet.hh"
 65 #include "CexmcEnergyDepositInCalorimeter.hh"
 66 #include "CexmcRunManager.hh"
 67 #include "CexmcPhysicsManager.hh"
 68 #include "CexmcException.hh"
 69 
 70 
 71 CexmcSetup::CexmcSetup( const G4String &  gdmlFile_,
 72                         G4bool  validateGDMLFile_ ) :
 73     world( 0 ), gdmlFile( gdmlFile_ ), validateGDMLFile( validateGDMLFile_ ),
 74     calorimeterRegionInitialized( false ),
 75     calorimeterGeometryDataInitialized( false ), monitorVolume( NULL ),
 76     vetoCounterVolume( NULL ), calorimeterVolume( NULL ), targetVolume( NULL ),
 77     rightVetoCounter( NULL ), rightCalorimeter( NULL )
 78 {
 79 }
 80 
 81 
 82 G4VPhysicalVolume *  CexmcSetup::Construct( void )
 83 {
 84     if ( world )
 85         return world;
 86 
 87     G4GDMLParser  gdmlParser;
 88 
 89     gdmlParser.Read( gdmlFile, validateGDMLFile );
 90     world = gdmlParser.GetWorldVolume();
 91 
 92     SetupSpecialVolumes( gdmlParser );
 93 
 94     ReadTransforms( gdmlParser );
 95 
 96     ReadRightDetectors();
 97 
 98     CexmcRunManager *  runManager( static_cast< CexmcRunManager * >(
 99                                             G4RunManager::GetRunManager() ) );
100 
101     runManager->SetupConstructionHook();
102 
103     const CexmcPhysicsManager *  physicsManager(
104             dynamic_cast< const CexmcPhysicsManager * >(
105                                         runManager->GetUserPhysicsList() ) );
106 
107     if ( ! physicsManager )
108         throw CexmcException( CexmcWeirdException );
109 
110     CexmcPhysicsManager *        thePhysicsManager(
111             const_cast< CexmcPhysicsManager * >( physicsManager ) );
112     thePhysicsManager->SetupConstructionHook( this );
113 
114     return world;
115 }
116 
117 
118 void  CexmcSetup::SetupSpecialVolumes( const G4GDMLParser &  gdmlParser )
119 {
120     G4MultiFunctionalDetector *   detector[ CexmcNumberOfDetectorRoles ] =
121                                                                     { NULL };
122     const G4LogicalVolumeStore *  lvs( G4LogicalVolumeStore::GetInstance() );
123 
124     for ( std::vector< G4LogicalVolume * >::const_iterator
125                         lvIter( lvs->begin() ); lvIter != lvs->end(); ++lvIter )
126     {
127         G4String           volumeName( G4String( ( *lvIter )->GetName() ) );
128         G4GDMLAuxListType  auxInfo( gdmlParser.GetVolumeAuxiliaryInformation(
129                                                                     *lvIter ) );
130         CexmcDetectorRole  curDetectorRole( CexmcNumberOfDetectorRoles );
131 
132         for ( G4GDMLAuxListType::const_iterator  pair( auxInfo.begin() );
133                                               pair != auxInfo.end(); ++pair )
134         {
135             CexmcPrimitiveScorer *  scorer( NULL );
136             G4String                detectorName( "uninitialized" );
137             do
138             {
139                 if ( pair->type == "EnergyDepositDetector" )
140                 {
141                     do
142                     {
143                         if ( pair->value == "MonitorRole" )
144                         {
145                             AssertAndAsignDetectorRole( curDetectorRole,
146                                                 CexmcMonitorDetectorRole );
147                             scorer = new CexmcSimpleEnergyDeposit(
148                                     CexmcDetectorTypeName[ CexmcEDDetector ] );
149                             break;
150                         }
151                         if ( pair->value == "VetoCounterRole" )
152                         {
153                             AssertAndAsignDetectorRole( curDetectorRole,
154                                                 CexmcVetoCounterDetectorRole );
155                             scorer = new CexmcEnergyDepositInLeftRightSet(
156                                     CexmcDetectorTypeName[ CexmcEDDetector ],
157                                     this );
158                             break;
159                         }
160                         if ( pair->value == "CalorimeterRole" )
161                         {
162                             AssertAndAsignDetectorRole( curDetectorRole,
163                                                 CexmcCalorimeterDetectorRole );
164                             scorer = new CexmcEnergyDepositInCalorimeter(
165                                     CexmcDetectorTypeName[ CexmcEDDetector ],
166                                     this );
167                             break;
168                         }
169                     } while ( false );
170                     detectorName = CexmcDetectorRoleName[ curDetectorRole ];
171                     G4cout << CEXMC_LINE_START "ED Scorer of detector role '" <<
172                                detectorName << "' in volume '" << volumeName <<
173                                "'" << G4endl;
174                     break;
175                 }
176                 if ( pair->type == "TrackPointsDetector" )
177                 {
178                     do
179                     {
180                         if ( pair->value == "MonitorRole" )
181                         {
182                             AssertAndAsignDetectorRole( curDetectorRole,
183                                                 CexmcMonitorDetectorRole );
184                             scorer = new CexmcTrackPoints(
185                                     CexmcDetectorTypeName[ CexmcTPDetector ] );
186                             break;
187                         }
188                         if ( pair->value == "VetoCounterRole"  )
189                         {
190                             AssertAndAsignDetectorRole( curDetectorRole,
191                                                 CexmcVetoCounterDetectorRole );
192                             scorer = new CexmcTrackPointsInLeftRightSet(
193                                     CexmcDetectorTypeName[ CexmcTPDetector ],
194                                     this );
195                             break;
196                         }
197                         if ( pair->value == "CalorimeterRole" )
198                         {
199                             AssertAndAsignDetectorRole( curDetectorRole,
200                                                 CexmcCalorimeterDetectorRole );
201                             scorer = new CexmcTrackPointsInCalorimeter(
202                                     CexmcDetectorTypeName[ CexmcTPDetector ],
203                                     this );
204                             break;
205                         }
206                         if ( pair->value == "TargetRole" )
207                         {
208                             AssertAndAsignDetectorRole( curDetectorRole,
209                                                 CexmcTargetDetectorRole );
210                             scorer = new CexmcTrackPoints(
211                                     CexmcDetectorTypeName[ CexmcTPDetector ] );
212                             break;
213                         }
214                     } while ( false );
215                     detectorName = CexmcDetectorRoleName[ curDetectorRole ];
216                     G4cout << CEXMC_LINE_START "TP Scorer of detector role '" <<
217                                detectorName << "' in volume '" << volumeName <<
218                                "'" << G4endl;
219                     if ( scorer )
220                     {
221                         CexmcTrackPointsFilter *  filter(
222                                  new CexmcTrackPointsFilter( "trackPoints" ) );
223                         scorer->SetFilter( filter );
224                     }
225                     break;
226                 }
227                 if ( pair->type == "SensitiveRegion" )
228                 {
229                     do
230                     {
231                         if ( pair->value == "CalorimeterRegion" )
232                         {
233                             G4Region *  region( NULL );
234                             if ( calorimeterRegionInitialized )
235                             {
236                                 region = G4RegionStore::GetInstance()->
237                                         GetRegion( CexmcCalorimeterRegionName );
238                             }
239                             else
240                             {
241                                 region = new G4Region(
242                                                 CexmcCalorimeterRegionName );
243                                 G4ProductionCuts *  cuts(
244                                                         new G4ProductionCuts );
245                                 G4double  defaultProductionCut( 1.0 * mm );
246                                 const G4VUserPhysicsList *  physicsList(
247                                             G4RunManager::GetRunManager()->
248                                                         GetUserPhysicsList() );
249                                 if ( physicsList )
250                                     defaultProductionCut =
251                                             physicsList->GetDefaultCutValue();
252                                 cuts->SetProductionCut( defaultProductionCut );
253                                 region->SetProductionCuts( cuts );
254                                 calorimeterRegionInitialized = true;
255                             }
256                             region->AddRootLogicalVolume( *lvIter );
257                             break;
258                         }
259                     } while ( false );
260                     G4cout << CEXMC_LINE_START "Sensitive Region for logical "
261                                "volume '" << volumeName << "' registered" <<
262                                G4endl;
263                     break;
264                 }
265                 if ( pair->type == "SpecialVolume" )
266                 {
267                     do
268                     {
269                         if ( pair->value == "Monitor" )
270                         {
271                             monitorVolume = *lvIter;
272                             G4cout << CEXMC_LINE_START "Monitor volume '";
273                             break;
274                         }
275                         if ( pair->value == "VetoCounter" )
276                         {
277                             vetoCounterVolume = *lvIter;
278                             G4cout << CEXMC_LINE_START "VetoCounter volume '";
279                             break;
280                         }
281                         if ( pair->value == "Calorimeter" )
282                         {
283                             calorimeterVolume = *lvIter;
284                             G4cout << CEXMC_LINE_START "Calorimeter volume '";
285                             ReadCalorimeterGeometryData( *lvIter );
286                             calorimeterGeometryDataInitialized = true;
287                             break;
288                         }
289                         if ( pair->value == "Target" )
290                         {
291                             targetVolume = *lvIter;
292                             G4cout << CEXMC_LINE_START "Target volume '";
293                             break;
294                         }
295                     } while ( false );
296                     G4cout << volumeName << "' registered" << G4endl;
297                     break;
298                 }
299             }
300             while ( false );
301 
302             if ( scorer )
303             {
304                 /* curDetectorRole must be intact when scorer is not NULL */
305                 if ( ! detector[ curDetectorRole ] )
306                 {
307                     detector[ curDetectorRole ] =
308                                 new G4MultiFunctionalDetector( detectorName );
309                 }
310                 detector[ curDetectorRole ]->RegisterPrimitive( scorer );
311                 /* now that scorer has initialized pointer to its detector, its
312                  * messenger's path shall be properly initialized as well */
313                 scorer->InitializeMessenger();
314                 /* NB: logical volumes in GDML file may not have multiple
315                  * detector roles: for example volume Monitor may have only one
316                  * role MonitorRole. This restriction arises from that fact that
317                  * a logical volume may contain only one sensitive detector. */
318                 ( *lvIter )->SetSensitiveDetector(
319                                                 detector[ curDetectorRole ] );
320             }
321         }
322     }
323 
324     if ( ! calorimeterRegionInitialized )
325         throw CexmcException( CexmcCalorimeterRegionNotInitialized );
326 
327     if ( ! calorimeterGeometryDataInitialized )
328         throw CexmcException( CexmcCalorimeterGeometryDataNotInitialized );
329 
330     for ( G4int  i( 0 ); i < CexmcNumberOfDetectorRoles; ++i )
331     {
332         if ( detector[ i ] )
333             G4SDManager::GetSDMpointer()->AddNewDetector( detector[ i ] );
334     }
335 }
336 
337 
338 void  CexmcSetup::ReadTransforms( const G4GDMLParser &  gdmlParser )
339 {
340     G4ThreeVector     position( gdmlParser.GetPosition( "TargetPos" ) );
341     G4ThreeVector     rotation( gdmlParser.GetRotation( "TargetRot" ) );
342     G4RotationMatrix  rm;
343 
344     RotateMatrix( rotation, rm );
345     targetTransform.SetNetTranslation( position );
346     targetTransform.SetNetRotation( rm );
347 
348     position = gdmlParser.GetPosition( "CalorimeterLeftPos" );
349     rotation = gdmlParser.GetRotation( "CalorimeterLeftRot" );
350     rm = G4RotationMatrix();
351     RotateMatrix( rotation, rm );
352     calorimeterLeftTransform.SetNetTranslation( position );
353     calorimeterLeftTransform.SetNetRotation( rm );
354 
355     position = gdmlParser.GetPosition( "CalorimeterRightPos" );
356     rotation = gdmlParser.GetRotation( "CalorimeterRightRot" );
357     rm = G4RotationMatrix();
358     RotateMatrix( rotation, rm );
359     calorimeterRightTransform.SetNetTranslation( position );
360     calorimeterRightTransform.SetNetRotation( rm );
361 }
362 
363 
364 void  CexmcSetup::ReadCalorimeterGeometryData(
365                                             const G4LogicalVolume *  lVolume )
366 {
367     if ( lVolume->GetNoDaughters() == 0 )
368         throw CexmcException( CexmcIncompatibleGeometry );
369 
370     G4VPhysicalVolume *  pVolume( lVolume->GetDaughter( 0 ) );
371     EAxis                axis;
372     G4double             width;
373     G4double             offset;
374     G4bool               consuming;
375 
376     if ( ! pVolume )
377         throw CexmcException( CexmcIncompatibleGeometry );
378 
379     if ( pVolume->IsReplicated() )
380     {
381         pVolume->GetReplicationData( axis,
382                                      calorimeterGeometry.nCrystalsInColumn,
383                                      width, offset, consuming );
384     }
385 
386     lVolume = pVolume->GetLogicalVolume();
387 
388     if ( lVolume->GetNoDaughters() == 0 )
389         throw CexmcException( CexmcIncompatibleGeometry );
390 
391     pVolume = lVolume->GetDaughter( 0 );
392 
393     if ( ! pVolume )
394         throw CexmcException( CexmcIncompatibleGeometry );
395 
396     if ( pVolume->IsReplicated() )
397     {
398         pVolume->GetReplicationData( axis, calorimeterGeometry.nCrystalsInRow,
399                                      width, offset, consuming );
400     }
401 
402     lVolume = pVolume->GetLogicalVolume();
403 
404     /* NB: this is not necessarily a crystal itself as far as crystals can be
405      * wrapped in paper and other materials, but this is what reconstructor and
406      * digitizers really need */
407     G4Box *  crystalBox( dynamic_cast< G4Box * >( lVolume->GetSolid() ) );
408 
409     if ( ! crystalBox )
410         throw CexmcException( CexmcIncompatibleGeometry );
411 
412     calorimeterGeometry.crystalWidth = crystalBox->GetXHalfLength() * 2;
413     calorimeterGeometry.crystalHeight = crystalBox->GetYHalfLength() * 2;
414     calorimeterGeometry.crystalLength = crystalBox->GetZHalfLength() * 2;
415 }
416 
417 
418 void  CexmcSetup::ConvertToCrystalGeometry( const G4ThreeVector &  src,
419                     G4int &  row, G4int &  column, G4ThreeVector &  dst ) const
420 {
421     G4int     nCrystalsInColumn( calorimeterGeometry.nCrystalsInColumn );
422     G4int     nCrystalsInRow( calorimeterGeometry.nCrystalsInRow );
423     G4double  crystalWidth( calorimeterGeometry.crystalWidth );
424     G4double  crystalHeight( calorimeterGeometry.crystalHeight );
425 
426     row = G4int( ( src.y() + crystalHeight * nCrystalsInColumn / 2 ) /
427                  crystalHeight );
428     column = G4int( ( src.x() + crystalWidth * nCrystalsInRow / 2 ) /
429                     crystalWidth );
430     G4double   xInCalorimeterOffset(
431                     ( G4double( column ) - G4double( nCrystalsInRow ) / 2 ) *
432                                             crystalWidth + crystalWidth / 2 );
433     G4double   yInCalorimeterOffset(
434                     ( G4double( row ) - G4double( nCrystalsInColumn ) / 2 ) *
435                                             crystalHeight + crystalHeight / 2 );
436     dst.setX( src.x() - xInCalorimeterOffset );
437     dst.setY( src.y() - yInCalorimeterOffset );
438 }
439 
440 
441 void  CexmcSetup::ReadRightDetectors( void )
442 {
443     G4PhysicalVolumeStore *  pvs( G4PhysicalVolumeStore::GetInstance() );
444 
445     for ( std::vector< G4VPhysicalVolume * >::const_iterator  k( pvs->begin() );
446                                                         k != pvs->end(); ++k )
447     {
448         /* FIXME: it would be more reasonable to find detectors from volumes
449          * tagged with 'EnergyDepositDetector' or 'TrackPointsDetector', and not
450          * from volumes tagged with 'SpecialVolume' as it is done here. However
451          * in case of calorimeters the role of detectors are played by crystal
452          * volumes, not the calorimeters themselves, but only calorimeters can
453          * hold information about their left or right positions! Thus, following
454          * considerations of convenience, right detectors for all detector roles
455          * are chosen from volumes tagged with 'SpecialVolume' */
456         do
457         {
458             if ( ( *k )->GetLogicalVolume() == vetoCounterVolume )
459             {
460                 if ( G4StrUtil::contains(( *k )->GetName(), "Right" ) )
461                     rightVetoCounter = *k;
462                 break;
463             }
464             if ( ( *k )->GetLogicalVolume() == calorimeterVolume )
465             {
466                 if ( G4StrUtil::contains(( *k )->GetName(), "Right" ) )
467                     rightCalorimeter = *k;
468                 break;
469             }
470         } while ( false );
471     }
472 }
473 
474 
475 void  CexmcSetup::AssertAndAsignDetectorRole( CexmcDetectorRole &  detectorRole,
476                                               CexmcDetectorRole  value )
477 {
478     if ( detectorRole != CexmcNumberOfDetectorRoles && detectorRole != value )
479         throw CexmcException( CexmcMultipleDetectorRoles );
480 
481     detectorRole = value;
482 }
483 
484 
485 void  CexmcSetup::RotateMatrix( const G4ThreeVector &  rot,
486                                 G4RotationMatrix &  rm )
487 {
488     rm.rotateX( rot.x() );
489     rm.rotateY( rot.y() );
490     rm.rotateZ( rot.z() );
491 }
492 
493