Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4MicroElecSurface.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// G4MicroElecSurface.cc,
28// 2020/05/20 P. Caron, C. Inguimbert are with ONERA [b]
29// Q. Gibaru is with CEA [a], ONERA [b] and CNES [c]
30// M. Raine and D. Lambert are with CEA [a]
31//
32// A part of this work has been funded by the French space agency(CNES[c])
33// [a] CEA, DAM, DIF - 91297 ARPAJON, France
34// [b] ONERA - DPHY, 2 avenue E.Belin, 31055 Toulouse, France
35// [c] CNES, 18 av.E.Belin, 31401 Toulouse CEDEX, France
36//
37// Based on the following publications
38//
39// - Q.Gibaru, C.Inguimbert, P.Caron, M.Raine, D.Lambert, J.Puech,
40// Geant4 physics processes for microdosimetry and secondary electron emission simulation:
41// Extension of MicroElec to very low energies and new materials
42// NIM B, 2020, in review.
43//
44// - Modele de transport d'electrons a basse energie (10 eV- 2 keV) pour
45// applications spatiales (OSMOSEE, GEANT4), PhD dissertation, 2017.
46//
47////////////////////////////////////////////////////////////////////////
48
49#include "G4MicroElecSurface.hh"
50#include "G4ios.hh"
52#include "G4EmProcessSubType.hh"
54#include "G4SystemOfUnits.hh"
55
56
57//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
58
60 : G4VDiscreteProcess(processName, type),
61 oldMomentum(0.,0.,0.), previousMomentum(0.,0.,0.),
62 theGlobalNormal(0.,0.,0.), theFacetNormal(0.,0.,0.)
63{
64 if ( verboseLevel > 0)
65 {
66 G4cout << GetProcessName() << " is created " << G4endl;
67 }
68
69 isInitialised=false;
71
72 theStatus = UndefinedSurf;
73 material1 = nullptr;
74 material2 = nullptr;
75
77 theParticleMomentum = 0.;
78
79 flag_franchissement_surface = false;
80 flag_normal = false;
81 flag_reflexion = false;
82 teleportToDo = teleportDone = false;
83
84 ekint = thetat = thetaft = energyThreshold = crossingProbability = 0.0;
85}
86
87//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
88
91
92//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
93
94G4bool
96{
97 return ( aParticleType.GetPDGEncoding() == 11 );
98}
99
100//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
101
103{
104 if (isInitialised) { return; }
105
106 G4ProductionCutsTable* theCoupleTable =
108 G4int numOfCouples = (G4int)theCoupleTable->GetTableSize();
109 G4cout << numOfCouples << G4endl;
110
111 for (G4int i = 0; i < numOfCouples; ++i)
112 {
113 const G4Material* material =
114 theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial();
115
116 G4cout << this->GetProcessName() << ", Material " << i + 1
117 << " / " << numOfCouples << " : " << material->GetName() << G4endl;
118 if (material->GetName() == "Vacuum")
119 {
120 tableWF[material->GetName()] = 0; continue;
121 }
122 G4String mat = material->GetName();
124 tableWF[mat] = str.GetWorkFunction();
125 }
126
127 isInitialised = true;
128}
129
130//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
131
133{
134
135 G4ProductionCutsTable* theCoupleTable =
137 G4int numOfCouples = (G4int)theCoupleTable->GetTableSize();
138 G4cout << "G4MicroElecSurface::Initialise: Ncouples= "
139 << numOfCouples << G4endl;
140
141 for (G4int i = 0; i < numOfCouples; ++i)
142 {
143 const G4Material* material =
144 theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial();
145
146 G4cout << "G4Surface, Material " << i + 1 << " / "
147 << numOfCouples << " : " << material->GetName() << G4endl;
148 if (material->GetName() == "Vacuum")
149 {
150 tableWF[material->GetName()] = 0;
151 continue;
152 }
153 G4String mat = material->GetName();
155 tableWF[mat] = str.GetWorkFunction();
156 }
157 isInitialised = true;
158}
159
160//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
161
163{
164
165 if (!isInitialised) { Initialise(); }
166 theStatus = UndefinedSurf;
167
168 // Definition of the parameters for the particle
169 aParticleChange.Initialize(aTrack);
170 aParticleChange.ProposeVelocity(aTrack.GetVelocity());
171
172 G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
173 G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
174
175 material1 = pPreStepPoint -> GetMaterial();
176 material2 = pPostStepPoint -> GetMaterial();
177
178 theStatus = UndefinedSurf;
179
180 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
181
182 theParticleMomentum = aParticle->GetTotalMomentum();
183 previousMomentum = oldMomentum;
184 oldMomentum = aParticle->GetMomentumDirection();
185
186 // Fisrt case: not a boundary
187 if (pPostStepPoint->GetStepStatus() != fGeomBoundary
188 || pPostStepPoint->GetPhysicalVolume()->GetName() == pPreStepPoint->GetPhysicalVolume()->GetName())
189 {
190 theStatus = NotAtBoundarySurf;
191 flag_franchissement_surface = false;
192 flag_reflexion = false;
193 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
194 }
195 theStatus = UndefinedSurf;
196
197 // Third case: same material
198 if (material1 == material2)
199 {
200 theStatus = SameMaterialSurf;
201 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
202 }
203 if (verboseLevel > 3)
204 {
205 G4cout << G4endl << " Electron at Boundary! " << G4endl;
206 G4VPhysicalVolume* thePrePV = pPreStepPoint->GetPhysicalVolume();
207 G4VPhysicalVolume* thePostPV = pPostStepPoint->GetPhysicalVolume();
208 if (thePrePV) G4cout << " thePrePV: " << thePrePV->GetName() << G4endl;
209 if (thePostPV) G4cout << " thePostPV: " << thePostPV->GetName() << G4endl;
210 G4cout << " Old Momentum Direction: " << oldMomentum << G4endl;
211 }
212
213 // Definition of the parameters for the surface
214 G4ThreeVector theGlobalPoint = pPostStepPoint->GetPosition();
215
218
219 G4bool valid;
220 theGlobalNormal = theNavigator->GetGlobalExitNormal(theGlobalPoint, &valid);
221
222 if (valid)
223 {
224 theGlobalNormal = -theGlobalNormal;
225 }
226 else
227 {
229 ed << " G4MicroElecSurface/PostStepDoIt(): "
230 << " The Navigator reports that it returned an invalid normal"
231 << G4endl;
232 G4Exception("G4MuElecSurf::PostStepDoIt", "OpBoun01",
234 "Invalid Surface Normal - Geometry must return valid surface normal");
235 }
236
237 // Exception: the particle is not in the right direction
238 if (oldMomentum * theGlobalNormal > 0.0)
239 {
240 theGlobalNormal = -theGlobalNormal;
241 }
242
243 if (aTrack.GetStepLength()<=kCarTolerance/2 * 0.0000000001)
244 {
245 if (flag_reflexion == true)
246 {
247 flag_reflexion = false;
248 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
249 }
250
251 theStatus = StepTooSmallSurf;
252
253 G4double energyThreshold_surface = 0.0*eV;
254
255 WorkFunctionTable::iterator postStepWF;
256 postStepWF = tableWF.find(pPostStepPoint->GetMaterial()->GetName());
257 WorkFunctionTable::iterator preStepWF;
258 preStepWF = tableWF.find(pPreStepPoint->GetMaterial()->GetName());
259
260 if (postStepWF == tableWF.end())
261 {
262 G4String str = "Material ";
263 str += pPostStepPoint->GetMaterial()->GetName() + " not found!";
264 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
265 return nullptr;
266 }
267 else if (preStepWF == tableWF.end())
268 {
269 G4String str = "Material ";
270 str += pPreStepPoint->GetMaterial()->GetName() + " not found!";
271 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
272 return nullptr;
273 }
274 else
275 {
276 G4double thresholdNew_surface = postStepWF->second;
277 G4double thresholdOld_surface = preStepWF->second;
278 energyThreshold_surface = thresholdNew_surface - thresholdOld_surface;
279 }
280
281 if (flag_franchissement_surface == true)
282 {
283 aParticleChange.ProposeEnergy(aStep.GetPostStepPoint()->GetKineticEnergy() + energyThreshold_surface);
284 flag_franchissement_surface = false;
285 }
286 if (flag_reflexion == true && flag_normal == true)
287 {
288 aParticleChange.ProposeMomentumDirection(-Reflexion(aStep.GetPostStepPoint()));
289 flag_reflexion = false;
290 flag_normal = false;
291 }
292 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
293 }
294
295 flag_normal = (theGlobalNormal == G4ThreeVector(0, 0, 1)
296 || theGlobalNormal == G4ThreeVector(0, 0, -1));
297
298 G4LogicalSurface* Surface = nullptr;
299
301 (pPreStepPoint ->GetPhysicalVolume(),
302 pPostStepPoint->GetPhysicalVolume());
303
304 if (Surface == nullptr)
305 {
306 G4bool enteredDaughter=(pPostStepPoint->GetPhysicalVolume()->GetMotherLogical()
307 == pPreStepPoint->GetPhysicalVolume()->GetLogicalVolume());
308 if(enteredDaughter)
309 {
311 (pPostStepPoint->GetPhysicalVolume()->GetLogicalVolume());
312
313 if(Surface == nullptr)
315 (pPreStepPoint->GetPhysicalVolume()->GetLogicalVolume());
316 }
317 else
318 {
320 (pPreStepPoint->GetPhysicalVolume()->GetLogicalVolume());
321
322 if(Surface == nullptr)
324 (pPostStepPoint->GetPhysicalVolume()->GetLogicalVolume());
325 }
326 }
327
328 // Definition of the parameters for the surface crossing
329 G4VPhysicalVolume* thePrePV = pPreStepPoint->GetPhysicalVolume();
330 G4VPhysicalVolume* thePostPV = pPostStepPoint->GetPhysicalVolume();
331
332 energyThreshold = 0.0*eV;
333 G4double energyDelta = 0;
334
335 if ((thePrePV)&&(thePostPV))
336 {
337 WorkFunctionTable::iterator postStepWF;
338 postStepWF = tableWF.find(thePostPV->GetLogicalVolume()->GetMaterial()->GetName());
339 WorkFunctionTable::iterator preStepWF;
340 preStepWF = tableWF.find(thePrePV->GetLogicalVolume()->GetMaterial()->GetName());
341
342 if (postStepWF == tableWF.end())
343 {
344 G4String str = "Material ";
345 str += thePostPV->GetLogicalVolume()->GetMaterial()->GetName() + " not found!";
346 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
347 return nullptr;
348 }
349 else if (preStepWF == tableWF.end())
350 {
351 G4String str = "Material ";
352 str += thePrePV->GetLogicalVolume()->GetMaterial()->GetName() + " not found!";
353 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
354 return nullptr;
355 }
356 else
357 {
358 G4double thresholdNew = postStepWF->second;
359 G4double thresholdOld = preStepWF->second;
360
361 energyThreshold = thresholdNew - thresholdOld;
362 energyDelta = thresholdOld- thresholdNew;
363 }
364 }
365
366 ekint=aStep.GetPostStepPoint()->GetKineticEnergy();
367 thetat= GetIncidentAngle(); //angle d'incidence
368 G4double ekinNormalt=ekint*std::cos(thetat)*std::cos(thetat);
369 G4double sin_thetaft = std::sqrt(ekint/(ekint+energyThreshold))*std::sin(thetat);
370 G4double cos_thetaft = 0.0;
371 //Refraction angle
372
373 if (1.0-sin_thetaft*sin_thetaft>0) {
374 cos_thetaft = std::sqrt(1.0-sin_thetaft*sin_thetaft);
375 }
376 else {
377 cos_thetaft = 0.0;
378 }
379
380 G4double aleat=G4UniformRand();
381 G4double waveVectort=std::sqrt(2*9.1093826E-31*1.602176487E-19)/(6.6260755E-34/(2.0*pi));
382
383 // Parameter for an exponential barrier of potential (Thesis P68)
384 G4double at=0.5E-10;
385
386 crossingProbability=0;
387
388 G4double kft=waveVectort*std::sqrt(ekint+energyThreshold)*cos_thetaft;
389 G4double kit=waveVectort*std::sqrt(ekinNormalt);
390
391 crossingProbability=1-(std::pow(std::sinh(pi*at*(kit-kft)), 2.0)/std::pow(std::sinh(pi*at*(kit+kft)), 2.0));
392
393 // First case: the electron crosses the surface
394 if((aleat<=crossingProbability)&&(ekint> energyDelta))
395 {
396 if (aStep.GetPreStepPoint()->GetMaterial()->GetName()
397 != aStep.GetPostStepPoint()->GetMaterial()->GetName())
398 {
399 aParticleChange.ProposeEnergy(ekint - energyDelta);
400 flag_franchissement_surface = true;
401 }
402
403 // calculation of cos_thetaft for thetaft=std::abs(thetaft-thetat);
404 cos_thetaft = cos_thetaft*std::cos(thetat)+sin_thetaft*std::sin(thetat);
405
407 G4ThreeVector xVerst = zVerst.orthogonal();
408 G4ThreeVector yVerst = zVerst.cross(xVerst);
409
410 G4double xDirt = std::sqrt(1. - cos_thetaft*cos_thetaft);
411 G4double yDirt = xDirt;
412
413 G4ThreeVector zPrimeVerst=((xDirt*xVerst + yDirt*yVerst + cos_thetaft*zVerst));
414
415 aParticleChange.ProposeMomentumDirection(zPrimeVerst.unit());
416 }
417 else if ((aleat > crossingProbability) && (ekint> energyDelta))
418 {
419 flag_reflexion = true;
420 if (flag_normal)
421 {
422 aParticleChange.ProposeMomentumDirection(-oldMomentum.unit());
423 }
424 else
425 {
426 aParticleChange.ProposeMomentumDirection(Reflexion(aStep.GetPostStepPoint()));
427 }
428 }
429 else
430 {
431 if (flag_normal)
432 {
433 aParticleChange.ProposeMomentumDirection(-oldMomentum.unit());
434 }
435 else
436 {
437 aParticleChange.ProposeMomentumDirection(Reflexion(aStep.GetPostStepPoint()));
438 }
439 flag_reflexion = true;
440 }
441 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
442}
443
444//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
445
452
453//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
454
455G4double G4MicroElecSurface::GetIncidentAngle()
456{
457 theFacetNormal=theGlobalNormal;
458
459 G4double PdotN = oldMomentum * theFacetNormal;
460 G4double magP= oldMomentum.mag();
461 G4double magN= theFacetNormal.mag();
462
463 G4double incidentangle = pi - std::acos(PdotN/(magP*magN));
464
465 return incidentangle;
466}
467
468//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
469
470G4ThreeVector G4MicroElecSurface::Reflexion(const G4StepPoint* PostStepPoint)
471{
472 // Normale
473 G4double Nx = theGlobalNormal.x();
474 G4double Ny = theGlobalNormal.y();
475 G4double Nz = theGlobalNormal.z();
476
477 // PostStepPoint
478 G4double PSx = PostStepPoint->GetPosition().x();
479 G4double PSy = PostStepPoint->GetPosition().y();
480 G4double PSz = PostStepPoint->GetPosition().z();
481
482 // P(alpha,beta,gamma) - PostStep avec translation momentum
483 G4double alpha = PSx + oldMomentum.x();
484 G4double beta = PSy + oldMomentum.y();
485 G4double gamma = PSz + oldMomentum.z();
486 G4double r = theGlobalNormal.mag();
487 G4double x, y, z, d, A, B, PM2x, PM2y, PM2z;
488 d = -(Nx*PSx + Ny*PSy + Nz*PSz);
489
490 if (Ny == 0 && Nx == 0)
491 {
492 gamma = -gamma;
493 }
494 else
495 {
496 if (Ny == 0)
497 {
498 A = (Nz*Nz*alpha) + (Nx*Nx*PSx) + (Nx*Nz*(PSz - gamma));
499 B = r*r;
500
501 // M(x,y,z) - Projection de P sur la surface
502 x = A / B;
503 y = beta;
504 z = (x - alpha)*(Nz / Nx) + gamma;
505 }
506 else
507 {
508 A = (r*r) / Ny;
509 B = (beta / Ny)*(Nx*Nx + Nz*Nz) - (Nx*alpha + Nz*gamma + d);
510
511 //M(x,y,z) - Projection de P sur la surface
512 y = B / A;
513 x = (y - beta)*(Nx / Ny) + alpha;
514 z = (y - beta)*(Nz / Ny) + gamma;
515 }
516
517 // Vecteur 2*PM
518 PM2x = 2 * (x - alpha); PM2y = 2 * (y - beta); PM2z = 2 * (z - gamma);
519
520 // Nouveau point P
521 alpha += PM2x; beta += PM2y; gamma += PM2z;
522
523 }
524
525 G4ThreeVector newMomentum = G4ThreeVector(alpha-PSx,beta-PSy,gamma-PSz);
526 return newMomentum.unit();
527}
528
529//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
530
532{
533 return theStatus;
534}
535
536//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
537
538
540{
541 flag_franchissement_surface = false;
542}
543
544//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
545
G4double B(G4double temperature)
@ fSurfaceReflection
G4double condition(const G4ErrorSymMatrix &m)
@ FatalException
@ EventMustBeAborted
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4ForceCondition
@ Forced
G4MicroElecSurfaceStatus
@ StepTooSmallSurf
@ SameMaterialSurf
@ UndefinedSurf
@ NotAtBoundarySurf
G4ProcessType
@ fGeomBoundary
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
const G4double A[17]
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
double z() const
Hep3Vector unit() const
Hep3Vector orthogonal() const
double x() const
double y() const
Hep3Vector cross(const Hep3Vector &) const
double mag() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetTotalMomentum() const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
static G4LogicalBorderSurface * GetSurface(const G4VPhysicalVolume *vol1, const G4VPhysicalVolume *vol2)
static G4LogicalSkinSurface * GetSurface(const G4LogicalVolume *vol)
G4LogicalSurface is an abstraction of a geometrical surface, it is an abstract base class for differe...
G4Material * GetMaterial() const
const G4Material * GetMaterial() const
const G4String & GetName() const
G4MicroElecSurfaceStatus GetStatus() const
G4double GetMeanFreePath(const G4Track &, G4double, G4ForceCondition *condition) override
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep) override
void BuildPhysicsTable(const G4ParticleDefinition &) override
G4MicroElecSurface(const G4String &processName="MicroElecSurface", G4ProcessType type=fElectromagnetic)
G4bool IsApplicable(const G4ParticleDefinition &aParticleType) override
G4Navigator is a class for use by the tracking management, able to obtain/calculate dynamic tracking ...
virtual G4ThreeVector GetGlobalExitNormal(const G4ThreeVector &point, G4bool *valid)
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
G4StepStatus GetStepStatus() const
G4Material * GetMaterial() const
const G4ThreeVector & GetPosition() const
const G4ThreeVector & GetMomentumDirection() const
G4VPhysicalVolume * GetPhysicalVolume() const
G4double GetKineticEnergy() const
G4StepPoint * GetPreStepPoint() const
G4StepPoint * GetPostStepPoint() const
G4double GetVelocity() const
const G4DynamicParticle * GetDynamicParticle() const
G4double GetStepLength() const
static G4TransportationManager * GetTransportationManager()
G4Navigator * GetNavigatorForTracking() const
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
G4VDiscreteProcess(const G4String &aName, G4ProcessType aType=fNotDefined)
G4VPhysicalVolume is an abstract base class for the representation of a positioned volume....
G4LogicalVolume * GetLogicalVolume() const
const G4String & GetName() const
G4ParticleChange aParticleChange
G4int verboseLevel
void SetProcessSubType(G4int)
const G4String & GetProcessName() const
#define DBL_MAX
Definition templates.hh:62