WG3

class ipkiss3.cml.WG3

Single mode polynomial waveguide model.

Uses a polynomial expression of the effective index and loss (in dB/m) as function of wavelength and temperature offset .

Parameters:
n_eff: List[List[float]]

Polynomial coefficients of the mode effective index as function of wavelength and temperature offset. First row contains the highest order wavelength-dependent terms, while the last row contains wavelength-independent terms. Similarly, the first column contains the highest order temperature-dependent terms, while the last column contains temperature-independent terms.

loss: List[float]

Polynomial coefficients [dB/um / (um)^n] of the loss of the waveguide mode as function of wavelength offset from center_wavelength. Highest order first (loss at center_wavelength last).

center_wavelength: float (um)

Center wavelength (in micrometer) of the model around which n_eff and loss are defined.

center_temperature: float (au)

Center temperature (in arbitrary units) of the model around which n_eff is defined.

length: float (um)

Total length of the waveguide in micrometer.

Notes

The effective index is calculated as:

\[n_{eff}(\lambda, T) = \sum_{i=0}^{M} \sum_{j=0}^{N} n_{eff}[i, j] (\lambda - \lambda_c)^{M-i} (T - T_c)^{N-j}\]

Where M and N represent the order of the polynomial in terms of wavelength and temperature, respectively. \(\lambda_c\) is the central wavelength and \(T_c\) is the central temperature.

Similarly, the loss is defined as

\[loss(\lambda) = \sum_{i=0}^{P} loss[i](\lambda-\lambda_c)^{P-i}\]

Note

All wavelengths, including those in the polynomial expansions, are represented in micrometers.

Frequency domain

The scatter matrix is given by:

\[\begin{split}\mathbf{S}_{wg}=\begin{bmatrix} 0 & \exp(-j\frac{2 \pi}{\lambda}L n_{eff}(\lambda, T)) * A \\ \exp(-j\frac{2 \pi}{\lambda}L n_{eff}(\lambda, T)) * A & 0 \end{bmatrix}\end{split}\]

Where the amplitude loss is calculated as:

\[A = 10^{-loss * L / 20.0}\]

Time domain

The electric field at the output is

\[E_{out}(\lambda, T) = \exp(j\phi_0) E_{in}(t - Ln_g(\lambda, T)/c) * A\]

where the group index is derived from the effective index by

\[n_g(\lambda, T) = n_{eff}(\lambda, T) - \lambda \frac{d}{d\lambda} n_{eff}(\lambda, T)\]

Terms

Term Name

Type

#modes

in

Optical

1

out

Optical

1

Examples

import ipkiss3.all as i3
import matplotlib.pyplot as plt
import numpy as np

class CustomWaveguide(i3.Waveguide):
    class CircuitModel(i3.CircuitModelView):
        def _generate_model(self):
            # Model effective index assuming there is a linear dependence on both wavelength and temperature
            # neff = n0 + wl_coeff * dwl + thermal_coeff * dT
            n0 = 2.57
            wl_coeff = -0.85  # First order wavelength dependence
            thermal_coeff = 1.86 * 10**-4  # First order temperature dependence (thermo-optic coefficient)
            return i3.cml.WG3(
                n_eff=[
                    [0, wl_coeff],
                    [thermal_coeff, n0],
                ],
                loss=[-10.0 * 1e-6, 3.0 * 1e-6],
                center_wavelength=1.55,
                center_temperature=273,
                length=1e6,
            )

wavelengths = np.linspace(1.549, 1.551, 50)
temperatures = [273, 274, 275, 276]
cm = CustomWaveguide().CircuitModel()
s_matrices = [cm.get_smatrix(wavelengths, temp, debug=True) for temp in temperatures]

plt.subplot(211)
plt.xlabel("wavelength [um]")
plt.ylabel("transmission [dB]")
plt.title("Transmitted power")
for S, temp in zip(s_matrices, temperatures):
    transmission = 10 * np.log10(np.abs(S["out", "in"]) ** 2)
    plt.plot(wavelengths, transmission, label=f"T={temp}")

plt.subplot(212)
plt.xlabel("wavelength [um]")
plt.ylabel("phase [rad]")
plt.title("Accumulated phase")
for S, temp in zip(s_matrices, temperatures):
    phase = np.unwrap(np.angle(S["out", "in"]))
    plt.plot(wavelengths, phase, label=f"T={temp}")
plt.tight_layout()
plt.legend()
plt.show()
../../../_images/ipkiss3-cml-WG3-1.png
import ipkiss3.all as i3
import numpy as np
import matplotlib.pyplot as plt

class CustomWaveguide(i3.Waveguide):
    class CircuitModel(i3.CircuitModelView):
        def _generate_model(self):
            n0 = 2.57
            wl_coeff = -0.85
            thermal_coeff = 1.86 * 10**-4  # thermo-optic coefficient
            return i3.cml.WG3(
                n_eff=[
                    [0, wl_coeff],
                    [thermal_coeff, n0],
                ],
                loss=[-10.0 * 1e-6, 5.0 * 1e-6],
                center_wavelength=1.55,
                center_temperature=273,
                length=0.25 * 1e6,
            )

def optical_pulse(optical_power=1.0, t_offset=1e-11, pulse_width=1e-9):
    """Create an optical pulse"""

    def f_pulse(t):
        sigma = pulse_width / (2.0 * np.sqrt(2.0 * np.log(2.0)))
        return np.sqrt(optical_power * np.exp(-(((t - t_offset) / (np.sqrt(2.0) * sigma)) ** 2)))

    return f_pulse

opt_pulse_source = i3.FunctionExcitation(
    port_domain=i3.OpticalDomain,
    excitation_function=optical_pulse(optical_power=1.0, t_offset=1e-10, pulse_width=5e-11),
)

testbench = i3.ConnectComponents(
    child_cells={
        "opt_in": opt_pulse_source,
        "wg": CustomWaveguide(),
        "opt_out": i3.Probe(port_domain=i3.OpticalDomain),
    },
    links=[
        ("opt_in:out", "wg:in"),
        ("wg:out", "opt_out:in"),
    ],
)

# Simulation
sim_result = testbench.CircuitModel().get_time_response(
    t0=0.0, t1=3e-9, dt=0.5e-12, center_wavelength=1.50, temperature=270, debug=True
)
time_data = sim_result.timesteps
input_power = np.abs(sim_result["opt_in"]) ** 2
output_power = np.abs(sim_result["opt_out"]) ** 2

# Plot the results
plt.plot(time_data * 1e9, input_power, "g-", label="Input pulse")
plt.plot(time_data * 1e9, output_power, "b-", label="Output pulse")
plt.xlabel(r"Time [ns]", fontsize=15)
plt.ylabel(r"Normalized optical power [a.u.]", fontsize=15)
plt.legend()
plt.show()
../../../_images/ipkiss3-cml-WG3-2.png