Skip to content

AnalyticMZIModel

AnalyticMZIModel(
*,
n_eff1: complex
| collections.abc.Sequence[complex]
| collections.abc.Sequence[collections.abc.Sequence[complex]]
| photonforge.Interpolator,
n_eff2: complex
| collections.abc.Sequence[complex]
| collections.abc.Sequence[collections.abc.Sequence[complex]]
| photonforge.Interpolator
| None = None,
length1: Annotated[float, units='μm'],
length2: Annotated[float, units='μm'] | None = None,
tau1: complex
| collections.abc.Sequence[complex]
| collections.abc.Sequence[collections.abc.Sequence[complex]]
| photonforge.Interpolator
| None = None,
tau2: complex
| collections.abc.Sequence[complex]
| collections.abc.Sequence[collections.abc.Sequence[complex]]
| photonforge.Interpolator
| None = None,
kappa1: complex
| collections.abc.Sequence[complex]
| collections.abc.Sequence[collections.abc.Sequence[complex]]
| photonforge.Interpolator = (-0 - 0.7071067811865476j),
kappa2: complex
| collections.abc.Sequence[complex]
| collections.abc.Sequence[collections.abc.Sequence[complex]]
| photonforge.Interpolator = (-0 - 0.7071067811865476j),
propagation_loss1: Annotated[float, minimum=0, units='dB/μm']
| collections.abc.Sequence[
Annotated[float, minimum=0, units='dB/μm']
] = 0.0,
propagation_loss2: Annotated[float, minimum=0, units='dB/μm']
| collections.abc.Sequence[
Annotated[float, minimum=0, units='dB/μm']
] = 0.0,
extra_loss1: Annotated[float, minimum=0, units='dB']
| collections.abc.Sequence[
Annotated[float, minimum=0, units='dB']
] = 0.0,
extra_loss2: Annotated[float, minimum=0, units='dB']
| collections.abc.Sequence[
Annotated[float, minimum=0, units='dB']
] = 0.0,
n_group1: float
| collections.abc.Sequence[float]
| photonforge.Interpolator
| None = None,
n_group2: float
| collections.abc.Sequence[float]
| photonforge.Interpolator
| None = None,
dispersion1: Annotated[float, units='s/μm²']
| collections.abc.Sequence[Annotated[float, units='s/μm²']] = 0.0,
dispersion2: Annotated[float, units='s/μm²']
| collections.abc.Sequence[Annotated[float, units='s/μm²']] = 0.0,
dispersion_slope1: Annotated[float, units='s/μm³']
| collections.abc.Sequence[Annotated[float, units='s/μm³']] = 0.0,
dispersion_slope2: 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,
dn1_dT: Annotated[
complex | collections.abc.Sequence[complex], units='1/K'
] = 0.0,
dn2_dT: Annotated[
complex | collections.abc.Sequence[complex], units='1/K'
] = 0.0,
dL1_dT: Annotated[
float | collections.abc.Sequence[float], units='dB/μm/K'
] = 0.0,
dL2_dT: Annotated[
float | collections.abc.Sequence[float], units='dB/μm/K'
] = 0.0,
temperature1: Annotated[float, minimum=0, units='K'] = 293.0,
temperature2: Annotated[float, minimum=0, units='K'] = 293.0,
reference_temperature: Annotated[float, minimum=0, units='K'] = 293.0,
voltage1: Annotated[float, units='V'] = 0.0,
voltage2: Annotated[float, units='V'] = 0.0,
v_piL1: Annotated[float, units='V·μm'] | None = None,
v_piL2: Annotated[float, units='V·μm'] | None = None,
k21: Annotated[float, units='rad/μm/V²'] = 0,
k22: Annotated[float, units='rad/μm/V²'] = 0,
k31: Annotated[float, units='rad/μm/V³'] = 0,
k32: Annotated[float, units='rad/μm/V³'] = 0,
dloss_dv_1: Annotated[float, units='dB/μm/V'] = 0,
dloss_dv_2: Annotated[float, units='dB/μm/V'] = 0,
dloss_dv2_1: Annotated[float, units='dB/μm/V²'] = 0,
dloss_dv2_2: Annotated[float, units='dB/μm/V²'] = 0,
ports: collections.abc.Sequence[str] | None = None,
) -> None

Analytic model for a 4-port Mach-Zehnder interferometer.

The S matrix for the MZI for each mode is given by:

S31=τ1t1τ2+κ1t2κ2S41=τ1t1κ2+κ1t2τ2S32=κ1t1τ2+τ1t2κ2S42=κ1t1κ2+τ1t2τ2\begin{aligned} S_{31} &= \tau_1 t_1 \tau_2 + \kappa_1 t_2 \kappa_2 \\ S_{41} &= \tau_1 t_1 \kappa_2 + \kappa_1 t_2 \tau_2 \\ S_{32} &= \kappa_1 t_1 \tau_2 + \tau_1 t_2 \kappa_2 \\ S_{42} &= \kappa_1 t_1 \kappa_2 + \tau_1 t_2 \tau_2 \end{aligned}

with remaining coefficients zero and transmissions t1t_1 and t2t_2 calculated through an AnalyticWaveguideModel.

Args

  • n_eff1: Effective refractive index for the first arm (loss can be included here by using complex values).
  • n_eff2: Effective refractive index for the second arm. If None, defaults to n_eff1.
  • length1: Length of the first arm.
  • length2: Length of the second arm. If None, defaults to length1.
  • tau1: Transmission coefficient for the first coupler. If None, it is calculated based on kappa1.
  • tau2: Transmission coefficient for the second coupler. If None, it is calculated based on kappa2.
  • kappa1: Coupling coefficient for the first coupler.
  • kappa2: Coupling coefficient for the second coupler.
  • propagation_loss1: Propagation loss for the first arm.
  • propagation_loss2: Propagation loss for the second arm.
  • extra_loss1: Length-independent loss for the first arm.
  • extra_loss2: Length-independent loss for the second arm.
  • n_group1: Group index for the first arm. If None, defaults to n_eff1.
  • n_group2: Group index for the second arm. If None, defaults to n_group1, n_eff2, or n_eff1 (first with valid value).
  • dispersion1: Chromatic dispersion coefficient for the first arm.
  • dispersion2: Chromatic dispersion coefficient for the second arm.
  • dispersion_slope1: Chromatic dispersion slope for the first arm.
  • dispersion_slope2: Chromatic dispersion slope for the second arm.
  • reference_frequency: Reference frequency for the dispersion coefficients. If None, the central frequency is used.
  • dn1_dT: Temperature sensitivity for n_eff1.
  • dn2_dT: Temperature sensitivity for n_eff2.
  • dL1_dT: Temperature sensitivity for propagation_loss1.
  • dL2_dT: Temperature sensitivity for propagation_loss2.
  • temperature1: Operating temperature for the first arm.
  • temperature2: Operating temperature for the second arm.
  • reference_temperature: Reference temperature.
  • voltage1: Operating voltage for the first arm.
  • voltage2: Operating voltage for the second arm.
  • v_piL1: Electro-optic phase coefficient for the first arm.
  • v_piL2: Electro-optic phase coefficient for the second arm.
  • k21: Quadratic nonlinear phase coefficient for the first arm.
  • k22: Quadratic nonlinear phase coefficient for the second arm.
  • k31: Cubic nonlinear phase coefficient for the first arm.
  • k32: Cubic nonlinear phase coefficient for the second arm.
  • dloss_dv_1: Linear voltage-dependent propagation loss coefficient for the first arm.
  • dloss_dv_2: Linear voltage-dependent propagation loss coefficient for the second arm.
  • dloss_dv2_1: Quadratic voltage-dependent propagation loss coefficient for the first arm.
  • dloss_dv2_2: Quadratic voltage-dependent propagation loss coefficient for the second arm.
  • ports: List of port names. If not set, the sorted list of port names from the component is used.

Note

For multimode ports, mixed-mode coefficients are 0. Parameters can be specified per mode by using sequences of values. Dispersion for tau1, tau2, kappa1, and kappa2 can also be manually included by setting the coefficients to an Interpolator (with multiple values for multimode ports), or a 2D array with shape (M, N), in which M is the number of modes, and N the length of the frequency sequence used in the S matrix computation.

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

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.

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']
],
temperature1: Annotated[float, minimum=0, units='K'] | None = None,
temperature2: Annotated[float, minimum=0, units='K'] | None = None,
voltage1: Annotated[float, units='V'] | None = None,
voltage2: 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.
  • temperature1: Operating temperature override for first arm.
  • temperature2: Operating temperature override for second arm.
  • voltage1: Operating voltage override for first arm.
  • voltage2: Operating voltage override for second arm.
  • **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.