All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OpBoundaryProcessSimple.cxx
Go to the documentation of this file.
1 // Adapted for LArSoft by Ben Jones, MIT, March 2010
2 //
3 // This class invokes a simplified model of optical reflections at
4 // boundaries between different materials. The relevant reflectivities
5 // are read in by an implementation of the MaterialPropertiesLoader.
6 //
7 // The required parameters are total reflectance and ratio of diffuse
8 // to specular reflectance. Each photon crossing a boundary with a
9 // defined reflectance is randomly either reflected or absorbed and killed
10 // according to the supplied probability.
11 //
12 // Every reflected photon with a defined diffuse reflection fraction
13 // is then randomly either diffusely or specularly reflected according
14 // to the supplied probability. All materials with no defined
15 // reflectance are assumed to be black and
16 // absorb all incident photons.
17 //
18 // This physics process is loaded in the OpticalPhysics physics constructor.
19 //
20 // This class is based on the G4OpBoundaryProcess class in Geant4
21 
22 //
23 // ********************************************************************
24 // * License and Disclaimer *
25 // * *
26 // * The Geant4 software is copyright of the Copyright Holders of *
27 // * the Geant4 Collaboration. It is provided under the terms and *
28 // * conditions of the Geant4 Software License, included in the file *
29 // * LICENSE and available at http://cern.ch/geant4/license . These *
30 // * include a list of copyright holders. *
31 // * *
32 // * Neither the authors of this software system, nor their employing *
33 // * institutes,nor the agencies providing financial support for this *
34 // * work make any representation or warranty, express or implied, *
35 // * regarding this software system or assume any liability for its *
36 // * use. Please see the license in the file LICENSE and URL above *
37 // * for the full disclaimer and the limitation of liability. *
38 // * *
39 // * This code implementation is the result of the scientific and *
40 // * technical work of the GEANT4 collaboration. *
41 // * By using, copying, modifying or distributing the software (or *
42 // * any work based on the software) you agree to acknowledge its *
43 // * use in resulting scientific publications, and indicate your *
44 // * acceptance of all terms of the Geant4 Software license. *
45 // ********************************************************************
46 //
47 ////////////////////////////////////////////////////////////////////////
48 // Optical Photon Boundary Process Class Implementation
49 ////////////////////////////////////////////////////////////////////////
50 
51 #include "art/Framework/Services/Registry/ServiceHandle.h"
52 
53 #include "Geant4/G4GeometryTolerance.hh"
54 #include "Geant4/G4Navigator.hh"
55 #include "Geant4/G4OpProcessSubType.hh"
56 #include "Geant4/G4RandomTools.hh"
57 #include "Geant4/G4TransportationManager.hh"
58 #include "Geant4/G4ios.hh"
59 
62 
63 //#define G4DEBUG_OPTICAL
64 
65 namespace larg4 {
66 
67  OpBoundaryProcessSimple::OpBoundaryProcessSimple(const G4String& processName, G4ProcessType type)
68  : G4VDiscreteProcess(processName, type)
69  {
70  G4cout << GetProcessName() << " is created " << G4endl;
71 
72  SetProcessSubType(fOpBoundary);
73 
75 
76  fCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
77  }
78 
79  //Action to take after making each step of an optical photon - described in file header.
80 
81  // PostStepDoIt
82  G4VParticleChange*
83  OpBoundaryProcessSimple::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep)
84  {
85 
86  // Note - these have to be loaded here, since this object
87  // is constructed before LArG4, and hence before the
88  // LArG4 parameters are read from config
89 
91  aParticleChange.Initialize(aTrack);
92 
93  G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
94  G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
95 
96  if (pPostStepPoint->GetStepStatus() != fGeomBoundary) {
98  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
99  }
100  if (aTrack.GetStepLength() <= fCarTolerance / 2) {
102  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
103  }
104 
105  G4Material* Material1 = pPreStepPoint->GetMaterial();
106  G4Material* Material2 = pPostStepPoint->GetMaterial();
107 
108  if (Material1 != Material2) {
109 
110  art::ServiceHandle<sim::LArG4Parameters const> lgp;
111 
112  fVerbosity = lgp->OpVerbosity();
113 
114  G4ThreeVector NewMomentum;
115  G4ThreeVector NewPolarization;
116 
117  G4ThreeVector theGlobalNormal;
118  G4ThreeVector theFacetNormal;
119 
120  std::string Material1Name = Material1->GetName();
121  std::string Material2Name = Material2->GetName();
122 
123  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
124  G4double thePhotonMomentum = aParticle->GetTotalMomentum();
125  G4ThreeVector OldMomentum = aParticle->GetMomentumDirection();
126  G4ThreeVector OldPolarization = aParticle->GetPolarization();
127 
128  if (fVerbosity > 9)
129  std::cout << "OpBoundaryProcessSimple Debug: Photon " << aTrack.GetTrackID() << " momentum "
130  << thePhotonMomentum << " Material1 " << Material1Name.c_str() << " Material 2 "
131  << Material2Name.c_str() << std::endl;
132 
133  G4ThreeVector theGlobalPoint = pPostStepPoint->GetPosition();
134 
135  G4Navigator* theNavigator =
136  G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking();
137 
138  G4ThreeVector theLocalPoint =
139  theNavigator->GetGlobalToLocalTransform().TransformPoint(theGlobalPoint);
140 
141  // Normal points back into volume
142  G4bool valid;
143  G4ThreeVector theLocalNormal = theNavigator->GetLocalExitNormal(&valid);
144 
145  if (valid) { theLocalNormal = -theLocalNormal; }
146  else {
147  G4cerr << " OpBoundaryProcessSimple/PostStepDoIt(): "
148  << " The Navigator reports that it returned an invalid normal" << G4endl;
149  }
150 
151  theGlobalNormal = theNavigator->GetLocalToGlobalTransform().TransformAxis(theLocalNormal);
152 
153  if (OldMomentum * theGlobalNormal > 0.0) {
154 #ifdef G4DEBUG_OPTICAL
155  G4cerr << " OpBoundaryProcessSimple/PostStepDoIt(): "
156  << " theGlobalNormal points the wrong direction " << G4endl;
157 #endif
158  theGlobalNormal = -theGlobalNormal;
159  }
160 
161  G4MaterialPropertiesTable* aMaterialPropertiesTable;
162  G4MaterialPropertyVector* Reflectance;
163  G4MaterialPropertyVector* DiffuseReflectanceFraction;
164 
165  aMaterialPropertiesTable = Material1->GetMaterialPropertiesTable();
166 
167  if (aMaterialPropertiesTable) {
168 
169  std::stringstream PropertyName;
170  PropertyName << "REFLECTANCE_" << Material2Name.c_str();
171  Reflectance = aMaterialPropertiesTable->GetProperty(PropertyName.str().c_str());
172 
173  PropertyName.str("");
174  PropertyName << "DIFFUSE_REFLECTANCE_FRACTION_" << Material2Name.c_str();
175  DiffuseReflectanceFraction =
176  aMaterialPropertiesTable->GetProperty(PropertyName.str().c_str());
177 
178  if (Reflectance) {
179  double theReflectance = Reflectance->Value(thePhotonMomentum);
180  if (G4BooleanRand(theReflectance)) {
181  if (DiffuseReflectanceFraction) {
182  double theDiffuseReflectanceFraction =
183  DiffuseReflectanceFraction->Value(thePhotonMomentum);
184  if (G4BooleanRand(theDiffuseReflectanceFraction)) { fTheStatus = SimpleDiffuse; }
185  else {
187  }
188  }
189  else {
191  }
192  }
193  else {
195  }
196  }
197  else {
199  }
200  }
201 
202  // Take action according to track status
203 
204  if (fTheStatus == SimpleDiffuse) {
205  NewMomentum = G4LambertianRand(theGlobalNormal);
206  theFacetNormal = (NewMomentum - OldMomentum).unit();
207  }
208 
209  else if (fTheStatus == SimpleSpecular) {
210  theFacetNormal = theGlobalNormal;
211  G4double PdotN = OldMomentum * theFacetNormal;
212  NewMomentum = OldMomentum - (2. * PdotN) * theFacetNormal;
213  }
214 
216  aParticleChange.ProposeTrackStatus(fStopAndKill);
217  }
218 
219  else if ((fTheStatus == NotAtBoundary) || (fTheStatus == StepTooSmall)) {
220  NewMomentum = OldMomentum;
221  }
222  else
223  aParticleChange.ProposeTrackStatus(fStopAndKill);
224 
225  NewMomentum = NewMomentum.unit();
226  aParticleChange.ProposeMomentumDirection(NewMomentum);
227  }
228  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
229  }
230 
231  // Compulsary method for G4DiscreteProcesses. Serves no actual function here.
232 
233  // GetMeanFreePath
234  G4double
235  OpBoundaryProcessSimple::GetMeanFreePath(const G4Track&, G4double, G4ForceCondition* condition)
236  {
237  *condition = Forced;
238 
239  return DBL_MAX;
240  }
241 }
Store parameters for running LArG4.
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
OpBoundaryProcessSimpleStatus fTheStatus
G4bool G4BooleanRand(const G4double prob) const
G4double GetMeanFreePath(const G4Track &, G4double, G4ForceCondition *condition)
BEGIN_PROLOG could also be cout
OpBoundaryProcessSimple(const G4String &processName="OpBoundary", G4ProcessType type=fOptical)