propagate.h : propagate_to_boundary / propagate_at_boundary_geant4_style

propagate.h : propagate_to_boundary absorb/scatter/sail

  • absorb
    1. advance p.time and p.position to absorption point
    2. if BULK_REEMIT(CONTINUE) change p.direction p.polarization p.wavelength
    3. if BULK_ABSORB(BREAK) .last_hit_triangle -1
  • scatter
    1. advance p.time and p.position to scattering point
    2. RAYLEIGH_SCATTER(CONTINUE) change p.direction p.polarization
  • sail
    1. advance p.position p.time to boundary
    2. sail to boundary(PASS)
    3. consumes 3u

Inputs:

  • p.time
  • p.position
  • p.direction
  • s.distance_to_boundary
  • s.material1.x refractive_index
  • s.material1.y absorption_length
  • s.material1.z scattering_length
  • s.material1.w reemission_prob

Outputs:

  • p.time
  • p.position
  • p.direction
  • p.wavelength
  • p.polarization
  • p.flags.i.x (boundary)
  • p.flags.i.w (history)

Returns:

  • BREAK(BULK_ABSORB)
  • CONTINUE(BULK_REEMIT)
  • CONTINUE(RAYLEIGH_SCATTER)
  • PASS(“SAIL”)

propagate.h : propagate_at_boundary_geant4_style

See env-/g4op-/G4OpBoundaryProcess.cc annotations to follow this and compare the Opticks and Geant4 implementations.

Inputs:

  • p.direction
  • p.polarization
  • s.material1.x : refractive index
  • s.material2.x : refractive index
  • s.surface_normal

Outputs:

  • p.direction
  • p.polarization
  • p.flags.i.x (boundary)
  • p.flags.i.w (history)

Tacitly returns CONTINUE

Notes:

  • when geometry dictates TIR there is no dependence on u_reflect, just always get reflection

fresnel reflect/transmit conventional directions

            s1
          +----+
           \   .   /      ^
      c1   i\  .  / r    /|\
             \ . /        |
material1     \./         | n
---------------+----------+----------
material2      .\
               . \
          c2   .  \ t
               .   \
               +----+
                 s2
i, incident photons
pointing down to interface (from material1 towards material2)
n, surface normal (s.surface_normal)
pointing up from interface (from material2 back into material1) Orientation is arranged by flipping geometric normal based on photon direction.
t, transmitted photons
from interface into material2
r, reflected photons
from interface back into material1
c1, costheta_1
cosine of incident angle, c1 = dot(-i, n) = - dot(i, n) arranged to be positive via normal flipping and corresponding flip of which material is labelled 1 and 2

polarisation

S polarized : E field perpendicular to plane of incidence
P polarized : E field within plane of incidence

normal incidence photons

  • no unique plane of incidence,
  • artifically setting incident_plane_normal to initial p.polarisation yields normal_coefficient = 1.0f so always treated as S polarized
initial momentum dir
-s.surface_normal
final momentum dir (c1 = 1.f)
-s.surface_normal + 2.0f*c1*s.surface_normal = +s.surface_normal = -p.direction

minimise use of trancendental functions

Obtain c2c2 from Snells Law without lots of expensive function calls.:

n1 s1 = n2 s2

   s2 = eta * s1       eta = n1/n2

 c2c2 = 1 - s2s2
      = 1 - eta eta s1 s1
      = 1 - eta eta (1 - c1c1)


 c2c2 - 1 = (c1c1 - 1) eta eta

TIR : total internal reflection

Total internal reflection, occurs when c2c2 < 0.f (c2 imaginary)

Handled by:

  • artificially setting c2 = 0.f
  • results in reflection_coefficient = 1.0f so will always reflect for both S and P cases

propagate.h : propagate_at_specular_reflector / propagate_at_specular_reflector_geant4_style

Inputs:

  • p.direction
  • p.polarization
  • s.surface_normal
  • s.cos_theta

Outputs:

  • p.direction
  • p.polarization
  • p.flags.i.x
  • p.flags.i.w

Returns:

CONTINUE

propagate.h : propagate_at_surface

Inputs:

  • s.surface.x detect
  • s.surface.y absorb (1.f - reflectivity ) ?
  • s.surface.z reflect_specular
  • s.surface.w reflect_diffuse

These properties are setup in GSurfaceLib::createStandardSurface which then get interveaved with material properties into the boundary_texture for GPU access.

Surface and material properties are read from the texture for the relevant boundary index that results from the ray trace.

  • optixrap/cu/state.h:fill_state
  • optixrap/cu/boundary_lookup.h

Returns:

  • BREAK(SURFACE_ABSORB)
  • BREAK(SURFACE_DETECT)
  • CONTINUE(SURFACE_DREFLECT)
  • CONTINUE(SURFACE_SREFLECT)

Known differences vs counterpart DsG4OpBoundaryProcess::DoAbsorption

  • u_surface_burn not compared against theEfficiency to decide on detect

TODO

  • arrange values to do equivalent to G4 ?

    absorb + detect + reflect_diffuse + reflect_specular = 1 ??

  • How to handle special casing of some surfaces…

    • SPECULARLOBE…