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

Last change on this file since 1337 was 1337, checked in by garnier, 15 years ago

tag geant4.9.4 beta 1 + modifs locales

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