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

Last change on this file since 831 was 819, checked in by garnier, 17 years ago

import all except CVS

File size: 30.7 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//
62// Author: Peter Gumplinger
63// adopted from work by Werner Keil - April 2/96
64// mail: gum@triumf.ca
65//
66////////////////////////////////////////////////////////////////////////
67
68#include "G4ios.hh"
69#include "G4OpBoundaryProcess.hh"
70#include "G4GeometryTolerance.hh"
71
72/////////////////////////
73// Class Implementation
74/////////////////////////
75
76 //////////////
77 // Operators
78 //////////////
79
80// G4OpBoundaryProcess::operator=(const G4OpBoundaryProcess &right)
81// {
82// }
83
84 /////////////////
85 // Constructors
86 /////////////////
87
88G4OpBoundaryProcess::G4OpBoundaryProcess(const G4String& processName,
89 G4ProcessType type)
90 : G4VDiscreteProcess(processName, type)
91{
92 if ( verboseLevel > 0) {
93 G4cout << GetProcessName() << " is created " << G4endl;
94 }
95
96 theStatus = Undefined;
97 theModel = glisur;
98 theFinish = polished;
99 theReflectivity = 1.;
100 theEfficiency = 0.;
101
102 prob_sl = 0.;
103 prob_ss = 0.;
104 prob_bs = 0.;
105
106 kCarTolerance = G4GeometryTolerance::GetInstance()
107 ->GetSurfaceTolerance();
108
109}
110
111// G4OpBoundaryProcess::G4OpBoundaryProcess(const G4OpBoundaryProcess &right)
112// {
113// }
114
115 ////////////////
116 // Destructors
117 ////////////////
118
119G4OpBoundaryProcess::~G4OpBoundaryProcess(){}
120
121 ////////////
122 // Methods
123 ////////////
124
125// PostStepDoIt
126// ------------
127//
128G4VParticleChange*
129G4OpBoundaryProcess::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep)
130{
131 theStatus = Undefined;
132
133 aParticleChange.Initialize(aTrack);
134
135 G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
136 G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
137
138 if (pPostStepPoint->GetStepStatus() != fGeomBoundary){
139 theStatus = NotAtBoundary;
140 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
141 }
142 if (aTrack.GetStepLength()<=kCarTolerance/2){
143 theStatus = StepTooSmall;
144 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
145 }
146
147 Material1 = pPreStepPoint -> GetMaterial();
148 Material2 = pPostStepPoint -> GetMaterial();
149
150 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
151
152 thePhotonMomentum = aParticle->GetTotalMomentum();
153 OldMomentum = aParticle->GetMomentumDirection();
154 OldPolarization = aParticle->GetPolarization();
155
156 G4ThreeVector theGlobalPoint = pPostStepPoint->GetPosition();
157
158 G4Navigator* theNavigator =
159 G4TransportationManager::GetTransportationManager()->
160 GetNavigatorForTracking();
161
162 G4ThreeVector theLocalPoint = theNavigator->
163 GetGlobalToLocalTransform().
164 TransformPoint(theGlobalPoint);
165
166 G4ThreeVector theLocalNormal; // Normal points back into volume
167
168 G4bool valid;
169 theLocalNormal = theNavigator->GetLocalExitNormal(&valid);
170
171 if (valid) {
172 theLocalNormal = -theLocalNormal;
173 }
174 else {
175 G4cerr << " G4OpBoundaryProcess/PostStepDoIt(): "
176 << " The Navigator reports that it returned an invalid normal"
177 << G4endl;
178 }
179
180 theGlobalNormal = theNavigator->GetLocalToGlobalTransform().
181 TransformAxis(theLocalNormal);
182
183 if (OldMomentum * theGlobalNormal > 0.0) {
184#ifdef G4DEBUG_OPTICAL
185 G4cerr << " G4OpBoundaryProcess/PostStepDoIt(): "
186 << " theGlobalNormal points the wrong direction "
187 << G4endl;
188#endif
189 theGlobalNormal = -theGlobalNormal;
190 }
191
192 G4MaterialPropertiesTable* aMaterialPropertiesTable;
193 G4MaterialPropertyVector* Rindex;
194
195 aMaterialPropertiesTable = Material1->GetMaterialPropertiesTable();
196 if (aMaterialPropertiesTable) {
197 Rindex = aMaterialPropertiesTable->GetProperty("RINDEX");
198 }
199 else {
200 theStatus = NoRINDEX;
201 aParticleChange.ProposeTrackStatus(fStopAndKill);
202 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
203 }
204
205 if (Rindex) {
206 Rindex1 = Rindex->GetProperty(thePhotonMomentum);
207 }
208 else {
209 theStatus = NoRINDEX;
210 aParticleChange.ProposeTrackStatus(fStopAndKill);
211 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
212 }
213
214 theModel = glisur;
215 theFinish = polished;
216
217 G4SurfaceType type = dielectric_dielectric;
218
219 Rindex = NULL;
220 OpticalSurface = NULL;
221
222 G4LogicalSurface* Surface = G4LogicalBorderSurface::GetSurface
223 (pPreStepPoint ->GetPhysicalVolume(),
224 pPostStepPoint->GetPhysicalVolume());
225
226 if (Surface == NULL){
227 G4bool enteredDaughter=(pPostStepPoint->GetPhysicalVolume()
228 ->GetMotherLogical() ==
229 pPreStepPoint->GetPhysicalVolume()
230 ->GetLogicalVolume());
231 if(enteredDaughter){
232 Surface = G4LogicalSkinSurface::GetSurface
233 (pPostStepPoint->GetPhysicalVolume()->
234 GetLogicalVolume());
235 if(Surface == NULL)
236 Surface = G4LogicalSkinSurface::GetSurface
237 (pPreStepPoint->GetPhysicalVolume()->
238 GetLogicalVolume());
239 }
240 else {
241 Surface = G4LogicalSkinSurface::GetSurface
242 (pPreStepPoint->GetPhysicalVolume()->
243 GetLogicalVolume());
244 if(Surface == NULL)
245 Surface = G4LogicalSkinSurface::GetSurface
246 (pPostStepPoint->GetPhysicalVolume()->
247 GetLogicalVolume());
248 }
249 }
250
251 // if (Surface) OpticalSurface = dynamic_cast <G4OpticalSurface*> (Surface->GetSurfaceProperty());
252 if (Surface) OpticalSurface = (G4OpticalSurface*) Surface->GetSurfaceProperty();
253
254 if (OpticalSurface) {
255
256 type = OpticalSurface->GetType();
257 theModel = OpticalSurface->GetModel();
258 theFinish = OpticalSurface->GetFinish();
259
260 aMaterialPropertiesTable = OpticalSurface->
261 GetMaterialPropertiesTable();
262
263 if (aMaterialPropertiesTable) {
264
265 if (theFinish == polishedbackpainted ||
266 theFinish == groundbackpainted ) {
267 Rindex = aMaterialPropertiesTable->GetProperty("RINDEX");
268 if (Rindex) {
269 Rindex2 = Rindex->GetProperty(thePhotonMomentum);
270 }
271 else {
272 theStatus = NoRINDEX;
273 aParticleChange.ProposeTrackStatus(fStopAndKill);
274 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
275 }
276 }
277
278 G4MaterialPropertyVector* PropertyPointer;
279 G4MaterialPropertyVector* PropertyPointer1;
280 G4MaterialPropertyVector* PropertyPointer2;
281
282 PropertyPointer =
283 aMaterialPropertiesTable->GetProperty("REFLECTIVITY");
284 PropertyPointer1 =
285 aMaterialPropertiesTable->GetProperty("REALRINDEX");
286 PropertyPointer2 =
287 aMaterialPropertiesTable->GetProperty("IMAGINARYRINDEX");
288
289 iTE = 1;
290 iTM = 1;
291
292 if (PropertyPointer) {
293
294 theReflectivity =
295 PropertyPointer->GetProperty(thePhotonMomentum);
296
297 } else if (PropertyPointer1 && PropertyPointer2) {
298
299 G4double RealRindex =
300 PropertyPointer1->GetProperty(thePhotonMomentum);
301 G4double ImaginaryRindex =
302 PropertyPointer2->GetProperty(thePhotonMomentum);
303
304 // calculate FacetNormal
305 if ( theFinish == ground ) {
306 theFacetNormal =
307 GetFacetNormal(OldMomentum, theGlobalNormal);
308 } else {
309 theFacetNormal = theGlobalNormal;
310 }
311
312 G4double PdotN = OldMomentum * theFacetNormal;
313 cost1 = -PdotN;
314
315 if (std::abs(cost1) < 1.0 - kCarTolerance) {
316 sint1 = std::sqrt(1. - cost1*cost1);
317 } else {
318 sint1 = 0.0;
319 }
320
321 G4ThreeVector A_trans, A_paral, E1pp, E1pl;
322 G4double E1_perp, E1_parl;
323
324 if (sint1 > 0.0 ) {
325 A_trans = OldMomentum.cross(theFacetNormal);
326 A_trans = A_trans.unit();
327 E1_perp = OldPolarization * A_trans;
328 E1pp = E1_perp * A_trans;
329 E1pl = OldPolarization - E1pp;
330 E1_parl = E1pl.mag();
331 }
332 else {
333 A_trans = OldPolarization;
334 // Here we Follow Jackson's conventions and we set the
335 // parallel component = 1 in case of a ray perpendicular
336 // to the surface
337 E1_perp = 0.0;
338 E1_parl = 1.0;
339 }
340
341 //calculate incident angle
342 G4double incidentangle = GetIncidentAngle();
343
344 //calculate the reflectivity depending on incident angle,
345 //polarization and complex refractive
346
347 theReflectivity =
348 GetReflectivity(E1_perp, E1_parl, incidentangle,
349 RealRindex, ImaginaryRindex);
350
351 } else {
352 theReflectivity = 1.0;
353 }
354
355 PropertyPointer =
356 aMaterialPropertiesTable->GetProperty("EFFICIENCY");
357 if (PropertyPointer) {
358 theEfficiency =
359 PropertyPointer->GetProperty(thePhotonMomentum);
360 } else {
361 theEfficiency = 0.0;
362 }
363
364 if ( theModel == unified ) {
365 PropertyPointer =
366 aMaterialPropertiesTable->GetProperty("SPECULARLOBECONSTANT");
367 if (PropertyPointer) {
368 prob_sl =
369 PropertyPointer->GetProperty(thePhotonMomentum);
370 } else {
371 prob_sl = 0.0;
372 }
373
374 PropertyPointer =
375 aMaterialPropertiesTable->GetProperty("SPECULARSPIKECONSTANT");
376 if (PropertyPointer) {
377 prob_ss =
378 PropertyPointer->GetProperty(thePhotonMomentum);
379 } else {
380 prob_ss = 0.0;
381 }
382
383 PropertyPointer =
384 aMaterialPropertiesTable->GetProperty("BACKSCATTERCONSTANT");
385 if (PropertyPointer) {
386 prob_bs =
387 PropertyPointer->GetProperty(thePhotonMomentum);
388 } else {
389 prob_bs = 0.0;
390 }
391 }
392 }
393 else if (theFinish == polishedbackpainted ||
394 theFinish == groundbackpainted ) {
395 aParticleChange.ProposeTrackStatus(fStopAndKill);
396 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
397 }
398 }
399
400 if (type == dielectric_dielectric ) {
401 if (theFinish == polished || theFinish == ground ) {
402
403 if (Material1 == Material2){
404 theStatus = SameMaterial;
405 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
406 }
407 aMaterialPropertiesTable =
408 Material2->GetMaterialPropertiesTable();
409 if (aMaterialPropertiesTable)
410 Rindex = aMaterialPropertiesTable->GetProperty("RINDEX");
411 if (Rindex) {
412 Rindex2 = Rindex->GetProperty(thePhotonMomentum);
413 }
414 else {
415 theStatus = NoRINDEX;
416 aParticleChange.ProposeTrackStatus(fStopAndKill);
417 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
418 }
419 }
420 }
421
422 if ( verboseLevel > 0 ) {
423 G4cout << " Photon at Boundary! " << G4endl;
424 G4cout << " Old Momentum Direction: " << OldMomentum << G4endl;
425 G4cout << " Old Polarization: " << OldPolarization << G4endl;
426 }
427
428 if (type == dielectric_metal) {
429
430 DielectricMetal();
431
432 }
433 else if (type == dielectric_dielectric) {
434
435 if ( theFinish == polishedfrontpainted ||
436 theFinish == groundfrontpainted ) {
437
438 if( !G4BooleanRand(theReflectivity) ) {
439 DoAbsorption();
440 }
441 else {
442 if ( theFinish == groundfrontpainted )
443 theStatus = LambertianReflection;
444 DoReflection();
445 }
446 }
447 else {
448 DielectricDielectric();
449 }
450 }
451 else {
452
453 G4cerr << " Error: G4BoundaryProcess: illegal boundary type " << G4endl;
454 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
455
456 }
457
458 NewMomentum = NewMomentum.unit();
459 NewPolarization = NewPolarization.unit();
460
461 if ( verboseLevel > 0) {
462 G4cout << " New Momentum Direction: " << NewMomentum << G4endl;
463 G4cout << " New Polarization: " << NewPolarization << G4endl;
464 if ( theStatus == Undefined )
465 G4cout << " *** Undefined *** " << G4endl;
466 if ( theStatus == FresnelRefraction )
467 G4cout << " *** FresnelRefraction *** " << G4endl;
468 if ( theStatus == FresnelReflection )
469 G4cout << " *** FresnelReflection *** " << G4endl;
470 if ( theStatus == TotalInternalReflection )
471 G4cout << " *** TotalInternalReflection *** " << G4endl;
472 if ( theStatus == LambertianReflection )
473 G4cout << " *** LambertianReflection *** " << G4endl;
474 if ( theStatus == LobeReflection )
475 G4cout << " *** LobeReflection *** " << G4endl;
476 if ( theStatus == SpikeReflection )
477 G4cout << " *** SpikeReflection *** " << G4endl;
478 if ( theStatus == BackScattering )
479 G4cout << " *** BackScattering *** " << G4endl;
480 if ( theStatus == Absorption )
481 G4cout << " *** Absorption *** " << G4endl;
482 if ( theStatus == Detection )
483 G4cout << " *** Detection *** " << G4endl;
484 if ( theStatus == NotAtBoundary )
485 G4cout << " *** NotAtBoundary *** " << G4endl;
486 if ( theStatus == SameMaterial )
487 G4cout << " *** SameMaterial *** " << G4endl;
488 if ( theStatus == StepTooSmall )
489 G4cout << " *** StepTooSmall *** " << G4endl;
490 if ( theStatus == NoRINDEX )
491 G4cout << " *** NoRINDEX *** " << G4endl;
492 }
493
494 aParticleChange.ProposeMomentumDirection(NewMomentum);
495 aParticleChange.ProposePolarization(NewPolarization);
496
497 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
498}
499
500G4ThreeVector
501G4OpBoundaryProcess::GetFacetNormal(const G4ThreeVector& Momentum,
502 const G4ThreeVector& Normal ) const
503{
504 G4ThreeVector FacetNormal;
505
506 if (theModel == unified) {
507
508 /* This function code alpha to a random value taken from the
509 distribution p(alpha) = g(alpha; 0, sigma_alpha)*std::sin(alpha),
510 for alpha > 0 and alpha < 90, where g(alpha; 0, sigma_alpha)
511 is a gaussian distribution with mean 0 and standard deviation
512 sigma_alpha. */
513
514 G4double alpha;
515
516 G4double sigma_alpha = 0.0;
517 if (OpticalSurface) sigma_alpha = OpticalSurface->GetSigmaAlpha();
518
519 G4double f_max = std::min(1.0,4.*sigma_alpha);
520
521 do {
522 do {
523 alpha = G4RandGauss::shoot(0.0,sigma_alpha);
524 } while (G4UniformRand()*f_max > std::sin(alpha) || alpha >= halfpi );
525
526 G4double phi = G4UniformRand()*twopi;
527
528 G4double SinAlpha = std::sin(alpha);
529 G4double CosAlpha = std::cos(alpha);
530 G4double SinPhi = std::sin(phi);
531 G4double CosPhi = std::cos(phi);
532
533 G4double unit_x = SinAlpha * CosPhi;
534 G4double unit_y = SinAlpha * SinPhi;
535 G4double unit_z = CosAlpha;
536
537 FacetNormal.setX(unit_x);
538 FacetNormal.setY(unit_y);
539 FacetNormal.setZ(unit_z);
540
541 G4ThreeVector tmpNormal = Normal;
542
543 FacetNormal.rotateUz(tmpNormal);
544 } while (Momentum * FacetNormal >= 0.0);
545 }
546 else {
547
548 G4double polish = 1.0;
549 if (OpticalSurface) polish = OpticalSurface->GetPolish();
550
551 if (polish < 1.0) {
552 do {
553 G4ThreeVector smear;
554 do {
555 smear.setX(2.*G4UniformRand()-1.0);
556 smear.setY(2.*G4UniformRand()-1.0);
557 smear.setZ(2.*G4UniformRand()-1.0);
558 } while (smear.mag()>1.0);
559 smear = (1.-polish) * smear;
560 FacetNormal = Normal + smear;
561 } while (Momentum * FacetNormal >= 0.0);
562 FacetNormal = FacetNormal.unit();
563 }
564 else {
565 FacetNormal = Normal;
566 }
567 }
568 return FacetNormal;
569}
570
571void G4OpBoundaryProcess::DielectricMetal()
572{
573 G4int n = 0;
574
575 do {
576
577 n++;
578
579 if( !G4BooleanRand(theReflectivity) && n == 1 ) {
580
581 DoAbsorption();
582 break;
583
584 }
585 else {
586
587 if ( theModel == glisur || theFinish == polished ) {
588
589 DoReflection();
590
591 } else {
592
593 if ( n == 1 ) ChooseReflection();
594
595 if ( theStatus == LambertianReflection ) {
596 DoReflection();
597 }
598 else if ( theStatus == BackScattering ) {
599 NewMomentum = -OldMomentum;
600 NewPolarization = -OldPolarization;
601 }
602 else {
603
604 if(theStatus==LobeReflection)theFacetNormal =
605 GetFacetNormal(OldMomentum,theGlobalNormal);
606
607 G4double PdotN = OldMomentum * theFacetNormal;
608 NewMomentum = OldMomentum - (2.*PdotN)*theFacetNormal;
609 G4double EdotN = OldPolarization * theFacetNormal;
610
611 G4ThreeVector A_trans, A_paral;
612
613 if (sint1 > 0.0 ) {
614 A_trans = OldMomentum.cross(theFacetNormal);
615 A_trans = A_trans.unit();
616 } else {
617 A_trans = OldPolarization;
618 }
619 A_paral = NewMomentum.cross(A_trans);
620 A_paral = A_paral.unit();
621
622 if(iTE>0&&iTM>0) {
623 NewPolarization =
624 -OldPolarization + (2.*EdotN)*theFacetNormal;
625 } else if (iTE>0) {
626 NewPolarization = -A_trans;
627 } else if (iTM>0) {
628 NewPolarization = -A_paral;
629 }
630
631 }
632
633 }
634
635 OldMomentum = NewMomentum;
636 OldPolarization = NewPolarization;
637
638 }
639
640 } while (NewMomentum * theGlobalNormal < 0.0);
641}
642
643void G4OpBoundaryProcess::DielectricDielectric()
644{
645 G4bool Inside = false;
646 G4bool Swap = false;
647
648 leap:
649
650 G4bool Through = false;
651 G4bool Done = false;
652
653 do {
654
655 if (Through) {
656 Swap = !Swap;
657 Through = false;
658 theGlobalNormal = -theGlobalNormal;
659 G4Swap(Material1,Material2);
660 G4Swap(&Rindex1,&Rindex2);
661 }
662
663 if ( theFinish == ground || theFinish == groundbackpainted ) {
664 theFacetNormal =
665 GetFacetNormal(OldMomentum,theGlobalNormal);
666 }
667 else {
668 theFacetNormal = theGlobalNormal;
669 }
670
671 G4double PdotN = OldMomentum * theFacetNormal;
672 G4double EdotN = OldPolarization * theFacetNormal;
673
674 cost1 = - PdotN;
675 if (std::abs(cost1) < 1.0-kCarTolerance){
676 sint1 = std::sqrt(1.-cost1*cost1);
677 sint2 = sint1*Rindex1/Rindex2; // *** Snell's Law ***
678 }
679 else {
680 sint1 = 0.0;
681 sint2 = 0.0;
682 }
683
684 if (sint2 >= 1.0) {
685
686 // Simulate total internal reflection
687
688 if (Swap) Swap = !Swap;
689
690 theStatus = TotalInternalReflection;
691
692 if ( theModel == unified && theFinish != polished )
693 ChooseReflection();
694
695 if ( theStatus == LambertianReflection ) {
696 DoReflection();
697 }
698 else if ( theStatus == BackScattering ) {
699 NewMomentum = -OldMomentum;
700 NewPolarization = -OldPolarization;
701 }
702 else {
703
704 PdotN = OldMomentum * theFacetNormal;
705 NewMomentum = OldMomentum - (2.*PdotN)*theFacetNormal;
706 EdotN = OldPolarization * theFacetNormal;
707 NewPolarization = -OldPolarization + (2.*EdotN)*theFacetNormal;
708
709 }
710 }
711 else if (sint2 < 1.0) {
712
713 // Calculate amplitude for transmission (Q = P x N)
714
715 if (cost1 > 0.0) {
716 cost2 = std::sqrt(1.-sint2*sint2);
717 }
718 else {
719 cost2 = -std::sqrt(1.-sint2*sint2);
720 }
721
722 G4ThreeVector A_trans, A_paral, E1pp, E1pl;
723 G4double E1_perp, E1_parl;
724
725 if (sint1 > 0.0) {
726 A_trans = OldMomentum.cross(theFacetNormal);
727 A_trans = A_trans.unit();
728 E1_perp = OldPolarization * A_trans;
729 E1pp = E1_perp * A_trans;
730 E1pl = OldPolarization - E1pp;
731 E1_parl = E1pl.mag();
732 }
733 else {
734 A_trans = OldPolarization;
735 // Here we Follow Jackson's conventions and we set the
736 // parallel component = 1 in case of a ray perpendicular
737 // to the surface
738 E1_perp = 0.0;
739 E1_parl = 1.0;
740 }
741
742 G4double s1 = Rindex1*cost1;
743 G4double E2_perp = 2.*s1*E1_perp/(Rindex1*cost1+Rindex2*cost2);
744 G4double E2_parl = 2.*s1*E1_parl/(Rindex2*cost1+Rindex1*cost2);
745 G4double E2_total = E2_perp*E2_perp + E2_parl*E2_parl;
746 G4double s2 = Rindex2*cost2*E2_total;
747
748 G4double TransCoeff;
749
750 if (cost1 != 0.0) {
751 TransCoeff = s2/s1;
752 }
753 else {
754 TransCoeff = 0.0;
755 }
756
757 G4double E2_abs, C_parl, C_perp;
758
759 if ( !G4BooleanRand(TransCoeff) ) {
760
761 // Simulate reflection
762
763 if (Swap) Swap = !Swap;
764
765 theStatus = FresnelReflection;
766
767 if ( theModel == unified && theFinish != polished )
768 ChooseReflection();
769
770 if ( theStatus == LambertianReflection ) {
771 DoReflection();
772 }
773 else if ( theStatus == BackScattering ) {
774 NewMomentum = -OldMomentum;
775 NewPolarization = -OldPolarization;
776 }
777 else {
778
779 PdotN = OldMomentum * theFacetNormal;
780 NewMomentum = OldMomentum - (2.*PdotN)*theFacetNormal;
781
782 if (sint1 > 0.0) { // incident ray oblique
783
784 E2_parl = Rindex2*E2_parl/Rindex1 - E1_parl;
785 E2_perp = E2_perp - E1_perp;
786 E2_total = E2_perp*E2_perp + E2_parl*E2_parl;
787 A_paral = NewMomentum.cross(A_trans);
788 A_paral = A_paral.unit();
789 E2_abs = std::sqrt(E2_total);
790 C_parl = E2_parl/E2_abs;
791 C_perp = E2_perp/E2_abs;
792
793 NewPolarization = C_parl*A_paral + C_perp*A_trans;
794
795 }
796
797 else { // incident ray perpendicular
798
799 if (Rindex2 > Rindex1) {
800 NewPolarization = - OldPolarization;
801 }
802 else {
803 NewPolarization = OldPolarization;
804 }
805
806 }
807 }
808 }
809 else { // photon gets transmitted
810
811 // Simulate transmission/refraction
812
813 Inside = !Inside;
814 Through = true;
815 theStatus = FresnelRefraction;
816
817 if (sint1 > 0.0) { // incident ray oblique
818
819 G4double alpha = cost1 - cost2*(Rindex2/Rindex1);
820 NewMomentum = OldMomentum + alpha*theFacetNormal;
821 NewMomentum = NewMomentum.unit();
822 PdotN = -cost2;
823 A_paral = NewMomentum.cross(A_trans);
824 A_paral = A_paral.unit();
825 E2_abs = std::sqrt(E2_total);
826 C_parl = E2_parl/E2_abs;
827 C_perp = E2_perp/E2_abs;
828
829 NewPolarization = C_parl*A_paral + C_perp*A_trans;
830
831 }
832 else { // incident ray perpendicular
833
834 NewMomentum = OldMomentum;
835 NewPolarization = OldPolarization;
836
837 }
838 }
839 }
840
841 OldMomentum = NewMomentum.unit();
842 OldPolarization = NewPolarization.unit();
843
844 if (theStatus == FresnelRefraction) {
845 Done = (NewMomentum * theGlobalNormal <= 0.0);
846 }
847 else {
848 Done = (NewMomentum * theGlobalNormal >= 0.0);
849 }
850
851 } while (!Done);
852
853 if (Inside && !Swap) {
854 if( theFinish == polishedbackpainted ||
855 theFinish == groundbackpainted ) {
856
857 if( !G4BooleanRand(theReflectivity) ) {
858 DoAbsorption();
859 }
860 else {
861 if (theStatus != FresnelRefraction ) {
862 theGlobalNormal = -theGlobalNormal;
863 }
864 else {
865 Swap = !Swap;
866 G4Swap(Material1,Material2);
867 G4Swap(&Rindex1,&Rindex2);
868 }
869 if ( theFinish == groundbackpainted )
870 theStatus = LambertianReflection;
871
872 DoReflection();
873
874 theGlobalNormal = -theGlobalNormal;
875 OldMomentum = NewMomentum;
876
877 goto leap;
878 }
879 }
880 }
881}
882
883// GetMeanFreePath
884// ---------------
885//
886G4double G4OpBoundaryProcess::GetMeanFreePath(const G4Track& ,
887 G4double ,
888 G4ForceCondition* condition)
889{
890 *condition = Forced;
891
892 return DBL_MAX;
893}
894
895G4double G4OpBoundaryProcess::GetIncidentAngle()
896{
897 G4double PdotN = OldMomentum * theFacetNormal;
898 G4double magP= OldMomentum.mag();
899 G4double magN= theFacetNormal.mag();
900 G4double incidentangle = pi - std::acos(PdotN/(magP*magN));
901
902 return incidentangle;
903}
904
905G4double G4OpBoundaryProcess::GetReflectivity(G4double E1_perp,
906 G4double E1_parl,
907 G4double incidentangle,
908 G4double RealRindex,
909 G4double ImaginaryRindex)
910{
911
912 G4complex Reflectivity, Reflectivity_TE, Reflectivity_TM;
913 G4complex N(RealRindex, ImaginaryRindex);
914 G4complex CosPhi;
915
916 G4complex u(1,0); //unit number 1
917
918 G4complex numeratorTE; // E1_perp=1 E1_parl=0 -> TE polarization
919 G4complex numeratorTM; // E1_parl=1 E1_perp=0 -> TM polarization
920 G4complex denominatorTE, denominatorTM;
921 G4complex rTM, rTE;
922
923 // Following two equations, rTM and rTE, are from: "Introduction To Modern
924 // Optics" written by Fowles
925
926 CosPhi=std::sqrt(u-((std::sin(incidentangle)*std::sin(incidentangle))/(N*N)));
927
928 numeratorTE = std::cos(incidentangle) - N*CosPhi;
929 denominatorTE = std::cos(incidentangle) + N*CosPhi;
930 rTE = numeratorTE/denominatorTE;
931
932 numeratorTM = N*std::cos(incidentangle) - CosPhi;
933 denominatorTM = N*std::cos(incidentangle) + CosPhi;
934 rTM = numeratorTM/denominatorTM;
935
936 // This is my calculaton for reflectivity on a metalic surface
937 // depending on the fraction of TE and TM polarization
938 // when TE polarization, E1_parl=0 and E1_perp=1, R=abs(rTE)^2 and
939 // when TM polarization, E1_parl=1 and E1_perp=0, R=abs(rTM)^2
940
941 Reflectivity_TE = (rTE*conj(rTE))*(E1_perp*E1_perp)
942 / (E1_perp*E1_perp + E1_parl*E1_parl);
943 Reflectivity_TM = (rTM*conj(rTM))*(E1_parl*E1_parl)
944 / (E1_perp*E1_perp + E1_parl*E1_parl);
945 Reflectivity = Reflectivity_TE + Reflectivity_TM;
946
947 do {
948 if(G4UniformRand()*real(Reflectivity) > real(Reflectivity_TE))iTE = -1;
949 if(G4UniformRand()*real(Reflectivity) > real(Reflectivity_TM))iTM = -1;
950 } while(iTE<0&&iTM<0);
951
952 return real(Reflectivity);
953
954}
Note: See TracBrowser for help on using the repository browser.