Skip to content

AnalyticWaveguideModel

AnalyticWaveguideModel(
*,
n_eff: complex
| collections.abc.Sequence[complex]
| photonforge.Interpolator,
length: Annotated[float, units='μm'] | None = None,
propagation_loss: Annotated[float, minimum=0, units='dB/μm']
| collections.abc.Sequence[
Annotated[float, minimum=0, units='dB/μm']
] = 0.0,
extra_loss: Annotated[float, minimum=0, units='dB']
| collections.abc.Sequence[
Annotated[float, minimum=0, units='dB']
] = 0.0,
n_group: float
| collections.abc.Sequence[float]
| photonforge.Interpolator
| None = None,
dispersion: Annotated[float, units='s/μm²']
| collections.abc.Sequence[Annotated[float, units='s/μm²']] = 0.0,
dispersion_slope: Annotated[float, units='s/μm³']
| collections.abc.Sequence[Annotated[float, units='s/μm³']] = 0.0,
reference_frequency: Annotated[float, minimum=0, units='Hz']
| None = None,
dn_dT: Annotated[
complex | collections.abc.Sequence[complex], units='1/K'
] = 0.0,
dL_dT: Annotated[
float | collections.abc.Sequence[float], units='dB/μm/K'
] = 0.0,
temperature: Annotated[float, minimum=0, units='K'] = 293.0,
reference_temperature: Annotated[float, minimum=0, units='K'] = 293.0,
voltage: Annotated[float, units='V'] = 0.0,
v_piL: Annotated[float, units='V·μm'] | None = None,
k2: Annotated[float, units='rad/μm/V²'] = 0.0,
k3: Annotated[float, units='rad/μm/V³'] = 0.0,
dloss_dv: Annotated[float, units='dB/μm/V'] = 0.0,
dloss_dv2: Annotated[float, units='dB/μm/V²'] = 0.0,
absorption: photonforge.Interpolator | None = None,
confinement_factor: Annotated[float, maximum=1, minimum=0] = 1.0,
chirp: float = 0.0,
) -> None

Analytic model for waveguides, bends, and EO modulators.

This model for 2-port components includes dispersion and temperature sensitivity for single- and multi-mode waveguides. For each mode, the transmission between ports at frequency ff is:

S12=S21=10−L20e12ln⁡Tαej(βℓ+ϕeo+ϕα)L=L0+ℓ(Lp+dLpdVV+d2LpdV2V2)β=β0+β1Δω+β22Δω2+β36Δω3β0=ω0c0neffβ1=ngroupc0β2=−λ0ω0Dβ3=(λ0ω0)2(S+2λ0D)ϕeo=πVℓVπL+k2V2ℓ+k3V3ℓln⁡Tα=−Γα(λ,V)ℓϕα=−αc2ln⁡Tα\begin{aligned} S_{12} &= S_{21} = 10^{-\frac{L}{20}} e^{\frac{1}{2}\ln T_\alpha} e^{j (\beta \ell + \phi_{eo} + \phi_\alpha)} \\ L &= L_0 + \ell \left(L_p + \frac{{\rm d}L_p}{{\rm d}V} V + \frac{{\rm d}^2L_p}{{\rm d}V^2} V^2 \right) \\ \beta &= \beta_0 + \beta_1 \Delta\omega + \frac{\beta_2}{2} \Delta\omega^2 + \frac{\beta_3}{6} \Delta\omega^3 \\ \beta_0 &= \frac{\omega_0}{c_0} n_\text{eff} \\ \beta_1 &= \frac{n_\text{group}}{c_0} \\ \beta_2 &= -\frac{\lambda_0}{\omega_0} D \\ \beta_3 &= \left(\frac{\lambda_0}{\omega_0}\right)^2 \left(S + \frac{2}{\lambda_0} D\right) \\ \phi_{eo} &= \frac{\pi V \ell}{V_{\pi L}} + k_2 V^2 \ell + k_3 V^3 \ell \\ \ln T_\alpha &= -\Gamma \alpha(\lambda, V) \ell \\ \phi_\alpha = -\frac{\alpha_c}{2} \ln T_\alpha \end{aligned}

in which λ0=c0f0−1\lambda_0 = c_0 f_0^{-1}, ω0=2πf0\omega_0 = 2 \pi f_0, Δω=2π(f−f0)\Delta\omega = 2 \pi (f - f_0), and the temperature dependence is taken into account through:

neff(T)=neff(T0)+dneffdT(T−T0)Lp(T)=Lp(T0)+dLpdT(T−T0)\begin{aligned} n_\text{eff}(T) &= n_\text{eff}(T_0) + \frac{{\rm d}n_\text{eff}}{{\rm d}T} (T - T_0) \\ L_p(T) &= L_p(T_0) + \frac{{\rm d}L_p}{{\rm d}T} (T - T_0) \end{aligned}

Without an absorption table, Tα=1T_\alpha = 1. With one, the bias- and wavelength-dependent electro-absorption multiplies the transmission, and the chirp parameter αc\alpha_c ties a phase to it. It coexists with the polynomial loss terms, which default to 0, so the user chooses either loss description (or, knowingly, both).

Args

  • n_eff: Effective refractive index (loss can be included here by using complex values).
  • length: Length ℓ\ell of the waveguide. If not provided, the length is measured by route_length or ports distance.
  • propagation_loss: Propagation loss LpL_p.
  • extra_loss: Length-independent loss L0L_0. This can be used, for example, to model bending losses.
  • n_group: Group index. If None, the value of n_eff is used.
  • dispersion: Chromatic dispersion coefficient DD.
  • dispersion_slope: Chromatic dispersion slope SS.
  • reference_frequency: Reference frequency f0f_0 for dispersion coefficients. If None, the central frequency is used.
  • dn_dT: Temperature sensitivity for n_eff.
  • dL_dT: Temperature sensitivity for propagation_loss.
  • temperature: Operating temperature TT.
  • reference_temperature: Reference temperature T0T_0.
  • voltage: Operating voltage VV.
  • v_piL: Electro-optic phase coefficient VπLV_{\pi L}.
  • k2: Quadratic nonlinear phase coefficient.
  • k3: Cubic nonlinear phase coefficient.
  • dloss_dv: Linear voltage-dependent propagation loss coefficient.
  • dloss_dv2: Quadratic voltage-dependent propagation loss coefficient.
  • absorption: Material absorption in 1/μm, as an Interpolator over voltage and wavelength, for electro-absorption sections.
  • confinement_factor: Fraction of the optical mode overlapping the absorbing region, between 0 and 1. Applies to absorption only.
  • chirp: Chirp parameter αc\alpha_c as quoted on modulator datasheets. Applies to absorption only.

Important

chirp takes the value quoted on a datasheet unchanged. In the time domain it gives the frequency deviation δν=(αc/4π) dln⁡P/dt\delta\nu = (\alpha_c/4\pi)\,{\rm d}\ln P/{\rm d}t, so a positive value blue-shifts the rising optical edge, the same sign convention as linewidth_enhancement_factor in the laser and semiconductor amplifier models. In this model, with the e−jωte^{-j\omega t} time convention, it appears as the phase ϕα\phi_\alpha, which grows with the absorption for αc>0\alpha_c > 0.

Note

Absorption queries outside the sampled range are clamped to it. An Interpolator of two variables cannot carry extrapolation="constant", and extrapolating an absorption edge gives nonsense.

See Also

franz_keldysh_absorption can be used to generate absorption from tabulated measured data.

MethodDescription
autograd_smatrixCompute an autograd-compatible S matrix for traced parameters.
black_box_componentCreate a black-box component using this model.
estimate_costEstimate the cost for S matrix computation.
nonlinearWaveguide model with a nonlinear time stepper, from physical parameters.
s_matrixCompute the S matrix for a component using this model.
setup_time_stepperObtain a time stepper for a component using this model.
startStart computing the S matrix response from a component.
transformApply a transformation to this model.
updateUpdate this model.

autograd_smatrix(
self,
*,
component,
traced_params,
frequencies,
component_for_params,
param_names,
show_progress=True,
model_kwargs=None,
)

Compute an autograd-compatible S matrix for traced parameters.

Important

This is an abstract method that must be implemented by derived classes that support autograd-based S-matrix computation.

Args

  • component (Component): Nominal component associated with this autograd evaluation.
  • traced_params (ndarray): Traced parameter vector used by autograd.
  • frequencies (Sequence[float]): Frequency values at which to calculate the scattering parameters (in Hz).
  • component_for_params (Callable[[ndarray], Component]): Callback that returns the component for a given traced parameter vector.
  • param_names (Sequence[str]): Flattened traced parameter names aligned with traced_params.
  • show_progress (bool): Progress display hint from Component.s_matrix.
  • model_kwargs (dict[str, Any] | None): Model-specific keyword arguments forwarded from Component.s_matrix.

Returns

AutogradSMatrix: Autograd-compatible S matrix.

black_box_component(
self,
port_spec: str | photonforge.PortSpec | None = None,
technology: photonforge.Technology | None = None,
name: str | None = None,
) -> photonforge.Component

Create a black-box component using this model.

The layout is the model’s schematic symbol in a box, sized by the port width, with the port profiles drawn as stubs. The box spans the model’s length when it is set.

Args

  • port_spec: Port specification used in the component. If None, look for "port_spec" in config.default_kwargs.
  • technology: Component technology. If None, the default technology is used.
  • name: Component name. If None a default is used.

Returns

Component with ports and model.

estimate_cost(self, *args, **kwargs)

Estimate the cost for S matrix computation.

All arguments are passed to the model’s start method with the addition of the keyword argument cost_estimation=True.

Returns

float: Cost estimation.

nonlinear(
*,
reference_frequency: Annotated[float, minimum=0, units='Hz'],
port_spec: str | photonforge.PortSpec | None = None,
technology: photonforge.Technology | None = None,
n_eff: complex | None = None,
n_group: float | None = None,
dispersion: Annotated[float, units='s/μm²'] | None = None,
dispersion_slope: Annotated[float, units='s/μm³'] = 0.0,
effective_area: Annotated[float, exclusiveMinimum=0, units='m²']
| None = None,
length: Annotated[float, units='μm'] | None = None,
propagation_loss: Annotated[float, minimum=0, units='dB/μm'] = 0.0,
extra_loss: Annotated[float, minimum=0, units='dB'] = 0.0,
kerr_index: Annotated[float, units='m²/W'] | None = None,
tpa_coefficient: Annotated[float, minimum=0, units='m/W'] | None = None,
fca_cross_section: Annotated[float, minimum=0, units='m²']
| None = None,
fcd_coefficients: tuple[float, float] | None = None,
fcd_exponents: tuple[float, float] | None = None,
carrier_lifetime: Annotated[float, minimum=0, units='s'] | None = None,
peak_power: Annotated[float, minimum=0, units='W'] | None = None,
sections: Annotated[int, exclusiveMinimum=0] | None = None,
max_phase: Annotated[float, exclusiveMinimum=0, units='rad'] = 0.15,
mesh_refinement: Annotated[float, exclusiveMinimum=0] | None = None,
verbose: bool = True,
) -> 'AnalyticWaveguideModel'

Waveguide model with a nonlinear time stepper, from physical parameters.

The returned model carries an AnalyticWaveguideTimeStepper whose perturbations describe the Kerr effect, two-photon absorption (TPA) and the free carriers TPA generates, with the carrier density NN relaxing with the carrier lifetime:

ΔnK=n2PA+iλ4πβPAτcdNdt+N=τcβ2hν(PA)2Δnfc=ceNee+chNeh+iλ4πσN\begin{aligned} &\Delta n_\text{K} = \frac{n_2 P}{A} + i\frac{\lambda}{4\pi}\frac{\beta P}{A} \\ &\tau_c\frac{{\rm d}N}{{\rm d}t} + N = \frac{\tau_c\beta}{2h\nu}\left(\frac{P}{A}\right)^2 \\ &\Delta n_\text{fc} = c_e N^{e_e} + c_h N^{e_h} + i\frac{\lambda}{4\pi}\sigma N \end{aligned}

With port_spec, a mode solve at reference_frequency supplies every cross-section parameter not given explicitly: n_eff, n_group, dispersion and the nonlinear effective areas. The areas use the vectorial, power-normalised definition,

n2A=∫n2n2(2∣E∣4+∣E⋅E∣2)/3 dSZ02(∫Re(E×H∗)⋅z^ dS)2,\frac{n_2}{A} = \frac{\int n^2 n_2 \left(2|E|^4 + |E\cdot E|^2\right)/3\,{\rm d}S} {Z_0^2 \left(\int {\rm Re}(E\times H^*)\cdot\hat{z}\, {\rm d}S\right)^2},

and the same for β/A\beta/A, integrated over the nonlinear materials only. Coefficients not given explicitly are read from the nonlinear_spec of those materials (Tidy3D KerrNonlinearity and TwoPhotonAbsorption). If no material has one, the explicit coefficients apply to the highest-index material. The free-carrier terms use the TPA effective area.

The model length is left to the component unless length is set, so the model can be added to a routed waveguide or turned into a black box.

Args

  • reference_frequency: Frequency at which the cross-section and nonlinear parameters apply.
  • port_spec: Port specification (or its name in the technology) of the waveguide cross-section, for the mode solve.
  • technology: Technology used for the mode solve. If None, the default technology is used.
  • n_eff: Effective index. Required without port_spec.
  • n_group: Group index. Required without port_spec.
  • dispersion: Chromatic dispersion DD. Without port_spec, zero if not given.
  • dispersion_slope: Chromatic dispersion slope SS.
  • effective_area: Nonlinear effective area used for every effect, instead of the ones computed from the mode.
  • length: Waveguide length. If None, it is measured from the component.
  • propagation_loss: Linear propagation loss.
  • extra_loss: Length-independent loss.
  • kerr_index: Kerr coefficient n2n_2.
  • tpa_coefficient: Two-photon absorption coefficient β\beta.
  • fca_cross_section: Free-carrier absorption cross-section σ\sigma, for electrons and holes together.
  • fcd_coefficients: Free-carrier dispersion coefficients (ce,ch)(c_e, c_h), in m^(3 e_e) and m^(3 e_h).
  • fcd_exponents: Free-carrier dispersion exponents (ee,eh)(e_e, e_h). If None, 1 for both.
  • carrier_lifetime: Free-carrier lifetime τc\tau_c. Zero disables the free carriers.
  • peak_power: Highest optical power expected at the input, used to choose the number of sections.
  • sections: Number of sections. If None, chosen from peak_power and max_phase.
  • max_phase: Largest nonlinear phase per section when the number of sections is chosen automatically.
  • mesh_refinement: Minimal number of mesh elements per wavelength used for the mode solve.
  • verbose: Flag controlling mode solver verbosity.

Returns

Waveguide model with its nonlinear time stepper attached. Its properties list the values used: n_eff, n_group, dispersion, kerr_index, tpa_coefficient, and the effective areas kerr_effective_area and tpa_effective_area in m².

Note

The mode solve runs once per call, on the Tidy3D mode solver.

s_matrix(self, component, frequencies, show_progress=True, model_kwargs={})

Compute the S matrix for a component using this model.

Args

  • component (Component): Component to perform the calculation.
  • frequencies (Sequence[float]): Frequency values at which to calculate the scattering parameters (in Hz).
  • show_progress (bool): If True, show computation progress.
  • model_kwargs (dict[str, object]): Keyword arguments passed to Model.start. Accepted arguments depend on the model type.

Returns

SMatrix: Computed S matrix.

Example

Compute only the responses from mode 0 of P0 with Tidy3D to reduce the number and cost of simulations:

>>> model = pf.Tidy3DModel()
>>> s_matrix = model.s_matrix( # doctest: +SKIP
... component,
... frequencies,
... model_kwargs={"inputs": ("P0@0",)},
... )

A port name such as ("P0",) selects all modes of that port. All outputs for the selected inputs are returned; responses from unselected inputs are not computed. Use Model.estimate_cost with the same inputs passed directly to estimate the reduced run.

setup_time_stepper(
self,
component,
time_step,
carrier_frequency=0,
show_progress=True,
time_stepper_kwargs={},
)

Obtain a time stepper for a component using this model.

Args

  • component (Component): Component for the time stepper.
  • time_step (float): The interval between time steps (in seconds).
  • carrier_frequency (float): The carrier frequency used to construct the time stepper. The carrier should be omitted from the input signals, as it is handled automatically by the time stepper.
  • show_progress (bool): If True, show computation progress.
  • time_stepper_kwargs (dict[str, object]): Keyword arguments passed to TimeStepper.setup. Each time stepper type can accept a different set of arguments. Check the documentation for the each time stepper’s setup_state method for more information.

Returns

TimeStepper: Initialized time stepper.

start(
self,
component: photonforge.Component,
frequencies: collections.abc.Sequence[
typing.Annotated[float, minimum=0, units='Hz']
],
temperature: Annotated[float, minimum=0, units='K'] | None = None,
voltage: Annotated[float, units='V'] | None = None,
**kwargs: object,
) -> photonforge.SMatrix

Start computing the S matrix response from a component.

Args

  • component: Component from which to compute the S matrix.
  • frequencies: Sequence of frequencies at which to perform the computation.
  • temperature: Operating temperature override.
  • voltage: Operating voltage override.
  • **kwargs: Unused.

Returns

Result object with attributes status and s_matrix.

transform(
self, translation=(0, 0), rotation=0, scaling=1, x_reflection=False
)

Apply a transformation to this model.

The base implementation is a no-op and returns self. Derived classes can override this method to transform model-specific geometry settings.

Args

  • translation (Sequence[float] | complex): Translation vector.
  • rotation (float): Rotation angle in degrees.
  • scaling (float): Magnification factor.
  • x_reflection (bool): Mirror across the horizontal axis.

Returns

Model: This object with transformations applied.

update(self, *args, **kwargs)

Update this model.

All contents of the model are updated with the contents from the updated version. object contents or modifications introduced after the model creation (outside of the original parametric function) are not propagated.

The model’s time stepper does not participate in the update, unless the __init__ method of the derived model class replaces it via set_time_stepper.

Args

  • *args (object): Positional arguments to the parametric model.
  • **kwargs (object): Keyword arguments to the parametric model.

Returns

Model: This model.

Note

The original keyword arguments used to generate the model are stored and updated with the passed kwargs. This updated version is used in the function call and will be stored for future updates. Positional arguments are not stored.

AttributeDescription
parametric_functionstr: Function used to update the model.
parametric_kwargsdict[str, object]: Keyword arguments used to update the model.
propertiesProperties: Object properties.
random_variableslist[RandomVariable]: Random variables associated to the model’s parameters.
time_stepperTimeStepper | None: Time stepper associated with this model.

str: Function used to update the model.

dict[str, object]: Keyword arguments used to update the model.

Properties: Object properties.

list[RandomVariable]: Random variables associated to the model’s parameters.

TimeStepper | None: Time stepper associated with this model.