/scratch0/jsnuveri/BDSIM/BDSIMgit/bdsim/src/BDSEnergyCounterSD.cc

00001 /* BDSIM code.    Version 1.0
00002    Author: Grahame A. Blair, Royal Holloway, Univ. of London.
00003    Last modified 24.7.2002
00004    Copyright (c) 2002 by G.A.Blair.  ALL RIGHTS RESERVED. 
00005 */
00006 #include "BDSExecOptions.hh"
00007 #include "BDSDebug.hh"
00008 #include "BDSGlobalConstants.hh"
00009 
00010 #include "BDSEnergyCounterSD.hh"
00011 #include "BDSEnergyCounterHit.hh"
00012 #include "BDSLogicalVolumeInfo.hh"
00013 #include "G4AffineTransform.hh"
00014 #include "G4Event.hh"
00015 #include "G4EventManager.hh"
00016 #include "G4ios.hh"
00017 #include "G4LogicalVolume.hh"
00018 #include "G4ParticleDefinition.hh"
00019 #include "G4RotationMatrix.hh"
00020 #include "G4SDManager.hh"
00021 #include "G4Step.hh"
00022 #include "G4ThreeVector.hh"
00023 #include "G4TouchableHistory.hh"
00024 #include "G4Track.hh"
00025 #include "G4VPhysicalVolume.hh"
00026 #include "G4VTouchable.hh"
00027 
00028 #include <map>
00029 
00030 #define NMAXCOPY 5
00031 
00032 BDSEnergyCounterSD::BDSEnergyCounterSD(G4String name)
00033   :G4VSensitiveDetector(name),
00034    energyCounterCollection(NULL),
00035    primaryCounterCollection(NULL),
00036    HCIDe(-1),
00037    HCIDp(-1),
00038    enrg(0.0),
00039    X(0.0),
00040    Y(0.0),
00041    Z(0.0),
00042    S(0.0),
00043    x(0.0),
00044    y(0.0),
00045    z(0.0)
00046 {
00047   verbose = BDSExecOptions::Instance()->GetVerbose();
00048   itsName = name;
00049   collectionName.insert("energy_counter");
00050   collectionName.insert("primary_counter");
00051 }
00052 
00053 BDSEnergyCounterSD::~BDSEnergyCounterSD()
00054 {;}
00055 
00056 void BDSEnergyCounterSD::Initialize(G4HCofThisEvent* HCE)
00057 {  
00058   energyCounterCollection = new BDSEnergyCounterHitsCollection(SensitiveDetectorName,collectionName[0]);
00059   if (HCIDe < 0)
00060     {HCIDe = G4SDManager::GetSDMpointer()->GetCollectionID(energyCounterCollection);}
00061   HCE->AddHitsCollection(HCIDe,energyCounterCollection);
00062 
00063   primaryCounterCollection = new BDSEnergyCounterHitsCollection
00064     (SensitiveDetectorName,collectionName[1]);
00065   if (HCIDp < 0)
00066     {HCIDp = G4SDManager::GetSDMpointer()->GetCollectionID(primaryCounterCollection);}
00067   HCE->AddHitsCollection(HCIDp,primaryCounterCollection);
00068 }
00069 
00070 G4bool BDSEnergyCounterSD::ProcessHits(G4Step*aStep, G4TouchableHistory* readOutTH)
00071 { 
00072   if(BDSGlobalConstants::Instance()->GetStopTracks())
00073     enrg = (aStep->GetTrack()->GetTotalEnergy() - aStep->GetTotalEnergyDeposit()); // Why subtract the energy deposit of the step? Why not add?
00074   //this looks like accounting for conservation of energy when you're killing a particle
00075   //which may normally break energy conservation for the whole event
00076   //see developer guide 6.2.2...
00077   else
00078     enrg = aStep->GetTotalEnergyDeposit();
00079 #ifdef BDSDEBUG
00080   G4cout << "BDSEnergyCounterSD> enrg = " << enrg << G4endl;
00081 #endif
00082   //if the energy is 0, don't do anything
00083   if (enrg==0.) return false;      
00084 
00085   // can get the copy number from the read out geometry if it exists
00086   G4int nCopy;
00087   if (readOutTH)
00088     {nCopy = readOutTH->GetCopyNumber();}
00089   else
00090     {nCopy = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetCopyNo();}
00091 #ifdef BDSDEBUG
00092   if(nCopy>0){
00093     G4cout << "BDSEnergyCounterSD::ProcessHits> nCopy = " << nCopy << G4endl;
00094   }
00095 #endif
00096   /*
00097   // LN - not sure why this arbritrary limit of NMAXCOPY is necessary 
00098   // looks like it was to do with registering existing beamline elements to save memory
00099   // but this wasn't fully implemented anyway and with recent changes, this would likely 
00100   // be implemented in a different way
00101   if(nCopy>NMAXCOPY-1)
00102     {
00103       G4cerr << " BDSEnergyCounterSD: nCopy too large: nCopy = " << nCopy 
00104              << " NMAXCOPY = " << NMAXCOPY 
00105              << " Volume = " << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName()
00106              << G4endl;
00107       G4Exception("Killing program in BDSEnergyCounterSD::ProcessHits", "-1", FatalException, "");
00108     }
00109   */
00110   // Get translation and rotation of volume w.r.t the World Volume
00111 
00112   // if there is a read out geometry volume, use that. Note there *should* always be a
00113   // read out geometry volume for any sensitive volume (if they've been made sensitive)
00114   // there is the possibility that there isn't a read out volume in which case the touchable
00115   // object would be a null pointer and seg fault - must catch this
00116   if (!readOutTH)
00117     {
00118       G4cout << __METHOD_NAME__ << "hit in a sensitive volume without readout geometry" << G4endl;
00119       G4cerr << __METHOD_NAME__ << "hit not recorded!" << G4endl;
00120       return true;
00121     }
00122 
00123   // get the coordinate transform from the read out geometry instead of the actual geometry
00124   // read out geometry is in accelerator s,x,y coordinates along beam line axis
00125   G4AffineTransform tf = readOutTH->GetHistory()->GetTopTransform();
00126   // this was the old method of getting the transform
00127   //G4AffineTransform tf = (aStep->GetPreStepPoint()->GetTouchableHandle()->GetHistory()->GetTopTransform());
00128   G4ThreeVector posbefore = aStep->GetPreStepPoint()->GetPosition();
00129   G4ThreeVector posafter  = aStep->GetPostStepPoint()->GetPosition();
00130   //G4ThreeVector momDir = aStep->GetTrack()->GetMomentumDirection();
00131 
00132   //calculate local coordinates
00133   G4ThreeVector posbeforelocal  = tf.TransformPoint(posbefore);
00134   G4ThreeVector posafterlocal   = tf.TransformPoint(posafter);
00135 
00136   //calculate mean position of step (which is two points)
00137   //global
00138   Y = 0.5 * (posbefore.x() + posafter.x());
00139   Y = 0.5 * (posbefore.y() + posafter.y());
00140   Z = 0.5 * (posbefore.z() + posafter.z());
00141   S = GetSPositionOfStep(aStep);
00142   //local
00143   x = 0.5 * (posbeforelocal.x() + posafterlocal.x());
00144   y = 0.5 * (posbeforelocal.y() + posafterlocal.y());
00145   z = 0.5 * (posbeforelocal.z() + posafterlocal.z());
00146 
00147   G4int event_number = G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetEventID();
00148   
00149   if(verbose && BDSGlobalConstants::Instance()->GetStopTracks()) 
00150     {
00151       G4cout << "BDSEnergyCounterSD: Current Volume: " 
00152              << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() 
00153              << "\tEvent:  " << event_number 
00154              << "\tEnergy: " << enrg/CLHEP::GeV 
00155              << "GeV\tPosition: " << S/CLHEP::m <<" m"<< G4endl;
00156     }
00157   
00158   G4double weight = aStep->GetTrack()->GetWeight();
00159   if (weight == 0){
00160     G4cerr << "Error: BDSEnergyCounterSD: weight = 0" << G4endl;
00161     exit(1);
00162   }
00163   G4int    ptype      = aStep->GetTrack()->GetDefinition()->GetPDGEncoding();
00164   G4String volName    = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName();
00165   G4String regionName = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetRegion()->GetName();
00166   
00167   G4bool precisionRegion = false;
00168   if (regionName.contains((G4String)"precisionRegion")) {
00169     precisionRegion=true;
00170   }
00171   //G4bool precisionRegion = get this info from the logical volume in future
00172   
00173   G4int turnstaken    = BDSGlobalConstants::Instance()->GetTurnsTaken();
00174   
00175   //create hits and put in hits collection of the event
00176   //do analysis / output in end of event action
00177   BDSEnergyCounterHit* ECHit = new BDSEnergyCounterHit(nCopy,
00178                                                        enrg,
00179                                                        X,
00180                                                        Y,
00181                                                        Z,
00182                                                        S,
00183                                                        x,
00184                                                        y,
00185                                                        z,
00186                                                        volName, 
00187                                                        ptype, 
00188                                                        weight, 
00189                                                        precisionRegion,
00190                                                        turnstaken,
00191                                                        event_number
00192                                                        );
00193   // don't worry, won't add 0 energy tracks as filtered at top by if statement
00194   energyCounterCollection->insert(ECHit);
00195   
00196   //record first scatter of primary if it exists
00197   if (aStep->GetTrack()->GetParentID() == 0) {
00198     //create a duplicate hit in the primarycounter hits collection
00199     //there are usually a few - filter at end of event action
00200     BDSEnergyCounterHit* PCHit = new BDSEnergyCounterHit(*ECHit);
00201     //set the energy to be the full energy of the primary
00202     //just now it's the wee bit of energy deposited in that step
00203     G4double primaryEnergy = BDSGlobalConstants::Instance()->GetBeamKineticEnergy();
00204     PCHit->SetEnergy(primaryEnergy);
00205     primaryCounterCollection->insert(PCHit);
00206   }
00207   
00208   if(BDSGlobalConstants::Instance()->GetStopTracks())
00209     aStep->GetTrack()->SetTrackStatus(fStopAndKill);
00210    
00211   return true;
00212 }
00213 
00214 G4bool BDSEnergyCounterSD::ProcessHits(G4GFlashSpot *aSpot,G4TouchableHistory*)
00215 { 
00216   enrg = aSpot->GetEnergySpot()->GetEnergy();
00217 #ifdef BDSDEBUG
00218   G4cout << "BDSEnergyCounterSD>gflash enrg = " << enrg << G4endl;
00219 #endif
00220   if (enrg==0.) return false;      
00221   G4VPhysicalVolume* pCurrentVolume = aSpot->GetTouchableHandle()->GetVolume();
00222   G4String           volName        = pCurrentVolume->GetName();
00223   G4int              nCopy          = pCurrentVolume->GetCopyNo();
00224 #ifdef BDSDEBUG
00225   if(nCopy>0){
00226     G4cout << "BDSEnergyCounterSD::ProcessHits>gFlash nCopy = " << nCopy << G4endl;
00227   }
00228 #endif
00229   if(nCopy > NMAXCOPY-1)
00230     {
00231       G4cerr << " BDSEnergyCounterSD: nCopy too large: nCopy = " << nCopy
00232              << " NMAXCOPY = " << NMAXCOPY 
00233              << " Volume = "<< volName;
00234       G4Exception("Killing program in BDSEnergyCounterSD::ProcessHits", "-1", FatalException, "");
00235     }
00236   
00237   // Get Translation and Rotation of Sampler Volume w.r.t the World Volume
00238   G4AffineTransform tf = (aSpot->GetTouchableHandle()->GetHistory()->GetTopTransform());
00239   G4ThreeVector pos    = aSpot->GetPosition();
00240 
00241   //calculate local coordinates
00242   G4ThreeVector poslocal = tf.TransformPoint(pos);
00243   
00244   //global
00245   Y = pos.x();
00246   Y = pos.y();
00247   Z = pos.z();
00248   S = GetSPositionOfSpot(aSpot);
00249   //local
00250   x = poslocal.x();
00251   y = poslocal.y();
00252   z = poslocal.z();
00253   
00254   G4int event_number = G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetEventID();
00255   
00256   if(verbose && BDSGlobalConstants::Instance()->GetStopTracks()) 
00257     {
00258       G4cout << " BDSEnergyCounterSD: Current Volume: " <<  volName 
00259              << " Event: "    << event_number 
00260              << " Energy: "   << enrg/CLHEP::GeV << " GeV"
00261              << " Position: " << S/CLHEP::m   << " m" 
00262              << G4endl;
00263     }
00264   
00265   G4double weight = aSpot->GetOriginatorTrack()->GetPrimaryTrack()->GetWeight();
00266   if (weight == 0){
00267     G4cerr << "Error: BDSEnergyCounterSD: weight = 0" << G4endl;
00268     exit(1);
00269   }
00270   int ptype = aSpot->GetOriginatorTrack()->GetPrimaryTrack()->GetDefinition()->GetPDGEncoding();
00271 
00272   G4int turnstaken = BDSGlobalConstants::Instance()->GetTurnsTaken();
00273   
00274   // see explanation in other processhits function
00275   BDSEnergyCounterHit* ECHit = new BDSEnergyCounterHit(nCopy,
00276                                                        enrg,
00277                                                        X,
00278                                                        Y,
00279                                                        Z,
00280                                                        S,
00281                                                        x,
00282                                                        y,
00283                                                        z,
00284                                                        volName, 
00285                                                        ptype, 
00286                                                        weight, 
00287                                                        0,
00288                                                        turnstaken,
00289                                                        event_number
00290                                                        );
00291   // don't worry, won't add 0 energy tracks as filtered at top by if statement
00292   energyCounterCollection->insert(ECHit);
00293   
00294   //record first scatter of primary if it exists
00295   if (aSpot->GetOriginatorTrack()->GetPrimaryTrack()->GetParentID() == 0) {
00296     //create a duplicate hit in the primarycounter hits collection
00297     //there are usually a few - filter at end of event action
00298     BDSEnergyCounterHit* PCHit = new BDSEnergyCounterHit(*ECHit);
00299     G4double primaryEnergy = BDSGlobalConstants::Instance()->GetBeamKineticEnergy();
00300     PCHit->SetEnergy(primaryEnergy);
00301     primaryCounterCollection->insert(PCHit);
00302   }
00303   
00304   return true;
00305 }
00306 
00307 G4double BDSEnergyCounterSD::GetSPositionOfStep(G4Step* aStep)
00308 {
00309   G4double thespos;
00310   // Get the s position along the accelerator by querying the logical volume
00311   // Get the logical volume from this step
00312   G4LogicalVolume* thevolume = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume();  
00313   // Find it's s position from global map made at constrcution time
00314   typedef std::map<G4LogicalVolume*,BDSLogicalVolumeInfo*>::iterator it_type;
00315   it_type search = BDSGlobalConstants::Instance()->LogicalVolumeInfo()->find(thevolume);
00316   
00317   if (search == BDSGlobalConstants::Instance()->LogicalVolumeInfo()->end()){
00318     //this means that the logical volume pointer doesn't exist in the map 
00319     //checking this prevents segfaults
00320     thespos = -1.0*CLHEP::m; // set to unreal s position to identify and not fail
00321   }
00322   else {
00323     thespos = BDSGlobalConstants::Instance()->GetLogicalVolumeInfo(thevolume)->GetSPos();
00324     G4ThreeVector     prestepposition = aStep->GetPreStepPoint()->GetPosition();
00325     G4AffineTransform tf              = (aStep->GetPreStepPoint()->GetTouchableHandle()->GetHistory()->GetTopTransform());
00326     G4ThreeVector     prestepposlocal = tf.TransformPoint(prestepposition);
00327     thespos += prestepposlocal.z();
00328    }
00329   return thespos;
00330 }
00331 
00332 G4double BDSEnergyCounterSD::GetSPositionOfSpot(G4GFlashSpot* aSpot)
00333 {
00334   G4double thespos;
00335   // Get the s position along the accelerator by querying the logical volume
00336   // Get the logical volume from this step
00337   G4LogicalVolume* thevolume = aSpot->GetTouchableHandle()->GetVolume()->GetLogicalVolume();
00338 
00339   // Find it's s position from global map made at constrcution time
00340   typedef std::map<G4LogicalVolume*,BDSLogicalVolumeInfo*>::iterator it_type;
00341   it_type search = BDSGlobalConstants::Instance()->LogicalVolumeInfo()->find(thevolume);
00342   
00343   if (search == BDSGlobalConstants::Instance()->LogicalVolumeInfo()->end()){
00344     //this means that the logical volume pointer doesn't exist in the map 
00345     //checking this prevents segfaults
00346     thespos = -1.0*CLHEP::m; // set to unreal s position to identify and not fail
00347   }
00348   else {
00349     thespos = BDSGlobalConstants::Instance()->GetLogicalVolumeInfo(thevolume)->GetSPos();
00350     G4ThreeVector     pos = aSpot->GetPosition();
00351     G4AffineTransform tf  = (aSpot->GetTouchableHandle()->GetHistory()->GetTopTransform());
00352     G4ThreeVector localposition = tf.TransformPoint(pos);
00353     thespos += localposition.z();
00354    }
00355   return thespos;
00356 }

Generated on 28 Jun 2015 for BDSIM by  doxygen 1.4.7