Geant4  10.02.p01
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 // $Id: G4UCNBoundaryPrcess.cc 69576 2013-05-08 13:48:13Z gcosmo $
27 //
29 // UCN BoundaryProcess Class Implementation
31 //
32 // File: G4UCNBoundaryProcess.cc
33 // Description: Discrete Process -- Boundary Process of UCN
34 // Version: 1.0
35 // Created: 2014-05-12
36 // Author: Peter Gumplinger
37 // adopted from Geant4UCN by Peter Fierlinger (9.9.04) and
38 // Marcin Kuzniak (21.4.06)
39 // 1/v energy dependent absorption cross section
40 // inside materials
41 // Updated: 2007 Extensions for the microroughness model by Stefan Heule
42 //
43 // mail: gum@triumf.ca
44 //
46 
47 #include "G4UCNProcessSubType.hh"
48 
49 
50 #include "G4UCNBoundaryProcess.hh"
52 
53 #include "G4GeometryTolerance.hh"
54 
55 #include "G4StepPoint.hh"
56 #include "G4ParticleDefinition.hh"
57 
59 
62 
63 #include "G4VSensitiveDetector.hh"
64 
65 #include "G4SystemOfUnits.hh"
66 #include "G4PhysicalConstants.hh"
67 
69  G4ProcessType type)
70  : G4VDiscreteProcess(processName, type)
71 {
72 
73  if (verboseLevel > 0) G4cout << GetProcessName() << " is created " << G4endl;
74 
76 
78 
80 
81  neV = 1.0e-9*eV;
82 
85 
86  Material1 = NULL;
87  Material2 = NULL;
88 
91 
94 
96  nAbsorption = nEzero = nFlip = 0;
101  aMRDiffuseTransmit = 0;
102  ftheta_o = fphi_o = 0;
103 }
104 
106 {
107  delete fMessenger;
108 }
109 
112 {
113  aParticleChange.Initialize(aTrack);
115 
116  // Get hyperStep from G4ParallelWorldProcess
117  // NOTE: PostSetpDoIt of this process should be
118  // invoked after G4ParallelWorldProcess!
119 
120  const G4Step* pStep = &aStep;
121 
123 
124  if (hStep) pStep = hStep;
125 
126  G4bool isOnBoundary =
128 
129  if (isOnBoundary) {
130  Material1 = pStep->GetPreStepPoint()->GetMaterial();
131  Material2 = pStep->GetPostStepPoint()->GetMaterial();
132  } else {
135  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
136  }
137 
138  if (aTrack.GetStepLength()<=kCarTolerance/2) {
141  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
142  }
143 
145  GetMaterialPropertiesTable();
147  GetMaterialPropertiesTable();
148 
149  G4String volnam1 = pStep->GetPreStepPoint() ->GetPhysicalVolume()->GetName();
150  G4String volnam2 = pStep->GetPostStepPoint()->GetPhysicalVolume()->GetName();
151 
152  if (verboseLevel > 0) {
153  G4cout << " UCN at Boundary! " << G4endl;
154  G4cout << " vol1: " << volnam1 << ", vol2: " << volnam2 << G4endl;
155  G4cout << " Ekin: " << aTrack.GetKineticEnergy()/neV <<"neV"<< G4endl;
156  G4cout << " MomDir: " << aTrack.GetMomentumDirection() << G4endl;
157  }
158 
159  if (Material1 == Material2) {
162  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
163  }
164 
165  G4ThreeVector theGlobalPoint = pStep->GetPostStepPoint()->GetPosition();
166 
167  G4bool valid;
168  // Use the new method for Exit Normal in global coordinates,
169  // which provides the normal more reliably.
170 
171  // ID of Navigator which limits step
172 
174  std::vector<G4Navigator*>::iterator iNav =
176  GetActiveNavigatorsIterator();
177 
178  G4ThreeVector theGlobalNormal =
179  (iNav[hNavId])->GetGlobalExitNormal(theGlobalPoint,&valid);
180 
181  if (valid) {
182  theGlobalNormal = -theGlobalNormal;
183  }
184  else
185  {
187  ed << " G4UCNBoundaryProcess/PostStepDoIt(): "
188  << " The Navigator reports that it returned an invalid normal"
189  << G4endl;
190  G4Exception("G4UCNBoundaryProcess::PostStepDoIt", "UCNBoun01",
192  "Invalid Surface Normal - Geometry must return valid surface normal");
193  }
194 
195  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
196 
197  G4ThreeVector OldMomentum = aParticle->GetMomentumDirection();
198 
199  if (OldMomentum * theGlobalNormal > 0.0) {
200 #ifdef G4OPTICAL_DEBUG
202  ed << " G4UCNBoundaryProcess/PostStepDoIt(): "
203  << " theGlobalNormal points in a wrong direction. "
204  << G4endl;
205  ed << " The momentum of the photon arriving at interface (oldMomentum)"
206  << " must exit the volume cross in the step. " << G4endl;
207  ed << " So it MUST have dot < 0 with the normal that Exits the new volume (globalNormal)." << G4endl;
208  ed << " >> The dot product of oldMomentum and global Normal is " << OldMomentum*theGlobalNormal << G4endl;
209  ed << " Old Momentum (during step) = " << OldMomentum << G4endl;
210  ed << " Global Normal (Exiting New Vol) = " << theGlobalNormal << G4endl;
211  ed << G4endl;
212  G4Exception("G4UCNBoundaryProcess::PostStepDoIt", "UCNBoun02",
213  EventMustBeAborted, // Or JustWarning to see if it happens repeatedbly on one ray
214  ed,
215  "Invalid Surface Normal - Geometry must return valid surface normal pointing in the right direction");
216 #else
217  theGlobalNormal = -theGlobalNormal;
218 #endif
219  }
220 
221  G4ThreeVector theNeutronMomentum = aTrack.GetMomentum();
222 
223  G4double theMomentumNormal = theNeutronMomentum*theGlobalNormal;
224  G4double theVelocityNormal = aTrack.GetVelocity() *
225  (OldMomentum * theGlobalNormal);
226 
227  G4double Enormal = theMomentumNormal*theMomentumNormal/2./neutron_mass_c2;
228  G4double Energy = aTrack.GetKineticEnergy();
229 
230  G4double FermiPot2 = 0.;
231  G4double pDiffuse = 0.;
232  G4double pSpinFlip = 0.;
233  G4double pUpScatter = 0.;
234 
236  FermiPot2 = aMaterialPropertiesTable2->GetConstProperty("FERMIPOT")*neV;
237  pDiffuse = aMaterialPropertiesTable2->GetConstProperty("DIFFUSION");
238  pSpinFlip = aMaterialPropertiesTable2->GetConstProperty("SPINFLIP");
239  pUpScatter = aMaterialPropertiesTable2->GetConstProperty("LOSS");
240  }
241 
242  G4double FermiPot1 = 0.;
244  FermiPot1 = aMaterialPropertiesTable1->GetConstProperty("FERMIPOT")*neV;
245 
246  G4double FermiPotDiff = FermiPot2 - FermiPot1;
247 
248  if ( verboseLevel > 1 )
249  G4cout << "UCNBoundaryProcess: new FermiPot: " << FermiPot2/neV
250  << "neV, old FermiPot:" << FermiPot1/neV << "neV" << G4endl;
251 
252  // Use microroughness diffuse reflection behavior if activated
253 
255 
256  G4double theta_i = 0.;
257 
259 
260  nNoMPT++;
261  theStatus = NoMPT;
264 
265  } else {
266 
268 
269  nNoMRT++;
270  theStatus = NoMRT;
272 
274  }
275 
276  // Angle theta_in between surface and momentum direction,
277  // Phi_in is defined to be 0
278 
279  theta_i = OldMomentum.angle(-theGlobalNormal);
280 
281  // Checks the MR-conditions
282 
284  ConditionsValid(Energy, FermiPotDiff, theta_i)) {
285 
286  nNoMRCondition++;
289 
291  }
292  }
293 
294  G4double MRpDiffuse = 0.;
295  G4double MRpDiffuseTrans = 0.;
296 
297  // If microroughness is available and active for material in question
298 
300 
301  // Integral probability for non-specular reflection with microroughness
302 
303  MRpDiffuse = aMaterialPropertiesTable2->
304  GetMRIntProbability(theta_i, Energy);
305 
306  // Integral probability for non-specular transmission with microroughness
307 
308  MRpDiffuseTrans = aMaterialPropertiesTable2->
309  GetMRIntTransProbability(theta_i, Energy);
310 
311  if ( verboseLevel > 1 ) {
312  G4cout << "theta: " << theta_i/degree << "degree" << G4endl;
313  G4cout << "Energy: " << Energy/neV << "neV"
314  << ", Enormal: " << Enormal/neV << "neV" << G4endl;
315  G4cout << "FermiPotDiff: " << FermiPotDiff/neV << "neV " << G4endl;
316  G4cout << "Reflection_prob: " << MRpDiffuse
317  << ", Transmission_prob: " << MRpDiffuseTrans << G4endl;
318  }
319  }
320 
321  if (!High(Enormal, FermiPotDiff)) {
322 
323  // Below critical velocity
324 
325  if (verboseLevel > 0) G4cout << "G4UCNBoundaryProcess -> BELOW critical velocity" << G4endl;
326 
327  // Loss on reflection
328 
329  if (Loss(pUpScatter, theVelocityNormal, FermiPotDiff)) {
330 
331  // kill it.
334 
335  nAbsorption++;
338 
339  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
340  }
341 
342  // spinflips
343 
344  if (SpinFlip(pSpinFlip)) {
345  nFlip++;
346  theStatus = Flip;
348 
349  G4ThreeVector NewPolarization = -1. * aParticle->GetPolarization();
350  aParticleChange.ProposePolarization(NewPolarization);
351  }
352 
353  // Reflect from surface
354 
355  G4ThreeVector NewMomentum;
356 
357  // If microroughness is available and active - do non-specular reflection
358 
360  NewMomentum = MRreflect(MRpDiffuse, OldMomentum, theGlobalNormal,
361  Energy, FermiPotDiff);
362  else
363 
364  // Else do it with the Lambert model as implemented by Peter Fierlinger
365 
366  NewMomentum = Reflect(pDiffuse, OldMomentum, theGlobalNormal);
367 
369 
370  } else {
371 
372  // Above critical velocity
373 
374  if (verboseLevel > 0) G4cout << "G4UCNBoundaryProcess -> ABOVE critical velocity" << G4endl;
375 
376  // If it is faster than the criticial velocity,
377  // there is a probability to be still reflected.
378  // This formula is (only) valid for low loss materials
379 
380  // If microroughness available and active, do reflection with it
381 
382  G4ThreeVector NewMomentum;
383 
385 
386  G4double Enew;
387 
388  NewMomentum =
389  MRreflectHigh(MRpDiffuse, MRpDiffuseTrans, 0., OldMomentum,
390  theGlobalNormal, Energy, FermiPotDiff, Enew);
391 
392  if (Enew == 0.) {
395  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
396  } else {
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++;
436 
438  aParticleChange.ProposeMomentumDirection(NewMomentum.unit());
440 
441  if (verboseLevel > 1) {
442  G4cout << "Energy: " << Energy/neV << "neV, Enormal: "
443  << Enormal/neV << "neV, fpdiff " << FermiPotDiff/neV
444  << "neV, Enew " << Enew/neV << "neV" << G4endl;
445  G4cout << "UCNBoundaryProcess: Transmit and set the new Energy "
446  << aParticleChange.GetEnergy()/neV << "neV" << G4endl;
447  }
448  }
449  }
450  }
451 
452  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
453 }
454 
456  G4double ,
458 {
459  *condition = Forced;
460 
461  return DBL_MAX;
462 }
463 
465  G4double theVelocityNormal,
466  G4double FermiPot)
467 {
468  // The surface roughness is not taken into account here.
469  // One could use e.g. ultracold neutrons, R. Golub, p.35,
470  // where mu is increased by roughness parameters sigma and
471  // omega, which are related to the height and the distance of
472  // "disturbances" on the surface
473 
474  G4double vBound = std::sqrt(2.*FermiPot/neutron_mass_c2*c_squared);
475  G4double vRatio = theVelocityNormal/vBound;
476 
477  G4double pLoss = (2*pUpScatter*vRatio)/(std::sqrt(1-(vRatio*vRatio)));
478 
479  // Check, if enhancement for surface roughness should be done
480 
483  const G4double hdm = hbar_Planck*c_squared/neutron_mass_c2;
486 
487  // cf. Golub's book p. 35, eq. 2.103
488 
489  pLoss *= 1+2*b*b*vBound*vBound/
490  (hdm*hdm+0.85*hdm*vBound*w+2*vBound*vBound*w*w);
491  }
492  }
493 
494  return (G4UniformRand() <= std::fabs(pLoss));
495 }
496 
498 {
499  return (G4UniformRand() <= pSpinFlip);
500 }
501 
503 {
504  G4double r = (std::sqrt(Enormal) - std::sqrt(Enormal - FermiPot)) /
505  (std::sqrt(Enormal) + std::sqrt(Enormal - FermiPot));
506 
507  return r*r;
508 }
509 
511  G4ThreeVector OldMomentum,
512  G4ThreeVector Normal)
513 {
514  G4double PdotN = OldMomentum * Normal;
515 
516  G4ThreeVector NewMomentum = OldMomentum - (2.*PdotN)*Normal;
517  NewMomentum.unit();
518 
519  // Reflect diffuse
520 
521  if (NewMomentum == OldMomentum || G4UniformRand() < pDiffuse) {
522 
523  NewMomentum = LDiffRefl(Normal);
524 
528 
529  return NewMomentum;
530  }
531 
532  // Reflect specular
533 
537 
538  return NewMomentum;
539 }
540 
542  G4ThreeVector OldMomentum,
543  G4ThreeVector Normal,
544  G4double Energy,
545  G4double FermiPot)
546 {
547  // Only for Enormal <= VFermi
548 
549  G4ThreeVector NewMomentum;
550 
551  // Checks if the reflection should be non-specular
552 
553  if (G4UniformRand() <= pDiffuse) {
554 
555  // Reflect diffuse
556 
557  // Determines the angles of the non-specular reflection
558 
559  NewMomentum =
560  MRDiffRefl(Normal, Energy, FermiPot, OldMomentum, pDiffuse);
561 
565 
566  return NewMomentum;
567 
568  } else {
569 
570  // Reflect specular
571 
572  G4double PdotN = OldMomentum * Normal;
573 
574  NewMomentum = OldMomentum - (2.*PdotN)*Normal;
575  NewMomentum.unit();
576 
580 
581  return NewMomentum;
582  }
583 }
584 
586  G4double pDiffuseTrans,
587  G4double pLoss,
588  G4ThreeVector OldMomentum,
589  G4ThreeVector Normal,
590  G4double Energy,
591  G4double FermiPot,
592  G4double &Enew)
593 {
594  // Only for Enormal > VFermi
595 
596  G4double costheta = OldMomentum*Normal;
597 
598  G4double Enormal = Energy * (costheta*costheta);
599 
600 // G4double pSpecular = Reflectivity(Enormal,FermiPot)*
601  G4double pSpecular = Reflectivity(FermiPot,Enormal)*
602  (1.-pDiffuse-pDiffuseTrans-pLoss);
603 
604  G4ThreeVector NewMomentum;
605 
606  G4double decide = G4UniformRand();
607 
608  if (decide < pSpecular) {
609 
610  // Reflect specularly
611 
612  G4double PdotN = OldMomentum * Normal;
613  NewMomentum = OldMomentum - (2.*PdotN)*Normal;
614  NewMomentum.unit();
615 
616  Enew = Energy;
617 
621 
622  return NewMomentum;
623  }
624 
625  if (decide < pSpecular + pDiffuse) {
626 
627  // Reflect diffusely
628 
629  // Determines the angles of the non-specular reflection
630 
631  NewMomentum =
632  MRDiffRefl(Normal, Energy, FermiPot, OldMomentum, pDiffuse);
633 
634  if (verboseLevel > 0) G4cout << "Diffuse normal " << Normal
635  << ", " << NewMomentum << G4endl;
636  Enew = Energy;
637 
641 
642  return NewMomentum;
643  }
644 
645  if (decide < pSpecular + pDiffuse + pDiffuseTrans) {
646 
647  // Transmit diffusely
648 
649  // Determines the angles of the non-specular transmission
650 
651  NewMomentum =
652  MRDiffTrans(Normal, Energy, FermiPot, OldMomentum, pDiffuseTrans);
653 
654  Enew = Energy - FermiPot;
655 
659 
660  return NewMomentum;
661  }
662 
663  if (decide < pSpecular + pDiffuse + pDiffuseTrans + pLoss) {
664 
665  // Loss
666 
667  Enew = 0.;
668 
669  nEzero++;
670  theStatus = Ezero;
672 
673  return NewMomentum;
674  }
675 
676  // last case: Refractive transmission
677 
678  Enew = Energy - FermiPot;
679 
680  G4double palt = std::sqrt(2*neutron_mass_c2/c_squared*Energy);
681  G4double produ = OldMomentum * Normal;
682 
683  NewMomentum = palt*OldMomentum-
684  (palt*produ+std::sqrt(palt*palt*produ*produ-2*neutron_mass_c2/
685  c_squared*FermiPot))*Normal;
686 
687  mSnellTransmit++;
690 
691  return NewMomentum.unit();
692 }
693 
695  G4double Energy,
696  G4double FermiPot,
697  G4ThreeVector OldMomentum,
698  G4double pDiffuse)
699 {
700  G4bool accepted = false;
701 
702  G4double theta_o, phi_o;
703 
704  // Polar angle of incidence
705 
706  G4double theta_i = OldMomentum.polarAngle(-Normal);
707 
708  // Azimuthal angle of incidence
709 
710  // G4double phi_i = -OldMomentum.azimAngle(-Normal);
711 
712  // accept-reject method for MR-reflection
713 
714  G4int count = 0;
715  while (!accepted) {
716  theta_o = G4UniformRand()*pi/2;
717  phi_o = G4UniformRand()*pi*2-pi;
718  // Box over distribution is increased by 50% to ensure no value is above
719  if (1.5*G4UniformRand()*
721  GetMRMaxProbability(theta_i, Energy)/pDiffuse <=
723  GetMRProbability(theta_i,Energy,FermiPot,theta_o,phi_o)/pDiffuse)
724 
725  accepted = true;
726 
727  // For the case that the box is nevertheless exceeded
728 
730  GetMRProbability(theta_i, Energy, FermiPot, theta_o, phi_o)/
732  GetMRMaxProbability(theta_i, Energy)) > 1) {
733  G4cout << "MRMax Wahrscheinlichkeitsueberschreitung!" << G4endl;
735  GetMRProbability(theta_i, Energy, FermiPot, theta_o, phi_o)/
737  GetMRMaxProbability(theta_i, Energy)) << G4endl;
739  SetMRMaxProbability(theta_i, Energy,
741  GetMRProbability(theta_i, Energy,
742  FermiPot, theta_o, phi_o));
743  }
744  // Loop checking, 31-Aug-2015, Vladimir Ivanchenko
745  if(++count > 10000) { accepted = true; }
746  }
747 
748  // Creates vector in the local coordinate system of the reflection
749 
750  G4ThreeVector localmomentum;
751  localmomentum.setRThetaPhi(1., theta_o, phi_o);
752 
753  ftheta_o = theta_o;
754  fphi_o = phi_o;
755 
756  // Get coordinate transform matrix
757 
758  G4RotationMatrix TransCoord =
759  GetCoordinateTransformMatrix(Normal, OldMomentum);
760 
761  //transfer to the coordinates of the global system
762 
763  G4ThreeVector momentum = TransCoord*localmomentum;
764 
765  //momentum.rotateUz(Normal);
766 
767  if (momentum * Normal<0) {
768  momentum*=-1;
769  // something has gone wrong...
770  G4cout << "G4UCNBoundaryProcess::MRDiffRefl: !" << G4endl;
771  }
772 
773  return momentum.unit();
774 }
775 
777  G4double Energy,
778  G4double FermiPot,
779  G4ThreeVector OldMomentum,
780  G4double pDiffuseTrans)
781 {
782  G4bool accepted = false;
783 
784  G4double theta_o, phi_o;
785 
786  // Polar angle of incidence
787 
788  G4double theta_i = OldMomentum.polarAngle(-Normal);
789 
790  // azimuthal angle of incidence
791 
792  // G4double phi_i = -OldMomentum.azimAngle(-Normal);
793 
794  G4int count = 0;
795  while (!accepted) {
796  theta_o = G4UniformRand()*pi/2;
797  phi_o = G4UniformRand()*pi*2-pi;
798 
799  // Box over distribution is increased by 50% to ensure no value is above
800 
801  if (1.5*G4UniformRand()*
803  GetMRMaxTransProbability(theta_i, Energy)/pDiffuseTrans <=
805  GetMRTransProbability(theta_i,Energy,FermiPot,theta_o,phi_o)/
806  pDiffuseTrans)
807 
808  accepted=true;
809 
810  // For the case that the box is nevertheless exceeded
811 
813  GetMRTransProbability(theta_i, Energy, FermiPot, theta_o, phi_o)/
815  GetMRMaxTransProbability(theta_i, Energy)) > 1) {
816  G4cout << "MRMaxTrans Wahrscheinlichkeitsueberschreitung!" << G4endl;
818  GetMRTransProbability(theta_i, Energy, FermiPot, theta_o, phi_o)/
820  GetMRMaxTransProbability(theta_i, Energy)) << G4endl;
822  SetMRMaxTransProbability(theta_i, Energy,
824  GetMRTransProbability(theta_i, Energy,
825  FermiPot, theta_o, phi_o));
826  }
827  // Loop checking, 31-Aug-2015, Vladimir Ivanchenko
828  if(++count > 10000) { accepted = true; }
829  }
830 
831  // Creates vector in the local coordinate system of the reflection
832 
833  G4ThreeVector localmomentum;
834  localmomentum.setRThetaPhi(1., pi-theta_o, phi_o);
835 
836  // Get coordinate transform matrix
837 
838  G4RotationMatrix TransCoord =
839  GetCoordinateTransformMatrix(Normal, OldMomentum);
840 
841  // Transfer to the coordinates of the global system
842 
843  G4ThreeVector momentum = TransCoord*localmomentum;
844 
845  if (momentum*Normal<0) {
846  // something has gone wrong...
847  momentum*=-1;
848  G4cout << "G4UCNBoundaryProcess::MRDiffTrans: !" << G4endl;
849  }
850 
851  return momentum.unit();
852 }
853 
855 {
856  return (Energy - FermiPot);
857 }
858 
860 {
861  G4ThreeVector momentum;
862 
863  // cosine distribution - Lambert's law
864 
865  momentum.setRThetaPhi(1., std::acos(std::sqrt(G4UniformRand())), 2.*pi*G4UniformRand());
866  momentum.rotateUz(Normal);
867 
868  if (momentum*Normal < 0) {
869  momentum*=-1;
870  G4cout << "G4UCNBoundaryProcess::LDiffRefl: !" << G4endl;
871  }
872 
873  return momentum.unit();
874 }
875 
878  G4ThreeVector direction)
879 {
880  // Definition of the local coordinate system (c.s. of the reflection)
881 
882  G4ThreeVector es1, es2, es3;
883 
884  // z-Coordinate is the surface normal, has already length 1
885 
886  es3 = Normal;
887 
888  // Perpendicular part of incident direction w.r.t. normal
889  es1 = direction.perpPart(Normal);
890 
891  // Set to unit length: x-Coordinate
892 
893  es1.setMag(1.);
894  es2 = es1;
895 
896  // y-Coordinate is the pi/2-rotation of x-axis around z-axis
897 
898  es2.rotate(90.*degree, es3);
899 
900  // Transformation matrix consists just of the three coordinate vectors
901  // as the global coordinate system is the 'standard' coordinate system
902 
903  G4RotationMatrix matrix(es1, es2, es3);
904 
905  return matrix;
906 }
907 
909 {
910  if ( theStatus == Undefined )
911  G4cout << " *** Undefined *** " << G4endl;
912  if ( theStatus == NotAtBoundary )
913  G4cout << " *** NotAtBoundary *** " << G4endl;
914  if ( theStatus == SameMaterial )
915  G4cout << " *** SameMaterial *** " << G4endl;
916  if ( theStatus == StepTooSmall )
917  G4cout << " *** StepTooSmall *** " << G4endl;
918  if ( theStatus == NoMPT )
919  G4cout << " *** No G4UCNMaterialPropertiesTable *** " << G4endl;
920  if ( theStatus == NoMRT )
921  G4cout << " *** No MicroRoughness Table *** " << G4endl;
922  if ( theStatus == NoMRCondition )
923  G4cout << " *** MicroRoughness Condition not satisfied *** " << G4endl;
924  if ( theStatus == Absorption )
925  G4cout << " *** Loss on Surface *** " << G4endl;
926  if ( theStatus == Ezero )
927  G4cout << " *** Ezero on Surface *** " << G4endl;
928  if ( theStatus == Flip )
929  G4cout << " *** Spin Flip on Surface *** " << G4endl;
930  if ( theStatus == SpecularReflection )
931  G4cout << " *** Specular Reflection *** " << G4endl;
933  G4cout << " *** LambertianR Reflection *** " << G4endl;
935  G4cout << " *** MR Model Diffuse Reflection *** " << G4endl;
936  if ( theStatus == SnellTransmit )
937  G4cout << " *** Snell Transmission *** " << G4endl;
938  if ( theStatus == MRDiffuseTransmit )
939  G4cout << " *** MR Model Diffuse Transmission *** " << G4endl;
940 }
941 
943 {
944  G4cout << "Sum NoMT: "
945  << nNoMPT << G4endl;
946  G4cout << "Sum NoMRT: "
947  << nNoMRT << G4endl;
948  G4cout << "Sum NoMRCondition: "
949  << nNoMRCondition << G4endl;
950  G4cout << "Sum No. E < V Loss: "
951  << nAbsorption << G4endl;
952  G4cout << "Sum No. E > V Ezero: "
953  << nEzero << G4endl;
954  G4cout << "Sum No. E < V SpinFlip: "
955  << nFlip << G4endl;
956  G4cout << "Sum No. E > V Specular Reflection: "
958  G4cout << "Sum No. E < V Specular Reflection: "
960  G4cout << "Sum No. E < V Lambertian Reflection: "
962  G4cout << "Sum No. E > V MR DiffuseReflection: "
964  G4cout << "Sum No. E < V MR DiffuseReflection: "
966  G4cout << "Sum No. E > V SnellTransmit: "
967  << nSnellTransmit << G4endl;
968  G4cout << "Sum No. E > V MR SnellTransmit: "
969  << mSnellTransmit << G4endl;
970  G4cout << "Sum No. E > V DiffuseTransmit: "
972  G4cout << " " << G4endl;
973 }
974 
976 {
977  G4Step aStep = *pStep;
978 
980 
982  if (sd) return sd->Hit(&aStep);
983  else return false;
984 }
G4double condition(const G4ErrorSymMatrix &m)
G4ThreeVector MRDiffTrans(G4ThreeVector, G4double, G4double, G4ThreeVector, G4double)
G4int verboseLevel
Definition: G4VProcess.hh:368
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
CLHEP::Hep3Vector G4ThreeVector
G4double GetVelocity() const
CLHEP::HepRotation G4RotationMatrix
const G4DynamicParticle * GetDynamicParticle() const
G4StepStatus GetStepStatus() const
G4Material * GetMaterial() const
G4RotationMatrix GetCoordinateTransformMatrix(G4ThreeVector, G4ThreeVector)
G4double GetSurfaceTolerance() const
const G4double w[NPOINTSGL]
G4bool High(G4double, G4double)
void ProposePolarization(G4double Px, G4double Py, G4double Pz)
G4UCNBoundaryProcessMessenger * fMessenger
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
G4double Transmit(G4double, G4double)
G4ThreeVector MRDiffRefl(G4ThreeVector, G4double, G4double, G4ThreeVector, G4double)
int G4int
Definition: G4Types.hh:78
void BoundaryProcessVerbose() const
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4StepPoint * GetPreStepPoint() const
G4double GetKineticEnergy() const
#define G4UniformRand()
Definition: Randomize.hh:97
G4GLOB_DLL std::ostream G4cout
G4VPhysicalVolume * GetPhysicalVolume() const
G4UCNBoundaryProcess(const G4String &processName="UCNBoundaryProcess", G4ProcessType type=fUCN)
const G4String & GetName() const
const G4ThreeVector & GetPosition() const
bool G4bool
Definition: G4Types.hh:79
const G4ThreeVector & GetMomentumDirection() const
G4ThreeVector LDiffRefl(G4ThreeVector)
G4bool Hit(G4Step *aStep)
void SetProcessSubType(G4int)
Definition: G4VProcess.hh:432
Definition: G4Step.hh:76
const G4String & GetProcessName() const
Definition: G4VProcess.hh:408
void BoundaryProcessSummary() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
static G4TransportationManager * GetTransportationManager()
G4bool Loss(G4double, G4double, G4double)
G4UCNMaterialPropertiesTable * aMaterialPropertiesTable1
G4ThreeVector MRreflect(G4double, G4ThreeVector, G4ThreeVector, G4double, G4double)
G4ThreeVector GetMomentum() const
virtual void Initialize(const G4Track &)
static const double eV
Definition: G4SIunits.hh:212
const G4ThreeVector & GetMomentumDirection() const
G4bool InvokeSD(const G4Step *step)
static const double pi
Definition: G4SIunits.hh:74
G4double GetMeanFreePath(const G4Track &aTrack, G4double, G4ForceCondition *condition)
G4ThreeVector MRreflectHigh(G4double, G4double, G4double, G4ThreeVector, G4ThreeVector, G4double, G4double, G4double &)
G4StepPoint * GetPostStepPoint() const
void AddTotalEnergyDeposit(G4double value)
const G4ThreeVector & GetPolarization() const
void ProposeEnergy(G4double finalEnergy)
G4ParticleChange aParticleChange
Definition: G4VProcess.hh:289
static const double degree
Definition: G4SIunits.hh:143
G4double GetEnergy() const
#define G4endl
Definition: G4ios.hh:61
G4ThreeVector Reflect(G4double, G4ThreeVector, G4ThreeVector)
G4VSensitiveDetector * GetSensitiveDetector() const
G4UCNMaterialPropertiesTable * aMaterialPropertiesTable2
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
double G4double
Definition: G4Types.hh:76
void ProposeTrackStatus(G4TrackStatus status)
G4UCNBoundaryProcessStatus theStatus
G4ForceCondition
G4Track * GetTrack() const
G4double GetConstProperty(const char *key)
void ProposeVelocity(G4double finalVelocity)
G4double Reflectivity(G4double, G4double)
#define DBL_MAX
Definition: templates.hh:83
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
G4double GetStepLength() const
static G4GeometryTolerance * GetInstance()
static const G4Step * GetHyperStep()
G4ProcessType