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

Generated on Fri Mar 28 15:34:35 2008 for loon by  doxygen 1.3.9.1