💡 参考文章见Ref,感谢提供思路!
🗺️当前这篇博文地址:https://myoontyee.github.io/article/c86dac85.html
⚠️警告:博客文章禁止一切形式的非授权非法转载!
⚠️Attention: All forms of unauthorized illegal reposts are prohibited !

创建时间:2022年4月7日15:29:08
最新更新:2022年4月8日10:16:03


Problem Description:C++ defines global variables, how to define all parameters in the header file? How to use a file to store all the parameters in the project? How to pass global parameters? ——Take Geant4 passing ray exit coordinates as an example

核心思路

  • 通常操作
    • 头文件.h里声明,源文件.cpp里定义
    • Geant4头文件是.hh,源文件是.cc
  • Geant4里的操作
    • include/B5Constants.hh声明变量(extern,不赋值)
    • 对应头文件public内声明变量,如include/B5PrimaryGeneratorAction.hhextern,不赋值)
    • 对应源文件
      • 头部初始化变量(没有extern,只定义,如G4double,初始化赋值)
      • 函数部分赋值(没有extern,没有定义,直接赋值)
    • 写到.root文件里
      • src/B5RunAction.cc初始化表格,记下Column Id
      • src/B5EventAction.cc内直接使用上面定义的变量传递数据(没有extern,没有定义,直接使用)

基本思路与概念

  • 例子
    • 头文件state.h
    • 源文件state.cpp
    • 其他源文件t1.cpp,t2.cpp,t3.cpp
      • 这些源文件都包含头文件state.h
    • 需要定义一个全局变量供这些源文件使用
  • 方法如下
    • state.h中声明全局变量extern int a;
    • state.cpp中定义该全局变量int a = 10;
  • 概念区别
    • 声明
      • 一个声明必须满足两个条件,否则就是定义
        • 声明必须使用extern关键字
        • 不能给变量赋初始值
    • 例子如下
      1
      2
      3
      4
      extern int a; // 声明
      int a; // 定义
      int a = 0; // 定义
      extern int a = 0; 定义
  • 注意事项
    • 头文件中应使用extern关键字声明全局变量(不定义)
    • 如果这个变量有多个文件用到,可以新建一个.cpp文件,在其中定义,并把该文件加入工程并调用
    • 头文件尽量不要定义任何变量
    • 一般只在头文件声明,用extern.cpp中定义,如果这个头文件被多个.cpp引用,会造成重复定义的链接错误
    • 头文件只能声明全局变量(extern),不可定义(不推荐使用)
    • .cpp里,在最外层定义即可(int gi),并直接引用
    • 如果在.cpp里用static定义,则该变量只在当前.cpp文件中有效,在别的文件中无效
    • 如果在.h里用static定义,不会进行编译(.h文件不编译),只会在其每个include.cpp文件中包含编译,相当于在.cpp里使用static定义

魔改exampleB5实现射线位置传递

声明变量

  • 用代码编辑器打开include/B5Constants.hh,添加以下内容
1
2
3
extern G4double Primary_worldpos_x;
extern G4double Primary_worldpos_y;
extern G4double Primary_worldpos_z;
  • 用代码编辑器打开include/B5PrimaryGeneratorAction.hh,在#include各种库下方,class B5PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction上方添加以下内容
1
2
3
4
5
6
7
8
9
10
11
// =============================================================================
// 传递变量
// =============================================================================
// 2022年4月7日
// 首次添加
// 粒子出射位置的x、y、z坐标
// =============================================================================
extern G4double Primary_worldpos_x;
extern G4double Primary_worldpos_y;
extern G4double Primary_worldpos_z;
// =============================================================================

定义变量

  • 用代码编辑器打开src/B5PrimaryGeneratorAction.cc,添加修改以下内容

    • 别忘记该文件要#include "Randomize.hh"用于产生随机数
  • #include下方,B5PrimaryGeneratorAction::B5PrimaryGeneratorAction()上方进行初始化

1
2
3
G4double Primary_worldpos_x = 0.; // 初始化
G4double Primary_worldpos_y = 0.; // 初始化
G4double Primary_worldpos_z = 0.; // 初始化
  • void B5PrimaryGeneratorAction::GeneratePrimaries(G4Event* event)内添加并修改对应内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 // =============================================================================
// 随机数版本
G4double x0 = G4UniformRand();
G4double y0 = G4UniformRand();
G4double z0 = G4UniformRand();
// =============================================================================
// 2022年4月7日
// 添加粒子出射位置的传递
// =============================================================================
G4double Primary_worldpos_x = x0; // 传递数值
G4double Primary_worldpos_y = y0; // 传递数值
G4double Primary_worldpos_z = z0; // 传递数值

G4cout << "=================================" << G4endl
<< "Primary_pox_x(mm) : " << (Primary_worldpos_x/mm) << G4endl
<< "Primary_pox_y(mm) : " << (Primary_worldpos_y/mm) << G4endl
<< "Primary_pox_z(mm) : " << (Primary_worldpos_z/mm) << G4endl
<< "=================================" << G4endl;
// =============================================================================

fParticleGun->SetParticlePosition(G4ThreeVector(x0,y0,z0));
// =============================================================================
  • void B5PrimaryGeneratorAction::GeneratePrimaries(G4Event* event)对应部分修改前后对比如下
修改前
修改后
1
2
3
4
5
6
7
8
9
// =============================================================================
// default particle kinematics
// 默认粒子运动学(运行前默认加载内容)
// =============================================================================
// 粒子位置
// 固定版本
// =============================================================================
fParticleGun->SetParticlePosition(G4ThreeVector(0., 0., 1.*m)); // 粒子位置
// =============================================================================
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 // =============================================================================
// 随机数版本
G4double x0 = G4UniformRand();
G4double y0 = G4UniformRand();
G4double z0 = G4UniformRand();
// =============================================================================
// 2022年4月7日
// 添加粒子出射位置的传递
// =============================================================================
G4double Primary_worldpos_x = x0; // 传递数值
G4double Primary_worldpos_y = y0; // 传递数值
G4double Primary_worldpos_z = z0; // 传递数值
G4cout << "=================================" << G4endl
<< "Primary_pox_x(mm) : " << (Primary_worldpos_x/mm) << G4endl
<< "Primary_pox_y(mm) : " << (Primary_worldpos_y/mm) << G4endl
<< "Primary_pox_z(mm) : " << (Primary_worldpos_z/mm) << G4endl
<< "=================================" << G4endl;
// =============================================================================
fParticleGun->SetParticlePosition(G4ThreeVector(x0,y0,z0));
// =============================================================================

初始化表格

  • 用代码编辑器打开src/B5RunAction.cc,在B5RunAction::B5RunAction(B5EventAction* eventAction) : G4UserRunAction(), fEventAction(eventAction)内添加以下内容
    • 我这3列对应的Id是26~28,具体到自己的代码里,要自己数一下对应的column Id
1
2
3
4
5
// 2022年4月7日
// 射线出射位置
analysisManager->CreateNtupleDColumn("Primary_pox_x"); // column Id = 26
analysisManager->CreateNtupleDColumn("Primary_pox_y"); // column Id = 27
analysisManager->CreateNtupleDColumn("Primary_pox_z"); // column Id = 28

输出进.root

  • 用代码编辑器打开src/B5EventAction.cc,在void B5EventAction::EndOfEventAction(const G4Event *event)对应位置添加以下内容
1
2
3
4
5
6
7
8
9
10
11
12
// columns 26-28
// 出射粒子 位置
// 下面这个输出的注释,当你需要确认参数是否传递过来,可以取消下面这个注释,检查效果
// G4cout << "=================================" << G4endl
// << "Primary_pox_x(mm) : " << (Primary_worldpos_x/mm) << G4endl
// << "Primary_pox_y(mm) : " << (Primary_worldpos_y/mm) << G4endl
// << "Primary_pox_z(mm) : " << (Primary_worldpos_z/mm) << G4endl
// << "=================================" << G4endl;
// 下面这个对应的是Column Id,我是26-28
analysisManager->FillNtupleDColumn(26, (Primary_worldpos_x));
analysisManager->FillNtupleDColumn(27, (Primary_worldpos_y));
analysisManager->FillNtupleDColumn(28, (Primary_worldpos_z));

输出效果

结果

Ref