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:
| Combination | Result |
|---|---|
Nonlinearity (kerr_chi3 or nonlinearity) with any tensor | NotImplementedError |
modulation with any tensor | NotImplementedError |
modulation with sigma_e != 0 | NotImplementedError |
pec=True with any pole, tensor, nonlinearity, modulation, or non-default eps_r, mu_r, sigma_e, sigma_m | ValueError |
breakdown with PEC, tensors, poles, nonlinearity, modulation, or a Medium2D | NotImplementedError |
mu_tensor or sigma_e_tensor given as Tensor3x3 | NotImplementedError |
orientation set to anything other than None | NotImplementedError |
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.
1.0Relative 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.
1.0Relative permeability. When mu_tensor is set, the tensor replaces it.
0.0Static electric conductivity in S/m.
NoneOptional label.
0.0Static magnetic conductivity in ohm/m, the magnetic dual of sigma_e. Must be zero or greater. FDFD rejects a nonzero value.
()Electric Debye poles. Pass one pole or an iterable of poles.
()Electric Drude poles.
()Electric Lorentz poles.
()Magnetic Debye poles. They add to mu_r the same way electric poles add to eps_r.
()Magnetic Drude poles.
()Magnetic Lorentz poles.
NoneAnisotropic relative permittivity in the lab frame. A Tensor3x3 must be symmetric positive-definite, otherwise ValueError.
NoneAxis-aligned anisotropic relative permeability. A Tensor3x3 raises NotImplementedError.
NoneAxis-aligned anisotropic electric conductivity in S/m. A Tensor3x3 raises NotImplementedError.
NoneReserved. Any value raises NotImplementedError; pass an already-rotated Tensor3x3 as epsilon_tensor instead.
NoneInstantaneous isotropic Kerr susceptibility in m^2/V^2. Equivalent to, and additive with, NonlinearSusceptibility(chi3=...).
NoneInstantaneous nonlinear terms. Several descriptors sum.
NoneHarmonic space-time permittivity modulation. Any other type raises TypeError.
FalseMarks the material as a perfect electric conductor. Prefer Material.pec().
NoneDynamic dielectric breakdown model. Any other type raises TypeError.
NoneTissue 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.
| Property | Type | Meaning |
|---|---|---|
is_dispersive | bool | Any electric or magnetic pole is present. |
is_electric_dispersive | bool | Any electric pole is present. |
is_magnetic_dispersive | bool | Any magnetic pole is present. |
has_custom_electric_poles | bool | An electric pole is a Custom*Pole. |
has_custom_magnetic_poles | bool | A magnetic pole is a Custom*Pole. |
has_custom_poles | bool | Either of the two above. |
is_anisotropic | bool | Any of epsilon_tensor, mu_tensor, sigma_e_tensor is set. |
has_full_epsilon_tensor | bool | epsilon_tensor is a Tensor3x3. |
nonlinear_chi2 | float | Sum of chi2 over nonlinearity, in m/V. |
nonlinear_chi3 | float | kerr_chi3 plus the sum of chi3 over nonlinearity, in m^2/V^2. |
tpa_sigma_scale | float | Sum of two-photon-absorption coefficients, in S*m/V^2, using sqrt(eps_r) as the host index. |
is_nonlinear | bool | Any of the three nonlinear totals is nonzero. |
is_modulated | bool | modulation is set. |
is_pec | bool | The material is a PEC marker. |
has_mass_density | bool | mass_density is set. |
is_electrically_lossy | bool | sigma_e, sigma_e_tensor, electric poles or nonlinearity is present. |
is_gyromagnetic | bool | False for Material; True for GyromagneticFerrite. |
Material.pec#
Material.pec(name=None) -> MaterialClassmethod. 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) -> MaterialClassmethod. 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) -> MaterialClassmethod. 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,
) -> MaterialClassmethod. 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) -> MaterialClassmethod. 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.
Oscillator strengths B_i, dimensionless.
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) -> complexReturns 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) -> complexReturns 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) -> FrequencyMaterialSampleReturns 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() -> StaticMaterialSampleReturns 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() -> MaterialCapabilitiesReturns 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.
Relaxation strength, dimensionless. Must be zero or greater.
Relaxation time in seconds. Must be greater than 0.
DebyePole.susceptibility#
DebyePole.susceptibility(angular_frequency) -> complex
DebyePole.susceptibility_at_freq(frequency) -> complexReturns 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 frequency in Hz. Must be greater than 0.
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.
Oscillator strength, dimensionless and finite. A negative value models linear gain and needs allow_gain=True.
Resonance frequency in Hz. Must be greater than 0.
Damping rate in Hz. Must be zero or greater.
FalseOpt-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.
3D grid of strengths. Must be finite, zero or greater everywhere, with at least one positive value.
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.
| Member | Returns |
|---|---|
peak_delta_eps | float, 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.
3D grid of plasma frequencies in Hz. Must be finite, zero or greater, with at least one positive value.
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.
3D grid of strengths.
Resonance frequency in Hz, uniform. Must be greater than 0.
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.
0.0Second-order susceptibility in m/V. Adds P_i = eps0 * chi2 * E_i^2 per component.
0.0Third-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.
TPA coefficient in m/W. Must be greater than 0.
NoneLinear 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) -> floatReturns (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.
Modulation frequency in Hz. Must be greater than 0.
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.
0.0Modulation 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.
Trigger field in V/m. Must be greater than 0.
Conductivity after breakdown in S/m. Must be greater than 0.
0.0Time the field must stay above threshold, in seconds. Must be zero or greater.
'field_duration'Trigger criterion. Only 'field_duration' is accepted; others raise NotImplementedError.
'latching'State machine. Only 'latching' is accepted.
NoneReserved. Any value raises NotImplementedError.
NoneReserved. Any value raises NotImplementedError.
NoneConductivity ramp duration in seconds. None uses default_ramp_steps time steps.
10Ramp 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.
1.0Relative permittivity of the host. Must be greater than 0.
Ms in A/m. Must be greater than 0.
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.
0.0Dimensionless Gilbert damping alpha. Must be zero or greater.
1.760859e11gamma in rad/(s*T). Must be greater than 0. The default is the electron value.
1.0High-frequency background permeability. Must be greater than 0.
0.0Electric conductivity in S/m.
NoneOptional label.
()Record of a CGS-to-SI conversion. from_cgs fills it; you normally leave it empty.
| Property | Meaning |
|---|---|
bias_magnitude | abs(H0) in A/m |
bias_unit_vector | H0 / abs(H0) |
omega_0 | Larmor frequency gamma*mu0*abs(H0) in rad/s |
omega_m | gamma*mu0*Ms in rad/s |
resonance_frequency | omega_0 / (2*pi) in Hz |
is_gyromagnetic | True |
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.TensorReturns 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.TensorSame 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,
) -> GyromagneticFerriteClassmethod. 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,
) -> GyromagneticFerriteClassmethod. 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.
0.0Sheet conductivity in S (siemens, a surface quantity). Must be zero or greater.
NoneOptional 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.
| Member | Returns |
|---|---|
is_medium2d | True |
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 potential mu_c in eV. Must be zero or greater.
Intraband relaxation time in seconds. Must be greater than 0.
300.0Temperature in K. Must be greater than 0.
FalseAdds the interband Kubo term, fitted at construction to four Lorentz sheet terms below the absorption edge hbar*omega = 2*mu_c.
NoneOptional 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).
| Property | Meaning |
|---|---|
intraband_drude_weight | Drude weight A in S/s |
scattering_rate | 1 / scattering_time in 1/s |
characteristic_frequency | Fastest 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.
Bulk conductivity in S/m. Must be greater than 0.
NoneOptional label.
| Member | Returns |
|---|---|
is_lossy_metal | True |
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 SurfaceImpedanceModelAbstract base for a causal, passive surface impedance E_t = Z_s(omega) (n x H_t). SurfaceImpedanceMedium accepts any subclass.
| Member | Meaning |
|---|---|
frequency_range | Abstract property, (f_min, f_max) in Hz |
port_count | Abstract 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_impedance | Class 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.
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.
Residues with shape [Nout, Nin, order], or [order] for a scalar model.
0.0Constant term, scalar or [Nout, Nin].
Validity band (f_min, f_max) in Hz with 0 < f_min < f_max. Passivity is certified only inside this band.
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.
NoneOptional fitter report, exposed as fit_report.
NoneOptional sample frequencies kept for inspection.
1.0e-9Allowed passivity violation. Must be zero or greater.
64Number 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.
| Member | Returns |
|---|---|
model | the RationalModel |
representation | 'Y' or 'Z' |
frequency_range, port_count, fit_report, passivity, sample_frequencies | stored 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,
) -> RationalSurfaceImpedanceClassmethod. Fits a rational model to samples with the shared vector fitter (fit_rational).
Sample frequencies in Hz, shape [F], finite and greater than 0.
Samples of Y_s or Z_s (matching representation), with leading dimension F.
Number of poles.
NoneValidity band in Hz. None uses the sample range.
'Y''Y' fits the admittance, 'Z' fits the impedance.
20Fitter iterations.
1.0e-3Fitter convergence tolerance.
TrueWeights each sample by the inverse of its magnitude.
FalseAsks the fitter to enforce passivity.
1.0e-9Tolerance for the fitter and the passivity certificate.
NoneFull 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.
The surface model. Any other type raises TypeError.
NoneOptional 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.
Material to perturb. Its eps_r, mu_r, sigma_e, poles, tensors, kerr_chi3, nonlinearity and modulation are copied.
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.
1.0Permittivity change per unit of perturbation.
NoneLabel. 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)