Multipath
Reflection and diffraction path tracing in RayD
Overview#
RayD exposes low-level multipath primitives for building custom wave simulators. These APIs enumerate geometric paths and accumulate field contributions — they do not implement a complete propagation model. The caller owns the source model, receiver model, material policy, and optimization loop.
There are two categories:
trace_*— enumerate geometric or field paths, return per-ray recordsaccum_*— launch native accumulation kernels that reduce contributions into grid cells
Reflection Path Tracing#
Trace specular reflection chains using image sources:
chain = scene.trace_reflections(ray, max_bounces=2)| Parameter | Type | Default | Description |
|---|---|---|---|
ray | Ray or RayAD | required | Rays to trace |
max_bounces | int | required | Maximum reflection bounces |
options | ReflectionTraceOptions | None | None | Optional trace options |
active | Mask | True | Per-ray active mask |
symbolic | bool | True | Use symbolic Dr.Jit recording |
Returns ReflectionChain (or ReflectionChainAD).
ReflectionChain fields#
| Field | Description |
|---|---|
t | Hit distances per bounce |
hit_points | Hit positions per bounce |
geo_normals | Geometric normals per bounce |
image_sources | Image source positions per bounce |
plane_points | Reflection plane points per bounce |
plane_normals | Reflection plane normals per bounce |
shape_ids | Mesh indices per bounce |
global_prim_ids | Global primitive indices per bounce |
bounce_count | Number of valid bounces per ray |
ray_count | Total number of rays |
ReflectionTraceOptions#
options = rd.ReflectionTraceOptions()
options.deduplicate = True
options.image_source_tolerance = 1e-5| Field | Default | Description |
|---|---|---|
deduplicate | False | Remove duplicate reflection paths |
image_source_tolerance | 1e-5 | Tolerance for image source deduplication |
export_mode | — | Controls export verbosity |
Reflection Accumulation#
Accumulate reflected field or power onto a receiver grid — the high-throughput path when individual path records are not needed:
grid = rd.AccumGrid()
grid.axis = 2 # z axis
grid.position = 1.5
grid.coord0_min = -5.0
grid.coord0_max = 5.0
grid.coord1_min = -5.0
grid.coord1_max = 5.0
grid.resolution0 = 32
grid.resolution1 = 32
material = rd.MaterialAD()
material.eta_r = ...
material.sigma = ...
material.mu_r = ...
material.gain = ...
material.valid = ...
options = rd.AccumOptions()
options.wavelength = 0.086
options.k = 73.0
options.solid_angle_per_ray = ...
options.cell_area = ...
options.seed = 0
result = scene.accumulate_reflections(
ray, tx_position, grid, material, max_bounces=2, options=options
)Returns AccumResult with:
| Field | Description |
|---|---|
reflection_power | Accumulated power per grid cell |
reflection_field_x/y/z | Accumulated field components per grid cell |
reflection_count | Number of reflections per grid cell |
ray_count | Total rays launched |
Equivalent Path Correction (EPC)#
EPC traces reflection paths toward a specific receiver point, correcting for path equivalence:
result = scene.trace_refl_epc(ray, receiver, max_bounces=2)Returns ReflEpc with reflection points, path lengths, and primitive IDs per bounce.
For the complex field version:
options = rd.ReflEpcFieldOptions()
options.wavelength = 0.086
options.omega = 2 * math.pi * frequency
# ... set material slot fields ...
result = scene.trace_refl_epc_field(ray, receiver, max_bounces=2, options=options)Returns ReflEpcField with complex field components field_x_re/im, field_y_re/im, field_z_re/im.
Diffraction Accumulation#
Native diffraction grid accumulation for order-1 chains:
result = scene.accum_dfr_direct(states, grid, material, options)For order-2/3 chains:
result = scene.accum_dfr(initial_states, recursive_states, grid, material, options)Both return DfrAccum with:
| Field | Description |
|---|---|
power | Accumulated diffraction power per grid cell |
field_x/y/z | Accumulated field components |
direct_count | Direct diffraction contributions |
keller_count | Keller diffraction contributions |
suffix_count | Suffix-reflection contributions |
Diffraction Path Export#
Export compact first-order diffraction paths:
paths = scene.trace_dfr_paths(tx_positions, rx_positions, states, material, options)Returns DfrPaths with per-path fields: delay, field_x/y/z, order, edge0/1/2, p0/1/2.
AD Support#
All multipath APIs accept both non-AD and AD inputs. Geometric outputs carry Dr.Jit gradients. Discrete path selection decisions run detached.
| API | AD support |
|---|---|
trace_reflections() | Geometric AD |
accumulate_reflections() | Native AD |
trace_refl_epc() | Detached only |
trace_refl_epc_field() | Native AD |
accum_dfr_direct() | Native AD |
accum_dfr() | Native AD |
trace_dfr_paths() | Geometric AD |
Next Steps#
- Tutorials — worked examples
- WiTwin Channel — high-level RF simulator built on RayD