Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4XrayReflection.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//------------------ G4XrayReflection physics process -----------------------
27//
28// History:
29// 14-09-23 H. Burkhardt, initial implementation
30//
31// --------------------------------------------------------------------------
32
33#include "G4XrayReflection.hh"
34
35#include "G4EmProcessSubType.hh"
36#include "G4Exp.hh"
37#include "G4Gamma.hh"
38#include "G4Step.hh"
39#include "G4SystemOfUnits.hh"
40#include "G4ThreeVector.hh"
41#include "G4Track.hh"
43#include "G4VDiscreteProcess.hh"
44
45G4double G4XrayReflection::fSurfaceRoughness = 0;
46
47//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
48
50 G4ProcessType type) // Constructor
51 : G4VDiscreteProcess(processName, type)
52{
55}
56
57//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
58
60{
61 return (&particle == G4Gamma::Gamma()); // apply only to gamma
62}
63
64//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
65
66G4double G4XrayReflection::Reflectivity(const G4double GamEner, const G4double SinIncidentAngle,
67 const G4Material* theMat) const
68{
69 G4double theReflectivity = 0;
70 const G4MaterialPropertiesTable* theMatProp = theMat->GetMaterialPropertiesTable();
71 if (SinIncidentAngle < 0.9 && theMatProp != nullptr)
72 { // avoid perpendicular refl. at straight entry and require
73 // data available
74 G4MaterialPropertyVector* RealIndex = theMatProp->GetProperty(kREALRINDEX);
76 if (nullptr == RealIndex || nullptr == ImagIndex) { return theReflectivity; }
77 const G4double delta = RealIndex->Value(GamEner);
78 const G4double beta = ImagIndex->Value(GamEner);
79 const G4double sin2 = std::pow(SinIncidentAngle, 2);
80 const G4double rho2 =
81 0.5 * (sin2 - 2 * delta + std::sqrt(std::pow(sin2 - 2 * delta, 2) + 4 * beta * beta));
82 const G4double rho = std::sqrt(rho2);
83 const G4double Refl_sigma = (rho2 * std::pow(SinIncidentAngle - rho, 2) + std::pow(beta, 2))
84 / (rho2 * std::pow(SinIncidentAngle + rho, 2) + std::pow(beta, 2));
85 const G4double coscot = std::sqrt(1 - sin2) / SinIncidentAngle;
86 const G4double pi_over_sigma = (rho2 * std::pow(rho - coscot, 2) + std::pow(beta, 2))
87 / (rho2 * std::pow(rho + coscot, 2) + std::pow(beta, 2));
88 const G4double Refl_pi = Refl_sigma * pi_over_sigma;
89 theReflectivity = 0.5 * (Refl_sigma + Refl_pi); // unpolarized
90 G4double RoughAtten = 1;
91 if (fSurfaceRoughness > 0) {
92 G4double kiz = SinIncidentAngle * GamEner / CLHEP::hbarc;
93 G4double kjz = SinIncidentAngle * (1 - delta) * GamEner / CLHEP::hbarc;
94 RoughAtten = G4Exp(-2 * kiz * kjz * fSurfaceRoughness * fSurfaceRoughness); // Nevot–Croce
95 theReflectivity *= RoughAtten;
96 }
97 if (GetVerboseLevel() > 1)
98 G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
99 << std::right << std::setw(4) << __LINE__ << " GamEner=" << GamEner
100 << " fSurfaceRoughness=" << G4BestUnit(fSurfaceRoughness, "Length")
101 << " RoughAtten=" << RoughAtten << " SinIncidentAngle=" << SinIncidentAngle
102 << " delta=" << delta << " beta=" << beta << " Refl_sigma=" << Refl_sigma
103 << " Refl_pi=" << Refl_pi << " theReflectivity=" << theReflectivity << G4endl;
104 }
105 return theReflectivity;
106}
107
108//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
109
112{
114 G4double GamEner = aTrack.GetDynamicParticle()->GetTotalEnergy();
115 if (GamEner < 30. * eV || GamEner > 30. * keV)
116 return DBL_MAX; // do nothing below and above the limits
117
118 if (GetVerboseLevel() > 2)
119 G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
120 << std::right << std::setw(4) << __LINE__ << " GamEner=" << GamEner / keV
121 << " keV previousStepSize=" << previousStepSize
122 << " TrackLength=" << aTrack.GetTrackLength() << " StepLength=" << aTrack.GetStepLength()
123 << G4endl;
124
125 G4double MeanFreePath = DBL_MAX; // by default no reflection
126 G4VPhysicalVolume* Volume = aTrack.GetVolume();
127 if (fLastVolume && Volume != fLastVolume && aTrack.GetTrackLength() > 0) { // at a boundary
128 const G4Material* theLastMat = fLastVolume->GetLogicalVolume()->GetMaterial();
129 const G4Material* theMat = Volume->GetLogicalVolume()->GetMaterial();
130
131 G4double last_density = theLastMat->GetDensity();
132 G4double density = theMat->GetDensity();
133 if (density > last_density) { // density has increased
134 G4Navigator* theNavigator =
136 G4bool valid = false;
137 G4ThreeVector theSurfaceNormal =
138 theNavigator->GetGlobalExitNormal(aTrack.GetPosition(), &valid);
139 if (valid) fSurfaceNormal = theSurfaceNormal;
140 G4double SinIncidentAngle =
141 aTrack.GetDynamicParticle()->GetMomentumDirection() * fSurfaceNormal;
142 if (G4UniformRand() < Reflectivity(GamEner, SinIncidentAngle, theMat)) {
143 MeanFreePath = 0;
144 }
145 G4ThreeVector Position = aTrack.GetPosition(); // only for info
146 const G4VSolid* LastSolid_Volume = fLastVolume->GetLogicalVolume()->GetSolid(); // for info
147 if (GetVerboseLevel() > 1 && MeanFreePath == 0)
148 G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
149 << std::right << std::setw(4) << __LINE__
150 << " trigger reflection SinIncidentAngle=" << SinIncidentAngle
151 << " at z=" << Position.getZ() / meter << " m" << G4endl;
152 else if (GetVerboseLevel() > 2)
153 G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
154 << std::right << std::setw(4) << __LINE__ << " volume has changed "
155 << " last logical volume name =" << fLastVolume->GetLogicalVolume()->GetName()
156 << " last logical volume material name =" << theLastMat->GetName()
157 << " last density=" << last_density << " part/cm3 ? "
158 << " logical volume name =" << Volume->GetLogicalVolume()->GetName()
159 << " logical volume material name =" << theMat->GetName() << " density=" << density
160 << " part/cm3 ? "
161 << " LastSolid_Volume->Inside(Position)=" << LastSolid_Volume->Inside(Position)
162 << " sin(IncidentAngle)=" << SinIncidentAngle << " MeanFreePath=" << MeanFreePath
163 << G4endl;
164 }
165 }
166 fLastVolume = Volume;
167 return MeanFreePath;
168}
169
170//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
171
173{
174 aParticleChange.Initialize(aTrack); // copy the current position to the changed particle
176 G4ThreeVector para_part = (PhotDir * fSurfaceNormal) * fSurfaceNormal;
177 G4ThreeVector photon_reflected = PhotDir - 2 * para_part; // invert the parallel component
178 if (GetVerboseLevel() > 1)
179 G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
180 << std::right << std::setw(4) << __LINE__ << " fSurfaceNormal=" << fSurfaceNormal
181 << " StepLength=" << aStep.GetStepLength() << " PhotDir=" << PhotDir
182 << " photon_reflected=" << photon_reflected << " para_part=" << para_part
183 << " aParticleChange.GetTrackStatus()=" << aParticleChange.GetTrackStatus()
184 << G4endl;
185
187 fStopAndKill); // needed when working with primary gamma to get rid of
188 // primary
189 auto ReflectedPhoton = new G4DynamicParticle(G4Gamma::Gamma(), photon_reflected,
191 aParticleChange.AddSecondary(ReflectedPhoton);
192 return &aParticleChange;
193}
194
195//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
196
198{
200
201 if (GetVerboseLevel() > 2)
202 G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
203 << std::right << std::setw(4) << __LINE__
204 << " is gamma=" << (&part == G4Gamma::Definition())
205 << " fSurfaceRoughness=" << G4BestUnit(fSurfaceRoughness, "Length") << G4endl;
206}
207
208//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
209
210void G4XrayReflection::ProcessDescription(std::ostream& out) const
211{
213 out << '\n' << GetProcessName() << ": Gamma specular reflection for energies > 30 eV.\n";
214}
215
216//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
217
218G4int G4XrayReflection::ReadHenkeXrayData(std::string ElName, std::vector<G4double>& Ephot,
219 std::vector<G4double>& f1, std::vector<G4double>& f2)
220{
221 std::transform(ElName.begin(), ElName.end(), ElName.begin(),
222 ::tolower); // henke_physical_reference uses lower case filanames
223 const G4String DataDir = G4EmParameters::Instance()->GetDirLEDATA() + "/XRayReflection_data/";
224 const G4String InpFname = DataDir + ElName + ".nff";
225 std::ifstream infile(InpFname);
226 if (!infile.is_open()) {
227 G4cout << "ReadHenkeXrayReflData " << InpFname << " not found" << G4endl;
228 return 1; // failure
229 }
230 std::vector<std::string> VarName(3);
231 infile >> VarName[0] >> VarName[1] >> VarName[2];
232 if (GetVerboseLevel())
233 G4cout << "ReadHenkeXrayData variable names " << VarName[0] << " " << VarName[1] << " "
234 << VarName[2] << G4endl;
235 G4double E_eV_i, f1_i, f2_i;
236 Ephot.resize(0);
237 f1.resize(0);
238 f2.resize(0);
239 for (;;) {
240 infile >> E_eV_i >> f1_i >> f2_i;
241 if (infile.eof()) break;
242 Ephot.push_back(E_eV_i * eV);
243 f1.push_back(f1_i);
244 f2.push_back(f2_i);
245 }
246 return 0; // success
247}
248
249//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
250
252{
253 // loop through the material table and load set up MaterialPropertiesTable
254 // with Henke data used to calculate the reflection
255 auto materialTable = G4Material::GetMaterialTable();
256 for (auto a_material : *materialTable) {
257 auto N = a_material->GetTotNbOfAtomsPerVolume();
258 if (GetVerboseLevel() > 2)
259 if (GetVerboseLevel() > 2)
260 G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
261 << std::right << std::setw(4) << __LINE__ << " " << a_material->GetName()
262 << " NbOfAtomsPerVolume()=" << N
263 << " NumberOfElements()=" << a_material->GetNumberOfElements() << G4endl;
264 // calculate the reflectivity from input data. Implemented for dense
265 // materials of a single element
266 if (a_material->GetNumberOfElements() == 1 && a_material->GetDensity() > 1) {
267 G4double factor = N * CLHEP::classic_electr_radius / CLHEP::twopi;
268 std::vector<G4double> Ephot, f1, f2;
269 const G4Element* theElement = a_material->GetElement(0);
270 G4int iret = ReadHenkeXrayData(theElement->GetName(), Ephot, f1, f2);
271 if (iret) {
272 if (GetVerboseLevel() > 2)
273 G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
274 << std::right << std::setw(4) << __LINE__ << " no Henke data found for "
275 << a_material->GetName() << " " << theElement->GetName() << G4endl;
276 }
277 else {
278 std::vector<G4double> RealIndex(Ephot.size()), ImagIndex(Ephot.size());
279 for (std::size_t i = 0; i < Ephot.size(); ++i) {
280 G4double lambda = CLHEP::twopi * CLHEP::hbarc / Ephot[i];
281 G4double lambda_sqr = lambda * lambda;
282 RealIndex[i] = fmax(0, factor * lambda_sqr * f1[i]); // delta or 1-RealIndex
283 ImagIndex[i] = factor * lambda_sqr * f2[i]; // beta or -ImagIndex
284 if (GetVerboseLevel() > 2)
285 G4cout << "Ephot=" << std::setw(10) << Ephot[i] / eV << " eV delta=" << std::setw(10)
286 << RealIndex[i] << " beta=" << std::setw(10) << ImagIndex[i] << G4endl;
287 } // photon energy
288 G4MaterialPropertiesTable* proptab = a_material->GetMaterialPropertiesTable();
289 if(proptab == nullptr) {
290 proptab = new G4MaterialPropertiesTable();
291 a_material->SetMaterialPropertiesTable(proptab);
292 }
293 proptab->AddProperty("REALRINDEX", Ephot, RealIndex); // 1-RealIndex
294 proptab->AddProperty("IMAGINARYRINDEX", Ephot, ImagIndex);
295 if (GetVerboseLevel() > 2)
296 G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
297 << std::right << std::setw(4) << __LINE__ << " " << a_material->GetName()
298 << " " << theElement->GetName()
299 << " reflection data saved in PropertiesTable" << G4endl;
300 } // data found
301 }
302 }
303}
304
305//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
306
308{
309 fSurfaceRoughness = value;
310}
311
312//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@ fGammaReflection
G4double condition(const G4ErrorSymMatrix &m)
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition G4Exp.hh:180
G4ForceCondition
@ NotForced
G4ProcessType
#define G4BestUnit(a, b)
@ fStopAndKill
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
const G4ThreeVector & GetMomentumDirection() const
G4double GetTotalEnergy() const
const G4String & GetName() const
Definition G4Element.hh:115
static G4Element * GetElement(const G4String &name, G4bool warning=true)
Definition G4Element.cc:397
static G4EmParameters * Instance()
const G4String & GetDirLEDATA() const
static G4Gamma * Gamma()
Definition G4Gamma.cc:81
static G4Gamma * Definition()
Definition G4Gamma.cc:43
G4VSolid * GetSolid() const
G4Material * GetMaterial() const
const G4String & GetName() const
G4MaterialPropertyVector * AddProperty(const G4String &key, const std::vector< G4double > &photonEnergies, const std::vector< G4double > &propertyValues, G4bool createNewKey=false, G4bool spline=false)
G4MaterialPropertyVector * GetProperty(const char *key) const
G4double GetDensity() const
G4MaterialPropertiesTable * GetMaterialPropertiesTable() const
static G4MaterialTable * GetMaterialTable()
const G4String & GetName() const
virtual G4ThreeVector GetGlobalExitNormal(const G4ThreeVector &point, G4bool *valid)
void AddSecondary(G4Track *aSecondary)
void Initialize(const G4Track &) override
G4double Value(const G4double energy, std::size_t &lastidx) const
G4double GetStepLength() const
G4VPhysicalVolume * GetVolume() const
const G4ThreeVector & GetPosition() const
G4double GetTrackLength() const
const G4DynamicParticle * GetDynamicParticle() const
G4double GetStepLength() const
static G4TransportationManager * GetTransportationManager()
G4Navigator * GetNavigatorForTracking() const
void ProposeTrackStatus(G4TrackStatus status)
G4TrackStatus GetTrackStatus() const
G4LogicalVolume * GetLogicalVolume() const
G4int GetVerboseLevel() const
G4ParticleChange aParticleChange
void SetProcessSubType(G4int)
const G4String & GetProcessName() const
virtual EInside Inside(const G4ThreeVector &p) const =0
void SetSurfaceRoughness(const G4double value)
G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &Step) override
void ProcessDescription(std::ostream &) const override
G4bool IsApplicable(const G4ParticleDefinition &) override
G4XrayReflection(const G4String &processName="XrayReflection", G4ProcessType type=fElectromagnetic)
G4int ReadHenkeXrayData(std::string ElName, std::vector< G4double > &Ephot, std::vector< G4double > &f1, std::vector< G4double > &f2)
void SaveHenkeDataAsMaterialProperty()
G4double Reflectivity(const G4double GamEner, const G4double SinIncidentAngle, const G4Material *theMat) const
void BuildPhysicsTable(const G4ParticleDefinition &) override
G4double GetMeanFreePath(const G4Track &track, G4double previousStepSize, G4ForceCondition *condition) override
#define N
Definition crc32.c:57
G4bool IsMasterThread()
#define DBL_MAX
Definition templates.hh:62