ヒット情報したい(G4VHit

有感検出器でのヒット情報を格納するためには G4VHitクラスを継承したクラスを作成します。

親クラス

1G4VHit() = default;
2virtual G4VHit() = default;
3virtual void Draw() {};
4virtual void Print() {};

コンストラクターとデストラクターはデフォルトのままでOKです。 Draw()は、イベントを描画するときのヒット点の見た目を調整する関数です。 Print()は、ヒットの情報を出力する関数です。 どちらも仮想関数になっているため、必要に応じて自作クラスでoverrideします。

SensorHitクラス

 1#ifndef SensorHit_h
 2#define SensorHit_h 1
 3
 4#include "G4VHit.hh"
 5#include "G4Step.hh"
 6
 7namespace ToyMC
 8{
 9
10class SensorHit : public G4VHit
11{
12  public:
13    // 1. コンストラクターなどを定義
14    SensorHit() = default;
15    ~SensorHit() = default;
16
17    // 2. new / delete を実装
18    inline void* operator new(size_t);
19    inline void operator delete(void* hit);
20
21    // 3. 仮想関数 を実装
22    void Draw() override;
23    void Print() override;
24
25    // 4. カスタム関数
26    void Fill(G4Step *aStep);
27    G4String ToCsvString() const;
28    G4String ToLtsvString() const;
29
30  private:
31    // 5. 測定したい値を定義する
32    G4int fDetectorID{-1};
33    G4int fCopyNumber{-1};
34    G4int fReplicaNumber{-1};
35    G4int fTrackID{-1};
36    G4int fStepID{-1};
37    G4double fEnergyDeposit{0.};
38    G4ThreeVector fXYZ{};
39    G4double fGlobalTime{0.};
40    G4double fStepLength{0.};
41    G4double fTrackLength{0.};
42
43};
44
45// __________________________________________________
46// SensorHitクラス型のヒット配列テンプレートの型エイリアス
47using SensorHitsCollection = G4THitsCollection<SensorHit>;
48
49// __________________________________________________
50// スレッドローカルなメモリアロケーターの定義
51// マルチスレッド環境で、スレッドごとにメモリを確保
52extern G4ThreadLocal G4Allocator<SensorHit> *SensorHitAllocator;
53
54// __________________________________________________
55inline void *SensorHit::operator new(size_t)
56{
57    // new演算子:
58    // コンストラクターの前に実行される特殊関数
59    // SensorHitに必要なメモリをG4Allocatorで割り当てる
60
61    if (!SensorHitAllocator) {
62        SensorHitAllocator = new G4Allocator<SensorHit>;
63    }
64    return (void *)SensorHitAllocator->MallocSingle();
65}
66
67// __________________________________________________
68inline void SensorHit::operator delete(void *hit)
69{
70    // delete演算子
71    // デストラクターの後に実行される特殊関数
72    // new演算子で割り当てたメモリを解放する
73    SensorHitAllocator->FreeSingle((SensorHit *)hit);
74}
75
76}; // namespace ToyMC
77#endif

測定器のヒット情報はG4VHitクラスを継承してユーザーが定義する必要があります。 ヒット情報の取得/ファイル出力はGeant4シミュレーションで結果を得るためにとても大事なアイテムです。 しかし、初心者向けの解説を見つけることができず、このクラスの役割を理解するのにかなり苦戦しました。 ここでは、その汗と涙と努力の結晶をまとめてみました。

サンプルコードはexamples/basic/B2a/TrackerHit.hhを参考に改変しました。 有感検出器でヒットを取得するクラスをSensorHitクラスと名づけました。 このクラスの役割は次のとおりです。

  1. コンストラクター/デストラクターは親クラスを引き継ぐ

  2. SensorHit型のヒット配列の型エイリアスを定義する(SensorHitsCollection

  3. スレッドローカルなメモリ割り当てを定義する(SensorHitAllocator

  4. 最適なメモリ管理のためnew演算子/delete演算子を定義する

  5. Draw()Print()をoverrideして定義する

  6. Fill(G4Step *aStep)と必要なprivate変数を定義する

たくさんの役割/処理が登場するので、順番に紹介します。

コンストラクターとデストラクター

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

SensorHitクラスの初期化/削除するときに実行されるコンストラクターとデストラクターは、親クラス(G4VHit)を引き継いでおきます。 ユーザーがカスタマイズする必要はありません。

型エイリアス: SensorHitsCollection

1using SensorHitsCollection = G4THitsCollection<SensorHit>;

SensorHitsCollectionという名前の型エイリアスを定義しています。

G4THitsCollectionは、親をたどるとstd:vector型をベースにしたテンプレートクラスです。 なのでSensorHit型を要素に持つstd:vector配列とイメージしておけばよいと思います。

1// Sensor.cc
2auto fHitsCollection = new SensorHitsCollection{}

有感検出器のヒット情報(SensorHit)を格納する配列(SensorHitsCollection)として使います。 具体的な使い方はSensorクラスを参照してください。

G4ThreadLocalとG4Allocator

1extern G4ThreadLocal G4Allocator<SensorHit> *SensorHitAllocator;

SensorHitAllocatorという名前で、スレッド別にメモリ領域を割り当てるアロケーターを定義しています。 詳細はメモリ割り当てしたい(G4Allocator)に整理しました。

new演算子とdelete演算子

1public:
2  inline void* operator new(size_t);
3  inline void operator delete(void* hit);

クラスのインスタンスを作成するときにコンストラクターが呼ばれます。 コンストラクターの中では「メモリを確保する」処理と「メンバー変数を初期化する」処理が実行されます。 new演算子は「メモリを確保する」処理のために実行される特殊関数です。 ここでSensorHitAllocatorを使って、SensorHitクラスに必要なメモリ領域を割り当てます。

クラスのインスタンスを削除するときにデストラクターが呼ばれます。 デストラクターの中では「リソースを解放する」処理と「メモリを解放する」処理が実行されます。 delete演算子は「メモリを解放する」処理のために実行される特殊関数です。 前述のnew演算子で割り当てたメモリ領域を解放します。

Draw()Print()関数

DrawPrintは仮想関数です。 必要であればこれらををoverrideして定義します。

Fill(G4Step *aStep)関数

Fillは僕が追加したカスタム関数です。 G4Stepを引数と渡し、Fillの中でprivate変数に値を直接代入するという設計です。 これにより、private変数ごとのゲッター/セッターを作成する必要がなくなります。

有感検出器とヒット用クラス

このページでは「汎用的なヒット」という意味でSensorHitとしました。 可能な限りすべてのデータを取得してファイルに書き出し、 解析でフィルタリングしようという魂胆です。 こういうことができるのが、シミュレーションのおもしろい部分かなと思います。

もし、具体的な検出器があり、その完全再現を目指すならば、それらに特化したクラスを作成するとよいかもしれません。

ヒント

  1. 飛跡検出器 → TrackerHit

  2. カロリメーター → CaloHit

  3. ホドスコープ → HodoHit

  4. ピクセル検出器 → PixelHit

  5. 光電子増倍管 → PmtHit

  6. MPPC → MppcHit

イベントのヒットしたい(G4HCofThisEvent

 1// SensitiveDetector: public G4VSensitiveDetector
 2
 3void SensitiveDetector::EndOfEvent(G4HCofThisEvent *aHC) {
 4
 5    // HitsCollectionの数を取得する
 6    G4int nHC = aHC->GetNumberOfCollections();
 7
 8    for (G4int i=0; i<nHC; i++) {
 9        auto hc = aHC->GetHC(i);
10        G4int nHit = hc->GetSize();
11        for (G4int j=0; j<nHit; j++) {
12            auto hit = hc->GetHit(j);
13        }
14    }
15}

G4Eventを処理する際に、たくさんのG4VHit(の派生クラスの)オブジェクトが生成されます。 これらのヒット情報は、配列コンテナー(G4HitsCollectionと、そのテンプレートクラスG4THitsCollection)に集めることができます。

G4EventG4HCofThisEventというヒット配列を持っています。 イベントごとのヒット情報は、このオブジェクト(のポインター)を介してアクセスてきます。

リファレンス