Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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// $Id$
28//
29//
30////////////////////////////////////////////////////////////////////////
31// Optical Photon Rayleigh Scattering Class Implementation
32////////////////////////////////////////////////////////////////////////
33//
34// File: G4OpRayleigh.cc
35// Description: Discrete Process -- Rayleigh scattering of optical
36// photons
37// Version: 1.0
38// Created: 1996-05-31
39// Author: Juliet Armstrong
40// Updated: 2010-06-11 - Fix Bug 207; Thanks to Xin Qian
41// (Kellogg Radiation Lab of Caltech)
42// 2005-07-28 - add G4ProcessType to constructor
43// 2001-10-18 by Peter Gumplinger
44// eliminate unused variable warning on Linux (gcc-2.95.2)
45// 2001-09-18 by mma
46// >numOfMaterials=G4Material::GetNumberOfMaterials() in BuildPhy
47// 2001-01-30 by Peter Gumplinger
48// > allow for positiv and negative CosTheta and force the
49// > new momentum direction to be in the same plane as the
50// > new and old polarization vectors
51// 2001-01-29 by Peter Gumplinger
52// > fix calculation of SinTheta (from CosTheta)
53// 1997-04-09 by Peter Gumplinger
54// > new physics/tracking scheme
55// mail: gum@triumf.ca
56//
57////////////////////////////////////////////////////////////////////////
58
59#include "G4OpRayleigh.hh"
60
61#include "G4ios.hh"
63#include "G4SystemOfUnits.hh"
64#include "G4OpProcessSubType.hh"
65
66/////////////////////////
67// Class Implementation
68/////////////////////////
69
70 //////////////
71 // Operators
72 //////////////
73
74// G4OpRayleigh::operator=(const G4OpRayleigh &right)
75// {
76// }
77
78 /////////////////
79 // Constructors
80 /////////////////
81
83 : G4VDiscreteProcess(processName, type)
84{
86
88
89 DefaultWater = false;
90
91 if (verboseLevel>0) {
92 G4cout << GetProcessName() << " is created " << G4endl;
93 }
94
95 BuildThePhysicsTable();
96}
97
98// G4OpRayleigh::G4OpRayleigh(const G4OpRayleigh &right)
99// {
100// }
101
102 ////////////////
103 // Destructors
104 ////////////////
105
107{
108 if (thePhysicsTable!= 0) {
110 delete thePhysicsTable;
111 }
112}
113
114 ////////////
115 // Methods
116 ////////////
117
118// PostStepDoIt
119// -------------
120//
122G4OpRayleigh::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep)
123{
125
126 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
127
128 if (verboseLevel>0) {
129 G4cout << "Scattering Photon!" << G4endl;
130 G4cout << "Old Momentum Direction: "
131 << aParticle->GetMomentumDirection() << G4endl;
132 G4cout << "Old Polarization: "
133 << aParticle->GetPolarization() << G4endl;
134 }
135
136 G4double cosTheta;
137 G4ThreeVector OldMomentumDirection, NewMomentumDirection;
138 G4ThreeVector OldPolarization, NewPolarization;
139
140 do {
141 // Try to simulate the scattered photon momentum direction
142 // w.r.t. the initial photon momentum direction
143
144 G4double CosTheta = G4UniformRand();
145 G4double SinTheta = std::sqrt(1.-CosTheta*CosTheta);
146 // consider for the angle 90-180 degrees
147 if (G4UniformRand() < 0.5) CosTheta = -CosTheta;
148
149 // simulate the phi angle
150 G4double rand = twopi*G4UniformRand();
151 G4double SinPhi = std::sin(rand);
152 G4double CosPhi = std::cos(rand);
153
154 // start constructing the new momentum direction
155 G4double unit_x = SinTheta * CosPhi;
156 G4double unit_y = SinTheta * SinPhi;
157 G4double unit_z = CosTheta;
158 NewMomentumDirection.set (unit_x,unit_y,unit_z);
159
160 // Rotate the new momentum direction into global reference system
161 OldMomentumDirection = aParticle->GetMomentumDirection();
162 OldMomentumDirection = OldMomentumDirection.unit();
163 NewMomentumDirection.rotateUz(OldMomentumDirection);
164 NewMomentumDirection = NewMomentumDirection.unit();
165
166 // calculate the new polarization direction
167 // The new polarization needs to be in the same plane as the new
168 // momentum direction and the old polarization direction
169 OldPolarization = aParticle->GetPolarization();
170 G4double constant = -1./NewMomentumDirection.dot(OldPolarization);
171
172 NewPolarization = NewMomentumDirection + constant*OldPolarization;
173 NewPolarization = NewPolarization.unit();
174
175 // There is a corner case, where the Newmomentum direction
176 // is the same as oldpolariztion direction:
177 // random generate the azimuthal angle w.r.t. Newmomentum direction
178 if (NewPolarization.mag() == 0.) {
179 rand = G4UniformRand()*twopi;
180 NewPolarization.set(std::cos(rand),std::sin(rand),0.);
181 NewPolarization.rotateUz(NewMomentumDirection);
182 } else {
183 // There are two directions which are perpendicular
184 // to the new momentum direction
185 if (G4UniformRand() < 0.5) NewPolarization = -NewPolarization;
186 }
187
188 // simulate according to the distribution cos^2(theta)
189 cosTheta = NewPolarization.dot(OldPolarization);
190 } while (std::pow(cosTheta,2) < G4UniformRand());
191
192 aParticleChange.ProposePolarization(NewPolarization);
193 aParticleChange.ProposeMomentumDirection(NewMomentumDirection);
194
195 if (verboseLevel>0) {
196 G4cout << "New Polarization: "
197 << NewPolarization << G4endl;
198 G4cout << "Polarization Change: "
200 G4cout << "New Momentum Direction: "
201 << NewMomentumDirection << G4endl;
202 G4cout << "Momentum Change: "
204 }
205
206 return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
207}
208
209// BuildThePhysicsTable for the Rayleigh Scattering process
210// --------------------------------------------------------
211//
212void G4OpRayleigh::BuildThePhysicsTable()
213{
214// Builds a table of scattering lengths for each material
215
216 if (thePhysicsTable) return;
217
218 const G4MaterialTable* theMaterialTable=
220 G4int numOfMaterials = G4Material::GetNumberOfMaterials();
221
222 // create a new physics table
223
224 thePhysicsTable = new G4PhysicsTable(numOfMaterials);
225
226 // loop for materials
227
228 for (G4int i=0 ; i < numOfMaterials; i++)
229 {
230 G4PhysicsOrderedFreeVector* ScatteringLengths = NULL;
231
232 G4MaterialPropertiesTable *aMaterialPropertiesTable =
233 (*theMaterialTable)[i]->GetMaterialPropertiesTable();
234
235 if(aMaterialPropertiesTable){
236
237 G4MaterialPropertyVector* AttenuationLengthVector =
238 aMaterialPropertiesTable->GetProperty("RAYLEIGH");
239
240 if(!AttenuationLengthVector){
241
242 if ((*theMaterialTable)[i]->GetName() == "Water")
243 {
244 // Call utility routine to Generate
245 // Rayleigh Scattering Lengths
246
247 DefaultWater = true;
248
249 ScatteringLengths =
250 RayleighAttenuationLengthGenerator(aMaterialPropertiesTable);
251 }
252 }
253 }
254
255 thePhysicsTable->insertAt(i,ScatteringLengths);
256 }
257}
258
259// GetMeanFreePath()
260// -----------------
261//
263 G4double ,
265{
266 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
267 const G4Material* aMaterial = aTrack.GetMaterial();
268
269 G4double thePhotonEnergy = aParticle->GetTotalEnergy();
270
271 G4double AttenuationLength = DBL_MAX;
272
273 if (aMaterial->GetName() == "Water" && DefaultWater){
274
275 G4bool isOutRange;
276
277 AttenuationLength =
278 (*thePhysicsTable)(aMaterial->GetIndex())->
279 GetValue(thePhotonEnergy, isOutRange);
280 }
281 else {
282
283 G4MaterialPropertiesTable* aMaterialPropertyTable =
284 aMaterial->GetMaterialPropertiesTable();
285
286 if(aMaterialPropertyTable){
287 G4MaterialPropertyVector* AttenuationLengthVector =
288 aMaterialPropertyTable->GetProperty("RAYLEIGH");
289 if(AttenuationLengthVector){
290 AttenuationLength = AttenuationLengthVector ->
291 Value(thePhotonEnergy);
292 }
293 else{
294// G4cout << "No Rayleigh scattering length specified" << G4endl;
295 }
296 }
297 else{
298// G4cout << "No Rayleigh scattering length specified" << G4endl;
299 }
300 }
301
302 return AttenuationLength;
303}
304
305// RayleighAttenuationLengthGenerator()
306// ------------------------------------
307// Private method to compute Rayleigh Scattering Lengths (for water)
308//
310G4OpRayleigh::RayleighAttenuationLengthGenerator(G4MaterialPropertiesTable *aMPT)
311{
312 // Physical Constants
313
314 // isothermal compressibility of water
315 G4double betat = 7.658e-23*m3/MeV;
316
317 // K Boltzman
318 G4double kboltz = 8.61739e-11*MeV/kelvin;
319
320 // Temperature of water is 10 degrees celsius
321 // conversion to kelvin:
322 // TCelsius = TKelvin - 273.15 => 273.15 + 10 = 283.15
323 G4double temp = 283.15*kelvin;
324
325 // Retrieve vectors for refraction index
326 // and photon energy from the material properties table
327
328 G4MaterialPropertyVector* Rindex = aMPT->GetProperty("RINDEX");
329
330 G4double refsq;
331 G4double e;
332 G4double xlambda;
333 G4double c1, c2, c3, c4;
334 G4double Dist;
335 G4double refraction_index;
336
337 G4PhysicsOrderedFreeVector *RayleighScatteringLengths =
339
340 if (Rindex ) {
341
342 for (size_t i = 0; i < Rindex->GetVectorLength(); i++) {
343
344 e = Rindex->Energy(i);
345
346 refraction_index = (*Rindex)[i];
347
348 refsq = refraction_index*refraction_index;
349 xlambda = h_Planck*c_light/e;
350
351 if (verboseLevel>0) {
352 G4cout << Rindex->Energy(i) << " MeV\t";
353 G4cout << xlambda << " mm\t";
354 }
355
356 c1 = 1 / (6.0 * pi);
357 c2 = std::pow((2.0 * pi / xlambda), 4);
358 c3 = std::pow( ( (refsq - 1.0) * (refsq + 2.0) / 3.0 ), 2);
359 c4 = betat * temp * kboltz;
360
361 Dist = 1.0 / (c1*c2*c3*c4);
362
363 if (verboseLevel>0) {
364 G4cout << Dist << " mm" << G4endl;
365 }
366 RayleighScatteringLengths->
367 InsertValues(Rindex->Energy(i), Dist);
368 }
369
370 }
371
372 return RayleighScatteringLengths;
373}
G4ForceCondition
std::vector< G4Material * > G4MaterialTable
@ fOpRayleigh
G4ProcessType
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
Hep3Vector unit() const
double dot(const Hep3Vector &) const
double mag() const
void set(double x, double y, double z)
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:72
const G4ThreeVector & GetMomentumDirection() const
G4double GetTotalEnergy() const
const G4ThreeVector & GetPolarization() const
G4MaterialPropertyVector * GetProperty(const char *key)
static const G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:562
G4MaterialPropertiesTable * GetMaterialPropertiesTable() const
Definition: G4Material.hh:251
static size_t GetNumberOfMaterials()
Definition: G4Material.cc:569
const G4String & GetName() const
Definition: G4Material.hh:177
size_t GetIndex() const
Definition: G4Material.hh:261
G4PhysicsTable * thePhysicsTable
G4double GetMeanFreePath(const G4Track &aTrack, G4double, G4ForceCondition *)
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
G4OpRayleigh(const G4String &processName="OpRayleigh", G4ProcessType type=fOptical)
Definition: G4OpRayleigh.cc:82
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 insertAt(size_t, G4PhysicsVector *)
void clearAndDestroy()
size_t GetVectorLength() const
G4double Energy(size_t index) const
Definition: G4Step.hh:78
G4Material * GetMaterial() const
const G4DynamicParticle * GetDynamicParticle() const
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
G4ParticleChange aParticleChange
Definition: G4VProcess.hh:289
G4int verboseLevel
Definition: G4VProcess.hh:368
void SetProcessSubType(G4int)
Definition: G4VProcess.hh:403
const G4String & GetProcessName() const
Definition: G4VProcess.hh:379
const G4double pi
#define DBL_MAX
Definition: templates.hh:83