Geant4-11
G4OpRayleigh.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//
30// Optical Photon Rayleigh Scattering Class Implementation
32//
33// File: G4OpRayleigh.cc
34// Description: Discrete Process -- Rayleigh scattering of optical
35// photons
36// Version: 1.0
37// Created: 1996-05-31
38// Author: Juliet Armstrong
39// Updated: 2014-10-10 - This version calculates the Rayleigh scattering
40// length for more materials than just Water (although the Water
41// default is kept). To do this the user would need to specify the
42// ISOTHERMAL_COMPRESSIBILITY as a material property and
43// optionally an RS_SCALE_LENGTH (useful for testing). Code comes
44// from Philip Graham (Queen Mary University of London).
45// 2010-06-11 - Fix Bug 207; Thanks to Xin Qian
46// (Kellogg Radiation Lab of Caltech)
47// 2005-07-28 - add G4ProcessType to constructor
48// 2001-10-18 by Peter Gumplinger
49// eliminate unused variable warning on Linux (gcc-2.95.2)
50// 2001-09-18 by mma
51// >numOfMaterials=G4Material::GetNumberOfMaterials() in BuildPhy
52// 2001-01-30 by Peter Gumplinger
53// > allow for positiv and negative CosTheta and force the
54// > new momentum direction to be in the same plane as the
55// > new and old polarization vectors
56// 2001-01-29 by Peter Gumplinger
57// > fix calculation of SinTheta (from CosTheta)
58// 1997-04-09 by Peter Gumplinger
59// > new physics/tracking scheme
60//
62
63#include "G4OpRayleigh.hh"
64#include "G4ios.hh"
66#include "G4SystemOfUnits.hh"
68#include "G4OpProcessSubType.hh"
69
70//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
72 : G4VDiscreteProcess(processName, type)
73{
74 Initialise();
76 thePhysicsTable = nullptr;
77
78 if(verboseLevel > 0)
79 {
80 G4cout << GetProcessName() << " is created " << G4endl;
81 }
82}
83
84//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
86{
87 // VI: inside this PhysicsTable all properties are unique
88 // it is not possible to destroy
90 {
91 delete thePhysicsTable;
92 }
93}
94
95//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
97{
98 Initialise();
99}
100
101//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
103{
104 SetVerboseLevel(G4OpticalParameters::Instance()->GetRayleighVerboseLevel());
105}
106
107//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
109 const G4Step& aStep)
110{
112 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
113
114 if(verboseLevel > 1)
115 {
116 G4cout << "OpRayleigh: Scattering Photon!" << G4endl
117 << "Old Momentum Direction: " << aParticle->GetMomentumDirection()
118 << G4endl << "Old Polarization: " << aParticle->GetPolarization()
119 << G4endl;
120 }
121
122 G4double cosTheta;
123 G4ThreeVector oldMomDir, newMomDir;
124 G4ThreeVector oldPol, newPol;
125 G4double rand;
126 G4double cost, sint, sinphi, cosphi;
127
128 do
129 {
130 // Try to simulate the scattered photon momentum direction
131 // w.r.t. the initial photon momentum direction
132 cost = G4UniformRand();
133 sint = std::sqrt(1. - cost * cost);
134 // consider for the angle 90-180 degrees
135 if(G4UniformRand() < 0.5)
136 cost = -cost;
137
138 // simulate the phi angle
139 rand = twopi * G4UniformRand();
140 sinphi = std::sin(rand);
141 cosphi = std::cos(rand);
142
143 // construct the new momentum direction
144 newMomDir.set(sint * cosphi, sint * sinphi, cost);
145 oldMomDir = aParticle->GetMomentumDirection();
146 newMomDir.rotateUz(oldMomDir);
147
148 // calculate the new polarization direction
149 // The new polarization needs to be in the same plane as the new
150 // momentum direction and the old polarization direction
151 oldPol = aParticle->GetPolarization();
152 newPol = (oldPol - newMomDir.dot(oldPol) * newMomDir).unit();
153
154 // There is a corner case, where the new momentum direction
155 // is the same as old polarization direction:
156 // random generate the azimuthal angle w.r.t. new momentum direction
157 if(newPol.mag() == 0.)
158 {
159 rand = G4UniformRand() * twopi;
160 newPol.set(std::cos(rand), std::sin(rand), 0.);
161 newPol.rotateUz(newMomDir);
162 }
163 else
164 {
165 // There are two directions perpendicular to the new momentum direction
166 if(G4UniformRand() < 0.5)
167 newPol = -newPol;
168 }
169
170 // simulate according to the distribution cos^2(theta)
171 cosTheta = newPol.dot(oldPol);
172 // Loop checking, 13-Aug-2015, Peter Gumplinger
173 } while(std::pow(cosTheta, 2) < G4UniformRand());
174
177
178 if(verboseLevel > 1)
179 {
180 G4cout << "New Polarization: " << newPol << G4endl
181 << "Polarization Change: " << *(aParticleChange.GetPolarization())
182 << G4endl << "New Momentum Direction: " << newMomDir << G4endl
183 << "Momentum Change: " << *(aParticleChange.GetMomentumDirection())
184 << G4endl;
185 }
186
187 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
188}
189
190//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
192{
194 {
195 // thePhysicsTable->clearAndDestroy();
196 delete thePhysicsTable;
197 thePhysicsTable = nullptr;
198 }
199
200 const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
201 const size_t numOfMaterials = G4Material::GetNumberOfMaterials();
202 thePhysicsTable = new G4PhysicsTable(numOfMaterials);
203
204 for(size_t i = 0; i < numOfMaterials; ++i)
205 {
206 G4Material* material = (*theMaterialTable)[i];
207 G4MaterialPropertiesTable* matProp = material->GetMaterialPropertiesTable();
208 G4PhysicsFreeVector* rayleigh = nullptr;
209 if(matProp)
210 {
211 rayleigh = matProp->GetProperty(kRAYLEIGH);
212 if(rayleigh == nullptr)
214 }
215 thePhysicsTable->insertAt(i, rayleigh);
216 }
217}
218
219//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
222{
223 G4PhysicsFreeVector* rayleigh =
224 static_cast<G4PhysicsFreeVector*>(
225 (*thePhysicsTable)(aTrack.GetMaterial()->GetIndex()));
226
227 G4double rsLength = DBL_MAX;
228 if(rayleigh)
229 {
230 rsLength = rayleigh->Value(aTrack.GetDynamicParticle()->GetTotalMomentum(),
232 }
233 return rsLength;
234}
235
236//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
238 const G4Material* material) const
239{
240 G4MaterialPropertiesTable* MPT = material->GetMaterialPropertiesTable();
241
242 // Retrieve the beta_T or isothermal compressibility value. For backwards
243 // compatibility use a constant if the material is "Water". If the material
244 // doesn't have an ISOTHERMAL_COMPRESSIBILITY constant then return
245 G4double betat;
246 if(material->GetName() == "Water")
247 {
248 betat = 7.658e-23 * m3 / MeV;
249 }
251 {
253 }
254 else
255 {
256 return nullptr;
257 }
258
259 // If the material doesn't have a RINDEX property vector then return
261 if(rIndex == nullptr)
262 return nullptr;
263
264 // Retrieve the optional scale factor (scales the scattering length)
265 G4double scaleFactor = 1.0;
267 {
268 scaleFactor = MPT->GetConstProperty(kRS_SCALE_FACTOR);
269 }
270
271 // Retrieve the material temperature. For backwards compatibility use a
272 // constant if the material is "Water"
273 G4double temperature;
274 if(material->GetName() == "Water")
275 {
276 temperature =
277 283.15 * kelvin; // Temperature of water is 10 degrees celsius
278 }
279 else
280 {
281 temperature = material->GetTemperature();
282 }
283
284 G4PhysicsFreeVector* rayleighMFPs = new G4PhysicsFreeVector();
285 // This calculates the meanFreePath via the Einstein-Smoluchowski formula
286 const G4double c1 =
287 scaleFactor * betat * temperature * k_Boltzmann / (6.0 * pi);
288
289 for(size_t uRIndex = 0; uRIndex < rIndex->GetVectorLength(); ++uRIndex)
290 {
291 const G4double energy = rIndex->Energy(uRIndex);
292 const G4double rIndexSquared = (*rIndex)[uRIndex] * (*rIndex)[uRIndex];
293 const G4double xlambda = h_Planck * c_light / energy;
294 const G4double c2 = std::pow(twopi / xlambda, 4);
295 const G4double c3 =
296 std::pow(((rIndexSquared - 1.0) * (rIndexSquared + 2.0) / 3.0), 2);
297
298 const G4double meanFreePath = 1.0 / (c1 * c2 * c3);
299
300 if(verboseLevel > 0)
301 {
302 G4cout << energy << "MeV\t" << meanFreePath << "mm" << G4endl;
303 }
304
305 rayleighMFPs->InsertValues(energy, meanFreePath);
306 }
307
308 return rayleighMFPs;
309}
310
311//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
313{
314 verboseLevel = verbose;
316}
G4ForceCondition
@ kISOTHERMAL_COMPRESSIBILITY
std::vector< G4Material * > G4MaterialTable
@ fOpRayleigh
G4ProcessType
static constexpr double kelvin
Definition: G4SIunits.hh:274
static constexpr double twopi
Definition: G4SIunits.hh:56
static constexpr double m3
Definition: G4SIunits.hh:111
static constexpr double MeV
Definition: G4SIunits.hh:200
static constexpr double pi
Definition: G4SIunits.hh:55
double G4double
Definition: G4Types.hh:83
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
double dot(const Hep3Vector &) const
double mag() const
void set(double x, double y, double z)
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:33
const G4ThreeVector & GetMomentumDirection() const
G4double GetTotalMomentum() const
const G4ThreeVector & GetPolarization() const
G4bool ConstPropertyExists(const G4String &key) const
G4double GetConstProperty(const G4String &key) const
G4MaterialPropertyVector * GetProperty(const char *key) const
static size_t GetNumberOfMaterials()
Definition: G4Material.cc:679
static G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:672
size_t GetIndex() const
Definition: G4Material.hh:256
void SetVerboseLevel(G4int)
G4PhysicsTable * thePhysicsTable
Definition: G4OpRayleigh.hh:88
size_t idx_rslength
Definition: G4OpRayleigh.hh:99
virtual void BuildPhysicsTable(const G4ParticleDefinition &aParticleType) override
virtual G4double GetMeanFreePath(const G4Track &aTrack, G4double, G4ForceCondition *) override
virtual ~G4OpRayleigh()
Definition: G4OpRayleigh.cc:85
G4PhysicsFreeVector * CalculateRayleighMeanFreePaths(const G4Material *material) const
virtual void PreparePhysicsTable(const G4ParticleDefinition &) override
Definition: G4OpRayleigh.cc:96
G4OpRayleigh(const G4String &processName="OpRayleigh", G4ProcessType type=fOptical)
Definition: G4OpRayleigh.cc:71
virtual G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep) override
virtual void Initialise()
void SetRayleighVerboseLevel(G4int)
static G4OpticalParameters * Instance()
void ProposePolarization(G4double Px, G4double Py, G4double Pz)
const G4ThreeVector * GetPolarization() const
const G4ThreeVector * GetMomentumDirection() const
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
virtual void Initialize(const G4Track &)
void InsertValues(const G4double energy, const G4double value)
void insertAt(std::size_t, G4PhysicsVector *)
G4double Energy(const std::size_t index) const
G4double Value(const G4double energy, std::size_t &lastidx) const
std::size_t GetVectorLength() const
Definition: G4Step.hh:62
G4Material * GetMaterial() const
const G4DynamicParticle * GetDynamicParticle() const
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
G4ParticleChange aParticleChange
Definition: G4VProcess.hh:327
G4int verboseLevel
Definition: G4VProcess.hh:356
void SetProcessSubType(G4int)
Definition: G4VProcess.hh:406
const G4String & GetProcessName() const
Definition: G4VProcess.hh:382
G4double energy(const ThreeVector &p, const G4double m)
string material
Definition: eplot.py:19
float c_light
Definition: hepunit.py:256
float k_Boltzmann
Definition: hepunit.py:298
float h_Planck
Definition: hepunit.py:262
#define DBL_MAX
Definition: templates.hh:62