Geant4程序 T1program
基本内容
本项目是初学Geant4的第一次尝试,希望完成一个满足基本运行要求的Geant4程序,支持可视化交互模式。物理过程是一束 射线入射到金箔上。
包括DetectorConstruction的构造(一片金箔),以及一支粒子枪,距离金箔数厘米,垂直射向金箔。
文件结构:
- Program/
- T1program.cc
- CMakeLists.txt
- init_vis.mac
- vis.mac
- src/
- include/
- T1PrimaryGeneratorAction.hh
- T1DetectorConstruction.hh
T1program.cc: Main()函数
main()函数负责整合所有的类 ,设置程序的物理环境以及交互模式,控制整个模拟的过程的进行。这些工作命令几乎全部交给一个类来产生,即G4RunManager。对于特定的程序来说,用户需要通过将G4RunManager实例化,通过调用实例化所产生的类指针runManager的各种成员方法来完成对模拟的控制。
必须要完成的工作有:
- 产生runManager
- 初始化探测器结构、物理过程
- 设置初始行为
- 初始化runManager内核
- 运行
- 终止程序,释放内存
在硬编码模式中,上述过程可以全部在main函数中完成。而可视化交互模式中,初始化runManager和运行命令可以分配给一些宏包来完成。编译后,运行可执行文件时,在后面加入宏包名称作为参数,然后调用UImanager的成员方法进行读取即可。
可视化交互功能由G4VisExecutive和UImanager控制,同时需要vis.mac和init_vis.mac两个宏文件来设置可视化的对象。
/// \file exampleB1.cc
/// \brief Main program of the B1 example
#include "T1DetectorConstruction.hh"
#include "T1PrimaryGeneratorAction.hh"
#include "G4RunManager.hh"
#include "G4UImanager.hh"
#include "QBBC.hh"
#include "G4VisExecutive.hh"
#include "G4UIExecutive.hh"
#include "Randomize.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
int main(int argc,char** argv)
{
G4UIExecutive* ui = new G4UIExecutive(argc,argv);
// Create a runManager
G4RunManager* runManager = new G4RunManager;
// Set mandatory initialization classes
// Detector construction
runManager->SetUserInitialization(new T1DetectorConstruction());
//Physics list
G4VModularPhysicsList* physicsList = new QBBC;
physicsList ->SetVerboseLevel(1); //
runManager ->SetUserInitialization(physicsList);
// Primary generator action
runManager->SetUserAction(new T1PrimaryGeneratorAction());
// Initialize visualization
//
G4VisManager* visManager = new G4VisExecutive;
// Initialize
visManager->Initialize();
// Get the pointer to the User Interface manager
G4UImanager* UImanager = G4UImanager::GetUIpointer();
// interactive mode
UImanager->ApplyCommand("/control/execute init_vis.mac");
ui->SessionStart();
delete ui;
////////////////////
// start a run in a purely hark-coded batch mode
//runManager->Initialize()
//int numberOfEvent = 3;
//
//runManager->BeamOn(numberOfEvent);
//
///////////////////
//Free up the memory
delete visManager;
delete runManager;
return 0;
}
T1DetectorConstruction类
C++中定义一个类有两部分组成,一部分是在头文件中声明类和成员函数,另一部分是在源文件中定义函数原型。有了原型并不能直接使用,它只是一个模板,就像main函数中做得那样,还需要进行实例化。
对于一个最简单的DetectorConstruction类,它继承自G4VUserDetectorConstruction类。其内部除了与它同名的初始化函数和析构函数外,还需要有Construct方法来登记特定的物理环境。
/// \file T1DetectorConstruction.hh
/// \brief Declaration of the T1DetectorConstruction class
#ifndef T1DetectorConstruction_h
#define T1DetectorConstruction_h 1 //这是标准头文件的规范写法,有这样一个if结构,可以防止编译时重复声明
#include "G4VUserDetectorConstruction.hh"
#include "globals.hh"
class G4VPhysicalVolume;
class G4LogicalVolume;
/// Detector construction class to define materials and geometry
class T1DetectorConstruction : public G4VUserDetectorConstruction
{
public:
T1DetectorConstruction(); // To initialize of this class
virtual ~T1DetectorConstruction(); // To clear the memory after using this class
virtual G4VPhysicalVolume* Construct();
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#endif
定义函数原型时,不能缺少初始化方法和析构方法,即便他们是空的。
Geant4有一套标准的数据类型和单位系统,在定义实体的尺寸时,最好带上单位。Geant4中的实体是一步一步成长而来的,由最初的形状(SolidVolume)加入材料信息后变成逻辑实体(LogicalVolume),然后放置在特定的位置形成物理实体(PhysicalVolume)。在不包含布尔运算的情况下,比较简单,可以直接看懂并使用example中的源码。
/// \file T1DetectorConstrucgtion.cc
/// \brief Defination of the T1DetectorConstruction class
#include "T1DetectorConstruction.hh"
#include "G4RunManager.hh"
#include "G4NistManager.hh" //include the standard materials
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4SystemOfUnits.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
T1DetectorConstruction::T1DetectorConstruction()
: G4VUserDetectorConstruction()
{ }
T1DetectorConstruction::~T1DetectorConstruction()
{ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VPhysicalVolume* T1DetectorConstruction::Construct()
{
// Get nist material manager
G4NistManager* nist = G4NistManager::Instance();
// Plate parameters
G4double pla_sizeX = 0.005*cm, pla_sizeYZ = 10*cm;
G4Material* pla_mat = nist->FindOrBuildMaterial("G4_Au");
// World
G4double world_sizeXYZ = 1.2*pla_sizeYZ;
G4Material* world_mat = nist->FindOrBuildMaterial("G4_AIR");
G4Box* solidWorld =
new G4Box("World", //its name
0.5*world_sizeXYZ, 0.5*world_sizeXYZ, 0.5*world_sizeXYZ); //its size
G4LogicalVolume* logicWorld =
new G4LogicalVolume(solidWorld, //its solid
world_mat, //its material
"World"); //its name
G4VPhysicalVolume* physWorld =
new G4PVPlacement(0, //no rotation
G4ThreeVector(), //at (0,0,0)
logicWorld, //its logical volume
"World", //its name
0, //its mother volume
false, //no boolean operation
0); //copy number
// Plate
G4Box* solidPla =
new G4Box("Plate", //its name
0.5*pla_sizeX, 0.5*pla_sizeYZ, 0.5*pla_sizeYZ); //its size
G4LogicalVolume* logicPla =
new G4LogicalVolume(solidPla, //its solid
pla_mat, //its material
"Plate"); //its name
G4VPhysicalVolume* physPla =
new G4PVPlacement(0, //no rotation
G4ThreeVector(), //at (0,0,0)
logicPla, //its logical volume
"Plate", //its name
logicWorld, //its mother volume
false, //no boolean operation
0); //copy number
return physWorld;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
T1PrimaryGeneratorAction类
初始化函数设置粒子的初始信息,如能量、动量方向、粒子种类。GeneratePrimary定义粒子初始位置分布。
/// \file T1PrimaryGeneratorAction.hh
/// \brief Declaration of the T1PrimaryGeneratorAction class
#ifndef T1PrimaryGeneratorAction_h
#define T1PrimaryGeneratorAction_h 1
#include "G4VUserPrimaryGeneratorAction.hh"
#include "G4ParticleGun.hh"
#include "globals.hh"
class G4ParticleGun;
class G4Event;
/// The primary generator action class with particle gun.
///
/// The default kinematic is a 7.7 MeV alpha, shooted to the plate in parallel
class T1PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction
{
public:
T1PrimaryGeneratorAction();
virtual ~T1PrimaryGeneratorAction();
// method from the base class
virtual void GeneratePrimaries(G4Event*);
private:
G4ParticleGun* fParticleGun; // a pointer to G4 gun class
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif
/// \file T1PrimaryGeneratorAction.cc
/// \brief Implementation of the T1PrimaryGeneratorAction class
#include "T1PrimaryGeneratorAction.hh"
#include "G4RunManager.hh"
#include "G4ParticleGun.hh"
#include "G4ParticleTable.hh"
#include "G4ParticleDefinition.hh"
#include "G4SystemOfUnits.hh"
#include "Randomize.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
T1PrimaryGeneratorAction::T1PrimaryGeneratorAction()
: G4VUserPrimaryGeneratorAction(),
fParticleGun(0)
{
G4int n_particle = 1;
fParticleGun = new G4ParticleGun(n_particle);
// default particle kinematic
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
G4String particleName;
G4ParticleDefinition* particle
= particleTable->FindParticle(particleName="alpha");
// The default kinematic is a 7.7 MeV alpha, shooted to the plate in parallel
fParticleGun->SetParticleDefinition(particle);
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(1.,0.,0.));
fParticleGun->SetParticleEnergy(20*MeV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
T1PrimaryGeneratorAction::~T1PrimaryGeneratorAction()
{
delete fParticleGun;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void T1PrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent)
{
//this function is called at the begining of ecah event
//
G4double SourceCenterX = -2.5*cm;
G4double SourceCenterYZ = 0*cm;
G4double RayWidth = 1;
G4double x0 = SourceCenterX + 0;
G4double y0 = RayWidth * (G4UniformRand()-0.5) + SourceCenterYZ;
G4double z0 = RayWidth * (G4UniformRand()-0.5) + SourceCenterYZ;
fParticleGun->SetParticlePosition(G4ThreeVector(x0,y0,z0));
fParticleGun->GeneratePrimaryVertex(anEvent);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
可视化宏包:init_vis.mac&vis.mac
后续补充(目前只是使用可视化功能检验探测器与粒子枪是否设置正确,迁移了example的源码还未做研究)
CMakeLists.txt: 编译前的声明
CMakeLists.txt是cmake编译时的必要文件,它告诉cmake整个项目依赖的包的版本,以及项目的文件分布。
# (1)
cmake_minimum_required(VERSION 2.6 FATAL_ERROR) #声明cmake版本
project(T1) #随意起一个名字
# (2)
option(WITH_GEANT4_UIVIS "Build example with Geant4 UI and Vis drivers" ON)#开启可视化交互选项
if(WITH_GEANT4_UIVIS)
find_package(Geant4 REQUIRED ui_all vis_all)
else()
find_package(Geant4 REQUIRED)
endif()
# (3)
include(${Geant4_USE_FILE})
include_directories(${PROJECT_SOURCE_DIR}/include)
# (4) 声明头文件和源文件位置
file(GLOB sources ${PROJECT_SOURCE_DIR}/src/*.cc)
file(GLOB headers ${PROJECT_SOURCE_DIR}/include/*.hh)
# (5)
add_executable(T1program T1program.cc ${sources} ${headers})
target_link_libraries(T1program ${Geant4_LIBRARIES})
# (6) 声明其他所需的文件,第一项是必要的
set(T1PROGRAM_SCRIPTS
init_vis.mac
vis.mac)
foreach(_script ${T1PROGRAM_SCRIPTS}) #将源文件拷贝到build/目录下
configure_file(
${PROJECT_SOURCE_DIR}/${_script}
${PROJECT_BINARY_DIR}/${_script}
COPYONLY
)
endforeach()
# (7)
install(TARGETS T1program DESTINATION bin)
写好CMakeLists.txt之后,就完成了所有的源码文件的编写。接下来只需要编译运行即可:
mkdir ./build && cd ./build
cmake ..
make -j4
source {geant4-install path}/bin/geant4.sh
./T1program
实际上并没有明显看出卢瑟福实验的样子,只能检查一下物理条件有没有设置对。另外PhysicsList也是一个问题,内置的物理过程如何选择还需要学。