source: trunk/source/processes/optical/src/G4OpBoundaryProcess.cc @ 1340

Last change on this file since 1340 was 1340, checked in by garnier, 14 years ago

update ti head

File size: 39.4 KB
Line 
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// Optical Photon Boundary Process Class Implementation
28////////////////////////////////////////////////////////////////////////
29//
30// File:        G4OpBoundaryProcess.cc
31// Description: Discrete Process -- reflection/refraction at
32//                                  optical interfaces
33// Version:     1.1
34// Created:     1997-06-18
35// Modified:    1998-05-25 - Correct parallel component of polarization
36//                           (thanks to: Stefano Magni + Giovanni Pieri)
37//              1998-05-28 - NULL Rindex pointer before reuse
38//                           (thanks to: Stefano Magni)
39//              1998-06-11 - delete *sint1 in oblique reflection
40//                           (thanks to: Giovanni Pieri)
41//              1998-06-19 - move from GetLocalExitNormal() to the new
42//                           method: GetLocalExitNormal(&valid) to get
43//                           the surface normal in all cases
44//              1998-11-07 - NULL OpticalSurface pointer before use
45//                           comparison not sharp for: std::abs(cost1) < 1.0
46//                           remove sin1, sin2 in lines 556,567
47//                           (thanks to Stefano Magni)
48//              1999-10-10 - Accommodate changes done in DoAbsorption by
49//                           changing logic in DielectricMetal
50//              2001-10-18 - avoid Linux (gcc-2.95.2) warning about variables
51//                           might be used uninitialized in this function
52//                           moved E2_perp, E2_parl and E2_total out of 'if'
53//              2003-11-27 - Modified line 168-9 to reflect changes made to
54//                           G4OpticalSurface class ( by Fan Lei)
55//              2004-02-02 - Set theStatus = Undefined at start of DoIt
56//              2005-07-28 - add G4ProcessType to constructor
57//              2006-11-04 - add capability of calculating the reflectivity
58//                           off a metal surface by way of a complex index
59//                           of refraction - Thanks to Sehwook Lee and John
60//                           Hauptman (Dept. of Physics - Iowa State Univ.)
61//              2009-11-10 - add capability of simulating surface reflections
62//                           with Look-Up-Tables (LUT) containing measured
63//                           optical reflectance for a variety of surface
64//                           treatments - Thanks to Martin Janecek and
65//                           William Moses (Lawrence Berkeley National Lab.)
66//
67// Author:      Peter Gumplinger
68//              adopted from work by Werner Keil - April 2/96
69// mail:        gum@triumf.ca
70//
71////////////////////////////////////////////////////////////////////////
72
73#include "G4ios.hh"
74#include "G4OpProcessSubType.hh"
75
76#include "G4OpBoundaryProcess.hh"
77#include "G4GeometryTolerance.hh"
78
79/////////////////////////
80// Class Implementation
81/////////////////////////
82
83        //////////////
84        // Operators
85        //////////////
86
87// G4OpBoundaryProcess::operator=(const G4OpBoundaryProcess &right)
88// {
89// }
90
91        /////////////////
92        // Constructors
93        /////////////////
94
95G4OpBoundaryProcess::G4OpBoundaryProcess(const G4String& processName,
96                                               G4ProcessType type)
97             : G4VDiscreteProcess(processName, type)
98{
99        if ( verboseLevel > 0) {
100           G4cout << GetProcessName() << " is created " << G4endl;
101        }
102
103        SetProcessSubType(fOpBoundary);
104
105        theStatus = Undefined;
106        theModel = glisur;
107        theFinish = polished;
108        theReflectivity = 1.;
109        theEfficiency   = 0.;
110
111        prob_sl = 0.;
112        prob_ss = 0.;
113        prob_bs = 0.;
114
115        PropertyPointer  = NULL;
116        PropertyPointer1 = NULL;
117        PropertyPointer2 = NULL;
118
119        kCarTolerance = G4GeometryTolerance::GetInstance()
120                        ->GetSurfaceTolerance();
121
122        iTE = iTM = 0;
123        thePhotonMomentum = 0.;
124        Rindex1 = Rindex2 = cost1 = cost2 = sint1 = sint2 = 0.;
125}
126
127// G4OpBoundaryProcess::G4OpBoundaryProcess(const G4OpBoundaryProcess &right)
128// {
129// }
130
131        ////////////////
132        // Destructors
133        ////////////////
134
135G4OpBoundaryProcess::~G4OpBoundaryProcess(){}
136
137        ////////////
138        // Methods
139        ////////////
140
141// PostStepDoIt
142// ------------
143//
144G4VParticleChange*
145G4OpBoundaryProcess::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep)
146{
147        theStatus = Undefined;
148
149        aParticleChange.Initialize(aTrack);
150
151        G4StepPoint* pPreStepPoint  = aStep.GetPreStepPoint();
152        G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
153
154        if ( verboseLevel > 0 ) {
155           G4cout << " Photon at Boundary! " << G4endl;
156           G4VPhysicalVolume* thePrePV = pPreStepPoint->GetPhysicalVolume();
157           G4VPhysicalVolume* thePostPV = pPostStepPoint->GetPhysicalVolume();
158           if (thePrePV)  G4cout << " thePrePV:  " << thePrePV->GetName()  << G4endl;
159           if (thePostPV) G4cout << " thePostPV: " << thePostPV->GetName() << G4endl;
160        }
161
162        if (pPostStepPoint->GetStepStatus() != fGeomBoundary){
163                theStatus = NotAtBoundary;
164                if ( verboseLevel > 0) BoundaryProcessVerbose();
165                return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
166        }
167        if (aTrack.GetStepLength()<=kCarTolerance/2){
168                theStatus = StepTooSmall;
169                if ( verboseLevel > 0) BoundaryProcessVerbose();
170                return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
171        }
172
173        Material1 = pPreStepPoint  -> GetMaterial();
174        Material2 = pPostStepPoint -> GetMaterial();
175
176        const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
177
178        thePhotonMomentum = aParticle->GetTotalMomentum();
179        OldMomentum       = aParticle->GetMomentumDirection();
180        OldPolarization   = aParticle->GetPolarization();
181
182        if ( verboseLevel > 0 ) {
183           G4cout << " Old Momentum Direction: " << OldMomentum     << G4endl;
184           G4cout << " Old Polarization:       " << OldPolarization << G4endl;
185        }
186
187        G4ThreeVector theGlobalPoint = pPostStepPoint->GetPosition();
188
189        G4Navigator* theNavigator =
190                     G4TransportationManager::GetTransportationManager()->
191                                              GetNavigatorForTracking();
192
193        G4ThreeVector theLocalPoint = theNavigator->
194                                      GetGlobalToLocalTransform().
195                                      TransformPoint(theGlobalPoint);
196
197        G4ThreeVector theLocalNormal;   // Normal points back into volume
198
199        G4bool valid;
200        theLocalNormal = theNavigator->GetLocalExitNormal(&valid);
201
202        if (valid) {
203          theLocalNormal = -theLocalNormal;
204        }
205        else {
206          G4cerr << " G4OpBoundaryProcess/PostStepDoIt(): "
207                 << " The Navigator reports that it returned an invalid normal"
208                 << G4endl;
209          G4Exception("G4OpBoundaryProcess::PostStepDoIt",
210                      "Invalid Surface Normal",
211                      EventMustBeAborted,
212                      "Geometry must return valid surface normal");
213        }
214
215        theGlobalNormal = theNavigator->GetLocalToGlobalTransform().
216                                        TransformAxis(theLocalNormal);
217
218        if (OldMomentum * theGlobalNormal > 0.0) {
219#ifdef G4DEBUG_OPTICAL
220           G4cerr << " G4OpBoundaryProcess/PostStepDoIt(): "
221                  << " theGlobalNormal points the wrong direction "
222                  << G4endl;
223#endif
224           theGlobalNormal = -theGlobalNormal;
225        }
226
227        G4MaterialPropertiesTable* aMaterialPropertiesTable;
228        G4MaterialPropertyVector* Rindex;
229
230        aMaterialPropertiesTable = Material1->GetMaterialPropertiesTable();
231        if (aMaterialPropertiesTable) {
232                Rindex = aMaterialPropertiesTable->GetProperty("RINDEX");
233        }
234        else {
235                theStatus = NoRINDEX;
236                if ( verboseLevel > 0) BoundaryProcessVerbose();
237                aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
238                aParticleChange.ProposeTrackStatus(fStopAndKill);
239                return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
240        }
241
242        if (Rindex) {
243                Rindex1 = Rindex->GetProperty(thePhotonMomentum);
244        }
245        else {
246                theStatus = NoRINDEX;
247                if ( verboseLevel > 0) BoundaryProcessVerbose();
248                aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
249                aParticleChange.ProposeTrackStatus(fStopAndKill);
250                return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
251        }
252
253        theReflectivity = 1.;
254        theEfficiency   = 0.;
255
256        theModel = glisur;
257        theFinish = polished;
258
259        G4SurfaceType type = dielectric_dielectric;
260
261        Rindex = NULL;
262        OpticalSurface = NULL;
263
264        G4LogicalSurface* Surface = NULL;
265
266        Surface = G4LogicalBorderSurface::GetSurface
267                  (pPreStepPoint ->GetPhysicalVolume(),
268                   pPostStepPoint->GetPhysicalVolume());
269
270        if (Surface == NULL){
271          G4bool enteredDaughter=(pPostStepPoint->GetPhysicalVolume()
272                                  ->GetMotherLogical() ==
273                                  pPreStepPoint->GetPhysicalVolume()
274                                  ->GetLogicalVolume());
275          if(enteredDaughter){
276            Surface = G4LogicalSkinSurface::GetSurface
277              (pPostStepPoint->GetPhysicalVolume()->
278               GetLogicalVolume());
279            if(Surface == NULL)
280              Surface = G4LogicalSkinSurface::GetSurface
281              (pPreStepPoint->GetPhysicalVolume()->
282               GetLogicalVolume());
283          }
284          else {
285            Surface = G4LogicalSkinSurface::GetSurface
286              (pPreStepPoint->GetPhysicalVolume()->
287               GetLogicalVolume());
288            if(Surface == NULL)
289              Surface = G4LogicalSkinSurface::GetSurface
290              (pPostStepPoint->GetPhysicalVolume()->
291               GetLogicalVolume());
292          }
293        }
294
295        if (Surface) OpticalSurface = 
296           dynamic_cast <G4OpticalSurface*> (Surface->GetSurfaceProperty());
297
298        if (OpticalSurface) {
299
300           type      = OpticalSurface->GetType();
301           theModel  = OpticalSurface->GetModel();
302           theFinish = OpticalSurface->GetFinish();
303
304           aMaterialPropertiesTable = OpticalSurface->
305                                        GetMaterialPropertiesTable();
306
307           if (aMaterialPropertiesTable) {
308
309              if (theFinish == polishedbackpainted ||
310                  theFinish == groundbackpainted ) {
311                  Rindex = aMaterialPropertiesTable->GetProperty("RINDEX");
312                  if (Rindex) {
313                     Rindex2 = Rindex->GetProperty(thePhotonMomentum);
314                  }
315                  else {
316                     theStatus = NoRINDEX;
317                     if ( verboseLevel > 0) BoundaryProcessVerbose();
318                     aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
319                     aParticleChange.ProposeTrackStatus(fStopAndKill);
320                     return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
321                  }
322              }
323
324              PropertyPointer =
325                      aMaterialPropertiesTable->GetProperty("REFLECTIVITY");
326              PropertyPointer1 =
327                      aMaterialPropertiesTable->GetProperty("REALRINDEX");
328              PropertyPointer2 =
329                      aMaterialPropertiesTable->GetProperty("IMAGINARYRINDEX");
330
331              iTE = 1;
332              iTM = 1;
333
334              if (PropertyPointer) {
335
336                 theReflectivity =
337                          PropertyPointer->GetProperty(thePhotonMomentum);
338
339              } else if (PropertyPointer1 && PropertyPointer2) {
340
341                 CalculateReflectivity();
342
343              }
344
345              PropertyPointer =
346              aMaterialPropertiesTable->GetProperty("EFFICIENCY");
347              if (PropertyPointer) {
348                      theEfficiency =
349                      PropertyPointer->GetProperty(thePhotonMomentum);
350              }
351
352              if ( theModel == unified ) {
353                PropertyPointer =
354                aMaterialPropertiesTable->GetProperty("SPECULARLOBECONSTANT");
355                if (PropertyPointer) {
356                         prob_sl =
357                         PropertyPointer->GetProperty(thePhotonMomentum);
358                } else {
359                         prob_sl = 0.0;
360                }
361
362                PropertyPointer =
363                aMaterialPropertiesTable->GetProperty("SPECULARSPIKECONSTANT");
364                if (PropertyPointer) {
365                         prob_ss =
366                         PropertyPointer->GetProperty(thePhotonMomentum);
367                } else {
368                         prob_ss = 0.0;
369                }
370
371                PropertyPointer =
372                aMaterialPropertiesTable->GetProperty("BACKSCATTERCONSTANT");
373                if (PropertyPointer) {
374                         prob_bs =
375                         PropertyPointer->GetProperty(thePhotonMomentum);
376                } else {
377                         prob_bs = 0.0;
378                }
379              }
380           }
381           else if (theFinish == polishedbackpainted ||
382                    theFinish == groundbackpainted ) {
383                      aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
384                      aParticleChange.ProposeTrackStatus(fStopAndKill);
385                      return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
386           }
387        }
388
389        if (type == dielectric_dielectric ) {
390           if (theFinish == polished || theFinish == ground ) {
391
392              if (Material1 == Material2){
393                 theStatus = SameMaterial;
394                 if ( verboseLevel > 0) BoundaryProcessVerbose();
395                 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
396              }
397              aMaterialPropertiesTable =
398                     Material2->GetMaterialPropertiesTable();
399              if (aMaterialPropertiesTable)
400                 Rindex = aMaterialPropertiesTable->GetProperty("RINDEX");
401              if (Rindex) {
402                 Rindex2 = Rindex->GetProperty(thePhotonMomentum);
403              }
404              else {
405                 theStatus = NoRINDEX;
406                 if ( verboseLevel > 0) BoundaryProcessVerbose();
407                 aParticleChange.ProposeLocalEnergyDeposit(thePhotonMomentum);
408                 aParticleChange.ProposeTrackStatus(fStopAndKill);
409                 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
410              }
411           }
412        }
413
414        if (type == dielectric_metal) {
415
416          DielectricMetal();
417
418          // Uncomment the following lines if you wish to have
419          //         Transmission instead of Absorption
420          // if (theStatus == Absorption) {
421          //    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
422          // }
423
424        }
425        else if (type == dielectric_LUT) {
426
427          DielectricLUT();
428
429        }
430        else if (type == dielectric_dielectric) {
431
432          if ( theFinish == polishedbackpainted ||
433               theFinish == groundbackpainted ) {
434             DielectricDielectric();
435          }
436          else {
437             if ( !G4BooleanRand(theReflectivity) ) {
438                DoAbsorption();
439             }
440             else {
441                if ( theFinish == polishedfrontpainted ) {
442                   DoReflection();
443                }
444                else if ( theFinish == groundfrontpainted ) {
445                   theStatus = LambertianReflection;
446                   DoReflection();
447                }
448                else {
449                   DielectricDielectric();
450                }
451             }
452          }
453        }
454        else {
455
456          G4cerr << " Error: G4BoundaryProcess: illegal boundary type " << G4endl;
457          return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
458
459        }
460
461        NewMomentum = NewMomentum.unit();
462        NewPolarization = NewPolarization.unit();
463
464        if ( verboseLevel > 0) {
465           G4cout << " New Momentum Direction: " << NewMomentum     << G4endl;
466           G4cout << " New Polarization:       " << NewPolarization << G4endl;
467           BoundaryProcessVerbose();
468        }
469
470        aParticleChange.ProposeMomentumDirection(NewMomentum);
471        aParticleChange.ProposePolarization(NewPolarization);
472
473        return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
474}
475
476void G4OpBoundaryProcess::BoundaryProcessVerbose() const
477{
478        if ( theStatus == Undefined )
479                G4cout << " *** Undefined *** " << G4endl;
480        if ( theStatus == FresnelRefraction )
481                G4cout << " *** FresnelRefraction *** " << G4endl;
482        if ( theStatus == FresnelReflection )
483                G4cout << " *** FresnelReflection *** " << G4endl;
484        if ( theStatus == TotalInternalReflection )
485                G4cout << " *** TotalInternalReflection *** " << G4endl;
486        if ( theStatus == LambertianReflection )
487                G4cout << " *** LambertianReflection *** " << G4endl;
488        if ( theStatus == LobeReflection )
489                G4cout << " *** LobeReflection *** " << G4endl;
490        if ( theStatus == SpikeReflection )
491                G4cout << " *** SpikeReflection *** " << G4endl;
492        if ( theStatus == BackScattering )
493                G4cout << " *** BackScattering *** " << G4endl;
494        if ( theStatus == PolishedLumirrorAirReflection )
495                G4cout << " *** PolishedLumirrorAirReflection *** " << G4endl;
496        if ( theStatus == PolishedLumirrorGlueReflection )
497                G4cout << " *** PolishedLumirrorGlueReflection *** " << G4endl;
498        if ( theStatus == PolishedAirReflection )
499                G4cout << " *** PolishedAirReflection *** " << G4endl;
500        if ( theStatus == PolishedTeflonAirReflection )
501                G4cout << " *** PolishedTeflonAirReflection *** " << G4endl;
502        if ( theStatus == PolishedTiOAirReflection )
503                G4cout << " *** PolishedTiOAirReflection *** " << G4endl;
504        if ( theStatus == PolishedTyvekAirReflection )
505                G4cout << " *** PolishedTyvekAirReflection *** " << G4endl;
506        if ( theStatus == PolishedVM2000AirReflection )
507                G4cout << " *** PolishedVM2000AirReflection *** " << G4endl;
508        if ( theStatus == PolishedVM2000GlueReflection )
509                G4cout << " *** PolishedVM2000GlueReflection *** " << G4endl;
510        if ( theStatus == EtchedLumirrorAirReflection )
511                G4cout << " *** EtchedLumirrorAirReflection *** " << G4endl;
512        if ( theStatus == EtchedLumirrorGlueReflection )
513                G4cout << " *** EtchedLumirrorGlueReflection *** " << G4endl;
514        if ( theStatus == EtchedAirReflection )
515                G4cout << " *** EtchedAirReflection *** " << G4endl;
516        if ( theStatus == EtchedTeflonAirReflection )
517                G4cout << " *** EtchedTeflonAirReflection *** " << G4endl;
518        if ( theStatus == EtchedTiOAirReflection )
519                G4cout << " *** EtchedTiOAirReflection *** " << G4endl;
520        if ( theStatus == EtchedTyvekAirReflection )
521                G4cout << " *** EtchedTyvekAirReflection *** " << G4endl;
522        if ( theStatus == EtchedVM2000AirReflection )
523                G4cout << " *** EtchedVM2000AirReflection *** " << G4endl;
524        if ( theStatus == EtchedVM2000GlueReflection )
525                G4cout << " *** EtchedVM2000GlueReflection *** " << G4endl;
526        if ( theStatus == GroundLumirrorAirReflection )
527                G4cout << " *** GroundLumirrorAirReflection *** " << G4endl;
528        if ( theStatus == GroundLumirrorGlueReflection )
529                G4cout << " *** GroundLumirrorGlueReflection *** " << G4endl;
530        if ( theStatus == GroundAirReflection )
531                G4cout << " *** GroundAirReflection *** " << G4endl;
532        if ( theStatus == GroundTeflonAirReflection )
533                G4cout << " *** GroundTeflonAirReflection *** " << G4endl;
534        if ( theStatus == GroundTiOAirReflection )
535                G4cout << " *** GroundTiOAirReflection *** " << G4endl;
536        if ( theStatus == GroundTyvekAirReflection )
537                G4cout << " *** GroundTyvekAirReflection *** " << G4endl;
538        if ( theStatus == GroundVM2000AirReflection )
539                G4cout << " *** GroundVM2000AirReflection *** " << G4endl;
540        if ( theStatus == GroundVM2000GlueReflection )
541                G4cout << " *** GroundVM2000GlueReflection *** " << G4endl;
542        if ( theStatus == Absorption )
543                G4cout << " *** Absorption *** " << G4endl;
544        if ( theStatus == Detection )
545                G4cout << " *** Detection *** " << G4endl;
546        if ( theStatus == NotAtBoundary )
547                G4cout << " *** NotAtBoundary *** " << G4endl;
548        if ( theStatus == SameMaterial )
549                G4cout << " *** SameMaterial *** " << G4endl;
550        if ( theStatus == StepTooSmall )
551                G4cout << " *** StepTooSmall *** " << G4endl;
552        if ( theStatus == NoRINDEX )
553                G4cout << " *** NoRINDEX *** " << G4endl;
554}
555
556G4ThreeVector
557G4OpBoundaryProcess::GetFacetNormal(const G4ThreeVector& Momentum,
558                                    const G4ThreeVector&  Normal ) const
559{
560        G4ThreeVector FacetNormal;
561
562        if (theModel == unified || theModel == LUT) {
563
564        /* This function code alpha to a random value taken from the
565           distribution p(alpha) = g(alpha; 0, sigma_alpha)*std::sin(alpha),
566           for alpha > 0 and alpha < 90, where g(alpha; 0, sigma_alpha)
567           is a gaussian distribution with mean 0 and standard deviation
568           sigma_alpha.  */
569
570           G4double alpha;
571
572           G4double sigma_alpha = 0.0;
573           if (OpticalSurface) sigma_alpha = OpticalSurface->GetSigmaAlpha();
574
575           G4double f_max = std::min(1.0,4.*sigma_alpha);
576
577           do {
578              do {
579                 alpha = G4RandGauss::shoot(0.0,sigma_alpha);
580              } while (G4UniformRand()*f_max > std::sin(alpha) || alpha >= halfpi );
581
582              G4double phi = G4UniformRand()*twopi;
583
584              G4double SinAlpha = std::sin(alpha);
585              G4double CosAlpha = std::cos(alpha);
586              G4double SinPhi = std::sin(phi);
587              G4double CosPhi = std::cos(phi);
588
589              G4double unit_x = SinAlpha * CosPhi;
590              G4double unit_y = SinAlpha * SinPhi;
591              G4double unit_z = CosAlpha;
592
593              FacetNormal.setX(unit_x);
594              FacetNormal.setY(unit_y);
595              FacetNormal.setZ(unit_z);
596
597              G4ThreeVector tmpNormal = Normal;
598
599              FacetNormal.rotateUz(tmpNormal);
600           } while (Momentum * FacetNormal >= 0.0);
601        }
602        else {
603
604           G4double  polish = 1.0;
605           if (OpticalSurface) polish = OpticalSurface->GetPolish();
606
607           if (polish < 1.0) {
608              do {
609                 G4ThreeVector smear;
610                 do {
611                    smear.setX(2.*G4UniformRand()-1.0);
612                    smear.setY(2.*G4UniformRand()-1.0);
613                    smear.setZ(2.*G4UniformRand()-1.0);
614                 } while (smear.mag()>1.0);
615                 smear = (1.-polish) * smear;
616                 FacetNormal = Normal + smear;
617              } while (Momentum * FacetNormal >= 0.0);
618              FacetNormal = FacetNormal.unit();
619           }
620           else {
621              FacetNormal = Normal;
622           }
623        }
624        return FacetNormal;
625}
626
627void G4OpBoundaryProcess::DielectricMetal()
628{
629        G4int n = 0;
630
631        do {
632
633           n++;
634
635           if( !G4BooleanRand(theReflectivity) && n == 1 ) {
636
637             // Comment out DoAbsorption and uncomment theStatus = Absorption;
638             // if you wish to have Transmission instead of Absorption
639
640             DoAbsorption();
641             // theStatus = Absorption;
642             break;
643
644           }
645           else {
646
647             if (PropertyPointer1 && PropertyPointer2) {
648                if ( n > 1 ) {
649                   CalculateReflectivity();
650                   if ( !G4BooleanRand(theReflectivity) ) {
651                      DoAbsorption();
652                      break;
653                   }
654                }
655             }
656
657             if ( theModel == glisur || theFinish == polished ) {
658
659                DoReflection();
660
661             } else {
662
663                if ( n == 1 ) ChooseReflection();
664                                                                               
665                if ( theStatus == LambertianReflection ) {
666                   DoReflection();
667                }
668                else if ( theStatus == BackScattering ) {
669                   NewMomentum = -OldMomentum;
670                   NewPolarization = -OldPolarization;
671                }
672                else {
673
674                   if(theStatus==LobeReflection){
675                     if ( PropertyPointer1 && PropertyPointer2 ){
676                     } else {
677                        theFacetNormal =
678                            GetFacetNormal(OldMomentum,theGlobalNormal);
679                     }
680                   }
681
682                   G4double PdotN = OldMomentum * theFacetNormal;
683                   NewMomentum = OldMomentum - (2.*PdotN)*theFacetNormal;
684                   G4double EdotN = OldPolarization * theFacetNormal;
685
686                   G4ThreeVector A_trans, A_paral;
687
688                   if (sint1 > 0.0 ) {
689                      A_trans = OldMomentum.cross(theFacetNormal);
690                      A_trans = A_trans.unit();
691                   } else {
692                      A_trans  = OldPolarization;
693                   }
694                   A_paral   = NewMomentum.cross(A_trans);
695                   A_paral   = A_paral.unit();
696
697                   if(iTE>0&&iTM>0) {
698                     NewPolarization = 
699                           -OldPolarization + (2.*EdotN)*theFacetNormal;
700                   } else if (iTE>0) {
701                     NewPolarization = -A_trans;
702                   } else if (iTM>0) {
703                     NewPolarization = -A_paral;
704                   }
705
706                }
707
708             }
709
710             OldMomentum = NewMomentum;
711             OldPolarization = NewPolarization;
712
713           }
714
715        } while (NewMomentum * theGlobalNormal < 0.0);
716}
717
718void G4OpBoundaryProcess::DielectricLUT()
719{
720        G4int thetaIndex, phiIndex;
721        G4double AngularDistributionValue, thetaRad, phiRad, EdotN;
722        G4ThreeVector PerpendicularVectorTheta, PerpendicularVectorPhi;
723
724        theStatus = G4OpBoundaryProcessStatus(G4int(theFinish) + 
725                           (G4int(NoRINDEX)-G4int(groundbackpainted)));
726
727        G4int thetaIndexMax = OpticalSurface->GetThetaIndexMax();
728        G4int phiIndexMax   = OpticalSurface->GetPhiIndexMax();
729
730        do {
731           if ( !G4BooleanRand(theReflectivity) ) // Not reflected, so Absorbed
732              DoAbsorption();
733           else {
734              // Calculate Angle between Normal and Photon Momentum
735              G4double anglePhotonToNormal = 
736                                          OldMomentum.angle(-theGlobalNormal);
737              // Round it to closest integer
738              G4int angleIncident = G4int(std::floor(180/pi*anglePhotonToNormal+0.5));
739
740              // Take random angles THETA and PHI,
741              // and see if below Probability - if not - Redo
742              do {
743                 thetaIndex = CLHEP::RandFlat::shootInt(thetaIndexMax-1);
744                 phiIndex = CLHEP::RandFlat::shootInt(phiIndexMax-1);
745                 // Find probability with the new indeces from LUT
746                 AngularDistributionValue = OpticalSurface -> 
747                   GetAngularDistributionValue(angleIncident,
748                                               thetaIndex,
749                                               phiIndex);
750              } while ( !G4BooleanRand(AngularDistributionValue) );
751
752              thetaRad = (-90 + 4*thetaIndex)*pi/180;
753              phiRad = (-90 + 5*phiIndex)*pi/180;
754              // Rotate Photon Momentum in Theta, then in Phi
755              NewMomentum = -OldMomentum;
756              PerpendicularVectorTheta = NewMomentum.cross(theGlobalNormal);
757              if (PerpendicularVectorTheta.mag() > kCarTolerance ) {
758                 PerpendicularVectorPhi = 
759                                  PerpendicularVectorTheta.cross(NewMomentum);
760              }
761              else {
762                 PerpendicularVectorTheta = NewMomentum.orthogonal();
763                 PerpendicularVectorPhi =
764                                  PerpendicularVectorTheta.cross(NewMomentum);
765              }
766              NewMomentum =
767                 NewMomentum.rotate(anglePhotonToNormal-thetaRad,
768                                    PerpendicularVectorTheta);
769              NewMomentum = NewMomentum.rotate(-phiRad,PerpendicularVectorPhi);
770              // Rotate Polarization too:
771              theFacetNormal = (NewMomentum - OldMomentum).unit();
772              EdotN = OldPolarization * theFacetNormal;
773              NewPolarization = -OldPolarization + (2.*EdotN)*theFacetNormal;
774           }
775        } while (NewMomentum * theGlobalNormal <= 0.0);
776}
777
778void G4OpBoundaryProcess::DielectricDielectric()
779{
780        G4bool Inside = false;
781        G4bool Swap = false;
782
783        leap:
784
785        G4bool Through = false;
786        G4bool Done = false;
787
788        do {
789
790           if (Through) {
791              Swap = !Swap;
792              Through = false;
793              theGlobalNormal = -theGlobalNormal;
794              G4SwapPtr(Material1,Material2);
795              G4SwapObj(&Rindex1,&Rindex2);
796           }
797       
798           if ( theFinish == polished ) {
799                theFacetNormal = theGlobalNormal;
800           }
801           else {
802                theFacetNormal =
803                             GetFacetNormal(OldMomentum,theGlobalNormal);
804           }
805
806           G4double PdotN = OldMomentum * theFacetNormal;
807           G4double EdotN = OldPolarization * theFacetNormal;
808
809           cost1 = - PdotN;
810           if (std::abs(cost1) < 1.0-kCarTolerance){
811              sint1 = std::sqrt(1.-cost1*cost1);
812              sint2 = sint1*Rindex1/Rindex2;     // *** Snell's Law ***
813           }
814           else {
815              sint1 = 0.0;
816              sint2 = 0.0;
817           }
818
819           if (sint2 >= 1.0) {
820
821              // Simulate total internal reflection
822
823              if (Swap) Swap = !Swap;
824
825              theStatus = TotalInternalReflection;
826
827              if ( theModel == unified && theFinish != polished )
828                                                     ChooseReflection();
829
830              if ( theStatus == LambertianReflection ) {
831                 DoReflection();
832              }
833              else if ( theStatus == BackScattering ) {
834                 NewMomentum = -OldMomentum;
835                 NewPolarization = -OldPolarization;
836              }
837              else {
838
839                 PdotN = OldMomentum * theFacetNormal;
840                 NewMomentum = OldMomentum - (2.*PdotN)*theFacetNormal;
841                 EdotN = OldPolarization * theFacetNormal;
842                 NewPolarization = -OldPolarization + (2.*EdotN)*theFacetNormal;
843
844              }
845           }
846           else if (sint2 < 1.0) {
847
848              // Calculate amplitude for transmission (Q = P x N)
849
850              if (cost1 > 0.0) {
851                 cost2 =  std::sqrt(1.-sint2*sint2);
852              }
853              else {
854                 cost2 = -std::sqrt(1.-sint2*sint2);
855              }
856
857              G4ThreeVector A_trans, A_paral, E1pp, E1pl;
858              G4double E1_perp, E1_parl;
859
860              if (sint1 > 0.0) {
861                 A_trans = OldMomentum.cross(theFacetNormal);
862                 A_trans = A_trans.unit();
863                 E1_perp = OldPolarization * A_trans;
864                 E1pp    = E1_perp * A_trans;
865                 E1pl    = OldPolarization - E1pp;
866                 E1_parl = E1pl.mag();
867              }
868              else {
869                 A_trans  = OldPolarization;
870                 // Here we Follow Jackson's conventions and we set the
871                 // parallel component = 1 in case of a ray perpendicular
872                 // to the surface
873                 E1_perp  = 0.0;
874                 E1_parl  = 1.0;
875              }
876
877              G4double s1 = Rindex1*cost1;
878              G4double E2_perp = 2.*s1*E1_perp/(Rindex1*cost1+Rindex2*cost2);
879              G4double E2_parl = 2.*s1*E1_parl/(Rindex2*cost1+Rindex1*cost2);
880              G4double E2_total = E2_perp*E2_perp + E2_parl*E2_parl;
881              G4double s2 = Rindex2*cost2*E2_total;
882
883              G4double TransCoeff;
884
885              if (cost1 != 0.0) {
886                 TransCoeff = s2/s1;
887              }
888              else {
889                 TransCoeff = 0.0;
890              }
891
892              G4double E2_abs, C_parl, C_perp;
893
894              if ( !G4BooleanRand(TransCoeff) ) {
895
896                 // Simulate reflection
897
898                 if (Swap) Swap = !Swap;
899
900                 theStatus = FresnelReflection;
901
902                 if ( theModel == unified && theFinish != polished )
903                                                     ChooseReflection();
904
905                 if ( theStatus == LambertianReflection ) {
906                    DoReflection();
907                 }
908                 else if ( theStatus == BackScattering ) {
909                    NewMomentum = -OldMomentum;
910                    NewPolarization = -OldPolarization;
911                 }
912                 else {
913
914                    PdotN = OldMomentum * theFacetNormal;
915                    NewMomentum = OldMomentum - (2.*PdotN)*theFacetNormal;
916
917                    if (sint1 > 0.0) {   // incident ray oblique
918
919                       E2_parl   = Rindex2*E2_parl/Rindex1 - E1_parl;
920                       E2_perp   = E2_perp - E1_perp;
921                       E2_total  = E2_perp*E2_perp + E2_parl*E2_parl;
922                       A_paral   = NewMomentum.cross(A_trans);
923                       A_paral   = A_paral.unit();
924                       E2_abs    = std::sqrt(E2_total);
925                       C_parl    = E2_parl/E2_abs;
926                       C_perp    = E2_perp/E2_abs;
927
928                       NewPolarization = C_parl*A_paral + C_perp*A_trans;
929
930                    }
931
932                    else {               // incident ray perpendicular
933
934                       if (Rindex2 > Rindex1) {
935                          NewPolarization = - OldPolarization;
936                       }
937                       else {
938                          NewPolarization =   OldPolarization;
939                       }
940
941                    }
942                 }
943              }
944              else { // photon gets transmitted
945
946                 // Simulate transmission/refraction
947
948                 Inside = !Inside;
949                 Through = true;
950                 theStatus = FresnelRefraction;
951
952                 if (sint1 > 0.0) {      // incident ray oblique
953
954                    G4double alpha = cost1 - cost2*(Rindex2/Rindex1);
955                    NewMomentum = OldMomentum + alpha*theFacetNormal;
956                    NewMomentum = NewMomentum.unit();
957                    PdotN = -cost2;
958                    A_paral = NewMomentum.cross(A_trans);
959                    A_paral = A_paral.unit();
960                    E2_abs     = std::sqrt(E2_total);
961                    C_parl     = E2_parl/E2_abs;
962                    C_perp     = E2_perp/E2_abs;
963
964                    NewPolarization = C_parl*A_paral + C_perp*A_trans;
965
966                 }
967                 else {                  // incident ray perpendicular
968
969                    NewMomentum = OldMomentum;
970                    NewPolarization = OldPolarization;
971
972                 }
973              }
974           }
975
976           OldMomentum = NewMomentum.unit();
977           OldPolarization = NewPolarization.unit();
978
979           if (theStatus == FresnelRefraction) {
980              Done = (NewMomentum * theGlobalNormal <= 0.0);
981           } 
982           else {
983              Done = (NewMomentum * theGlobalNormal >= 0.0);
984           }
985
986        } while (!Done);
987
988        if (Inside && !Swap) {
989          if( theFinish == polishedbackpainted ||
990              theFinish == groundbackpainted ) {
991
992              if( !G4BooleanRand(theReflectivity) ) {
993                DoAbsorption();
994              }
995              else {
996                if (theStatus != FresnelRefraction ) {
997                   theGlobalNormal = -theGlobalNormal;
998                }
999                else {
1000                   Swap = !Swap;
1001                   G4SwapPtr(Material1,Material2);
1002                   G4SwapObj(&Rindex1,&Rindex2);
1003                }
1004                if ( theFinish == groundbackpainted )
1005                                        theStatus = LambertianReflection;
1006
1007                DoReflection();
1008
1009                theGlobalNormal = -theGlobalNormal;
1010                OldMomentum = NewMomentum;
1011
1012                goto leap;
1013              }
1014          }
1015        }
1016}
1017
1018// GetMeanFreePath
1019// ---------------
1020//
1021G4double G4OpBoundaryProcess::GetMeanFreePath(const G4Track& ,
1022                                              G4double ,
1023                                              G4ForceCondition* condition)
1024{
1025        *condition = Forced;
1026
1027        return DBL_MAX;
1028}
1029
1030G4double G4OpBoundaryProcess::GetIncidentAngle() 
1031{
1032    G4double PdotN = OldMomentum * theFacetNormal;
1033    G4double magP= OldMomentum.mag();
1034    G4double magN= theFacetNormal.mag();
1035    G4double incidentangle = pi - std::acos(PdotN/(magP*magN));
1036
1037    return incidentangle;
1038}
1039
1040G4double G4OpBoundaryProcess::GetReflectivity(G4double E1_perp,
1041                                              G4double E1_parl,
1042                                              G4double incidentangle,
1043                                              G4double RealRindex,
1044                                              G4double ImaginaryRindex)
1045{
1046
1047  G4complex Reflectivity, Reflectivity_TE, Reflectivity_TM;
1048  G4complex N(RealRindex, ImaginaryRindex);
1049  G4complex CosPhi;
1050
1051  G4complex u(1,0);           //unit number 1
1052
1053  G4complex numeratorTE;      // E1_perp=1 E1_parl=0 -> TE polarization
1054  G4complex numeratorTM;      // E1_parl=1 E1_perp=0 -> TM polarization
1055  G4complex denominatorTE, denominatorTM;
1056  G4complex rTM, rTE;
1057
1058  // Following two equations, rTM and rTE, are from: "Introduction To Modern
1059  // Optics" written by Fowles
1060
1061  CosPhi=std::sqrt(u-((std::sin(incidentangle)*std::sin(incidentangle))/(N*N)));
1062
1063  numeratorTE   = std::cos(incidentangle) - N*CosPhi;
1064  denominatorTE = std::cos(incidentangle) + N*CosPhi;
1065  rTE = numeratorTE/denominatorTE;
1066
1067  numeratorTM   = N*std::cos(incidentangle) - CosPhi;
1068  denominatorTM = N*std::cos(incidentangle) + CosPhi;
1069  rTM = numeratorTM/denominatorTM;
1070
1071  // This is my calculaton for reflectivity on a metalic surface
1072  // depending on the fraction of TE and TM polarization
1073  // when TE polarization, E1_parl=0 and E1_perp=1, R=abs(rTE)^2 and
1074  // when TM polarization, E1_parl=1 and E1_perp=0, R=abs(rTM)^2
1075
1076  Reflectivity_TE =  (rTE*conj(rTE))*(E1_perp*E1_perp)
1077                    / (E1_perp*E1_perp + E1_parl*E1_parl);
1078  Reflectivity_TM =  (rTM*conj(rTM))*(E1_parl*E1_parl)
1079                    / (E1_perp*E1_perp + E1_parl*E1_parl);
1080  Reflectivity    = Reflectivity_TE + Reflectivity_TM;
1081
1082  do {
1083     if(G4UniformRand()*real(Reflectivity) > real(Reflectivity_TE))
1084       {iTE = -1;}else{iTE = 1;}
1085     if(G4UniformRand()*real(Reflectivity) > real(Reflectivity_TM))
1086       {iTM = -1;}else{iTM = 1;}
1087  } while(iTE<0&&iTM<0);
1088
1089  return real(Reflectivity);
1090
1091}
1092
1093void G4OpBoundaryProcess::CalculateReflectivity()
1094{
1095  G4double RealRindex =
1096           PropertyPointer1->GetProperty(thePhotonMomentum);
1097  G4double ImaginaryRindex =
1098           PropertyPointer2->GetProperty(thePhotonMomentum);
1099
1100  // calculate FacetNormal
1101  if ( theFinish == ground ) {
1102     theFacetNormal =
1103               GetFacetNormal(OldMomentum, theGlobalNormal);
1104  } else {
1105     theFacetNormal = theGlobalNormal;
1106  }
1107
1108  G4double PdotN = OldMomentum * theFacetNormal;
1109  cost1 = -PdotN;
1110
1111  if (std::abs(cost1) < 1.0 - kCarTolerance) {
1112     sint1 = std::sqrt(1. - cost1*cost1);
1113  } else {
1114     sint1 = 0.0;
1115  }
1116
1117  G4ThreeVector A_trans, A_paral, E1pp, E1pl;
1118  G4double E1_perp, E1_parl;
1119
1120  if (sint1 > 0.0 ) {
1121     A_trans = OldMomentum.cross(theFacetNormal);
1122     A_trans = A_trans.unit();
1123     E1_perp = OldPolarization * A_trans;
1124     E1pp    = E1_perp * A_trans;
1125     E1pl    = OldPolarization - E1pp;
1126     E1_parl = E1pl.mag();
1127  }
1128  else {
1129     A_trans  = OldPolarization;
1130     // Here we Follow Jackson's conventions and we set the
1131     // parallel component = 1 in case of a ray perpendicular
1132     // to the surface
1133     E1_perp  = 0.0;
1134     E1_parl  = 1.0;
1135  }
1136
1137  //calculate incident angle
1138  G4double incidentangle = GetIncidentAngle();
1139
1140  //calculate the reflectivity depending on incident angle,
1141  //polarization and complex refractive
1142
1143  theReflectivity =
1144             GetReflectivity(E1_perp, E1_parl, incidentangle,
1145                                                 RealRindex, ImaginaryRindex);
1146}
Note: See TracBrowser for help on using the repository browser.