Materials

Reference for Material, dispersive poles, tensors, nonlinear and modulated media, 2D sheets, surface-impedance metals, ferrites and perturbations.

This page lists every material class in witwin.maxwell (import as import witwin.maxwell as mw). You need it when you assign a material to a Structure, add dispersion, anisotropy or nonlinearity, or model sheets, good conductors and ferrites. For a task-oriented walk-through, see Define materials.

A material never stands alone in a scene. You attach it to a geometry through mw.Structure(geometry, material) (see Geometry) and add the structure with Scene.add_structure (see Scene).

All quantities are SI unless a parameter says otherwise. Frequency-domain formulas use the exp(-i*omega*t) convention, so a lossy material has a positive imaginary permittivity.

import witwin.maxwell as mw
 
glass = mw.Material(eps_r=2.25, name="glass")
scene.add_structure(
    mw.Structure(mw.Box(position=(0.0, 0.0, 0.0), size=(0.4, 0.4, 0.4)), glass)
)

How materials compose#

Material is the single container. Poles, tensors, nonlinear terms, modulation, breakdown and mass density are arguments of the same constructor. The subclasses (GyromagneticFerrite, Medium2D, Graphene, LossyMetalMedium, SurfaceImpedanceMedium, PerturbationMedium) are also Material instances, so you attach them to a Structure the same way.

The constructor rejects combinations the solver cannot model:

CombinationResult
Nonlinearity (kerr_chi3 or nonlinearity) with any tensorNotImplementedError
modulation with any tensorNotImplementedError
modulation with sigma_e != 0NotImplementedError
pec=True with any pole, tensor, nonlinearity, modulation, or non-default eps_r, mu_r, sigma_e, sigma_mValueError
breakdown with PEC, tensors, poles, nonlinearity, modulation, or a Medium2DNotImplementedError
mu_tensor or sigma_e_tensor given as Tensor3x3NotImplementedError
orientation set to anything other than NoneNotImplementedError

Supported pairings inside one Material include poles with a DiagonalTensor3 or Tensor3x3 permittivity, poles with nonlinearity, and modulation with poles or nonlinearity.

Note

FDFD supports only a subset: isotropic or diagonal electric media, sigma_e, and electric dispersion evaluated at the solve frequency. It rejects magnetic response (mu_r != 1, mu_tensor, sigma_m), nonlinear media, Tensor3x3 permittivity and in-domain PEC. Use FDTD for the rest. See FDTD and FDFD.

Material#

class Material(
    eps_r=1.0, mu_r=1.0, sigma_e=0.0, name=None, *,
    sigma_m=0.0,
    debye_poles=(), drude_poles=(), lorentz_poles=(),
    mu_debye_poles=(), mu_drude_poles=(), mu_lorentz_poles=(),
    epsilon_tensor=None, mu_tensor=None, sigma_e_tensor=None,
    orientation=None, kerr_chi3=None, nonlinearity=None,
    modulation=None, pec=False, breakdown=None, mass_density=None,
)

An immutable (frozen dataclass) electromagnetic material. It extends the shared witwin.core PhysicalMaterial with Maxwell-specific constitutive terms.

eps_rfloatdefault 1.0

Relative permittivity. For a dispersive material this is the high-frequency background eps_inf. When epsilon_tensor is set, the tensor replaces it for the static sample.

mu_rfloatdefault 1.0

Relative permeability. When mu_tensor is set, the tensor replaces it.

sigma_efloatdefault 0.0

Static electric conductivity in S/m.

namestr | Nonedefault None

Optional label.

sigma_mfloatdefault 0.0

Static magnetic conductivity in ohm/m, the magnetic dual of sigma_e. Must be zero or greater. FDFD rejects a nonzero value.

debye_polesDebyePole | CustomDebyePole | Iterabledefault ()

Electric Debye poles. Pass one pole or an iterable of poles.

drude_polesDrudePole | CustomDrudePole | Iterabledefault ()

Electric Drude poles.

lorentz_polesLorentzPole | CustomLorentzPole | Iterabledefault ()

Electric Lorentz poles.

mu_debye_polesDebyePole | CustomDebyePole | Iterabledefault ()

Magnetic Debye poles. They add to mu_r the same way electric poles add to eps_r.

mu_drude_polesDrudePole | CustomDrudePole | Iterabledefault ()

Magnetic Drude poles.

mu_lorentz_polesLorentzPole | CustomLorentzPole | Iterabledefault ()

Magnetic Lorentz poles.

epsilon_tensorDiagonalTensor3 | Tensor3x3 | Nonedefault None

Anisotropic relative permittivity in the lab frame. A Tensor3x3 must be symmetric positive-definite, otherwise ValueError.

mu_tensorDiagonalTensor3 | Nonedefault None

Axis-aligned anisotropic relative permeability. A Tensor3x3 raises NotImplementedError.

sigma_e_tensorDiagonalTensor3 | Nonedefault None

Axis-aligned anisotropic electric conductivity in S/m. A Tensor3x3 raises NotImplementedError.

orientationNonedefault None

Reserved. Any value raises NotImplementedError; pass an already-rotated Tensor3x3 as epsilon_tensor instead.

kerr_chi3float | Nonedefault None

Instantaneous isotropic Kerr susceptibility in m^2/V^2. Equivalent to, and additive with, NonlinearSusceptibility(chi3=...).

nonlinearityNonlinearSusceptibility | TwoPhotonAbsorption | Iterable | Nonedefault None

Instantaneous nonlinear terms. Several descriptors sum.

modulationModulationSpec | Nonedefault None

Harmonic space-time permittivity modulation. Any other type raises TypeError.

pecbooldefault False

Marks the material as a perfect electric conductor. Prefer Material.pec().

breakdownDielectricBreakdown | Nonedefault None

Dynamic dielectric breakdown model. Any other type raises TypeError.

mass_densityfloat | torch.Tensor | Nonedefault None

Tissue mass density in kg/m^3 for SAR analysis. A scalar must be finite and greater than 0. A tensor must be a 3D grid that is finite and positive everywhere. None excludes the material from SAR; see SAR, power loss and breakdown.

Raises ValueError or NotImplementedError for the combinations in How materials compose, and ValueError for a negative sigma_m.

water = mw.Material.debye(eps_inf=4.9, delta_eps=74.1, tau=8.3e-12, name="water")
crystal = mw.Material(epsilon_tensor=mw.DiagonalTensor3(2.0, 3.0, 4.0))
tissue = mw.Material(eps_r=41.4, sigma_e=0.87, mass_density=1100.0, name="skin")
metal = mw.Material.pec()

Material properties#

All properties are read-only.

PropertyTypeMeaning
is_dispersiveboolAny electric or magnetic pole is present.
is_electric_dispersiveboolAny electric pole is present.
is_magnetic_dispersiveboolAny magnetic pole is present.
has_custom_electric_polesboolAn electric pole is a Custom*Pole.
has_custom_magnetic_polesboolA magnetic pole is a Custom*Pole.
has_custom_polesboolEither of the two above.
is_anisotropicboolAny of epsilon_tensor, mu_tensor, sigma_e_tensor is set.
has_full_epsilon_tensorboolepsilon_tensor is a Tensor3x3.
nonlinear_chi2floatSum of chi2 over nonlinearity, in m/V.
nonlinear_chi3floatkerr_chi3 plus the sum of chi3 over nonlinearity, in m^2/V^2.
tpa_sigma_scalefloatSum of two-photon-absorption coefficients, in S*m/V^2, using sqrt(eps_r) as the host index.
is_nonlinearboolAny of the three nonlinear totals is nonzero.
is_modulatedboolmodulation is set.
is_pecboolThe material is a PEC marker.
has_mass_densityboolmass_density is set.
is_electrically_lossyboolsigma_e, sigma_e_tensor, electric poles or nonlinearity is present.
is_gyromagneticboolFalse for Material; True for GyromagneticFerrite.

Material.pec#

Material.pec(name=None) -> Material

Classmethod. Returns a perfect-electric-conductor marker material, equivalent to Material(pec=True, name=name). Read the flag back with is_pec.

Material.debye#

Material.debye(*, eps_inf=1.0, delta_eps, tau, mu_r=1.0, sigma_e=0.0, name=None) -> Material

Classmethod. Returns a material with one DebyePole(delta_eps, tau) and eps_r=eps_inf.

Material.drude#

Material.drude(*, eps_inf=1.0, plasma_frequency, gamma, mu_r=1.0, sigma_e=0.0, name=None) -> Material

Classmethod. Returns a material with one DrudePole(plasma_frequency, gamma). Both frequencies are in Hz.

Material.lorentz#

Material.lorentz(
    *, eps_inf=1.0, delta_eps, resonance_frequency, gamma,
    mu_r=1.0, sigma_e=0.0, name=None, allow_gain=False,
) -> Material

Classmethod. Returns a material with one LorentzPole. Set allow_gain=True to accept a negative delta_eps (linear gain).

Material.sellmeier#

Material.sellmeier(*, b_coefficients, c_coefficients, eps_inf=1.0, mu_r=1.0, sigma_e=0.0, name=None) -> Material

Classmethod. Returns a lossless Sellmeier dielectric, n^2 = eps_inf + sum_i B_i * lambda^2 / (lambda^2 - C_i). Each (B_i, C_i) pair becomes a LorentzPole with delta_eps=B_i, resonance_frequency=c/sqrt(C_i) and gamma=0.0.

b_coefficientsIterable[float]required

Oscillator strengths B_i, dimensionless.

c_coefficientsIterable[float]required

Squared resonance wavelengths C_i in m^2. Each must be greater than 0. Tables quoted in micron^2 must be multiplied by 1e-12.

Raises ValueError if the two lists differ in length, are empty, or a C_i is not positive.

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",
)

Material.relative_permittivity#

Material.relative_permittivity(frequency) -> complex

Returns eps_r + i*sigma_e/(omega*eps0) plus the sum of electric pole susceptibilities at frequency (Hz).

Raises ValueError if frequency is not greater than 0. NotImplementedError for anisotropic or nonlinear materials, custom electric poles, and PerturbationMedium.

Material.relative_permeability#

Material.relative_permeability(frequency) -> complex

Returns mu_r plus the sum of magnetic pole susceptibilities at frequency (Hz). It does not include sigma_m.

Raises NotImplementedError for anisotropic or nonlinear materials, custom magnetic poles, and GyromagneticFerrite.

Material.evaluate_at_frequency#

Material.evaluate_at_frequency(frequency) -> FrequencyMaterialSample

Returns a witwin.core frequency sample with eps_r, mu_r and sigma_e. For an isotropic material, eps_r and mu_r are the complex values from the two methods above. For a material with tensors, the sample keeps the tensors; with poles, each axis of a DiagonalTensor3 is shifted by the real part of the pole susceptibility.

Raises NotImplementedError for nonlinear materials, for dispersive materials with a Tensor3x3 permittivity or custom poles, and for GyromagneticFerrite and PerturbationMedium. For those, evaluate the compiled scene model with Scene.compile_relative_materials.

Material.evaluate_static#

Material.evaluate_static() -> StaticMaterialSample

Returns a witwin.core static sample. Each of eps_r, mu_r, sigma_e is the matching tensor when set, otherwise the scalar.

Material.capabilities#

Material.capabilities() -> MaterialCapabilities

Returns the witwin.core capability flags conductive, magnetic, anisotropic and dispersive. On top of the base flags, conductive is also true when sigma_e_tensor is set, and magnetic when mu_tensor is set, a magnetic pole is present, or sigma_m != 0.

DebyePole#

class DebyePole(delta_eps, tau)

Debye relaxation term, chi(omega) = delta_eps / (1 - i*omega*tau). Frozen dataclass.

delta_epsfloatrequired

Relaxation strength, dimensionless. Must be zero or greater.

taufloatrequired

Relaxation time in seconds. Must be greater than 0.

DebyePole.susceptibility#

DebyePole.susceptibility(angular_frequency) -> complex
DebyePole.susceptibility_at_freq(frequency) -> complex

Returns chi at an angular frequency (rad/s) or at an ordinary frequency (Hz, must be greater than 0). All pole classes on this page provide both methods.

DrudePole#

class DrudePole(plasma_frequency, gamma)

Drude free-carrier term, chi(omega) = -omega_p^2 / (omega^2 + i*gamma_w*omega) with omega_p = 2*pi*plasma_frequency and gamma_w = 2*pi*gamma. Frozen dataclass.

plasma_frequencyfloatrequired

Plasma frequency in Hz. Must be greater than 0.

gammafloatrequired

Collision rate in Hz (ordinary frequency, not rad/s). Must be zero or greater.

plasma_angular_frequency and gamma_angular_frequency return the two values in rad/s. susceptibility(angular_frequency) raises ValueError at zero or negative frequency.

gold = mw.Material.drude(eps_inf=9.0, plasma_frequency=2.18e15, gamma=1.6e13, name="gold")

LorentzPole#

class LorentzPole(delta_eps, resonance_frequency, gamma, allow_gain=False)

Lorentz oscillator, chi(omega) = delta_eps * omega_0^2 / (omega_0^2 - omega^2 - i*gamma_w*omega) with omega_0 = 2*pi*resonance_frequency and gamma_w = 2*pi*gamma. Frozen dataclass.

delta_epsfloatrequired

Oscillator strength, dimensionless and finite. A negative value models linear gain and needs allow_gain=True.

resonance_frequencyfloatrequired

Resonance frequency in Hz. Must be greater than 0.

gammafloatrequired

Damping rate in Hz. Must be zero or greater.

allow_gainbooldefault False

Opt-in for a negative delta_eps.

Raises ValueError for a negative delta_eps without allow_gain=True. With gain enabled, construction emits a UserWarning because gain can make the FDTD run diverge.

resonance_angular_frequency and gamma_angular_frequency return the values in rad/s.

Experimental gain

Gain media carry no stability guarantee, and the FDTD adjoint does not cover them. Keep the single-pass gain small and check that the run stays finite.

CustomDebyePole#

class CustomDebyePole(delta_eps, tau)

Debye pole whose strength delta_eps varies per cell. Frozen dataclass.

delta_epstorch.Tensorrequired

3D grid of strengths. Must be finite, zero or greater everywhere, with at least one positive value.

taufloatrequired

Relaxation time in seconds, uniform in space. Must be greater than 0.

The grid spans the axis-aligned extent of the Box geometry of the structure that carries the material. Box faces select grid nodes lower-inclusive and upper-exclusive, and the grid is trilinearly resampled when its shape differs from the covered node count. The result multiplies the structure's soft occupancy. Only the strength varies per cell; rate parameters stay uniform.

MemberReturns
peak_delta_epsfloat, the largest grid value
reference_pole()DebyePole at the peak strength
amplitude()torch.Tensor, the grid divided by its peak, in [0, 1]
susceptibility(angular_frequency)torch.Tensor, per-cell complex chi
susceptibility_at_freq(frequency)torch.Tensor, per-cell complex chi
import torch
 
profile = torch.linspace(0.5, 3.0, 16).reshape(16, 1, 1).expand(16, 8, 8).contiguous()
graded = mw.Material(eps_r=2.0, debye_poles=mw.CustomDebyePole(delta_eps=profile, tau=1.0e-10))

CustomDrudePole#

class CustomDrudePole(plasma_frequency, gamma)

Drude pole whose plasma frequency varies per cell. Frozen dataclass with the same grid rules as CustomDebyePole.

plasma_frequencytorch.Tensorrequired

3D grid of plasma frequencies in Hz. Must be finite, zero or greater, with at least one positive value.

gammafloatrequired

Collision rate in Hz, uniform. Must be zero or greater.

Members: peak_plasma_frequency, reference_pole() (a DrudePole), amplitude() returning (f_p / f_p_peak)^2, susceptibility(angular_frequency) and susceptibility_at_freq(frequency).

CustomLorentzPole#

class CustomLorentzPole(delta_eps, resonance_frequency, gamma)

Lorentz pole whose strength varies per cell. Frozen dataclass with the same grid rules as CustomDebyePole. It has no allow_gain option: strengths must be zero or greater.

delta_epstorch.Tensorrequired

3D grid of strengths.

resonance_frequencyfloatrequired

Resonance frequency in Hz, uniform. Must be greater than 0.

gammafloatrequired

Damping rate in Hz, uniform. Must be zero or greater.

Members: peak_delta_eps, reference_pole() (a LorentzPole), amplitude(), susceptibility(angular_frequency) and susceptibility_at_freq(frequency).

Note

relative_permittivity(), relative_permeability() and evaluate_at_frequency() raise NotImplementedError for a material with custom poles. Use Scene.compile_relative_materials to inspect the compiled grid.

DiagonalTensor3#

class DiagonalTensor3(xx, yy, zz)

Axis-aligned diagonal tensor. Frozen dataclass; each value is converted to float. Use it for epsilon_tensor, mu_tensor and sigma_e_tensor.

as_tuple() returns (xx, yy, zz).

lossy_crystal = mw.Material(
    epsilon_tensor=mw.DiagonalTensor3(2.0, 3.0, 4.0),
    sigma_e_tensor=mw.DiagonalTensor3(0.5, 0.1, 0.0),
)

Tensor3x3#

class Tensor3x3(rows)

Full 3x3 tensor given as three rows of three numbers, stored in rows as a tuple of tuples. Only epsilon_tensor accepts it, and it must be symmetric positive-definite (symmetry tolerance 1e-6 relative to the largest entry).

Raises ValueError if rows is not 3x3.

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)))
)

Note

A Tensor3x3 permittivity is FDTD-only and runs forward-only when combined with poles or sigma_e.

NonlinearSusceptibility#

class NonlinearSusceptibility(chi2=0.0, chi3=0.0)

Instantaneous scalar nonlinear susceptibility. Pass it through Material(nonlinearity=...). Frozen dataclass.

chi2floatdefault 0.0

Second-order susceptibility in m/V. Adds P_i = eps0 * chi2 * E_i^2 per component.

chi3floatdefault 0.0

Third-order susceptibility in m^2/V^2. Adds P_i = eps0 * chi3 * |E|^2 * E_i, the same channel as kerr_chi3.

Raises ValueError if both are zero or either is not finite. Nonlinear media are FDTD-only.

shg = mw.Material(eps_r=4.0, nonlinearity=mw.NonlinearSusceptibility(chi2=1.0e-12))

TwoPhotonAbsorption#

class TwoPhotonAbsorption(beta, n0=None)

Intensity-dependent two-photon loss, dI/dz = -beta * I^2. Pass it through Material(nonlinearity=...). Frozen dataclass.

betafloatrequired

TPA coefficient in m/W. Must be greater than 0.

n0float | Nonedefault None

Linear refractive index used to convert field to intensity. None uses sqrt(eps_r) of the host material.

TwoPhotonAbsorption.sigma_scale#

TwoPhotonAbsorption.sigma_scale(base_index) -> float

Returns (4/3) * beta * (n * eps0 * c0)^2 in S*m/V^2, where n is n0 or base_index. The runtime multiplies this by |E|^2 to get the field-dependent conductivity.

ModulationSpec#

class ModulationSpec(frequency, amplitude, phase=0.0)

Harmonic space-time permittivity modulation, eps(x, t) = eps_static(x) * (1 + amplitude(x) * cos(2*pi*frequency*t + phase(x))). Pass it through Material(modulation=...). Frozen dataclass.

frequencyfloatrequired

Modulation frequency in Hz. Must be greater than 0.

amplitudefloat | torch.Tensorrequired

Modulation depth, dimensionless. A scalar must be in (0, 0.5). A 3D grid must be finite, in [0, 0.5), with at least one positive value; it maps over the structure's Box extent like custom poles.

phasefloat | torch.Tensordefault 0.0

Modulation phase in rad. A scalar or a finite 3D grid; a grid gives a traveling-wave profile.

angular_frequency returns 2*pi*frequency. Modulation is FDTD-only and acts on the electric permittivity only.

modulated = mw.Material(eps_r=4.0, modulation=mw.ModulationSpec(frequency=2e13, amplitude=0.3, phase=0.7))

DielectricBreakdown#

class DielectricBreakdown(
    critical_field, post_breakdown_conductivity, minimum_duration=0.0,
    model='field_duration', state='latching', recovery=None,
    damage_parameters=None, ramp_time=None, default_ramp_steps=10,
)

Deterministic latching breakdown. A cell switches to conducting once its cell-center |E| stays at or above critical_field for minimum_duration. Its conductivity then ramps linearly to post_breakdown_conductivity and stays there. Pass it through Material(breakdown=...). Frozen dataclass.

Experimental

This is an uncalibrated conductive-path model, not a validated arc or device-failure predictor. It needs a scalar, non-dispersive, linear, unmodulated, non-PEC bulk material.

critical_fieldfloatrequired

Trigger field in V/m. Must be greater than 0.

post_breakdown_conductivityfloatrequired

Conductivity after breakdown in S/m. Must be greater than 0.

minimum_durationfloatdefault 0.0

Time the field must stay above threshold, in seconds. Must be zero or greater.

modelstrdefault 'field_duration'

Trigger criterion. Only 'field_duration' is accepted; others raise NotImplementedError.

statestrdefault 'latching'

State machine. Only 'latching' is accepted.

recoveryNonedefault None

Reserved. Any value raises NotImplementedError.

damage_parametersNonedefault None

Reserved. Any value raises NotImplementedError.

ramp_timefloat | Nonedefault None

Conductivity ramp duration in seconds. None uses default_ramp_steps time steps.

default_ramp_stepsintdefault 10

Ramp length in time steps when ramp_time is None. Must be greater than 0.

See SAR, power loss and breakdown for the monitors and result data.

GyromagneticFerrite#

class GyromagneticFerrite(
    *, eps_r=1.0, saturation_magnetization, bias_field,
    gilbert_damping=0.0, gyromagnetic_ratio=1.760859e11,
    mu_infinity=1.0, sigma_e=0.0, name=None, cgs_conversion=(),
)

DC-biased ferrite with a non-reciprocal Polder permeability tensor, mu_r(omega) = mu*(I - b b^T) + mu_infinity*(b b^T) + i*kappa*[b]_x, where b is the bias unit vector. A linearized Landau-Lifshitz-Gilbert magnetization state carries the gyrotropy at runtime. Subclass of Material; mu_r is set to mu_infinity.

eps_rfloatdefault 1.0

Relative permittivity of the host. Must be greater than 0.

saturation_magnetizationfloatrequired

Ms in A/m. Must be greater than 0.

bias_fieldtuple[float, float, float]required

Static internal bias H0 in A/m. Must be a non-zero 3-vector. You supply the internal field; Maxwell does not solve for it.

gilbert_dampingfloatdefault 0.0

Dimensionless Gilbert damping alpha. Must be zero or greater.

gyromagnetic_ratiofloatdefault 1.760859e11

gamma in rad/(s*T). Must be greater than 0. The default is the electron value.

mu_infinityfloatdefault 1.0

High-frequency background permeability. Must be greater than 0.

sigma_efloatdefault 0.0

Electric conductivity in S/m.

namestr | Nonedefault None

Optional label.

cgs_conversiontupledefault ()

Record of a CGS-to-SI conversion. from_cgs fills it; you normally leave it empty.

PropertyMeaning
bias_magnitudeabs(H0) in A/m
bias_unit_vectorH0 / abs(H0)
omega_0Larmor frequency gamma*mu0*abs(H0) in rad/s
omega_mgamma*mu0*Ms in rad/s
resonance_frequencyomega_0 / (2*pi) in Hz
is_gyromagneticTrue

relative_permeability() and evaluate_at_frequency() raise NotImplementedError; use the tensor methods below.

yig = mw.GyromagneticFerrite(
    eps_r=15.0, saturation_magnetization=1.4e5, bias_field=(0.0, 0.0, 8.0e4), gilbert_damping=1e-3
)

GyromagneticFerrite.polder_tensor#

GyromagneticFerrite.polder_tensor(angular_frequency, *, dtype=torch.complex128) -> torch.Tensor

Returns the complex 3x3 lab-frame permeability at angular_frequency (rad/s). Differentiable in angular_frequency.

GyromagneticFerrite.permeability_tensor_at_freq#

GyromagneticFerrite.permeability_tensor_at_freq(frequency, *, dtype=torch.complex128) -> torch.Tensor

Same tensor at an ordinary frequency in Hz. Accepts a float (must be greater than 0) or a tensor.

GyromagneticFerrite.scalar_polder_components#

GyromagneticFerrite.scalar_polder_components(frequency) -> tuple[complex, complex]

Returns the scalar Polder components (mu, kappa) at frequency (Hz), valid for any bias direction.

GyromagneticFerrite.from_cgs#

GyromagneticFerrite.from_cgs(
    *, saturation_4piMs_gauss, bias_Oe, bias_direction=(0.0, 0.0, 1.0),
    eps_r=1.0, gilbert_damping=0.0, gyromagnetic_ratio=1.760859e11,
    mu_infinity=1.0, sigma_e=0.0, name=None,
) -> GyromagneticFerrite

Classmethod. Builds a ferrite from datasheet values: 4*pi*Ms in gauss and the internal bias in oersted. Both convert at 1000/(4*pi) A/m per unit. bias_direction is normalized. The conversion factors are stored in cgs_conversion.

ferrite = mw.GyromagneticFerrite.from_cgs(saturation_4piMs_gauss=1780.0, bias_Oe=1000.0, eps_r=15.0)

GyromagneticFerrite.from_resonance#

GyromagneticFerrite.from_resonance(
    *, resonance_frequency, saturation_magnetization, linewidth=0.0,
    bias_direction=(0.0, 0.0, 1.0), eps_r=1.0, gyromagnetic_ratio=1.760859e11,
    mu_infinity=1.0, sigma_e=0.0, name=None,
) -> GyromagneticFerrite

Classmethod. Back-computes the bias magnitude from 2*pi*resonance_frequency = gamma*mu0*abs(H0) and the damping from the full-width linewidth, alpha = linewidth / (2*resonance_frequency). Both frequencies are in Hz.

Medium2D#

class Medium2D(*, sigma_s=0.0, name=None)

Zero-thickness conductive sheet. Subclass of Material with vacuum bulk properties. The sheet carries J_s = sigma_s * E_t in the two tangential components and leaves the normal component untouched.

sigma_sfloatdefault 0.0

Sheet conductivity in S (siemens, a surface quantity). Must be zero or greater.

namestr | Nonedefault None

Optional label.

Attach it to a Structure whose geometry is an axis-aligned Box with exactly one zero-size axis. The compiler snaps the sheet to the nearest node plane and applies sigma_s / dcell on that one Yee layer, where dcell is the local dual-cell width. Sheets add to bulk conductivity and to each other.

MemberReturns
is_medium2dTrue
sheet_conductivity(angular_frequency)complex sheet conductivity in S
sheet_conductivity_at_freq(frequency)same, at a frequency in Hz
sheet_pole_terms()(weight, rate) Drude-like terms; each adds weight / (rate - i*omega). Empty for Medium2D.
sheet_lorentz_terms()(strength, omega_0, gamma) resonant terms. Empty for Medium2D.
sheet = mw.Medium2D(sigma_s=2.5e-3, name="sheet")
scene.add_structure(mw.Structure(mw.Box(position=(0.0, 0.0, 0.0), size=(1.0, 1.0, 0.0)), sheet))

Note

Medium2D sheets are rejected by the FDTD and FDFD adjoint bridges.

Graphene#

class Graphene(*, chemical_potential, scattering_time, temperature=300.0, include_interband=False, name=None)

Graphene sheet with the Kubo surface conductivity. Subclass of Medium2D; the same geometry rules apply. The intraband term is sigma_intra(omega) = A / (1/scattering_time - i*omega).

chemical_potentialfloatrequired

Chemical potential mu_c in eV. Must be zero or greater.

scattering_timefloatrequired

Intraband relaxation time in seconds. Must be greater than 0.

temperaturefloatdefault 300.0

Temperature in K. Must be greater than 0.

include_interbandbooldefault False

Adds the interband Kubo term, fitted at construction to four Lorentz sheet terms below the absorption edge hbar*omega = 2*mu_c.

namestr | Nonedefault None

Optional label.

Raises ValueError for out-of-range inputs, or when include_interband=True and the fit exceeds 3 % band error (for example when mu_c is not large compared to kB*T).

PropertyMeaning
intraband_drude_weightDrude weight A in S/s
scattering_rate1 / scattering_time in 1/s
characteristic_frequencyFastest material rate in Hz, used by the FDTD automatic time step
graphene = mw.Graphene(chemical_potential=0.2, scattering_time=1.0e-13, temperature=300.0)

LossyMetalMedium#

class LossyMetalMedium(*, conductivity, name=None)

Good conductor modeled by a Leontovich surface-impedance boundary instead of a meshed skin depth. Subclass of Material. The runtime masks the metal interior and updates the tangential electric field on exposed faces from the vacuum-side magnetic field, using the surface impedance at the operating frequency.

conductivityfloatrequired

Bulk conductivity in S/m. Must be greater than 0.

namestr | Nonedefault None

Optional label.

MemberReturns
is_lossy_metalTrue
skin_depth(frequency)sqrt(2 / (omega*mu0*sigma)) in m
surface_impedance(angular_frequency)(1 - i) * sqrt(omega*mu0 / (2*sigma)) in ohm; raises ValueError if omega is not greater than 0
surface_impedance_at_freq(frequency)same, at a frequency in Hz

Differentiable and distributed runs through the surface are not supported. Resolve such metals with Material(sigma_e=...) or use Material.pec().

ground = mw.Structure(
    mw.Box(position=(0.0, 0.0, -0.9), size=(2.0, 2.0, 0.2)),
    mw.LossyMetalMedium(conductivity=5.8e7),
)

SurfaceImpedanceModel#

class SurfaceImpedanceModel

Abstract base for a causal, passive surface impedance E_t = Z_s(omega) (n x H_t). SurfaceImpedanceMedium accepts any subclass.

MemberMeaning
frequency_rangeAbstract property, (f_min, f_max) in Hz
port_countAbstract property, 1 for a scalar response, 2 for a tangential 2x2 response
surface_impedance(frequencies)Abstract method, Z_s in ohm with shape [F] or [F, P, P]
is_surface_impedanceClass attribute, True

RationalSurfaceImpedance#

class RationalSurfaceImpedance(
    poles, residues, direct=0.0, *, frequency_range,
    representation=None, fit_report=None, sample_frequencies=None,
    passivity_tolerance=1.0e-9, certificate_samples=64,
)

Passive rational surface model built on RationalModel (see Networks and rational fitting). The rational function is evaluated with s = -i*2*pi*f.

polestorch.Tensor | RationalModelrequired

Pole array with shape [order], in rad/s. All poles need a negative real part. You may pass a ready RationalModel instead; then residues and direct are ignored.

residuestorch.Tensor | Nonerequired

Residues with shape [Nout, Nin, order], or [order] for a scalar model.

directfloat | complex | torch.Tensordefault 0.0

Constant term, scalar or [Nout, Nin].

frequency_rangetuple[float, float]required

Validity band (f_min, f_max) in Hz with 0 < f_min < f_max. Passivity is certified only inside this band.

representationstr | Nonedefault None

'Y' if the model is the admittance Y_s, 'Z' if it is the impedance Z_s. None means 'Y' for raw poles, or the model's own value for a RationalModel. A value that contradicts a passed model raises ValueError.

fit_reportFitReport | Nonedefault None

Optional fitter report, exposed as fit_report.

sample_frequenciestorch.Tensor | Nonedefault None

Optional sample frequencies kept for inspection.

passivity_tolerancefloatdefault 1.0e-9

Allowed passivity violation. Must be zero or greater.

certificate_samplesintdefault 64

Number of log-spaced frequencies used for the passivity check. At least 2.

Raises ValueError if the model is unstable, not certified passive in the band, not square, or larger than 2x2.

MemberReturns
modelthe RationalModel
representation'Y' or 'Z'
frequency_range, port_count, fit_report, passivity, sample_frequenciesstored values
evaluate(frequencies)the represented transfer (Y_s or Z_s), shape [F, P, P]
surface_impedance(frequencies)Z_s in ohm, shape [F] or [F, P, P]
admittance(frequencies)Y_s in S, shape [F] or [F, P, P]

Out-of-band evaluation extrapolates the model and has no passivity guarantee.

import math, torch
 
f0 = 2.0e9
omega0 = 2.0 * math.pi * f0
r = math.sqrt(omega0 * 4e-7 * math.pi / (2.0 * 50.0))
model = mw.RationalSurfaceImpedance(
    poles=torch.tensor([-omega0], dtype=torch.complex128),
    residues=torch.tensor([[[omega0 / r]]], dtype=torch.complex128),
    frequency_range=(1.0e8, 1.0e10),
    representation="Y",
)

RationalSurfaceImpedance.fit#

RationalSurfaceImpedance.fit(
    frequencies, values, *, order, band=None, representation='Y',
    iterations=20, relative_tolerance=1.0e-3, relative_weighting=True,
    enforce_passivity=False, passivity_tolerance=1.0e-9, config=None,
) -> RationalSurfaceImpedance

Classmethod. Fits a rational model to samples with the shared vector fitter (fit_rational).

frequenciesarray-likerequired

Sample frequencies in Hz, shape [F], finite and greater than 0.

valuesarray-likerequired

Samples of Y_s or Z_s (matching representation), with leading dimension F.

orderintrequired

Number of poles.

bandtuple[float, float] | Nonedefault None

Validity band in Hz. None uses the sample range.

representationstrdefault 'Y'

'Y' fits the admittance, 'Z' fits the impedance.

iterationsintdefault 20

Fitter iterations.

relative_tolerancefloatdefault 1.0e-3

Fitter convergence tolerance.

relative_weightingbooldefault True

Weights each sample by the inverse of its magnitude.

enforce_passivitybooldefault False

Asks the fitter to enforce passivity.

passivity_tolerancefloatdefault 1.0e-9

Tolerance for the fitter and the passivity certificate.

configRationalFitConfig | Nonedefault None

Full fitter configuration. When given, it replaces order, band, iterations, relative_tolerance, relative_weighting and enforce_passivity in the fit itself.

Raises ValueError for empty, non-finite or non-positive frequencies, mismatched values, or a result that is not certified passive.

SurfaceImpedanceMedium#

class SurfaceImpedanceMedium(*, impedance, name=None)

Material that declares the exposed faces of its structure as a surface-impedance boundary described by impedance. Bulk properties are vacuum. Subclass of Material.

impedanceSurfaceImpedanceModelrequired

The surface model. Any other type raises TypeError.

namestr | Nonedefault None

Optional label.

is_surface_impedance returns True. frequency_range returns impedance.frequency_range. At runtime the model is refit as a passive Z-form rational and stepped per edge on each exposed axis-aligned face. A tangential 2x2 model and differentiable or distributed runs are rejected.

coating = mw.SurfaceImpedanceMedium(impedance=model, name="coating")

PerturbationMedium#

class PerturbationMedium(base, *, perturbation, eps_sensitivity=1.0, name=None)

A base material whose permittivity is shifted by an external field, eps(x) = eps_base + eps_sensitivity * perturbation(x). Subclass of Material.

baseMaterialrequired

Material to perturb. Its eps_r, mu_r, sigma_e, poles, tensors, kerr_chi3, nonlinearity and modulation are copied.

perturbationtorch.Tensorrequired

Finite 3D grid, for example a temperature map. It maps over the structure's Box extent like custom poles. A tensor with requires_grad=True becomes a trainable input for the gradient bridges.

eps_sensitivityfloatdefault 1.0

Permittivity change per unit of perturbation.

namestr | Nonedefault None

Label. None keeps the base name.

Raises TypeError if base is not a material or perturbation is not a tensor. ValueError for a PEC base, a grid that is not 3D or not finite, or a shifted permittivity that would reach zero or below. NotImplementedError for a GyromagneticFerrite base or a Tensor3x3 base permittivity.

relative_permittivity() and evaluate_at_frequency() raise NotImplementedError because the result varies in space.

import torch
 
heat = torch.zeros(16, 16, 4, requires_grad=True)
tuned = mw.PerturbationMedium(mw.Material(eps_r=2.0), perturbation=heat, eps_sensitivity=2.0)

See also#