Import Geant4 11.2.0 source tree

This commit is contained in:
Gabriele Cosmo
2023-12-08 10:43:34 +01:00
parent dd1f179cda
commit 860a2b92bf
3962 changed files with 139318 additions and 164259 deletions
@@ -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); // NevotCroce
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......