Geant4 11.2.2
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 if (isInitialised) { return; }
135
136 G4ProductionCutsTable* theCoupleTable =
138 G4int numOfCouples = (G4int)theCoupleTable->GetTableSize();
139 G4cout << "G4MicroElecSurface::Initialise: Ncouples= "
140 << numOfCouples << G4endl;
141
142 for (G4int i = 0; i < numOfCouples; ++i)
143 {
144 const G4Material* material =
145 theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial();
146
147 G4cout << "G4Surface, Material " << i + 1 << " / "
148 << numOfCouples << " : " << material->GetName() << G4endl;
149 if (material->GetName() == "Vacuum")
150 {
151 tableWF[material->GetName()] = 0;
152 continue;
153 }
154 G4String mat = material->GetName();
156 tableWF[mat] = str.GetWorkFunction();
157 }
158 isInitialised = true;
159}
160
161//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
162
164{
165
166 if (!isInitialised) { Initialise(); }
167 theStatus = UndefinedSurf;
168
169 // Definition of the parameters for the particle
172
173 G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
174 G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
175
176 material1 = pPreStepPoint -> GetMaterial();
177 material2 = pPostStepPoint -> GetMaterial();
178
179 theStatus = UndefinedSurf;
180
181 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
182
183 theParticleMomentum = aParticle->GetTotalMomentum();
184 previousMomentum = oldMomentum;
185 oldMomentum = aParticle->GetMomentumDirection();
186
187
188 // Fisrt case: not a boundary
189 if (pPostStepPoint->GetStepStatus() != fGeomBoundary
190 || pPostStepPoint->GetPhysicalVolume()->GetName() == pPreStepPoint->GetPhysicalVolume()->GetName())
191 {
192 theStatus = NotAtBoundarySurf;
193 flag_franchissement_surface = false;
194 flag_reflexion = false;
195 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
196 }
197 theStatus = UndefinedSurf;
198
199 // Third case: same material
200 if (material1 == material2)
201 {
202 theStatus = SameMaterialSurf;
203 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
204 }
205 if (verboseLevel > 3)
206 {
207 G4cout << G4endl << " Electron at Boundary! " << G4endl;
208 G4VPhysicalVolume* thePrePV = pPreStepPoint->GetPhysicalVolume();
209 G4VPhysicalVolume* thePostPV = pPostStepPoint->GetPhysicalVolume();
210 if (thePrePV) G4cout << " thePrePV: " << thePrePV->GetName() << G4endl;
211 if (thePostPV) G4cout << " thePostPV: " << thePostPV->GetName() << G4endl;
212 G4cout << " Old Momentum Direction: " << oldMomentum << G4endl;
213 }
214
215 // Definition of the parameters for the surface
216 G4ThreeVector theGlobalPoint = pPostStepPoint->GetPosition();
217
220
221 G4bool valid;
222 theGlobalNormal = theNavigator->GetGlobalExitNormal(theGlobalPoint, &valid);
223
224 if (valid)
225 {
226 theGlobalNormal = -theGlobalNormal;
227 }
228 else
229 {
231 ed << " G4MicroElecSurface/PostStepDoIt(): "
232 << " The Navigator reports that it returned an invalid normal"
233 << G4endl;
234 G4Exception("G4MuElecSurf::PostStepDoIt", "OpBoun01",
236 "Invalid Surface Normal - Geometry must return valid surface normal");
237 }
238
239 // Exception: the particle is not in the right direction
240 if (oldMomentum * theGlobalNormal > 0.0)
241 {
242 theGlobalNormal = -theGlobalNormal;
243 }
244
245 if (aTrack.GetStepLength()<=kCarTolerance/2 * 0.0000000001)
246 {
247 if (flag_reflexion == true)
248 {
249 flag_reflexion = false;
250 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
251 }
252
253 theStatus = StepTooSmallSurf;
254
255 G4double energyThreshold_surface = 0.0*eV;
256
257 WorkFunctionTable::iterator postStepWF;
258 postStepWF = tableWF.find(pPostStepPoint->GetMaterial()->GetName());
259 WorkFunctionTable::iterator preStepWF;
260 preStepWF = tableWF.find(pPreStepPoint->GetMaterial()->GetName());
261
262 if (postStepWF == tableWF.end())
263 {
264 G4String str = "Material ";
265 str += pPostStepPoint->GetMaterial()->GetName() + " not found!";
266 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
267 return nullptr;
268 }
269 else if (preStepWF == tableWF.end())
270 {
271 G4String str = "Material ";
272 str += pPreStepPoint->GetMaterial()->GetName() + " not found!";
273 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
274 return nullptr;
275 }
276 else
277 {
278 G4double thresholdNew_surface = postStepWF->second;
279 G4double thresholdOld_surface = preStepWF->second;
280 energyThreshold_surface = thresholdNew_surface - thresholdOld_surface;
281 }
282
283 if (flag_franchissement_surface == true)
284 {
285 aParticleChange.ProposeEnergy(aStep.GetPostStepPoint()->GetKineticEnergy() + energyThreshold_surface);
286 flag_franchissement_surface = false;
287 }
288 if (flag_reflexion == true && flag_normal == true)
289 {
291 flag_reflexion = false;
292 flag_normal = false;
293 }
294 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
295 }
296
297 flag_normal = (theGlobalNormal == G4ThreeVector(0, 0, 1)
298 || theGlobalNormal == G4ThreeVector(0, 0, -1));
299
300 G4LogicalSurface* Surface = nullptr;
301
303 (pPreStepPoint ->GetPhysicalVolume(),
304 pPostStepPoint->GetPhysicalVolume());
305
306 if (Surface == nullptr)
307 {
308 G4bool enteredDaughter=(pPostStepPoint->GetPhysicalVolume()->GetMotherLogical()
309 == pPreStepPoint->GetPhysicalVolume()->GetLogicalVolume());
310 if(enteredDaughter)
311 {
313 (pPostStepPoint->GetPhysicalVolume()->GetLogicalVolume());
314
315 if(Surface == nullptr)
317 (pPreStepPoint->GetPhysicalVolume()->GetLogicalVolume());
318 }
319 else
320 {
322 (pPreStepPoint->GetPhysicalVolume()->GetLogicalVolume());
323
324 if(Surface == nullptr)
326 (pPostStepPoint->GetPhysicalVolume()->GetLogicalVolume());
327 }
328 }
329
330 // Definition of the parameters for the surface crossing
331 G4VPhysicalVolume* thePrePV = pPreStepPoint->GetPhysicalVolume();
332 G4VPhysicalVolume* thePostPV = pPostStepPoint->GetPhysicalVolume();
333
334 energyThreshold = 0.0*eV;
335 G4double energyDelta = 0;
336
337 if ((thePrePV)&&(thePostPV))
338 {
339 WorkFunctionTable::iterator postStepWF;
340 postStepWF = tableWF.find(thePostPV->GetLogicalVolume()->GetMaterial()->GetName());
341 WorkFunctionTable::iterator preStepWF;
342 preStepWF = tableWF.find(thePrePV->GetLogicalVolume()->GetMaterial()->GetName());
343
344 if (postStepWF == tableWF.end())
345 {
346 G4String str = "Material ";
347 str += thePostPV->GetLogicalVolume()->GetMaterial()->GetName() + " not found!";
348 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
349 return nullptr;
350 }
351 else if (preStepWF == tableWF.end())
352 {
353 G4String str = "Material ";
354 str += thePrePV->GetLogicalVolume()->GetMaterial()->GetName() + " not found!";
355 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
356 return nullptr;
357 }
358 else
359 {
360 G4double thresholdNew = postStepWF->second;
361 G4double thresholdOld = preStepWF->second;
362
363 energyThreshold = thresholdNew - thresholdOld;
364 energyDelta = thresholdOld- thresholdNew;
365 }
366 }
367
368 ekint=aStep.GetPostStepPoint()->GetKineticEnergy();
369 thetat= GetIncidentAngle(); //angle d'incidence
370 G4double ekinNormalt=ekint*std::cos(thetat)*std::cos(thetat);
371
372 thetaft=std::asin(std::sqrt(ekint/(ekint+energyThreshold))*std::sin(thetat));//Angle de refraction
373 if(std::sqrt(ekint/(ekint+energyThreshold))*std::sin(thetat)>1.0)
374 {
375 thetaft=std::asin(1.0);
376 }
377
378 G4double aleat=G4UniformRand();
379
380 G4double waveVectort=std::sqrt(2*9.1093826E-31*1.602176487E-19)/(6.6260755E-34/(2.0*pi));
381
382 // Parameter for an exponential barrier of potential (Thesis P68)
383 G4double at=0.5E-10;
384
385 crossingProbability=0;
386
387 G4double kft=waveVectort*std::sqrt(ekint+energyThreshold)*std::cos(thetaft);
388 G4double kit=waveVectort*std::sqrt(ekinNormalt);
389
390 crossingProbability=1-(std::pow(std::sinh(pi*at*(kit-kft)), 2.0)/std::pow(std::sinh(pi*at*(kit+kft)), 2.0));
391
392 // First case: the electron crosses the surface
393 if((aleat<=crossingProbability)&&(ekint> energyDelta))
394 {
395 if (aStep.GetPreStepPoint()->GetMaterial()->GetName()
396 != aStep.GetPostStepPoint()->GetMaterial()->GetName())
397 {
398 aParticleChange.ProposeEnergy(ekint - energyDelta);
399 flag_franchissement_surface = true;
400 }
401
402 thetaft=std::abs(thetaft-thetat);
403
405 G4ThreeVector xVerst = zVerst.orthogonal();
406 G4ThreeVector yVerst = zVerst.cross(xVerst);
407
408 G4double xDirt = std::sqrt(1. - std::cos(thetaft)*std::cos(thetaft));
409 G4double yDirt = xDirt;
410
411 G4ThreeVector zPrimeVerst=((xDirt*xVerst + yDirt*yVerst + std::cos(thetaft)*zVerst));
412
414 }
415 else if ((aleat > crossingProbability) && (ekint> energyDelta))
416 {
417 flag_reflexion = true;
418 if (flag_normal)
419 {
421 }
422 else
423 {
425 }
426 }
427 else
428 {
429 if (flag_normal)
430 {
432 }
433 else
434 {
436 }
437 flag_reflexion = true;
438 }
439 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
440}
441
442//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
443
450
451//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
452
453G4double G4MicroElecSurface::GetIncidentAngle()
454{
455 theFacetNormal=theGlobalNormal;
456
457 G4double PdotN = oldMomentum * theFacetNormal;
458 G4double magP= oldMomentum.mag();
459 G4double magN= theFacetNormal.mag();
460
461 G4double incidentangle = pi - std::acos(PdotN/(magP*magN));
462
463 return incidentangle;
464}
465
466//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
467
468G4ThreeVector G4MicroElecSurface::Reflexion(const G4StepPoint* PostStepPoint)
469{
470 // Normale
471 G4double Nx = theGlobalNormal.x();
472 G4double Ny = theGlobalNormal.y();
473 G4double Nz = theGlobalNormal.z();
474
475 // PostStepPoint
476 G4double PSx = PostStepPoint->GetPosition().x();
477 G4double PSy = PostStepPoint->GetPosition().y();
478 G4double PSz = PostStepPoint->GetPosition().z();
479
480 // P(alpha,beta,gamma) - PostStep avec translation momentum
481 G4double alpha = PSx + oldMomentum.x();
482 G4double beta = PSy + oldMomentum.y();
483 G4double gamma = PSz + oldMomentum.z();
484 G4double r = theGlobalNormal.mag();
485 G4double x, y, z, d, A, B, PM2x, PM2y, PM2z;
486 d = -(Nx*PSx + Ny*PSy + Nz*PSz);
487
488 if (Ny == 0 && Nx == 0)
489 {
490 gamma = -gamma;
491 }
492 else
493 {
494 if (Ny == 0)
495 {
496 A = (Nz*Nz*alpha) + (Nx*Nx*PSx) + (Nx*Nz*(PSz - gamma));
497 B = r*r;
498
499 // M(x,y,z) - Projection de P sur la surface
500 x = A / B;
501 y = beta;
502 z = (x - alpha)*(Nz / Nx) + gamma;
503 }
504 else
505 {
506 A = (r*r) / Ny;
507 B = (beta / Ny)*(Nx*Nx + Nz*Nz) - (Nx*alpha + Nz*gamma + d);
508
509 //M(x,y,z) - Projection de P sur la surface
510 y = B / A;
511 x = (y - beta)*(Nx / Ny) + alpha;
512 z = (y - beta)*(Nz / Ny) + gamma;
513 }
514
515 // Vecteur 2*PM
516 PM2x = 2 * (x - alpha); PM2y = 2 * (y - beta); PM2z = 2 * (z - gamma);
517
518 // Nouveau point P
519 alpha += PM2x; beta += PM2y; gamma += PM2z;
520
521 }
522
523 G4ThreeVector newMomentum = G4ThreeVector(alpha-PSx,beta-PSy,gamma-PSz);
524 return newMomentum.unit();
525}
526
527//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
528
530{
531 return theStatus;
532}
533
534//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
535
536
538{
539 flag_franchissement_surface = false;
540}
541
542//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
543
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)
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
virtual G4ThreeVector GetGlobalExitNormal(const G4ThreeVector &point, G4bool *valid)
void Initialize(const G4Track &) override
void ProposeVelocity(G4double finalVelocity)
void ProposeEnergy(G4double finalEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
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 &)
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