Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

MCApplication.cxx

Go to the documentation of this file.
00001 
00002 //
00003 // MCApplication
00004 //
00005 // MCApplication is a pure virtual base class to be used to define the required
00006 // interface of derived vmc Application classes, e.g. PTSimApplication
00007 // and GeoSwimmerApplication.
00008 //
00009 // Author:  S. Kasahara 10/06
00010 //
00011 // Notes: This class contains a subset of the methods defined in
00012 //        $ROOTSYS/vmc/inc/TVirtualMCApplication class.
00013 //
00015 
00016 #include <TVirtualMC.h>
00017 #include <TInterpreter.h>
00018 #include <TRandom3.h>
00019 #include <TROOT.h>
00020 #include <TSystem.h>
00021 #include <TDatabasePDG.h>
00022 
00023 #include "Util/UtilPDG.h"
00024 #include "Util/UtilMCFlag.h"
00025 using namespace UtilMCFlag;
00026 #include "Util/LoadMinosPDG.h"
00027 #include "MCApplication/MCApp.h" // for process/cut flags
00028 #include "MCApplication/MCApplication.h"
00029 #include "MessageService/MsgService.h"
00030 #include "BField/BField.h"
00031 #include "GeoGeometry/GeoMedium.h"
00032 
00033 ClassImp(MCApplication)
00034 
00035 CVSID("$Id: MCApplication.cxx,v 1.21 2009/06/22 03:51:00 kasahara Exp $");
00036 
00037 //_____________________________________________________________________________
00038 const MCApplication& MCApplication::Instance() {
00039   // Access to singleton instance of MCApplication
00040 
00041   // fgInstance belongs to base class
00042   if ( !TVirtualMCApplication::Instance() ) {
00043     // Construct an Instance of this
00044     static MCApplication::Cleaner c;
00045     c.ClassIsUsed();
00046     new MCApplication("MCApplication","MINOS MC Application");
00047   }
00048   
00049   return dynamic_cast<const MCApplication&>
00050                      (*(TVirtualMCApplication::Instance()));
00051   
00052 }
00053   
00054 //_____________________________________________________________________________
00055 MCApplication::MCApplication(const char *name, const char *title) 
00056   : TVirtualMCApplication(name,title), fMCAppUser(0),fMC(0),
00057     fUgliGeomHandle(0),fVldContext(),fBField(0),fBFldInZTestSave(0),fRandom(0),
00058     fMCConfigScript(""),fDecayConfigScript(""),fLogLevel(kInfo) {
00059   // Normal constructor.  Private.  Use MCApplication::Instance() to
00060   // construct Instance of MCApplication singleton.
00061 
00062   MSG("MCApp",Msg::kDebug) << "MCApplication normal ctor @ " << this << endl;
00063 
00064   // Initialize random number generator
00065   fRandom = new TRandom3();
00066 
00067   LoadMinosPDG(); // initialize MINOS specific particles
00068   
00069 }
00070 
00071 
00072 //_____________________________________________________________________________
00073 MCApplication::~MCApplication() {
00074   // Destructor.  Delete all owned sub-objects
00075 
00076   MSG("MCApp",Msg::kDebug) << "MCApplication dtor @ " << this << endl;
00077 
00078   Clear(); // clear dynamically allocated memory
00079 
00080 }
00081 
00082 //_____________________________________________________________________________
00083 void MCApplication::Clear(const Option_t* /* option */) {
00084   // Protected method to Clear dynamically allocated memory.  
00085 
00086   // fMCAppUser not owned.
00087   if ( fUgliGeomHandle ) delete fUgliGeomHandle; fUgliGeomHandle = 0;
00088   if ( fBField ) delete fBField; fBField = 0;
00089   if ( fRandom ) delete fRandom; fRandom = 0;
00090   if ( fMC ) delete fMC; fMC = 0;
00091 
00092 }
00093 
00094 //_____________________________________________________________________________
00095 void MCApplication::SetUserApplication(MCAppUser* appuser) {
00096   // Set new user application to be called during particle tranport
00097 
00098   fMCAppUser = appuser;
00099   if ( fMC ) fMC -> SetStack(fMCAppUser->GetStack());
00100  
00101 }
00102   
00103 //_____________________________________________________________________________
00104 void MCApplication::InitMC(const char* mcconfigscript, const VldContext& vldc,
00105                            const char* decayconfigscript) {
00106   // Initialize MC through execution of configuration script. Can only
00107   // be done once.   Also initialize geometry appropriate for input validity
00108   // context.  
00109 
00110   // Store vldcontext to be used in construction of geometry
00111   fVldContext = vldc;
00112   fMCConfigScript = mcconfigscript;
00113   fDecayConfigScript = decayconfigscript;
00114   fLogLevel = MsgService::Instance()->GetStream("MCApp")->GetLogLevel();
00115   
00116   // Initialize MC from configuration script
00117   if ( fMC ) { 
00118     MSG("MCApp",Msg::kWarning) << "MCApplication::InitMC called with script "
00119        << fMCConfigScript.c_str() << "\nbut MC already initialized. Ignored." 
00120        << endl;
00121     return;
00122   }
00123   if ( fMCConfigScript.empty() || fMCConfigScript == std::string("<null>") ) {
00124     MSG("MCApp",Msg::kFatal) << "MCApplication::InitMC called with null "
00125                              << " configuration script." << endl;
00126     abort();
00127   }
00128   
00129   // Print, load, and execute configuration script
00130   std::string mcConfigScriptPath = gSystem->Which(gROOT->GetMacroPath(),
00131                                    fMCConfigScript.c_str(),kReadPermission);
00132   if ( mcConfigScriptPath.empty() ) {
00133     MSG("MCApp",Msg::kError) << "MCApplication::InitMC configuration script "
00134                            << fMCConfigScript.c_str() << " not found in path "
00135                            << gROOT->GetMacroPath() << ". Abort." << endl;
00136     abort();
00137   }
00138     
00139   MSG("MCApp",Msg::kInfo) 
00140           << "MCApplication::InitMC initializing MC with configuration script "
00141           << mcConfigScriptPath.c_str() << ":" << endl;
00142 
00143   if ( fLogLevel <= Msg::kInfo ) {
00144     std::string printstr = ".!cat -n " + mcConfigScriptPath;
00145     gInterpreter->ProcessLineSynch(printstr.c_str());
00146   }
00147   gROOT->LoadMacro(mcConfigScriptPath.c_str());
00148   gInterpreter->ProcessLineSynch("Config()");
00149   
00150   if ( !gMC ) {
00151     MSG("MCApp",Msg::kFatal) << "Construction of MC implementation failed."
00152                              << endl;
00153     abort();
00154   }
00155   fMC = gMC;
00156 
00157   // Now begin initialization of MC
00158 
00159   // random number generator can be seeded in BeginEvent by user app
00160   fMC -> SetRandom(fRandom); 
00161   if ( fMCAppUser ) fMC -> SetStack(fMCAppUser->GetStack());
00162   // Init() will call MCApplication::AddParticles() to define additional
00163   // particles not defined in MC by default and 
00164   // MCApplication::ConstructGeometry to build geometry
00165   fMC -> Init(); 
00166 
00167   // Initialize parameters of swim media for continuous energy loss
00168   // This has to be done after Init() method has been called, but before
00169   // BuildPhysics();
00170   InitMedia();
00171   
00172   fMC -> BuildPhysics();
00173   
00174 }
00175 
00176 //_____________________________________________________________________________
00177 bool MCApplication::InitSnarl(const VldContext& vldc) {
00178   // Initialize Snarl according to current VldContext.  
00179 
00180   bool isOkay = true;
00181 
00182   if ( !fBField || !fUgliGeomHandle ) {
00183     MSG("MCApp",Msg::kError) << "InitSnarl w/" << vldc
00184                              << " called before InitMC. Abort." 
00185                              << endl;
00186     abort();
00187   }
00188   
00189   // Reset BField to match snarl vldcontext
00190   fBField -> ResetVldContext(vldc);
00191 
00192   // Check that Geometry hasn't changed.  
00193   const VldRange& vldrange = fUgliGeomHandle -> GetVldRange();
00194   
00195   if ( !(vldrange.IsCompatible(vldc)) ) {
00196     MSG("MCApp",Msg::kError) << "InitSnarl w/vld " << vldc
00197                              << " is incompatible with VMC Geometry vld "
00198                              << vldrange << ". Abort." << endl;
00199     abort();
00200   }
00201   
00202   return isOkay;
00203   
00204 }
00205 
00206 //_____________________________________________________________________________
00207 void MCApplication::FatalNoApp() const {
00208   // Issue fatal warning message and abort
00209 
00210   MSG("MCApp",Msg::kFatal) << "MCApplication has null fMCAppUser. abort."
00211                            << endl;
00212   abort();
00213   
00214 }
00215 
00216 //_____________________________________________________________________________
00217 void MCApplication::ConstructGeometry() {
00218   // Construct geometry.  Called once during initialization by 
00219   // TVirtualMC::Init()
00220 
00221   MSG("MCApp",Msg::kDebug) << "MCApplication::ConstructGeometry for vldc "
00222                            << fVldContext.AsString() << endl;
00223   
00224   if ( fUgliGeomHandle ) { 
00225     MSG("MCApp",Msg::kFatal) 
00226     << "ConstructGeometry called but fUgliGeomHandle non-null. abort." << endl;
00227     abort();
00228   }
00229   if ( !fVldContext.IsValid() ) {
00230     MSG("MCApp",Msg::kFatal)
00231       << "ConstructGeometry but invalid fVldContext. abort." << endl;
00232     abort();
00233   }
00234 
00235   fUgliGeomHandle = new UgliGeomHandle(fVldContext);
00236   fBField = new BField(fVldContext);
00237 
00238   // Update gGeoManager to guarantee that it points to the right place before
00239   // returning
00240   UpdateGlobalGeoManager();
00241 
00242   // Notify VMC about ROOT geometry
00243   gMC -> SetRootGeometry();
00244  
00245   return;
00246   
00247 }
00248 
00249 //_____________________________________________________________________________
00250 void MCApplication::AddParticles() {
00251   // Define particles beyond those defined by MC.  Called once during 
00252   // initialization by concrete MC.
00253   // Also define additional or redefine existing Geant3 decay modes.
00254 
00255   MSG("MCApp",Msg::kDebug) << "MCApplication::AddParticles" << endl;
00256 
00257   // Define ion types
00258   AddIons();
00259 
00260   // Define decay modes 
00261   AddDecayModes();
00262 
00263   return;
00264   
00265 }
00266 
00267 //_____________________________________________________________________________
00268 void MCApplication::AddIons() {
00269   // Private method to define ions to be used in monte carlo simulation.
00270   // Called by AddParticles() during initialization.
00271   // Ions are defined according to ion particle definitions in
00272   // TDatabasePDG, as filled by LoadMinosPDG, using pdg-2006 particle
00273   // codes.
00274 
00275   MSG("MCApp",Msg::kDebug) << "MCApplication::AddIons" << endl;
00276 
00277   // Loop over particles defined in TDatabasePDG and define
00278   // those up to z = zmax to Monte Carlo
00279   const Int_t zmax = 28;
00280 
00281   const TDatabasePDG& dbpdg = *(TDatabasePDG::Instance());
00282   TIter next(dbpdg.ParticleList());
00283   TParticlePDG* particle = 0;
00284   Int_t ia,iz,ij;
00285   Double_t lifetime = 1.e20; // lifetime in sec, stable for all ions
00286 
00287   while ((particle = (TParticlePDG*)next())) {
00288     Int_t pdgcode = particle -> PdgCode();
00289     UtilPDG::ionscheme_t ionscheme = UtilPDG::getIonAZJ(pdgcode,ia,iz,ij);
00290     if ( ionscheme == UtilPDG::kPDG2006 && iz <= zmax ) {
00291       std::string pname = particle -> GetName();
00292       Double_t mass = particle -> Mass();
00293       Double_t charge = (particle -> Charge())/3.; //charge in units of |e|
00294       if ( gMC->IdFromPDG(pdgcode) <= 0 ) {
00295 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,22,0)
00296         gMC->DefineParticle(pdgcode,pname.c_str(),kPTIon,mass,charge,lifetime,
00297                            "nucleus", 0.0, 1, 1, 0, 1, 1, 0, 0, 1, kTRUE);
00298 #else
00299         gMC->DefineParticle(pdgcode,pname.c_str(),kPTIon,mass,charge,lifetime);
00300 #endif
00301         MSG("MCApp",Msg::kDebug) << "AddIon " << pdgcode << "/" 
00302            << pname.c_str() << " mass " << mass << " charge " << charge 
00303            << " lifetime " << lifetime << endl;
00304       }    
00305     }
00306   }
00307 
00308   // Add additional ion types with z > zmax to cover all those
00309   // defined by GMINOS.
00310   const Int_t nion = 15+12+1;
00311   // The first set of 15 ions are the subset of ions defined by 
00312   // Geant3 GPIONS .AND. TDatabasePDG.  (Ions defined in GPIONS but
00313   // not TDatabasePDG are not added and are commented out below.)   
00314   // The TDatabasePDG definitions of this set of ions is used in place
00315   // of that defined in GPIONS for consistency with the rest of the
00316   // ion definitions.
00317   // The second set of 12 ions are those defined by GMINOS lbl_part.
00318   // The third set of ions are those defined because they've popped
00319   // up during simulation.
00320   Int_t izia[nion][2] = {{29,63},  // Cu63
00321                          {30,64},  // Zn64
00322                          {32,74},  // Ge74
00323                          {34,80},  // Se80
00324                          {36,84},  // Kr84 
00325                          //  {38,88},  // Sr88
00326                          //  {40,90},  // Zr90
00327                          //  {42,98},  // Mo98
00328                          {46,106}, // Pd106
00329                          {48,114}, // Cd114
00330                          {50,120}, // Sn120 
00331                          {54,132}, // Xe132
00332                          {56,138}, // Ba138
00333                          //  {58,140}, // Ce140
00334                          //  {62,152}, // Sm152
00335                          //  {66,164}, // Dy164
00336                          //  {70,174}, // Yb174
00337                          {74,184}, // W184
00338                          {78,194}, // Pt194
00339                          {79,197}, // Au197
00340                          {80,202}, // Hg202
00341                          {82,208}, // Pb208
00342                          //  {92,238}, // U238
00343                          {31,69},  // Ga69
00344                          {33,75},  // As75
00345                          {35,79},  // Br79
00346                          {47,107}, // Ag107
00347                          {49,115}, // In115
00348                          {51,121}, // Sb121
00349                          {52,130}, // Te130
00350                          {53,127}, // I127
00351                          {55,133}, // Cs133
00352                          {73,181}, // Ta181
00353                          {77,193}, // Ir193
00354                          {81,205}, // Tl205
00355                          {50,115}, // Sn115
00356                                  };
00357   
00358   for ( int iion = 0; iion < nion; iion++ ) {
00359     Int_t pdgcode = UtilPDG::makeIonPDG(izia[iion][1],izia[iion][0],ij=0,
00360                                          UtilPDG::kPDG2006);
00361     TParticlePDG* particle = dbpdg.GetParticle(pdgcode);
00362     if ( particle ) {
00363       std::string pname = particle -> GetName();
00364       Double_t mass = particle -> Mass();
00365       Double_t charge = (particle -> Charge())/3.; //charge in units of |e|
00366       if ( gMC->IdFromPDG(pdgcode) <= 0 ) {
00367 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,22,0)
00368         gMC->DefineParticle(pdgcode,pname.c_str(),kPTIon,mass,charge,lifetime,
00369                            "nucleus", 0.0, 1, 1, 0, 1, 1, 0, 0, 1, kTRUE);
00370 #else
00371         gMC->DefineParticle(pdgcode,pname.c_str(),kPTIon,mass,charge,lifetime);
00372 #endif
00373         MSG("MCApp",Msg::kDebug) << "AddIon " << pdgcode << "/" 
00374            << pname.c_str() << " mass " << mass << " charge " << charge 
00375            << " lifetime " << lifetime << endl;
00376       }    
00377     }
00378     else {
00379       MSG("MCApp",Msg::kWarning) << "MCApplication::AddIons. Ion " 
00380                                  << pdgcode << " not present "
00381                                  << "in TDatabasePDG. Will not be defined!"
00382                                  << endl;
00383     }
00384   }
00385   
00386   return;
00387   
00388 }
00389 
00390 //_____________________________________________________________________________
00391 void MCApplication::AddDecayModes() {
00392   // Add decay modes beyond or overriding those defined by the 
00393   // concrete VMC.
00394   // This is done through the activation of an external decayer, e.g.
00395   // TPythia6Decayer, through an external script. An example of such
00396   // a script is PTSim_DecayConfig.C.
00397   
00398   if ( fDecayConfigScript.empty() 
00399        || fDecayConfigScript == std::string("<null>") ) {
00400     MSG("MCApp",Msg::kDebug) << "MCApplication::AddDecayModes. No "
00401                          << "external decay script defined." << endl;
00402     return;
00403   }
00404   
00405   // Print, load, and execute configuration script
00406   std::string decayConfigScriptPath = gSystem->Which(gROOT->GetMacroPath(),
00407                                fDecayConfigScript.c_str(),kReadPermission);
00408   if ( decayConfigScriptPath.empty() ) {
00409     MSG("MCApp",Msg::kError) << "MCApplication::InitMC configuration script "
00410                         << fDecayConfigScript.c_str() << " not found in path "
00411                         << gROOT->GetMacroPath() << ". Abort." << endl;
00412     abort();
00413   }
00414     
00415   // Configure decayer using an external configuration script
00416   MSG("MCApp",Msg::kInfo) 
00417    << "MCApplication::AddDecayModes initializing decayer with script "
00418    << decayConfigScriptPath.c_str() << ":" << endl;
00419 
00420   if ( fLogLevel <= Msg::kInfo ) {
00421     std::string printstr = ".!cat -n " + decayConfigScriptPath;
00422     gInterpreter->ProcessLineSynch(printstr.c_str());
00423   }
00424   gROOT->LoadMacro(decayConfigScriptPath.c_str());
00425   gInterpreter->ProcessLineSynch("DecayConfig()");
00426 
00427   return;
00428   
00429 }
00430 
00431 //_____________________________________________________________________________
00432 void MCApplication::InitGeometry() {
00433   // Initialize geometry. Called by TVirtualMC::Init().  
00434 
00435   return;
00436   
00437 }
00438 
00439 //_____________________________________________________________________________
00440 void MCApplication::InitMedia() {
00441   // Private method to initialize parameters of media according to
00442   // user configured cut & process values if specified.
00443 
00444   UpdateGlobalGeoManager(); 
00445   
00446   TIter nextmed(gGeoManager->GetListOfMedia());
00447   TGeoMedium* med = 0;
00448   while ( ( med = (TGeoMedium*)nextmed() ) ) {
00449     GeoMedium* geomed = dynamic_cast<GeoMedium*>(med);
00450     if ( !geomed ) continue;
00451     std::string medName = geomed -> GetName();
00452     const GeoMedium::CutMap& cutmap = geomed -> GetCutMap();
00453     for ( GeoMedium::CutMapConstItr citr  = cutmap.begin(); 
00454                                     citr != cutmap.end(); citr++ ) {
00455       MSG("Geo",Msg::kDebug) << "Medium " << medName.c_str()
00456                              << " " << UtilMCFlag::AsString(citr->first)
00457                              << " set to " << citr->second 
00458                              << " overriding default." << endl;
00459       fMC -> Gstpar(geomed->GetId(),UtilMCFlag::AsString(citr->first),
00460                                     citr->second);
00461     }
00462     const GeoMedium::ProcessMap& processmap = geomed -> GetProcessMap();
00463     for ( GeoMedium::ProcessMapConstItr citr = processmap.begin(); 
00464                                         citr!= processmap.end(); citr++ ) {
00465       MSG("Geo",Msg::kDebug) << "Medium " << medName.c_str()
00466                              << " " << UtilMCFlag::AsString(citr->first)
00467                              << " set to " << citr->second 
00468                              << " overriding default." << endl;
00469       fMC -> Gstpar(geomed->GetId(),UtilMCFlag::AsString(citr->first),
00470                                     citr->second);
00471     }
00472   }
00473 
00474 }
00475 
00476 //_____________________________________________________________________________
00477 void MCApplication::Field(const Double_t* x, Double_t* b) const {
00478   // Determine magnetic field b[3] at global position x[3]
00479   //
00480   // Units of BField map are meters for input position and Tesla for field
00481   // Units of MC application are cm for position and kiloGauss for field.
00482   //
00483 
00484   // Assume null
00485   b[0] = 0; b[1] = 0; b[2] = 0;
00486   
00487   if ( !fBField ) {
00488     MSG("MCApp",Msg::kWarning) << "MCApplication::Field but Null fBField!"
00489                                << endl;
00490     return;
00491   }
00492 
00493   // Insurance that current medium has field activated, although in principle 
00494   // this shouldn't be necessary 
00495   TGeoNode* node = gGeoManager->GetCurrentNode();
00496   if ( node -> GetVolume() -> GetMedium() -> GetParam(1) <= 0 ) return;
00497   
00498   TVector3 bxyz(0,0,0);
00499   TVector3 xyz(x[0]*Munits::cm,x[1]*Munits::cm,x[2]*Munits::cm);
00500 
00501   bxyz = fBField -> GetBField(xyz);
00502 
00503   // Convert Tesla to kGauss
00504   for ( int i = 0; i < 3; i++ ) b[i] = bxyz[i]*10.;
00505 
00506   UpdateGlobalGeoManager(); // shouldn't be necessary, but caution rules
00507 
00508   return;
00509  
00510   
00511 }
00512 
00513 //_____________________________________________________________________________
00514 void MCApplication::BeginEvent() {
00515   // Action to be taken at beginning of an event
00516   //
00517 
00518   UpdateGlobalGeoManager(); // in case gGeoManager has been altered
00519 
00520   // Deactivate BField test to determine if test pt is within steel plane
00521   // when using VMC.  Store current state of test, to be restored
00522   // post particle transport in FinishEvent()
00523   fBFldInZTestSave = fBField -> GetRequireInZTest();
00524   //fBField -> SetRequireInZTest(0);
00525   
00526   if ( !fMCAppUser ) FatalNoApp();
00527   fMCAppUser -> BeginEvent();
00528 
00529   return;
00530   
00531 }
00532 
00533 //_____________________________________________________________________________
00534 void MCApplication::FinishEvent() {
00535   // Action to be taken at end of an event
00536 
00537   UpdateGlobalGeoManager(); // in case gGeoManager has been altered
00538 
00539   // Restore BField test to status before particle transport
00540   fBField -> SetRequireInZTest(fBFldInZTestSave);
00541 
00542   if ( !fMCAppUser ) FatalNoApp();
00543   fMCAppUser -> FinishEvent();
00544   
00545   return;
00546   
00547 }
00548 
00549   
00550   
00551 
00552 
00553   

Generated on Sat Nov 7 01:26:20 2009 for loon by  doxygen 1.3.9.1