Exemplo n.º 1
0
def guided_mode_given_g(g, eps_array, d_array, n_modes=1, 
                omega_lb=None, omega_ub=None,
                step=1e-2, tol=1e-2, pol='TE'):
    """
    Finds the first 'n_modes' guided modes of polarization 'pol' for a given 'g'
    """

    # Set lower and upper bound on the possible solutions
    eps_val = get_value(eps_array)
    d_val = get_value(d_array)
    if omega_lb is None:
        omega_lb = g/np.sqrt(eps_val[1:-1].max())
    if omega_ub is None:
        omega_ub = g/np.sqrt(max(eps_val[0],eps_val[-1]))

    omega_lb = omega_lb*(1+tol)
    omega_ub = omega_ub*(1-tol)

    # D22real is used in the fsolve; D22test is vectorized and used on a test 
    # array of omega-s to find sign flips
    D22real = lambda x,*args: bd.real(D22(x, *args, pol=pol))
    D22test = lambda x,*args: bd.real(D22s_vec(x, *args, pol=pol))

    # Making sure the bounds go all the way to omega_ub
    omega_bounds = np.append(np.arange(omega_lb, omega_ub, step), omega_ub) 

    # Variables storing the solutions
    omega_solutions = [] 
    coeffs = []

    # Find omegas between which D22 changes sign
    D22s = D22test(omega_bounds, g, eps_val, d_val).real
    sign_change = np.where(D22s[0:-1]*D22s[1:] < 0)[0]
    lb = omega_bounds[0]

    # Use fsolve to find the first 'n_modes' guided modes
    for i in sign_change:
        if len(omega_solutions) >= n_modes:
            break
        lb = omega_bounds[i]
        ub = omega_bounds[i+1]

        # Compute guided mode frequency 
        omega = bd.fsolve_D22(D22real, lb, ub, g, eps_array, d_array)
        omega_solutions.append(omega)
        chi_array = chi(omega, g, eps_array)
        if pol.lower()=='te' or pol.lower()=='tm':
            # Compute A-B coefficients              
            AB = AB_matrices(omega, g, eps_array, d_array, 
                                chi_array, pol)
            # Normalize
            norm = normalization_coeff(omega, g, eps_array, d_array, 
                                chi_array, AB, pol)
            coeffs.append(AB / bd.sqrt(norm))
        else:
            raise ValueError("Polarization should be 'TE' or 'TM'")

    return (omega_solutions, coeffs)
Exemplo n.º 2
0
def chi(omega, g, eps):
    """
    Function to compute chi_j, the z-direction wave-vector in each layer j
    Either omega is an array and eps is a number, or vice versa
    Input
        omega           : frequency * 2π , in units of light speed/unit length
        eps             : slab permittivity array
        g               : wave vector along propagation direction 
    Output
        chi             : array of chi_j for all layers j including claddings
    """
    sqarg = bd.array(eps * omega**2 - g**2, dtype=bd.complex)
    return bd.where(bd.real(sqarg) >= 0, bd.sqrt(sqarg), 1j * bd.sqrt(-sqarg))
Exemplo n.º 3
0
 def __init__(self, eps=1.):
     """Create a shape
     """
     self.eps = eps
     self.area = bd.real(self.compute_ft(bd.array([[0.], [0.]])))