Geant4 가이드

이벤트 파일을 읽어서 시뮬레이션에 쏘기

이 문제는 c++ 프로그래밍 문제이며 해결방식은 이벤트 파일이 저장되어 있는 형식에, 그리고 어떤 시뮬레이션을 하려고 하는지에 따라 달라진다. Geant4에 관한 지식은 앞서 배운 Primary Generator Action 토픽의 내용에서 벗어나지 않는다. 따라서 여기서는 아주 간단한 아이디어를 소개한다.

두 핵간의 충돌에서 나오는 입자의 종류와 운동량이 적혀있는 이벤트 파일이 다음과 같은 형식으로 저장되어 있다고 하자.

[이벤트 개수]
[이벤트 아이디] [이벤트에 들어있는 트랙의 개수] [버텍스-x] [버텍스-y] [버텍스-z]
[PDG Encoding] [운동량-x] [운동량-y] [운동량-z]
[PDG Encoding] [운동량-x] [운동량-y] [운동량-z]
[PDG Encoding] [운동량-x] [운동량-y] [운동량-z]
...
[이벤트 아이디] 
[이벤트에 들어있는 트랙의 개수] [버텍스-x] [버텍스-y] [버텍스-z]
[PDG Encoding] [운동량-x] [운동량-y] [운동량-z]
...
...

예를 들면 다음과 같다.

2
0 2 0. 0. 0.
2212 0. 0. 100.
2112 100. 0. 0.
1 1 0. 0. 0.
11 0. 100. 0.

위 예제는 2개의 이벤트가 들어 있으며, 입자의 시작 위치점인 버텍스는 두 이벤트 모두 (0,0,0)이다. 첫번쨰 이벤트에는 양성자와 중성자, 두번째 이벤트에는 전자가 하나 들어있다.

이제 이 파일을 Primary Generator Action에 넣어주면 된다. 파일을 읽는것을 도와주기 위해서 새로운 클래스를 다음과 같이 만들어보자.

OTMCEventGenerator.hh

#ifndef OTMCEVENTGENGENERATOR_HH
#define OTMCEVENTGENGENERATOR_HH

#include <fstream>
#include "globals.hh"

class OTMCEventGenerator {
  public:
    OTMCEventGenerator(TString fileName);
    virtual ~OTMCEventGenerator();

    bool ReadNextEvent(G4double &vx, G4double &vy, G4double &vz);
    bool ReadNextTrack(G4int &pdg, G4double &px, G4double &py, G4double &pz);

    G4int GetNumEvents() { return fNumEvents; };

  private:
    std::ifstream fInputFile;
    G4int fNumEvents;
    G4int fNumTracks;
    G4int fCurrentTrackID;
};

#endif

OTMCEventGenerator.cc

#include "OTMCEventGenerator.hh"

OTMCEventGenerator::OTMCEventGenerator(TString fileName) {
  fInputFile.open(fileName.Data());
  fInputFile >> fNumEvents;
}

OTMCEventGenerator::~OTMCEventGenerator() {
  if(fInputFile.is_open()) fInputFile.close();
}

bool OTMCEventGenerator::ReadNextEvent(Double_t &vx, Double_t &vy, Double_t &vz) {
  G4int eventID;
  if (!(fInputFile >> eventID >> fNumTracks >> vx >> vy >> vz))
    return false;

  fCurrentTrackID = 0;
  return true;
}

bool OTMCEventGenerator::ReadNextTrack(Int_t &pdg, Double_t &px, Double_t &py, Double_t &pz) {
  if (fCurrentTrackID >= fNumTracks)
    return false;

  fInputFile >> pdg >> px >> py >> pz;
  fCurrentTrackID++;

  return true;
}

이제 Primary Generator Action에서 이 클래스를 생성하고 GeneratePrimaries(G4Event *)에서 이벤트를 생성해주면 된다.

OTPrimaryGeneratorAction.hh

...
  private:
    G4ParticleGun *fParticleGun;
    OTMCEventGenerator *fEventGenerator;
...

OTPrimaryGeneratorAction.cc

...
OTPrimaryGeneratorAction::OTPrimaryGeneratorAction() {
  fParticleGun = new G4ParticleGun();
  fEventGenerator = new OTMCEventGenerator(EVENT_FILE_NAME);    
}

...

void OTPrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent) {
  G4int pdg;
  G4double vx, vy, vz, px, py, pz;

  fEventGenerator -> ReadNextEvent(vx, vy, vz);
  fParticleGun -> SetParticlePosition(G4ThreeVector(vx,vy,vz));

  while (fEventGenerator -> ReadNextTrack(pdg, px, py, pz)) {
    G4ParticleDefinition* particle = G4ParticleTable::GetParticleTable() -> FindParticle(pdg);
    fParticleGun -> SetParticleDefinition(particle);

    G4ThreeVector momentum(px,py,pz);
    fParticleGun -> SetParticleMomentum(momentum.mag()*MeV);
    fParticleGun -> SetParticleMomentumDirection(momentum.unit());
    fParticleGun -> GeneratePrimaryVertex(anEvent);
  }
}

EVENT_FILE_NAME 에는 이벤트 파일의 경로를 쓰면 된다. 자세한 설명은 생략한다.

주의사항
1. 위치와 운동량의 단위를 잘 생각하면서 시뮬레이션에 적용하도록 하자.

2. 이벤트 파일의 형식은 임의대로 정한 것이며 경우에 따라 달라질 수 있으니 내용을 이해하도록 하자.

댓글

댓글 본문