source: trunk/source/geometry/management/test/TestAssemblyVolume/src/TstVADetectorConstruction.cc @ 1316

Last change on this file since 1316 was 1316, checked in by garnier, 14 years ago

update geant4-09-04-beta-cand-01 interfaces-V09-03-09 vis-V09-03-08

File size: 14.3 KB
Line 
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// $Id: TstVADetectorConstruction.cc,v 1.12 2006/06/29 18:34:33 gunter Exp $
28// GEANT4 tag $Name: geant4-09-04-beta-cand-01 $
29//
30// --------------------------------------------------------------
31
32#include "TstVADetectorConstruction.hh"
33#include "TstVADetectorMessenger.hh"
34
35#include <sstream>
36
37#include "G4ios.hh"
38#include "G4Material.hh"
39#include "G4MaterialTable.hh"
40#include "G4Element.hh"
41#include "G4ElementTable.hh"
42#include "G4Box.hh"
43#include "G4Tubs.hh"
44#include "G4LogicalVolume.hh"
45#include "G4ThreeVector.hh"
46#include "G4PVPlacement.hh"
47#include "G4SDManager.hh"
48#include "G4VisAttributes.hh"
49#include "G4Colour.hh"
50#include "G4TransportationManager.hh"
51#include "G4GeometryManager.hh"
52#include "G4StateManager.hh"
53#include "G4UImanager.hh"
54#include "G4TransportationManager.hh"
55#include "G4AssemblyVolume.hh"
56#include "G4PhysicalVolumeStore.hh"
57#include "G4RunManager.hh"
58
59TstVADetectorConstruction::TstVADetectorConstruction()
60:worldVol(0),Air(0),Al(0),Pb(0),selectedMaterial(0),detectorChoice(0),plateLV(0)
61{
62  classicDetector.caloLV      = 0;
63  classicDetector.PVs.clear()    ;
64  assemblyDetector            = 0;
65  ConstructClassic();
66  materialChoice              = "Air";
67  detectorMessenger           = new TstVADetectorMessenger(this);
68}
69
70TstVADetectorConstruction::~TstVADetectorConstruction()
71{
72  // R.I.P. messenger
73  delete detectorMessenger;
74}
75
76G4VPhysicalVolume* TstVADetectorConstruction::Construct()
77{
78  if( worldVol == 0 )
79  {
80    switch(detectorChoice)
81    { 
82      case 1:
83        ConstructAssembly(); 
84        break;
85      default:
86        ConstructClassic();
87    }
88  }
89  return worldVol;
90}
91
92void TstVADetectorConstruction::SwitchDetector()
93{
94  CleanClassic();
95  CleanAssembly();
96  switch(detectorChoice)
97  { 
98    case 1:
99      ConstructAssembly(); 
100      break;
101    default:
102      ConstructClassic(); 
103  }
104
105  // Let the navigator to know about the new top of the new geometry
106  G4RunManager::GetRunManager()->DefineWorldVolume( worldVol );
107}
108
109void TstVADetectorConstruction::SelectDetector(G4String val)
110{
111  if(val=="assembly") 
112  { detectorChoice = 1; }
113  else
114  { detectorChoice = 0; }
115  G4cout << "Now Detector is " << val << G4endl;
116}
117
118void TstVADetectorConstruction::SelectMaterial(G4String val)
119{
120  materialChoice = val;
121  SelectMaterialPointer();
122  G4cout << "World volume is now made of " << materialChoice << G4endl;
123}
124
125void TstVADetectorConstruction::SelectMaterialPointer()
126{
127//--------- Material definition ---------
128
129  G4double a, iz, z, density;
130  G4String name, symbol;
131  G4int nel;
132
133  if(!Air)
134  {
135    a = 14.01*g/mole;
136    G4Element* elN = new G4Element(name="Nitrogen", symbol="N", iz=7., a);
137    a = 16.00*g/mole;
138    G4Element* elO = new G4Element(name="Oxigen", symbol="O", iz=8., a);
139    density = 1.29e-03*g/cm3;
140    Air = new G4Material(name="Air", density, nel=2);
141    Air->AddElement(elN, .7);
142    Air->AddElement(elO, .3);
143  }
144
145  if(!Al)
146  {
147    a = 26.98*g/mole;
148    density = 2.7*g/cm3;
149    Al = new G4Material(name="Aluminium", z=13., a, density);
150  }
151
152  if(!Pb)
153  {
154    a = 207.19*g/mole;
155    density = 11.35*g/cm3;
156    Pb = new G4Material(name="Lead", z=82., a, density);
157  }
158
159  if(materialChoice=="Air")
160  { selectedMaterial = Air; }
161  else if(materialChoice=="Al")
162  { selectedMaterial = Al; }
163  else
164  { selectedMaterial = Pb; }
165
166  G4LogicalVolume* worldLV = worldVol->GetLogicalVolume();
167  if(worldLV)
168  { worldLV->SetMaterial(selectedMaterial); }
169}
170
171const double worldX              = 2000*mm;
172const double worldY              = 2000*mm;
173const double worldZ              = 2000*mm;
174
175const double caloX               = 1600*mm;
176const double caloY               = 1600*mm;
177const double caloZ               =  200*mm;
178
179const double plateX              =  700*mm;
180const double plateY              =  700*mm;
181const double plateZ              =  100*mm;
182
183const unsigned int layers        =    5;
184
185const double firstCaloPos        =  500*mm;
186const double caloCaloOffset      =   50*mm;
187const double plateCaloOffset     =    1*mm;
188const double platePlateOffset    =    2*mm;
189
190void TstVADetectorConstruction::ConstructClassic()
191{
192  if( worldVol == 0 )
193  {
194    // Define world volume
195    G4Box*           WorldBox  = new G4Box( "WBox", worldX/2., worldY/2., worldZ/2. );
196    G4LogicalVolume* worldLV   = new G4LogicalVolume( WorldBox, selectedMaterial, "WLog", 0, 0, 0);
197    worldVol                   = new G4PVPlacement(0, G4ThreeVector(), "WPhys", worldLV, 0, false, 0);
198
199    // We need to do this here to avoid the chicken-egg problem of proper initialization of the
200    // world volume's material
201    if( selectedMaterial == 0 )
202    {
203      SelectMaterialPointer();
204    }
205   
206    // Define a calorimeter layer
207    G4Box*           CaloBox   = new G4Box( "CaloBox", caloX/2., caloY/2., caloZ/2. );
208    classicDetector.caloLV     = new G4LogicalVolume( CaloBox, Air, "CaloLV", 0, 0, 0 );
209
210    // Define a calorimeter plate
211    G4Box*           PlateBox  = new G4Box( "PlateBox", plateX/2., plateY/2., plateZ/2. );
212    plateLV                    = new G4LogicalVolume( PlateBox, Pb, "PlateLV", 0, 0, 0 );
213
214    // Fill layer with plates
215    G4VPhysicalVolume* platePV = new G4PVPlacement(  (G4RotationMatrix*)0
216                                                    ,G4ThreeVector( caloX/4. 
217                                                                   ,caloY/4. 
218                                                                   ,0.)
219                                                    ,plateLV
220                                                    ,"plate_pv_0"
221                                                    ,classicDetector.caloLV
222                                                    ,false, 0 );
223
224    // Remember the instance so we can clean up properly later
225    classicDetector.PVs.push_back( platePV );
226
227    platePV                    = new G4PVPlacement(  (G4RotationMatrix*)0
228                                                    ,G4ThreeVector( -1*caloX/4. 
229                                                                   ,caloY/4.
230                                                                   ,0.)
231                                                    ,plateLV
232                                                    ,"plate_pv_1"
233                                                    ,classicDetector.caloLV
234                                                    ,false, 1 );
235
236    // Remember the instance so we can clean up properly later
237    classicDetector.PVs.push_back( platePV );
238
239    platePV                    = new G4PVPlacement(  (G4RotationMatrix*)0
240                                                    ,G4ThreeVector( -1*caloX/4. 
241                                                                   ,-1*caloY/4.
242                                                                   ,0.)
243                                                    ,plateLV
244                                                    ,"plate_pv_2"
245                                                    ,classicDetector.caloLV
246                                                    ,false, 2 );
247
248    // Remember the instance so we can clean up properly later
249    classicDetector.PVs.push_back( platePV );
250
251    platePV                    = new G4PVPlacement(  (G4RotationMatrix*)0
252                                                    ,G4ThreeVector( caloX/4.
253                                                                   ,-1*caloY/4. 
254                                                                   ,0.)
255                                                    ,plateLV
256                                                    ,"plate_pv_3"
257                                                    ,classicDetector.caloLV
258                                                    ,false, 3 );
259
260    // Remember the instance so we can clean up properly later
261    classicDetector.PVs.push_back( platePV );
262
263    // Create layers of quazi calorimeter
264    for( unsigned int i = 0; i < layers; i++ )
265    {
266      std::stringstream pvName;
267
268      pvName << "CaloPV_" << i << std::ends;
269     
270      // Place each layer
271      G4VPhysicalVolume* caloPV = new G4PVPlacement( 0
272                                                    ,G4ThreeVector
273                                                      ( 0
274                                                       ,0
275                                                       ,i*( caloZ + caloCaloOffset) - firstCaloPos
276                                                      )
277                                                    ,pvName.str(), classicDetector.caloLV, worldVol,
278                                                     false, i );
279
280      // Remember the instance so we can clean up properly later
281      classicDetector.PVs.push_back( caloPV );
282    }
283
284#ifdef G4DEBUG   
285    G4cout << "PVs created: " << classicDetector.PVs.size() << G4endl;
286#endif
287  }
288}
289
290void TstVADetectorConstruction::ConstructAssembly()
291{
292  if( worldVol == 0 )
293  {
294    // Define world volume
295    G4Box*           WorldBox  = new G4Box( "WBox", worldX/2., worldY/2., worldZ/2. );
296    G4LogicalVolume* worldLV   = new G4LogicalVolume( WorldBox, selectedMaterial, "WLog", 0, 0, 0);
297    worldVol                   = new G4PVPlacement(0, G4ThreeVector(), "WPhys", worldLV, 0, false, 0);
298
299    // We need to this here to overcome the chicken-egg problem of proper initialization of the
300    // world volume material
301    if( selectedMaterial == 0 )
302    {
303      SelectMaterialPointer();
304    }
305
306    // Define a calorimeter plate
307    G4Box*           PlateBox  = new G4Box( "PlateBox", plateX/2., plateY/2., plateZ/2. );
308    plateLV                    = new G4LogicalVolume( PlateBox, Pb, "PlateLV", 0, 0, 0 );
309   
310    // Define one calorimeter layer as one assembly volume
311    assemblyDetector           = new G4AssemblyVolume();
312
313    // Rotation and translation of a plate inside the assembly
314    G4RotationMatrix        Ra;
315    G4ThreeVector           Ta;
316
317    // Rotation of the assembly inside the world
318    G4RotationMatrix        Rm;
319
320    // Fill the assembly by the plates
321    // Test if 0 pointer instead of matrix works, it should create an identity by default
322    Ta.setX( caloX/4. );  Ta.setY( caloY/4. );  Ta.setZ( 0. );
323    assemblyDetector->AddPlacedVolume( plateLV, Ta, 0 );
324   
325    Ta.setX( -1*caloX/4. );  Ta.setY( caloY/4. );  Ta.setZ( 0. );
326    assemblyDetector->AddPlacedVolume( plateLV, Ta, &Ra );
327   
328    Ta.setX( -1*caloX/4. );  Ta.setY( -1*caloY/4. );  Ta.setZ( 0. );
329    assemblyDetector->AddPlacedVolume( plateLV, Ta, &Ra );
330
331    Ta.setX( caloX/4. );  Ta.setY( -1*caloY/4. );  Ta.setZ( 0. );
332    assemblyDetector->AddPlacedVolume( plateLV, Ta, &Ra );
333   
334    // Now instantiate the layers of calorimeter
335    for( unsigned int i = 0; i < layers; i++ )
336    {
337      // Translation of the assembly inside the world
338      G4ThreeVector Tm( 0,0,i*(caloZ + caloCaloOffset) - firstCaloPos );
339      assemblyDetector->MakeImprint( worldLV, Tm, &Rm );
340    }
341  }
342}
343
344void TstVADetectorConstruction::CleanClassic()
345{
346  // First free the memory occupied by physical volumes
347  for( unsigned int i = 0; i < classicDetector.PVs.size(); i++ )
348  {
349    G4VPhysicalVolume* toDie  = classicDetector.PVs[i];
350    if( toDie != 0 )
351    {
352      // Clean up the rotation matrix if any
353      G4RotationMatrix* rmToDie = toDie->GetRotation();
354      if( rmToDie != 0 )
355      {
356        delete rmToDie;
357      }
358      delete toDie;
359    }
360  }
361 
362  classicDetector.PVs.clear();
363 
364  // Now free the memory of logical volume objects
365  if( classicDetector.caloLV != 0 )
366  {
367    G4VSolid* solToDie = classicDetector.caloLV->GetSolid();
368    if( solToDie != 0 )
369    {
370      delete solToDie;
371    }
372    delete classicDetector.caloLV;
373    classicDetector.caloLV = 0;
374  }
375
376  if( plateLV != 0 )
377  {
378    G4VSolid* solToDie = plateLV->GetSolid();
379    if( solToDie != 0 )
380    {
381      delete solToDie;
382    }
383    delete plateLV;
384    plateLV = 0;
385  }
386
387  // Finally R.I.P. world instance
388  if( worldVol != 0 )
389  {
390    G4LogicalVolume* worldLV = worldVol->GetLogicalVolume();
391    if( worldLV != 0 )
392    {
393       G4VSolid* solToDie = worldLV->GetSolid();
394       if( solToDie != 0 )
395       {
396         delete solToDie;
397       }
398       delete worldLV;
399    }
400 
401    delete worldVol;
402    worldVol = 0;
403  }
404}
405
406void TstVADetectorConstruction::CleanAssembly()
407{
408  // Clean-up of assembly is simple :-)
409  if( assemblyDetector != 0 )
410  {
411    delete assemblyDetector;
412    assemblyDetector = 0;
413  }
414
415  // Clean the plates logical volume
416  if( plateLV != 0 )
417  {
418    G4VSolid* solToDie = plateLV->GetSolid();
419    if( solToDie != 0 )
420    {
421      delete solToDie;
422    }
423    delete plateLV;
424    plateLV = 0;
425  }
426 
427  // Finally R.I.P. world instance
428  if( worldVol != 0 )
429  {
430    G4LogicalVolume* worldLV = worldVol->GetLogicalVolume();
431    if( worldLV != 0 )
432    {
433       G4VSolid* solToDie = worldLV->GetSolid();
434       if( solToDie != 0 )
435       {
436         delete solToDie;
437       }
438       delete worldLV;
439    }
440 
441    delete worldVol;
442    worldVol = 0;
443  }
444}
445
Note: See TracBrowser for help on using the repository browser.