測定器したい(G4VUserDetectorConstruction

測定器の構造はユーザーが定義する必要があります。 G4VUserDetectorConstructionクラスを継承した自作クラスを作成し、 Construct(必須)やConstructSDandField(オプション)を実装します。

親クラス

1G4VUserDetectorConstruction() = default;
2virtual ~G4UserDetectorConstruction() = default;
3virtual G4VPhysicalVolume* Construct() = 0;
4virtual void ConstructSDandField();

親クラス(G4VUserDetectorConstruction)のメンバー関数を抜粋しました。 コンストラクターとデストラクターは、このデフォルトの設定を引き継げばよさそうです。

Construct()は測定器の構造を初期化して配置する関数です。 純粋仮想関数になっているため、自作クラスでoverrideが必要です。 必要なソリッド、論理ボリューム、物理ボリュームはすべてこの関数の中で生成します。

ConstructSDandField()は、Constructで生成した論理ボリュームに対して 有感検出器(SensitiveDetector)や場(Field)を設定するための関数です。 マルチスレッド環境で実行する場合は、自作クラスでoverrideが必要です。

注釈

ConstructSDandFieldはGeant4.10で追加されたようです。

Geometryクラス

 1// //////////////////////////////////////////////////
 2// include/Geometry.hh
 3// //////////////////////////////////////////////////
 4
 5#ifndef Geometry_h
 6#define Geometry_h 1
 7
 8#include "G4VUserDetectorConstruction.hh"
 9#include "G4LogicalVolume.hh"
10#include "G4SystemOfUnits.hh"
11
12namespace ToyMC
13{
14
15class Geometry : public G4VUserDetectorConstruction
16{
17  public:
18    // コンストラクタとデストラクタは
19    // 親クラスを引き継ぐことにする
20    Geometry() = default;
21    ~Geometry() = default;
22
23  public:
24    // これらの関数は override する
25    G4PhysicalVolume* Construct() override;
26    void ConstructSDandField() override;
27
28  // __________________________________________________
29  // これ以降は僕のベストプラクティス
30  private:
31    // ワールドを設定するための関数とパラメーター
32    G4LogicalVolume* SetupWorldVolume();
33    G4String fWorldLVName = "World";
34    G4String fWorldMaterial = "G4_AIR";
35    G4double fWorldX = 15. * cm;
36    G4double fWorldY = 15. * cm;
37    G4double fWorldZ = 15. * cm;
38
39  private:
40    // 測定器を設定するための関数とパラメーター
41    // 測定器ごとに用意する
42    G4LogicalVolume* SetupDetectorVolume();
43    G4String fDetectorLVName = "Detector";
44    G4String fDetectorMaterial = "G4_WATER";
45    G4double fDetectorX = 5. * cm;
46    G4double fDetectorY = 5. * cm;
47    G4double fDetectorZ = 5. * cm;
48
49  public:
50    // main()関数から測定器のパラメーターを確認・変更するメソッド
51    G4String GetDetectorLVName() const { return fDetectorLVName; };
52    void SetDetectorLVName(const G4String &name) { fDetectorLVName = name};
53
54    G4String GetDetectorMaterial() const { return fDetectorMaterial; };
55    void SetDetectorMaterial(const G4String &name) { fDetectorMaterial = name};
56
57    G4double GetDetectorX() const { return fDetectorX; };
58    void SetDetectorX(const G4double length) { fDetectorX = length; };
59
60    G4double GetDetectorY() const { return fDetectorY; };
61    void SetDetectorY(const G4double length) { fDetectorY = length; };
62
63    G4double GetDetectorZ() const { return fDetectorZ; };
64    void SetDetectorZ(const G4double length) { fDetectorZ = length; };
65
66};
67
68}; // namespace ToyMC
69
70#endif

自作クラス名をGeometryとして作成しています。 namespaceToyMC(お遊びのモンテカルロの意味)としました。

また、必要な論理物体(G4LogicalVolume)を作成する関数も用意しました。

1public:
2    Geometry() = default;
3    ~Geometry() = default;

コンストラクターとデストラクターは親クラスを引き継ぐことにしました。

Geometry::Construct

1public:
2    G4PhysicalVolume* Construct() override;
3    void ConstructSDandField() override;

overrideキーワードを設定し、親クラスが持っている(純粋)仮想関数を上書きすることを明示しました。 また、overrideをつけておくと、関数名をタイポしていた場合にコンパイルエラーで指摘してくれます。

メンバー変数

1private:
2    // ワールドを設定するための関数とパラメーター
3    G4LogicalVolume* SetupWorldVolume();
4    G4String fWorldLVName = "World";
5    G4String fWorldMaterial = "G4_AIR";
6    G4double fWorldX = 15. * cm;
7    G4double fWorldY = 15. * cm;
8    G4double fWorldZ = 15. * cm;

これ以降は、僕がカスタマイズするときのベストプラクティス(と思っている)な書き方です。参考までにどうぞ。 ここでは、ワールドの大きさのパラメーターと、それをセットアップする関数を宣言しています。 具体的な中身は実験室を作りたい(SetupWorldVolume)を参照してください。

 1private:
 2    // 測定器を設定するための関数とパラメーター
 3    // 測定器ごとに用意する
 4    G4LogicalVolume* SetupDetectorVolume();
 5    G4String fDetectorLVName = "Detector";
 6    G4String fDetectorMaterial = "G4_WATER";
 7    G4double fDetectorX = 5. * cm;
 8    G4double fDetectorY = 5. * cm;
 9    G4double fDetectorZ = 5. * cm;
10
11public:
12    // main()関数から測定器のパラメーターを確認・変更するメソッド
13    G4String GetDetectorLVName() const { return fDetectorLVName; };
14    void SetDetectorLVName(const G4String &name) { fDetectorLVName = name};
15
16    G4String GetDetectorMaterial() const { return fDetectorMaterial; };
17    void SetDetectorMaterial(const G4String &name) { fDetectorMaterial = name};
18
19    G4double GetDetectorX() const { return fDetectorX; };
20    void SetDetectorX(const G4double length) { fDetectorX = length; };
21
22    G4double GetDetectorY() const { return fDetectorY; };
23    void SetDetectorY(const G4double length) { fDetectorY = length; };
24
25    G4double GetDetectorZ() const { return fDetectorZ; };
26    void SetDetectorZ(const G4double length) { fDetectorZ = length; };

実験室の中に配置する物体を作成する部分です。 配置する測定器の種類の数だけ、コピペが必要です。

ここでは大きさをprivateで定義し、それにアクセスするためのセッター/ゲッターをpublicで定義しました。 これによりmain()関数から測定器のパラメーターを変更できます。

メイン関数

 1#include "Geometry.hh"
 2
 3int main(int argc, char** argv)
 4{
 5    auto rm = G4RunManagerFactory::CreateRunManager();
 6
 7    auto geometry = new Geometry{};
 8    geometry->SetDetectorMaterial("G4_Pb");  // 測定器の素材を"G4_Pb"に変更
 9    rm->SetUserInitialization(geometry);
10
11}

main()関数の中で、 Geometryクラスのインスタンスを作成し、 SetUserInitializationでRunManagerに追加します。

publicなセッターを作成しておいたため、geometry->SetDetectorMaterialのように変更できます。

ヒント

実験の最適なセットアップを検討している段階では、検出器や標的の素材を変えたり、厚みを変えたりしたいはずです。 main()関数から変更できるようにしておくと、そのようなスタディがはかどります。