Import Geant4 11.2.0 source tree
This commit is contained in:
@@ -243,10 +243,17 @@ G4VParticleChange* G4Cerenkov::PostStepDoIt(const G4Track& aTrack,
|
||||
return pParticleChange;
|
||||
|
||||
G4double charge = aParticle->GetDefinition()->GetPDGCharge();
|
||||
G4double beta = (pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta()) * 0.5;
|
||||
|
||||
G4double beta1 = pPreStepPoint->GetBeta();
|
||||
G4double beta2 = pPostStepPoint->GetBeta();
|
||||
G4double beta = (beta1 + beta2) * 0.5;
|
||||
|
||||
G4double MeanNumberOfPhotons =
|
||||
GetAverageNumberOfPhotons(charge, beta, aMaterial, Rindex);
|
||||
G4double MeanNumberOfPhotons1 =
|
||||
GetAverageNumberOfPhotons(charge, beta1, aMaterial, Rindex);
|
||||
G4double MeanNumberOfPhotons2 =
|
||||
GetAverageNumberOfPhotons(charge, beta2, aMaterial, Rindex);
|
||||
|
||||
if(MeanNumberOfPhotons <= 0.0)
|
||||
{
|
||||
@@ -255,11 +262,13 @@ G4VParticleChange* G4Cerenkov::PostStepDoIt(const G4Track& aTrack,
|
||||
return pParticleChange;
|
||||
}
|
||||
|
||||
G4double step_length = aStep.GetStepLength();
|
||||
MeanNumberOfPhotons = MeanNumberOfPhotons * step_length;
|
||||
fNumPhotons = (G4int) G4Poisson(MeanNumberOfPhotons);
|
||||
MeanNumberOfPhotons *= aStep.GetStepLength();
|
||||
fNumPhotons = (G4int) G4Poisson(MeanNumberOfPhotons);
|
||||
|
||||
if(fNumPhotons <= 0 || !fStackingFlag)
|
||||
// third condition added to prevent infinite loop in do-while below,
|
||||
// see bugzilla 2555
|
||||
if(fNumPhotons <= 0 || !fStackingFlag ||
|
||||
std::max(MeanNumberOfPhotons1, MeanNumberOfPhotons2) < 1e-15)
|
||||
{
|
||||
// return unchanged particle and no secondaries
|
||||
aParticleChange.SetNumberOfSecondaries(0);
|
||||
@@ -286,14 +295,6 @@ G4VParticleChange* G4Cerenkov::PostStepDoIt(const G4Track& aTrack,
|
||||
G4double maxCos = BetaInverse / nMax;
|
||||
G4double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
|
||||
|
||||
G4double beta1 = pPreStepPoint->GetBeta();
|
||||
G4double beta2 = pPostStepPoint->GetBeta();
|
||||
|
||||
G4double MeanNumberOfPhotons1 =
|
||||
GetAverageNumberOfPhotons(charge, beta1, aMaterial, Rindex);
|
||||
G4double MeanNumberOfPhotons2 =
|
||||
GetAverageNumberOfPhotons(charge, beta2, aMaterial, Rindex);
|
||||
|
||||
for(G4int i = 0; i < fNumPhotons; ++i)
|
||||
{
|
||||
// Determine photon energy
|
||||
|
||||
@@ -58,7 +58,11 @@ void G4GaussXTRadiator::ProcessDescription(std::ostream& out) const
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
G4double G4GaussXTRadiator::SpectralXTRdEdx(G4double energy)
|
||||
//
|
||||
// The Fabian-Strujinsky (FS) algorithm for integration over XTR angle,
|
||||
// resolution is about 0.5 mrad
|
||||
|
||||
G4double G4GaussXTRadiator::SpectralXTRdEdxFS(G4double energy)
|
||||
{
|
||||
G4double result, sum = 0., tmp, cof1, cof2, cofMin, cofPHC, theta2, theta2k;
|
||||
G4int k, kMax, kMin;
|
||||
|
||||
@@ -388,12 +388,16 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
|
||||
G4double yield1 = 0.;
|
||||
G4double yield2 = 0.;
|
||||
G4double yield3 = 0.;
|
||||
G4double timeconstant1 = 0.;
|
||||
G4double timeconstant2 = 0.;
|
||||
G4double timeconstant3 = 0.;
|
||||
G4double sum_yields = 0.;
|
||||
|
||||
if(fScintillationByParticleType)
|
||||
{
|
||||
MeanNumberOfPhotons = GetScintillationYieldByParticleType(
|
||||
aTrack, aStep, yield1, yield2, yield3);
|
||||
aTrack, aStep, yield1, yield2, yield3, timeconstant1, timeconstant2,
|
||||
timeconstant3);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -467,7 +471,14 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
|
||||
{
|
||||
numPhot = yield1 / sum_yields * fNumPhotons;
|
||||
}
|
||||
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(fScintillationByParticleType)
|
||||
{
|
||||
scintTime = timeconstant1;
|
||||
}
|
||||
else
|
||||
{
|
||||
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
}
|
||||
if(fFiniteRiseTime)
|
||||
{
|
||||
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME1);
|
||||
@@ -487,7 +498,14 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
|
||||
{
|
||||
numPhot = yield2 / sum_yields * fNumPhotons;
|
||||
}
|
||||
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
if(fScintillationByParticleType)
|
||||
{
|
||||
scintTime = timeconstant2;
|
||||
}
|
||||
else
|
||||
{
|
||||
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(fFiniteRiseTime)
|
||||
{
|
||||
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME2);
|
||||
@@ -499,7 +517,14 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
|
||||
else if(scnt == 2)
|
||||
{
|
||||
numPhot = yield3 / sum_yields * fNumPhotons;
|
||||
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
if(fScintillationByParticleType)
|
||||
{
|
||||
scintTime = timeconstant3;
|
||||
}
|
||||
else
|
||||
{
|
||||
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
if(fFiniteRiseTime)
|
||||
{
|
||||
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME3);
|
||||
@@ -634,11 +659,13 @@ G4double G4Scintillation::sample_time(G4double tau1, G4double tau2)
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double G4Scintillation::GetScintillationYieldByParticleType(
|
||||
const G4Track& aTrack, const G4Step& aStep, G4double& yield1,
|
||||
G4double& yield2, G4double& yield3)
|
||||
G4double& yield2, G4double& yield3, G4double& timeconstant1,
|
||||
G4double& timeconstant2, G4double& timeconstant3)
|
||||
{
|
||||
// new in 10.7, allow multiple time constants with ScintByParticleType
|
||||
// Get the G4MaterialPropertyVector containing the scintillation
|
||||
// yield as a function of the energy deposited and particle type
|
||||
// In 11.2, allow different time constants for different particles
|
||||
|
||||
G4ParticleDefinition* pDef = aTrack.GetDynamicParticle()->GetDefinition();
|
||||
G4MaterialPropertyVector* yieldVector = nullptr;
|
||||
@@ -658,6 +685,21 @@ G4double G4Scintillation::GetScintillationYieldByParticleType(
|
||||
yield3 = MPT->ConstPropertyExists(kPROTONSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kPROTONSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kPROTONSCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kPROTONSCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kPROTONSCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kPROTONSCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kPROTONSCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kPROTONSCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Deuterons
|
||||
@@ -673,6 +715,21 @@ G4double G4Scintillation::GetScintillationYieldByParticleType(
|
||||
yield3 = MPT->ConstPropertyExists(kDEUTERONSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kDEUTERONSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kDEUTERONSCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kDEUTERONSCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kDEUTERONSCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kDEUTERONSCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kDEUTERONSCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kDEUTERONSCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Tritons
|
||||
@@ -688,6 +745,21 @@ G4double G4Scintillation::GetScintillationYieldByParticleType(
|
||||
yield3 = MPT->ConstPropertyExists(kTRITONSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kTRITONSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kTRITONSCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kTRITONSCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kTRITONSCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kTRITONSCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kTRITONSCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kTRITONSCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Alphas
|
||||
@@ -703,6 +775,21 @@ G4double G4Scintillation::GetScintillationYieldByParticleType(
|
||||
yield3 = MPT->ConstPropertyExists(kALPHASCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kALPHASCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kALPHASCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kALPHASCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kALPHASCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kALPHASCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kALPHASCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kALPHASCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Ions (particles derived from G4VIon and G4Ions) and recoil ions
|
||||
@@ -720,6 +807,21 @@ G4double G4Scintillation::GetScintillationYieldByParticleType(
|
||||
yield3 = MPT->ConstPropertyExists(kIONSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kIONSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kIONSCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kIONSCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kIONSCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kIONSCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kIONSCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kIONSCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Electrons (must also account for shell-binding energy
|
||||
@@ -737,22 +839,38 @@ G4double G4Scintillation::GetScintillationYieldByParticleType(
|
||||
yield3 = MPT->ConstPropertyExists(kELECTRONSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kELECTRONSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kELECTRONSCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kELECTRONSCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kELECTRONSCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kELECTRONSCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kELECTRONSCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kELECTRONSCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Throw an exception if no scintillation yield vector is found
|
||||
if(!yieldVector)
|
||||
if(yieldVector == nullptr)
|
||||
{
|
||||
G4ExceptionDescription ed;
|
||||
ed << "\nG4Scintillation::PostStepDoIt(): "
|
||||
<< "Request for scintillation yield for energy deposit and particle\n"
|
||||
<< "type without correct entry in MaterialPropertiesTable.\n"
|
||||
<< "ScintillationByParticleType requires at minimum that \n"
|
||||
<< "ELECTRONSCINTILLATIONYIELD is set by the user\n"
|
||||
<< "type without correct entry in MaterialPropertiesTable. A material\n"
|
||||
<< "property (vector) with name like PARTICLESCINTILLATIONYIELD is\n"
|
||||
<< "needed (hint: PARTICLE might not be the primary particle."
|
||||
<< G4endl;
|
||||
G4String comments = "Missing MaterialPropertiesTable entry - No correct "
|
||||
"entry in MaterialPropertiesTable";
|
||||
G4Exception("G4Scintillation::PostStepDoIt", "Scint01", FatalException, ed,
|
||||
comments);
|
||||
return 0.; // NOLINT: required to help Coverity recognise this as exit point
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
@@ -777,15 +895,24 @@ G4double G4Scintillation::GetScintillationYieldByParticleType(
|
||||
}
|
||||
else
|
||||
{
|
||||
G4ExceptionDescription ed;
|
||||
ed << "\nG4Scintillation::GetScintillationYieldByParticleType(): Request\n"
|
||||
<< "for scintillation light yield above the available energy range\n"
|
||||
<< "specified in G4MaterialPropertiesTable. A linear interpolation\n"
|
||||
<< "will be performed to compute the scintillation light yield using\n"
|
||||
<< "(L_max / E_max) as the photon yield per unit energy." << G4endl;
|
||||
G4String cmt = "\nScintillation yield may be unphysical!\n";
|
||||
G4Exception("G4Scintillation::GetScintillationYieldByParticleType()",
|
||||
"Scint03", JustWarning, ed, cmt);
|
||||
++fNumEnergyWarnings;
|
||||
if(verboseLevel > 0 && fNumEnergyWarnings <= 10)
|
||||
{
|
||||
G4ExceptionDescription ed;
|
||||
ed << "\nG4Scintillation::GetScintillationYieldByParticleType(): Request\n"
|
||||
<< "for scintillation light yield above the available energy range\n"
|
||||
<< "specified in G4MaterialPropertiesTable. A linear interpolation\n"
|
||||
<< "will be performed to compute the scintillation light yield using\n"
|
||||
<< "(L_max / E_max) as the photon yield per unit energy." << G4endl;
|
||||
G4String cmt = "\nScintillation yield may be unphysical!\n";
|
||||
|
||||
if(fNumEnergyWarnings == 10)
|
||||
{
|
||||
ed << G4endl << "*** Scintillation energy warnings stopped.";
|
||||
}
|
||||
G4Exception("G4Scintillation::GetScintillationYieldByParticleType()",
|
||||
"Scint03", JustWarning, ed, cmt);
|
||||
}
|
||||
|
||||
// Units: [# scintillation photons]
|
||||
ScintillationYield = yieldVector->GetMaxValue() /
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//------------------ G4XrayReflection physics process -----------------------
|
||||
//
|
||||
// History:
|
||||
// 14-09-23 H. Burkhardt, initial implementation
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include "G4XrayReflection.hh"
|
||||
|
||||
#include "G4EmProcessSubType.hh"
|
||||
#include "G4Exp.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4TransportationManager.hh"
|
||||
#include "G4VDiscreteProcess.hh"
|
||||
|
||||
G4double G4XrayReflection::fSurfaceRoughness = 0;
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4XrayReflection::G4XrayReflection(const G4String& processName,
|
||||
G4ProcessType type) // Constructor
|
||||
: G4VDiscreteProcess(processName, type)
|
||||
{
|
||||
SetProcessSubType(fGammaReflection);
|
||||
SaveHenkeDataAsMaterialProperty();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool G4XrayReflection::IsApplicable(const G4ParticleDefinition& particle)
|
||||
{
|
||||
return (&particle == G4Gamma::Gamma()); // apply only to gamma
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4XrayReflection::Reflectivity(const G4double GamEner, const G4double SinIncidentAngle,
|
||||
const G4Material* theMat) const
|
||||
{
|
||||
G4double theReflectivity = 0;
|
||||
const G4MaterialPropertiesTable* theMatProp = theMat->GetMaterialPropertiesTable();
|
||||
if (SinIncidentAngle < 0.9 && theMatProp != nullptr)
|
||||
{ // avoid perpendicular refl. at straight entry and require
|
||||
// data available
|
||||
G4MaterialPropertyVector* RealIndex = theMatProp->GetProperty(kREALRINDEX);
|
||||
G4MaterialPropertyVector* ImagIndex = theMatProp->GetProperty(kIMAGINARYRINDEX);
|
||||
if (nullptr == RealIndex || nullptr == ImagIndex) { return theReflectivity; }
|
||||
const G4double delta = RealIndex->Value(GamEner);
|
||||
const G4double beta = ImagIndex->Value(GamEner);
|
||||
const G4double sin2 = std::pow(SinIncidentAngle, 2);
|
||||
const G4double rho2 =
|
||||
0.5 * (sin2 - 2 * delta + std::sqrt(std::pow(sin2 - 2 * delta, 2) + 4 * beta * beta));
|
||||
const G4double rho = std::sqrt(rho2);
|
||||
const G4double Refl_sigma = (rho2 * std::pow(SinIncidentAngle - rho, 2) + std::pow(beta, 2))
|
||||
/ (rho2 * std::pow(SinIncidentAngle + rho, 2) + std::pow(beta, 2));
|
||||
const G4double coscot = std::sqrt(1 - sin2) / SinIncidentAngle;
|
||||
const G4double pi_over_sigma = (rho2 * std::pow(rho - coscot, 2) + std::pow(beta, 2))
|
||||
/ (rho2 * std::pow(rho + coscot, 2) + std::pow(beta, 2));
|
||||
const G4double Refl_pi = Refl_sigma * pi_over_sigma;
|
||||
theReflectivity = 0.5 * (Refl_sigma + Refl_pi); // unpolarized
|
||||
G4double RoughAtten = 1;
|
||||
if (fSurfaceRoughness > 0) {
|
||||
G4double kiz = SinIncidentAngle * GamEner / CLHEP::hbarc;
|
||||
G4double kjz = SinIncidentAngle * (1 - delta) * GamEner / CLHEP::hbarc;
|
||||
RoughAtten = G4Exp(-2 * kiz * kjz * fSurfaceRoughness * fSurfaceRoughness); // Nevot–Croce
|
||||
theReflectivity *= RoughAtten;
|
||||
}
|
||||
if (GetVerboseLevel() > 1)
|
||||
G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
|
||||
<< std::right << std::setw(4) << __LINE__ << " GamEner=" << GamEner
|
||||
<< " fSurfaceRoughness=" << G4BestUnit(fSurfaceRoughness, "Length")
|
||||
<< " RoughAtten=" << RoughAtten << " SinIncidentAngle=" << SinIncidentAngle
|
||||
<< " delta=" << delta << " beta=" << beta << " Refl_sigma=" << Refl_sigma
|
||||
<< " Refl_pi=" << Refl_pi << " theReflectivity=" << theReflectivity << G4endl;
|
||||
}
|
||||
return theReflectivity;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4XrayReflection::GetMeanFreePath(const G4Track& aTrack, G4double previousStepSize,
|
||||
G4ForceCondition* condition)
|
||||
{
|
||||
*condition = NotForced;
|
||||
G4double GamEner = aTrack.GetDynamicParticle()->GetTotalEnergy();
|
||||
if (GamEner < 30. * eV || GamEner > 30. * keV)
|
||||
return DBL_MAX; // do nothing below and above the limits
|
||||
|
||||
if (GetVerboseLevel() > 2)
|
||||
G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
|
||||
<< std::right << std::setw(4) << __LINE__ << " GamEner=" << GamEner / keV
|
||||
<< " keV previousStepSize=" << previousStepSize
|
||||
<< " TrackLength=" << aTrack.GetTrackLength() << " StepLength=" << aTrack.GetStepLength()
|
||||
<< G4endl;
|
||||
|
||||
G4double MeanFreePath = DBL_MAX; // by default no reflection
|
||||
G4VPhysicalVolume* Volume = aTrack.GetVolume();
|
||||
if (fLastVolume && Volume != fLastVolume && aTrack.GetTrackLength() > 0) { // at a boundary
|
||||
const G4Material* theLastMat = fLastVolume->GetLogicalVolume()->GetMaterial();
|
||||
const G4Material* theMat = Volume->GetLogicalVolume()->GetMaterial();
|
||||
|
||||
G4double last_density = theLastMat->GetDensity();
|
||||
G4double density = theMat->GetDensity();
|
||||
if (density > last_density) { // density has increased
|
||||
G4Navigator* theNavigator =
|
||||
G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking();
|
||||
G4bool valid = false;
|
||||
G4ThreeVector theSurfaceNormal =
|
||||
theNavigator->GetGlobalExitNormal(aTrack.GetPosition(), &valid);
|
||||
if (valid) fSurfaceNormal = theSurfaceNormal;
|
||||
G4double SinIncidentAngle =
|
||||
aTrack.GetDynamicParticle()->GetMomentumDirection() * fSurfaceNormal;
|
||||
if (G4UniformRand() < Reflectivity(GamEner, SinIncidentAngle, theMat)) {
|
||||
MeanFreePath = 0;
|
||||
}
|
||||
G4ThreeVector Position = aTrack.GetPosition(); // only for info
|
||||
const G4VSolid* LastSolid_Volume = fLastVolume->GetLogicalVolume()->GetSolid(); // for info
|
||||
if (GetVerboseLevel() > 1 && MeanFreePath == 0)
|
||||
G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
|
||||
<< std::right << std::setw(4) << __LINE__
|
||||
<< " trigger reflection SinIncidentAngle=" << SinIncidentAngle
|
||||
<< " at z=" << Position.getZ() / meter << " m" << G4endl;
|
||||
else if (GetVerboseLevel() > 2)
|
||||
G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
|
||||
<< std::right << std::setw(4) << __LINE__ << " volume has changed "
|
||||
<< " last logical volume name =" << fLastVolume->GetLogicalVolume()->GetName()
|
||||
<< " last logical volume material name =" << theLastMat->GetName()
|
||||
<< " last density=" << last_density << " part/cm3 ? "
|
||||
<< " logical volume name =" << Volume->GetLogicalVolume()->GetName()
|
||||
<< " logical volume material name =" << theMat->GetName() << " density=" << density
|
||||
<< " part/cm3 ? "
|
||||
<< " LastSolid_Volume->Inside(Position)=" << LastSolid_Volume->Inside(Position)
|
||||
<< " sin(IncidentAngle)=" << SinIncidentAngle << " MeanFreePath=" << MeanFreePath
|
||||
<< G4endl;
|
||||
}
|
||||
}
|
||||
fLastVolume = Volume;
|
||||
return MeanFreePath;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4VParticleChange* G4XrayReflection::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep)
|
||||
{
|
||||
aParticleChange.Initialize(aTrack); // copy the current position to the changed particle
|
||||
G4ThreeVector PhotDir = aTrack.GetDynamicParticle()->GetMomentumDirection();
|
||||
G4ThreeVector para_part = (PhotDir * fSurfaceNormal) * fSurfaceNormal;
|
||||
G4ThreeVector photon_reflected = PhotDir - 2 * para_part; // invert the parallel component
|
||||
if (GetVerboseLevel() > 1)
|
||||
G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
|
||||
<< std::right << std::setw(4) << __LINE__ << " fSurfaceNormal=" << fSurfaceNormal
|
||||
<< " StepLength=" << aStep.GetStepLength() << " PhotDir=" << PhotDir
|
||||
<< " photon_reflected=" << photon_reflected << " para_part=" << para_part
|
||||
<< " aParticleChange.GetTrackStatus()=" << aParticleChange.GetTrackStatus()
|
||||
<< G4endl;
|
||||
|
||||
aParticleChange.ProposeTrackStatus(
|
||||
fStopAndKill); // needed when working with primary gamma to get rid of
|
||||
// primary
|
||||
auto ReflectedPhoton = new G4DynamicParticle(G4Gamma::Gamma(), photon_reflected,
|
||||
aTrack.GetDynamicParticle()->GetTotalEnergy());
|
||||
aParticleChange.AddSecondary(ReflectedPhoton);
|
||||
return &aParticleChange;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4XrayReflection::BuildPhysicsTable(const G4ParticleDefinition& part)
|
||||
{
|
||||
ProcessDescription(G4cout);
|
||||
|
||||
if (GetVerboseLevel() > 2)
|
||||
G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
|
||||
<< std::right << std::setw(4) << __LINE__
|
||||
<< " is gamma=" << (&part == G4Gamma::Definition())
|
||||
<< " fSurfaceRoughness=" << G4BestUnit(fSurfaceRoughness, "Length") << G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4XrayReflection::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
if (G4Threading::IsMasterThread())
|
||||
out << '\n' << GetProcessName() << ": Gamma specular reflection for energies > 30 eV.\n";
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4int G4XrayReflection::ReadHenkeXrayData(std::string ElName, std::vector<G4double>& Ephot,
|
||||
std::vector<G4double>& f1, std::vector<G4double>& f2)
|
||||
{
|
||||
std::transform(ElName.begin(), ElName.end(), ElName.begin(),
|
||||
::tolower); // henke_physical_reference uses lower case filanames
|
||||
const G4String DataDir = G4EmParameters::Instance()->GetDirLEDATA() + "/XRayReflection_data/";
|
||||
const G4String InpFname = DataDir + ElName + ".nff";
|
||||
std::ifstream infile(InpFname);
|
||||
if (!infile.is_open()) {
|
||||
G4cout << "ReadHenkeXrayReflData " << InpFname << " not found" << G4endl;
|
||||
return 1; // failure
|
||||
}
|
||||
std::vector<std::string> VarName(3);
|
||||
infile >> VarName[0] >> VarName[1] >> VarName[2];
|
||||
if (GetVerboseLevel())
|
||||
G4cout << "ReadHenkeXrayData variable names " << VarName[0] << " " << VarName[1] << " "
|
||||
<< VarName[2] << G4endl;
|
||||
G4double E_eV_i, f1_i, f2_i;
|
||||
Ephot.resize(0);
|
||||
f1.resize(0);
|
||||
f2.resize(0);
|
||||
for (;;) {
|
||||
infile >> E_eV_i >> f1_i >> f2_i;
|
||||
if (infile.eof()) break;
|
||||
Ephot.push_back(E_eV_i * eV);
|
||||
f1.push_back(f1_i);
|
||||
f2.push_back(f2_i);
|
||||
}
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4XrayReflection::SaveHenkeDataAsMaterialProperty()
|
||||
{
|
||||
// loop through the material table and load set up MaterialPropertiesTable
|
||||
// with Henke data used to calculate the reflection
|
||||
auto materialTable = G4Material::GetMaterialTable();
|
||||
for (auto a_material : *materialTable) {
|
||||
auto N = a_material->GetTotNbOfAtomsPerVolume();
|
||||
if (GetVerboseLevel() > 2)
|
||||
if (GetVerboseLevel() > 2)
|
||||
G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
|
||||
<< std::right << std::setw(4) << __LINE__ << " " << a_material->GetName()
|
||||
<< " NbOfAtomsPerVolume()=" << N
|
||||
<< " NumberOfElements()=" << a_material->GetNumberOfElements() << G4endl;
|
||||
// calculate the reflectivity from input data. Implemented for dense
|
||||
// materials of a single element
|
||||
if (a_material->GetNumberOfElements() == 1 && a_material->GetDensity() > 1) {
|
||||
G4double factor = N * CLHEP::classic_electr_radius / CLHEP::twopi;
|
||||
std::vector<G4double> Ephot, f1, f2;
|
||||
const G4Element* theElement = a_material->GetElement(0);
|
||||
G4int iret = ReadHenkeXrayData(theElement->GetName(), Ephot, f1, f2);
|
||||
if (iret) {
|
||||
if (GetVerboseLevel() > 2)
|
||||
G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
|
||||
<< std::right << std::setw(4) << __LINE__ << " no Henke data found for "
|
||||
<< a_material->GetName() << " " << theElement->GetName() << G4endl;
|
||||
}
|
||||
else {
|
||||
std::vector<G4double> RealIndex(Ephot.size()), ImagIndex(Ephot.size());
|
||||
for (std::size_t i = 0; i < Ephot.size(); ++i) {
|
||||
G4double lambda = CLHEP::twopi * CLHEP::hbarc / Ephot[i];
|
||||
G4double lambda_sqr = lambda * lambda;
|
||||
RealIndex[i] = fmax(0, factor * lambda_sqr * f1[i]); // delta or 1-RealIndex
|
||||
ImagIndex[i] = factor * lambda_sqr * f2[i]; // beta or -ImagIndex
|
||||
if (GetVerboseLevel() > 2)
|
||||
G4cout << "Ephot=" << std::setw(10) << Ephot[i] / eV << " eV delta=" << std::setw(10)
|
||||
<< RealIndex[i] << " beta=" << std::setw(10) << ImagIndex[i] << G4endl;
|
||||
} // photon energy
|
||||
G4MaterialPropertiesTable* proptab = a_material->GetMaterialPropertiesTable();
|
||||
if(proptab == nullptr) {
|
||||
proptab = new G4MaterialPropertiesTable();
|
||||
a_material->SetMaterialPropertiesTable(proptab);
|
||||
}
|
||||
proptab->AddProperty("REALRINDEX", Ephot, RealIndex); // 1-RealIndex
|
||||
proptab->AddProperty("IMAGINARYRINDEX", Ephot, ImagIndex);
|
||||
if (GetVerboseLevel() > 2)
|
||||
G4cout << std::left << std::setw(12) << __FILE__ << " " << __FUNCTION__ << " line "
|
||||
<< std::right << std::setw(4) << __LINE__ << " " << a_material->GetName()
|
||||
<< " " << theElement->GetName()
|
||||
<< " reflection data saved in PropertiesTable" << G4endl;
|
||||
} // data found
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4XrayReflection::SetSurfaceRoughness(const G4double value)
|
||||
{
|
||||
fSurfaceRoughness = value;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
Reference in New Issue
Block a user