Solvers and path types

The five propagation components Channel traces and the four solvers that combine them, with what each solver returns and supports.

Channel separates what a signal can do on its way to the receiver (the propagation components) from how the paths are found and combined (the solver). You pick both: a solver module, and a set of components in that solver's Config.

Propagation components#

Every Config has a components argument, a non-empty subset of these five names. The default is {"los", "reflection", "diffraction"}.

ComponentPhysicsNotes
"los"Line of sight, free-space spreading wavelength / (4 * pi * d)Blocked by any surface in between, unless the surface is part of a "transmission" path.
"reflection"Specular reflection with Fresnel coefficients of the hit materialUp to max_depth bounces, at most 5.
"diffraction"First-order edge diffraction with the uniform theory of diffraction (UTD)Diffraction order is 1. max_diffraction_order accepts only 0 or 1.
"transmission"Penetration through layered thin-sheet wallsOpt-in. Each wall crossing counts toward max_depth, like a bounce.
"scattering"Diffuse scattering from rough surfaces (Kirchhoff model)Opt-in. Needs materials with roughness_front or roughness_back.

max_depth is the maximum number of interactions per path. max_depth=0 keeps only line of sight; max_depth=1 adds single reflections, single wall penetrations and edge diffraction.

Coupled reflection-diffraction paths#

With coupled_paths=True, the deterministic, path and BDPT solvers also trace paths that combine one reflection and one diffraction in either order (reflection then diffraction, diffraction then reflection) and double diffraction. Coupled paths need max_depth >= 2 and both "reflection" and "diffraction" in components. coupled_candidate_limit (default 1,000,000, the maximum) bounds the candidate search; exceeding it raises an error instead of dropping paths.

Component codes#

Path tables report a component_id per path:

CodeComponent
0los
1reflection
2diffraction
3reflection then diffraction
4diffraction then reflection
5transmission
6scattering
7double diffraction (coupled)

The Path solver also reports per-interaction flags in interaction_type with the InteractionType flag enum: NONE=0, REFLECTION=1, DIFFRACTION=2, TRANSMISSION=4, SCATTERING=8.

The four solvers#

Each solver is a module with its own Config, Result and solve(scene, config, *, reference_frequency_hz). Configs are not interchangeable: passing one solver's Config to another raises.

ModuleMethodMain resultUse it for
witwin.channel.deterministicExact path discovery, coherent sum of complex fieldspath_gain, complex field, per-component power and fields, optional compact PathTableRepeatable link values and radio maps, inverse problems
witwin.channel.pathExact path discovery per antenna pairPathResult: complex coefficients a, delays tau, angles, interactions, CIR/CFR/taps, beamformingLink-level channel models, arrays, delay spread
witwin.channel.montecarlo.basicMonte Carlo ray sampling, incoherent powerpath_gain and per-component power and mapsFast coverage estimates over large grids
witwin.channel.montecarlo.bdptBidirectional path tracing with multiple importance sampling (MIS)path_gain, per-component power and maps, optional sample exportCoverage in scenes where unidirectional sampling misses paths

What each solver supports, from witwin.channel.capabilities():

Capabilitydeterministicpathmontecarlo.basicmontecarlo.bdpt
Complex path coefficientsyesyesno (power only)yes, for coherent events
Polarizationyesyesnoyes
Antenna arraysnoyesnono
Coupled reflection-diffractionyesyesnoyes
Gradients (ad_mode="jvp" / "vjp")yesyesyessee below
Receiver gridsyes, as a mapyes, each sample becomes one receiveryes, as a mapyes, one grid per scene

All five components are available in all four solvers. Scattering is not differentiable in any solver. In 0.5.0 the BDPT Config accepts ad_mode="jvp" and "vjp" and differentiates material, frequency and transmit-power parameters through the sampled paths, but capabilities() still reports BDPT as primal-only and refuses geometry gradients through its stochastic sampler. Treat BDPT gradients as experimental. See Differentiability.

Coherent and incoherent combination#

The deterministic solver adds the complex fields of all paths (coherent=True, the default), so path_gain shows interference fringes, as a real narrowband receiver would see. With coherent=False it adds powers instead. Monte Carlo Basic always adds powers. BDPT adds powers by default; coherent=True sums the line-of-sight, reflection and diffraction contributions as complex phasors per transmitter, receiver and component, and is refused together with "transmission" or "scattering".

Rough-surface scattering rows are incoherent power by default. In the deterministic solver, scattering_coherent=True sums them coherently, which is physical only for realization-coherent phase screens (see Materials).

Choosing a solver#

  • Start with deterministic for a link or a radio map. Its results are exact for the traced paths and repeatable.
  • Use path when you need individual paths, delays, angles, CIR/CFR or antenna arrays.
  • Use Monte Carlo Basic for large grids where an incoherent power estimate is enough. Raise samples until the map stops changing.
  • Use BDPT when Monte Carlo Basic is noisy because the important paths are hard to hit from the transmitter side.

The radio map solver comparison runs all three radio-map solvers on one scene.

Failure behavior#

Channel never returns a partial or silently degraded result. An invalid configuration raises in the Config constructor (ValueError or RuntimeError). An unsupported combination, a capacity overflow, a missing native capability or a missing GPU raises during the solve, before any result is returned. Requested components are never dropped silently.