magnelio.materials#

Material components — dispersion, roughness and surface-impedance fits. Material itself lives in the core magnelio namespace.

class magnelio.materials.DispersionModel(eps_inf, poles, f_band)#

Pole-residue permittivity model eps_inf + sum r_p/(j*omega - a_p).

Parameters:
  • eps_inf (float) – Relative permittivity in the high-frequency limit. This is the value the host Material must carry in epsilon — it drives the mass matrix and the CFL limit.

  • poles (tuple of (complex, complex)) – (a_p, r_p) pairs in rad/s. A pole with Im(a_p) != 0 represents a complex-conjugate pair stored once (poles with Im(a_p) < 0 are conjugated on input so the stored member has Im(a_p) > 0); a real pole must carry a real residue.

  • f_band (tuple of (float, float)) – Declared validity band (f_min, f_max) in Hz. Passivity (eps'' >= 0) is enforced on log-spaced samples across this band at construction.

Raises:

ValueError – If any pole is unstable (Re(a_p) > 0), marginally stable but oscillatory (Re(a_p) = 0 with Im(a_p) != 0), a real pole carries a complex residue, the DC pole (a_p = 0) has a non-positive residue, or eps''(omega) < 0 anywhere on the sampled band.

classmethod debye(eps_inf, delta_eps, tau, f_band=None)#

Multi-term Debye relaxation sum delta_eps_k / (1 + j*omega*tau_k).

Parameters:
  • eps_inf (float) – High-frequency relative permittivity.

  • delta_eps (float or sequence of float) – Relaxation strength per term (eps_s - eps_inf for one term).

  • tau (float or sequence of float) – Relaxation time per term [s]; same length as delta_eps.

  • f_band ((float, float), optional) – Validity band [Hz]. Default: two decades around the relaxation frequencies 1/(2 pi tau).

Return type:

DispersionModel

classmethod djordjevic_sarkar(eps_r, tan_delta, f_ref, f1=1000.0, f2=1000000000000.0)#

Causal wideband constant-loss-tangent substrate model.

The Djordjevic–Sarkar continuum (log-uniform Debye distribution between f1 and f2) is discretised at two poles per decade — enough that the comb ripple is negligible against the model’s inherent tan-delta slope (eps’’ is near-constant while eps’ falls logarithmically, so tan delta drifts ~5 % per 1.5 decades from f_ref at eps_r=4.3/tan_delta=0.02; that drift IS the causal Kramers–Kronig behaviour, not a discretisation artefact). eps_inf and the total relaxation strength are solved so the model reproduces exactly eps' = eps_r and eps''/eps' = tan_delta at f_ref. A truly constant tan delta over all frequencies violates Kramers–Kronig — this is the standard causal approximation every time-domain solver uses.

Parameters:
  • eps_r (float) – Real relative permittivity at f_ref.

  • tan_delta (float) – Loss tangent at f_ref (>= 0; 0 returns a pole-free model).

  • f_ref (float) – Reference frequency [Hz]; must lie inside (f1, f2).

  • f1 (float, optional) – Debye-distribution corner frequencies [Hz] — also the declared validity band. Defaults 1 kHz / 1 THz.

  • f2 (float, optional) – Debye-distribution corner frequencies [Hz] — also the declared validity band. Defaults 1 kHz / 1 THz.

Return type:

DispersionModel

classmethod drude(eps_inf, omega_p, gamma, f_band=None)#

Drude free-carrier model eps_inf - omega_p^2 / (omega^2 - j*omega*gamma).

Partial fractions give one real relaxation pole at -gamma and the real DC pole at 0 whose trapezoidal update is exactly the semi-implicit conductor with sigma = eps0 * omega_p^2 / gamma.

Parameters:
  • eps_inf (float) – High-frequency relative permittivity.

  • omega_p (float) – Plasma angular frequency [rad/s].

  • gamma (float) – Collision rate [rad/s] (must be > 0).

  • f_band ((float, float), optional) – Validity band [Hz]. Default: two decades around omega_p / (2 pi).

Return type:

DispersionModel

classmethod from_table(f, eps, n_poles=None, f_band=None, tol=0.001, max_poles=30)#

Fit a tabulated permittivity onto the pole-residue form.

In-repo Gustavsen/Semlyen vector fitting (magnelio.materials.vector_fit); the fit enforces pole stability, and the DispersionModel constructor acts as the mandatory passivity acceptance filter — a fit that violates it raises with the offending frequency, an active material is never silently shipped.

Parameters:
  • f (array_like) – Table frequencies [Hz], ascending, > 0 (>= 4 points).

  • eps (array_like or (array_like, array_like)) – Complex relative permittivity eps' - j*eps'' per table point, or a (eps_prime, tan_delta) pair of real arrays.

  • n_poles (int, optional) – Model order (conjugate partners counted individually). Default None: automatic — the order grows until the maximum relative fit error over the table beats tol and the result passes the passivity filter, capped at max_poles with a clear error. With an explicit order the fit is accepted at whatever error it reaches (noisy measured tables) — only passivity is enforced.

  • f_band ((float, float), optional) – Declared validity band [Hz]. Default: the table span.

  • tol (float, optional) – Automatic-order acceptance threshold on max |fit - table| / max |table| (default 1e-3).

  • max_poles (int, optional) – Automatic-order cap (default 30).

Raises:

ValueError – If the table itself is non-passive (eps'' < 0), the automatic order search hits max_poles without an acceptable passive fit, or the fitted model violates the passivity/stability rules.

Return type:

DispersionModel

classmethod lorentz(eps_inf, delta_eps, omega0, delta, f_band=None)#

Lorentz resonance delta_eps * omega0^2 / (omega0^2 + 2j*omega*delta - omega^2).

Parameters:
  • eps_inf (float) – High-frequency relative permittivity.

  • delta_eps (float) – Resonance strength (eps_s - eps_inf).

  • omega0 (float) – Resonance angular frequency [rad/s].

  • delta (float) – Damping rate [rad/s] (must be > 0 and != omega0; the critically damped double pole is not representable in the simple-pole form — perturb delta instead).

  • f_band ((float, float), optional) – Validity band [Hz]. Default: two decades around omega0 / (2 pi).

Return type:

DispersionModel

evaluate(omega)#

Complex relative permittivity at angular frequency omega [rad/s].

Conjugate pairs contribute both members; the result follows the engineering e^{+j omega t} convention (eps = eps' - j eps'' with eps'' >= 0 for a passive material).

Return type:

ndarray

class magnelio.materials.Hammerstad(rms_height)#

Hammerstad-Jensen roughness correction (the classical curve fit).

K(f) = 1 + (2/pi) * arctan(1.4 * (Rq/delta(f))^2)

Fitted to measured microstrip loss, and adequate for low to moderate roughness. Its ceiling is structural, not a fit artefact: the arctan saturates, so K -> 2 however rough the profile gets. Strongly roughened foils exceed that ceiling in reality — use Huray there.

Parameters:

rms_height (float) – RMS roughness Rq [m] of the profile. 0 is the smooth limit (K == 1 at every frequency).

factor(f, sigma, mu=1.0)#

Roughness correction factor K(f) >= 1.

Parameters:
  • f (float or array_like) – Frequency [Hz].

  • sigma (float) – Conductivity [S/m] of the metal (enters through the skin depth — the roughness scale only matters relative to it).

  • mu (float, optional) – Relative permeability of the metal (default 1).

Returns:

K at each frequency.

Return type:

numpy.ndarray

class magnelio.materials.Huray(radius, coverage, base_ratio=1.0)#

Huray “snowball” roughness correction (physics-based).

A tile of flat base area A_flat carries a cluster of conducting spheres of radius a. Superposing the analytic loss of a single sphere in a uniform tangential field over the cluster gives [Bracken 2012, eq. (5)]

K(f) = base_ratio + (3/2) * coverage

/ (1 + delta/a + delta^2/(2*a^2))

with coverage = N*4*pi*a^2 / A_flat the total sphere surface per unit tile area. The asymptotes are the model’s physical content: at low frequency delta >> a the field does not resolve the spheres and K -> base_ratio; at high frequency delta << a every sphere contributes its full surface and K -> base_ratio + 1.5*coverage. Unlike Hammerstad that ceiling follows the actual profile instead of saturating at 2.

Parameters:
  • radius (float) – Sphere (“snowball”) radius a [m]. Must be > 0.

  • coverage (float) – Total sphere surface area per unit flat tile area, N*4*pi*a^2/A_flat (dimensionless). 0 is the smooth limit.

  • base_ratio (float, optional) – Area of the matte base relative to a flat surface, A_matte/A_flat (default 1 — a flat base, the Cannonball assumption). It scales the base plate’s own loss.

Notes

Multiple sphere classes (radii a_i with coverages c_i) are additive in the original model; sum the factor contributions of one Huray per class and subtract the duplicated base_ratio terms, or use the single-class fit that the cannonball() parameter set provides.

classmethod cannonball(rz)#

Huray parameters from the datasheet Rz via the Cannonball stack.

Foil datasheets publish the 10-point mean roughness Rz, not the sphere radius and tile area the Huray model wants. The Cannonball model closes that gap with a fixed geometry: 14 equal spheres stacked 9 + 4 + 1 on a square tile of side 6a, the stack height identified with Rz, giving a = Rz/16.73 and coverage = 14*4*pi*a^2/(6a)^2 = 56*pi/36. The coverage is therefore a pure constant — Rz sets the radius alone.

Parameters:

rz (float) – 10-point mean roughness Rz [m] from the foil datasheet.

Return type:

Huray

factor(f, sigma, mu=1.0)#

Roughness correction factor K(f) >= 1.

Parameters:
  • f (float or array_like) – Frequency [Hz].

  • sigma (float) – Conductivity [S/m] of the metal (enters through the skin depth — the roughness scale only matters relative to it).

  • mu (float, optional) – Relative permeability of the metal (default 1).

Returns:

K at each frequency.

Return type:

numpy.ndarray

class magnelio.materials.SurfaceImpedanceFit(sigma, mu, roughness, f_lo, f_hi, c0, branches, rel_err_re, rel_err_cplx)#

Passive rational surface impedance c0 + sum c_p s/(s+b_p).

Frozen (joins Material equality and the store the way the roughness models do); built by fit_surface_impedance().

Parameters:
  • sigma (float) – Conductivity [S/m] of the fitted conductor.

  • mu (float) – Relative permeability.

  • roughness (SurfaceRoughness or None) – Roughness model whose causal completion this fit carries.

  • f_lo (float) – Working band [Hz]; accuracy statements hold on this band.

  • f_hi (float) – Working band [Hz]; accuracy statements hold on this band.

  • c0 (float) – Instantaneous (high-frequency) resistance term [Ohm].

  • branches (tuple of (float, float)) – (b_p [rad/s], c_p [Ohm]) ladder branches, all positive.

  • rel_err_re (float) – Achieved max relative deviation of Re Z from the target surface resistance over the band.

  • rel_err_cplx (float) – Achieved max relative deviation of the complex fit from the (causally completed) target over the band.

impedance(f)#

Evaluate the rational Z(j 2 pi f) [Ohm].

Return type:

ndarray

property r_instantaneous: float#

High-frequency limit Z(inf) = c0 + sum c_p [Ohm].

class magnelio.materials.SurfaceRoughness#

Frequency-dependent multiplier on a conductor’s surface resistance.

abstractmethod factor(f, sigma, mu=1.0)#

Roughness correction factor K(f) >= 1.

Parameters:
  • f (float or array_like) – Frequency [Hz].

  • sigma (float) – Conductivity [S/m] of the metal (enters through the skin depth — the roughness scale only matters relative to it).

  • mu (float, optional) – Relative permeability of the metal (default 1).

Returns:

K at each frequency.

Return type:

numpy.ndarray

magnelio.materials.fit_surface_impedance(sigma, mu=1.0, roughness=None, f_lo=100000000.0, f_hi=100000000000.0, tol=0.001, guard=10.0, max_branches=32)#

Fit a passive Foster ladder to a conductor’s surface impedance.

The branch count is chosen by an acceptance loop: the smallest ladder whose Re Z matches the target surface resistance within tol (max relative, on a denser check grid than the fit grid) is returned; failure to reach tol at max_branches raises.

Parameters:
  • sigma (float) – Conductivity [S/m].

  • mu (float, optional) – Relative permeability of the conductor.

  • roughness (SurfaceRoughness, optional) – Roughness model; its real factor K(f) is causally completed via kk_reactance() on the roughness excess.

  • f_lo (float, optional) – Working band [Hz].

  • f_hi (float, optional) – Working band [Hz].

  • tol (float, optional) – Acceptance bound on the band’s Re Z relative error.

  • guard (float, optional) – Pole-placement guard factor beyond the band (measured default; the top branches need room above the band to carry the sqrt growth).

  • max_branches (int, optional) – Acceptance-loop cap.

Return type:

SurfaceImpedanceFit

Raises:

ValueError – If tol is not reached at max_branches branches.

magnelio.materials.fit_wall_impedances(resolved, f_lo, f_hi, *, tol=0.001, guard=10.0, max_branches=32)#

Fit one surface impedance per wall tag, sharing identical fits.

Completes the wall-tag resolution: takes the conductor properties of mesh.surfaces.resolve_wall_conductors and returns tag -> SurfaceImpedanceFit over the caller band. Tags with identical (sigma, mu, roughness) — the common case of many walls in one metal — share ONE fit object (the roughness models are frozen/hashable, so the triple is a dict key), so the NNLS acceptance loop runs once per distinct conductor, not once per tag.

Parameters:
Returns:

tag -> SurfaceImpedanceFit.

Return type:

dict