Import Geant4 11.2.0 source tree
This commit is contained in:
@@ -39,51 +39,52 @@
|
||||
|
||||
#include "G4TransportationWithMsc.hh"
|
||||
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4EmConfigurator.hh"
|
||||
#include "G4EmDataHandler.hh"
|
||||
#include "G4LossTableBuilder.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4EmConfigurator.hh"
|
||||
#include "G4VMscModel.hh"
|
||||
|
||||
#include "G4ParticleChangeForGamma.hh"
|
||||
#include "G4ParticleChangeForMSC.hh"
|
||||
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4PhysicsTableHelper.hh"
|
||||
#include "G4PhysicsVector.hh"
|
||||
#include "G4ProductionCutsTable.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4StepPoint.hh"
|
||||
#include "G4StepStatus.hh"
|
||||
#include "G4Track.hh"
|
||||
|
||||
#include "G4Electron.hh"
|
||||
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4VMscModel.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
static constexpr G4double kLowestKinEnergy = 10 * CLHEP::eV;
|
||||
static constexpr G4double kGeomMin = 0.05 * CLHEP::nm;
|
||||
static constexpr G4double kLowestKinEnergy = 10 * CLHEP::eV;
|
||||
static constexpr G4double kGeomMin = 0.05 * CLHEP::nm;
|
||||
static constexpr G4double kMinDisplacement2 = kGeomMin * kGeomMin;
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4TransportationWithMsc::G4TransportationWithMsc(ScatteringType type,
|
||||
G4int verbosity)
|
||||
: G4Transportation(verbosity, "TransportationWithMsc")
|
||||
, fType(type)
|
||||
G4TransportationWithMsc::G4TransportationWithMsc(ScatteringType type, G4int verbosity)
|
||||
: G4Transportation(verbosity, "TransportationWithMsc"), fType(type)
|
||||
{
|
||||
SetVerboseLevel(1);
|
||||
|
||||
fEmManager = G4LossTableManager::Instance();
|
||||
fEmManager = G4LossTableManager::Instance();
|
||||
fModelManager = new G4EmModelManager;
|
||||
|
||||
if(type == ScatteringType::MultipleScattering)
|
||||
{
|
||||
if (type == ScatteringType::MultipleScattering) {
|
||||
fParticleChangeForMSC = new G4ParticleChangeForMSC;
|
||||
}
|
||||
else if (type == ScatteringType::SingleScattering) {
|
||||
fParticleChangeForSS = new G4ParticleChangeForGamma;
|
||||
fSecondariesSS = new std::vector<G4DynamicParticle*>;
|
||||
}
|
||||
|
||||
G4ThreeVector zero;
|
||||
fSubStepDynamicParticle =
|
||||
new G4DynamicParticle(G4Electron::Definition(), zero);
|
||||
fSubStepDynamicParticle = new G4DynamicParticle(G4Electron::Definition(), zero);
|
||||
fSubStepTrack = new G4Track(fSubStepDynamicParticle, 0, zero);
|
||||
fSubStep = new G4Step;
|
||||
fSubStep = new G4Step;
|
||||
fSubStepTrack->SetStep(fSubStep);
|
||||
}
|
||||
|
||||
@@ -93,6 +94,9 @@ G4TransportationWithMsc::~G4TransportationWithMsc()
|
||||
{
|
||||
delete fModelManager;
|
||||
delete fParticleChangeForMSC;
|
||||
delete fEmData;
|
||||
delete fParticleChangeForSS;
|
||||
delete fSecondariesSS;
|
||||
|
||||
// fSubStepDynamicParticle is owned and also deleted by fSubStepTrack!
|
||||
delete fSubStepTrack;
|
||||
@@ -104,10 +108,8 @@ G4TransportationWithMsc::~G4TransportationWithMsc()
|
||||
void G4TransportationWithMsc::AddMscModel(G4VMscModel* mscModel, G4int order,
|
||||
const G4Region* region)
|
||||
{
|
||||
if(fType != ScatteringType::MultipleScattering)
|
||||
{
|
||||
G4Exception("G4TransportationWithMsc::AddMscModel", "em0051",
|
||||
FatalException,
|
||||
if (fType != ScatteringType::MultipleScattering) {
|
||||
G4Exception("G4TransportationWithMsc::AddMscModel", "em0051", FatalException,
|
||||
"not allowed unless type == MultipleScattering");
|
||||
}
|
||||
|
||||
@@ -117,89 +119,129 @@ void G4TransportationWithMsc::AddMscModel(G4VMscModel* mscModel, G4int order,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4TransportationWithMsc::PreparePhysicsTable(
|
||||
const G4ParticleDefinition& part)
|
||||
void G4TransportationWithMsc::AddSSModel(G4VEmModel* model, G4int order, const G4Region* region)
|
||||
{
|
||||
if(nullptr == fFirstParticle)
|
||||
{
|
||||
if (fType != ScatteringType::SingleScattering) {
|
||||
G4Exception("G4TransportationWithMsc::AddSSModel", "em0051", FatalException,
|
||||
"not allowed unless type == SingleScattering");
|
||||
}
|
||||
|
||||
fModelManager->AddEmModel(order, model, nullptr, region);
|
||||
model->SetPolarAngleLimit(0.0);
|
||||
model->SetParticleChange(fParticleChangeForSS);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4TransportationWithMsc::PreparePhysicsTable(const G4ParticleDefinition& part)
|
||||
{
|
||||
if (nullptr == fFirstParticle) {
|
||||
fFirstParticle = ∂
|
||||
G4VMultipleScattering* ptr = nullptr;
|
||||
auto emConfigurator = fEmManager->EmConfigurator();
|
||||
emConfigurator->PrepareModels(&part, ptr, this);
|
||||
}
|
||||
|
||||
if(fFirstParticle == &part)
|
||||
{
|
||||
G4bool master = fEmManager->IsMaster();
|
||||
G4LossTableBuilder* bld = fEmManager->GetTableBuilder();
|
||||
G4bool baseMat = bld->GetBaseMaterialFlag();
|
||||
if (fFirstParticle == &part) {
|
||||
G4bool master = fEmManager->IsMaster();
|
||||
G4LossTableBuilder* bld = fEmManager->GetTableBuilder();
|
||||
G4bool baseMat = bld->GetBaseMaterialFlag();
|
||||
const auto* theParameters = G4EmParameters::Instance();
|
||||
|
||||
if(master)
|
||||
{
|
||||
if (master) {
|
||||
SetVerboseLevel(theParameters->Verbose());
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
SetVerboseLevel(theParameters->WorkerVerbose());
|
||||
}
|
||||
|
||||
const G4int numberOfModels = fModelManager->NumberOfModels();
|
||||
if(fType == ScatteringType::MultipleScattering)
|
||||
{
|
||||
for(G4int i = 0; i < numberOfModels; ++i)
|
||||
{
|
||||
if (fType == ScatteringType::MultipleScattering) {
|
||||
for (G4int i = 0; i < numberOfModels; ++i) {
|
||||
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
|
||||
msc->SetMasterThread(master);
|
||||
msc->SetPolarAngleLimit(theParameters->MscThetaLimit());
|
||||
G4double emax =
|
||||
std::min(msc->HighEnergyLimit(), theParameters->MaxKinEnergy());
|
||||
G4double emax = std::min(msc->HighEnergyLimit(), theParameters->MaxKinEnergy());
|
||||
msc->SetHighEnergyLimit(emax);
|
||||
msc->SetUseBaseMaterials(baseMat);
|
||||
}
|
||||
}
|
||||
else if (fType == ScatteringType::SingleScattering) {
|
||||
if (master) {
|
||||
if (fEmData == nullptr) {
|
||||
fEmData = new G4EmDataHandler(2);
|
||||
}
|
||||
|
||||
fModelManager->Initialise(fFirstParticle, G4Electron::Electron(),
|
||||
verboseLevel);
|
||||
fLambdaTable = fEmData->MakeTable(0);
|
||||
bld->InitialiseBaseMaterials(fLambdaTable);
|
||||
}
|
||||
}
|
||||
|
||||
fCuts = fModelManager->Initialise(fFirstParticle, G4Electron::Electron(), verboseLevel);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4TransportationWithMsc::BuildPhysicsTable(
|
||||
const G4ParticleDefinition& part)
|
||||
void G4TransportationWithMsc::BuildPhysicsTable(const G4ParticleDefinition& part)
|
||||
{
|
||||
if(fFirstParticle == &part)
|
||||
{
|
||||
if (fFirstParticle == &part) {
|
||||
fEmManager->BuildPhysicsTable(fFirstParticle);
|
||||
|
||||
if(!fEmManager->IsMaster())
|
||||
{
|
||||
const auto masterProcess =
|
||||
static_cast<const G4TransportationWithMsc*>(GetMasterProcess());
|
||||
if (fEmManager->IsMaster()) {
|
||||
if (fType == ScatteringType::SingleScattering) {
|
||||
const auto* theParameters = G4EmParameters::Instance();
|
||||
G4LossTableBuilder* bld = fEmManager->GetTableBuilder();
|
||||
const G4ProductionCutsTable* theCoupleTable =
|
||||
G4ProductionCutsTable::GetProductionCutsTable();
|
||||
std::size_t numOfCouples = theCoupleTable->GetTableSize();
|
||||
|
||||
G4double emin = theParameters->MinKinEnergy();
|
||||
G4double emax = theParameters->MaxKinEnergy();
|
||||
|
||||
G4double scale = emax / emin;
|
||||
G4int nbin = theParameters->NumberOfBinsPerDecade() * G4lrint(std::log10(scale));
|
||||
scale = nbin / G4Log(scale);
|
||||
|
||||
G4int bin = G4lrint(scale * G4Log(emax / emin));
|
||||
bin = std::max(bin, 5);
|
||||
|
||||
for (std::size_t i = 0; i < numOfCouples; ++i) {
|
||||
if (!bld->GetFlag(i)) continue;
|
||||
|
||||
// Create physics vector and fill it
|
||||
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple((G4int)i);
|
||||
|
||||
auto* aVector = new G4PhysicsLogVector(emin, emax, bin, /*splineFlag*/ true);
|
||||
fModelManager->FillLambdaVector(aVector, couple, /*startNull*/ false);
|
||||
aVector->FillSecondDerivatives();
|
||||
G4PhysicsTableHelper::SetPhysicsVector(fLambdaTable, i, aVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const auto masterProcess = static_cast<const G4TransportationWithMsc*>(GetMasterProcess());
|
||||
|
||||
// Initialisation of models.
|
||||
const G4int numberOfModels = fModelManager->NumberOfModels();
|
||||
if(fType == ScatteringType::MultipleScattering)
|
||||
{
|
||||
for(G4int i = 0; i < numberOfModels; ++i)
|
||||
{
|
||||
if (fType == ScatteringType::MultipleScattering) {
|
||||
for (G4int i = 0; i < numberOfModels; ++i) {
|
||||
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
|
||||
auto msc0 =
|
||||
static_cast<G4VMscModel*>(masterProcess->fModelManager->GetModel(i));
|
||||
auto msc0 = static_cast<G4VMscModel*>(masterProcess->fModelManager->GetModel(i));
|
||||
msc->SetCrossSectionTable(msc0->GetCrossSectionTable(), false);
|
||||
msc->InitialiseLocal(fFirstParticle, msc0);
|
||||
}
|
||||
}
|
||||
else if (fType == ScatteringType::SingleScattering) {
|
||||
this->fLambdaTable = masterProcess->fLambdaTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!G4EmParameters::Instance()->IsPrintLocked() && verboseLevel > 0)
|
||||
{
|
||||
if (!G4EmParameters::Instance()->IsPrintLocked() && verboseLevel > 0) {
|
||||
G4cout << G4endl;
|
||||
G4cout << GetProcessName() << ": for " << part.GetParticleName();
|
||||
if(fMultipleSteps)
|
||||
{
|
||||
if (fMultipleSteps) {
|
||||
G4cout << " (multipleSteps: 1)";
|
||||
}
|
||||
G4cout << G4endl;
|
||||
@@ -212,18 +254,16 @@ void G4TransportationWithMsc::BuildPhysicsTable(
|
||||
void G4TransportationWithMsc::StartTracking(G4Track* track)
|
||||
{
|
||||
auto* currParticle = track->GetParticleDefinition();
|
||||
auto* ionisation = fEmManager->GetEnergyLossProcess(currParticle);
|
||||
fIonisation = fEmManager->GetEnergyLossProcess(currParticle);
|
||||
|
||||
fSubStepDynamicParticle->SetDefinition(currParticle);
|
||||
|
||||
const G4int numberOfModels = fModelManager->NumberOfModels();
|
||||
if(fType == ScatteringType::MultipleScattering)
|
||||
{
|
||||
for(G4int i = 0; i < numberOfModels; ++i)
|
||||
{
|
||||
if (fType == ScatteringType::MultipleScattering) {
|
||||
for (G4int i = 0; i < numberOfModels; ++i) {
|
||||
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
|
||||
msc->StartTracking(track);
|
||||
msc->SetIonisation(ionisation, currParticle);
|
||||
msc->SetIonisation(fIonisation, currParticle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,42 +273,38 @@ void G4TransportationWithMsc::StartTracking(G4Track* track)
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4TransportationWithMsc::AlongStepGetPhysicalInteractionLength(
|
||||
const G4Track& track, G4double previousStepSize, G4double currentMinimumStep,
|
||||
G4double& proposedSafety, G4GPILSelection* selection)
|
||||
G4double G4TransportationWithMsc::AlongStepGetPhysicalInteractionLength(const G4Track& track,
|
||||
G4double previousStepSize,
|
||||
G4double currentMinimumStep,
|
||||
G4double& proposedSafety,
|
||||
G4GPILSelection* selection)
|
||||
{
|
||||
*selection = NotCandidateForSelection;
|
||||
|
||||
const G4double physStepLimit = currentMinimumStep;
|
||||
|
||||
switch(fType)
|
||||
{
|
||||
switch (fType) {
|
||||
case ScatteringType::MultipleScattering: {
|
||||
// Select the MSC model for the current kinetic energy.
|
||||
G4VMscModel* mscModel = nullptr;
|
||||
const G4double ekin = track.GetKineticEnergy();
|
||||
const auto* couple = track.GetMaterialCutsCouple();
|
||||
G4VMscModel* mscModel = nullptr;
|
||||
const G4double ekin = track.GetKineticEnergy();
|
||||
const auto* couple = track.GetMaterialCutsCouple();
|
||||
const auto* particleDefinition = track.GetParticleDefinition();
|
||||
if(physStepLimit > kGeomMin)
|
||||
{
|
||||
if (physStepLimit > kGeomMin) {
|
||||
G4double ekinForSelection = ekin;
|
||||
G4double pdgMass = particleDefinition->GetPDGMass();
|
||||
if(pdgMass > CLHEP::GeV)
|
||||
{
|
||||
G4double pdgMass = particleDefinition->GetPDGMass();
|
||||
if (pdgMass > CLHEP::GeV) {
|
||||
ekinForSelection *= proton_mass_c2 / pdgMass;
|
||||
}
|
||||
|
||||
if(ekinForSelection >= kLowestKinEnergy)
|
||||
{
|
||||
if (ekinForSelection >= kLowestKinEnergy) {
|
||||
mscModel = static_cast<G4VMscModel*>(
|
||||
fModelManager->SelectModel(ekinForSelection, couple->GetIndex()));
|
||||
if(mscModel == nullptr)
|
||||
{
|
||||
G4Exception("G4TransportationWithMsc::AlongStepGPIL", "em0052",
|
||||
FatalException, "no MSC model found");
|
||||
if (mscModel == nullptr) {
|
||||
G4Exception("G4TransportationWithMsc::AlongStepGPIL", "em0052", FatalException,
|
||||
"no MSC model found");
|
||||
}
|
||||
if(!mscModel->IsActive(ekinForSelection))
|
||||
{
|
||||
if (!mscModel->IsActive(ekinForSelection)) {
|
||||
mscModel = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -276,8 +312,7 @@ G4double G4TransportationWithMsc::AlongStepGetPhysicalInteractionLength(
|
||||
|
||||
// Call the MSC model to potentially limit the step and convert to
|
||||
// geometric path length.
|
||||
if(mscModel != nullptr)
|
||||
{
|
||||
if (mscModel != nullptr) {
|
||||
mscModel->SetCurrentCouple(couple);
|
||||
|
||||
// Use the provided track for the first step.
|
||||
@@ -286,56 +321,46 @@ G4double G4TransportationWithMsc::AlongStepGetPhysicalInteractionLength(
|
||||
G4double currentSafety = proposedSafety;
|
||||
G4double currentEnergy = ekin;
|
||||
|
||||
G4double stepLimitLeft = physStepLimit;
|
||||
G4double stepLimitLeft = physStepLimit;
|
||||
G4double totalGeometryStepLength = 0, totalTruePathLength = 0;
|
||||
G4bool firstStep = true, continueStepping = fMultipleSteps;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
G4double gPathLength = stepLimitLeft;
|
||||
G4double tPathLength =
|
||||
mscModel->ComputeTruePathLengthLimit(*currentTrackPtr, gPathLength);
|
||||
G4bool mscLimitsStep = (tPathLength < stepLimitLeft);
|
||||
if(!fMultipleSteps && mscLimitsStep)
|
||||
{
|
||||
if (!fMultipleSteps && mscLimitsStep) {
|
||||
// MSC limits the step.
|
||||
*selection = CandidateForSelection;
|
||||
}
|
||||
|
||||
if(!firstStep)
|
||||
{
|
||||
if (!firstStep) {
|
||||
// Move the navigator to where the previous step ended.
|
||||
fLinearNavigator->LocateGlobalPointWithinVolume(
|
||||
fTransportEndPosition);
|
||||
fLinearNavigator->LocateGlobalPointWithinVolume(fTransportEndPosition);
|
||||
}
|
||||
|
||||
G4GPILSelection transportSelection;
|
||||
G4double geometryStepLength =
|
||||
G4Transportation::AlongStepGetPhysicalInteractionLength(
|
||||
*currentTrackPtr, previousStepSize, gPathLength, currentSafety,
|
||||
&transportSelection);
|
||||
if(geometryStepLength < gPathLength)
|
||||
{
|
||||
G4double geometryStepLength = G4Transportation::AlongStepGetPhysicalInteractionLength(
|
||||
*currentTrackPtr, previousStepSize, gPathLength, currentSafety, &transportSelection);
|
||||
if (geometryStepLength < gPathLength) {
|
||||
// Transportation limits the step, ie the track hit a boundary.
|
||||
*selection = CandidateForSelection;
|
||||
*selection = CandidateForSelection;
|
||||
continueStepping = false;
|
||||
}
|
||||
if(fTransportEndKineticEnergy != currentEnergy)
|
||||
{
|
||||
if (fTransportEndKineticEnergy != currentEnergy) {
|
||||
// Field propagation changed the energy, it's not possible to
|
||||
// estimate the continuous energy loss and continue stepping.
|
||||
continueStepping = false;
|
||||
}
|
||||
|
||||
if(firstStep)
|
||||
{
|
||||
if (firstStep) {
|
||||
proposedSafety = currentSafety;
|
||||
}
|
||||
totalGeometryStepLength += geometryStepLength;
|
||||
|
||||
// Sample MSC direction change and displacement.
|
||||
const G4double range =
|
||||
mscModel->GetRange(particleDefinition, currentEnergy, couple);
|
||||
const G4double range = mscModel->GetRange(particleDefinition, currentEnergy, couple);
|
||||
|
||||
tPathLength = mscModel->ComputeTrueStepLength(geometryStepLength);
|
||||
|
||||
@@ -343,27 +368,23 @@ G4double G4TransportationWithMsc::AlongStepGetPhysicalInteractionLength(
|
||||
tPathLength = std::min(tPathLength, stepLimitLeft);
|
||||
|
||||
totalTruePathLength += tPathLength;
|
||||
if(*selection != CandidateForSelection && !mscLimitsStep)
|
||||
{
|
||||
if (*selection != CandidateForSelection && !mscLimitsStep) {
|
||||
// If neither MSC nor transportation limits the step, we got the
|
||||
// distance we want - make sure we exit the loop.
|
||||
continueStepping = false;
|
||||
}
|
||||
else if(tPathLength >= range)
|
||||
{
|
||||
else if (tPathLength >= range) {
|
||||
// The particle will stop, exit the loop.
|
||||
continueStepping = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
stepLimitLeft -= tPathLength;
|
||||
}
|
||||
|
||||
// Do not sample scattering at the last or at a small step.
|
||||
if(tPathLength < range && tPathLength > kGeomMin)
|
||||
{
|
||||
if (tPathLength < range && tPathLength > kGeomMin) {
|
||||
static constexpr G4double minSafety = 1.20 * CLHEP::nm;
|
||||
static constexpr G4double sFact = 0.99;
|
||||
static constexpr G4double sFact = 0.99;
|
||||
|
||||
// The call to SampleScattering() *may* directly fill in the changed
|
||||
// direction into fParticleChangeForMSC, so we have to:
|
||||
@@ -372,74 +393,61 @@ G4double G4TransportationWithMsc::AlongStepGetPhysicalInteractionLength(
|
||||
// 2) Call SampleScattering(), which *may* change it.
|
||||
const G4ThreeVector displacement =
|
||||
mscModel->SampleScattering(fTransportEndMomentumDir, minSafety);
|
||||
// 3) Get the changed direction and inform G4Transportation.
|
||||
fMomentumChanged = true;
|
||||
// 3) Get the changed direction.
|
||||
fTransportEndMomentumDir = *fParticleChangeForMSC->GetProposedMomentumDirection();
|
||||
|
||||
const G4double r2 = displacement.mag2();
|
||||
if(r2 > kMinDisplacement2)
|
||||
{
|
||||
if (r2 > kMinDisplacement2) {
|
||||
G4bool positionChanged = true;
|
||||
G4double dispR = std::sqrt(r2);
|
||||
G4double postSafety = sFact * fpSafetyHelper->ComputeSafety(
|
||||
fTransportEndPosition, dispR);
|
||||
G4double dispR = std::sqrt(r2);
|
||||
G4double postSafety =
|
||||
sFact * fpSafetyHelper->ComputeSafety(fTransportEndPosition, dispR);
|
||||
|
||||
// Far away from geometry boundary
|
||||
if(postSafety > 0.0 && dispR <= postSafety)
|
||||
{
|
||||
if (postSafety > 0.0 && dispR <= postSafety) {
|
||||
fTransportEndPosition += displacement;
|
||||
|
||||
// Near the boundary
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// displaced point is definitely within the volume
|
||||
if(dispR < postSafety)
|
||||
{
|
||||
if (dispR < postSafety) {
|
||||
fTransportEndPosition += displacement;
|
||||
|
||||
// reduced displacement
|
||||
}
|
||||
else if(postSafety > kGeomMin)
|
||||
{
|
||||
else if (postSafety > kGeomMin) {
|
||||
fTransportEndPosition += displacement * (postSafety / dispR);
|
||||
|
||||
// very small postSafety
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
positionChanged = false;
|
||||
}
|
||||
}
|
||||
if(positionChanged)
|
||||
{
|
||||
if (positionChanged) {
|
||||
fpSafetyHelper->ReLocateWithinVolume(fTransportEndPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(continueStepping)
|
||||
{
|
||||
if (continueStepping) {
|
||||
// Update safety according to the geometry distance.
|
||||
if(currentSafety < fEndPointDistance)
|
||||
{
|
||||
if (currentSafety < fEndPointDistance) {
|
||||
currentSafety = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
currentSafety -= fEndPointDistance;
|
||||
}
|
||||
|
||||
// Update the kinetic energy according to the continuous loss.
|
||||
currentEnergy = mscModel->GetEnergy(particleDefinition,
|
||||
range - tPathLength, couple);
|
||||
currentEnergy = mscModel->GetEnergy(particleDefinition, range - tPathLength, couple);
|
||||
|
||||
// From now on, use the track that we can update below.
|
||||
currentTrackPtr = fSubStepTrack;
|
||||
|
||||
fSubStepDynamicParticle->SetKineticEnergy(currentEnergy);
|
||||
fSubStepDynamicParticle->SetMomentumDirection(
|
||||
fTransportEndMomentumDir);
|
||||
fSubStepDynamicParticle->SetMomentumDirection(fTransportEndMomentumDir);
|
||||
fSubStepTrack->SetPosition(fTransportEndPosition);
|
||||
|
||||
G4StepPoint& subPreStepPoint = *fSubStep->GetPreStepPoint();
|
||||
@@ -449,14 +457,13 @@ G4double G4TransportationWithMsc::AlongStepGetPhysicalInteractionLength(
|
||||
subPreStepPoint.SetStepStatus(fAlongStepDoItProc);
|
||||
}
|
||||
firstStep = false;
|
||||
} while(continueStepping);
|
||||
} while (continueStepping);
|
||||
|
||||
// Note: currentEnergy is only updated if continueStepping is true.
|
||||
// In case field propagation changed the energy, this flag is
|
||||
// immediately set to false and currentEnergy is still equal to the
|
||||
// initial kinetic energy stored in ekin.
|
||||
if(currentEnergy != ekin)
|
||||
{
|
||||
if (currentEnergy != ekin) {
|
||||
// If field propagation didn't change the energy and we potentially
|
||||
// did multiple steps, reset the energy that G4Transportation will
|
||||
// propose to not subtract the energy loss twice.
|
||||
@@ -464,13 +471,192 @@ G4double G4TransportationWithMsc::AlongStepGetPhysicalInteractionLength(
|
||||
// Also ask for the range again with the initial energy so it is
|
||||
// correctly cached in the G4VEnergyLossProcess.
|
||||
// FIXME: Asking for a range should never change the cached values!
|
||||
(void) mscModel->GetRange(particleDefinition, ekin, couple);
|
||||
(void)mscModel->GetRange(particleDefinition, ekin, couple);
|
||||
}
|
||||
|
||||
fParticleChange.ProposeTrueStepLength(totalTruePathLength);
|
||||
|
||||
// Inform G4Transportation that the momentum might have changed due
|
||||
// to scattering. We do this unconditionally to avoid the situation
|
||||
// where the last step is done without MSC and G4Transportation reset
|
||||
// the flag, for example when running without field.
|
||||
fMomentumChanged = true;
|
||||
|
||||
return totalGeometryStepLength;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ScatteringType::SingleScattering: {
|
||||
// Select the model for the current kinetic energy.
|
||||
const G4double ekin = track.GetKineticEnergy();
|
||||
const auto* couple = track.GetMaterialCutsCouple();
|
||||
const auto* particleDefinition = track.GetParticleDefinition();
|
||||
|
||||
G4double ekinForSelection = ekin;
|
||||
G4double pdgMass = particleDefinition->GetPDGMass();
|
||||
if (pdgMass > CLHEP::GeV) {
|
||||
ekinForSelection *= proton_mass_c2 / pdgMass;
|
||||
}
|
||||
|
||||
G4VEmModel* currentModel = fModelManager->SelectModel(ekinForSelection, couple->GetIndex());
|
||||
if (currentModel == nullptr) {
|
||||
G4Exception("G4TransportationWithMsc::AlongStepGPIL", "em0052", FatalException,
|
||||
"no scattering model found");
|
||||
}
|
||||
if (!currentModel->IsActive(ekinForSelection)) {
|
||||
currentModel = nullptr;
|
||||
}
|
||||
|
||||
if (currentModel != nullptr) {
|
||||
currentModel->SetCurrentCouple(couple);
|
||||
G4int coupleIndex = couple->GetIndex();
|
||||
|
||||
// Compute mean free path.
|
||||
G4double logEkin = track.GetDynamicParticle()->GetLogKineticEnergy();
|
||||
G4double lambda = ((*fLambdaTable)[coupleIndex])->LogVectorValue(ekin, logEkin);
|
||||
if (lambda > 0.0) {
|
||||
// Assume that the mean free path and dE/dx are constant along the
|
||||
// step, which is a valid approximation for most cases.
|
||||
G4double meanFreePath = 1.0 / lambda;
|
||||
G4double dedx = fIonisation->GetDEDX(ekin, couple);
|
||||
|
||||
G4double currentSafety = proposedSafety;
|
||||
G4double currentEnergy = ekin;
|
||||
|
||||
// Use the provided track for the first step.
|
||||
const G4Track* currentTrackPtr = &track;
|
||||
|
||||
G4double stepLimitLeft = physStepLimit;
|
||||
G4double totalStepLength = 0;
|
||||
G4bool firstStep = true, continueStepping = fMultipleSteps;
|
||||
|
||||
do {
|
||||
G4double interactionLength = meanFreePath * -G4Log(G4UniformRand());
|
||||
|
||||
G4bool ssLimitsStep = (interactionLength < stepLimitLeft);
|
||||
G4double gPathLength = stepLimitLeft;
|
||||
if (ssLimitsStep) {
|
||||
if (!fMultipleSteps) {
|
||||
// Scattering limits the step.
|
||||
*selection = CandidateForSelection;
|
||||
}
|
||||
gPathLength = interactionLength;
|
||||
}
|
||||
|
||||
if (!firstStep) {
|
||||
// Move the navigator to where the previous step ended.
|
||||
fLinearNavigator->LocateGlobalPointWithinVolume(fTransportEndPosition);
|
||||
}
|
||||
|
||||
G4GPILSelection transportSelection;
|
||||
G4double geometryStepLength = G4Transportation::AlongStepGetPhysicalInteractionLength(
|
||||
*currentTrackPtr, previousStepSize, gPathLength, currentSafety, &transportSelection);
|
||||
if (geometryStepLength < gPathLength) {
|
||||
// Transportation limits the step, ie the track hit a boundary.
|
||||
*selection = CandidateForSelection;
|
||||
ssLimitsStep = false;
|
||||
continueStepping = false;
|
||||
}
|
||||
if (fTransportEndKineticEnergy != currentEnergy) {
|
||||
// Field propagation changed the energy, it's not possible to
|
||||
// estimate the continuous energy loss and continue stepping.
|
||||
continueStepping = false;
|
||||
}
|
||||
|
||||
if (firstStep) {
|
||||
proposedSafety = currentSafety;
|
||||
}
|
||||
totalStepLength += geometryStepLength;
|
||||
|
||||
if (*selection != CandidateForSelection && !ssLimitsStep) {
|
||||
// If neither scattering nor transportation limits the step, we
|
||||
// got the distance we want - make sure we exit the loop.
|
||||
continueStepping = false;
|
||||
}
|
||||
else {
|
||||
stepLimitLeft -= geometryStepLength;
|
||||
}
|
||||
|
||||
// Update the kinetic energy according to the continuous loss.
|
||||
G4double energyAfterLinearLoss =
|
||||
fTransportEndKineticEnergy - geometryStepLength * dedx;
|
||||
|
||||
if (ssLimitsStep) {
|
||||
fSubStepDynamicParticle->SetKineticEnergy(energyAfterLinearLoss);
|
||||
|
||||
// The call to SampleSecondaries() directly fills in the changed
|
||||
// direction into fParticleChangeForSS, so we have to:
|
||||
// 1) Set the momentum direction in dynamic particle.
|
||||
fSubStepDynamicParticle->SetMomentumDirection(fTransportEndMomentumDir);
|
||||
// 2) Call SampleSecondaries(), which changes the direction.
|
||||
currentModel->SampleSecondaries(fSecondariesSS, couple, fSubStepDynamicParticle,
|
||||
(*fCuts)[coupleIndex]);
|
||||
// 3) Get the changed direction.
|
||||
fTransportEndMomentumDir = fParticleChangeForSS->GetProposedMomentumDirection();
|
||||
|
||||
// Check that the model neither created secondaries nor proposed
|
||||
// a local energy deposit because this process does not know how
|
||||
// to handle these cases.
|
||||
if (fSecondariesSS->size() > 0) {
|
||||
G4Exception("G4TransportationWithMsc::AlongStepGPIL", "em0053", FatalException,
|
||||
"scattering model created secondaries");
|
||||
}
|
||||
if (fParticleChangeForSS->GetLocalEnergyDeposit() > 0) {
|
||||
G4Exception("G4TransportationWithMsc::AlongStepGPIL", "em0053", FatalException,
|
||||
"scattering model proposed energy deposit");
|
||||
}
|
||||
}
|
||||
|
||||
if (continueStepping) {
|
||||
// Update safety according to the geometry distance.
|
||||
if (currentSafety < fEndPointDistance) {
|
||||
currentSafety = 0;
|
||||
}
|
||||
else {
|
||||
currentSafety -= fEndPointDistance;
|
||||
}
|
||||
|
||||
// Update the energy taking continuous loss into account.
|
||||
currentEnergy = energyAfterLinearLoss;
|
||||
|
||||
// From now on, use the track that we can update below.
|
||||
currentTrackPtr = fSubStepTrack;
|
||||
|
||||
fSubStepDynamicParticle->SetKineticEnergy(currentEnergy);
|
||||
fSubStepDynamicParticle->SetMomentumDirection(fTransportEndMomentumDir);
|
||||
fSubStepTrack->SetPosition(fTransportEndPosition);
|
||||
|
||||
G4StepPoint& subPreStepPoint = *fSubStep->GetPreStepPoint();
|
||||
subPreStepPoint.SetMaterialCutsCouple(couple);
|
||||
subPreStepPoint.SetPosition(fTransportEndPosition);
|
||||
subPreStepPoint.SetSafety(currentSafety);
|
||||
subPreStepPoint.SetStepStatus(fAlongStepDoItProc);
|
||||
}
|
||||
firstStep = false;
|
||||
} while (continueStepping);
|
||||
|
||||
// Note: currentEnergy is only updated if continueStepping is true.
|
||||
// In case field propagation changed the energy, this flag is
|
||||
// immediately set to false and currentEnergy is still equal to the
|
||||
// initial kinetic energy stored in ekin.
|
||||
if (currentEnergy != ekin) {
|
||||
// If field propagation didn't change the energy and we potentially
|
||||
// did multiple steps, reset the energy that G4Transportation will
|
||||
// propose to not subtract the energy loss twice.
|
||||
fTransportEndKineticEnergy = ekin;
|
||||
}
|
||||
|
||||
fParticleChange.ProposeTrueStepLength(totalStepLength);
|
||||
|
||||
// Inform G4Transportation that the momentum might have changed due
|
||||
// to scattering, even if there is no field.
|
||||
fMomentumChanged = true;
|
||||
|
||||
return totalStepLength;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user