Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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: [email protected]
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