diff options
author | Stan Seibert <stan@mtrr.org> | 2011-08-18 19:38:42 -0400 |
---|---|---|
committer | Stan Seibert <stan@mtrr.org> | 2011-08-18 19:38:42 -0400 |
commit | 58c02bd3b24cfbb399f1c68e6965f69b56e7e498 (patch) | |
tree | 3616529092b15aeee793540561f66442a31d1993 /src | |
parent | 10f8e10b73dbf88f244cb83dbdec5e80d89ee658 (diff) | |
download | chroma-58c02bd3b24cfbb399f1c68e6965f69b56e7e498.tar.gz chroma-58c02bd3b24cfbb399f1c68e6965f69b56e7e498.tar.bz2 chroma-58c02bd3b24cfbb399f1c68e6965f69b56e7e498.zip |
Replace Rayleigh scattering implementation with that from SNOMAN. The
angular distribution is slightly different, and now fits with the
distribution given in the GEANT4 physics reference manual.
Unit test is now included to verify the correctness of the scattering.
Diffstat (limited to 'src')
-rw-r--r-- | src/photon.h | 60 |
1 files changed, 41 insertions, 19 deletions
diff --git a/src/photon.h b/src/photon.h index 45ad79b..e781864 100644 --- a/src/photon.h +++ b/src/photon.h @@ -105,30 +105,52 @@ __device__ void fill_state(State &s, Photon &p) } // fill_state -__device__ void rayleigh_scatter(Photon &p, curandState &rng) +__device__ float3 pick_new_direction(float3 axis, float theta, float phi) { - float theta, y; - - while (true) - { - y = curand_uniform(&rng); - theta = uniform(&rng, 0, 2*PI); - - if (y < powf(cosf(theta),2)) - break; + // Taken from SNOMAN rayscatter.for + float cos_theta = cosf(theta); + float sin_theta = sinf(theta); + float cos_phi = cosf(phi); + float sin_phi = sinf(phi); + + float sin_axis_theta = sqrt(1.0f - axis.z*axis.z); + float cos_axis_phi, sin_axis_phi; + + if (isnan(sin_axis_theta) || sin_axis_theta < 0.00001f) { + cos_axis_phi = 1.0f; + sin_axis_phi = 0.0f; + } else { + cos_axis_phi = axis.x / sin_axis_theta; + sin_axis_phi = axis.y / sin_axis_theta; } - float phi = uniform(&rng, 0, 2*PI); - - float3 b = cross(p.polarization, p.direction); - float3 c = p.polarization; - - p.direction = rotate(p.direction, theta, b); - p.direction = rotate(p.direction, phi, c); + return make_float3(cos_theta*axis.x + sin_theta*(axis.z*cos_phi*cos_axis_phi - sin_phi*sin_axis_phi), + cos_theta*axis.y + sin_theta*(cos_phi*axis.z*sin_axis_phi - sin_phi*cos_axis_phi), + cos_theta*axis.z - sin_theta*cos_phi*sin_axis_theta); +} - p.polarization = rotate(p.polarization, theta, b); - p.polarization = rotate(p.polarization, phi, c); +__device__ void rayleigh_scatter(Photon &p, curandState &rng) +{ + float cos_theta = 2.0f*cosf((acosf(1.0f - 2.0f*curand_uniform(&rng))-2*PI)/3.0f); + if (cos_theta > 1.0f) + cos_theta = 1.0f; + else if (cos_theta < -1.0f) + cos_theta = -1.0f; + + float theta = acosf(cos_theta); + float phi = uniform(&rng, 0.0f, 2.0f * PI); + + p.direction = pick_new_direction(p.polarization, theta, phi); + + if (1.0f - fabsf(cos_theta) < 1e-6f) { + p.polarization = pick_new_direction(p.polarization, PI/2.0f, phi); + } else { + // linear combination of old polarization and new direction + p.polarization = p.polarization - cos_theta * p.direction; + } + p.direction /= norm(p.direction); + p.polarization /= norm(p.polarization); } // scatter __device__ int propagate_to_boundary(Photon &p, State &s, curandState &rng) |