VMC Examples Version 6.8
Loading...
Searching...
No Matches
Ex03dMCApplication.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 Ex03dMCApplication.cxx
11/// \brief Implementation of the Ex03dMCApplication class
12///
13/// Geant4 ExampleN03 adapted to Virtual Monte Carlo
14///
15/// \date 07/07/2026
16/// \author Radoslaw Karabowicz; GSI
17
18#include "Ex03dMCApplication.h"
19#include "Ex03DetectorConstructionOld.h"
20#include "Ex03PrimaryGenerator.h"
21#include "Ex03dMCStack.h"
22
23#include <TMCRootManager.h>
24
25#include <Riostream.h>
26#include <TGeoManager.h>
27#include <TGeoUniformMagField.h>
28#include <TInterpreter.h>
29#include <TPDGCode.h>
30#include <TParticle.h>
31#include <TROOT.h>
32#include <TRandom.h>
33#include <TVector3.h>
34#include <TVirtualGeoTrack.h>
35#include <TVirtualMC.h>
36
37using namespace std;
38
39/// \cond CLASSIMP
40ClassImp(Ex03dMCApplication)
41 /// \endcond
42
43 //_____________________________________________________________________________
44 Ex03dMCApplication::Ex03dMCApplication(const char* name, const char* title)
45 : TVirtualMCApplication(name, title),
46 fRootManager(0),
47 fPrintModulo(1),
48 fEventNo(0),
49 fVerbose(0),
50 fStack(0),
54 fMagField(0),
55 fOldGeometry(kFALSE),
56 fIsControls(kFALSE),
57 fIsMaster(kTRUE)
58{
59 /// Standard constructor
60 /// \param name The MC application name
61 /// \param title The MC application description
62
63 cout << "--------------------------------------------------------------"
64 << endl;
65 cout << " VMC Example E03" << endl;
66 cout << "--------------------------------------------------------------"
67 << endl;
68
69 // Create a user stack
70 fStack = new Ex03dMCStack(1000);
71
72 // Create detector construction
74
75 // Create a calorimeter SD
77
78 // Create a primary generator
80
81 // Constant magnetic field (in kiloGauss)
82 fMagField = new TGeoUniformMagField();
83}
84
85//_____________________________________________________________________________
87 : TVirtualMCApplication(origin.GetName(), origin.GetTitle()),
88 fRootManager(0),
90 fEventNo(0),
91 fVerbose(origin.fVerbose),
92 fStack(0),
96 fMagField(0),
98 fIsMaster(kFALSE),
101{
102 /// Copy constructor for cloning application on workers (in multithreading
103 /// mode) \param origin The source MC application
104
105 // Create new user stack
106 fStack = new Ex03dMCStack(1000);
107
108 // Create a calorimeter SD
111
112 // Create a primary generator
115
116 // Constant magnetic field (in kiloGauss)
117 fMagField = new TGeoUniformMagField(origin.fMagField->GetFieldValue()[0],
118 origin.fMagField->GetFieldValue()[1], origin.fMagField->GetFieldValue()[2]);
119}
120
121//_____________________________________________________________________________
124 fRootManager(0),
125 fPrintModulo(1),
126 fEventNo(0),
127 fStack(0),
131 fMagField(0),
132 fOldGeometry(kFALSE),
133 fIsControls(kFALSE),
134 fIsMaster(kTRUE)
135{
136 /// Default constructor
137}
138
139//_____________________________________________________________________________
141{
142 /// Destructor
143
144 delete fRootManager;
145 delete fStack;
146 if (fIsMaster) delete fDetConstruction;
147 delete fCalorimeterSD;
148 delete fPrimaryGenerator;
149 delete fMagField;
150 delete gMC;
151}
152
153//
154// private methods
155//
156
157//_____________________________________________________________________________
159{
160 /// Register stack in the Root manager.
161
162 if (fRootManager) {
163 // cout << "Ex03dMCApplication::RegisterStack: " << endl;
164 fStack->Register();
165 }
166}
167
168//
169// public methods
170//
171
172//_____________________________________________________________________________
174 const char* setup, TMCRootManager::StorageMode storageMode)
175{
176 fStorageMode = storageMode;
177 /// Initialize MC.
178 /// The selection of the concrete MC is done in the macro.
179 /// \param setup The name of the configuration macro
180 cout << "InitMC with "
181 << (fStorageMode == TMCRootManager::kTTree ? "TTree" : "RNTuple")
182 << " storage" << endl;
183
184 fVerbose.InitMC();
185
186 if (TString(setup) != "") {
187 gROOT->LoadMacro(setup);
188 gInterpreter->ProcessLine("Config()");
189 if (!gMC) {
190 Fatal(
191 "InitMC", "Processing Config() has failed. (No MC is instantiated.)");
192 }
193 }
194
195 TString fileModifier = "T";
196 if (fStorageMode == TMCRootManager::kRNTuple) fileModifier = "R";
197
198// MT support available from root v 5.34/18
199#if ROOT_VERSION_CODE >= 336402
200 // Create Root manager
201 if (!gMC->IsMT()) {
202 fRootManager = new TMCRootManager(
203 fileModifier + GetName(), fStorageMode, TMCRootManager::kWrite);
204 // fRootManager->SetDebug(true);
205 }
206 else if (fStorageMode == TMCRootManager::kRNTuple) {
207 fRootManager = new TMCRootManager(
208 fileModifier + GetName(), fStorageMode, TMCRootManager::kWrite);
209 }
210#else
211 // Create Root manager
213 new TMCRootManager(fileModifier + GetName(), TMCRootManager::kWrite);
214 // fRootManager->SetDebug(true);
215#endif
216
218
219 if (fStorageMode == TMCRootManager::kRNTuple) {
220 if (!gMC->IsMT()) {
221 fRootManager->CreateRNTuple();
222 }
223 else {
224 fRootManager->CreateRNTuple(true);
226 std::move(fRootManager->GetParallelRNTupleWriter());
227 }
228 }
229
230 gMC->SetStack(fStack);
231 gMC->SetMagField(fMagField);
232 gMC->Init();
233 gMC->BuildPhysics();
234}
235
236//_____________________________________________________________________________
237void Ex03dMCApplication::RunMC(Int_t nofEvents)
238{
239 /// Run MC.
240 /// \param nofEvents Number of events to be processed
241
242 fVerbose.RunMC(nofEvents);
243
244 gMC->ProcessRun(nofEvents);
245 FinishRun();
246}
247
248//_____________________________________________________________________________
250{
251 /// Finish MC run.
252
253 fVerbose.FinishRun();
254 // cout << "Ex03dMCApplication::FinishRun: " << endl;
255 if (fRootManager) {
256 fRootManager->WriteAll();
257 fRootManager->Close();
258 }
259}
260
261//_____________________________________________________________________________
266
267//_____________________________________________________________________________
269{
270 // Create Root manager
271 Int_t threadRank = 1;
272 // The real thread rank will be set in MCRootManager
273 if (fStorageMode == TMCRootManager::kRNTuple) {
274 fRootManager = new TMCRootManager(fParallelRNTupleWriter);
275 }
276 else {
277 TString fileModifier = "T";
278 fRootManager = new TMCRootManager(fileModifier + GetName(), fStorageMode,
279 TMCRootManager::kWrite, threadRank);
280 }
281
282 // Set data to MC
283 gMC->SetStack(fStack);
284 gMC->SetMagField(fMagField);
285
287
288 if (fStorageMode == TMCRootManager::kRNTuple) {
289 fRootManager->CreateRNTuple(true, true);
290 }
291}
292
293//_____________________________________________________________________________
295{
296 // cout << "Ex03dMCApplication::FinishWorkerRun: " << endl;
297 if (fRootManager) {
298 fRootManager->WriteAll();
299 if (fStorageMode != TMCRootManager::kRNTuple) fRootManager->Close();
300 }
301}
302
303//_____________________________________________________________________________
305{
306 /// Read \em i -th event and prints hits.
307 /// \param i The number of event to be read
308 if (!fRootManager) {
309 fRootManager = new TMCRootManager(GetName(), TMCRootManager::kRead);
310 }
311
312 fCalorimeterSD->Register();
314 fRootManager->ReadEvent(i);
315}
316
317//_____________________________________________________________________________
319{
320 /// Construct geometry using detector contruction class.
321 /// The detector contruction class is using TGeo functions or
322 /// TVirtualMC functions (if oldGeometry is selected)
323
324 fVerbose.ConstructGeometry();
325
326 if (!fOldGeometry) {
327 fDetConstruction->ConstructMaterials();
328 fDetConstruction->ConstructGeometry();
329 // TGeoManager::Import("geometry.root");
330 // gMC->SetRootGeometry();
331 }
332 else {
333 Ex03DetectorConstructionOld detConstructionOld;
334 detConstructionOld.ConstructMaterials();
335 detConstructionOld.ConstructGeometry();
336 }
337}
338
339//_____________________________________________________________________________
341{
342 /// Initialize geometry
343 fVerbose.InitGeometry();
344
345 fDetConstruction->SetCuts();
346
347 if (fIsControls) fDetConstruction->SetControls();
348
349 fCalorimeterSD->Initialize();
350}
351
352//_____________________________________________________________________________
354{
355 /// Example of user defined particle with user defined decay mode
356
357 fVerbose.AddParticles();
358
359 // Define particle
360 gMC->DefineParticle(1000020050, "He5", kPTHadron, 5.03427, 2.0, 0.002, "Ion",
361 0.0, 0, 1, 0, 0, 0, 0, 0, 5, kFALSE);
362
363 // Define the 2 body phase space decay for He5
364 Int_t mode[6][3];
365 Float_t bratio[6];
366
367 for (Int_t kz = 0; kz < 6; kz++) {
368 bratio[kz] = 0.;
369 mode[kz][0] = 0;
370 mode[kz][1] = 0;
371 mode[kz][2] = 0;
372 }
373 bratio[0] = 100.;
374 mode[0][0] = kNeutron; // neutron (2112)
375 mode[0][1] = 1000020040; // alpha
376
377 gMC->SetDecayMode(1000020050, bratio, mode);
378
379 // Overwrite a decay mode already defined in MCs
380 // Kaon Short: 310 normally decays in two modes
381 // pi+, pi- 68.61 %
382 // pi0, pi0 31.39 %
383 // and we force only the mode pi0, pi0
384
385 Int_t mode2[6][3];
386 Float_t bratio2[6];
387
388 for (Int_t kz = 0; kz < 6; kz++) {
389 bratio2[kz] = 0.;
390 mode2[kz][0] = 0;
391 mode2[kz][1] = 0;
392 mode2[kz][2] = 0;
393 }
394 bratio2[0] = 100.;
395 mode2[0][0] = kPi0; // pi0 (111)
396 mode2[0][1] = kPi0; // pi0 (111)
397
398 gMC->SetDecayMode(kK0Short, bratio2, mode2);
399}
400
401//_____________________________________________________________________________
403{
404 /// Example of user defined ion
405
406 fVerbose.AddIons();
407
408 gMC->DefineIon("MyIon", 34, 70, 12, 0.);
409}
410
411//_____________________________________________________________________________
413{
414 /// Fill the user stack (derived from TVirtualMCStack) with primary particles.
415
416 fVerbose.GeneratePrimaries();
417
418 TVector3 origin(fDetConstruction->GetWorldSizeX(),
419 fDetConstruction->GetCalorSizeYZ(), fDetConstruction->GetCalorSizeYZ());
420
421 fPrimaryGenerator->GeneratePrimaries(origin);
422}
423
424//_____________________________________________________________________________
426{
427 /// User actions at beginning of event
428
429 fVerbose.BeginEvent();
430
431 // Clear TGeo tracks (if filled)
432 if (TString(gMC->GetName()) == "TGeant3TGeo" &&
433 gGeoManager->GetListOfTracks() && gGeoManager->GetTrack(0) &&
434 ((TVirtualGeoTrack*)gGeoManager->GetTrack(0))->HasPoints()) {
435
436 gGeoManager->ClearTracks();
437 // if (gPad) gPad->Clear();
438 }
439
440 fEventNo++;
441 if (fEventNo % fPrintModulo == 0) {
442 cout << "\n---> Begin of event: " << fEventNo << endl;
443 // ??? How to do this in VMC
444 // HepRandom::showEngineStatus();
445 }
446}
447
448//_____________________________________________________________________________
450{
451 /// User actions at beginning of a primary track.
452 /// If test for user defined decay is activated,
453 /// the primary track ID is printed on the screen.
454
455 fVerbose.BeginPrimary();
456
457 if (fPrimaryGenerator->GetUserDecay()) {
458 cout << " Primary track ID = " << fStack->GetCurrentTrackNumber() << endl;
459 }
460}
461
462//_____________________________________________________________________________
464{
465 /// User actions at beginning of each track
466 /// If test for user defined decay is activated,
467 /// the decay products of the primary track (K0Short)
468 /// are printed on the screen.
469
470 fVerbose.PreTrack();
471
472 // print info about K0Short decay products
473 if (fPrimaryGenerator->GetUserDecay()) {
474 Int_t parentID = fStack->GetCurrentParentTrackNumber();
475
476 if (parentID >= 0 &&
477 fStack->GetParticle(parentID)->GetPdgCode() == kK0Short &&
478 fStack->GetCurrentTrack()->GetUniqueID() == kPDecay) {
479 // The production process is saved as TParticle unique ID
480 // via Ex03dMCStack
481
482 cout << " Current track " << fStack->GetCurrentTrack()->GetName()
483 << " is a decay product of Parent ID = "
484 << fStack->GetCurrentParentTrackNumber() << endl;
485 }
486 }
487}
488
489//_____________________________________________________________________________
491{
492 /// User actions at each step
493
494 // Work around for Fluka VMC, which does not call
495 // MCApplication::PreTrack()
496 //
497
498 static Int_t trackId = 0;
499 if (TString(gMC->GetName()) == "TFluka" &&
500 gMC->GetStack()->GetCurrentTrackNumber() != trackId) {
501 fVerbose.PreTrack();
502 trackId = gMC->GetStack()->GetCurrentTrackNumber();
503 }
504
505 fVerbose.Stepping();
506
507 fCalorimeterSD->ProcessHits();
508}
509
510//_____________________________________________________________________________
512{
513 /// User actions after finishing of each track
514
515 fVerbose.PostTrack();
516}
517
518//_____________________________________________________________________________
520{
521 /// User actions after finishing of a primary track
522
523 fVerbose.FinishPrimary();
524
525 if (fPrimaryGenerator->GetUserDecay()) {
526 cout << endl;
527 }
528}
529
530//_____________________________________________________________________________
532{
533 /// User actions after finishing of an event
534
535 fVerbose.FinishEvent();
536
537 // Geant3 + TGeo
538 // (use TGeo functions for visualization)
539 if (TString(gMC->GetName()) == "TGeant3TGeo") {
540
541 // Draw volume
542 gGeoManager->SetVisOption(0);
543 gGeoManager->SetTopVisible();
544 gGeoManager->GetTopVolume()->Draw();
545
546 // Draw tracks (if filled)
547 // Available when this feature is activated via
548 // gMC->SetCollectTracks(kTRUE);
549 if (gGeoManager->GetListOfTracks() && gGeoManager->GetTrack(0) &&
550 ((TVirtualGeoTrack*)gGeoManager->GetTrack(0))->HasPoints()) {
551
552 gGeoManager->DrawTracks("/*"); // this means all tracks
553 }
554 }
555
556 fRootManager->Fill();
557
558 if (fEventNo % fPrintModulo == 0) fCalorimeterSD->PrintTotal();
559
560 fCalorimeterSD->EndOfEvent();
561
562 fStack->Reset();
563}
Definition of the Ex03dMCApplication class.
The old detector construction (via VMC functions).
The detector construction (via TGeo ).
The primary generator.
The calorimeter sensitive detector.
Implementation of the TVirtualMCApplication.
TMCRootManager * fRootManager
Root manager.
virtual void GeneratePrimaries()
Ex03DetectorConstruction * fDetConstruction
Dector construction.
void RunMC(Int_t nofEvents)
virtual TVirtualMCApplication * CloneForWorker() const
TGeoUniformMagField * fMagField
Magnetic field.
Int_t fEventNo
Event counter.
std::shared_ptr< RNTParaWriter > fParallelRNTupleWriter
virtual void ConstructGeometry()
Ex03dMCApplication(const char *name, const char *title)
Ex03dCalorimeterSD * fCalorimeterSD
Calorimeter SD.
Bool_t fIsControls
Option to activate special controls.
TMCRootManager::StorageMode fStorageMode
Ex03PrimaryGenerator * fPrimaryGenerator
Primary generator.
Bool_t fOldGeometry
Option for geometry definition.
Ex03dMCStack * fStack
VMC stack.
void InitMC(const char *setup, TMCRootManager::StorageMode storageMode=TMCRootManager::kRNTuple)
TMCVerbose fVerbose
VMC verbose helper.
virtual void FinishRunOnWorker()
Bool_t fIsMaster
If is on master thread.
Int_t fPrintModulo
The event modulus number to be printed.
Implementation of the TVirtualMCStack interface.