Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4UCNBoundaryProcess.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27///////////////////////////////////////////////////////////////////////
28// UCN BoundaryProcess Class Implementation
29///////////////////////////////////////////////////////////////////////
30//
31// File: G4UCNBoundaryProcess.cc
32// Description: Discrete Process -- Boundary Process of UCN
33// Version: 1.0
34// Created: 2014-05-12
35// Author: Peter Gumplinger
36// adopted from Geant4UCN by Peter Fierlinger (9.9.04) and
37// Marcin Kuzniak (21.4.06)
38// 1/v energy dependent absorption cross section
39// inside materials
40// Updated: 2007 Extensions for the microroughness model by Stefan Heule
41//
42// mail: [email protected]
43//
44///////////////////////////////////////////////////////////////////////
45
47
48
51
53
54#include "G4StepPoint.hh"
56
58
61
63
64#include "G4SystemOfUnits.hh"
66
68 G4ProcessType type)
69 : G4VDiscreteProcess(processName, type)
70{
71
72 if (verboseLevel > 0) G4cout << GetProcessName() << " is created " << G4endl;
73
75
76 theStatus = Undefined;
77
78 fMessenger = new G4UCNBoundaryProcessMessenger(this);
79
80 neV = 1.0e-9*eV;
81
82 kCarTolerance = G4GeometryTolerance::GetInstance()
84
85 Material1 = NULL;
86 Material2 = NULL;
87
88 aMaterialPropertiesTable1 = NULL;
89 aMaterialPropertiesTable2 = NULL;
90
91 UseMicroRoughnessReflection = false;
92 DoMicroRoughnessReflection = false;
93
94 nNoMPT = nNoMRT = nNoMRCondition = 0;
95 nAbsorption = nEzero = nFlip = 0;
96 aSpecularReflection = bSpecularReflection = 0;
97 bLambertianReflection = 0;
98 aMRDiffuseReflection = bMRDiffuseReflection = 0;
99 nSnellTransmit = mSnellTransmit = 0;
100 aMRDiffuseTransmit = 0;
101 ftheta_o = fphi_o = 0;
102}
103
105{
106 delete fMessenger;
107}
108
111{
114
115 // Get hyperStep from G4ParallelWorldProcess
116 // NOTE: PostSetpDoIt of this process should be
117 // invoked after G4ParallelWorldProcess!
118
119 const G4Step* pStep = &aStep;
120
122
123 if (hStep) pStep = hStep;
124
125 G4bool isOnBoundary =
126 (pStep->GetPostStepPoint()->GetStepStatus() == fGeomBoundary);
127
128 if (isOnBoundary) {
129 Material1 = pStep->GetPreStepPoint()->GetMaterial();
130 Material2 = pStep->GetPostStepPoint()->GetMaterial();
131 } else {
132 theStatus = NotAtBoundary;
133 if ( verboseLevel > 1 ) BoundaryProcessVerbose();
134 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
135 }
136
137 if (aTrack.GetStepLength()<=kCarTolerance/2) {
138 theStatus = StepTooSmall;
139 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
140 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
141 }
142
143 aMaterialPropertiesTable1 = (G4UCNMaterialPropertiesTable*)Material1->
144 GetMaterialPropertiesTable();
145 aMaterialPropertiesTable2 = (G4UCNMaterialPropertiesTable*)Material2->
146 GetMaterialPropertiesTable();
147
148 G4String volnam1 = pStep->GetPreStepPoint() ->GetPhysicalVolume()->GetName();
149 G4String volnam2 = pStep->GetPostStepPoint()->GetPhysicalVolume()->GetName();
150
151 if (verboseLevel > 0) {
152 G4cout << " UCN at Boundary! " << G4endl;
153 G4cout << " vol1: " << volnam1 << ", vol2: " << volnam2 << G4endl;
154 G4cout << " Ekin: " << aTrack.GetKineticEnergy()/neV <<"neV"<< G4endl;
155 G4cout << " MomDir: " << aTrack.GetMomentumDirection() << G4endl;
156 }
157
158 if (Material1 == Material2) {
159 theStatus = SameMaterial;
160 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
161 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
162 }
163
164 G4ThreeVector theGlobalPoint = pStep->GetPostStepPoint()->GetPosition();
165
166 G4bool valid;
167 // Use the new method for Exit Normal in global coordinates,
168 // which provides the normal more reliably.
169
170 // ID of Navigator which limits step
171
173 std::vector<G4Navigator*>::iterator iNav =
175 GetActiveNavigatorsIterator();
176
177 G4ThreeVector theGlobalNormal =
178 (iNav[hNavId])->GetGlobalExitNormal(theGlobalPoint,&valid);
179
180 if (valid) {
181 theGlobalNormal = -theGlobalNormal;
182 }
183 else
184 {
186 ed << " G4UCNBoundaryProcess/PostStepDoIt(): "
187 << " The Navigator reports that it returned an invalid normal"
188 << G4endl;
189 G4Exception("G4UCNBoundaryProcess::PostStepDoIt", "UCNBoun01",
191 "Invalid Surface Normal - Geometry must return valid surface normal");
192 }
193
194 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
195
196 G4ThreeVector OldMomentum = aParticle->GetMomentumDirection();
197
198 if (OldMomentum * theGlobalNormal > 0.0) {
199#ifdef G4OPTICAL_DEBUG
201 ed << " G4UCNBoundaryProcess/PostStepDoIt(): "
202 << " theGlobalNormal points in a wrong direction. "
203 << G4endl;
204 ed << " The momentum of the photon arriving at interface (oldMomentum)"
205 << " must exit the volume cross in the step. " << G4endl;
206 ed << " So it MUST have dot < 0 with the normal that Exits the new volume (globalNormal)." << G4endl;
207 ed << " >> The dot product of oldMomentum and global Normal is " << OldMomentum*theGlobalNormal << G4endl;
208 ed << " Old Momentum (during step) = " << OldMomentum << G4endl;
209 ed << " Global Normal (Exiting New Vol) = " << theGlobalNormal << G4endl;
210 ed << G4endl;
211 G4Exception("G4UCNBoundaryProcess::PostStepDoIt", "UCNBoun02",
212 EventMustBeAborted, // Or JustWarning to see if it happens repeatedbly on one ray
213 ed,
214 "Invalid Surface Normal - Geometry must return valid surface normal pointing in the right direction");
215#else
216 theGlobalNormal = -theGlobalNormal;
217#endif
218 }
219
220 G4ThreeVector theNeutronMomentum = aTrack.GetMomentum();
221
222 G4double theMomentumNormal = theNeutronMomentum*theGlobalNormal;
223 G4double theVelocityNormal = aTrack.GetVelocity() *
224 (OldMomentum * theGlobalNormal);
225
226 G4double Enormal = theMomentumNormal*theMomentumNormal/2./neutron_mass_c2;
227 G4double Energy = aTrack.GetKineticEnergy();
228
229 G4double FermiPot2 = 0.;
230 G4double pDiffuse = 0.;
231 G4double pSpinFlip = 0.;
232 G4double pUpScatter = 0.;
233
234 if (aMaterialPropertiesTable2) {
235 FermiPot2 = aMaterialPropertiesTable2->GetConstProperty("FERMIPOT")*neV;
236 pDiffuse = aMaterialPropertiesTable2->GetConstProperty("DIFFUSION");
237 pSpinFlip = aMaterialPropertiesTable2->GetConstProperty("SPINFLIP");
238 pUpScatter = aMaterialPropertiesTable2->GetConstProperty("LOSS");
239 }
240
241 G4double FermiPot1 = 0.;
242 if (aMaterialPropertiesTable1)
243 FermiPot1 = aMaterialPropertiesTable1->GetConstProperty("FERMIPOT")*neV;
244
245 G4double FermiPotDiff = FermiPot2 - FermiPot1;
246
247 if ( verboseLevel > 1 )
248 G4cout << "UCNBoundaryProcess: new FermiPot: " << FermiPot2/neV
249 << "neV, old FermiPot:" << FermiPot1/neV << "neV" << G4endl;
250
251 // Use microroughness diffuse reflection behavior if activated
252
253 DoMicroRoughnessReflection = UseMicroRoughnessReflection;
254
255 G4double theta_i = 0.;
256
257 if (!aMaterialPropertiesTable2) {
258
259 nNoMPT++;
260 theStatus = NoMPT;
261 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
262 DoMicroRoughnessReflection = false;
263
264 } else {
265
266 if (!aMaterialPropertiesTable2->GetMicroRoughnessTable()) {
267
268 nNoMRT++;
269 theStatus = NoMRT;
270 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
271
272 DoMicroRoughnessReflection = false;
273 }
274
275 // Angle theta_in between surface and momentum direction,
276 // Phi_in is defined to be 0
277
278 theta_i = OldMomentum.angle(-theGlobalNormal);
279
280 // Checks the MR-conditions
281
282 if (!aMaterialPropertiesTable2->
283 ConditionsValid(Energy, FermiPotDiff, theta_i)) {
284
285 nNoMRCondition++;
286 theStatus = NoMRCondition;
287 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
288
289 DoMicroRoughnessReflection = false;
290 }
291 }
292
293 G4double MRpDiffuse = 0.;
294 G4double MRpDiffuseTrans = 0.;
295
296 // If microroughness is available and active for material in question
297
298 if (DoMicroRoughnessReflection) {
299
300 // Integral probability for non-specular reflection with microroughness
301
302 MRpDiffuse = aMaterialPropertiesTable2->
303 GetMRIntProbability(theta_i, Energy);
304
305 // Integral probability for non-specular transmission with microroughness
306
307 MRpDiffuseTrans = aMaterialPropertiesTable2->
308 GetMRIntTransProbability(theta_i, Energy);
309
310 if ( verboseLevel > 1 ) {
311 G4cout << "theta: " << theta_i/degree << "degree" << G4endl;
312 G4cout << "Energy: " << Energy/neV << "neV"
313 << ", Enormal: " << Enormal/neV << "neV" << G4endl;
314 G4cout << "FermiPotDiff: " << FermiPotDiff/neV << "neV " << G4endl;
315 G4cout << "Reflection_prob: " << MRpDiffuse
316 << ", Transmission_prob: " << MRpDiffuseTrans << G4endl;
317 }
318 }
319
320 if (!High(Enormal, FermiPotDiff)) {
321
322 // Below critical velocity
323
324 if (verboseLevel > 0) G4cout << "G4UCNBoundaryProcess -> BELOW critical velocity" << G4endl;
325
326 // Loss on reflection
327
328 if (Loss(pUpScatter, theVelocityNormal, FermiPotDiff)) {
329
330 // kill it.
333
334 nAbsorption++;
335 theStatus = Absorption;
336 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
337
338 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
339 }
340
341 // spinflips
342
343 if (SpinFlip(pSpinFlip)) {
344 nFlip++;
345 theStatus = Flip;
346 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
347
348 G4ThreeVector NewPolarization = -1. * aParticle->GetPolarization();
349 aParticleChange.ProposePolarization(NewPolarization);
350 }
351
352 // Reflect from surface
353
354 G4ThreeVector NewMomentum;
355
356 // If microroughness is available and active - do non-specular reflection
357
358 if (DoMicroRoughnessReflection)
359 NewMomentum = MRreflect(MRpDiffuse, OldMomentum, theGlobalNormal,
360 Energy, FermiPotDiff);
361 else
362
363 // Else do it with the Lambert model as implemented by Peter Fierlinger
364
365 NewMomentum = Reflect(pDiffuse, OldMomentum, theGlobalNormal);
366
368
369 } else {
370
371 // Above critical velocity
372
373 if (verboseLevel > 0) G4cout << "G4UCNBoundaryProcess -> ABOVE critical velocity" << G4endl;
374
375 // If it is faster than the criticial velocity,
376 // there is a probability to be still reflected.
377 // This formula is (only) valid for low loss materials
378
379 // If microroughness available and active, do reflection with it
380
381 G4ThreeVector NewMomentum;
382
383 if (DoMicroRoughnessReflection) {
384
385 G4double Enew;
386
387 NewMomentum =
388 MRreflectHigh(MRpDiffuse, MRpDiffuseTrans, 0., OldMomentum,
389 theGlobalNormal, Energy, FermiPotDiff, Enew);
390
391 if (Enew == 0.) {
394 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
395 } else {
398 aParticleChange.ProposeVelocity(std::sqrt(2*Enew/neutron_mass_c2)*c_light);
400 }
401
402 } else {
403
404 G4double reflectivity = Reflectivity(FermiPotDiff, Enormal);
405
406 if ( verboseLevel > 1 ) G4cout << "UCNBoundaryProcess: reflectivity "
407 << reflectivity << G4endl;
408
409 if (G4UniformRand() < reflectivity) {
410
411 // Reflect from surface
412
413 NewMomentum = Reflect(pDiffuse, OldMomentum, theGlobalNormal);
415
416 } else {
417
418 // --- Transmission because it is faster than the critical velocity
419
420 G4double Enew = Transmit(FermiPotDiff, Energy);
421
422 // --- Change of the normal momentum component
423 // p = sqrt(2*m*Ekin)
424
425 G4double mass = -std::sqrt(theMomentumNormal*theMomentumNormal -
426 neutron_mass_c2*2.*FermiPotDiff);
427
428 // --- Momentum direction in new media
429
430 NewMomentum =
431 theNeutronMomentum - (theMomentumNormal-mass)*theGlobalNormal;
432
433 nSnellTransmit++;
434 theStatus = SnellTransmit;
435 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
436
439 aParticleChange.ProposeVelocity(std::sqrt(2*Enew/neutron_mass_c2)*c_light);
441
442 if (verboseLevel > 1) {
443 G4cout << "Energy: " << Energy/neV << "neV, Enormal: "
444 << Enormal/neV << "neV, fpdiff " << FermiPotDiff/neV
445 << "neV, Enew " << Enew/neV << "neV" << G4endl;
446 G4cout << "UCNBoundaryProcess: Transmit and set the new Energy "
447 << aParticleChange.GetEnergy()/neV << "neV" << G4endl;
448 }
449 }
450 }
451 }
452
453 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
454}
455
464
465G4bool G4UCNBoundaryProcess::Loss(G4double pUpScatter,
466 G4double theVelocityNormal,
467 G4double FermiPot)
468{
469 // The surface roughness is not taken into account here.
470 // One could use e.g. ultracold neutrons, R. Golub, p.35,
471 // where mu is increased by roughness parameters sigma and
472 // omega, which are related to the height and the distance of
473 // "disturbances" on the surface
474
475 G4double vBound = std::sqrt(2.*FermiPot/neutron_mass_c2*c_squared);
476 G4double vRatio = theVelocityNormal/vBound;
477
478 G4double pLoss = (2*pUpScatter*vRatio)/(std::sqrt(1-(vRatio*vRatio)));
479
480 // Check, if enhancement for surface roughness should be done
481
482 if (DoMicroRoughnessReflection) {
483 if (aMaterialPropertiesTable2) {
484 const G4double hdm = hbar_Planck*c_squared/neutron_mass_c2;
485 G4double b = aMaterialPropertiesTable2->GetRMS();
486 G4double w = aMaterialPropertiesTable2->GetCorrLen();
487
488 // cf. Golub's book p. 35, eq. 2.103
489
490 pLoss *= std::sqrt(1+2*b*b*vBound*vBound/
491 (hdm*hdm+0.85*hdm*vBound*w+2*vBound*vBound*w*w));
492 }
493 }
494
495 return (G4UniformRand() <= std::fabs(pLoss));
496}
497
498G4bool G4UCNBoundaryProcess::SpinFlip(G4double pSpinFlip)
499{
500 return (G4UniformRand() <= pSpinFlip);
501}
502
503G4double G4UCNBoundaryProcess::Reflectivity(G4double FermiPot, G4double Enormal)
504{
505 G4double r = (std::sqrt(Enormal) - std::sqrt(Enormal - FermiPot)) /
506 (std::sqrt(Enormal) + std::sqrt(Enormal - FermiPot));
507
508 return r*r;
509}
510
511G4ThreeVector G4UCNBoundaryProcess::Reflect(G4double pDiffuse,
512 G4ThreeVector OldMomentum,
513 G4ThreeVector Normal)
514{
515 G4double PdotN = OldMomentum * Normal;
516
517 G4ThreeVector NewMomentum = OldMomentum - (2.*PdotN)*Normal;
518 NewMomentum.unit();
519
520 // Reflect diffuse
521
522 if (NewMomentum == OldMomentum || G4UniformRand() < pDiffuse) {
523
524 NewMomentum = LDiffRefl(Normal);
525
526 bLambertianReflection++;
527 theStatus = LambertianReflection;
528 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
529
530 return NewMomentum;
531 }
532
533 // Reflect specular
534
535 bSpecularReflection++;
536 theStatus = SpecularReflection;
537 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
538
539 return NewMomentum;
540}
541
543 G4ThreeVector OldMomentum,
544 G4ThreeVector Normal,
545 G4double Energy,
546 G4double FermiPot)
547{
548 // Only for Enormal <= VFermi
549
550 G4ThreeVector NewMomentum;
551
552 // Checks if the reflection should be non-specular
553
554 if (G4UniformRand() <= pDiffuse) {
555
556 // Reflect diffuse
557
558 // Determines the angles of the non-specular reflection
559
560 NewMomentum =
561 MRDiffRefl(Normal, Energy, FermiPot, OldMomentum, pDiffuse);
562
563 bMRDiffuseReflection++;
564 theStatus = MRDiffuseReflection;
565 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
566
567 return NewMomentum;
568
569 } else {
570
571 // Reflect specular
572
573 G4double PdotN = OldMomentum * Normal;
574
575 NewMomentum = OldMomentum - (2.*PdotN)*Normal;
576 NewMomentum.unit();
577
578 bSpecularReflection++;
579 theStatus = SpecularReflection;
580 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
581
582 return NewMomentum;
583 }
584}
585
587 G4double pDiffuseTrans,
588 G4double pLoss,
589 G4ThreeVector OldMomentum,
590 G4ThreeVector Normal,
591 G4double Energy,
592 G4double FermiPot,
593 G4double &Enew)
594{
595 // Only for Enormal > VFermi
596
597 G4double costheta = OldMomentum*Normal;
598
599 G4double Enormal = Energy * (costheta*costheta);
600
601// G4double pSpecular = Reflectivity(Enormal,FermiPot)*
602 G4double pSpecular = Reflectivity(FermiPot,Enormal)*
603 (1.-pDiffuse-pDiffuseTrans-pLoss);
604
605 G4ThreeVector NewMomentum;
606
607 G4double decide = G4UniformRand();
608
609 if (decide < pSpecular) {
610
611 // Reflect specularly
612
613 G4double PdotN = OldMomentum * Normal;
614 NewMomentum = OldMomentum - (2.*PdotN)*Normal;
615 NewMomentum.unit();
616
617 Enew = Energy;
618
619 aSpecularReflection++;
620 theStatus = SpecularReflection;
621 if ( verboseLevel ) BoundaryProcessVerbose();
622
623 return NewMomentum;
624 }
625
626 if (decide < pSpecular + pDiffuse) {
627
628 // Reflect diffusely
629
630 // Determines the angles of the non-specular reflection
631
632 NewMomentum =
633 MRDiffRefl(Normal, Energy, FermiPot, OldMomentum, pDiffuse);
634
635 if (verboseLevel > 0) G4cout << "Diffuse normal " << Normal
636 << ", " << NewMomentum << G4endl;
637 Enew = Energy;
638
639 aMRDiffuseReflection++;
640 theStatus = MRDiffuseReflection;
641 if ( verboseLevel ) BoundaryProcessVerbose();
642
643 return NewMomentum;
644 }
645
646 if (decide < pSpecular + pDiffuse + pDiffuseTrans) {
647
648 // Transmit diffusely
649
650 // Determines the angles of the non-specular transmission
651
652 NewMomentum =
653 MRDiffTrans(Normal, Energy, FermiPot, OldMomentum, pDiffuseTrans);
654
655 Enew = Energy - FermiPot;
656
657 aMRDiffuseTransmit++;
658 theStatus = MRDiffuseTransmit;
659 if ( verboseLevel ) BoundaryProcessVerbose();
660
661 return NewMomentum;
662 }
663
664 if (decide < pSpecular + pDiffuse + pDiffuseTrans + pLoss) {
665
666 // Loss
667
668 Enew = 0.;
669
670 nEzero++;
671 theStatus = Ezero;
672 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
673
674 return NewMomentum;
675 }
676
677 // last case: Refractive transmission
678
679 Enew = Energy - FermiPot;
680
681 G4double palt = std::sqrt(2*neutron_mass_c2/c_squared*Energy);
682 G4double produ = OldMomentum * Normal;
683
684 NewMomentum = palt*OldMomentum-
685 (palt*produ+std::sqrt(palt*palt*produ*produ-2*neutron_mass_c2/
686 c_squared*FermiPot))*Normal;
687
688 mSnellTransmit++;
689 theStatus = SnellTransmit;
690 if ( verboseLevel > 0 ) BoundaryProcessVerbose();
691
692 return NewMomentum.unit();
693}
694
695G4ThreeVector G4UCNBoundaryProcess::MRDiffRefl(G4ThreeVector Normal,
696 G4double Energy,
697 G4double FermiPot,
698 G4ThreeVector OldMomentum,
699 G4double pDiffuse)
700{
701 G4bool accepted = false;
702
703 G4double theta_o, phi_o;
704
705 // Polar angle of incidence
706
707 G4double theta_i = OldMomentum.polarAngle(-Normal);
708
709 // Azimuthal angle of incidence
710
711 // G4double phi_i = -OldMomentum.azimAngle(-Normal);
712
713 // accept-reject method for MR-reflection
714
715 G4int count = 0;
716 while (!accepted) {
717 theta_o = G4UniformRand()*pi/2;
718 phi_o = G4UniformRand()*pi*2-pi;
719 // Box over distribution is increased by 50% to ensure no value is above
720 if (1.5*G4UniformRand()*
721 aMaterialPropertiesTable2->
722 GetMRMaxProbability(theta_i, Energy)/pDiffuse <=
723 aMaterialPropertiesTable2->
724 GetMRProbability(theta_i,Energy,FermiPot,theta_o,phi_o)/pDiffuse)
725
726 accepted = true;
727
728 // For the case that the box is nevertheless exceeded
729
730 if (aMaterialPropertiesTable2->
731 GetMRProbability(theta_i, Energy, FermiPot, theta_o, phi_o)/
732 (1.5*aMaterialPropertiesTable2->
733 GetMRMaxProbability(theta_i, Energy)) > 1) {
734 G4cout << "MRMax Wahrscheinlichkeitsueberschreitung!" << G4endl;
735 G4cout << aMaterialPropertiesTable2->
736 GetMRProbability(theta_i, Energy, FermiPot, theta_o, phi_o)/
737 (1.5*aMaterialPropertiesTable2->
738 GetMRMaxProbability(theta_i, Energy)) << G4endl;
739 aMaterialPropertiesTable2->
740 SetMRMaxProbability(theta_i, Energy,
741 aMaterialPropertiesTable2->
742 GetMRProbability(theta_i, Energy,
743 FermiPot, theta_o, phi_o));
744 }
745 // Loop checking, 31-Aug-2015, Vladimir Ivanchenko
746 if(++count > 10000) { accepted = true; }
747 }
748
749 // Creates vector in the local coordinate system of the reflection
750
751 G4ThreeVector localmomentum;
752 localmomentum.setRThetaPhi(1., theta_o, phi_o);
753
754 ftheta_o = theta_o;
755 fphi_o = phi_o;
756
757 // Get coordinate transform matrix
758
759 G4RotationMatrix TransCoord =
760 GetCoordinateTransformMatrix(Normal, OldMomentum);
761
762 //transfer to the coordinates of the global system
763
764 G4ThreeVector momentum = TransCoord*localmomentum;
765
766 //momentum.rotateUz(Normal);
767
768 if (momentum * Normal<0) {
769 momentum*=-1;
770 // something has gone wrong...
771 G4cout << "G4UCNBoundaryProcess::MRDiffRefl: !" << G4endl;
772 }
773
774 return momentum.unit();
775}
776
777G4ThreeVector G4UCNBoundaryProcess::MRDiffTrans(G4ThreeVector Normal,
778 G4double Energy,
779 G4double FermiPot,
780 G4ThreeVector OldMomentum,
781 G4double pDiffuseTrans)
782{
783 G4bool accepted = false;
784
785 G4double theta_o, phi_o;
786
787 // Polar angle of incidence
788
789 G4double theta_i = OldMomentum.polarAngle(-Normal);
790
791 // azimuthal angle of incidence
792
793 // G4double phi_i = -OldMomentum.azimAngle(-Normal);
794
795 G4int count = 0;
796 while (!accepted) {
797 theta_o = G4UniformRand()*pi/2;
798 phi_o = G4UniformRand()*pi*2-pi;
799
800 // Box over distribution is increased by 50% to ensure no value is above
801
802 if (1.5*G4UniformRand()*
803 aMaterialPropertiesTable2->
804 GetMRMaxTransProbability(theta_i, Energy)/pDiffuseTrans <=
805 aMaterialPropertiesTable2->
806 GetMRTransProbability(theta_i,Energy,FermiPot,theta_o,phi_o)/
807 pDiffuseTrans)
808
809 accepted=true;
810
811 // For the case that the box is nevertheless exceeded
812
813 if(aMaterialPropertiesTable2->
814 GetMRTransProbability(theta_i, Energy, FermiPot, theta_o, phi_o)/
815 (1.5*aMaterialPropertiesTable2->
816 GetMRMaxTransProbability(theta_i, Energy)) > 1) {
817 G4cout << "MRMaxTrans Wahrscheinlichkeitsueberschreitung!" << G4endl;
818 G4cout << aMaterialPropertiesTable2->
819 GetMRTransProbability(theta_i, Energy, FermiPot, theta_o, phi_o)/
820 (1.5*aMaterialPropertiesTable2->
821 GetMRMaxTransProbability(theta_i, Energy)) << G4endl;
822 aMaterialPropertiesTable2->
823 SetMRMaxTransProbability(theta_i, Energy,
824 aMaterialPropertiesTable2->
825 GetMRTransProbability(theta_i, Energy,
826 FermiPot, theta_o, phi_o));
827 }
828 // Loop checking, 31-Aug-2015, Vladimir Ivanchenko
829 if(++count > 10000) { accepted = true; }
830 }
831
832 // Creates vector in the local coordinate system of the reflection
833
834 G4ThreeVector localmomentum;
835 localmomentum.setRThetaPhi(1., pi-theta_o, phi_o);
836
837 // Get coordinate transform matrix
838
839 G4RotationMatrix TransCoord =
840 GetCoordinateTransformMatrix(Normal, OldMomentum);
841
842 // Transfer to the coordinates of the global system
843
844 G4ThreeVector momentum = TransCoord*localmomentum;
845
846 if (momentum*Normal<0) {
847 // something has gone wrong...
848 momentum*=-1;
849 G4cout << "G4UCNBoundaryProcess::MRDiffTrans: !" << G4endl;
850 }
851
852 return momentum.unit();
853}
854
855G4double G4UCNBoundaryProcess::Transmit(G4double FermiPot, G4double Energy)
856{
857 return (Energy - FermiPot);
858}
859
860G4ThreeVector G4UCNBoundaryProcess::LDiffRefl(G4ThreeVector Normal)
861{
862 G4ThreeVector momentum;
863
864 // cosine distribution - Lambert's law
865
866 momentum.setRThetaPhi(1., std::acos(std::sqrt(G4UniformRand())), 2.*pi*G4UniformRand());
867 momentum.rotateUz(Normal);
868
869 if (momentum*Normal < 0) {
870 momentum*=-1;
871 G4cout << "G4UCNBoundaryProcess::LDiffRefl: !" << G4endl;
872 }
873
874 return momentum.unit();
875}
876
877G4RotationMatrix G4UCNBoundaryProcess::
878 GetCoordinateTransformMatrix(G4ThreeVector Normal,
879 G4ThreeVector direction)
880{
881 // Definition of the local coordinate system (c.s. of the reflection)
882
883 G4ThreeVector es1, es2, es3;
884
885 // z-Coordinate is the surface normal, has already length 1
886
887 es3 = Normal;
888
889 // Perpendicular part of incident direction w.r.t. normal
890 es1 = direction.perpPart(Normal);
891
892 // Set to unit length: x-Coordinate
893
894 es1.setMag(1.);
895 es2 = es1;
896
897 // y-Coordinate is the pi/2-rotation of x-axis around z-axis
898
899 es2.rotate(90.*degree, es3);
900
901 // Transformation matrix consists just of the three coordinate vectors
902 // as the global coordinate system is the 'standard' coordinate system
903
904 G4RotationMatrix matrix(es1, es2, es3);
905
906 return matrix;
907}
908
909void G4UCNBoundaryProcess::BoundaryProcessVerbose() const
910{
911 if ( theStatus == Undefined )
912 G4cout << " *** Undefined *** " << G4endl;
913 if ( theStatus == NotAtBoundary )
914 G4cout << " *** NotAtBoundary *** " << G4endl;
915 if ( theStatus == SameMaterial )
916 G4cout << " *** SameMaterial *** " << G4endl;
917 if ( theStatus == StepTooSmall )
918 G4cout << " *** StepTooSmall *** " << G4endl;
919 if ( theStatus == NoMPT )
920 G4cout << " *** No G4UCNMaterialPropertiesTable *** " << G4endl;
921 if ( theStatus == NoMRT )
922 G4cout << " *** No MicroRoughness Table *** " << G4endl;
923 if ( theStatus == NoMRCondition )
924 G4cout << " *** MicroRoughness Condition not satisfied *** " << G4endl;
925 if ( theStatus == Absorption )
926 G4cout << " *** Loss on Surface *** " << G4endl;
927 if ( theStatus == Ezero )
928 G4cout << " *** Ezero on Surface *** " << G4endl;
929 if ( theStatus == Flip )
930 G4cout << " *** Spin Flip on Surface *** " << G4endl;
931 if ( theStatus == SpecularReflection )
932 G4cout << " *** Specular Reflection *** " << G4endl;
933 if ( theStatus == LambertianReflection )
934 G4cout << " *** LambertianR Reflection *** " << G4endl;
935 if ( theStatus == MRDiffuseReflection )
936 G4cout << " *** MR Model Diffuse Reflection *** " << G4endl;
937 if ( theStatus == SnellTransmit )
938 G4cout << " *** Snell Transmission *** " << G4endl;
939 if ( theStatus == MRDiffuseTransmit )
940 G4cout << " *** MR Model Diffuse Transmission *** " << G4endl;
941}
942
944{
945 G4cout << "Sum NoMT: "
946 << nNoMPT << G4endl;
947 G4cout << "Sum NoMRT: "
948 << nNoMRT << G4endl;
949 G4cout << "Sum NoMRCondition: "
950 << nNoMRCondition << G4endl;
951 G4cout << "Sum No. E < V Loss: "
952 << nAbsorption << G4endl;
953 G4cout << "Sum No. E > V Ezero: "
954 << nEzero << G4endl;
955 G4cout << "Sum No. E < V SpinFlip: "
956 << nFlip << G4endl;
957 G4cout << "Sum No. E > V Specular Reflection: "
958 << aSpecularReflection << G4endl;
959 G4cout << "Sum No. E < V Specular Reflection: "
960 << bSpecularReflection << G4endl;
961 G4cout << "Sum No. E < V Lambertian Reflection: "
962 << bLambertianReflection << G4endl;
963 G4cout << "Sum No. E > V MR DiffuseReflection: "
964 << aMRDiffuseReflection << G4endl;
965 G4cout << "Sum No. E < V MR DiffuseReflection: "
966 << bMRDiffuseReflection << G4endl;
967 G4cout << "Sum No. E > V SnellTransmit: "
968 << nSnellTransmit << G4endl;
969 G4cout << "Sum No. E > V MR SnellTransmit: "
970 << mSnellTransmit << G4endl;
971 G4cout << "Sum No. E > V DiffuseTransmit: "
972 << aMRDiffuseTransmit << G4endl;
973 G4cout << " " << G4endl;
974}
975
976G4bool G4UCNBoundaryProcess::InvokeSD(const G4Step* pStep)
977{
978 G4Step aStep = *pStep;
979
981
983 if (sd) return sd->Hit(&aStep);
984 else return false;
985}
G4double condition(const G4ErrorSymMatrix &m)
@ EventMustBeAborted
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4ForceCondition
@ Forced
G4ProcessType
@ fGeomBoundary
@ fStopAndKill
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
@ NotAtBoundary
@ NoMRCondition
@ SnellTransmit
@ MRDiffuseReflection
@ SpecularReflection
@ MRDiffuseTransmit
@ LambertianReflection
@ fUCNBoundary
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
Hep3Vector unit() const
void setRThetaPhi(double r, double theta, double phi)
double angle(const Hep3Vector &) const
Hep3Vector perpPart() const
void setMag(double)
Hep3Vector & rotateUz(const Hep3Vector &)
Hep3Vector & rotate(double, const Hep3Vector &)
double polarAngle(const Hep3Vector &v2) const
const G4ThreeVector & GetMomentumDirection() const
const G4ThreeVector & GetPolarization() const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetConstProperty(const G4String &key) const
static const G4Step * GetHyperStep()
void ProposePolarization(G4double Px, G4double Py, G4double Pz)
G4double GetEnergy() const
void Initialize(const G4Track &) override
void ProposeVelocity(G4double finalVelocity)
void ProposeEnergy(G4double finalEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
G4Material * GetMaterial() const
const G4ThreeVector & GetPosition() const
G4VSensitiveDetector * GetSensitiveDetector() const
G4VPhysicalVolume * GetPhysicalVolume() const
G4Track * GetTrack() const
void AddTotalEnergyDeposit(G4double value)
G4StepPoint * GetPreStepPoint() const
G4StepPoint * GetPostStepPoint() const
G4double GetVelocity() const
G4ThreeVector GetMomentum() const
const G4DynamicParticle * GetDynamicParticle() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
G4double GetStepLength() const
static G4TransportationManager * GetTransportationManager()
G4double GetMeanFreePath(const G4Track &aTrack, G4double, G4ForceCondition *condition)
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
G4ThreeVector MRreflectHigh(G4double, G4double, G4double, G4ThreeVector, G4ThreeVector, G4double, G4double, G4double &)
G4UCNBoundaryProcess(const G4String &processName="UCNBoundaryProcess", G4ProcessType type=fUCN)
G4ThreeVector MRreflect(G4double, G4ThreeVector, G4ThreeVector, G4double, G4double)
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
const G4String & GetName() const
G4ParticleChange aParticleChange
G4int verboseLevel
void SetProcessSubType(G4int)
const G4String & GetProcessName() const
G4bool Hit(G4Step *aStep)
#define DBL_MAX
Definition templates.hh:62