Exemple #1
0
def basic_test():
    """
    Compare with program I wrote previously in Mathematica. Also confirms
    that I don't accidentally mess up the program by editing.
    """
    n_list = [1, 2 + 4j, 3 + 0.3j, 1 + 0.1j]
    d_list = [inf, 2, 3, inf]
    th_0 = 0.1
    lam_vac = 100

    print('The following should all be zero (within rounding errors):')

    s_data = coh_tmm('s', n_list, d_list, th_0, lam_vac)
    print(df(s_data['r'], -0.60331226568845775 - 0.093522181653632019j))
    print(df(s_data['t'], 0.44429533471192989 + 0.16921936169383078j))
    print(df(s_data['R'], 0.37273208839139516))
    print(df(s_data['T'], 0.22604491247079261))
    p_data = coh_tmm('p', n_list, d_list, th_0, lam_vac)
    print(df(p_data['r'], 0.60102654255772481 + 0.094489146845323682j))
    print(df(p_data['t'], 0.4461816467503148 + 0.17061408427088917j))
    print(df(p_data['R'], 0.37016110373044969))
    print(df(p_data['T'], 0.22824374314132009))
    ellips_data = ellips(n_list, d_list, th_0, lam_vac)
    print(df(ellips_data['psi'], 0.78366777347038352))
    print(df(ellips_data['Delta'], 0.0021460774404193292))
    return
Exemple #2
0
def sample2():
    """
    Here's the transmitted intensity versus wavelength through a single-layer
    film which has some complicated wavelength-dependent index of refraction.
    (I made these numbers up, but in real life they could be read out of a
    graph / table published in the literature.) Air is on both sides of the
    film, and the light is normally incident.
    """
    #index of refraction of my material: wavelength in nm versus index.
    material_nk_data = array([[200, 2.1 + 0.1j], [300, 2.4 + 0.3j],
                              [400, 2.3 + 0.4j], [500, 2.2 + 0.4j],
                              [750, 2.2 + 0.5j]])
    material_nk_fn = interp1d(material_nk_data[:, 0].real,
                              material_nk_data[:, 1],
                              kind='quadratic')
    d_list = [inf, 300, inf]  #in nm
    lambda_list = linspace(200, 750, 400)  #in nm
    T_list = []
    for lambda_vac in lambda_list:
        n_list = [1, material_nk_fn(lambda_vac), 1]
        T_list.append(coh_tmm('s', n_list, d_list, 0, lambda_vac)['T'])
    plt.figure()
    plt.plot(lambda_list, T_list)
    plt.xlabel('Wavelength (nm)')
    plt.ylabel('Fraction of power transmitted')
    plt.title('Transmission at normal incidence')
    plt.show()
Exemple #3
0
def sample6():
    """
    An example reflection plot with a surface plasmon resonance (SPR) dip.
    Compare with http://doi.org/10.2320/matertrans.M2010003 ("Spectral and
    Angular Responses of Surface Plasmon Resonance Based on the Kretschmann
    Prism Configuration") Fig 6a
    """
    # list of layer thicknesses in nm
    d_list = [inf, 5, 30, inf]
    # list of refractive indices
    n_list = [1.517, 3.719 + 4.362j, 0.130 + 3.162j, 1]
    # wavelength in nm
    lam_vac = 633
    # list of angles to plot
    theta_list = linspace(30 * degree, 60 * degree, num=300)
    # initialize lists of y-values to plot
    Rp = []
    for theta in theta_list:
        Rp.append(coh_tmm('p', n_list, d_list, theta, lam_vac)['R'])
    plt.figure()
    plt.plot(theta_list / degree, Rp, 'blue')
    plt.xlabel('theta (degree)')
    plt.ylabel('Fraction reflected')
    plt.xlim(30, 60)
    plt.ylim(0, 1)
    plt.title(
        'Reflection of p-polarized light with Surface Plasmon Resonance\n'
        'Compare with http://doi.org/10.2320/matertrans.M2010003 Fig 6a')
    plt.show()
Exemple #4
0
def sample1():
    """
    Here's a thin non-absorbing layer, on top of a thick absorbing layer, with
    air on both sides. Plotting reflected intensity versus wavenumber, at two
    different incident angles.
    """

        
    # list of wavenumbers to plot in nm^-1
    
    ks=linspace(0.0025,.00125,num=800)
    
    # list of layer thicknesses in nm

    ks=linspace(0.0025,.00125,num=800)
    
    d0 = inf
    d1 = 92
    d2 = 91
    d3 = inf
    
    d_list = [d0, d1, d2, d1, d2, d1, d2, d1, d2, d1, d2, d1, d2, d1, d3]


    material_nk_data2 = array([[0.0025, 1.575+0.17j], # @400nm
                              [0.002, 1.5552+0.15j], # @500nm
                              [0.001667, 1.5444+0.14j], # @600nm
                              [0.001429, 1.53796+0.13j], # @700nm
                              [0.00125, 1.53375+0.12j]]) # @800nm
    material_nk_fn2 = interp1d(material_nk_data2[:,0].real,
                              material_nk_data2[:,1], kind='quadratic')

    material_nk_data1 = array([[0.0025, 1.705+0.06j], # @400nm
                              [0.002, 1.6852+0.04j], # @500nm
                              [0.001667, 1.6744+0.03j], # @600nm
                              [0.001429, 1.66796+0.02j], # @700nm
                              [0.00125, 1.66375+0.014j]]) # @800nm
 
    material_nk_fn1 = interp1d(material_nk_data1[:,0].real,
                              material_nk_data1[:,1], kind='quadratic')   
    
    
    # initialize lists of y-values to plot
    Rnorm=[] 
    R37=[]
    for k in ks:
		# For normal incidence, s and p polarizations are identical.
		# I arbitrarily decided to use 's'.
        n_list = [1, material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), 1.615+0.085j]
        Rnorm.append(coh_tmm('s',n_list, d_list, 0, 1/k)['R'])
        #R37.append(unpolarized_RT(n_list, d_list, 37*degree, 1/k)['R'])
    kcm = ks * 1e7 #ks in cm^-1 rather than nm^-1
    lamb = 1/ks
    plt.figure()
    plt.plot(lamb,Rnorm,'blue',expx,expy,'purple')
    plt.xlabel('Wavelength (/nm)')
    plt.ylabel('Fraction reflected')
    plt.title('Simulated reflection of unpolarized light at 0$^\circ$ incidence (blue), '
                'Experimental data (purple)')
    plt.axis([400, 800, 0, 0.25])
Exemple #5
0
def sample1():
    """
    Here's a thin non-absorbing layer, on top of a thick absorbing layer, with
    air on both sides. Plotting reflected intensity versus wavenumber, at two
    different incident angles.
    """
    # list of layer thicknesses in nm
    d_list = [inf, 100, 300, inf]
    # list of refractive indices
    n_list = [1, 2.2, 3.3 + 0.3j, 1]
    # list of wavenumbers to plot in nm^-1
    ks = linspace(0.0001, .01, num=400)
    # initialize lists of y-values to plot
    Rnorm = []
    R45 = []
    for k in ks:
        # For normal incidence, s and p polarizations are identical.
        # I arbitrarily decided to use 's'.
        Rnorm.append(coh_tmm('s', n_list, d_list, 0, 1 / k)['R'])
        R45.append(unpolarized_RT(n_list, d_list, 45 * degree, 1 / k)['R'])
    kcm = ks * 1e7  #ks in cm^-1 rather than nm^-1
    plt.figure()
    plt.plot(kcm, Rnorm, 'blue', kcm, R45, 'purple')
    plt.xlabel('k (cm$^{-1}$)')
    plt.ylabel('Fraction reflected')
    plt.title('Reflection of unpolarized light at 0$^\circ$ incidence (blue), '
              '45$^\circ$ (purple)')
    plt.show()
Exemple #6
0
def sample4():
    """
    Here is an example where we plot absorption and Poynting vector
    as a function of depth.
    """
    d_list = [inf, 100, 300, inf]  #in nm
    n_list = [1, 2.2 + 0.2j, 3.3 + 0.3j, 1]
    th_0 = pi / 4
    lam_vac = 400
    pol = 'p'
    coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)

    ds = linspace(-50, 400, num=1000)  #position in structure
    poyn = []
    absor = []
    for d in ds:
        layer, d_in_layer = find_in_structure_with_inf(d_list, d)
        data = position_resolved(layer, d_in_layer, coh_tmm_data)
        poyn.append(data['poyn'])
        absor.append(data['absor'])
    # convert data to numpy arrays for easy scaling in the plot
    poyn = array(poyn)
    absor = array(absor)
    plt.figure()
    plt.plot(ds, poyn, 'blue', ds, 200 * absor, 'purple')
    plt.xlabel('depth (nm)')
    plt.ylabel('AU')
    plt.title('Local absorption (purple), Poynting vector (blue)')
    plt.show()
def sample1():
    """
    Here's a thin non-absorbing layer, on top of a thick absorbing layer, with
    air on both sides. Plotting reflected intensity versus wavenumber, at two
    different incident angles.
    """

        
    # list of wavenumbers to plot in nm^-1
    
    ks=linspace(0.0025,.00125,num=800)
    
    # list of layer thicknesses in nm

    d0 = inf
    d1 = 117
    d2 = 73
    d3 = inf
    
    d_list = [inf, d1, d2, d1, d2, d1, d2, d1, d2, d1, d2, d1, d2, d3]
    
    # list of refractive indices
    #Light-constasted layers
    
    material_nk_data1 = array([[0.0025, 1.6335+0.0564j], # @400nm
                              [0.002,1.61376+0.0366], # @500nm
                              [0.001667, 1.603+0.025844j], # @600nm
                              [0.001429,1.5965+0.01935j], # @700nm
                              [0.00125, 1.59231+0.001515j]]) # @800nm
 
    material_nk_fn1 = interp1d(material_nk_data1[:,0].real,
                              material_nk_data1[:,1], kind='quadratic')
    #Dark-contrasted layers
    material_nk_data2 = array([[0.0025,1.5326+0.13955j], # @400nm
                              [0.002, 1.5128+0.11975j], # @500nm
                              [0.001667,1.5024+0.109j], # @600nm
                              [0.001429,1.4956+0.1025j], # @700nm
                              [0.00125,1.49135+0.0983j]]) # @800nm
    material_nk_fn2 = interp1d(material_nk_data2[:,0].real,
                              material_nk_data2[:,1], kind='quadratic')
    
    # initialize lists of y-values to plot
    Rnorm=[] 
    R37=[]
    for k in ks:
		# For normal incidence, s and p polarizations are identical.
		# I arbitrarily decided to use 's'.
        n_list = [1, material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k),1.55+0.1j]
        Rnorm.append(coh_tmm('s',n_list, d_list, 0, 1/k)['R'])
        #R37.append(unpolarized_RT(n_list, d_list, 37*degree, 1/k)['R'])
    kcm = ks * 1e7 #ks in cm^-1 rather than nm^-1
    lamb = 1/ks
    plt.figure()
    plt.plot(lamb,Rnorm,'blue',expx,expy,'purple')
    plt.xlabel('Wavelength (/nm)')
    plt.ylabel('Fraction reflected')
    plt.title('Simulated reflection of unpolarized light at 0$^\circ$ incidence (blue), '
                'Experimental data (purple)')
    plt.axis([400, 800, 0, 0.25])
Exemple #8
0
def coh_overflow_test():
    """
    Test whether very very opaque layers will break the coherent program
    """
    n_list = [1., 2 + .1j, 1 + 3j, 4., 5.]
    d_list = [inf, 50, 1e5, 50, inf]
    lam = 200
    alpha_d = imag(n_list[2]) * 4 * pi * d_list[2] / lam
    print('Very opaque layer: Calculation should involve e^(-', alpha_d, ')!')
    data = coh_tmm('s', n_list, d_list, 0, lam)
    n_list2 = n_list[0:3]
    d_list2 = d_list[0:3]
    d_list2[-1] = inf
    data2 = coh_tmm('s', n_list2, d_list2, 0, lam)
    print('First entries of the following two lists should agree:')
    print(data['vw_list'])
    print(data2['vw_list'])
Exemple #9
0
def calc_reflectances(n_fn_list, d_list, th_0, pol='s', spectral_range='narrow'):
    """
    Calculate the reflection spectrum of a thin-film stack.

    n_fn_list[m] should be a function that inputs wavelength in nm and
    outputs refractive index of the m'th layer. In other words,
    n_fn_list[2](456) == 1.53 + 0.4j mans that layer #2 has a refractive index
    of 1.53 + 0.4j at 456nm. These functions could be defined with
    scipy.interpolate.interp1d() for example.

    pol, d_list and th_0 are defined as in tmm.coh_tmm ... but d_list
    MUST be in units of nanometers

    spectral_range can be 'full' if all the functions in n_fn_list can take
    wavelength arguments between 360-830nm; or 'narrow' if some or all require
    arguments only in the range 400-700nm. The wavelengths outside the
    'narrow' range make only a tiny difference to the color, because they are
    almost invisible to the eye. If spectral_range is 'narrow', then the n(400)
    values are used for 360-400 and n(700) for 700-830nm

    Returns a 2-column array where the first column is wavelength in nm
    (360,361,362,...,830) and the second column is reflectivity (from 0
    to 1, where 1 is a perfect mirror). This range is chosen to be
    consistent with colorpy.illuminants. See  colorpy.ciexyz.start_wl_nm etc.
    """

    lam_vac_list = arange(360, 831)

    num_layers = len(n_fn_list)

    def extend_spectral_range(n_fn):
        """
        Starting with a narrow-spectrum refractive index function
        n_fn(wavelength), create then return the corresponding full-spectrum
        refractive index function
        """
        def extended_n_fn(lam):
            if lam < 400:
                return n_fn(400)
            elif lam > 700:
                return n_fn(700)
            else:
                return n_fn(lam)
        return extended_n_fn

    if spectral_range == 'narrow':
        n_fn_list = [extend_spectral_range(n_fn) for n_fn in n_fn_list]

    final_answer = []

    for lam_vac in lam_vac_list:
        n_list = [n_fn_list[i](lam_vac) for i in range(num_layers)]
        R = coh_tmm(pol, n_list, d_list, th_0, lam_vac)['R']
        final_answer.append([lam_vac,R])
    final_answer = array(final_answer)

    return final_answer
Exemple #10
0
def sample1():
    """
    Here's a thin non-absorbing layer, on top of a thick absorbing layer, with
    air on both sides. Plotting reflected intensity versus wavenumber, at two
    different incident angles.
    """

        
    # list of wavenumbers to plot in nm^-1
    
    ks=linspace(0.0025,.00125,num=800)
    
    d0 = inf
    d1 = 92
    d2 = 90
    d3 = inf
    
    d_list = [d0, d1, d2, d1, d2, d1, d2, d1, d2, d1, d2, d1, d2, d1, d3]


    material_nk_data2 = array([[0.0025, 1.575+0.17j], # @400nm
                              [0.002, 1.5552+0.15j], # @500nm
                              [0.001667, 1.5444+0.14j], # @600nm
                              [0.001429, 1.53796+0.13j], # @700nm
                              [0.00125, 1.53375+0.12j]]) # @800nm
    material_nk_fn2 = interp1d(material_nk_data2[:,0].real,
                              material_nk_data2[:,1], kind='quadratic')

    material_nk_data1 = array([[0.0025, 1.705+0.06j], # @400nm
                              [0.002, 1.6852+0.04j], # @500nm
                              [0.001667, 1.6744+0.03j], # @600nm
                              [0.001429, 1.66796+0.02j], # @700nm
                              [0.00125, 1.66375+0.014j]]) # @800nm
 
    material_nk_fn1 = interp1d(material_nk_data1[:,0].real,
                              material_nk_data1[:,1], kind='quadratic')   
    

    
    # initialize lists of y-values to plot
    Rnorm=[] 
    R37=[]
    for k in ks:
		# For normal incidence, s and p polarizations are identical.
		# I arbitrarily decided to use 's'.
        n_list = [1, material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), material_nk_fn2(k), material_nk_fn1(k), 1.615+0.085j]
        Rnorm.append(coh_tmm('s',n_list, d_list, 0, 1/k)['R'])
        #R37.append(unpolarized_RT(n_list, d_list, 37*degree, 1/k)['R'])
    kcm = ks * 1e7 #ks in cm^-1 rather than nm^-1
    lamb = 1/ks
    plt.figure()
    plt.plot(lamb,Rnorm,'blue',expx,expy,'purple')
    plt.xlabel('Wavelength (/nm)')
    plt.ylabel('Fraction reflected')
    plt.title('Simulated reflection of unpolarized light at 0$^\circ$ incidence (blue), '
                'Experimental data (purple)')
    plt.axis([400, 800, 0, 0.25])
Exemple #11
0
 def run(self, thicknesses, theta0, polarization=None):
     """
     runs the model with specified parameters
     :param thicknesses: list of thicknesses, first and last must be inf
     :param theta0: input angle
     :param polarization: polarization state 's', 'p', or None
     :return: void
     """
     self.index_array = np.array(self.mat_df[self.layers])
     if polarization is None:
         self.data = tmm.unpolarized_RT(self.index_array, thicknesses, theta0, self.wavelength)
     elif polarization in ['p', 's']:
         self.data = tmm.coh_tmm(polarization, self.index_array, thicknesses, theta0, self.wavelength)
Exemple #12
0
def sample1():
    """
    Here's a thin non-absorbing layer, on top of a thick absorbing layer, with
    air on both sides. Plotting reflected intensity versus wavenumber, at two
    different incident angles.
    """
    # list of layer thicknesses in nm
    d_list = [inf, 100, 80, 100, 80, 100, 80, 100, 80, 100, 80, 100, 80, inf]
    # list of refractive indices
    n_list = [
        1, 1.68 + 0.03j, 1.55 + 0.14j, 1.68 + 0.03j, 1.55 + 0.14j,
        1.68 + 0.03j, 1.55 + 0.14j, 1.68 + 0.03j, 1.55 + 0.14j, 1.68 + 0.03j,
        1.55 + 0.14j, 1.68 + 0.03j, 1.55 + 0.14j, 1.61 + 0.085j
    ]
    # list of wavenumbers to plot in nm^-1
    ks = linspace(0.0025, .00125, num=800)
    # initialize lists of y-values to plot
    Rnorm = []
    R37 = []
    for k in ks:
        # For normal incidence, s and p polarizations are identical.
        # I arbitrarily decided to use 's'.
        Rnorm.append(coh_tmm('s', n_list, d_list, 0, 1 / k)['R'])
        R37.append(unpolarized_RT(n_list, d_list, 37 * degree, 1 / k)['R'])
    kcm = ks * 1e7  #ks in cm^-1 rather than nm^-1
    lamb = 1 / ks
    plt.figure()
    plt.plot(lamb, Rnorm, 'blue', lamb, R37, 'purple')
    plt.xlabel('Wavelength (/nm)')
    plt.ylabel('Fraction reflected')
    plt.title('Reflection of unpolarized light at 0$^\circ$ incidence (blue), '
              '37$^\circ$ (purple)')

    # data file
    import numpy
    datafile_path = "/users/Olimpia/Desktop/datafile.txt"
    datafile_id = open(datafile_path, 'w+')
    data = numpy.array([lamb, Rnorm])
    data = data.T
    numpy.savetxt(datafile_id, data, fmt=['%.4f', '%.4f'])
    datafile_id.close()
Exemple #13
0
def absorp_analytic_fn_test():
    """
    Test absorp_analytic_fn functions
    """
    d_list = [inf, 100, 300, inf]  #in nm
    n_list = [1, 2.2 + 0.2j, 3.3 + 0.3j, 1]
    th_0 = pi / 4
    lam_vac = 400
    layer = 1
    d = d_list[layer]
    dist = 37
    print('The following should all be zero (within rounding errors):')

    for pol in ['s', 'p']:
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        expected_absorp = position_resolved(layer, dist, coh_tmm_data)['absor']
        absorp_fn = absorp_analytic_fn()
        absorp_fn.fill_in(coh_tmm_data, layer)
        print(df(absorp_fn.run(dist), expected_absorp))
        absorp_fn2 = absorp_fn.copy().flip()
        dist_from_other_side = d - dist
        print(df(absorp_fn2.run(dist_from_other_side), expected_absorp))

    return
Exemple #14
0
def position_resolved_test():
    """
    Compare with program I wrote previously in Mathematica. Also, various
    consistency checks.
    """
    d_list = [inf, 100, 300, inf]  #in nm
    n_list = [1, 2.2 + 0.2j, 3.3 + 0.3j, 1]
    th_0 = pi / 4
    lam_vac = 400
    layer = 1
    dist = 37
    print('The following should all be zero (within rounding errors):')

    pol = 'p'
    coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
    print(
        df(coh_tmm_data['kz_list'][1],
           0.0327410685922732 + 0.003315885921866465j))
    data = position_resolved(layer, dist, coh_tmm_data)
    print(df(data['poyn'], 0.7094950598055798))
    print(df(data['absor'], 0.005135049118053356))
    print(df(1, sum(absorp_in_each_layer(coh_tmm_data))))

    pol = 's'
    coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
    print(
        df(coh_tmm_data['kz_list'][1],
           0.0327410685922732 + 0.003315885921866465j))
    data = position_resolved(layer, dist, coh_tmm_data)
    print(df(data['poyn'], 0.5422594735025152))
    print(df(data['absor'], 0.004041912286816303))
    print(df(1, sum(absorp_in_each_layer(coh_tmm_data))))

    #Poynting vector derivative should equal absorption
    for pol in ['s', 'p']:
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data1 = position_resolved(layer, dist, coh_tmm_data)
        data2 = position_resolved(layer, dist + 0.001, coh_tmm_data)
        print(
            'Finite difference should approximate derivative. Difference is ' +
            str(
                df((data1['absor'] + data2['absor']) /
                   2, (data1['poyn'] - data2['poyn']) / 0.001)))

    #Poynting vector at end should equal T
    layer = 2
    dist = 300
    for pol in ['s', 'p']:
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data = position_resolved(layer, dist, coh_tmm_data)
        print(df(data['poyn'], coh_tmm_data['T']))

    #Poynting vector at start should equal power_entering
    layer = 1
    dist = 0
    for pol in ['s', 'p']:
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data = position_resolved(layer, dist, coh_tmm_data)
        print(df(data['poyn'], coh_tmm_data['power_entering']))

    #Poynting vector should be continuous
    for pol in ['s', 'p']:
        layer = 1
        dist = 100
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data = position_resolved(layer, dist, coh_tmm_data)
        poyn1 = data['poyn']
        layer = 2
        dist = 0
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data = position_resolved(layer, dist, coh_tmm_data)
        poyn2 = data['poyn']
        print(df(poyn1, poyn2))

    return
def sample1():
    """
    Here's a thin non-absorbing layer, on top of a thick absorbing layer, with
    air on both sides. Plotting reflected intensity versus wavenumber, at two
    different incident angles.
    """

    # list of wavenumbers to plot in nm^-1

    ks = linspace(0.0025, .00125, num=800)

    # list of layer thicknesses in nm

    d0 = inf
    d1 = 117
    d2 = 73
    d3 = inf

    d_list = [inf, d1, d2, d1, d2, d1, d2, d1, d2, d1, d2, d1, d2, d3]

    # list of refractive indices
    #Light-constasted layers

    material_nk_data1 = array([
        [0.0025, 1.6335 + 0.0564j],  # @400nm
        [0.002, 1.61376 + 0.0366],  # @500nm
        [0.001667, 1.603 + 0.025844j],  # @600nm
        [0.001429, 1.5965 + 0.01935j],  # @700nm
        [0.00125, 1.59231 + 0.001515j]
    ])  # @800nm

    material_nk_fn1 = interp1d(material_nk_data1[:, 0].real,
                               material_nk_data1[:, 1],
                               kind='quadratic')
    #Dark-contrasted layers
    material_nk_data2 = array([
        [0.0025, 1.5326 + 0.13955j],  # @400nm
        [0.002, 1.5128 + 0.11975j],  # @500nm
        [0.001667, 1.5024 + 0.109j],  # @600nm
        [0.001429, 1.4956 + 0.1025j],  # @700nm
        [0.00125, 1.49135 + 0.0983j]
    ])  # @800nm
    material_nk_fn2 = interp1d(material_nk_data2[:, 0].real,
                               material_nk_data2[:, 1],
                               kind='quadratic')

    # initialize lists of y-values to plot
    Rnorm = []
    R37 = []
    for k in ks:
        # For normal incidence, s and p polarizations are identical.
        # I arbitrarily decided to use 's'.
        n_list = [
            1,
            material_nk_fn1(k),
            material_nk_fn2(k),
            material_nk_fn1(k),
            material_nk_fn2(k),
            material_nk_fn1(k),
            material_nk_fn2(k),
            material_nk_fn1(k),
            material_nk_fn2(k),
            material_nk_fn1(k),
            material_nk_fn2(k),
            material_nk_fn1(k),
            material_nk_fn2(k), 1.55 + 0.1j
        ]
        Rnorm.append(coh_tmm('s', n_list, d_list, 0, 1 / k)['R'])
        #R37.append(unpolarized_RT(n_list, d_list, 37*degree, 1/k)['R'])
    kcm = ks * 1e7  #ks in cm^-1 rather than nm^-1
    lamb = 1 / ks
    plt.figure()
    plt.plot(lamb, Rnorm, 'blue', expx, expy, 'purple')
    plt.xlabel('Wavelength (/nm)')
    plt.ylabel('Fraction reflected')
    plt.title(
        'Simulated reflection of unpolarized light at 0$^\circ$ incidence (blue), '
        'Experimental data (purple)')
    plt.axis([400, 800, 0, 0.25])
Exemple #16
0
def incoherent_test():
    """
    test inc_tmm(). To do: Add more tests.
    """
    print('The following should all be zero (within rounding errors):')

    #3-incoherent-layer test, real refractive indices (so that R and T are the
    #same in both directions)
    n0 = 1
    n1 = 2
    n2 = 3
    n_list = [n0, n1, n2]
    d_list = [inf, 567, inf]
    c_list = ['i', 'i', 'i']
    th0 = pi / 3
    th1 = snell(n0, n1, th0)
    th2 = snell(n0, n2, th0)
    lam_vac = 400

    for pol in ['s', 'p']:
        inc_data = inc_tmm(pol, n_list, d_list, c_list, th0, lam_vac)
        R0 = abs(interface_r(pol, n0, n1, th0, th1)**2)
        R1 = abs(interface_r(pol, n1, n2, th1, th2)**2)
        T0 = 1 - R0
        RR = R0 + R1 * T0**2 / (1 - R0 * R1)
        print(df(inc_data['R'], RR))
        print(df(inc_data['R'] + inc_data['T'], 1))

    #One finite layer with incoherent layers on both sides. Should agree with
    #coherent program
    n0 = 1 + 0.1j
    n1 = 2 + 0.2j
    n2 = 3 + 0.4j
    n_list = [n0, n1, n2]
    d_list = [inf, 100, inf]
    c_list = ['i', 'c', 'i']
    n00 = 1
    th00 = pi / 3
    th0 = snell(n00, n0, th00)
    lam_vac = 400
    for pol in ['s', 'p']:
        inc_data = inc_tmm(pol, n_list, d_list, c_list, th0, lam_vac)
        coh_data = coh_tmm(pol, n_list, d_list, th0, lam_vac)
        print(df(inc_data['R'], coh_data['R']))
        print(df(inc_data['T'], coh_data['T']))
        print(df(1, sum(inc_absorp_in_each_layer(inc_data))))

    #One finite layer with three incoherent layers. Should agree with
    #manual calculation + coherent program
    n0 = 1 + 0.1j
    n1 = 2 + 0.2j
    n2 = 3 + 0.004j
    n3 = 4 + 0.2j
    d1 = 100
    d2 = 10000
    n_list = [n0, n1, n2, n3]
    d_list = [inf, d1, d2, inf]
    c_list = ['i', 'c', 'i', 'i']
    n00 = 1
    th00 = pi / 3
    th0 = snell(n00, n0, th00)
    lam_vac = 400
    for pol in ['s', 'p']:
        inc_data = inc_tmm(pol, n_list, d_list, c_list, th0, lam_vac)
        coh_data = coh_tmm(pol, [n0, n1, n2], [inf, d1, inf], th0, lam_vac)
        th2 = snell(n0, n2, th0)
        th3 = snell(n0, n3, th0)
        coh_bdata = coh_tmm(pol, [n2, n1, n0], [inf, d1, inf], th2, lam_vac)
        R02 = coh_data['R']
        R20 = coh_bdata['R']
        T02 = coh_data['T']
        T20 = coh_bdata['T']
        P2 = exp(-4 * pi * d2 * (n2 * cos(th2)).imag /
                 lam_vac)  #fraction passing through
        R23 = interface_R(pol, n2, n3, th2, th3)
        T23 = interface_T(pol, n2, n3, th2, th3)
        #T = T02 * P2 * T23 + T02 * P2 * R23 * P2 * R20 * P2 * T23 + ...
        T = T02 * P2 * T23 / (1 - R23 * P2 * R20 * P2)
        #R = R02
        #    + T02 * P2 * R23 * P2 * T20
        #    + T02 * P2 * R23 * P2 * R20 * P2 * R23 * P2 * T20 + ...
        R = R02 + T02 * P2 * R23 * P2 * T20 / (1 - R20 * P2 * R23 * P2)
        print(df(inc_data['T'], T))
        print(df(inc_data['R'], R))

    #The coherent program with a thick but randomly-varying-thickness substrate
    #should agree with the incoherent program.
    nair = 1 + 0.1j
    nfilm = 2 + 0.2j
    nsub = 3
    nf = 3 + 0.4j
    n_list = [nair, nfilm, nsub, nf]
    n00 = 1
    th00 = pi / 3
    th0 = snell(n00, n0, th00)
    lam_vac = 400
    for pol in ['s', 'p']:
        d_list_inc = [inf, 100, 1, inf]  #sub thickness doesn't matter here
        c_list = ['i', 'c', 'i', 'i']
        inc_data = inc_tmm(pol, n_list, d_list_inc, c_list, th0, lam_vac)
        coh_Rs = []
        coh_Ts = []
        for dsub in np.linspace(10000, 30000, 357):
            d_list = [inf, 100, dsub, inf]
            coh_data = coh_tmm(pol, n_list, d_list, th0, lam_vac)
            coh_Rs.append(coh_data['R'])
            coh_Ts.append(coh_data['T'])
        print('Coherent with random thickness should agree with incoherent. ' +
              'Discrepency is: ' + str(df(average(coh_Rs), inc_data['R'])))
        print('Coherent with random thickness should agree with incoherent. ' +
              'Discrepency is: ' + str(df(average(coh_Ts), inc_data['T'])))
    #The coherent program with a thick substrate and randomly-varying wavelength
    #should agree with the incoherent program.
    n0 = 1 + 0.0j
    n_list = [n0, 2 + 0.0002j, 3 + 0.0001j, 3 + 0.4j]
    n00 = 1
    th00 = pi / 3
    th0 = snell(n00, n0, th00)
    d_list = [inf, 10000, 10200, inf]
    c_list = ['i', 'i', 'i', 'i']
    for pol in ['s', 'p']:
        inc_absorp = array([0., 0., 0., 0.])
        coh_absorp = array([0., 0., 0., 0.])
        num_pts = 234
        for lam_vac in np.linspace(40, 50, num_pts):
            inc_data = inc_tmm(pol, n_list, d_list, c_list, th0, lam_vac)
            inc_absorp += array(inc_absorp_in_each_layer(inc_data))
            coh_data = coh_tmm(pol, n_list, d_list, th0, lam_vac)
            coh_absorp += array(absorp_in_each_layer(coh_data))
        inc_absorp /= num_pts
        coh_absorp /= num_pts
        print(
            'Coherent with random wavelength should agree with incoherent. ' +
            'The two rows of this array should be the same:')
        print(vstack((inc_absorp, coh_absorp)))
Exemple #17
0
def position_resolved_test2():
    """
    Similar to position_resolved_test(), but with initial and final medium
    having a complex refractive index.
    """
    d_list = [inf, 100, 300, inf]  #in nm
    # "00" is before the 0'th layer. This is easy way to generate th0, ensuring
    #that n0*sin(th0) is real.
    n00 = 1
    th00 = pi / 4
    n0 = 1 + 0.1j
    th_0 = snell(n00, n0, th00)
    n_list = [n0, 2.2 + 0.2j, 3.3 + 0.3j, 1 + 0.4j]
    lam_vac = 400
    layer = 1
    dist = 37
    print('The following should all be zero (within rounding errors):')

    for pol in ['s', 'p']:
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data = position_resolved(layer, dist, coh_tmm_data)
        print(df(1, sum(absorp_in_each_layer(coh_tmm_data))))

    #Poynting vector derivative should equal absorption
    for pol in ['s', 'p']:
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data1 = position_resolved(layer, dist, coh_tmm_data)
        data2 = position_resolved(layer, dist + 0.001, coh_tmm_data)
        print(
            'Finite difference should approximate derivative. Difference is ' +
            str(
                df((data1['absor'] + data2['absor']) /
                   2, (data1['poyn'] - data2['poyn']) / 0.001)))

    #Poynting vector at end should equal T
    layer = 2
    dist = 300
    for pol in ['s', 'p']:
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data = position_resolved(layer, dist, coh_tmm_data)
        print(df(data['poyn'], coh_tmm_data['T']))

    #Poynting vector at start should equal power_entering
    layer = 1
    dist = 0
    for pol in ['s', 'p']:
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data = position_resolved(layer, dist, coh_tmm_data)
        print(df(data['poyn'], coh_tmm_data['power_entering']))

    #Poynting vector should be continuous
    for pol in ['s', 'p']:
        layer = 1
        dist = 100
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data = position_resolved(layer, dist, coh_tmm_data)
        poyn1 = data['poyn']
        layer = 2
        dist = 0
        coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac)
        data = position_resolved(layer, dist, coh_tmm_data)
        poyn2 = data['poyn']
        print(df(poyn1, poyn2))

    return