Geant4 案例分析(二): B2
本文是对Geant4 B2的案例分析。在B1 案例分析的基础上,Geant4大致的项目结构和主要功能实现已经较为清晰,本文乃至以后的案例分析,将注重于其他功能的实现。
ExampleB2中将要介绍的是通过Messenger与程序进行交互,以及通过SensitiveDetector将Hits存储在Hit Collections中。
Messenger的使用
// DetectorMessenger::DetectorMessenger
fDetectorConstruction = det;
fDirectory = new G4UIdirectory("/B2/");
fDirectory->SetGuidance("UI commands specific to this example.");
fDetDirectory = new G4UIdirectory("/B2/det/");
fDetDirectory->SetGuidance("Detector construction control");
fTargMatCmd = new G4UIcmdWithAString("/B2/det/setTargetMaterial",this);
fTargMatCmd->SetGuidance("Select Material of the Target.");
fTargMatCmd->SetParameterName("choice",false);
fTargMatCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
// DetectorMessenger::~DetectorMessenger
delete fTargMatCmd;
// DetectorMessenger::SetNewValue
if( command == fTargMatCmd )
{ fDetectorConstruction->SetTargetMaterial(newValue);}
如代码所示,实现了通过/B2/det/setTarget/Material 来调用SetTargetMaterial,后者实际上在DetetecotrConstruction中实现
void DetectorConstruction::SetTargetMaterial(G4String materialName)
{
G4NistManager* nistManager = G4NistManager::Instance();
G4Material* pttoMaterial =
nistManager->FindOrBuildMaterial(materialName);
// ...
fTargetMaterial = pttoMaterial;
fLogicTarget->SetMaterial(fTargetMaterial);
// ...
Messenger的实现就是以上了,而在程序中调用,只需要
// DetectorConstruction::DetectorConstruction
fMessenger = new DetectorMessenger(this);
// DetectorConstruction::~DetectorConstruction()
delete fMessenger;
SensitiveDetecotr的使用
SensitiveDetector的注册在DetectorConstruction中完成。
// DetectorConstruction::ConstructSDandField
G4String trackerChamberSDname = "/TrackerChamberSD";
auto aTrackerSD = new TrackerSD(trackerChamberSDname, "TrackerHitsCollection");
G4SDManager::GetSDMpointer()->AddNewDetector(aTrackerSD);
// Setting aTrackerSD to all logical volumes with the same name
// of "Chamber_LV".
SetSensitiveDetector("Chamber_LV", aTrackerSD, true);
看起来比较摸不着头脑,多看几遍,这段代码的实际用途是
- 将aTrackerSD注册给G4SDManager
- 将aTrackerSD和DetectorConstruction中名称为Chanmebr_LV的逻辑体积联系起来
TrackerSD的实现显然在TrackerSD.cc中,事实上如果只需要访问到TrackerSD中的Hit,只需要有以下内容即可:
TrackerSD::TrackerSD(const G4String& name)
:G4VSensitiveDetector(name)
{}
TrackerSD::~TrackerSD(){}
G4bool TrackerSD::ProcessHits(G4Step *aStep,
G4TouchableHistory *ROhist)
{
// 获取相应的输出
}
然而此处的TrackerSD.CC显然还有其他更多的内容,是因为B2a还实现了另外一个功能。
其中
TrackerSD( const G4String& name,const G4String& hitsCollectionName)
SetSensitiveDetector(G4LogicalVolume* logVol, G4VSensitiveDetector) // or G4String* logVolName, 为案例中的参数
Hit的使用
在此处,自定义的TrackerHit的唯一作用是令我们生成的可视化图像逼格满满便于查看。
在TrackerHit.cc中,要纠结的内容没有多少。
G4ThreadLocal G4Allocator<TrackerHit>* TrackerHitAllocator = nullptr;
G4bool TrackerHit::operator==(const TrackerHit& right) const{
return ( this == &right ) ? true : false;
}
void TrackerHit::Draw(){
// draw command
}
void TrackerHit::Print(){
// print command
}
值得一提的是,因为Hit中包含着许多成员,可以初始化也可也不初始化,这样的设计有利于解决空间。但是这要求用户对自定义的Hit要提供相应的容器和Allocator — 此处的TrackerHitCollection与TrackerHitAllocator。
在TrackerHit.hh中
using TrackerHitsCollection = G4THitsCollection<TrackerHit>;
extern G4ThreadLocal G4Allocator<TrackerHit>* TrackerHitAllocator;
声明了TrackerHitsCollection和TrackerHitAllocator,后者的实现在TrackerHit.cc中。
补充:ProcessHit(G4Step)能获得的数据
Tracks and steps
通常的信息,如能量沉积,位置,所在volume,要通过Step得到
const G4StepPoint* preStepPoint = step->GetPreStepPoint();
const G4ThreeVector& preStepPosition = preStepPoint->GetPosition();
const G4TouhchableHandle& preStepTouch = preStepPoint->GetTouchableHandle();
const G4VPhysicalVolume* volume = preStepTouch->GetVolume();
const G4String& name = volume->GetName();
const G4int copyNumber = preStepTouch->GetCopyNumber();
const G4LogicalVolume* lvolume = volume->GetLogicalVolume();
const G4Material* material = preStepPoint->GetMaterial();
const G4double eDeposit = step->GetTotalEnergyDeposit();
const G4double sLength = step->GetStepLength();
const G4ThreeVector& displace = step->GetDeltaPosition();
const G4double tof = step->GetDeltaTime();
const G4Track* track = step->GetTrack();
const G4ThreeVector& momentum = track->GetMomentum();
const G4double kinEnergy = track->GetKineticEnergy();
const G4double globalTime = track-> GetGlobalTime();
补充:Volume颜色设置
// DetectorConstruction
auto boxVisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0));
auto chamberVisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 0.0));
worldLV ->SetVisAttributes(boxVisAtt);
fLogicTarget ->SetVisAttributes(boxVisAtt);
trackerLV ->SetVisAttributes(boxVisAtt);