Adiabatic operation slope-loss algorithm (AO-SLA), how to do it: adiabatic coupling

2 views (last 30 days)
I would like to write a code that can implement the equations of this paper: Adiabatic operation slope-loss algorithm for ultrashort and broadband waveguide taper
I tried it in python but it did not improve my coupling efficiency at all, mayba I am doing something wrong... Here it is my python code:
import sys
sys.path.append(r"C:\Program Files\Lumerical\v241\api\python")
import lumapi
import numpy as np
def create_adiabatic_taper(fdtd, width_input, width_output, alpha, lambda_0, n_eff):
# Define the number of segments to approximate the adiabatic taper
num_segments = 100
L_i_segments = np.zeros(num_segments)
# Widths for each section
widths = np.linspace(width_input, width_output, num_segments + 1)
vertices_x = []
vertices_y = []
for i in range(num_segments):
W1 = widths[i]
W2 = widths[i + 1]
W0 = (W1 + W2) / 2
epsilon = 1e-10 # Small value to prevent division by zero or very small numbers
theta = alpha * lambda_0 / (2 * (W0 + epsilon) * n_eff)
# Prevent theta from becoming too small
if np.abs(theta) < 1e-10:
theta = np.sign(theta) * 1e-10
L_i = (W1 - W2) / (2 * np.tan(theta))
# Ensure L_i is not negative
if L_i < 0:
L_i = 0
L_i_segments[i] = L_i
if i == 0:
vertices_x.append(0)
vertices_y.append(W1 / 2) # For half width
vertices_x.append(sum(L_i_segments[:i+1]))
vertices_y.append(W2 / 2) # For half width
vertices_x = np.array(vertices_x)
vertices_y = np.array(vertices_y)
vertices_x_full = np.concatenate([vertices_x, vertices_x[::-1]])
vertices_y_full = np.concatenate([vertices_y, -vertices_y[::-1]])
vertices = np.vstack((vertices_x_full, vertices_y_full)).T
print("L_i_segments:", L_i_segments)
print("Vertices X:", vertices_x_full)
print("Vertices Y:", vertices_y_full)
# Create the polygon
fdtd.addpoly(
x=0, # Center of the polygon in the x-direction
y=0, # Center of the polygon in the y-direction
z=0, # Center of the polygon in the z-direction
vertices=vertices, # Vertices of the polygon
material="Si (Silicon) - Palik",
name="adiabatic_taper_polygon"
)
fdtd.addtogroup("::model::Taper")
fdtd = lumapi.FDTD()
fdtd.selectall()
fdtd.delete()
# Parameters for the adiabatic taper
wavelength = 1550e-9 # Operating wavelength in meters
width_input = 0.5e-6 # Width of the input waveguide in meters
width_output = 0.075e-6 # Width of the output waveguide in meters
alpha = 1 # Slope angle in degrees
lambda_0 = 1550e-9 # Center wavelength in meters
n_eff = 3.47 # Effective index of the cross-section at the center of the taper
# Create the adiabatic taper
create_adiabatic_taper(fdtd, width_input, width_output, alpha, lambda_0, n_eff)

Answers (2)

Umar
Umar on 30 Jun 2024
Hi Tay,
The calculation of the variable L_i is incorrect, leading to negative values for some segments. This causes an error when trying to create the polygon.
To fix the issue, you need to modify the calculation of L_i to ensure that it is always positive. You can achieve this by taking the absolute value of the difference between W1 and W2 before dividing by 2 * np.tan(theta).
Replace the following line:
L_i = (W1 - W2) / (2 * np.tan(theta))
with:
L_i = np.abs(W1 - W2) / (2 * np.tan(theta))
This modification ensures that L_i is always positive, preventing any negative values.
Hope this will help resolve your problem.
  2 Comments
Tay
Tay on 1 Jul 2024
Thank you so much for replying :).
Yeah, indeed, so I should delete the lines?
# Ensure L_i is not negative
if L_i < 0:
L_i = 0
Tay
Tay on 1 Jul 2024
I did a quick test by deleting the lines I mentioned and replacing by abs values the line you recommended, and i think still we have some negatives values there, because the shape has a deepth in there.

Sign in to comment.


Umar
Umar on 1 Jul 2024

Hi Tay,

I took the liberty of modifying your code after reviewing it, try this updated version and let me know if it works for you.

import sys sys.path.append(r"C:\Program Files\Lumerical\v241\api\python") import lumapi import numpy as np

def create_adiabatic_taper(fdtd, width_input, width_output, alpha, lambda_0, n_eff): # Define the number of segments to approximate the adiabatic taper num_segments = 100 L_i_segments = np.zeros(num_segments)

    # Widths for each section 
    widths = np.linspace(width_input, width_output, num_segments + 1)
    vertices_x = []
    vertices_y = []
    for i in range(num_segments):
        W1 = widths[i]
        W2 = widths[i + 1]
        W0 = (W1 + W2) / 2
        epsilon = 1e-10  # Small value to prevent division by zero or very small numbers
        theta = alpha * lambda_0 / (2 * (W0 + epsilon) * n_eff)
        # Prevent theta from becoming too small
        if np.abs(theta) < 1e-10:
            theta = np.sign(theta) * 1e-10
        L_i = np.abs(W1 - W2) / (2 * np.tan(theta))
        L_i_segments[i] = L_i
        if i == 0:
            vertices_x.append(0)
            vertices_y.append(W1 / 2)  # For half width
        vertices_x.append(sum(L_i_segments[:i+1]))
        vertices_y.append(W2 / 2)  # For half width
    vertices_x = np.array(vertices_x)
    vertices_y = np.array(vertices_y)
    vertices_x_full = np.concatenate([vertices_x, vertices_x[::-1]])
    vertices_y_full = np.concatenate([vertices_y, -vertices_y[::-1]])
    vertices = np.vstack((vertices_x_full, vertices_y_full)).T
    print("L_i_segments:", L_i_segments)
    print("Vertices X:", vertices_x_full)
    print("Vertices Y:", vertices_y_full)
    # Create the polygon 
    fdtd.addpoly(
        x=0,  # Center of the polygon in the x-direction
        y=0,  # Center of the polygon in the y-direction
        z=0,  # Center of the polygon in the z-direction
        vertices=vertices,  # Vertices of the polygon
        material="Si (Silicon) - Palik",
        name="adiabatic_taper_polygon"
    )
    fdtd.addtogroup("::model::Taper")

fdtd = lumapi.FDTD() fdtd.selectall() fdtd.delete()

  1. Parameters for the adiabatic taper wavelength = 1550e-9 # Operating wavelength in meters width_input = 0.5e-6 # Width of the input waveguide in meters width_output = 0.075e-6 # Width of the output waveguide in meters alpha = 1 # Slope angle in degrees lambda_0 = 1550e-9 # Center wavelength in meters n_eff = 3.47 # Effective index of the cross-section at the center of the taper
  1. Create the adiabatic taper create_adiabatic_taper(fdtd, width_input, width_output, alpha, lambda_0, n_eff)

Hopefully, this code should now correctly calculate the length of each segment of the adiabatic taper without producing negative values.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!