Files
geant4/source/processes/electromagnetic/utils/src/G4VMultipleScattering.cc
T
2016-06-09 10:28:22 +02:00

343 lines
11 KiB
C++

//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * 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. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4VMultipleScattering
//
// Author: Vladimir Ivanchenko on base of Laszlo Urban code
//
// Creation date: 25.03.2003
//
// Modifications:
//
// 13.04.03 Change printout (V.Ivanchenko)
// 04-06-03 Fix compilation warnings (V.Ivanchenko)
//
//
// Class Description:
//
// It is the generic process of multiple scattering it includes common
// part of calculations for all charged particles
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4VMultipleScattering.hh"
#include "G4LossTableManager.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4VEmModel.hh"
#include "G4VEmFluctuationModel.hh"
#include "G4DataVector.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsVector.hh"
#include "G4PhysicsLogVector.hh"
#include "G4UnitsTable.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Region.hh"
#include "G4RegionStore.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VMultipleScattering::G4VMultipleScattering(const G4String& name, G4ProcessType type):
G4VContinuousDiscreteProcess(name, type),
navigator(0),
theLambdaTable(0),
currentCouple(0),
nBins(110),
minKinEnergy(1.0*eV),
maxKinEnergy(100.0*GeV),
boundary(false),
latDisplasment(true),
buildLambdaTable(true)
{
modelManager = new G4EmModelManager();
(G4LossTableManager::Instance())->Register(this);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VMultipleScattering::~G4VMultipleScattering()
{
(G4LossTableManager::Instance())->DeRegister(this);
delete modelManager;
if (theLambdaTable) {
theLambdaTable->clearAndDestroy();
delete theLambdaTable;
}
(G4LossTableManager::Instance())->DeRegister(this);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::BuildPhysicsTable(const G4ParticleDefinition& part)
{
currentCouple = 0;
if(0 < verboseLevel) {
G4cout << "G4VMultipleScattering::BuildPhysicsTable() for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< G4endl;
}
G4bool cutsWasModified = false;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for (size_t j=0; j<numOfCouples; j++){
if (theCoupleTable->GetMaterialCutsCouple(j)->IsRecalcNeeded()) {
cutsWasModified = true;
break;
}
}
if( !cutsWasModified ) return;
InitialiseProcess(part);
if(latDisplasment) navigator = G4TransportationManager::GetTransportationManager()
->GetNavigatorForTracking();
modelManager->Clear();
const G4DataVector* theCuts = modelManager->Initialise(&part, 0, 10.0, verboseLevel);
if (buildLambdaTable) {
theLambdaTable = new G4PhysicsTable(numOfCouples);
for (size_t i=0; i<numOfCouples; i++) {
// create physics vector and fill it
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
G4PhysicsVector* aVector = PhysicsVector(couple);
modelManager->FillLambdaVector(aVector, couple, false);
// Insert vector for this material into the table
theLambdaTable->insert(aVector) ;
}
if(0 < verboseLevel) {
G4cout << "Lambda table is built for "
<< part.GetParticleName()
<< G4endl;
}
if(2 < verboseLevel) G4cout << *theLambdaTable << G4endl;
if(5 < verboseLevel) G4cout << theCuts << G4endl;
}
G4String num = part.GetParticleName();
if (verboseLevel>0 || num == "e-" || num == "mu+" || num == "proton")
PrintInfoDefinition();
if(0 < verboseLevel) {
G4cout << "G4VMultipleScattering::BuildPhysicsTable() done for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::AddEmModel(G4int order, G4VEmModel* p,
const G4Region* region)
{
G4VEmFluctuationModel* fm = 0;
modelManager->AddEmModel(order, p, fm, region);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4VMultipleScattering::PostStepDoIt(const G4Track& track,
const G4Step& step)
{
fParticleChange.Initialize(track);
G4double kineticEnergy = track.GetKineticEnergy();
G4double truestep = step.GetStepLength();
if (kineticEnergy > 0.0) {
G4double cth = currentModel->SampleCosineTheta(truestep);
G4double sth = sqrt(1.-cth*cth);
G4double phi = twopi*G4UniformRand();
G4double dirx = sth*cos(phi);
G4double diry = sth*sin(phi);
G4ThreeVector oldDirection = track.GetMomentumDirection();
G4ThreeVector newDirection(dirx,diry,cth);
newDirection.rotateUz(oldDirection);
fParticleChange.SetMomentumChange(newDirection);
/*
if(0 < verboseLevel) {
const G4ParticleDefinition* pd = dynParticle->GetDefinition();
G4cout << "G4VMultipleScattering::PostStepDoIt: Sample secondary; E= " << finalT/MeV
<< " MeV; model= (" << currentModel->LowEnergyLimit(pd)
<< ", " << currentModel->HighEnergyLimit(pd) << ")"
<< G4endl;
}
*/
// G4cout << "PostStep: sth= " << sth << " trueLength= " << truestep << " tLast= " << truePathLength << G4endl;
if (latDisplasment) {
G4double safety = step.GetPostStepPoint()->GetSafety();
if ( safety > 0.0) {
G4double r = currentModel->SampleDisplacement();
if (r > safety) r = safety;
// G4cout << "r= " << r << " safety= " << safety << G4endl;
// sample direction of lateral displacement
G4double phi = twopi*G4UniformRand();
G4double dirx = cos(phi);
G4double diry = sin(phi);
G4ThreeVector latDirection(dirx,diry,0.0);
latDirection.rotateUz(oldDirection);
// compute new endpoint of the Step
G4ThreeVector newPosition = (step.GetPostStepPoint())->GetPosition()
+ r*latDirection;
navigator->LocateGlobalPointWithinVolume(newPosition);
fParticleChange.SetPositionChange(newPosition);
}
}
}
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VMultipleScattering::PrintInfoDefinition()
{
G4cout << G4endl << GetProcessName() << ": Model variant of multiple scattering " << G4endl;
if (theLambdaTable) {
G4cout << " Lambda tables from "
<< G4BestUnit(MinKinEnergy(),"Energy")
<< " to "
<< G4BestUnit(MaxKinEnergy(),"Energy")
<< " in " << nBins << " bins."
<< G4endl;
}
if (1 < verboseLevel) {
G4cout << "LambdaTable address= " << theLambdaTable << G4endl;
if(theLambdaTable) G4cout << (*theLambdaTable) << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector* G4VMultipleScattering::PhysicsVector(const G4MaterialCutsCouple* couple)
{
G4int nbins = 3;
//G4int nbins = nDEDXBins;
if( couple->IsUsed() ) nbins = nBins;
// G4double xmax = maxKinEnergy*exp( log(maxKinEnergy/minKinEnergy) / ((G4double)(nbins-1)) );
G4PhysicsVector* v = new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nbins);
return v;
}
G4bool G4VMultipleScattering::StorePhysicsTable(G4ParticleDefinition* part,
const G4String& directory,
G4bool ascii)
{
G4bool res = true;
if ( theLambdaTable ) {
const G4String name = GetPhysicsTableFileName(part,directory,"Lambda",ascii);
G4bool yes = theLambdaTable->StorePhysicsTable(name,ascii);
if( !yes ) res = false;
}
if ( res ) {
G4cout << "Physics table are stored for " << part->GetParticleName()
<< " and process " << GetProcessName()
<< " in the directory <" << directory
<< "> " << G4endl;
} else {
G4cout << "Fail to store Physics Table for " << part->GetParticleName()
<< " and process " << GetProcessName()
<< " in the directory <" << directory
<< "> " << G4endl;
}
return res;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4VMultipleScattering::RetrievePhysicsTable(G4ParticleDefinition* part,
const G4String& directory,
G4bool ascii)
{
if(0 < verboseLevel) {
G4cout << "G4VMultipleScattering::RetrievePhysicsTable() for "
<< part->GetParticleName() << " and process "
<< GetProcessName() << G4endl;
}
G4bool res = true;
if(!buildLambdaTable) return res;
G4String num = part->GetParticleName();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
G4String filename = GetPhysicsTableFileName(part,directory,"Lambda",ascii);
theLambdaTable = new G4PhysicsTable(numOfCouples);
res = theLambdaTable->RetrievePhysicsTable(filename,ascii);
if ( res ) {
if (0 < verboseLevel) {
G4cout << "Lambda table for " << num << " is retrieved from <"
<< filename << ">"
<< G4endl;
}
} else {
theLambdaTable->clearAndDestroy();
theLambdaTable = 0;
if (0 < verboseLevel) {
G4cout << "Lambda table for " << num << " in file <"
<< filename << "> is not exist"
<< G4endl;
}
}
if (verboseLevel>0 || num == "e-" || num == "mu+" || num == "proton")
PrintInfoDefinition();
return res;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....