Geant4 10.7.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//
45// - Modèle de transport d'électrons à basse énergie (10 eV- 2 keV) pour
46// applications spatiales (OSMOSEE, GEANT4), PhD dissertation, 2017.
47//
48//
49////////////////////////////////////////////////////////////////////////
50
51#include "G4MicroElecSurface.hh"
52
53#include "G4ios.hh"
55#include "G4EmProcessSubType.hh"
57
58#include "G4SystemOfUnits.hh"
59
60
61//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
62
64 : G4VDiscreteProcess(processName, type),
65 oldMomentum(0.,0.,0.), previousMomentum(0.,0.,0.),
66 theGlobalNormal(0.,0.,0.), theFacetNormal(0.,0.,0.)
67{
68 if ( verboseLevel > 0)
69 {
70 G4cout << GetProcessName() << " is created " << G4endl;
71 }
72
73 isInitialised=false;
75
76 theStatus = UndefinedSurf;
77 material1 = nullptr;
78 material2 = nullptr;
79
81 theParticleMomentum = 0.;
82
83 flag_franchissement_surface = false;
84 flag_normal = false;
85 flag_reflexion = false;
86 teleportToDo = teleportDone = false;
87
88 ekint = thetat = thetaft = energyThreshold = crossingProbability = 0.0;
89}
90
91//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
92
94{}
95
96//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
97
98G4bool
100{
101 return ( aParticleType.GetPDGEncoding() == 11 );
102}
103
104//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
105
107{
108 if (isInitialised) { return; }
109
110 G4ProductionCutsTable* theCoupleTable =
112 G4int numOfCouples = theCoupleTable->GetTableSize();
113 G4cout << "G4MicroElecSurface::Initialise: Ncouples= "
114 << numOfCouples << G4endl;
115
116 for (G4int i = 0; i < numOfCouples; ++i) {
117 const G4Material* material =
118 theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial();
119
120 G4cout << "G4Surface, Material " << i + 1 << " / " << numOfCouples << " : " << material->GetName() << G4endl;
121 if (material->GetName() == "Vacuum") { tableWF[material->GetName()] = 0; continue; }
122 G4String mat = material->GetName();
124 tableWF[mat] = str.GetWorkFunction();
125 }
126 isInitialised = true;
127}
128
129//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
130
132{
133 theStatus = UndefinedSurf;
134
135 //Definition of the parameters for the particle
138
139 G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
140 G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
141
142 material1 = pPreStepPoint -> GetMaterial();
143 material2 = pPostStepPoint -> GetMaterial();
144
145 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
146
147 theParticleMomentum = aParticle->GetTotalMomentum();
148 previousMomentum = oldMomentum;
149 oldMomentum = aParticle->GetMomentumDirection();
150
151 //First case: not a boundary
152 if (pPostStepPoint->GetStepStatus() != fGeomBoundary ||
153 pPostStepPoint->GetPhysicalVolume() == pPreStepPoint->GetPhysicalVolume())
154 {
155 theStatus = NotAtBoundarySurf;
156 flag_franchissement_surface = false;
157 flag_reflexion = false;
158 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
159
160 }
161 theStatus = UndefinedSurf;
162
163 //Third case: same material
164 if (material1 == material2)
165 {
166 theStatus = SameMaterialSurf;
167 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
168
169 }
170 if (verboseLevel > 0)
171 {
172 G4cout << G4endl << " Electron at Boundary! " << G4endl;
173 G4VPhysicalVolume* thePrePV = pPreStepPoint->GetPhysicalVolume();
174 G4VPhysicalVolume* thePostPV = pPostStepPoint->GetPhysicalVolume();
175 if (thePrePV) G4cout << " thePrePV: " << thePrePV->GetName() << G4endl;
176 if (thePostPV) G4cout << " thePostPV: " << thePostPV->GetName() << G4endl;
177 G4cout << " Old Momentum Direction: " << oldMomentum << G4endl;
178 }
179
180 //Definition of the parameters for the surface
181 G4ThreeVector theGlobalPoint = pPostStepPoint->GetPosition();
182
183 G4Navigator* theNavigator =
185 GetNavigatorForTracking();
186
187 G4bool valid;
188
189 theGlobalNormal = theNavigator->GetGlobalExitNormal(theGlobalPoint, &valid);
190 // G4cout << "Global exit normal = " << theGlobalNormal << " valid = " << valid << G4endl;
191
192 if (valid)
193 {
194 theGlobalNormal = -theGlobalNormal;
195 }
196 else
197 {
199 ed << " G4MicroElecSurface/PostStepDoIt(): "
200 << " The Navigator reports that it returned an invalid normal.\n"
201 << "PV: " << pPreStepPoint->GetPhysicalVolume()->GetName()
202 << " TrackID= " << aTrack.GetTrackID()
203 << " Ekin(MeV)= " << aTrack.GetKineticEnergy()
204 << " position: " << theGlobalPoint
205 << " direction: " << oldMomentum
206 << G4endl;
207 G4Exception("G4MuElecSurf::PostStepDoIt", "OpBoun01",
208 FatalException, ed,
209 "Invalid Surface Normal - Geometry must return valid surface normal");
210 return 0;
211 }
212
213 //Exception: the particle is not in the right direction
214 if (oldMomentum * theGlobalNormal > 0.0)
215 {
216 theGlobalNormal = -theGlobalNormal;
217 }
218
219 //Second case: step too small
220 //Corrections bug rotation + réflexion
221 if (aTrack.GetStepLength()<=kCarTolerance)
222 {
223 theStatus = StepTooSmallSurf;
224 if (pPostStepPoint) {
225
226 WorkFunctionTable::iterator postStepWF;
227 postStepWF = tableWF.find(pPostStepPoint->GetMaterial()->GetName());
228 WorkFunctionTable::iterator preStepWF;
229 preStepWF = tableWF.find(pPreStepPoint->GetMaterial()->GetName());
230
231 if (postStepWF == tableWF.end()) {
232 G4String str = "Material ";
233 str += pPostStepPoint->GetMaterial()->GetName() + " not found!";
234 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
235 return 0;
236 }
237
238 else if (preStepWF == tableWF.end()) {
239 G4String str = "Material ";
240 str += pPreStepPoint->GetMaterial()->GetName() + " not found!";
241 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
242 return 0;
243 }
244
245 if (pPreStepPoint->GetMaterial() != pPostStepPoint->GetMaterial()) {
246
247 flag_franchissement_surface = false;
248
249 if (flag_reflexion == true && flag_normal == true) {
251 flag_reflexion = false;
252 flag_normal = false;
253 }
254 }
255 }
256 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
257 }
258
259 flag_normal = (theGlobalNormal.x() == 0.0 && theGlobalNormal.y() == 0.0);
260
261 G4LogicalSurface* Surface = nullptr;
262
264 (pPreStepPoint ->GetPhysicalVolume(),
265 pPostStepPoint->GetPhysicalVolume());
266
267 if (Surface == nullptr)
268 {
269 G4bool enteredDaughter=(pPostStepPoint->GetPhysicalVolume()
270 ->GetMotherLogical() ==
271 pPreStepPoint->GetPhysicalVolume()
272 ->GetLogicalVolume());
273 if(enteredDaughter)
274 {
276 (pPostStepPoint->GetPhysicalVolume()->
277 GetLogicalVolume());
278
279 if(Surface == nullptr)
281 (pPreStepPoint->GetPhysicalVolume()->
282 GetLogicalVolume());
283 }
284 else
285 {
287 (pPreStepPoint->GetPhysicalVolume()->
288 GetLogicalVolume());
289
290 if(Surface == nullptr)
292 (pPostStepPoint->GetPhysicalVolume()->
293 GetLogicalVolume());
294 }
295 }
296
297
298 G4VPhysicalVolume* thePrePV = pPreStepPoint->GetPhysicalVolume();
299 G4VPhysicalVolume* thePostPV = pPostStepPoint->GetPhysicalVolume();
300
301 if (thePostPV)
302 {
303 WorkFunctionTable::iterator postStepWF;
304 postStepWF = tableWF.find(thePostPV->GetLogicalVolume()->GetMaterial()->GetName());
305 WorkFunctionTable::iterator preStepWF;
306 preStepWF = tableWF.find(thePrePV->GetLogicalVolume()->GetMaterial()->GetName());
307
308 if (postStepWF == tableWF.end()) {
309 G4String str = "Material ";
310 str += thePostPV->GetLogicalVolume()->GetMaterial()->GetName() + " not found!";
311 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
312 return 0;
313 }
314
315 else if (preStepWF == tableWF.end()) {
316 G4String str = "Material ";
317 str += thePrePV->GetLogicalVolume()->GetMaterial()->GetName() + " not found!";
318 G4Exception("G4Surface::G4Surface", "em0002", FatalException, str);
319 return 0;
320 }
321
322 else
323 {
324 G4double thresholdNew = postStepWF->second;
325 G4double thresholdOld = preStepWF->second;
326 energyThreshold = thresholdNew - thresholdOld;
327 }
328 }
329
330 ekint = pPreStepPoint->GetKineticEnergy();
331 thetat= GetIncidentAngle(); //angle d'incidence
332 G4double ekinNormalt=ekint*std::cos(thetat)*std::cos(thetat);
333
334 G4double atet = std::sqrt(ekint/(ekint+energyThreshold))*std::sin(thetat);
335 thetaft = (atet > 1.0) ? pi*0.5 : std::asin(atet);//Angle de réfraction
336
337 G4double aleat=G4UniformRand();
338
339 const G4double waveVectort=std::sqrt(2*9.1093826E-31*1.602176487E-19)/(6.6260755E-34/(2.0*pi));
340
341 //Parameter for an exponential barrier of potential (Thèse P68)
342 const G4double at=0.5E-10;
343
344 //G4double modif already declared in .hh
345 crossingProbability=0;
346
347 G4double kft=waveVectort*std::sqrt(ekint+energyThreshold)*std::cos(thetaft);
348 G4double kit=waveVectort*std::sqrt(ekinNormalt);
349
350 G4double yy = std::sinh(pi*at*(kit-kft))/std::sinh(pi*at*(kit+kft));
351 crossingProbability = 1 - yy*yy;
352
353 //First case: the electron crosses the surface
354 if((aleat<=crossingProbability)&&(ekint>std::abs(energyThreshold)))
355 {
356 if (pPreStepPoint->GetMaterial() != pPostStepPoint->GetMaterial()) {
357 flag_franchissement_surface = true;
358 }
359
360 thetaft=std::abs(thetaft-thetat);
361
363 G4ThreeVector xVerst = zVerst.orthogonal();
364 G4ThreeVector yVerst = zVerst.cross(xVerst);
365
366 G4double cost = std::cos(thetaft);
367 G4double xDirt = std::sqrt(1. - cost*cost);
368 G4double yDirt = xDirt;
369
370 G4ThreeVector zPrimeVerst = xDirt*xVerst + yDirt*yVerst + cost*zVerst;
371
373 }
374 else if ((aleat > crossingProbability) && (ekint>std::abs(energyThreshold)))
375 {
376 flag_reflexion = true;
377 if (flag_normal) { aParticleChange.ProposeMomentumDirection(-oldMomentum.unit()); }
378 else { aParticleChange.ProposeMomentumDirection(Reflexion(aStep.GetPostStepPoint())); }
379
380 }
381 else {
382
383 if (flag_normal) { aParticleChange.ProposeMomentumDirection(-oldMomentum.unit()); }
384 else { aParticleChange.ProposeMomentumDirection(Reflexion(aStep.GetPostStepPoint())); }
385 flag_reflexion = true;
386 }
387
388 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
389}
390
391//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
392
395{
396 *condition = Forced;
397 return DBL_MAX;
398}
399
400//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
401
402G4double G4MicroElecSurface::GetIncidentAngle()
403{
404 theFacetNormal=theGlobalNormal;
405
406 G4double PdotN = oldMomentum * theFacetNormal;
407 G4double magP= oldMomentum.mag();
408 G4double magN= theFacetNormal.mag();
409
410 G4double incidentangle = pi - std::acos(PdotN/(magP*magN));
411
412 return incidentangle;
413}
414
415//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
416
417G4ThreeVector G4MicroElecSurface::Reflexion(const G4StepPoint* PostStepPoint)
418{
419 //Normale
420 G4double Nx = theGlobalNormal.x();
421 G4double Ny = theGlobalNormal.y();
422 G4double Nz = theGlobalNormal.z();
423
424 //PostStepPoint
425 G4double PSx = PostStepPoint->GetPosition().x();
426 G4double PSy = PostStepPoint->GetPosition().y();
427 G4double PSz = PostStepPoint->GetPosition().z();
428
429 //P(alpha,beta,gamma) - PostStep avec translation momentum
430 G4double alpha = PSx + oldMomentum.x();
431 G4double beta = PSy + oldMomentum.y();
432 G4double gamma = PSz + oldMomentum.z();
433 G4double r = theGlobalNormal.mag();
434 G4double x, y, z, d, A, B, PM2x, PM2y, PM2z;
435 d = -(Nx*PSx + Ny*PSy + Nz*PSz);
436
437 if (Ny == 0 && Nx == 0) {
438 gamma = -gamma;
439 }
440
441 else {
442 if (Ny == 0) {
443
444 A = (Nz*Nz*alpha) + (Nx*Nx*PSx) + (Nx*Nz*(PSz - gamma));
445 B = r*r;
446
447 //M(x,y,z) - Projection de P sur la surface
448 x = A / B;
449 y = beta;
450 z = (x - alpha)*(Nz / Nx) + gamma;
451 }
452
453 else {
454
455 A = (r*r) / Ny;
456 B = (beta / Ny)*(Nx*Nx + Nz*Nz) - (Nx*alpha + Nz*gamma + d);
457
458 //M(x,y,z) - Projection de P sur la surface
459 y = B / A;
460 x = (y - beta)*(Nx / Ny) + alpha;
461 z = (y - beta)*(Nz / Ny) + gamma;
462 }
463
464 //Vecteur 2*PM
465 PM2x = 2 * (x - alpha); PM2y = 2 * (y - beta); PM2z = 2 * (z - gamma);
466
467 //Nouveau point P
468 alpha += PM2x; beta += PM2y; gamma += PM2z;
469
470 }
471
472 G4ThreeVector newMomentum = G4ThreeVector(alpha-PSx,beta-PSy,gamma-PSz);
473
474 return newMomentum.unit();
475}
476
477//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
478
480{
481 return theStatus;
482}
483
484//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
485
486
488{
489 flag_franchissement_surface = false;
490}
491
492//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
493
double B(double temperature)
double A(double temperature)
G4double condition(const G4ErrorSymMatrix &m)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
G4ForceCondition
@ Forced
G4MicroElecSurfaceStatus
@ StepTooSmallSurf
@ SameMaterialSurf
@ UndefinedSurf
@ NotAtBoundarySurf
G4ProcessType
@ fGeomBoundary
Definition: G4StepStatus.hh:43
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
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
Definition: G4Material.hh:175
G4MicroElecSurfaceStatus GetStatus() const
G4double GetMeanFreePath(const G4Track &, G4double, G4ForceCondition *condition) override
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep) override
~G4MicroElecSurface() 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 ProposeVelocity(G4double finalVelocity)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
virtual void Initialize(const G4Track &)
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
Definition: G4Step.hh:62
G4StepPoint * GetPreStepPoint() const
G4StepPoint * GetPostStepPoint() const
G4double GetVelocity() const
G4int GetTrackID() const
const G4DynamicParticle * GetDynamicParticle() const
G4double GetKineticEnergy() const
G4double GetStepLength() const
static G4TransportationManager * GetTransportationManager()
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
G4LogicalVolume * GetMotherLogical() const
G4LogicalVolume * GetLogicalVolume() const
const G4String & GetName() const
G4ParticleChange aParticleChange
Definition: G4VProcess.hh:327
G4int verboseLevel
Definition: G4VProcess.hh:356
void SetProcessSubType(G4int)
Definition: G4VProcess.hh:406
const G4String & GetProcessName() const
Definition: G4VProcess.hh:382
#define DBL_MAX
Definition: templates.hh:62