Scene

Scene, Domain, GridSpec, BoundarySpec, and MaterialRegion API reference

Overview#

Scene is the central object in WiTwin Maxwell. It holds the simulation domain, grid resolution, boundary conditions, structures, sources, monitors, and optional differentiable material regions.

import witwin.maxwell as mw
 
scene = mw.Scene(
    domain=mw.Domain(bounds=((-0.5, 0.5), (-0.5, 0.5), (-0.5, 0.5))),
    grid=mw.GridSpec.uniform(0.05),
    boundary=mw.BoundarySpec.pml(num_layers=15, strength=1e6),
    device="cuda",
)

Scene#

Constructor#

ParameterTypeDefaultDescription
domainDomain | NoneNoneSimulation volume. Defaults to (-1, 1) on all axes
gridGridSpec | NoneNoneGrid resolution. Defaults to GridSpec.uniform(0.05)
boundaryBoundarySpec | NoneNoneBoundary conditions. Defaults to BoundarySpec.none()
structureslist | NoneNoneInitial list of Structure objects
sourceslist | NoneNoneInitial list of source objects
monitorslist | NoneNoneInitial list of monitor objects
material_regionslist | NoneNoneInitial list of MaterialRegion objects
devicestr"cuda"PyTorch device string
subpixel_samplesint1Subpixel averaging samples for material compilation
symmetrytuple | NoneNonePer-axis symmetry. Each entry is None, "PEC", or "PMC"
verboseboolFalseEnable verbose logging

Methods#

scene.add_structure(structure) — Add a Structure to the scene.

scene.add_source(source) — Add a source to the scene.

scene.add_monitor(monitor) — Add a monitor to the scene.

scene.add_port(port) — Add a ModePort to the scene.

scene.add_material_region(material_region) — Add a MaterialRegion for differentiable material optimization.

scene.clone(**overrides) — Return a copy of the scene with selected fields replaced.

scene.to_tidy3d(**kwargs) — Export the scene to a tidy3d.Simulation object.

Properties#

PropertyDescription
scene.dx, scene.dy, scene.dzGrid spacing along each axis
scene.grid_spacingGrid spacing as (dx, dy, dz)
scene.domain_sizeMaximum domain extent across all axes
scene.boundary_typeHuman-readable boundary type string
scene.pml_thicknessPML layer count
scene.pml_strengthPML strength
scene.bloch_wavevectorBloch wavevector (kx, ky, kz)
scene.has_symmetryTrue if any symmetry axis is set

Domain#

Defines the 3D simulation volume as axis-aligned bounds.

mw.Domain(bounds=((-0.5, 0.5), (-0.5, 0.5), (-0.5, 0.5)))
ParameterTypeDescription
bounds((xmin, xmax), (ymin, ymax), (zmin, zmax))Simulation volume bounds. Each axis must have end > start

Domain.from_domain_range(domain_range) — Construct from a flat 6-tuple (xmin, xmax, ymin, ymax, zmin, zmax).


GridSpec#

Defines the spatial resolution of the Yee grid.

# Uniform grid
mw.GridSpec.uniform(0.05)
 
# Anisotropic grid
mw.GridSpec.anisotropic(dx=0.05, dy=0.05, dz=0.02)
Class methodDescription
GridSpec.uniform(dl)Uniform spacing dl on all axes
GridSpec.anisotropic(dx, dy, dz)Independent spacing per axis
PropertyDescription
grid.spacingGrid spacing as (dx, dy, dz)
grid.is_uniformTrue if all spacings are equal

BoundarySpec#

Defines boundary conditions on all six faces of the domain.

Presets#

mw.BoundarySpec.pml(num_layers=15, strength=1e6)  # Perfectly matched layer
mw.BoundarySpec.none()                              # No boundary
mw.BoundarySpec.periodic()                          # Periodic on all axes
mw.BoundarySpec.bloch(wavevector=(kx, ky, kz))     # Bloch periodic
mw.BoundarySpec.pec()                               # Perfect electric conductor
mw.BoundarySpec.pmc()                               # Perfect magnetic conductor

Per-face control#

mw.BoundarySpec.faces(
    default="none",
    num_layers=15,
    strength=1e6,
    x="pml",               # Both x faces
    y=("pml", "periodic"), # Low y = pml, high y = periodic
    z_low="pec",           # Low z face only
)
ParameterTypeDescription
kindstrGlobal boundary kind: "none", "pml", "periodic", "bloch", "pec", "pmc"
num_layersintPML layer count. Required when using PML
strengthfloatPML absorption strength. Required when using PML
bloch_wavevectortuple[float, float, float]Bloch wavevector. Required when using Bloch boundaries

MaterialRegion#

A differentiable density-based material design region.

import torch
import witwin.maxwell as mw
 
density = torch.ones(32, 32, 32, device="cuda", requires_grad=True)
 
region = mw.MaterialRegion(
    name="design",
    geometry=mw.Box(position=(0.0, 0.0, 0.0), size=(0.5, 0.5, 0.5)),
    density=density,
    eps_bounds=(1.0, 12.0),
    filter_radius=2.0,
    projection_beta=10.0,
)
scene.add_material_region(region)
ParameterTypeDefaultDescription
namestrrequiredRegion name
geometryGeometryBaserequiredGeometry defining the design region
densitytorch.Tensorrequired3D density tensor of shape (Nx, Ny, Nz). Can have requires_grad=True
boundstuple[float, float](0.0, 1.0)Density value range
eps_boundstuple[float, float](1.0, 1.0)Permittivity interpolation range (eps_min, eps_max)
mu_boundstuple[float, float](1.0, 1.0)Permeability interpolation range
filter_radiusfloat | NoneNoneDensity filter radius. Must be > 0 when set
projection_betafloat | NoneNoneProjection sharpness. Must be > 0 when set

SceneModule#

Base class for wrapping a differentiable scene as a torch.nn.Module. Implement to_scene() to return a Scene:

class MyDesign(mw.SceneModule):
    def __init__(self):
        super().__init__()
        self.density = torch.nn.Parameter(torch.ones(32, 32, 32))
 
    def to_scene(self) -> mw.Scene:
        scene = mw.Scene(...)
        scene.add_material_region(
            mw.MaterialRegion(
                name="design",
                geometry=mw.Box(...),
                density=self.density,
                eps_bounds=(1.0, 12.0),
            )
        )
        return scene

Pass the SceneModule directly to Simulation.fdtd() — it calls to_scene() automatically before each forward pass.

Next Steps#