1112 lines
35 KiB
C++
1112 lines
35 KiB
C++
//
|
|
// ********************************************************************
|
|
// * 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. *
|
|
// ********************************************************************
|
|
//
|
|
// G4VUserPhysicsList implementation
|
|
//
|
|
// Original author: H.Kurashige (Kobe University), 9 January 1998
|
|
// --------------------------------------------------------------------
|
|
|
|
#include "G4PhysicsListHelper.hh"
|
|
#include "G4VUserPhysicsList.hh"
|
|
|
|
#include "G4Material.hh"
|
|
#include "G4MaterialCutsCouple.hh"
|
|
#include "G4ParticleDefinition.hh"
|
|
#include "G4ParticleTable.hh"
|
|
#include "G4ProcessManager.hh"
|
|
#include "G4ProductionCuts.hh"
|
|
#include "G4ProductionCutsTable.hh"
|
|
#include "G4Region.hh"
|
|
#include "G4RegionStore.hh"
|
|
#include "G4SystemOfUnits.hh"
|
|
#include "G4UImanager.hh"
|
|
#include "G4UnitsTable.hh"
|
|
#include "G4UserPhysicsListMessenger.hh"
|
|
#include "G4VTrackingManager.hh"
|
|
#include "G4ios.hh"
|
|
#include "globals.hh"
|
|
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <unordered_set>
|
|
|
|
// This static member is thread local. For each thread, it holds the array
|
|
// size of G4VUPLData instances.
|
|
//
|
|
#define G4MT_theMessenger \
|
|
((this->subInstanceManager.offset[this->g4vuplInstanceID])._theMessenger)
|
|
#define G4MT_thePLHelper \
|
|
((this->subInstanceManager.offset[this->g4vuplInstanceID])._thePLHelper)
|
|
#define fIsPhysicsTableBuilt \
|
|
((this->subInstanceManager.offset[this->g4vuplInstanceID]) \
|
|
._fIsPhysicsTableBuilt)
|
|
#define fDisplayThreshold \
|
|
((this->subInstanceManager.offset[this->g4vuplInstanceID])._fDisplayThreshold)
|
|
#define theParticleIterator \
|
|
((this->subInstanceManager.offset[this->g4vuplInstanceID]) \
|
|
._theParticleIterator)
|
|
|
|
// This field helps to use the class G4VUPLManager
|
|
//
|
|
G4VUPLManager G4VUserPhysicsList::subInstanceManager;
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUPLData::initialize()
|
|
{
|
|
_theParticleIterator = G4ParticleTable::GetParticleTable()->GetIterator();
|
|
_theMessenger = nullptr;
|
|
_thePLHelper = G4PhysicsListHelper::GetPhysicsListHelper();
|
|
_fIsPhysicsTableBuilt = false;
|
|
_fDisplayThreshold = 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
G4VUserPhysicsList::G4VUserPhysicsList()
|
|
{
|
|
g4vuplInstanceID = subInstanceManager.CreateSubInstance(); // AND
|
|
// default cut value (1.0mm)
|
|
defaultCutValue = 1.0 * mm;
|
|
|
|
// pointer to the particle table
|
|
theParticleTable = G4ParticleTable::GetParticleTable();
|
|
// theParticleIterator = theParticleTable->GetIterator();
|
|
|
|
// pointer to the cuts table
|
|
fCutsTable = G4ProductionCutsTable::GetProductionCutsTable();
|
|
|
|
// set energy range for SetCut calcuration
|
|
fCutsTable->SetEnergyRange(0.99 * keV, 100 * TeV);
|
|
|
|
// UI Messenger
|
|
// theMessenger = new G4UserPhysicsListMessenger(this);
|
|
G4MT_theMessenger = new G4UserPhysicsListMessenger(this); // AND
|
|
|
|
// PhysicsListHelper
|
|
// thePLHelper = G4PhysicsListHelper::GetPhysicsListHelper();
|
|
// thePLHelper->SetVerboseLevel(verboseLevel);
|
|
// G4MT_thePLHelper = G4PhysicsListHelper::GetPhysicsListHelper(); //AND
|
|
G4MT_thePLHelper->SetVerboseLevel(verboseLevel); // AND
|
|
|
|
fIsPhysicsTableBuilt = false;
|
|
fDisplayThreshold = 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::InitializeWorker()
|
|
{
|
|
// Remember messengers are per-thread, so this needs to be done by each
|
|
// worker and due to the presence of "this" cannot be done in
|
|
// G4VUPLData::initialize()
|
|
G4MT_theMessenger = new G4UserPhysicsListMessenger(this);
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::TerminateWorker()
|
|
{
|
|
RemoveProcessManager();
|
|
RemoveTrackingManager();
|
|
delete G4MT_theMessenger;
|
|
G4MT_theMessenger = nullptr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
G4VUserPhysicsList::~G4VUserPhysicsList()
|
|
{
|
|
delete G4MT_theMessenger;
|
|
G4MT_theMessenger = nullptr;
|
|
|
|
RemoveProcessManager();
|
|
RemoveTrackingManager();
|
|
|
|
// invoke DeleteAllParticle
|
|
theParticleTable->DeleteAllParticles();
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
G4VUserPhysicsList::G4VUserPhysicsList(const G4VUserPhysicsList& right)
|
|
: verboseLevel(right.verboseLevel)
|
|
, defaultCutValue(right.defaultCutValue)
|
|
, isSetDefaultCutValue(right.isSetDefaultCutValue)
|
|
, fRetrievePhysicsTable(right.fRetrievePhysicsTable)
|
|
, fStoredInAscii(right.fStoredInAscii)
|
|
, fIsCheckedForRetrievePhysicsTable(right.fIsCheckedForRetrievePhysicsTable)
|
|
, fIsRestoredCutValues(right.fIsRestoredCutValues)
|
|
, directoryPhysicsTable(right.directoryPhysicsTable)
|
|
, fDisableCheckParticleList(right.fDisableCheckParticleList)
|
|
{
|
|
g4vuplInstanceID = subInstanceManager.CreateSubInstance();
|
|
// pointer to the particle table
|
|
theParticleTable = G4ParticleTable::GetParticleTable();
|
|
theParticleIterator = theParticleTable->GetIterator();
|
|
// pointer to the cuts table
|
|
fCutsTable = G4ProductionCutsTable::GetProductionCutsTable();
|
|
|
|
// UI Messenger
|
|
G4MT_theMessenger = new G4UserPhysicsListMessenger(this);
|
|
|
|
// PhysicsListHelper
|
|
G4MT_thePLHelper = G4PhysicsListHelper::GetPhysicsListHelper();
|
|
G4MT_thePLHelper->SetVerboseLevel(verboseLevel);
|
|
|
|
fIsPhysicsTableBuilt = right.GetSubInstanceManager()
|
|
.offset[right.GetInstanceID()]
|
|
._fIsPhysicsTableBuilt;
|
|
fDisplayThreshold = right.GetSubInstanceManager()
|
|
.offset[right.GetInstanceID()]
|
|
._fDisplayThreshold;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
G4VUserPhysicsList&
|
|
G4VUserPhysicsList::operator=(const G4VUserPhysicsList& right)
|
|
{
|
|
if(this != &right)
|
|
{
|
|
verboseLevel = right.verboseLevel;
|
|
defaultCutValue = right.defaultCutValue;
|
|
isSetDefaultCutValue = right.isSetDefaultCutValue;
|
|
fRetrievePhysicsTable = right.fRetrievePhysicsTable;
|
|
fStoredInAscii = right.fStoredInAscii;
|
|
fIsCheckedForRetrievePhysicsTable = right.fIsCheckedForRetrievePhysicsTable;
|
|
fIsRestoredCutValues = right.fIsRestoredCutValues;
|
|
directoryPhysicsTable = right.directoryPhysicsTable;
|
|
fIsPhysicsTableBuilt = right.GetSubInstanceManager()
|
|
.offset[right.GetInstanceID()]
|
|
._fIsPhysicsTableBuilt;
|
|
fDisplayThreshold = right.GetSubInstanceManager()
|
|
.offset[right.GetInstanceID()]
|
|
._fDisplayThreshold;
|
|
fDisableCheckParticleList = right.fDisableCheckParticleList;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::AddProcessManager(G4ParticleDefinition* newParticle,
|
|
G4ProcessManager*)
|
|
{
|
|
if(newParticle == nullptr)
|
|
return;
|
|
G4Exception("G4VUserPhysicsList::AddProcessManager", "Run0252",
|
|
JustWarning, "This method is obsolete");
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::InitializeProcessManager()
|
|
{
|
|
// Request lock for particle table access. Some changes are inside
|
|
// this critical region.
|
|
#ifdef G4MULTITHREADED
|
|
G4MUTEXLOCK(&G4ParticleTable::particleTableMutex());
|
|
G4ParticleTable::lockCount()++;
|
|
#endif
|
|
G4ParticleDefinition* gion =
|
|
G4ParticleTable::GetParticleTable()->GetGenericIon();
|
|
|
|
// loop over all particles in G4ParticleTable
|
|
theParticleIterator->reset();
|
|
while((*theParticleIterator)())
|
|
{
|
|
G4ParticleDefinition* particle = theParticleIterator->value();
|
|
G4ProcessManager* pmanager = particle->GetProcessManager();
|
|
|
|
if(pmanager == nullptr)
|
|
{
|
|
// create process manager if the particle does not have its own.
|
|
pmanager = new G4ProcessManager(particle);
|
|
particle->SetProcessManager(pmanager);
|
|
if(particle->GetMasterProcessManager() == nullptr)
|
|
particle->SetMasterProcessManager(pmanager);
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::InitializeProcessManager: creating "
|
|
"ProcessManager to "
|
|
<< particle->GetParticleName() << G4endl;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if(gion != nullptr)
|
|
{
|
|
G4ProcessManager* gionPM = gion->GetProcessManager();
|
|
// loop over all particles once again (this time, with all general ions)
|
|
theParticleIterator->reset(false);
|
|
while((*theParticleIterator)())
|
|
{
|
|
G4ParticleDefinition* particle = theParticleIterator->value();
|
|
if(particle->IsGeneralIon())
|
|
{
|
|
particle->SetProcessManager(gionPM);
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::InitializeProcessManager: copying "
|
|
"ProcessManager to "
|
|
<< particle->GetParticleName() << G4endl;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
// release lock for particle table access
|
|
#ifdef G4MULTITHREADED
|
|
G4MUTEXUNLOCK(&G4ParticleTable::particleTableMutex());
|
|
#endif
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::RemoveProcessManager()
|
|
{
|
|
// Request lock for particle table access. Some changes are inside
|
|
// this critical region.
|
|
#ifdef G4MULTITHREADED
|
|
G4MUTEXLOCK(&G4ParticleTable::particleTableMutex());
|
|
G4ParticleTable::lockCount()++;
|
|
#endif
|
|
|
|
// loop over all particles in G4ParticleTable
|
|
theParticleIterator->reset();
|
|
while((*theParticleIterator)())
|
|
{
|
|
G4ParticleDefinition* particle = theParticleIterator->value();
|
|
if(particle->GetInstanceID() <
|
|
G4ParticleDefinitionSubInstanceManager::slavetotalspace())
|
|
{
|
|
if(particle->GetParticleSubType() != "generic" ||
|
|
particle->GetParticleName() == "GenericIon")
|
|
{
|
|
G4ProcessManager* pmanager = particle->GetProcessManager();
|
|
if(pmanager != nullptr)
|
|
delete pmanager;
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::RemoveProcessManager: ";
|
|
G4cout << "remove ProcessManager from ";
|
|
G4cout << particle->GetParticleName() << G4endl;
|
|
}
|
|
#endif
|
|
}
|
|
particle->SetProcessManager(nullptr);
|
|
}
|
|
}
|
|
|
|
// release lock for particle table access
|
|
#ifdef G4MULTITHREADED
|
|
G4MUTEXUNLOCK(&G4ParticleTable::particleTableMutex());
|
|
#endif
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::RemoveTrackingManager()
|
|
{
|
|
// One tracking manager may be registered for multiple particles, make sure
|
|
// to delete every object only once.
|
|
std::unordered_set<G4VTrackingManager *> trackingManagers;
|
|
|
|
// loop over all particles in G4ParticleTable
|
|
theParticleIterator->reset();
|
|
while((*theParticleIterator)())
|
|
{
|
|
G4ParticleDefinition* particle = theParticleIterator->value();
|
|
if (auto *trackingManager = particle->GetTrackingManager())
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::RemoveTrackingManager: ";
|
|
G4cout << "remove TrackingManager from ";
|
|
G4cout << particle->GetParticleName() << G4endl;
|
|
}
|
|
#endif
|
|
trackingManagers.insert(trackingManager);
|
|
particle->SetTrackingManager(nullptr);
|
|
}
|
|
}
|
|
|
|
for (G4VTrackingManager *tm : trackingManagers)
|
|
{
|
|
delete tm;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetCuts()
|
|
{
|
|
if(!isSetDefaultCutValue)
|
|
{
|
|
SetDefaultCutValue(defaultCutValue);
|
|
}
|
|
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 1)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::SetCuts: " << G4endl;
|
|
G4cout << "Cut for gamma: " << GetCutValue("gamma") / mm << "[mm]"
|
|
<< G4endl;
|
|
G4cout << "Cut for e-: " << GetCutValue("e-") / mm << "[mm]" << G4endl;
|
|
G4cout << "Cut for e+: " << GetCutValue("e+") / mm << "[mm]" << G4endl;
|
|
G4cout << "Cut for proton: " << GetCutValue("proton") / mm << "[mm]"
|
|
<< G4endl;
|
|
}
|
|
#endif
|
|
|
|
// dump Cut values if verboseLevel==3
|
|
if(verboseLevel > 2)
|
|
{
|
|
DumpCutValuesTable();
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetDefaultCutValue(G4double value)
|
|
{
|
|
if(value < 0.0)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::SetDefaultCutValue: negative cut values"
|
|
<< " :" << value / mm << "[mm]" << G4endl;
|
|
}
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
defaultCutValue = value;
|
|
isSetDefaultCutValue = true;
|
|
|
|
// set cut values for gamma at first and for e- and e+
|
|
SetCutValue(defaultCutValue, "gamma");
|
|
SetCutValue(defaultCutValue, "e-");
|
|
SetCutValue(defaultCutValue, "e+");
|
|
SetCutValue(defaultCutValue, "proton");
|
|
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 1)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::SetDefaultCutValue:"
|
|
<< "default cut value is changed to :" << defaultCutValue / mm
|
|
<< "[mm]" << G4endl;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
G4double G4VUserPhysicsList::GetCutValue(const G4String& name) const
|
|
{
|
|
std::size_t nReg = (G4RegionStore::GetInstance())->size();
|
|
if(nReg == 0)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::GetCutValue "
|
|
<< " : No Default Region " << G4endl;
|
|
}
|
|
#endif
|
|
G4Exception("G4VUserPhysicsList::GetCutValue", "Run0253", FatalException,
|
|
"No Default Region");
|
|
return -1. * mm;
|
|
}
|
|
G4Region* region =
|
|
G4RegionStore::GetInstance()->GetRegion("DefaultRegionForTheWorld", false);
|
|
return region->GetProductionCuts()->GetProductionCut(name);
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetCutValue(G4double aCut, const G4String& name)
|
|
{
|
|
SetParticleCuts(aCut, name);
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetCutValue(G4double aCut, const G4String& pname,
|
|
const G4String& rname)
|
|
{
|
|
G4Region* region = G4RegionStore::GetInstance()->GetRegion(rname);
|
|
if(region != nullptr)
|
|
{
|
|
// set cut value
|
|
SetParticleCuts(aCut, pname, region);
|
|
}
|
|
else
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::SetCutValue "
|
|
<< " : No Region of " << rname << G4endl;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetCutsWithDefault()
|
|
{
|
|
SetDefaultCutValue(defaultCutValue);
|
|
G4VUserPhysicsList::SetCuts();
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetCutsForRegion(G4double aCut, const G4String& rname)
|
|
{
|
|
// set cut values for gamma at first and for e- and e+
|
|
SetCutValue(aCut, "gamma", rname);
|
|
SetCutValue(aCut, "e-", rname);
|
|
SetCutValue(aCut, "e+", rname);
|
|
SetCutValue(aCut, "proton", rname);
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetParticleCuts(G4double cut,
|
|
G4ParticleDefinition* particle,
|
|
G4Region* region)
|
|
{
|
|
SetParticleCuts(cut, particle->GetParticleName(), region);
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetParticleCuts(G4double cut,
|
|
const G4String& particleName,
|
|
G4Region* region)
|
|
{
|
|
if(cut < 0.0)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::SetParticleCuts: negative cut values"
|
|
<< " :" << cut / mm << "[mm]"
|
|
<< " for " << particleName << G4endl;
|
|
}
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
G4Region* world_region =
|
|
G4RegionStore::GetInstance()->GetRegion("DefaultRegionForTheWorld", false);
|
|
if(region == nullptr)
|
|
{
|
|
std::size_t nReg = G4RegionStore::GetInstance()->size();
|
|
if(nReg == 0)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::SetParticleCuts "
|
|
<< " : No Default Region " << G4endl;
|
|
}
|
|
#endif
|
|
G4Exception("G4VUserPhysicsList::SetParticleCuts ", "Run0254",
|
|
FatalException, "No Default Region");
|
|
return;
|
|
}
|
|
region = world_region;
|
|
}
|
|
|
|
if(!isSetDefaultCutValue)
|
|
{
|
|
SetDefaultCutValue(defaultCutValue);
|
|
}
|
|
|
|
G4ProductionCuts* pcuts = region->GetProductionCuts();
|
|
if(region != world_region &&
|
|
pcuts == G4ProductionCutsTable::GetProductionCutsTable()
|
|
->GetDefaultProductionCuts())
|
|
{ // This region had no unique cuts yet but shares the default cuts.
|
|
// Need to create a new object before setting the value.
|
|
pcuts =
|
|
new G4ProductionCuts(*(G4ProductionCutsTable::GetProductionCutsTable()
|
|
->GetDefaultProductionCuts()));
|
|
region->SetProductionCuts(pcuts);
|
|
}
|
|
pcuts->SetProductionCut(cut, particleName);
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::SetParticleCuts: "
|
|
<< " :" << cut / mm << "[mm]"
|
|
<< " for " << particleName << G4endl;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::BuildPhysicsTable()
|
|
{
|
|
// Prepare Physics table for all particles
|
|
theParticleIterator->reset();
|
|
while((*theParticleIterator)())
|
|
{
|
|
G4ParticleDefinition* particle = theParticleIterator->value();
|
|
PreparePhysicsTable(particle);
|
|
}
|
|
|
|
// ask processes to prepare physics table
|
|
if(fRetrievePhysicsTable)
|
|
{
|
|
fIsRestoredCutValues =
|
|
fCutsTable->RetrieveCutsTable(directoryPhysicsTable, fStoredInAscii);
|
|
// check if retrieve Cut Table successfully
|
|
if(!fIsRestoredCutValues)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildPhysicsTable"
|
|
<< " Retrieve Cut Table failed !!" << G4endl;
|
|
}
|
|
#endif
|
|
G4Exception("G4VUserPhysicsList::BuildPhysicsTable", "Run0255",
|
|
RunMustBeAborted, "Fail to retrieve Production Cut Table");
|
|
}
|
|
else
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildPhysicsTable"
|
|
<< " Retrieve Cut Table successfully " << G4endl;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildPhysicsTable"
|
|
<< " does not retrieve Cut Table but calculate " << G4endl;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// Sets a value to particle
|
|
// set cut values for gamma at first and for e- and e+
|
|
G4String particleName;
|
|
G4ParticleDefinition* GammaP = theParticleTable->FindParticle("gamma");
|
|
if(GammaP)
|
|
BuildPhysicsTable(GammaP);
|
|
G4ParticleDefinition* EMinusP = theParticleTable->FindParticle("e-");
|
|
if(EMinusP)
|
|
BuildPhysicsTable(EMinusP);
|
|
G4ParticleDefinition* EPlusP = theParticleTable->FindParticle("e+");
|
|
if(EPlusP)
|
|
BuildPhysicsTable(EPlusP);
|
|
G4ParticleDefinition* ProtonP = theParticleTable->FindParticle("proton");
|
|
if(ProtonP)
|
|
BuildPhysicsTable(ProtonP);
|
|
|
|
theParticleIterator->reset();
|
|
while((*theParticleIterator)())
|
|
{
|
|
G4ParticleDefinition* particle = theParticleIterator->value();
|
|
if(particle != GammaP && particle != EMinusP && particle != EPlusP &&
|
|
particle != ProtonP)
|
|
{
|
|
BuildPhysicsTable(particle);
|
|
}
|
|
}
|
|
|
|
// Set flag
|
|
fIsPhysicsTableBuilt = true;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::BuildPhysicsTable(G4ParticleDefinition* particle)
|
|
{
|
|
if (auto *trackingManager = particle->GetTrackingManager())
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildPhysicsTable "
|
|
<< "Calculate Physics Table for " << particle->GetParticleName()
|
|
<< " via custom TrackingManager" << G4endl;
|
|
}
|
|
#endif
|
|
trackingManager->BuildPhysicsTable(*particle);
|
|
return;
|
|
}
|
|
|
|
// Change in order to share physics tables for two kind of process.
|
|
|
|
if(particle->GetMasterProcessManager() == nullptr)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{ G4cout
|
|
<< "#### G4VUserPhysicsList::BuildPhysicsTable() - BuildPhysicsTable("
|
|
<< particle->GetParticleName() << ") skipped..." << G4endl; }
|
|
#endif
|
|
return;
|
|
}
|
|
if(fRetrievePhysicsTable)
|
|
{
|
|
if(!fIsRestoredCutValues)
|
|
{
|
|
// fail to retrieve cut tables
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildPhysicsTable "
|
|
<< "Physics table can not be retrieved and will be calculated "
|
|
<< G4endl;
|
|
}
|
|
#endif
|
|
fRetrievePhysicsTable = false;
|
|
}
|
|
else
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildPhysicsTable "
|
|
<< " Retrieve Physics Table for " << particle->GetParticleName()
|
|
<< G4endl;
|
|
}
|
|
#endif
|
|
// Retrieve PhysicsTable from files for proccesses
|
|
RetrievePhysicsTable(particle, directoryPhysicsTable, fStoredInAscii);
|
|
}
|
|
}
|
|
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildPhysicsTable "
|
|
<< "Calculate Physics Table for " << particle->GetParticleName()
|
|
<< G4endl;
|
|
}
|
|
#endif
|
|
// Rebuild the physics tables for every process for this particle type
|
|
// if particle is not ShortLived
|
|
if(!particle->IsShortLived())
|
|
{
|
|
G4ProcessManager* pManager = particle->GetProcessManager();
|
|
if(pManager == nullptr)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildPhysicsTable "
|
|
<< " : No Process Manager for " << particle->GetParticleName()
|
|
<< G4endl;
|
|
G4cout << particle->GetParticleName()
|
|
<< " should be created in your PhysicsList" << G4endl;
|
|
}
|
|
#endif
|
|
G4Exception("G4VUserPhysicsList::BuildPhysicsTable", "Run0271",
|
|
FatalException, "No process manager");
|
|
return;
|
|
}
|
|
|
|
// Get processes from master thread;
|
|
G4ProcessManager* pManagerShadow = particle->GetMasterProcessManager();
|
|
|
|
G4ProcessVector* pVector = pManager->GetProcessList();
|
|
if(pVector == nullptr)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildPhysicsTable "
|
|
<< " : No Process Vector for " << particle->GetParticleName()
|
|
<< G4endl;
|
|
}
|
|
#endif
|
|
G4Exception("G4VUserPhysicsList::BuildPhysicsTable", "Run0272",
|
|
FatalException, "No process Vector");
|
|
return;
|
|
}
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildPhysicsTable %%%%%% "
|
|
<< particle->GetParticleName() << G4endl;
|
|
G4cout << " ProcessManager : " << pManager
|
|
<< " ProcessManagerShadow : " << pManagerShadow << G4endl;
|
|
for(std::size_t iv1 = 0; iv1 < pVector->size(); ++iv1)
|
|
{
|
|
G4cout << " " << iv1 << " - " << (*pVector)[iv1]->GetProcessName()
|
|
<< G4endl;
|
|
}
|
|
G4cout << "--------------------------------------------------------------"
|
|
<< G4endl;
|
|
G4ProcessVector* pVectorShadow = pManagerShadow->GetProcessList();
|
|
|
|
for(std::size_t iv2 = 0; iv2 < pVectorShadow->size(); ++iv2)
|
|
{
|
|
G4cout << " " << iv2 << " - "
|
|
<< (*pVectorShadow)[iv2]->GetProcessName() << G4endl;
|
|
}
|
|
}
|
|
#endif
|
|
for(std::size_t j = 0; j < pVector->size(); ++j)
|
|
{
|
|
// Andrea July 16th 2013 : migration to new interface...
|
|
// Infer if we are in a worker thread or master thread
|
|
// Master thread is the one in which the process manager
|
|
// and process manager shadow pointers are the same
|
|
if(pManagerShadow == pManager)
|
|
{
|
|
(*pVector)[j]->BuildPhysicsTable(*particle);
|
|
}
|
|
else
|
|
{
|
|
(*pVector)[j]->BuildWorkerPhysicsTable(*particle);
|
|
}
|
|
|
|
} // End loop on processes vector
|
|
} // End if short-lived
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::PreparePhysicsTable(G4ParticleDefinition* particle)
|
|
{
|
|
if (auto *trackingManager = particle->GetTrackingManager())
|
|
{
|
|
trackingManager->PreparePhysicsTable(*particle);
|
|
return;
|
|
}
|
|
|
|
if(!(particle->GetMasterProcessManager()))
|
|
{
|
|
return;
|
|
}
|
|
// Prepare the physics tables for every process for this particle type
|
|
// if particle is not ShortLived
|
|
if(!particle->IsShortLived())
|
|
{
|
|
G4ProcessManager* pManager = particle->GetProcessManager();
|
|
if(pManager == nullptr)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::PreparePhysicsTable "
|
|
<< ": No Process Manager for " << particle->GetParticleName()
|
|
<< G4endl;
|
|
G4cout << particle->GetParticleName()
|
|
<< " should be created in your PhysicsList" << G4endl;
|
|
}
|
|
#endif
|
|
G4Exception("G4VUserPhysicsList::PreparePhysicsTable", "Run0273",
|
|
FatalException, "No process manager");
|
|
return;
|
|
}
|
|
|
|
// Get processes from master thread
|
|
G4ProcessManager* pManagerShadow = particle->GetMasterProcessManager();
|
|
|
|
G4ProcessVector* pVector = pManager->GetProcessList();
|
|
if(pVector == nullptr)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 0)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::PreparePhysicsTable "
|
|
<< ": No Process Vector for " << particle->GetParticleName()
|
|
<< G4endl;
|
|
}
|
|
#endif
|
|
G4Exception("G4VUserPhysicsList::PreparePhysicsTable", "Run0274",
|
|
FatalException, "No process Vector");
|
|
return;
|
|
}
|
|
for(std::size_t j = 0; j < pVector->size(); ++j)
|
|
{
|
|
// Andrea July 16th 2013 : migration to new interface...
|
|
// Infer if we are in a worker thread or master thread
|
|
// Master thread is the one in which the process manager
|
|
// and process manager shadow pointers are the same
|
|
if(pManagerShadow == pManager)
|
|
{
|
|
(*pVector)[j]->PreparePhysicsTable(*particle);
|
|
}
|
|
else
|
|
{
|
|
(*pVector)[j]->PrepareWorkerPhysicsTable(*particle);
|
|
}
|
|
} // End loop on processes vector
|
|
} // End if pn ShortLived
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::BuildIntegralPhysicsTable(
|
|
G4VProcess* process, G4ParticleDefinition* particle)
|
|
{
|
|
// TODO Should we change this function?
|
|
//*******************************************************************
|
|
// Temporary addition to make the integral schema of electromagnetic
|
|
// processes work.
|
|
|
|
if((process->GetProcessName() == "Imsc") ||
|
|
(process->GetProcessName() == "IeIoni") ||
|
|
(process->GetProcessName() == "IeBrems") ||
|
|
(process->GetProcessName() == "Iannihil") ||
|
|
(process->GetProcessName() == "IhIoni") ||
|
|
(process->GetProcessName() == "IMuIoni") ||
|
|
(process->GetProcessName() == "IMuBrems") ||
|
|
(process->GetProcessName() == "IMuPairProd"))
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::BuildIntegralPhysicsTable "
|
|
<< " BuildPhysicsTable is invoked for "
|
|
<< process->GetProcessName() << "(" << particle->GetParticleName()
|
|
<< ")" << G4endl;
|
|
}
|
|
#endif
|
|
process->BuildPhysicsTable(*particle);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::DumpList() const
|
|
{
|
|
theParticleIterator->reset();
|
|
G4int idx = 0;
|
|
while((*theParticleIterator)())
|
|
{
|
|
G4ParticleDefinition* particle = theParticleIterator->value();
|
|
G4cout << particle->GetParticleName();
|
|
if((idx++ % 4) == 3)
|
|
{
|
|
G4cout << G4endl;
|
|
}
|
|
else
|
|
{
|
|
G4cout << ", ";
|
|
}
|
|
}
|
|
G4cout << G4endl;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::DumpCutValuesTable(G4int flag)
|
|
{
|
|
fDisplayThreshold = flag;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::DumpCutValuesTableIfRequested()
|
|
{
|
|
if(fDisplayThreshold == 0)
|
|
return;
|
|
G4ProductionCutsTable::GetProductionCutsTable()->DumpCouples();
|
|
fDisplayThreshold = 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
G4bool G4VUserPhysicsList::StorePhysicsTable(const G4String& directory)
|
|
{
|
|
G4bool ascii = fStoredInAscii;
|
|
G4String dir = directory;
|
|
if(dir.empty())
|
|
dir = directoryPhysicsTable;
|
|
else
|
|
directoryPhysicsTable = dir;
|
|
|
|
// store CutsTable info
|
|
if(!fCutsTable->StoreCutsTable(dir, ascii))
|
|
{
|
|
G4Exception("G4VUserPhysicsList::StorePhysicsTable", "Run0281", JustWarning,
|
|
"Fail to store Cut Table");
|
|
return false;
|
|
}
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::StorePhysicsTable "
|
|
<< " Store material and cut values successfully" << G4endl;
|
|
}
|
|
#endif
|
|
|
|
G4bool success = true;
|
|
|
|
// loop over all particles in G4ParticleTable
|
|
theParticleIterator->reset();
|
|
while((*theParticleIterator)())
|
|
{
|
|
G4ParticleDefinition* particle = theParticleIterator->value();
|
|
// Store physics tables for every process for this particle type
|
|
G4ProcessVector* pVector =
|
|
(particle->GetProcessManager())->GetProcessList();
|
|
for(std::size_t j = 0; j < pVector->size(); ++j)
|
|
{
|
|
if(!(*pVector)[j]->StorePhysicsTable(particle, dir, ascii))
|
|
{
|
|
G4String comment = "Fail to store physics table for ";
|
|
comment += (*pVector)[j]->GetProcessName();
|
|
comment += "(" + particle->GetParticleName() + ")";
|
|
G4Exception("G4VUserPhysicsList::StorePhysicsTable", "Run0282",
|
|
JustWarning, comment);
|
|
success = false;
|
|
}
|
|
}
|
|
// end loop over processes
|
|
}
|
|
// end loop over particles
|
|
return success;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetPhysicsTableRetrieved(const G4String& directory)
|
|
{
|
|
fRetrievePhysicsTable = true;
|
|
if(!directory.empty())
|
|
{
|
|
directoryPhysicsTable = directory;
|
|
}
|
|
fIsCheckedForRetrievePhysicsTable = false;
|
|
fIsRestoredCutValues = false;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::RetrievePhysicsTable(G4ParticleDefinition* particle,
|
|
const G4String& directory,
|
|
G4bool ascii)
|
|
{
|
|
G4bool success[100];
|
|
// Retrieve physics tables for every process for this particle type
|
|
G4ProcessVector* pVector = (particle->GetProcessManager())->GetProcessList();
|
|
for(std::size_t j = 0; j < pVector->size(); ++j)
|
|
{
|
|
success[j] =
|
|
(*pVector)[j]->RetrievePhysicsTable(particle, directory, ascii);
|
|
|
|
if(!success[j])
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::RetrievePhysicsTable "
|
|
<< " Fail to retrieve Physics Table for "
|
|
<< (*pVector)[j]->GetProcessName() << G4endl;
|
|
G4cout << "Calculate Physics Table for " << particle->GetParticleName()
|
|
<< G4endl;
|
|
}
|
|
#endif
|
|
(*pVector)[j]->BuildPhysicsTable(*particle);
|
|
}
|
|
}
|
|
for(std::size_t j = 0; j < pVector->size(); ++j)
|
|
{
|
|
// temporary addition to make the integral schema
|
|
if(!success[j])
|
|
BuildIntegralPhysicsTable((*pVector)[j], particle);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetApplyCuts(G4bool value, const G4String& name)
|
|
{
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 2)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::SetApplyCuts for " << name << G4endl;
|
|
}
|
|
#endif
|
|
if(name == "all")
|
|
{
|
|
theParticleTable->FindParticle("gamma")->SetApplyCutsFlag(value);
|
|
theParticleTable->FindParticle("e-")->SetApplyCutsFlag(value);
|
|
theParticleTable->FindParticle("e+")->SetApplyCutsFlag(value);
|
|
theParticleTable->FindParticle("proton")->SetApplyCutsFlag(value);
|
|
}
|
|
else
|
|
{
|
|
theParticleTable->FindParticle(name)->SetApplyCutsFlag(value);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
G4bool G4VUserPhysicsList::GetApplyCuts(const G4String& name) const
|
|
{
|
|
return theParticleTable->FindParticle(name)->GetApplyCutsFlag();
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::CheckParticleList()
|
|
{
|
|
if(!fDisableCheckParticleList)
|
|
{
|
|
G4MT_thePLHelper->CheckParticleList();
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::AddTransportation()
|
|
{
|
|
G4MT_thePLHelper->AddTransportation();
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::UseCoupledTransportation(G4bool vl)
|
|
{
|
|
G4MT_thePLHelper->UseCoupledTransportation(vl);
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
G4bool G4VUserPhysicsList::RegisterProcess(G4VProcess* process,
|
|
G4ParticleDefinition* particle)
|
|
{
|
|
return G4MT_thePLHelper->RegisterProcess(process, particle);
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
G4ParticleTable::G4PTblDicIterator*
|
|
G4VUserPhysicsList::GetParticleIterator() const
|
|
{
|
|
return (subInstanceManager.offset[g4vuplInstanceID])._theParticleIterator;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
void G4VUserPhysicsList::SetVerboseLevel(G4int value)
|
|
{
|
|
verboseLevel = value;
|
|
// set verboseLevel for G4ProductionCutsTable same as one for
|
|
// G4VUserPhysicsList:
|
|
fCutsTable->SetVerboseLevel(verboseLevel);
|
|
|
|
G4MT_thePLHelper->SetVerboseLevel(verboseLevel);
|
|
|
|
#ifdef G4VERBOSE
|
|
if(verboseLevel > 1)
|
|
{
|
|
G4cout << "G4VUserPhysicsList::SetVerboseLevel :"
|
|
<< " Verbose level is set to " << verboseLevel << G4endl;
|
|
}
|
|
#endif
|
|
}
|