ステッピングアクションしたい(G4UserSteppingAction

ステップごとのデータを収集したい場合は、 G4UserSteppingActionクラスを継承したクラスを作成します。

ヒント

測定器のヒット情報を取得するときにステップ情報へのアクセスが必要になります。 その場合は、迷わずG4VSensitiveDetectorクラスを使いましょう。

親クラス

1G4UserSteppingAction();
2virtual ~G4UserSteppingAction() = default;
3virtual void UserSteppingAction(const G4Step*){};

親クラスのメンバー関数を抜粋しました。 コンストラクターとデストラクターは、この設定を引き継げばよさそうです。 UserSteppingAction()は、ステッピング処理で実行される関数です。 仮想関数になっているため、設定は必須ではありません。 必要に応じて自作クラスでoverrideします。

SteppingActionクラス

 1// include/SteppingAction.hh
 2
 3#ifndef SteppingAction_h
 4#define SteppingAction_h 1
 5
 6#include "G4UserSteppingAction.hh"
 7
 8namespace ToyMC
 9{
10
11class SteppingAction : public G4UserSteppingAction
12{
13  public:
14    SteppingAction() = default;
15    ~SteppingAction() = default;
16
17    void UserSteppingAction(const G4Step* aStep) override;
18}
19
20}  // namespace ToyMC
21
22#endif

ステッピングアクションはG4UserSteppingActionを継承したクラスを自作します。 仮想関数として定義されているUserSteppingActionを実装します。

UserSteppingAction

 1void SteppingAction::UserSteppingAction(const G4Step *aStep)
 2{
 3    G4coud << "UserSteppingAction" << G4endl;
 4
 5    G4int parent_id = aStep->GetTrack()->GetParentID();
 6
 7    // 入射粒子の位置を表示
 8    if (parent_id == 0) {
 9        G4int track_id = aStep->GetTrack()->GetTrackID();
10        G4int step_id = aStep->GetTrack()->GetCurrentStepNumber();
11        auto p = aStep->GetPreStepPoint()->GetPosition() / mm;
12        auto q = aStep->GetPostStepPoint()->GetPosition() / mm;
13        G4cout << "TrackID: " << track_id << G4endl;
14        G4cout << "StepID: " << step_id << G4endl;
15        G4cout
16          << "Pre : (" << p.getX()
17          << ", " << p.getY()
18          << ", " << p.getZ()
19          << ") [mm]"
20          << G4endl;
21        G4cout
22          << "Post: (" << q.getX()
23          << ", " << q.getY()
24          << ", " << q.getZ()
25          << ") [mm]"
26          << G4endl;
27    }
28}

入射した粒子のステッピング処理を確認するため、ステップ番号とその両端の座標を表示してみました。 このようにデバッグ的にUserSteppingActionをしてみるのはよいと思いますが、測定器のヒット情報はG4VSensitiveDetector::ProcessHitsに定義したほうがよいと思います。

境界判断したい

 1void SteppingAction::UserSteppingAction(const G4Step *aStep)
 2{
 3    auto pre_step = aStep->GetPreStepPoint();
 4    auto status = pre_step->GetStepStatus();
 5
 6    if (status == fWorldBoundary) { G4cout << "ワールド境界の外に到達" << G4endl; };
 7    if (status == fGeomBoundary) { G4cout << "ジオメトリ境界に到達 = いまのボリュームに入射した" << G4endl; };
 8    if (status == fUserDefinedLimit) { G4cout << "ユーザー設定のリミットに到達" << G4endl; };
 9    if (status == fUndefined) { G4coud << "ステップが未定義" << G4endl; };
10};