Skip to main content

Geant4 무작정 따라하기 - 9. 확률변수 이용하여 선원항 정의하기

Geant4 무작정 따라하기 시리즈의 아홉번째. 확률변수를 이용하여 Event마다 바뀌는 선원항을 정의하는 방법을 알아봅니다.


등방성 점선원 모사​

문제 제기​

등방적으로 발생하는 점선원을 생각해봅시다. 일반적으로 다음 그림과 같은 모양이 떠오를 것입니다.

01_isotropic

하지만 앞서 말씀드린 것처럼 Geant4는 한 번에 하나의 입자만을 수송하기 때문에, 실제로는 다음과 같이 매 Event마다 방향이 바뀌는 입자가 순차적으로 나오는 형태일 것입니다.

02_isotropic

이제 앞서 배운 선원항의 방향 정의 부분을 다시 살펴봅시다.

예를 들어 초기 입자의 운동방향을 +Z축인 (0, 0, 1)으로 설정하고 싶다면, 다음과 같이 입력하면 됩니다.

 // ...    
void PrimaryGeneratorAction::GeneratePrimaries(G4Event *anEvent)
{
// ...
fPrimary->SetParticleMomentumDirection(G4ThreeVector(0., 0., 1.));

fPrimary->GeneratePrimaryVertex(anEvent);
}

SetParticleMomentumDirection 함수를 통해 방향을 설정하고, 이 때 방향은 G4ThreeVector 형태로 입력을 해주어야 합니다. 우리는 결국 방향을 명시해서 입력해 줘야만 하는데, 이 방향이 알아서 매 번 바뀌어야 하는 상황에 놓였습니다.

해결책​

이 문제를 해결하기 위해 다음과 같은 함수를 상상해봅시다.

  • 이 함수는 G4ThreeVector를 반환하는데, 함수가 호출될 때마다 반환되는 값이 매번 바뀝니다.

  • 반환되는 G4ThreeVector들을 쭉 모아서 분포를 살펴보니, 단위구(Unit sphere) 표면 위의 점이 균일한 확률로 나옵니다.

  • 함수의 원형은 다음과 같습니다.

    G4ThreeVector RandomDirection();

이런 함수를 어떻게 만들 수 있을 지는 나중에 생각해보기로 하고, 이 함수의 출력값을 먼저 살펴봅시다. 아마도 다음과 같이 나타날 것입니다.

G4ThreeVector dir;

dir = RandomDirection(); // dir = G4ThreeVector(-0.157616,-0.293535,-0.942865);
dir = RandomDirection(); // dir = G4ThreeVector(0.185649,-0.743512,0.642437);
dir = RandomDirection(); // dir = G4ThreeVector(0.643525,0.268099,0.716937);
dir = RandomDirection(); // dir = G4ThreeVector(0.636717,-0.421678,0.645584);

바로 이 RandomDirection() 함수가 바로 우리가 원하던 방향을 등방적으로 균일하게 매 번 알아서 바꾸어서 제공해주는 함수입니다. 이런 함수만 있다면 선원항을 다음과 같이 정의하여 우리의 문제를 해결할 수 있겠군요. 다음과 같이 말입니다.

// ...    
void PrimaryGeneratorAction::GeneratePrimaries(G4Event *anEvent)
{
// ...
auto dir = RandomDirection();
fPrimary->SetParticleMomentumDirection(dir);

fPrimary->GeneratePrimaryVertex(anEvent);
}

설명​

이처럼 특정한 확률분포(Probability Distribution Function, PDF)를 따라 변하는 수를 확률변수라고 합니다. 그리고 이렇게 확률변수를 생성해내는 행위를 샘플링(sampling)한다고 합니다.

확률변수에 있어 가장 기본이 되는 것은, 소위 난수(random number)라고 불리는 ξ∼U(0 1)\xi \sim \mathcal{U}(0\,1)입니다. 0~1 범위 내의 실수가 균일하게 샘플링되는 난수 ξ\xi를 반환하는 함수는 대부분의 프로그래밍 언어가 기본으로 제공하고 있습니다1. 이 ξ\xi만 있으면, 이론상 임의의 PDF를 따르는 확률변수를 샘플링하는 함수를 만들 수 있습니다.

물론 이 부분은 수학적인 기교가 들어가는 내용이므로 여기서 다루지는 않겠습니다.

중요한 점은, 이렇게 확률변수를 샘플링하는 함수만 있으면 매 번 발생 조건이 바뀌는 선원항도 정의할 수 있게 된다는 것입니다.


G4RandomTools.hh​

Geant4는 G4RandomTools.hh라는 헤더를 통해, 자주 사용되는 PDF에 대해 확률변수를 샘플링하는 다양한 함수를 이미 만들어서 제공하고 있습니다. 덕분에 이러한 함수를 굳이 공부하여 만들어 쓸 필요가 없습니다.

대표적인 함수들을 일부 소개해드리겠습니다. (10.7 버전 기준)

G4RandomDirection​

앞서 설명했던, 등방적으로 방향을 샘플링하는 함수입니다. 원형은 다음과 같습니다.

G4ThreeVector G4RandomDirection();
G4ThreeVector G4RandomDirection(G4double cosTheta);

이 함수는 입력인자를 아예 입력하지 않고 사용할 수 있습니다. 이 경우 모든 방향(4π4\pi)에 대해 균일하게 샘플링된 G4ThreeVector를 반환받을 수 있습니다.

혹은, 입력인자로 임의의 각도 θ\theta에 대해 cosθ\mathcal{cos} \theta 값에 해당하는 실수(G4double)를 넣을 수도 있습니다. 이 경우에는 \+z\+z축을 중심축으로 하고 꼭짓각의 절반이 θ\theta인 원뿔 형태로 제한된 영역에 대해 균일하게 샘플링된 G4ThreeVector를 반환받을 수 있습니다.

G4LambertianRand​

입력된 벡터를 법선벡터로 갖는 평면에 대해 Lambert 코사인 법칙2을 따르게끔 방향을 샘플링하는 함수입니다. 원형은 다음과 같습니다.

G4ThreeVector G4LambertianRand(const G4ThreeVector& normal);

이 함수는 입력인자로 G4ThreeVector 하나를 넣어줘야 합니다. 그러면 그 벡터를 법선벡터(normal vector)로 갖는 평면을 기준으로 하여 Lambert 코사인 법칙을 따르는 방향을 샘플링하여 G4ThreeVector 형태로 반환해 줍니다.

G4PlaneVectorRand​

입력된 벡터를 법선벡터로 갖는 무한 평면상의 점을 샘플링하는 함수입니다. 원형은 다음과 같습니다.

G4ThreeVector G4PlaneVectorRand(const G4ThreeVector& normal);

이 함수는 입력인자로 G4ThreeVector 하나를 넣어줘야 합니다. 그러면 그 벡터를 법선벡터(normal vector)로 갖는 무한평면 상의 한 지점을 샘플링하여 G4ThreeVector 형태로 반환받을 수 있습니다.

G4RandomRadiusInRing​

평면 원 혹은 평면 고리에서 균일한 분포의 점을 샘플링 하기 위한 반경의 샘플링을 수행해주는 함수입니다. 원형은 다음과 같습니다.

G4double G4RandomRadiusInRing(G4double rmin, G4double rmax);

원이면 rmin을 0으로, rmax를 반지름으로 주면 됩니다. 고리라면 rmin을 내경으로, rmax를 외경으로 주면 됩니다.

G4RandomPointInEllipse​

평면 타원 내에서 균일한 분포의 2차원 점을 샘플링하는 함수입니다. 원형은 다음과 같습니다.

G4TwoVector G4RandomPointInEllipse(G4double a, G4double b);

x2a2+y2b2=1{x^2 \over a^2} + {y^2 \over b^2} = 1의 타원의 방정식을 따르는 평면 타원에 대해 aa, bb를 입력인자로 넣으면, 타원 내에서 균일한 분포의 2차원 점을 샘플링하여 반환해줍니다. G4TwoVector는 2차원 벡터를 다루는 클래스로, G4ThreeVector와 유사하게 사용하면 됩니다.

G4RandomPointOnEllipse​

평면 타원의 원주 위에서 균일한 분포의 2차원 점을 샘플링하는 함수입니다. 원형은 다음과 같습니다.

G4TwoVector G4RandomPointOnEllipse(G4double a, G4double b);

x2a2+y2b2=1{x^2 \over a^2} + {y^2 \over b^2} = 1의 타원의 방정식을 따르는 평면 타원에 대해 aa, bb를 입력인자로 넣으면, 타원의 원주 위에서 균일한 분포의 2차원 점을 샘플링하여 반환해줍니다. In과 On의 차이에 주의하세요.

G4RandomPointOnEllipsoid​

3차원 타원체의 표면 위에서 균일한 분포의 3차원 점을 샘플링하는 함수입니다. 원형은 다음과 같습니다.

G4ThreeVector G4RandomPointOnEllipsoid(G4double a, G4double b, G4double c);

x2a2+y2b2+z2c2=1{x^2 \over a^2} + {y^2 \over b^2} + {z^2 \over c^2} = 1의 타원체의 방정식을 따르는 3차원 타원체에 대해 aa, bb, cc를 입력인자로 넣으면, 타원체의 겉표면 위에서 균일한 분포의 3차원 점을 샘플링하여 반환해줍니다.

G4UniformRand​

X∼U(0 1)X \sim \mathcal{U}(0\,1)를 따르는 실수를 샘플링하는 함수입니다. 원형은 다음과 같습니다.

double G4UniformRand();

G4RandFlat::shoot​

균등분포를 따르는 실수를 샘플링하는 함수입니다. 원형은 다음과 같습니다.

double shoot(double a, double b); // example: G4RandFlat::shoot(a, b)

X∼U(a b)X \sim \mathcal{U}(a\,b)를 따르는 확률변수 XX를 샘플링하는 함수입니다.

G4RandGaussQ::shoot​

정규분포를 따르는 실수를 샘플링하는 함수입니다. 원형은 다음과 같습니다.

double shoot(double mean, double stdDev); // example: G4RandGaussQ::shoot(mean, stdDev)

평균(mean)이 μ\mu이고, 표준편차(stdDev)가 σ\sigma인 X∼N(μ σ2)X \sim \mathcal{N}(\mu \, {\sigma}^2)를 따르는 확률변수 XX를 샘플링하는 함수입니다.

G4RandExponential::shoot​

지수분포를 따르는 실수를 샘플링하는 함수입니다. 원형은 다음과 같습니다.

double shoot(double mean); // example: G4RandExponential::shoot(mean)

평균(mean)이 λ\lambda인 X∼Exp(λ)X \sim Exp(\lambda)를 따르는 확률변수 XX를 샘플링하는 함수입니다.


실제 적용 - 등방성 점선원​

이제 맨처음 고민하였던 등방성 점선원을 모사하는 방법을 모두 알아냈습니다.

PrimaryGeneratorAction 코드를 다음과 같이 작성하면 등방성 점선원을 모사할 수 있게 됩니다.

  • 헤더 G4RandomTools.hh를 포함
  • SetParticleMomentumDirection() 함수의 입력 인자로, G4RandomDirection() 함수의 출력값을 대입

실제 소스코드는 다음과 같이 작성하면 됩니다.

03_isotropic_code


최종 파일 다운받는 법​

이번 글에서 작성한 코드는 g4_minimal/ch2_PriGen 폴더에서 확인하실 수 있습니다.


정리​

이로써 선원항을 정의하는 방법까지 마쳤습니다.

다음 글에서는 시뮬레이션을 돌리며 원하는 정보를 획득하는 스코어링에 대해 살펴보도록 하겠습니다.


Changelog​

2025-12-02: github repository의 폴더구조 변경에 따른 내용 수정

Footnotes​

  1. 사실 컴퓨터는 완전히 무작위적인 난수를 발생시키지는 못해서 의사난수(pseudo random number)를 샘플링하는 함수들을 제공합니다. ↩

  2. 이상적인 난반사 표면에서 방출되는 선속이 법선벡터로부터 벗어난 각도의 cos\mathcal{cos} 값에 비례한다는 법칙. 참고 링크: Lambert's cosine law - Wikipedia ↩