witwin.channel.propagation.consumer

API reference for the propagation consumer - request types, evaluate, fixed-topology replay, time-varying evaluation, wideband offsets and constants.

The propagation consumer is the compact interface other WiTwin solvers (for example Radar) use to get paths from Channel. Instead of a solver result, it returns exactly K path rows: their discrete topology, continuous geometry and a transport coefficient. It can also replay a discovered topology for moved endpoints, many time slots or many frequencies without searching for paths again.

from witwin.channel.propagation import consumer
from witwin.channel.scene import compile

Result and topology types are on consumer types. The fixed-topology replay guide walks through a complete example.

Constants#

NameValue
CONTRACT_VERSION6
MAX_DEPTH5
COMPONENTSfrozenset({"los", "reflection", "transmission", "diffraction"})
RESPONSESfrozenset({"scalar_transport", "complex3_transport", "polarimetric_transport"})
TOPOLOGY_MODESfrozenset({"discover"})
AD_MODESfrozenset({"none", "jvp", "vjp"})
PropagationComponent, PropagationResponse, PropagationTopologyMode, PropagationAdModeLiteral type aliases of the four sets above

"scattering" is not a consumer component. Membership in these sets does not mean every combination works: ask capabilities().

EndpointBatch#

EndpointBatch(stable_ids, positions_m, polarizations, polarization_basis=None, powers_w=None)

A batch of N point endpoints. All tensors must be contiguous CUDA tensors on one device.

stable_idstorch.Tensorrequired

int64, (N,). Stable endpoint IDs, chosen by you; they are echoed in the topology.

positions_mtorch.Tensorrequired

float32, (N, 3) world positions in metres.

polarizationstorch.Tensorrequired

float32, (N, 3) polarization vectors.

polarization_basistorch.Tensor | Nonedefault None

float32, (N, 2, 3) transverse basis. Required for "polarimetric_transport".

powers_wtorch.Tensor | Nonedefault None

float32, (N,) transmit power in watts. Required for sources, not allowed for sinks.

Properties: count (N) and device. Raises TypeError or ValueError on a dtype, shape, device or contiguity error.

PropagationRequest#

PropagationRequest(sources, sinks, reference_frequency_hz, components, max_depth, response, topology_mode, ad_mode, max_paths=None)

A path-discovery request. Every argument except max_paths is required.

sourcesEndpointBatchrequired

Transmitting endpoints, with powers_w.

sinksEndpointBatchrequired

Receiving endpoints, without powers_w.

reference_frequency_hzfloat | torch.Tensorrequired

Must equal the frequency the CompiledScene was compiled at.

componentsfrozenset[str]required

Non-empty frozenset of consumer components.

max_depthintrequired

0 to MAX_DEPTH (5).

responsestrrequired

"scalar_transport" (complex scalar per row), "complex3_transport" (world-frame field vector per row) or "polarimetric_transport" (2 x 2 Jones matrix per row).

topology_modestrrequired

"discover".

ad_modestrrequired

"none", "jvp" or "vjp".

max_pathsint | Nonedefault None

Positive limit on K. Exceeding it raises instead of truncating.

FixedTopologyRequest#

FixedTopologyRequest(sources, sinks, reference_frequency_hz, topology, response, ad_mode, world_motion="frozen_world", slot_count=1, frequency_offsets_hz=None)

A replay request: evaluate known paths again for new endpoint positions.

topologyPreparedFixedTopology | PropagationTopologyrequired

A handle from prepare_fixed_topology. A raw PropagationTopology is accepted only for line-of-sight-only topologies.

world_motionstrdefault 'frozen_world'

"frozen_world" requires all four scene versions to match the discovery. "fixed_winner_replay" also allows a changed geometry_version, replaying the same paths on moved geometry.

slot_countintdefault 1

Number of block-diagonal slots stacked in the endpoint batches. Values above 1 need a PreparedFixedTopology built with replicate_over_slots.

frequency_offsets_hztuple[float, ...] | Nonedefault None

Host tuple of frequency offsets. Column j is evaluated at reference_frequency_hz + frequency_offsets_hz[j]. Values must be finite, unique and resolvable on the native float32 grid; see native_frequency_resolution_hz.

sources, sinks, reference_frequency_hz, response and ad_mode mean the same as in PropagationRequest. Property frozen_topology returns the underlying PropagationTopology.

TimeVaryingRequest#

TimeVaryingRequest(sources, sinks, reference_frequency_hz, topology, times_s, response, ad_mode, world_motion="frozen_world")

Replay one topology across S time slots in one call.

topologyPreparedFixedTopologyrequired

The per-slot prepared topology (from prepare_fixed_topology), not a replicated one. Channel replicates it over the slots.

times_storch.Tensorrequired

Non-empty 1-D float64 tensor of S time labels. They label the slots; they do not drive any computation.

Source and sink batches hold S slots stacked slot-major: rows s * n to (s + 1) * n - 1 belong to slot s. Property slot_count returns S.

Functions#

evaluate#

evaluate(compiled_scene, request) -> PropagationEvaluation

Discovers the paths between all sources and sinks and evaluates them. Validates the scene, frequency, component, response and AD combination before any GPU work.

compiled = compile(scene, reference_frequency_hz=3.0e9)
result = consumer.evaluate(compiled, request)
print(result.paths.path_count)              # K
print(result.paths.transport.coefficient)   # (K,) complex64

prepare_fixed_topology#

prepare_fixed_topology(topology) -> PreparedFixedTopology

Groups the rows of a discovered topology by (component, depth) for replay. It copies a few integers to the host and synchronizes once. Call it once per discovery and reuse the handle.

reevaluate#

reevaluate(compiled_scene, request) -> FixedTopologyEvaluation

Evaluates the frozen rows of a FixedTopologyRequest without searching for paths. Rows can become invalid (row_valid is False) when a path is blocked at the new positions; new paths are never found. A changed topology_version, material_version or assignment_version raises; a changed geometry_version raises unless world_motion="fixed_winner_replay".

rediscovery_required#

rediscovery_required(compiled_scene, topology, *, revalidate_source=False) -> str | None

Returns the name of the version domain that changed since the topology was discovered, or None. The default compares four host integers. revalidate_source=True also recomputes the versions from the source witwin.core world, which costs time proportional to the scene size. It cannot detect a new path that appeared under "fixed_winner_replay"; rediscover on a schedule for that.

replicate_over_slots#

replicate_over_slots(prepared, slot_count, *, source_count, sink_count) -> PreparedFixedTopology

Repeats a per-slot topology over slot_count block-diagonal slots, by index arithmetic only. source_count and sink_count are the endpoint counts per slot; they cannot be inferred because an endpoint without paths has no row. slot_count=1 returns prepared.

evaluate_time_varying#

evaluate_time_varying(compiled_scene, request) -> TimeVaryingEvaluation

Evaluates all slots of a TimeVaryingRequest in one replay and returns (S, K) views. All slots share one CompiledScene, so structures must not move between slots; only endpoints move. See the time-varying channel tutorial.

capabilities#

capabilities() -> PropagationCapabilities

Returns what this contract version supports. No GPU work.

caps = consumer.capabilities()
print(sorted(caps.components_for("scalar_transport")))  # ['diffraction', 'los', 'reflection', 'transmission']
print(caps.ad_modes_for_component("diffraction"))       # frozenset({'none'})
print(caps.fixed_topology_components)                   # frozenset({'los', 'reflection'})

native_frequency_resolution_hz#

native_frequency_resolution_hz(reference_frequency_hz) -> float

The smallest frequency step the native float32 launch grid can resolve at this carrier, in hertz: 256.0 at 3 GHz, 8192.0 at 77 GHz. Offsets closer than this cannot be told apart. Non-finite or non-positive input raises ValueError.

Wideband replay refusals#

frequency_offsets_hz raises before any GPU work in these cases:

ConditionException
The scene has dispersive materialsNotImplementedError
The scene has rough materials or phase screensNotImplementedError
Offsets are empty, duplicate, non-finite or not resolvableValueError
Offsets are a tensor instead of a tupleTypeError
response="polarimetric_transport"NotImplementedError