From 117da1b2b3197f41621242cdb7f92e52989ed81f Mon Sep 17 00:00:00 2001 From: adrien matta <matta@lpccaen.in2p3.fr> Date: Thu, 5 Jan 2017 10:31:33 +0100 Subject: [PATCH] * Drift Electron transport no correctly working - Adjustable step length - good speed at 1mm step - take into account the local field direction --- NPSimulation/Detectors/Chio/Chio.cc | 47 +++++++++++++------ NPSimulation/Process/G4DEAmplification.cc | 10 +--- NPSimulation/Process/G4DETransport.cc | 53 ++++++++++++++++------ NPSimulation/Process/G4DETransport.hh | 4 +- NPSimulation/Process/G4DriftElectron.cc | 6 ++- NPSimulation/Process/G4IonizationWithDE.cc | 10 ++-- Projects/BeLise/PhysicsListOption.txt | 2 +- 7 files changed, 86 insertions(+), 46 deletions(-) diff --git a/NPSimulation/Detectors/Chio/Chio.cc b/NPSimulation/Detectors/Chio/Chio.cc index 4ed7fa3ee..9fd9f085c 100644 --- a/NPSimulation/Detectors/Chio/Chio.cc +++ b/NPSimulation/Detectors/Chio/Chio.cc @@ -68,11 +68,11 @@ using namespace CLHEP; //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... namespace Chio_NS{ // Energy and time Resolution -// const double EnergyThreshold = 0.1*MeV; + // const double EnergyThreshold = 0.1*MeV; //const double ResoTime = 4.5*ns ; - // const double ResoEnergy = 1.0*MeV ; + // const double ResoEnergy = 1.0*MeV ; //const double Radius = 50*mm ; - // const double Width = 100*mm ; + // const double Width = 100*mm ; const double Thickness = 300*mm ; const string Material = "BC400"; } @@ -133,12 +133,12 @@ G4LogicalVolume* Chio::BuildDetector(){ G4Material* Fe= MaterialManager::getInstance()->GetMaterialFromLibrary("Fe"); G4Material* CF4= MaterialManager::getInstance()->GetGasFromLibrary("CF4",0.0693276*bar,273.15*kelvin); G4Material* Mylar= MaterialManager::getInstance()->GetMaterialFromLibrary("Mylar"); - + G4MaterialPropertiesTable* MPT = new G4MaterialPropertiesTable(); MPT->AddConstProperty("DE_PAIRENERGY",30*eV); - MPT->AddConstProperty("DE_YIELD",1e-3); -// MPT->AddConstProperty("DE_AMPLIFICATION",1e4); - MPT->AddConstProperty("DE_ABSLENGTH",1*km); + MPT->AddConstProperty("DE_YIELD",1e-4); + // MPT->AddConstProperty("DE_AMPLIFICATION",1e4); + MPT->AddConstProperty("DE_ABSLENGTH",1*pc); MPT->AddConstProperty("DE_DRIFTSPEED",8e-3*mm/ns); MPT->AddConstProperty("DE_TRANSVERSALSPREAD",6e-5*mm2/ns); MPT->AddConstProperty("DE_LONGITUDINALSPREAD",4e-5*mm2/ns); @@ -162,14 +162,31 @@ G4LogicalVolume* Chio::BuildDetector(){ logicWindows, "ChioEntranceWindows",m_SquareDetector,false,0); - -/* G4Region* DriftRegion = new G4Region("DriftRegion"); - DriftRegion->AddRootLogicalVolume(logicGas); - G4ProductionCuts* cuts = new G4ProductionCuts; - cuts->SetProductionCut(1e-9*micrometer); // same cuts for gamma, e- and e+ - DriftRegion->SetProductionCuts(cuts); - - new DriftElectron("DriftElectron",DriftRegion);*/ + G4ElectricField* field = new G4UniformElectricField(G4ThreeVector(0.0,-1000*volt/cm,0.0)); + // Create an equation of motion for this field + G4EqMagElectricField* Equation = new G4EqMagElectricField(field); + G4MagIntegratorStepper* Stepper = new G4ClassicalRK4( Equation, 8 ); + + // Get the global field manager + G4FieldManager* FieldManager= new G4FieldManager(); + // Set this field to the global field manager + FieldManager->SetDetectorField(field ); + logicGas->SetFieldManager(FieldManager,true); + + G4MagInt_Driver* IntgrDriver = new G4MagInt_Driver(0.1*mm, + Stepper, + Stepper->GetNumberOfVariables() ); + + G4ChordFinder* ChordFinder = new G4ChordFinder(IntgrDriver); + FieldManager->SetChordFinder( ChordFinder ); + + /* G4Region* DriftRegion = new G4Region("DriftRegion"); + DriftRegion->AddRootLogicalVolume(logicGas); + G4ProductionCuts* cuts = new G4ProductionCuts; + cuts->SetProductionCut(1e-9*micrometer); // same cuts for gamma, e- and e+ + DriftRegion->SetProductionCuts(cuts); + + new DriftElectron("DriftElectron",DriftRegion);*/ m_SquareDetector->SetVisAttributes(m_VisChamber); logicGas->SetVisAttributes(m_VisGas); logicWindows->SetVisAttributes(m_VisWindows); diff --git a/NPSimulation/Process/G4DEAmplification.cc b/NPSimulation/Process/G4DEAmplification.cc index a171c3187..2db666141 100644 --- a/NPSimulation/Process/G4DEAmplification.cc +++ b/NPSimulation/Process/G4DEAmplification.cc @@ -108,8 +108,6 @@ G4DEAmplification::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint(); - - G4ThreeVector x0 = pPreStepPoint->GetPosition(); G4ThreeVector p0 = aStep.GetDeltaPosition().unit(); G4double t0 = pPreStepPoint->GetGlobalTime(); @@ -158,13 +156,8 @@ G4DEAmplification::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) G4ThreeVector p; p.setRThetaPhi(1,theta,phi); - // Random Position along the step with matching time - G4double rand = G4UniformRand(); - G4ThreeVector pos = x0 + rand * aStep.GetDeltaPosition(); - G4double time = t0+ rand* aStep.GetDeltaTime(); - G4DynamicParticle* particle = new G4DynamicParticle(G4DriftElectron::DriftElectron(),p, pair_energy); - G4Track* aSecondaryTrack = new G4Track(particle,time,pos); + G4Track* aSecondaryTrack = new G4Track(particle,t0,x0); aSecondaryTrack->SetTouchableHandle( aStep.GetPreStepPoint()->GetTouchableHandle()); @@ -174,6 +167,7 @@ G4DEAmplification::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) aParticleChange.AddSecondary(aSecondaryTrack); } + // The original track is left intact return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep); } diff --git a/NPSimulation/Process/G4DETransport.cc b/NPSimulation/Process/G4DETransport.cc index 0e721759d..1247dabac 100644 --- a/NPSimulation/Process/G4DETransport.cc +++ b/NPSimulation/Process/G4DETransport.cc @@ -49,6 +49,8 @@ #include "G4PhysicalConstants.hh" #include "G4SystemOfUnits.hh" #include "G4DETransport.hh" +#include "G4FieldManager.hh" +#include "G4ElectroMagneticField.hh" ///////////////////////// // Class Implementation @@ -90,7 +92,6 @@ G4DETransport::~G4DETransport(){} //////////// // Methods -//////////// // PostStepDoIt // ------------- @@ -99,6 +100,7 @@ G4VParticleChange* G4DETransport::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) { aParticleChange.Initialize(aTrack); + G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint(); G4ThreeVector x0 = pPreStepPoint->GetPosition(); @@ -107,6 +109,13 @@ G4DETransport::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) G4double Energy = pPreStepPoint->GetKineticEnergy(); + // The time scale is imposed by the drift speed + G4double step = aStep.GetDeltaTime(); + + if(!step){ // allow internal relocation of the track by the kernel taking a 0 length intermediate step + return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); + } + // Get the material table const G4Material* aMaterial = aTrack.GetMaterial(); @@ -125,15 +134,24 @@ G4DETransport::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) // Electron follow the field direction - G4ThreeVector driftDir(0,1,0); + // The field direction is taken from the field manager + G4double* fieldArr = new G4double[6]; + G4double Point[4]={x0.x(),x0.y(),x0.z(),t0}; + G4FieldManager* fMng = pPreStepPoint->GetTouchableHandle()->GetVolume()->GetLogicalVolume()-> + GetFieldManager(); + + G4ElectroMagneticField* field = (G4ElectroMagneticField*)fMng->GetDetectorField(); + field->GetFieldValue(Point,fieldArr) ; + + // Electron move opposite to the field direction, hance the minus sign + G4ThreeVector driftDir(-fieldArr[3],-fieldArr[4],-fieldArr[5]); + // Normalised the drift direction + driftDir = driftDir.unit(); G4double v_drift = aMaterialPropertiesTable->GetConstProperty("DE_DRIFTSPEED"); - // The time scale is imposed by the drift speed - G4double step = aStep.GetDeltaTime(); - if(!step) - return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep); - - // Should be equal to delta pos y - G4double step_length = step*v_drift; + // Should be equal to delta length + G4double step_length = aStep.GetDeltaPosition().mag(); + step = step_length/v_drift; + G4double sigmaTrans = sqrt(2*step_length*aMaterialPropertiesTable->GetConstProperty("DE_TRANSVERSALSPREAD")/v_drift); G4double sigmaLong = sqrt(2*step_length*aMaterialPropertiesTable->GetConstProperty("DE_LONGITUDINALSPREAD")/v_drift); @@ -143,18 +161,22 @@ G4DETransport::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) G4ThreeVector trans(G4RandGauss::shoot(0,d_trans),0,0); trans.rotateY(twopi*G4UniformRand()); G4ThreeVector d_Pos = (step_length+d_long)*driftDir+trans; - // Random Position along the step with matching time + + // New particle Position with matching time G4ThreeVector pos = x0 + d_Pos; G4double time = t0 + step; - // Garanty that the electron does not jump outside the current volume - m_SafetyHelper->ReLocateWithinVolume(pos); + G4double safety = m_SafetyHelper->ComputeSafety(x0,d_Pos.mag()); + + if(d_Pos.mag()>safety){ + pos = x0+safety*d_Pos.unit(); + } aParticleChange.ProposeMomentumDirection(d_Pos.unit()); aParticleChange.ProposeEnergy(Energy); aParticleChange.ProposePosition(pos); aParticleChange.ProposeGlobalTime(time); - + aParticleChange.ProposeVelocity(v_drift/c_light); return &aParticleChange; } @@ -166,5 +188,8 @@ G4double G4DETransport::GetMeanFreePath(const G4Track& , G4double , G4ForceCondition* ) { - return 0.5*mm; + // Typical distance after which the electron position should be reevaluated + // to take into account the diffusivity of the charge cloud inside the + // medium + return 1*mm; } diff --git a/NPSimulation/Process/G4DETransport.hh b/NPSimulation/Process/G4DETransport.hh index c85e2f588..d885efe8b 100644 --- a/NPSimulation/Process/G4DETransport.hh +++ b/NPSimulation/Process/G4DETransport.hh @@ -105,8 +105,8 @@ public: G4double GetMeanFreePath(const G4Track& aTrack, G4double , G4ForceCondition* ); - // Returns the transport length for bulk transport of drift - // electron in media with a specified attenuation length. + // Returns the typical travel length for transport of drift + // electron in media G4VParticleChange* PostStepDoIt(const G4Track& aTrack, const G4Step& aStep); diff --git a/NPSimulation/Process/G4DriftElectron.cc b/NPSimulation/Process/G4DriftElectron.cc index 04a09993a..d64f55a76 100644 --- a/NPSimulation/Process/G4DriftElectron.cc +++ b/NPSimulation/Process/G4DriftElectron.cc @@ -53,6 +53,9 @@ G4DriftElectron* G4DriftElectron::Definition() // search in particle table] G4ParticleTable* pTable = G4ParticleTable::GetParticleTable(); G4ParticleDefinition* anInstance = pTable->FindParticle(name); + // Note: The charge of drift electron is null so they are not afected by the + // electro magnetic field directly. This is taken care of "manually" by the + // G4DETransport process that get the local field direction if (anInstance ==0) { // create particle @@ -65,7 +68,7 @@ G4DriftElectron* G4DriftElectron::Definition() // stable lifetime decay table // shortlived subType anti_encoding anInstance = new G4ParticleDefinition( - name, electron_mass_c2, 0.0*MeV, -1.*eplus, + name, electron_mass_c2, 0.0*MeV, -0.*eplus, 1, 0, 0, 0, 0, 0, "lepton", 1, 0, 11, @@ -73,6 +76,7 @@ G4DriftElectron* G4DriftElectron::Definition() false, "e" ); } + theInstance = reinterpret_cast<G4DriftElectron*>(anInstance); return theInstance; } diff --git a/NPSimulation/Process/G4IonizationWithDE.cc b/NPSimulation/Process/G4IonizationWithDE.cc index 2856283b4..b2aa522a4 100644 --- a/NPSimulation/Process/G4IonizationWithDE.cc +++ b/NPSimulation/Process/G4IonizationWithDE.cc @@ -163,14 +163,16 @@ G4IonizationWithDE::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep); - G4double pair_energy=0; - pair_energy= + G4double v_drift= + aMaterialPropertiesTable->GetConstProperty("DE_DRIFTSPEED"); + G4double pair_energy= aMaterialPropertiesTable->GetConstProperty("DE_PAIRENERGY"); G4double IonizationWithDEYield = 0; IonizationWithDEYield= aMaterialPropertiesTable->GetConstProperty("DE_YIELD"); G4int number_electron = IonizationWithDEYield*TotalEnergyDeposit/pair_energy; + number_electron = G4Poisson(number_electron); //if no electron leave if(number_electron<1){ aParticleChange.SetNumberOfSecondaries(0); @@ -195,9 +197,7 @@ G4IonizationWithDE::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) G4DynamicParticle* particle = new G4DynamicParticle(G4DriftElectron::DriftElectron(),p, pair_energy); G4Track* aSecondaryTrack = new G4Track(particle,time,pos); - - aSecondaryTrack->SetTouchableHandle( - aStep.GetPreStepPoint()->GetTouchableHandle()); + aSecondaryTrack->SetVelocity(v_drift/c_light); aSecondaryTrack->SetParentID(aTrack.GetTrackID()); aSecondaryTrack->SetTouchableHandle(aStep.GetPreStepPoint()->GetTouchableHandle()); diff --git a/Projects/BeLise/PhysicsListOption.txt b/Projects/BeLise/PhysicsListOption.txt index d85f8d5db..8c522e9f8 100644 --- a/Projects/BeLise/PhysicsListOption.txt +++ b/Projects/BeLise/PhysicsListOption.txt @@ -1,5 +1,5 @@ EmPhysicsList Option4 -DefaultCutOff 100 +DefaultCutOff 1000 IonBinaryCascadePhysics 0 NPIonInelasticPhysics 0 EmExtraPhysics 0 -- GitLab