Define materials
Model dielectrics, conductors, metals, dispersive and anisotropic media, thin sheets and nonlinear materials, and check what the solver compiled.
This guide shows how to describe the common material types and attach them to geometry. Every material is a Material (or a subclass) that you pair with a geometry in a Structure. All values are SI; permittivity and permeability are relative. The full list of classes and arguments is on the Materials API page.
Attach a material to geometry#
import witwin.maxwell as mw
glass = mw.Material(eps_r=2.25, name="glass")
scene.add_structure(
mw.Structure(
name="lens",
geometry=mw.Sphere(position=(0.0, 0.0, 0.0), radius=0.1),
material=glass,
)
)Where structures overlap, the one with the higher Structure(priority=...) wins; at equal priority (default 0) the one added later wins.
Warning
Use mw.Structure(geometry=..., material=...). The Geometry.with_material(...) shortcut from the base witwin package is broken in its published 0.4.0 build.
Lossless and lossy dielectrics#
substrate = mw.Material(eps_r=4.4, sigma_e=0.02, name="FR4-like") # sigma_e in S/m
ferrite_block = mw.Material(eps_r=12.0, mu_r=50.0, sigma_m=1e3) # sigma_m: magnetic conductivitysigma_e adds a frequency-flat conduction loss. To match a loss tangent tan_d at frequency f, use sigma_e = 2 * pi * f * EPSILON_0 * eps_r * tan_d (from witwin.maxwell.constants).
Metals#
At RF and microwave frequencies, treat good conductors as perfect electric conductors:
copper = mw.Material.pec(name="copper")A PEC material cannot carry any other property. For finite conductivity on a flat metal surface without meshing the skin depth, use LossyMetalMedium (a narrowband surface-impedance model, normal incidence, planar). At optical frequencies, use a Drude or Lorentz model.
Dispersive media#
Each pole adds a term to the susceptibility. The factories build a material with one pole; pass lists of poles to Material for more.
water_like = mw.Material.debye(eps_inf=4.9, delta_eps=74.1, tau=8.3e-12)
plasma = mw.Material.drude(eps_inf=1.0, plasma_frequency=2.0e9, gamma=1.0e8)
resonator = mw.Material.lorentz(eps_inf=2.0, delta_eps=1.5, resonance_frequency=3e9, gamma=2e8)
# Several poles in one material
metal = mw.Material(
eps_r=1.0,
drude_poles=(mw.DrudePole(plasma_frequency=2.0e15, gamma=1.0e13),),
lorentz_poles=(mw.LorentzPole(delta_eps=1.0, resonance_frequency=6.0e14, gamma=5.0e13),),
)Pole frequencies are in hertz and tau in seconds. For glasses quoted with Sellmeier coefficients, use Material.sellmeier; c_coefficients are in m² (multiply µm² tables by 1e-12):
bk7 = mw.Material.sellmeier(
b_coefficients=(1.03961212, 0.231792344, 1.01046945),
c_coefficients=(6.00069867e-15, 2.00179144e-14, 1.03560653e-10),
name="BK7",
)
print(bk7.relative_permittivity(1.94e14)) # complex eps_r at 1550 nmFast poles shorten the FDTD time step; result.stats()["time_step"]["limiting_factor"] reports "material_cfl" when a material sets it.
Anisotropic media#
uniaxial = mw.Material(epsilon_tensor=mw.DiagonalTensor3(2.0, 2.0, 3.5))
rotated = mw.Material(
epsilon_tensor=mw.Tensor3x3(((3.0, 0.5, 0.0), (0.5, 3.0, 0.0), (0.0, 0.0, 2.0)))
)Prefer DiagonalTensor3 when the axes line up with the grid; it is cheaper. A full Tensor3x3 must be symmetric positive-definite and works only in FDTD. mu_tensor and sigma_e_tensor accept DiagonalTensor3 only.
Thin conductive sheets and graphene#
A zero-thickness Box (one size component equal to 0) with a Medium2D material becomes a conductive sheet on one grid plane:
sheet = mw.Medium2D(sigma_s=2.5e-3) # sheet conductivity, S
graphene = mw.Graphene(chemical_potential=0.4, scattering_time=1e-13, temperature=300.0)
scene.add_structure(mw.Structure(name="sheet", geometry=mw.Box(position=(0, 0, 0), size=(1.0, 1.0, 0.0)), material=graphene))Nonlinear and time-modulated media#
kerr = mw.Material(eps_r=2.1, kerr_chi3=1e-20) # m²/V²
shg = mw.Material(eps_r=4.0, nonlinearity=mw.NonlinearSusceptibility(chi2=1e-12)) # m/V
modulated = mw.Material(eps_r=3.0, modulation=mw.ModulationSpec(frequency=1e9, amplitude=0.05))Nonlinear and modulated materials work in FDTD only and cannot be combined with tensors.
Optimize a material distribution#
For inverse design, a MaterialRegion interpolates between two permittivities inside a box from a density tensor you train. See Differentiability and the inverse design tutorial.
Check what the solver compiled#
Add a PermittivityMonitor, or read the compiled per-component tensors after a run:
result = sim.run()
eps = result.material("eps_r") # compiled relative permittivity on the grid
result.plot.material("eps_r", axis="z", position=0.0)The same scene-level checks apply before running: Material.relative_permittivity(f) evaluates the model at a frequency, and Material.capabilities() reports whether it is conductive, magnetic, anisotropic or dispersive.