BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSLaserCumulativePhotodetachment.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSAuxiliaryNavigator.hh"
19#include "BDSLaserCumulativePhotodetachment.hh"
20#include "BDSLogicalVolumeLaser.hh"
21#include "BDSPhotoDetachmentEngine.hh"
22#include "BDSStep.hh"
23#include "BDSGlobalConstants.hh"
24
25#include "globals.hh"
26#include "G4AffineTransform.hh"
27#include "G4Electron.hh"
28#include "G4LogicalVolume.hh"
29#include "G4ParticleTable.hh"
30#include "G4ProcessType.hh"
31#include "G4Proton.hh"
32#include "G4Step.hh"
33#include "G4StepPoint.hh"
34#include "G4ThreeVector.hh"
35#include "G4Track.hh"
36#include "G4VTouchable.hh"
37#include "Randomize.hh"
38#include "G4TransportationManager.hh"
39#include "G4VPhysicalVolume.hh"
40#include "G4RandomDirection.hh"
41#include "CLHEP/Units/PhysicalConstants.h"
42#include "CLHEP/Units/SystemOfUnits.h"
43
44#include <cmath>
45
46BDSLaserCumulativePhotodetachment::BDSLaserCumulativePhotodetachment(const G4String& processName):
47 G4VDiscreteProcess(processName, G4ProcessType::fElectromagnetic),
48 auxNavigator(new BDSAuxiliaryNavigator()),
49 photoDetachmentEngine(new BDSPhotoDetachmentEngine())
50{;}
51
52BDSLaserCumulativePhotodetachment::~BDSLaserCumulativePhotodetachment()
53{
54 delete auxNavigator;
55 delete photoDetachmentEngine;
56}
57
58G4double BDSLaserCumulativePhotodetachment::GetMeanFreePath(const G4Track& track,
59 G4double /*previousStepSize*/,
60 G4ForceCondition* forceCondition)
61{
62
63 //########### Typical volume check here for process active or not ########################
64
65 G4LogicalVolume* lv = track.GetVolume()->GetLogicalVolume();
66 if (!lv->IsExtended()) // not extended so can't be a laser logical volume
67 {return std::numeric_limits<double>::max();}
68
69 BDSLogicalVolumeLaser* lvv = dynamic_cast<BDSLogicalVolumeLaser*>(lv);
70 if (!lvv) // it's an extended volume but not ours (could be a crystal)
71 {return std::numeric_limits<double>::max();}
72
73 *forceCondition = Forced;
74
75 return std::numeric_limits<double>::max();
76}
77
78G4VParticleChange* BDSLaserCumulativePhotodetachment::PostStepDoIt(const G4Track& track,
79 const G4Step& step)
80{
81 // get coordinates for photon density calculations
82 aParticleChange.Initialize(track);
83
84 G4LogicalVolume* lv = track.GetVolume()->GetLogicalVolume();
85 if (!lv->IsExtended()) // not extended so can't be a laser logical volume
86 {return pParticleChange;}
87
88 BDSLogicalVolumeLaser* lvv = dynamic_cast<BDSLogicalVolumeLaser *>(lv);
89 if (!lvv) // it's an extended volume but not ours (could be a crystal)
90 {return pParticleChange;}
91
92 // else proceed
93 const BDSLaser* laser = lvv->Laser();
94
95 G4DynamicParticle* ion = const_cast<G4DynamicParticle*>(track.GetDynamicParticle());
96 G4int ionCharge=ion->GetCharge();
97 if(ionCharge==0){ return G4VDiscreteProcess::PostStepDoIt(track, step); }
98 G4double particleEnergy = ion->GetTotalEnergy();
99 G4ThreeVector particleMomentum = ion->GetMomentum();
100 G4ThreeVector particleBeta = particleMomentum/particleEnergy;
101 G4double particleGamma = particleEnergy/ion->GetMass();
102 G4double particleVelocity = particleBeta.mag()*CLHEP::c_light;
103 G4LorentzVector particle4VectorMomentum = ion->Get4Momentum();
104 particle4VectorMomentum.boost(-particleBeta);
105 //G4double particleTimePostStepGlobal = track.GetGlobalTime();
106
107 //######### Get particle position and momentum direction ###############################
108 G4ThreeVector particlePositionPostStepGlobal = track.GetPosition();
109 G4ThreeVector particlePositionPreStepGlobal = track.GetStep()->GetPreStepPoint()->GetPosition();
110 G4ThreeVector particleMomentumDirectionPreStepGlobal = track.GetStep()->GetPreStepPoint()->GetMomentumDirection();
111
112 G4ThreeVector stepVector = particlePositionPostStepGlobal-particlePositionPreStepGlobal;
113 G4double stepMagnitude = stepVector.mag();
114
115 //#################### Get rotation and translation matrices for global to laser coordinates ############################
116
117 const G4RotationMatrix* rot = track.GetTouchable()->GetRotation();
118 const G4AffineTransform transform = track.GetTouchable()->GetHistory()->GetTopTransform();
119
120 //######################## Get/Create photon information ##############################
121 G4ThreeVector photonUnit(0,0,1);
122 photonUnit.transform(*rot);
123 G4double photonEnergy = (CLHEP::h_Planck*CLHEP::c_light)/laser->Wavelength();
124 G4ThreeVector photonVector = photonUnit*photonEnergy;
125 G4LorentzVector photonLorentzVector = G4LorentzVector(photonVector,photonEnergy);
126
127 photonLorentzVector.boost(particleBeta);
128 G4double photonEnergyLorentz = photonLorentzVector.e();
129
130 G4double photonFluxSum = 0;
131
132 G4double particleTimePreStepGlobal = track.GetStep()->GetPreStepPoint()->GetGlobalTime();
133
134 std::vector<G4double> fluxArray;
135 std::vector<G4LorentzVector> trajectoryPositions;
136
137
138 for(G4int i = 0;i<=99;i++)
139 {
140 G4ThreeVector stepPositionGlobal = particlePositionPreStepGlobal+float(i)*(stepMagnitude/100.)*particleMomentumDirectionPreStepGlobal;
141 G4ThreeVector stepPositionLocal = transform.TransformPoint(stepPositionGlobal);
142 G4double stepTimeGlobal = particleTimePreStepGlobal+(float(i)*(stepMagnitude/100.)/particleVelocity);
143 G4double stepIntensity = ((laser->Intensity(stepPositionLocal)/photonEnergyLorentz)
144 * laser->TemporalProfileGaussian(stepTimeGlobal,stepPositionLocal.z()));
145 photonFluxSum = photonFluxSum + stepIntensity;
146 fluxArray.push_back(stepIntensity);
147 }
148
149 G4double crossSection = photoDetachmentEngine->CrossSection(photonEnergyLorentz);
150
151 G4double stepTime = stepMagnitude/particleVelocity;
152 G4double cumulativeProbability = 1.0 - std::exp((-1.0*crossSection*photonFluxSum*(stepTime/100.)*particleGamma));
153
154 G4double secondaryStepPosition;
155
156 if (photonFluxSum == 0)
157 {secondaryStepPosition = G4UniformRand();}
158 else
159 {
160 G4RandGeneral trajectoryPDFRandom = CLHEP::RandGeneral(*CLHEP::HepRandom::getTheEngine(),
161 fluxArray.data(),100,0);
162 secondaryStepPosition = trajectoryPDFRandom.shoot();
163 }
164
165 G4ThreeVector proposedPositionGlobal = particlePositionPreStepGlobal + (stepMagnitude*secondaryStepPosition*particleMomentumDirectionPreStepGlobal);
166 G4double proposedTimeGlobal = particleTimePreStepGlobal + (stepMagnitude*secondaryStepPosition/particleVelocity);
167
168 aParticleChange.ProposePosition(proposedPositionGlobal);
169 G4double initialWeight=aParticleChange.GetParentWeight();
170 aParticleChange.ProposeParentWeight(initialWeight*cumulativeProbability);
171 aParticleChange.SetNumberOfSecondaries(1);
172
173 // electron kinematics
174 G4ThreeVector randomDirection = G4RandomDirection();
175 G4double hydrogenMass = (CLHEP::electron_mass_c2 + CLHEP::proton_mass_c2);
176 G4double outgoingElectronEnergy = CLHEP::electron_mass_c2;
177 G4double ionEnergy = ion->GetTotalEnergy();
178 G4ThreeVector ionMomentum = ion->GetMomentum();
179 G4ThreeVector ionBeta = ionMomentum/ionEnergy;
180
181 G4LorentzVector outgoingElectron;
182 outgoingElectron.setE(outgoingElectronEnergy);
183
184 G4double ionMass = ion->GetMass();
185 // hydrogen kinematics
186
187 G4double outgoingH0Energy = ionMass+photonEnergyLorentz-outgoingElectronEnergy;
188 G4double outgoingH0Momentum = std::sqrt(outgoingH0Energy*outgoingH0Energy-hydrogenMass*hydrogenMass);
189 G4LorentzVector outgoingH0;
190 outgoingH0.setPx(-1.0*randomDirection.x()*outgoingH0Momentum);
191 outgoingH0.setPy(-1.0*randomDirection.y()*outgoingH0Momentum);
192 outgoingH0.setPz(-1.0*randomDirection.z()*outgoingH0Momentum);
193 outgoingH0.setE(outgoingH0Energy);
194
195 outgoingElectron.boost(ionBeta);
196 outgoingH0.boost(ionBeta);
197
198 aParticleChange.ProposeMass(hydrogenMass);
199 G4ThreeVector H0Momentum;
200 H0Momentum.set(outgoingH0.px(),outgoingH0.py(),outgoingH0.pz());
201 aParticleChange.ProposeMomentumDirection(H0Momentum.unit());
202 aParticleChange.ProposeCharge(0);
203 ion->RemoveElectron(1);
204 ion->SetCharge(0);
205
206 // create outgoing electron
207 G4DynamicParticle* electron = new G4DynamicParticle(G4Electron::ElectronDefinition(),
208 outgoingElectron.vect().unit(),
209 outgoingElectron.e());
210 aParticleChange.AddSecondary(electron,proposedTimeGlobal);
211 aParticleChange.ProposePosition(particlePositionPostStepGlobal);
212
213 aParticleChange.ProposeParentWeight(initialWeight*cumulativeProbability);
214 return G4VDiscreteProcess::PostStepDoIt(track, step);
215}
216
Extra G4Navigator to get coordinate transforms.
Class to provide laser intensity at any point.
Definition BDSLaser.hh:35
G4double Wavelength() const
Accessor.
Definition BDSLaser.hh:63
Extended logical volume with laser definition.
const BDSLaser * Laser() const
Access the laser.