Release notes

What changed in each witwin (WiTwin Core) release, newest first, with migration steps from 0.3 to 0.4 and the known issues of 0.4.0.

This page summarizes each witwin release, newest first. The repository has no changelog file; these notes come from the git history and the tags of witwin-core and from the README's migration section. Core uses semantic versioning within 0.x, so a minor release can break the API.

0.4.0 (2026-07-30)#

Current release. Pure-Python wheel witwin-0.4.0-py3-none-any.whl on PyPI. Requires CPython 3.10 to 3.14, torch>=2.10 and numpy>=1.24. Channel 0.5.0 pins witwin==0.4.0; Maxwell 0.5.1 and Radar 0.4.1 require witwin>=0.4,<0.5.

0.4.0 turns Core from a geometry-and-material library into the shared logical world model of the WiTwin solvers.

Added

  • World model. Scene, SceneSnapshot, SceneVersions, StructureState, EndpointState. A scene holds structures and antenna endpoints, enforces unique IDs, and reports four granular versions (topology, geometry, material, assignment) that also detect in-place tensor changes. The with_* methods return updated scenes. See The world model.
  • Motion. DynamicScene, LinearTrajectory, RigidMotion, DeformationState and the Trajectory and Deformation protocols. See Animate a scene.
  • Antennas. AntennaState, ReceiverGrid, AntennaPattern and antenna_orientation_matrix, with differentiable orientation, polarization and grid points.
  • Identity. StructureId, MaterialId, AssignmentId, SurfaceId, AntennaId, PrimitiveId, with new_*_id() and reserve_*_id() allocators. See Identity and versions.
  • Materials. PhysicalMaterial gains material_id, version, thickness_m, layers, geometry_mode, front and back roughness, dispersion, gain, scattering_coefficient, xpd_coefficient and conductor_model, plus PhysicalMaterial.perfect_conductor(). New: MaterialLayer, SurfaceRoughness, PhaseScreen, PowerLawDispersion, DispersionSpec, MaterialAssignment. Frequency evaluation keeps autograd for tensor inputs.
  • Structures. Structure gains stable IDs, primitive_ids and primitive_id(), a phase_screen, and typed mesh UVs (uv, face_uv).
  • Math. normalize_vec3, and the type aliases ScalarLike (float | torch.Tensor) and ComplexLike.
  • Stable API. The supported public API is exactly witwin.core.__all__, and a test locks it.

Changed

  • Mesh.vertices, Mesh.faces, Mesh.world_vertices and Mesh.bounds_world are tensors. vertices and faces return the authored tensors themselves. bounds_world has shape (2, 3): minimum corner in row 0, maximum in row 1.
  • Geometry never moves a tensor to another device. Conflicting devices raise ValueError.
  • CUDA-authored meshes skip host topology diagnostics and never build a host BVH, so fill_mode="auto" needs an explicit "solid" or "surface" before a distance query.
  • Structure moved from witwin.core.material to witwin.core.structure. Imports from witwin.core are unchanged.
  • Continuous quantities are annotated ScalarLike instead of Any. Accepted runtime values are unchanged.
  • Reading scene versions is about 6 times faster (four versions on a 1024-structure scene: 112 ms to 16.8 ms). The values are unchanged.

Removed

  • Material. It was an alias of the material class; use PhysicalMaterial.
  • Mesh.world_vertices_tensor(). Use the world_vertices property, which is now a tensor.
  • The compiled CUDA mesh-SDF module and its prebuilt binaries. Core now ships no native code and computes mesh distances in PyTorch. A solver package can install a faster backend.
  • The channel extra (witwin-channel-native).

Known issues

  • GeometryBase.with_material() raises ImportError. Use Structure(geometry, material).
  • to_mesh() of Cylinder, Cone, Pyramid, Prism and Torus with axis="x" or axis="y" returns inward-wound faces. Distances and masks are correct.
  • The maxwell, radar, genesis and all extras still name old solver ranges (witwin-maxwell<0.3, witwin-radar<0.4), and witwin-genesis is not on PyPI. Install solvers by their own package names.

Migrating from 0.3#

0.30.4
from witwin.core import Materialfrom witwin.core import PhysicalMaterial
mesh.vertices, mesh.faces (NumPy arrays)tensors; call .detach().cpu().numpy() if you need NumPy
mesh.world_vertices_tensor()mesh.world_vertices
mesh.bounds_world as ((xmin, xmax), (ymin, ymax), (zmin, zmax))a (2, 3) tensor [[xmin, ymin, zmin], [xmax, ymax, zmax]]
Tensors on mixed devices, moved implicitlyput every tensor on one device before you build the geometry
from witwin.core.material import Structurefrom witwin.core import Structure

Use reserve_*_id(value) (or pass explicit IDs to constructors) wherever IDs must match across processes. new_*_id() depends on construction order.

Compare 0.3.0 to 0.4.0

0.3.0 (2026-07-15)#

  • Platform wheels built against the CPython Stable ABI, carrying a prebuilt CUDA mesh signed-distance module, with wider CUDA architecture coverage.
  • Narrowed the shared geometry and material contracts: GeometrySpec, MaterialSpec, Material, Structure and the nine primitives plus Mesh.
  • Fixed the torus mesh parameterization.
  • Optional extras for Maxwell, Radar, Channel (witwin-channel-native) and Genesis.

Earlier releases#

0.0.1 (2026-03-22) and 0.0.2 were early packaging releases. Their API differs from the one on these pages.