Geant4 가이드

Randomize

랜덤 엔진은 보통 같은 시드를 사용했을 때 항상 같은 랜덤 수의 배열을 사용한다. 매 시뮬레이션을 마다 항상 같은 결과를 원하는 것이 아니라면 항상 다른 시드를 사용해야 한다. 예를 들어서 c의 time 함수를 이용해서 메인 프로그램에 다음과 같이 적용할 수 있다.

G4Random::setTheSeed(time(0));

헤더는 Randomize.hh와 time.h를 사용한다.

G4Random의 랜덤 엔진은 다음과 같이 지원한다.

  • HepJamesRandom (기본)
  • DRand48Engine
  • RandEngine
  • RanluxEngine
  • RanecuEngine

자세한 내용은 아래 참고자료를 참고 하자. 엔진 세팅은 다음과 같이 한다.

G4Random::setTheEngine(new CLHEP::RanecuEngine);

균일하게 랜덤한 숫자를 꺼내오고 싶을 때는 flat() 함수를 사용한다.

G4Random::getTheGenerator() -> flat()

참고자료

댓글

댓글 본문
  1. ejungwoo
    SetMomentumDirection(G4ThreeVector(0,0,1))의 (0,0,1) 은 빔이 나가는 방향 벡터를 의미합니다.

    G4ThreeVector라는 이름이 헷갈릴 수 있다고 생각합니다만 SetParticlePosition(...) 에 넣을 때는 위치를 의미하고 SetMomentumDirection(...)에 넣을때는 방향벡터를 의미합니다.

    아래 작성하신 코드를 보면,

    1. OTPrimaryGeneratorAction::OTPrimaryGeneratorAction() 즉, OTPrimaryGeneratorAction 생성자에 작성하신것으로 보이는데 이 함수는 처음 클래스가 만들어질 때 딱 한번만 실행되기 때문에 이 함수에서 랜덤한 위치나 방향을 설정하여도 결국 매 이벤트마다 같은 위치와 방향을 적용하게 됩니다.
    이 부분은 매 이벤트 마다 실행되는 GeneratePrimaries(G4Event* anEvent) 함수에 작성해야 합니다. GeneratePrimaries(G4Event* anEvent) 함수에 작성하신 것이 맞다면 fParticle = new G4ParticleGun(1) 부분은 생성자에 두는 것이 좋습니다.

    2. 제가 작성했던 랜덤한 벡터 G4ThreeVector(std::sin(theta)*std::cos(phi), std::sin(theta)*std::sin(phi), std::cos(theta)) 는 위치가 아닌 방향벡터입니다. 이제 보니 제가 처음 질문을 잘못 이해했었네요. 일정 범위 안의 랜덤한 위치를 만드려면 위 벡터에 원하는 반지름 이하의 랜덤 값을 곱하고 원의 중심 위치만큼 이동을 시켜야겠네요.

    3. 랜덤하게 구한 ParticleGun의 위치를 position0, 검출기의 위치를 position1 이라고 했을때 검출기를 향하는 방향은 단순하게 position1 - position0 이 되겠죠.
    대화보기
    • 이핑크
      압변 감사드립니다.
      다만 위의 예제에서는 시작점을 일정하게 두고, random한 방향으로 발사하는것으로 코드를 이해하였습니다.
      그렇다면 시작점을 랜덤하게 주고, 우리가설정한 DETECTOR를 목표 Direction 으로 하여 particlegun을 할수도 있나요?

      fParticleGun = new G4ParticleGun(1);

      G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
      G4ParticleDefinition* particle = particleTable -> FindParticle("proton");
      auto phi = 2*CLHEP::pi*G4UniformRand();
      auto theta = CLHEP::pi*G4UniformRand();

      fParticleGun -> SetParticlePosition(G4ThreeVector(std::sin(theta)*std::cos(phi), std::sin(theta)*std::sin(phi), std::cos(theta)));
      fParticleGun -> SetParticleDefinition(particle);
      ------------------------------------------------------------------------------------------------------
      fParticleGun -> SetParticleMomentumDirection(G4ThreeVector(0.,0.,1.));
      ------------------------------------------------------------------------------------------------------
      fParticleGun -> SetParticleEnergy(40.*MeV);

      가운데 001 부분을 어떻게 조정해야 기존 001에놓여있던 Detector에 임의의 방향에서 발사한 Particle들이 입사하는지 궁금하네요
    • 이핑크
      압변 감사드립니다.
      다만 위의 예제에서는 시작점을 일정하게 두고, random한 방향으로 발사하는것으로 코드를 이해하였습니다.
      그렇다면 시작점을 랜덤하게 주고, 우리가설정한 DETECTOR를 목표 Direction 으로 하여 particlegun을 할수도 있나요?

      particle의 시작위치를 정해주는 명령어가 어떤것인지도 궁금하네요
    • ejungwoo
      flat() 함수와 G4UniformRand() 함수는 같습니다.

      매 이벤트 마다 바꾸려면 G4VUserPrimaryGeneratorAction::GeneratePrimarries(G4Event* anEvent) 함수에서
      에서 랜덤 함수를 이용해서 방향을 매번 바꿔주면 됩니다. 예를 들어서 완전히 랜덤한 방향을 원할때는 아래와 같이 할 수 있습니다.

      void OTPrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent)
      {
      auto phi = 2*CLHEP::pi*G4UniformRand();
      auto theta = CLHEP::pi*G4UniformRand();

      fParticleGun -> SetParticleMomentumDirection(G4ThreeVector(std::sin(theta)*std::cos(phi), std::sin(theta)*std::sin(phi), std::cos(theta)));
      fParticleGun -> GeneratePrimaryVertex(anEvent);
      }

      원하는 각도가 있다면 G4UniformRand()의 범위(0~1)를 생각해서 각도의 범위를 조절하면 됩니다.

      참고로 CLHEP::pi는 우리가 흔히 알고 있는 원주율 pi의 값입니다.
      std::cos, std::sin을 사용하기 위해서는 파일에 #include <cmath> 를 추가해야 합니다.
      대화보기
      • 이핑크
        random 함수를 사용하여 매 이벤트마다 random하게 particle을 발사하려고하면 어떻게해야 할까요?
        인터넷을 찾아보니 G4uniformRand()함수를 사용하는것 같기도한데 위예제 에서는 어떻게 사용해야할지 잘모르겠네요. 혹시 일정한 반지름 안에서 random하게 쏠수도 있을까요?
      버전 관리
      ejungwoo
      현재 버전
      선택 버전
      graphittie 자세히 보기