Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/lowenergy/src/G4MicroElecSurface.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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"
 51 #include "G4PhysicalConstants.hh"
 52 #include "G4EmProcessSubType.hh"
 53 #include "G4GeometryTolerance.hh"
 54 #include "G4SystemOfUnits.hh"
 55 
 56 
 57 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 58 
 59 G4MicroElecSurface::G4MicroElecSurface(const G4String& processName,G4ProcessType type)
 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;
 70   SetProcessSubType(fSurfaceReflection);
 71   
 72   theStatus = UndefinedSurf;
 73   material1 = nullptr;
 74   material2 = nullptr;
 75   
 76   kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); 
 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 
 89 G4MicroElecSurface::~G4MicroElecSurface()
 90 {}
 91 
 92 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 93 
 94 G4bool 
 95 G4MicroElecSurface::IsApplicable(const G4ParticleDefinition& aParticleType) 
 96 { 
 97   return ( aParticleType.GetPDGEncoding() == 11 ); 
 98 } 
 99 
100 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
101 
102 void G4MicroElecSurface::Initialise()
103 {
104   if (isInitialised) { return; }
105 
106   G4ProductionCutsTable* theCoupleTable =
107     G4ProductionCutsTable::GetProductionCutsTable();
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();
123     G4MicroElecMaterialStructure str = G4MicroElecMaterialStructure(mat);
124     tableWF[mat] = str.GetWorkFunction();
125   }
126 
127   isInitialised = true;
128 }
129 
130 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
131 
132 void G4MicroElecSurface::BuildPhysicsTable(const G4ParticleDefinition&)
133 {
134   if (isInitialised) { return; }
135   
136   G4ProductionCutsTable* theCoupleTable =
137     G4ProductionCutsTable::GetProductionCutsTable();
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();
155     G4MicroElecMaterialStructure str = G4MicroElecMaterialStructure(mat);
156     tableWF[mat] = str.GetWorkFunction();
157   }
158   isInitialised = true;
159 }
160 
161 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
162 
163 G4VParticleChange* G4MicroElecSurface::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep)
164 {
165   
166   if (!isInitialised) { Initialise(); }
167   theStatus = UndefinedSurf;
168   
169   // Definition of the parameters for the particle
170   aParticleChange.Initialize(aTrack);
171   aParticleChange.ProposeVelocity(aTrack.GetVelocity());
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 
218   G4Navigator* theNavigator = G4TransportationManager::
219     GetTransportationManager()->GetNavigatorForTracking();
220 
221   G4bool valid;
222   theGlobalNormal = theNavigator->GetGlobalExitNormal(theGlobalPoint, &valid);
223 
224   if (valid)
225   {
226     theGlobalNormal = -theGlobalNormal;
227   }
228   else
229   {
230     G4ExceptionDescription ed;
231     ed << " G4MicroElecSurface/PostStepDoIt(): "
232        << " The Navigator reports that it returned an invalid normal"
233        << G4endl;
234     G4Exception("G4MuElecSurf::PostStepDoIt", "OpBoun01",
235                 EventMustBeAborted, ed,
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     {
290       aParticleChange.ProposeMomentumDirection(-Reflexion(aStep.GetPostStepPoint()));
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   
302   Surface = G4LogicalBorderSurface::GetSurface
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     {
312       Surface = G4LogicalSkinSurface::GetSurface
313                 (pPostStepPoint->GetPhysicalVolume()->GetLogicalVolume());
314 
315       if(Surface == nullptr)
316       Surface = G4LogicalSkinSurface::GetSurface
317                 (pPreStepPoint->GetPhysicalVolume()->GetLogicalVolume());
318     }
319     else 
320     {
321       Surface = G4LogicalSkinSurface::GetSurface
322                 (pPreStepPoint->GetPhysicalVolume()->GetLogicalVolume());
323 
324       if(Surface == nullptr)
325       Surface = G4LogicalSkinSurface::GetSurface
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 
404     G4ThreeVector zVerst = aStep.GetPostStepPoint()->GetMomentumDirection();
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     
413     aParticleChange.ProposeMomentumDirection(zPrimeVerst.unit());
414   }
415   else if ((aleat > crossingProbability) && (ekint> energyDelta))
416   {
417     flag_reflexion = true;
418     if (flag_normal)
419     {
420       aParticleChange.ProposeMomentumDirection(-oldMomentum.unit());
421     }
422     else
423     {
424       aParticleChange.ProposeMomentumDirection(Reflexion(aStep.GetPostStepPoint()));
425     }
426   }
427   else
428   {
429     if (flag_normal)
430     {
431       aParticleChange.ProposeMomentumDirection(-oldMomentum.unit());
432     }
433     else
434     {
435       aParticleChange.ProposeMomentumDirection(Reflexion(aStep.GetPostStepPoint()));
436     }
437     flag_reflexion = true;
438   }
439   return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
440 }
441 
442 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
443 
444 G4double G4MicroElecSurface::GetMeanFreePath(const G4Track&, G4double,
445                                              G4ForceCondition* condition)
446 { 
447   *condition = Forced;
448   return  DBL_MAX;   
449 }
450 
451 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
452 
453 G4double 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 
468 G4ThreeVector 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 
529 G4MicroElecSurfaceStatus G4MicroElecSurface::GetStatus() const 
530 { 
531   return theStatus; 
532 } 
533 
534 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
535 
536   
537 void G4MicroElecSurface::SetFlagFranchissement() 
538 { 
539   flag_franchissement_surface = false; 
540 } 
541  
542 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
543 
544