VMC Examples Version 6.7
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
Ex03cMCApplication.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 Ex03cMCApplication.cxx
11/// \brief Implementation of the Ex03cMCApplication class
12///
13/// Geant4 ExampleN03 adapted to Virtual Monte Carlo
14///
15/// \date 21/08/2019
16/// \author Benedikt Volkel, CERN
17
18#include "Ex03cMCApplication.h"
19#include "Ex03PrimaryGenerator.h"
20#include "Ex03cMCStack.h"
21
22#include <TMCRootManager.h>
23
24#include <TMCManager.h>
25
26#include <Riostream.h>
27#include <TGeoManager.h>
28#include <TGeoUniformMagField.h>
29#include <TInterpreter.h>
30#include <TPDGCode.h>
31#include <TParticle.h>
32#include <TROOT.h>
33#include <TRandom.h>
34#include <TTimer.h>
35#include <TVector3.h>
36#include <TVirtualGeoTrack.h>
37#include <TVirtualMC.h>
38
39#include <TLorentzVector.h>
40
41using namespace std;
42
43/// \cond CLASSIMP
44ClassImp(Ex03cMCApplication)
45 /// \endcond
46
47 //_____________________________________________________________________________
49 const char* name, const char* title, Bool_t isMulti, Bool_t splitSimulation)
50 : TVirtualMCApplication(name, title),
51 fRootManager(0),
52 fPrintModulo(1),
53 fEventNo(0),
54 fVerbose(0),
55 fStack(0),
59 fMagField(0),
60 fOldGeometry(kFALSE),
61 fIsControls(kFALSE),
62 fIsMaster(kTRUE),
63 fIsMultiRun(isMulti),
64 fSplitSimulation(splitSimulation),
65 fG3Id(-1),
66 fG4Id(-1),
67 fDebug(0)
68{
69 /// Standard constructor
70 /// \param name The MC application name
71 /// \param title The MC application description
72
73 if (splitSimulation && !isMulti) {
74 Fatal("Ex03cMCApplication",
75 "Cannot split simulation between engines without \"isMulti\" being "
76 "switched on");
77 }
78
79 cout << "--------------------------------------------------------------"
80 << endl;
81 cout << " VMC Example E03c: new version with multiple engines" << endl;
82 cout << "--------------------------------------------------------------"
83 << endl;
84
85 // Create a user stack
86 fStack = new Ex03cMCStack(1000);
87
88 // Create detector construction
90
91 // Create a calorimeter SD
93
94 // Create a primary generator
96
97 // Constant magnetic field (in kiloGauss)
98 fMagField = new TGeoUniformMagField();
99
100 if (isMulti) {
101 RequestMCManager();
102 fMCManager->SetUserStack(fStack);
103 }
104}
105
106//_____________________________________________________________________________
108 : TVirtualMCApplication(origin.GetName(), origin.GetTitle()),
109 fRootManager(0),
111 fEventNo(0),
112 fVerbose(origin.fVerbose),
113 fStack(0),
117 fMagField(0),
119 fIsControls(origin.fIsControls),
120 fIsMaster(kFALSE),
121 fIsMultiRun(origin.fIsMultiRun),
123 fG3Id(origin.fG3Id),
124 fG4Id(origin.fG4Id),
125 fDebug(origin.fDebug)
126{
127 /// Copy constructor for cloning application on workers (in multithreading
128 /// mode) \param origin The source MC application
129
130 // Create new user stack
131 fStack = new Ex03cMCStack(1000);
132
133 // Create a calorimeter SD
136
137 // Create a primary generator
140
141 // Constant magnetic field (in kiloGauss)
142 fMagField = new TGeoUniformMagField(origin.fMagField->GetFieldValue()[0],
143 origin.fMagField->GetFieldValue()[1], origin.fMagField->GetFieldValue()[2]);
144}
145
146//_____________________________________________________________________________
149 fRootManager(0),
150 fPrintModulo(1),
151 fEventNo(0),
152 fStack(0),
156 fMagField(0),
157 fOldGeometry(kFALSE),
158 fIsControls(kFALSE),
159 fIsMaster(kTRUE),
160 fIsMultiRun(kFALSE),
161 fSplitSimulation(kFALSE),
162 fG3Id(-1),
163 fG4Id(-1),
164 fDebug(0)
165{
166 /// Default constructor
167}
168
169//_____________________________________________________________________________
171{
172 /// Destructor
173
174 // cout << "Ex03cMCApplication::~Ex03cMCApplication " << this << endl;
175
176 delete fRootManager;
177 delete fStack;
178 if (fIsMaster) delete fDetConstruction;
179 delete fCalorimeterSD;
180 delete fPrimaryGenerator;
181 delete fMagField;
182 if (!fIsMultiRun) {
183 delete fMC;
184 }
185
186 // cout << "Done Ex03cMCApplication::~Ex03cMCApplication " << this << endl;
187}
188
189//
190// private methods
191//
192
193//_____________________________________________________________________________
195{
196 /// Register stack in the Root manager.
197
198 if (fRootManager) {
199 // cout << "Ex03cMCApplication::RegisterStack: " << endl;
200 fRootManager->Register("stack", "Ex03cMCStack", &fStack);
201 }
202}
203
204//
205// public methods
206//
207
208//_____________________________________________________________________________
209void Ex03cMCApplication::InitMC(const char* setup)
210{
211 /// Initialize MC.
212 /// The selection (and creation) of the concrete MC is done in the macro.
213 /// If no macro is provided, the MC must be created before calling this
214 /// function. \param setup The name of the configuration macro.
215
216 fVerbose.InitMC();
217
218 if (TString(setup) != "") {
219 gROOT->LoadMacro(setup);
220 gInterpreter->ProcessLine("Config()");
221 if (!fMC) {
222 Fatal(
223 "InitMC", "Processing Config() has failed. (No MC is instantiated.)");
224 }
225 }
226
227// MT support available from root v 5.34/18
228#if ROOT_VERSION_CODE >= 336402
229 // Create Root manager
230 if (!fMC->IsMT()) {
231 fRootManager = new TMCRootManager(GetName(), TMCRootManager::kWrite);
232 // fRootManager->SetDebug(true);
233 }
234#else
235 // Create Root manager
236 fRootManager = new TMCRootManager(GetName(), TMCRootManager::kWrite);
237// fRootManager->SetDebug(true);
238#endif
239
240 fMC->SetStack(fStack);
241 fMC->SetRootGeometry();
242 fMC->SetMagField(fMagField);
243 fMC->Init();
244 fMC->BuildPhysics();
245
247
248 if (fDebug > 0) {
249 Info("InitMC", "Single run initialised");
250 }
251}
252
253//_____________________________________________________________________________
254void Ex03cMCApplication::InitMC(std::initializer_list<const char*> setupMacros)
255{
256 /// Initialize MC.
257 /// New function for initialization with multiple engines.
258 /// \param setupMacros The names of the configuration macros.
259
260 fVerbose.InitMC();
261
262 if (!fIsMultiRun) {
263 Fatal("InitMC",
264 "Initialisation of multiple engines not supported in single run");
265 }
266
267 if (setupMacros.size() > 0) {
268 for (const char* setup : setupMacros) {
269 gROOT->LoadMacro(setup);
270 gInterpreter->ProcessLine("Config()");
271 if (!fMC) {
272 Fatal(
273 "InitMC", "Processing Config() has failed. (No MC is instantiated.)");
274 }
275 // gInterpreter->UnloadAllSharedLibraryMaps();
276 gInterpreter->UnloadFile(setup);
277 }
278 }
279
280 InitMC();
281}
282
283//_____________________________________________________________________________
285{
286 /// Initialize MC.
287 /// New function for initialization with multiple engines.
288 /// The MCs must be created before calling this function.
289
290 if (!fIsMultiRun) {
291 Fatal("InitMC",
292 "Initialisation of multiple engines not supported in single run");
293 }
294
295// MT support available from root v 5.34/18
296#if ROOT_VERSION_CODE >= 336402
297 // Create Root manager
298 if (!fMC->IsMT()) {
299 fRootManager = new TMCRootManager(GetName(), TMCRootManager::kWrite);
300 // fRootManager->SetDebug(true);
301 }
302#else
303 // Create Root manager
304 fRootManager = new TMCRootManager(GetName(), TMCRootManager::kWrite);
305// fRootManager->SetDebug(true);
306#endif
307
308 fMCManager->Init([this](TVirtualMC* mc) {
309 mc->SetRootGeometry();
310 mc->SetMagField(this->fMagField);
311 mc->Init();
312 mc->BuildPhysics();
313 });
315
316 fG3Id = fMCManager->GetEngineId("TGeant3TGeo");
317 fG4Id = fMCManager->GetEngineId("TGeant4");
318 if (fDebug > 0) {
319 Info("InitMC", "Multi run initialised");
320 std::cout << "Engine IDs\n"
321 << "TGeant3TGeo: " << fG3Id << "\n"
322 << "TGeant4: " << fG4Id << std::endl;
323 }
324}
325
326//_____________________________________________________________________________
327void Ex03cMCApplication::RunMC(Int_t nofEvents)
328{
329 /// Run MC.
330 /// \param nofEvents Number of events to be processed
331
332 fVerbose.RunMC(nofEvents);
333
334 // Prepare a timer
335 TTimer timer;
336
337 if (!fIsMultiRun) {
338 if (fDebug > 0) {
339 Info("RunMC", "Start single run");
340 std::cout << "Simulation entirely done with engine " << fMC->GetName()
341 << std::endl;
342 timer.Start();
343 }
344 fMC->ProcessRun(nofEvents);
345 }
346 else {
347 if (fDebug > 0) {
348 Info("RunMC", "Start multi run");
349 if (fSplitSimulation) {
350 std::cout << "GAPX simulated with engine "
351 << fMCManager->GetEngine(0)->GetName() << "\n"
352 << "ABSO simulated with engine "
353 << fMCManager->GetEngine(1)->GetName() << std::endl;
354 }
355 else {
356 std::cout << "Simulation entirely done with engine "
357 << fMCManager->GetCurrentEngine()->GetName() << std::endl;
358 }
359 timer.Start();
360 }
361 fMCManager->Run(nofEvents);
362 }
363 if (fDebug > 0) {
364 timer.Stop();
365 Info("RunMC", "Transport finished.");
366 timer.Print();
367 }
368 FinishRun();
369}
370
371//_____________________________________________________________________________
373{
374 /// Finish MC run.
375
376 fVerbose.FinishRun();
377 // cout << "Ex03cMCApplication::FinishRun: " << endl;
378 if (fRootManager) {
379 fRootManager->WriteAll();
380 fRootManager->Close();
381 }
382}
383
384//_____________________________________________________________________________
389
390//_____________________________________________________________________________
392{
393 // cout << "Ex03cMCApplication::InitForWorker " << this << endl;
394
395 // Create Root manager
396 fRootManager = new TMCRootManager(GetName(), TMCRootManager::kWrite);
397 // fRootManager->SetDebug(true);
398
399 // Set data to MC
400 fMC->SetStack(fStack);
401 fMC->SetMagField(fMagField);
402
404}
405
406//_____________________________________________________________________________
408{
409 // cout << "Ex03cMCApplication::FinishWorkerRun: " << endl;
410 if (fRootManager) {
411 fRootManager->WriteAll();
412 fRootManager->Close();
413 }
414}
415
416//_____________________________________________________________________________
418{
419 /// Read \em i -th event and prints hits.
420 /// \param i The number of event to be read
421
422 fCalorimeterSD->Register();
424 fRootManager->ReadEvent(i);
425}
426
427//_____________________________________________________________________________
429{
430 /// Construct geometry using detector contruction class.
431 /// The detector contruction class is using TGeo functions or
432 /// TVirtualMC functions (if oldGeometry is selected)
433
434 fVerbose.ConstructGeometry();
435
436 if (fOldGeometry) {
437 Fatal("ConstructGeometry", "Cannot run with old geomtry");
438 }
439 fDetConstruction->ConstructMaterials();
440 fDetConstruction->ConstructGeometry();
441 // TGeoManager::Import("geometry.root");
442 // fMC->SetRootGeometry();
443}
444
445//_____________________________________________________________________________
447{
448 /// Initialize geometry
449
450 fVerbose.InitGeometry();
451
452 fDetConstruction->SetCuts();
453
454 if (fIsControls) fDetConstruction->SetControls();
455
456 fCalorimeterSD->Initialize();
457}
458
459//_____________________________________________________________________________
461{
462 /// Example of user defined particle with user defined decay mode
463
464 fVerbose.AddParticles();
465
466 // Define the 2 body phase space decay for He5
467 Int_t mode[6][3];
468 Float_t bratio[6];
469
470 for (Int_t kz = 0; kz < 6; kz++) {
471 bratio[kz] = 0.;
472 mode[kz][0] = 0;
473 mode[kz][1] = 0;
474 mode[kz][2] = 0;
475 }
476 bratio[0] = 100.;
477 mode[0][0] = kNeutron; // neutron (2112)
478 mode[0][1] = 1000020040; // alpha
479
480 // Overwrite a decay mode already defined in MCs
481 // Kaon Short: 310 normally decays in two modes
482 // pi+, pi- 68.61 %
483 // pi0, pi0 31.39 %
484 // and we force only the mode pi0, pi0
485
486 Int_t mode2[6][3];
487 Float_t bratio2[6];
488
489 for (Int_t kz = 0; kz < 6; kz++) {
490 bratio2[kz] = 0.;
491 mode2[kz][0] = 0;
492 mode2[kz][1] = 0;
493 mode2[kz][2] = 0;
494 }
495 bratio2[0] = 100.;
496 mode2[0][0] = kPi0; // pi0 (111)
497 mode2[0][1] = kPi0; // pi0 (111)
498
499 // Define particle
500 fMC->DefineParticle(1000020050, "He5", kPTHadron, 5.03427, 2.0, 0.002, "Ion",
501 0.0, 0, 1, 0, 0, 0, 0, 0, 5, kFALSE);
502 fMC->SetDecayMode(1000020050, bratio, mode);
503 fMC->SetDecayMode(kK0Short, bratio2, mode2);
504}
505
506//_____________________________________________________________________________
508{
509 /// Example of user defined ion
510
511 fVerbose.AddIons();
512 fMC->DefineIon("MyIon", 34, 70, 12, 0.);
513}
514
515//_____________________________________________________________________________
517{
518 /// Fill the user stack (derived from TVirtualMCStack) with primary particles.
519
520 fVerbose.GeneratePrimaries();
521
522 TVector3 origin(fDetConstruction->GetWorldSizeX(),
523 fDetConstruction->GetCalorSizeYZ(), fDetConstruction->GetCalorSizeYZ());
524
525 fPrimaryGenerator->GeneratePrimaries(origin);
526}
527
528//_____________________________________________________________________________
530{
531 /// User actions at beginning of event
532
533 fVerbose.BeginEvent();
534
535 // Clear TGeo tracks (if filled)
536 if (!fIsMultiRun && TString(fMC->GetName()) == "TGeant3TGeo" &&
537 gGeoManager->GetListOfTracks() && gGeoManager->GetTrack(0) &&
538 ((TVirtualGeoTrack*)gGeoManager->GetTrack(0))->HasPoints()) {
539
540 gGeoManager->ClearTracks();
541 // if (gPad) gPad->Clear();
542 }
543
544 fEventNo++;
545 if (fEventNo % fPrintModulo == 0) {
546 cout << "\n---> Begin of event: " << fEventNo << endl;
547 // ??? How to do this in VMC
548 // HepRandom::showEngineStatus();
549 }
550}
551
552//_____________________________________________________________________________
554{
555 /// User actions at beginning of a primary track.
556 /// If test for user defined decay is activated,
557 /// the primary track ID is printed on the screen.
558
559 fVerbose.BeginPrimary();
560
561 if (fPrimaryGenerator->GetUserDecay()) {
562 cout << " Primary track ID = " << fStack->GetCurrentTrackNumber() << endl;
563 }
564}
565
566//_____________________________________________________________________________
568{
569 /// User actions at beginning of each track
570 /// If test for user defined decay is activated,
571 /// the decay products of the primary track (K0Short)
572 /// are printed on the screen.
573
574 fVerbose.PreTrack();
575
576 // print info about K0Short decay products
577 if (fPrimaryGenerator->GetUserDecay()) {
578 Int_t parentID = fStack->GetCurrentParentTrackNumber();
579
580 if (parentID >= 0 &&
581 fStack->GetParticle(parentID)->GetPdgCode() == kK0Short &&
582 fStack->GetCurrentTrack()->GetUniqueID() == kPDecay) {
583 // The production process is saved as TParticle unique ID
584 // via Ex03cMCStack
585
586 cout << " Current track " << fStack->GetCurrentTrack()->GetName()
587 << " is a decay product of Parent ID = "
588 << fStack->GetCurrentParentTrackNumber() << endl;
589 }
590 }
591}
592
593//_____________________________________________________________________________
595{
596 /// User actions at each step
597
598 fVerbose.Stepping();
599
600 fCalorimeterSD->ProcessHits();
601
602 TLorentzVector pos;
603 TLorentzVector mom;
604
605 fMC->TrackPosition(pos);
606 fMC->TrackMomentum(mom);
607
608 if (fDebug > 1) {
609 std::cout << "Current engine " << fMC->GetName() << "\n"
610 << "Track ID=" << fStack->GetCurrentTrackNumber() << "\n"
611 << "Momentum\n"
612 << "E=" << mom.T() << ", Px=" << mom.X() << ", Py=" << mom.Y()
613 << ", Pz=" << mom.Z() << std::endl;
614 }
615
616 // Now transfer track
617 if (fSplitSimulation) {
618 Int_t targetId = -1;
619 if (fMC->GetId() == 0 && strcmp(fMC->CurrentVolName(), "ABSO") == 0) {
620 targetId = 1;
621 }
622 else if (fMC->GetId() == 1 && strcmp(fMC->CurrentVolName(), "GAPX") == 0) {
623 targetId = 0;
624 }
625 if (targetId > -1) {
626 if (fDebug > 1) {
627 Info("Stepping", "Transfer track");
628 }
629 fMCManager->TransferTrack(targetId);
630 }
631 }
632}
633
634//_____________________________________________________________________________
636{
637 /// User actions after finishing of each track
638 fVerbose.PostTrack();
639}
640
641//_____________________________________________________________________________
643{
644 /// User actions after finishing of a primary track
645
646 fVerbose.FinishPrimary();
647
648 if (fPrimaryGenerator->GetUserDecay()) {
649 cout << endl;
650 }
651}
652
653//_____________________________________________________________________________
655{
656 /// User actions after finishing of an event
657
658 fVerbose.FinishEvent();
659
660 // Geant3 + TGeo
661 // (use TGeo functions for visualization)
662 if (!fIsMultiRun && TString(fMC->GetName()) == "TGeant3TGeo") {
663
664 // Draw volume
665 gGeoManager->SetVisOption(0);
666 gGeoManager->SetTopVisible();
667 gGeoManager->GetTopVolume()->Draw();
668
669 // Draw tracks (if filled)
670 // Available when this feature is activated via
671 // fMC->SetCollectTracks(kTRUE);
672 if (gGeoManager->GetListOfTracks() && gGeoManager->GetTrack(0) &&
673 ((TVirtualGeoTrack*)gGeoManager->GetTrack(0))->HasPoints()) {
674
675 gGeoManager->DrawTracks("/*"); // this means all tracks
676 }
677 }
678
679 fRootManager->Fill();
680
681 if (fEventNo % fPrintModulo == 0) fCalorimeterSD->PrintTotal();
682
683 fCalorimeterSD->EndOfEvent();
684
685 fStack->Reset();
686}
Definition of the Ex03cMCApplication class.
Definition of the Ex03cMCStack class.
The primary generator.
The calorimeter sensitive detector.
The detector construction (via TGeo )
Implementation of the TVirtualMCApplication.
Ex03cMCApplication(const char *name, const char *title, Bool_t isMulti=kFALSE, Bool_t splitSimulation=kFALSE)
TGeoUniformMagField * fMagField
Magnetic field.
TMCRootManager * fRootManager
Root manager.
Ex03PrimaryGenerator * fPrimaryGenerator
Primary generator.
Ex03cDetectorConstruction * fDetConstruction
Dector construction.
Int_t fG3Id
engine ID of Geant3
TMCVerbose fVerbose
VMC verbose helper.
Ex03cCalorimeterSD * fCalorimeterSD
Calorimeter SD.
virtual void GeneratePrimaries()
void RunMC(Int_t nofEvents)
Bool_t fOldGeometry
Option for geometry definition.
Bool_t fIsControls
Option to activate special controls.
Int_t fPrintModulo
The event modulus number to be printed.
Bool_t fIsMultiRun
Flag if having multiple engines.
virtual TVirtualMCApplication * CloneForWorker() const
Bool_t fIsMaster
If is on master thread.
Bool_t fSplitSimulation
Split geometry given user criteria.
Ex03cMCStack * fStack
VMC stack.
Int_t fEventNo
Event counter.
virtual void ConstructGeometry()
virtual void FinishRunOnWorker()
Int_t fG4Id
engine ID of Geant4
Int_t fDebug
debug option for multiple run
Implementation of the TVirtualMCStack interface.