VMC Examples Version 6.8
Loading...
Searching...
No Matches
Ex03DetectorConstruction.cxx
Go to the documentation of this file.
1//------------------------------------------------
2// The Virtual Monte Carlo examples
3// Copyright (C) 2014 - 2018 Ivana Hrivnacova
4// All rights reserved.
5//
6// For the licensing terms see geant4_vmc/LICENSE.
7// Contact: root-vmc@cern.ch
8//-------------------------------------------------
9
10/// \file Ex03DetectorConstruction.cxx
11/// \brief Implementation of the Ex03DetectorConstruction class
12///
13/// Geant4 ExampleN03 adapted to Virtual Monte Carlo \n
14/// Id: ExN03DetectorConstruction.cc,v 1.11 2002/01/09 17:24:12 ranjard Exp \n
15///
16/// 11/12/2008:
17/// - Updated materials definition using directly Root objects
18/// - Added new materials according to:
19/// Id: ExN03DetectorConstruction.cc,v 1.24 2008/08/12 20:00:03 gum Exp
20/// GEANT4 tag Name: geant4-09-01-ref-09
21/// - Changed cuts in SetCuts() according to Geant4 09-01-ref-09
22///
23/// \date 06/03/2002
24/// \author I. Hrivnacova; IPN, Orsay
25
26#include <Riostream.h>
27#include <TGeoElement.h>
28#include <TGeoManager.h>
29#include <TGeoMaterial.h>
30#include <TGeoMatrix.h>
31#include <TList.h>
32#include <TThread.h>
33#include <TVirtualMC.h>
34
35#include <set>
36
37#include "Ex03DetectorConstruction.h"
38
39using namespace std;
40
41/// \cond CLASSIMP
43 /// \endcond
44
45 //_____________________________________________________________________________
47 : TObject(),
48 fNbOfLayers(0),
49 fWorldSizeX(0.),
50 fWorldSizeYZ(0.),
51 fCalorSizeYZ(0.),
52 fCalorThickness(0.),
53 fLayerThickness(0.),
54 fAbsorberThickness(0.),
55 fGapThickness(0.),
56 fDefaultMaterial("Galactic"),
57 fAbsorberMaterial("Lead"),
58 fGapMaterial("liquidArgon"),
59 fUseReflection(kFALSE),
60 fRequireReflectedHits(kFALSE)
61{
62 /// Default constuctor
63
64 // default parameter values of the calorimeter (in cm)
65 fAbsorberThickness = 1.;
66 fGapThickness = 0.5;
67 fNbOfLayers = 10;
68 fCalorSizeYZ = 10.;
69
70 ComputeCalorParameters();
71}
72
73//_____________________________________________________________________________
75{
76 /// Destructor
77}
78
79//
80// private methods
81//
82
83//_____________________________________________________________________________
85{
86 /// Compute derived parameters of the calorimeter
87
90
93}
94
95//
96// public methods
97//
98
99//_____________________________________________________________________________
101{
102 /// Construct materials using TGeo modeller
103
104 //
105 // Tracking medias (defaut parameters)
106 //
107
108 // Create Root geometry manager
109 new TGeoManager("E03_geometry", "E03 VMC example geometry");
110
111 //--------- Material definition ---------
112
113 TString name; // Material name
114 Double_t a; // Mass of a mole in g/mole
115 Double_t z; // Atomic number
116 Double_t density; // Material density in g/cm3
117
118 //
119 // define simple materials
120 //
121
122 new TGeoMaterial("Aluminium", a = 26.98, z = 13., density = 2.700);
123
124 new TGeoMaterial("liquidArgon", a = 39.95, z = 18., density = 1.390);
125
126 new TGeoMaterial("Lead", a = 207.19, z = 82., density = 11.35);
127
128 //
129 // define a material from elements. case 1: chemical molecule
130 //
131
132 // Elements
133
134 TGeoElement* elH = new TGeoElement("Hydrogen", "H", z = 1, a = 1.01);
135 TGeoElement* elC = new TGeoElement("Carbon", "C", z = 6., a = 12.01);
136 TGeoElement* elN = new TGeoElement("Nitrogen", "N", z = 7., a = 14.01);
137 TGeoElement* elO = new TGeoElement("Oxygen", "O", z = 8., a = 16.00);
138 TGeoElement* elSi = new TGeoElement("Silicon", "Si", z = 14., a = 28.09);
139
140 /*
141 // define an Element from isotopes, by relative abundance
142 // (cannot be done with TGeo)
143
144 G4Isotope* U5 = new G4Isotope("U235", iz=92, n=235, a=235.01*g/mole);
145 G4Isotope* U8 = new G4Isotope("U238", iz=92, n=238, a=238.03*g/mole);
146
147 G4Element* U = new G4Element("enriched Uranium",symbol="U",ncomponents=2);
148 U->AddIsotope(U5, abundance= 90.*perCent);
149 U->AddIsotope(U8, abundance= 10.*perCent);
150 */
151
152 TGeoMixture* matH2O = new TGeoMixture("Water", 2, density = 1.000);
153 matH2O->AddElement(elH, 2);
154 matH2O->AddElement(elO, 1);
155 // overwrite computed meanExcitationEnergy with ICRU recommended value
156 // (cannot be done with TGeo)
157 // H2O->GetIonisation()->SetMeanExcitationEnergy(75.0*eV);
158
159 TGeoMixture* matSci = new TGeoMixture("Scintillator", 2, density = 1.032);
160 matSci->AddElement(elC, 9);
161 matSci->AddElement(elH, 10);
162
163 TGeoMixture* matMyl = new TGeoMixture("Mylar", 3, density = 1.397);
164 matMyl->AddElement(elC, 10);
165 matMyl->AddElement(elH, 8);
166 matMyl->AddElement(elO, 4);
167
168 TGeoMixture* matSiO2 = new TGeoMixture("quartz", 2, density = 2.200);
169 matSiO2->AddElement(elSi, 1);
170 matSiO2->AddElement(elO, 2);
171
172 //
173 // define a material from elements. case 2: mixture by fractional mass
174 //
175
176 TGeoMixture* matAir = new TGeoMixture("Air", 2, density = 1.29e-03);
177 matAir->AddElement(elN, 0.7);
178 matAir->AddElement(elO, 0.3);
179
180 //
181 // Define a material from elements and/or others materials (mixture of
182 // mixtures)
183 //
184
185 TGeoMixture* matAerog = new TGeoMixture("Aerogel", 3, density = 0.200);
186 matAerog->AddElement(matSiO2, 0.625);
187 matAerog->AddElement(matH2O, 0.374);
188 matAerog->AddElement(elC, 0.001);
189
190 //
191 // examples of gas in non STP conditions
192 //
193
194 TGeoMixture* matCO2 = new TGeoMixture("CarbonicGas", 2, density = 1.842e-03);
195 matCO2->AddElement(elC, 1);
196 matCO2->AddElement(elO, 2);
197
198 Double_t atmosphere = 6.32421e+08;
199 Double_t pressure = 50. * atmosphere;
200 Double_t temperature = 325.;
201 matCO2->SetPressure(pressure);
202 matCO2->SetTemperature(temperature);
203 matCO2->SetState(TGeoMaterial::kMatStateGas);
204
205 TGeoMixture* matSteam = new TGeoMixture("WaterSteam", 1, density = 0.3e-03);
206 matSteam->AddElement(matH2O, 1.0);
207
208 pressure = 2. * atmosphere;
209 temperature = 500.;
210 matSteam->SetPressure(pressure);
211 matSteam->SetTemperature(temperature);
212 matSteam->SetState(TGeoMaterial::kMatStateGas);
213
214 //
215 // examples of vacuum
216 //
217
218 new TGeoMaterial("Galactic", a = 1.e-16, z = 1.e-16, density = 1.e-16);
219
220 TGeoMixture* matBeam = new TGeoMixture("Beam", 1, density = 1.e-5);
221 matBeam->AddElement(matAir, 1.0);
222
223 pressure = 2. * atmosphere;
224 temperature = STP_temperature;
225 matBeam->SetPressure(pressure);
226 matBeam->SetTemperature(temperature);
227 matBeam->SetState(TGeoMaterial::kMatStateGas);
228
229 //
230 // Tracking media
231 //
232
233 // Paremeter for tracking media
234 Double_t param[20];
235 param[0] = 0; // isvol - Not used
236 param[1] = 2; // ifield - User defined magnetic field
237 param[2] = 10.; // fieldm - Maximum field value (in kiloGauss)
238 param[3] = -20.; // tmaxfd - Maximum angle due to field deflection
239 param[4] = -0.01; // stemax - Maximum displacement for multiple scat
240 param[5] = -.3; // deemax - Maximum fractional energy loss, DLS
241 param[6] = .001; // epsil - Tracking precision
242 param[7] = -.8; // stmin
243 for (Int_t i = 8; i < 20; ++i) param[i] = 0.;
244
245 Int_t mediumId = 0;
246 TList* materials = gGeoManager->GetListOfMaterials();
247 TIter next(materials);
248 while (TObject* obj = next()) {
249 TGeoMaterial* material = (TGeoMaterial*)obj;
250 new TGeoMedium(material->GetName(), ++mediumId, material, param);
251 }
252}
253
254//_____________________________________________________________________________
256{
257 /// Contruct volumes using TGeo modeller
258
259 // Complete the Calor parameters definition
261
262 Double_t* ubuf = 0;
263
264 // Media Ids
265 Int_t defaultMediumId =
266 gGeoManager->GetMedium(fDefaultMaterial.Data())->GetId();
267 Int_t absorberMediumId =
268 gGeoManager->GetMedium(fAbsorberMaterial.Data())->GetId();
269 Int_t gapMediumId = gGeoManager->GetMedium(fGapMaterial.Data())->GetId();
270
271 //
272 // World
273 //
274
275 Double_t world[3];
276 world[0] = fWorldSizeX / 2.;
277 world[1] = fWorldSizeYZ / 2.;
278 world[2] = fWorldSizeYZ / 2.;
279 TGeoVolume* top =
280 gGeoManager->Volume("WRLD", "BOX", defaultMediumId, world, 3);
281 gGeoManager->SetTopVolume(top);
282
283 //
284 // Calorimeter
285 //
286 if (fCalorThickness > 0.) {
287
288 Double_t calo[3];
289 calo[0] = fCalorThickness / 2.;
290 calo[1] = fCalorSizeYZ / 2.;
291 calo[2] = fCalorSizeYZ / 2.;
292 gGeoManager->Volume("CALO", "BOX", defaultMediumId, calo, 3);
293
294 Double_t posX = 0.;
295 Double_t posY = 0.;
296 Double_t posZ = 0.;
297 gGeoManager->Node("CALO", 1, "WRLD", posX, posY, posZ, 0, kTRUE, ubuf);
298
299 // Divide calorimeter along X axis to place layers
300 //
301 Double_t start = -calo[0];
302 Double_t width = fCalorThickness / fNbOfLayers;
303 gGeoManager->Division("CELL", "CALO", 1, fNbOfLayers, start, width);
304
305 //
306 // Layer
307 //
308 Double_t layer[3];
309 layer[0] = fLayerThickness / 2.;
310 layer[1] = fCalorSizeYZ / 2.;
311 layer[2] = fCalorSizeYZ / 2.;
312 gGeoManager->Volume("LAYE", "BOX", defaultMediumId, layer, 3);
313
314 posX = 0.;
315 posY = 0.;
316 posZ = 0.;
317 gGeoManager->Node("LAYE", 1, "CELL", posX, posY, posZ, 0, kTRUE, ubuf);
318 }
319
320 //
321 // Absorber
322 //
323
324 if (fAbsorberThickness > 0.) {
325
326 Double_t abso[3];
327 abso[0] = fAbsorberThickness / (fUseReflection ? 4. : 2.);
328 abso[1] = fCalorSizeYZ / 2.;
329 abso[2] = fCalorSizeYZ / 2.;
330 gGeoManager->Volume("ABSO", "BOX", absorberMediumId, abso, 3);
331
332 Double_t posX = -fGapThickness / 2.;
333 Double_t posY = 0.;
334 Double_t posZ = 0.;
335 if (fUseReflection) {
336 // Two adjacent halves retain the original material thickness.
337 // Copy 2 is reflected; copy 1 uses an ordinary translation.
338 auto volume = gGeoManager->GetVolume("ABSO");
339 auto mother = gGeoManager->GetVolume("LAYE");
340 mother->AddNode(volume, 1, new TGeoTranslation(posX + abso[0], 0., 0.));
341 auto reflection = new TGeoHMatrix();
342 reflection->ReflectX(kTRUE);
343 reflection->SetDx(posX - abso[0]);
344 mother->AddNode(volume, 2, reflection);
345 }
346 else {
347 gGeoManager->Node("ABSO", 1, "LAYE", posX, posY, posZ, 0, kTRUE, ubuf);
348 }
349 }
350
351 //
352 // Gap
353 //
354
355 if (fGapThickness > 0.) {
356
357 Double_t gap[3];
358 gap[0] = fGapThickness / (fUseReflection ? 4. : 2.);
359 gap[1] = fCalorSizeYZ / 2.;
360 gap[2] = fCalorSizeYZ / 2.;
361 gGeoManager->Volume("GAPX", "BOX", gapMediumId, gap, 3);
362
363 Double_t posX = fAbsorberThickness / 2.;
364 Double_t posY = 0.;
365 Double_t posZ = 0.;
366 if (fUseReflection) {
367 // Two adjacent halves retain the original material thickness.
368 // Copy 2 is reflected; copy 1 uses an ordinary translation.
369 auto volume = gGeoManager->GetVolume("GAPX");
370 auto mother = gGeoManager->GetVolume("LAYE");
371 mother->AddNode(volume, 1, new TGeoTranslation(posX + gap[0], 0., 0.));
372 auto reflection = new TGeoHMatrix();
373 reflection->ReflectX(kTRUE);
374 reflection->SetDx(posX - gap[0]);
375 mother->AddNode(volume, 2, reflection);
376 }
377 else {
378 gGeoManager->Node("GAPX", 1, "LAYE", posX, posY, posZ, 0, kTRUE, ubuf);
379 }
380 }
381
382 /*
383 //
384 // Visualization attributes
385 //
386 logicWorld->SetVisAttributes (G4VisAttributes::Invisible);
387 G4VisAttributes* simpleBoxVisAtt= new
388 G4VisAttributes(G4Colour(1.0,1.0,1.0));
389 simpleBoxVisAtt->SetVisibility(true);
390 logicCalor->SetVisAttributes(simpleBoxVisAtt);
391 */
392
393 // close geometry
394 gGeoManager->CloseGeometry();
395
396 // notify VMC about Root geometry
397 gMC->SetRootGeometry();
398
400}
401
402//_____________________________________________________________________________
404{
405 /// Set cuts for e-, gamma equivalent to 1mm cut in G4.
406
407 // created material names
408 std::set<TString> createdMaterials;
409 createdMaterials.insert(fDefaultMaterial);
410 createdMaterials.insert(fAbsorberMaterial);
411 createdMaterials.insert(fGapMaterial);
412
413 // Cuts for e-, gamma equivalent to 1mm cut in G4,
414 // or 10keV (minimal value accepted by Geant3) if lower
415 std::vector<MaterialCuts> materialCutsVector = {
416 MaterialCuts("Aluminium", 10.e-06, 10.e-06, 597.e-06, 597.e-06),
417 MaterialCuts("liquidArgon", 10.e-06, 10.e-06, 342.9e-06, 342.9e-06),
418 MaterialCuts("Lead", 100.5e-06, 100.5e-06, 1.378e-03, 1.378e-03),
419 MaterialCuts("Water", 10.e-06, 10.e-06, 347.2e-06, 347.2e-06),
420 MaterialCuts("Scintillator", 10.e-06, 10.e-06, 355.8e-06, 355.8e-06),
421 MaterialCuts("Mylar", 10.e-06, 10.e-06, 417.5e-06, 417.5e-06),
422 MaterialCuts("quartz", 10.e-06, 10.e-06, 534.1e-06, 534.1e-06),
423 MaterialCuts("Air", 10.e-06, 10.e-06, 10.e-06, 10.e-06),
424 MaterialCuts("Aerogel", 10.e-06, 10.e-06, 119.0e-06, 119.0e-06),
425 MaterialCuts("CarbonicGas", 10.e-09, 10.e-06, 10.e-06, 10.e-06),
426 MaterialCuts("WaterSteam", 10.e-06, 10.e-06, 10.e-06, 10.e-06),
427 MaterialCuts("Galactic", 10.e-06, 10.e-06, 10.e-06, 10.e-06),
428 MaterialCuts("Beam", 10.e-06, 10.e-06, 10.e-06, 10.e-06)
429 };
430
431 // set VMC cutes for created media
432 for (auto materialCuts : materialCutsVector) {
433 // skip materials which were not created (to avoid warning)
434 if (createdMaterials.find(materialCuts.fName) == createdMaterials.end())
435 continue;
436 // set VMC cutes for the medium
437 Int_t mediumId = gMC->MediumId(materialCuts.fName);
438 if (mediumId) {
439 // Set cuts as defined in the vector
440 // gMC->Gstpar(mediumId, "CUTGAM", materialCuts.fCUTGAM);
441 // gMC->Gstpar(mediumId, "BCUTE", materialCuts.fBCUTE);
442 // gMC->Gstpar(mediumId, "CUTELE", materialCuts.fCUTELE);
443 // gMC->Gstpar(mediumId, "DCUTE", materialCuts.fDCUTE);
444 //
445 // Set 100 keV cut everywhere
446 Double_t cut = 100.e-06;
447 gMC->Gstpar(mediumId, "CUTGAM", cut);
448 gMC->Gstpar(mediumId, "BCUTE", cut);
449 gMC->Gstpar(mediumId, "CUTELE", cut);
450 gMC->Gstpar(mediumId, "DCUTE", cut);
451 }
452 }
453}
454
455//_____________________________________________________________________________
457{
458 /// This function demonstrate how to inactivate physics processes via VMC
459 /// controls. Here gamma processes are inactivated in Lead medium. Note that
460 /// while in Geant3 this mechanism is used to speed-up simulation, this may
461 /// cause slow down in Geant4 simulation where implementation of this
462 /// mechanism is quite tricky.
463
464 Int_t mediumId = gMC->MediumId("Lead");
465 if (mediumId) {
466 gMC->Gstpar(mediumId, "COMP", 0);
467 gMC->Gstpar(mediumId, "PAIR", 0);
468 gMC->Gstpar(mediumId, "PHOT", 0);
469 }
470}
471
472//_____________________________________________________________________________
474{
475 /// Print calorimeter parameters
476
477 cout << "\n------------------------------------------------------------"
478 << "\n---> The calorimeter is " << fNbOfLayers << " layers of: [ "
479 << fAbsorberThickness << "cm of " << fAbsorberMaterial << " + "
480 << fGapThickness << "cm of " << fGapMaterial << " ] "
481 << "\n------------------------------------------------------------\n";
482}
483
484//_____________________________________________________________________________
486{
487 /// Set the number of layers.
488 /// \param value The new number of calorimeter layers
489
490 fNbOfLayers = value;
491}
492
493//_____________________________________________________________________________
494void Ex03DetectorConstruction::SetDefaultMaterial(const TString& materialName)
495{
496 /// Set default material
497 /// \param materialName The new default material name.
498
499 fDefaultMaterial = materialName;
500}
501
502//_____________________________________________________________________________
503void Ex03DetectorConstruction::SetAbsorberMaterial(const TString& materialName)
504{
505 /// Set absorer material
506 /// \param materialName The new absorber material name.
507
508 fAbsorberMaterial = materialName;
509}
510
511//_____________________________________________________________________________
512void Ex03DetectorConstruction::SetGapMaterial(const TString& materialName)
513{
514 /// Set gap material
515 /// \param materialName The new gap material name.
516
517 fGapMaterial = materialName;
518}
519
520//_____________________________________________________________________________
522{
523 /// Change the transverse size and recompute the calorimeter parameters
524 /// \param value The new calorimeter tranverse size
525
526 fCalorSizeYZ = value;
527}
528
529//_____________________________________________________________________________
531{
532 /// Change the absorber thickness and recompute the calorimeter parameters
533 /// \param value The new absorber thickness
534
535 fAbsorberThickness = value;
536}
537
538//_____________________________________________________________________________
540{
541 /// Change the gap thickness and recompute the calorimeter parameters
542 /// \param value The new gap thickness
543
544 fGapThickness = value;
545}
546
547/*
548//_____________________________________________________________________________
549void Ex03DetectorConstruction::UpdateGeometry()
550{
551// Not available in VMC
552}
553*/
The detector construction (via TGeo ).
Double_t fWorldSizeYZ
The world size y,z component.
Int_t fNbOfLayers
The number of calorimeter layers.
Bool_t fUseReflection
Enable reflected sensitive placements.
Double_t fGapThickness
The gap thickness.
TString fDefaultMaterial
The default material name.
void SetAbsorberThickness(Double_t value)
TString fAbsorberMaterial
The absorber material name.
Double_t fLayerThickness
The calorimeter layer thickness.
TString fGapMaterial
The gap material name.
Double_t fAbsorberThickness
The absorber thickness.
void SetAbsorberMaterial(const TString &materialName)
void SetDefaultMaterial(const TString &materialName)
Double_t fCalorThickness
The calorimeter thickness.
Double_t fWorldSizeX
The world size x component.
void SetGapMaterial(const TString &materialName)
Double_t fCalorSizeYZ
The calorimeter size y,z component.