Geant4程序 T1program

Geant4程序 T1program

基本内容

本项目是初学Geant4的第一次尝试,希望完成一个满足基本运行要求的Geant4程序,支持可视化交互模式。物理过程是一束 α \alpha 射线入射到金箔上。

包括DetectorConstruction的构造(一片金箔),以及一支粒子枪,距离金箔数厘米,垂直射向金箔。

文件结构:

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也是一个问题,内置的物理过程如何选择还需要学。

发布了29 篇原创文章 · 获赞 3 · 访问量 6707

猜你喜欢

转载自blog.csdn.net/weixin_43316938/article/details/88572270