예제 #1
0
def calculate(args):
    Si, Electrode, T, V_p, V_rb = args
    sample_data_dir = join(dirname(__file__), '03-data')
    db_name = '03_Au_nSi_BW_transient' + '_%02.2fVp_%02.2fVrb_%03.2fK' % (
        V_p, abs(V_rb), T) + '.db'
    db_name = join(sample_data_dir, db_name)
    MyProject = Project(db_name=db_name,
                        backend='sqlite',
                        hostname='',
                        overwrite=False)
    MyDiode = SchottkyDiode(MyProject,
                            'Au-Si_BW',
                            Electrode,
                            Si,
                            DeadLayer=1.5e-7,
                            L=5e-6)
    MyDiode.set_T(T)
    MyDiode.set_Va(V_p)

    type_sign = -1 if MyDiode.Semiconductor.dop_type == 'n' else 1
    Psi = Psi_approx(MyDiode.L, -(MyDiode.V_bi(eV=True) + type_sign * V_p),
                     0.0)

    Psi, E, z_nodes, rho_err_points, Vd, Vd_err, J, J_err, \
        BI_F, dopants_F, ic_id = Poisson.Reccurent_Poisson_solver(MyDiode, Psi, Vd_error=1e-6,
                                                                  equilibrium_filling=True, t=mp.inf,
                                                                  initial_condition_id=-1,
                                                                  rho_rel_err=Poisson_rel_err, max_iter=100,
                                                                  debug=False)

    #plt.plot(z_nodes, -Psi(z_nodes), 'r-o')
    #plt.show()

    MyDiode.set_Va(V_rb)
    Psi, E, z_nodes, rho_err_points, Vd, Vd_err, J, J_err, \
        BI_F, dopants_F, ic_id = Poisson.Reccurent_Poisson_solver(MyDiode, Psi, Vd_error=1e-6,
                                                                  equilibrium_filling=False, fast_traps=['Phosphorus'],
                                                                  t=0.0,
                                                                  initial_condition_id=ic_id,
                                                                  rho_rel_err=Poisson_rel_err, max_iter=100,
                                                                  debug=False)

    #plt.plot(z_nodes, -Psi(z_nodes), 'r-o')
    #plt.show()

    t_points, potential_t, field_d, z_t, diode_voltage_drop_t, current_density_t, \
        bonding_interfaces_f_t, dopants_f_t, last_state_id = Kinetics.traps_kinetics(MyDiode, ic_id,
                                                                                     1e-9, 10e-3, 100e-3,
                                                                                     fast_traps=['Phosphorus'],
                                                                                     rho_rel_err=Poisson_rel_err,
                                                                                     df_threshold=1e-2, debug=True)

    return [T, t_points, bonding_interfaces_f_t, dopants_f_t]
예제 #2
0
def calculate(args):
    Si, Electrode, T, V_p = args
    sample_data_dir = join(dirname(__file__), '03-data')
    db_name = '03_Au_nSi_BW_transient' + '_%02.2fVp_%02.2fVrb_%03.2fK' % (
        V_p, abs(V_rb), T) + '.db'
    db_name = join(sample_data_dir, db_name)
    MyProject = Project(db_name=db_name,
                        backend='sqlite',
                        hostname='',
                        overwrite=False)
    MyDiode = SchottkyDiode(MyProject,
                            'Au-Si_BW',
                            Electrode,
                            Si,
                            DeadLayer=1.5e-7,
                            L=5e-6)
    MyDiode.set_T(T)
    MyDiode.set_Va(V_p)
    print T

    type_sign = -1 if MyDiode.Semiconductor.dop_type == 'n' else 1
    Psi = Psi_approx(MyDiode.L, -(MyDiode.V_bi(eV=True) + type_sign * V_p),
                     0.0)

    Psi, E, z_nodes, rho_err_points, Vd, Vd_err, J, J_err, \
        BI_F, dopants_F, ic_id = Poisson.Reccurent_Poisson_solver(MyDiode, Psi, Vd_error=1e-6,
                                                                  equilibrium_filling=True, t=mp.inf,
                                                                  initial_condition_id=-1,
                                                                  rho_rel_err=Poisson_rel_err, max_iter=100,
                                                                  debug=False)
    return db_name
예제 #3
0
def dopants_df_dt(schottky_diode, initial_condition_id):
    ic_found, potential, field, z_nodes, _, \
        diode_voltage_drop, _, current_density, _, bonding_interfaces_f, dopants_f, \
        measurement_id = Poisson.load_diode_state(schottky_diode, initial_condition_id, debug=True)
    if not ic_found:
        raise (
            Exception('Initial condition not found. Please check everything'))
    #schottky_diode.dopants_set_eq_F(z_nodes, potential, debug=False)
    _, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(5, sharex=True)
    ax1.plot(z_nodes, -potential(z_nodes))
    for dopant_name in dopants_f.keys():
        ax2.plot(z_nodes, dopants_f[dopant_name])
    fermi_level = schottky_diode.EfEc(potential, z_nodes, eV=False)
    n, p = schottky_diode.n_carriers_theory(potential, z_nodes)
    if schottky_diode.Semiconductor.dop_type == 'n':
        p = np.zeros_like(p)
    elif schottky_diode.Semiconductor.dop_type == 'p':
        n = np.zeros_like(n)
    ax4.plot(z_nodes, n)
    for dopant in schottky_diode.Semiconductor.dopants:
        dopant_f = dopant.equilibrium_f(schottky_diode.T,
                                        schottky_diode.Semiconductor,
                                        fermi_level,
                                        electron_volts=False,
                                        debug=False)
        ax2.plot(z_nodes, dopant_f)
        df_dt, tau = dopant.df_dt(schottky_diode.T,
                                  schottky_diode.Semiconductor,
                                  dopants_f[dopant_name],
                                  n,
                                  p,
                                  barrier_lowering_e=None,
                                  barrier_lowering_h=None,
                                  use_mpmath=False,
                                  debug=False)
        capture_e, capture_h, capture_tau_e, capture_tau_h = dopant.capture_rate(
            schottky_diode.T,
            schottky_diode.Semiconductor,
            dopants_f[dopant_name],
            n,
            p,
            debug=False)
        emission_e, emission_h, emission_tau_e, emission_tau_h = dopant.emission_rate(
            schottky_diode.T,
            schottky_diode.Semiconductor,
            dopants_f[dopant_name],
            barrier_lowering_e=None,
            barrier_lowering_h=None,
            use_mpmath=False,
            debug=False)
        print 'electrons: capture tau = %2.2g s, emission tau = %2.2g s' % (
            min(capture_tau_e), min(emission_tau_e))
        print 'holes: capture tau = %2.2g s, emission tau = %2.2g s' % (
            min(capture_tau_h), min(emission_tau_h))
        print 'tau = %2.2g s' % tau
        #ax3.plot(z_nodes, emission_h - emission_e)
        ax3.plot(z_nodes, df_dt)
        #ax5.plot(z_nodes, capture_tau_e)
    plt.show()
예제 #4
0
def dopants_df_dt(schottky_diode, initial_condition_id):
    ic_found, potential, field, z_nodes, _, \
        diode_voltage_drop, _, current_density, _, bonding_interfaces_f, dopants_f, \
        measurement_id = Poisson.load_diode_state(schottky_diode, initial_condition_id, debug=True)
    if not ic_found:
        raise(Exception('Initial condition not found. Please check everything'))
    #schottky_diode.dopants_set_eq_F(z_nodes, potential, debug=False)
    _, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(5, sharex=True)
    ax1.plot(z_nodes, -potential(z_nodes))
    for dopant_name in dopants_f.keys():
        ax2.plot(z_nodes, dopants_f[dopant_name])
    fermi_level = schottky_diode.EfEc(potential, z_nodes, eV=False)
    n, p = schottky_diode.n_carriers_theory(potential, z_nodes)
    if schottky_diode.Semiconductor.dop_type == 'n':
        p = np.zeros_like(p)
    elif schottky_diode.Semiconductor.dop_type == 'p':
        n = np.zeros_like(n)
    ax4.plot(z_nodes, n)
    for dopant in schottky_diode.Semiconductor.dopants:
        dopant_f = dopant.equilibrium_f(schottky_diode.T, schottky_diode.Semiconductor, fermi_level,
                                        electron_volts=False, debug=False)
        ax2.plot(z_nodes, dopant_f)
        df_dt, tau = dopant.df_dt(schottky_diode.T, schottky_diode.Semiconductor, dopants_f[dopant_name], n, p,
                                  barrier_lowering_e=None, barrier_lowering_h=None, use_mpmath=False, debug=False)
        capture_e, capture_h, capture_tau_e, capture_tau_h = dopant.capture_rate(schottky_diode.T,
                                                                                 schottky_diode.Semiconductor,
                                                                                 dopants_f[dopant_name],
                                                                                 n, p, debug=False)
        emission_e, emission_h, emission_tau_e, emission_tau_h = dopant.emission_rate(schottky_diode.T,
                                                                                      schottky_diode.Semiconductor,
                                                                                      dopants_f[dopant_name],
                                                                                      barrier_lowering_e=None,
                                                                                      barrier_lowering_h=None,
                                                                                      use_mpmath=False, debug=False)
        print 'electrons: capture tau = %2.2g s, emission tau = %2.2g s' % (min(capture_tau_e), min(emission_tau_e))
        print 'holes: capture tau = %2.2g s, emission tau = %2.2g s' % (min(capture_tau_h), min(emission_tau_h))
        print 'tau = %2.2g s' % tau
        #ax3.plot(z_nodes, emission_h - emission_e)
        ax3.plot(z_nodes, df_dt)
        #ax5.plot(z_nodes, capture_tau_e)
    plt.show()
예제 #5
0
MyDiode = SchottkyDiode(MyProject,
                        'Au-Si_BW',
                        Electrode,
                        Si,
                        DeadLayer=1.5e-7,
                        L=5e-6)
MyDiode.set_T(T)
MyDiode.set_Va(V_p)

type_sign = -1 if MyDiode.Semiconductor.dop_type == 'n' else 1
Psi = Psi_approx(MyDiode.L, -(MyDiode.V_bi(eV=True) + type_sign * V_p), 0.0)

Psi, E, z_nodes, rho_err_points, Vd, Vd_err, J, J_err, \
    BI_F, dopants_F, ic_id = Poisson.Reccurent_Poisson_solver(MyDiode, Psi, Vd_error=1e-6,
                                                              equilibrium_filling=True, t=mp.inf,
                                                              initial_condition_id=-1,
                                                              rho_rel_err=Poisson_rel_err, max_iter=100,
                                                              debug=False)
z_nodes = np.linspace(0, 3e-6, num=500, dtype=np.float)
_, (ax1, ax2) = plt.subplots(2, sharex=True)
Visual.BandsBendingDiagram(ax1,
                           MyDiode,
                           Psi,
                           Vd,
                           z_nodes,
                           BI_F,
                           dopants_F,
                           eV=True,
                           draw_metal=True,
                           label_bands=True,
                           fancy_ticks=False,
예제 #6
0
def traps_kinetics(schottky_diode, initial_condition_id, delta_t_min, delta_t_max, t_stop, fast_traps=None,
                   rho_rel_err=1e-1, df_threshold=1e-3, debug=False, debug_plot=False):
    t_points = []
    potential_t = []
    field_d = []
    z_t = []
    diode_voltage_drop_t = []
    current_density_t = []
    bonding_interfaces_f_t = []
    dopants_f_t = []

    ic_found, potential, z_nodes, _, _, _, _, _, _, _, _, _ = Poisson.load_diode_state(schottky_diode,
                                                                                       initial_condition_id,
                                                                                       debug=True)
    if not ic_found:
        raise(Exception('Initial condition not found. Please check everything'))

    if debug_plot:
        plt.ion()
        axes = Visual.prepare_debug_axes(['Potential', 'Dopants', 'Localized traps'])
        potential_lines = Visual.create_lines(axes['Potential'], ['Start potential', 'Current potential'])
        dopants_lines_names = [dopant.name + '_F' for dopant in schottky_diode.Semiconductor.dopants]
        localized_traps_lines_names = []
        for bi in schottky_diode.Semiconductor.bonding_interfaces:
            localized_traps_lines_names += [bi.label + '_tilt_' + trap[0].name + '_F' for trap in bi.dsl_tilt.traps]
            localized_traps_lines_names += [bi.label + '_twist_' + trap[0].name + '_F' for trap in bi.dsl_twist.traps]
        dopants_lines = Visual.create_lines(axes['Dopants'], dopants_lines_names)
        localized_traps_lines = Visual.create_lines(axes['Localized traps'], localized_traps_lines_names)

    t = 0
    last_state_id = initial_condition_id
    if fast_traps is None:
        fast_traps = []
    while t <= t_stop:
        print 't =', t
        potential, field, z_nodes, _, \
            diode_voltage_drop, _, current_density, _, \
            bonding_interface_f, dopants_f, \
            last_state_id = Poisson.Reccurent_Poisson_solver(schottky_diode, potential,
                                                             equilibrium_filling=False,
                                                             fast_traps=fast_traps,
                                                             t=t, initial_condition_id=last_state_id,
                                                             rho_rel_err=rho_rel_err, max_iter=100, debug=False)
        t_points.append(t)
        potential_t.append(potential)
        field_d.append(field)
        z_t.append(z_nodes)
        diode_voltage_drop_t.append(diode_voltage_drop)
        current_density_t.append(current_density)
        bonding_interfaces_f_t.append(bonding_interface_f)
        dopants_f_t.append(dopants_f)

        fermi_level = schottky_diode.EfEc(potential, z_nodes, eV=False)

        if debug_plot:
            if t == 0:
                potential_lines['Start potential'].set_data(z_nodes * 1e6, -potential(z_nodes))
            potential_lines['Current potential'].set_data(z_nodes * 1e6, -potential(z_nodes))

            for dopant_line_name in dopants_lines_names:
                dopants_lines[dopant_line_name].set_data(z_nodes * 1e6, dopants_f[dopant_line_name])

            for localized_trap_line_name in localized_traps_lines_names:
                localized_trap_f_t = []
                for bonding_interfaces_f_t_i in bonding_interfaces_f_t:
                    localized_trap_f_t.append(bonding_interfaces_f_t_i[localized_trap_line_name])
                localized_traps_lines[localized_trap_line_name].set_data(t_points, localized_trap_f_t)
            Visual.autoscale_axes(axes)
            plt.draw()

        dt = delta_t_max if t_stop - t > delta_t_max else t_stop - t
        if dt == 0:
            break
        if debug:
            print '\n\nT = %2.2f K, t = %2.2g s, dt = %2.2g s' % (schottky_diode.T, t, dt)

        n, p = schottky_diode.n_carriers_theory(potential, z_nodes)
        if schottky_diode.Semiconductor.dop_type == 'n':
            p = np.zeros_like(p)
        elif schottky_diode.Semiconductor.dop_type == 'p':
            n = np.zeros_like(n)

        #fast_traps = []

        dopants_skip_list = []
        df_dopants = {}
        for dopant in schottky_diode.Semiconductor.dopants:
            dopant_key = dopant.name + '_F'
            if dopant.name in fast_traps:
                if debug:
                    print 'This dopant is in a fast-traps list, skipping.'
                # dopant_f = dopant.equilibrium_f(schottky_diode.T, schottky_diode.Semiconductor, fermi_level,
                #                                 electron_volts=False, debug=False)
                # dopant.set_F_interp(z_nodes, dopant_f)
                # dopant.set_dF_interp(z_nodes, np.zeros_like(dopant_f))
                # fast_traps.append(dopant.name)
                dopants_skip_list.append(dopant_key)
                continue
            poole_frenkel_e = 1.0
            poole_frenkel_h = 1.0
            barrier_lowering_e = np.zeros_like(n, dtype=np.float)
            barrier_lowering_h = np.zeros_like(p, dtype=np.float)
            df_dt, tau = dopant.df_dt(schottky_diode.T, schottky_diode.Semiconductor, dopants_f[dopant_key], n, p,
                                      poole_frenkel_e=poole_frenkel_e,
                                      poole_frenkel_h=poole_frenkel_h,
                                      barrier_lowering_e=barrier_lowering_e,
                                      barrier_lowering_h=barrier_lowering_h,
                                      use_mpmath=False, debug=False)
            df_dopants[dopant_key] = df_dt
            max_dt = df_threshold / np.max(np.abs(df_dt))
            if debug:
                print '\nDopant:', dopant.name
                print 'time constant %2.2g s' % tau
                print 'Max dF:', np.max(np.abs(df_dt)), 'th:', df_threshold
                print 'Max dt:', max_dt, 'dt:', dt
            if dt > max_dt > delta_t_min:
                if debug:
                    print 'Setting dt to', max_dt
                dt = max_dt
            elif max_dt < delta_t_min:
                if debug:
                    print 'Traps are too fast. Setting dopant occupation to equilibrium value'
                dopant_f = dopant.equilibrium_f(schottky_diode.T, schottky_diode.Semiconductor, fermi_level,
                                                electron_volts=False, debug=False)
                dopant.set_F_interp(z_nodes, dopant_f)
                dopant.set_dF_interp(z_nodes, np.zeros_like(dopant_f))
                # fast_traps.append(dopant.name)
                dopants_skip_list.append(dopant_key)

        localized_traps_skip_list = []
        df_bonding_interfaces = {}
        for bi in schottky_diode.Semiconductor.bonding_interfaces:
            fermi_level_at_bi = schottky_diode.EfEc(potential, bi.depth, eV=False)
            electric_field_at_bi = field(bi.depth)
            n_bi, p_bi = schottky_diode.n_carriers_theory(potential, bi.depth)
            if schottky_diode.Semiconductor.dop_type == 'n':
                p_bi = 0.0
            elif schottky_diode.Semiconductor.dop_type == 'p':
                n_bi = 0.0
            if debug:
                print '\nBI:', bi.label
                print 'n_BI = %2.4g' % n_bi
                print 'p_BI = %2.4g' % p_bi

            bi_tilt_f = []
            for trap_idx, trap in enumerate(bi.dsl_tilt.traps):
                localized_trap_key = bi.label + '_tilt_' + trap[0].name + '_F'
                print 'BI Density of Charge = %2.2g cm-2' % (bi.density_of_charge / 1e4)
                print 'TILT F = %2.2f' % bi.dsl_tilt_f[trap_idx]
                dsl_charge_density = bi.dsl_tilt_f[trap_idx] * trap[1]
                print 'TILT Density of Charge = %2.2g cm-1' % (dsl_charge_density / 1e2)
                print 'EXT FIELD = %2.2g V*cm' % (electric_field_at_bi / 1e2)
                electric_field_at_bi_r = abs(electric_field_at_bi)
                electric_field_at_bi_theta = 0 if electric_field_at_bi >= 0 else np.pi
                electric_field_at_bi_3d = (electric_field_at_bi_r, electric_field_at_bi_theta, 0.0)
                trap[0].trap_potential.get_potential_by_name('Charged Dislocation').set_linear_charge_density(dsl_charge_density)
                trap[0].trap_potential.get_potential_by_name('External Field').external_field = electric_field_at_bi_3d

                kT = to_numeric(k * schottky_diode.T / q)
                theta = np.linspace(0, np.pi, num=100, endpoint=True)
                barrier_lowering = np.array([trap[0].trap_potential.barrier_lowering(theta_i) for theta_i in theta])
                poole_frenkel = 0.5 * np.trapz(np.sin(theta) * np.exp(abs(barrier_lowering[:, 0]) / kT), theta)
                poole_frenkel_e = 1.0
                poole_frenkel_h = 1.0
                if np.sum(barrier_lowering[:, 0]) < 0:
                    poole_frenkel_e = poole_frenkel
                    print 'emission boost e: %2.4g' % poole_frenkel
                elif np.sum(barrier_lowering[:, 0]) > 0:
                    poole_frenkel_h = poole_frenkel
                    print 'emission boost h: %2.4g' % poole_frenkel
                barrier_lowering_e = 0.0
                barrier_lowering_h = 0.0
                df_dt, tau = trap[0].df_dt(schottky_diode.T, schottky_diode.Semiconductor,
                                           bonding_interface_f[localized_trap_key], n_bi, p_bi,
                                           poole_frenkel_e=poole_frenkel_e,
                                           poole_frenkel_h=poole_frenkel_h,
                                           barrier_lowering_e=barrier_lowering_e,
                                           barrier_lowering_h=barrier_lowering_h,
                                           use_mpmath=False, debug=False)
                df_bonding_interfaces[localized_trap_key] = df_dt
                try:
                    max_dt = df_threshold / abs(df_dt)
                except ZeroDivisionError:
                    max_dt = 1e250
                if debug:
                    print '\nTrap:', trap[0].name
                    print 'time constant %2.2g s' % tau
                    print 'dF: %2.4g, th: %2.2f'% (df_dt, df_threshold)
                    print 'Max dt:', max_dt, 'dt:', dt
                if dt > max_dt > delta_t_min:
                    if debug:
                        print 'Setting dt to', max_dt
                    dt = max_dt
                elif max_dt < delta_t_min:
                    if dt > 10 * max_dt:
                        if debug:
                            print 'Trap is too fast. Setting trap occupation to equilibrium value'
                        bonding_interface_f[localized_trap_key] = trap[0].equilibrium_f(schottky_diode.T,
                                                                                        schottky_diode.Semiconductor,
                                                                                        fermi_level_at_bi,
                                                                                        electron_volts=False, debug=False)
                        localized_traps_skip_list.append(localized_trap_key)
                    else:
                        if debug:
                            print 'Setting dt to', max_dt
                        dt = max_dt
                        # fast_traps.append(bi.label + '_tilt_' + trap[0].name)
                bi_tilt_f.append(bonding_interface_f[localized_trap_key])
            bi_twist_f = []
            for trap in bi.dsl_twist.traps:
                localized_trap_key = bi.label + '_twist_' + trap[0].name + '_F'
                trap[0].trap_potential.get_potential_by_name('External Field').external_field = electric_field_at_bi
                print 'EXT FIELD = %2.2g V*cm' % (electric_field_at_bi / 1e2)
                print trap[0].trap_potential.barrier_lowering()
                barrier_lowering_e = 0.0
                barrier_lowering_h = 0.0
                df_dt, tau = trap[0].df_dt(schottky_diode.T, schottky_diode.Semiconductor,
                                           bonding_interface_f[localized_trap_key], n_bi, p_bi,
                                           barrier_lowering_e=barrier_lowering_e,
                                           barrier_lowering_h=barrier_lowering_h,
                                           use_mpmath=False, debug=False)
                df_bonding_interfaces[localized_trap_key] = df_dt
                try:
                    max_dt = df_threshold / abs(df_dt)
                except ZeroDivisionError:
                    max_dt = 1e250
                if debug:
                    print '\nTrap:', trap[0].name
                    print 'time constant %2.2g s' % tau
                    print 'dF: %2.4g, th: %2.2f'% (df_dt, df_threshold)
                    print 'Max dt:', max_dt, 'dt:', dt
                if dt > max_dt > delta_t_min:
                    if debug:
                        print 'Setting dt to', max_dt
                    dt = max_dt
                elif max_dt < delta_t_min:
                    if dt > 10 * max_dt:
                        if debug:
                            print 'Trap is too fast. Setting trap occupation to equilibrium value'
                        bonding_interface_f[localized_trap_key] = trap[0].equilibrium_f(schottky_diode.T,
                                                                                        schottky_diode.Semiconductor,
                                                                                        fermi_level,
                                                                                        electron_volts=False, debug=False)
                        localized_traps_skip_list.append(localized_trap_key)
                    else:
                        if debug:
                            print 'Setting dt to', max_dt
                        dt = max_dt
                    # fast_traps.append(bi.label + '_twist_' + trap[0].name)
                bi_twist_f.append(bonding_interface_f[localized_trap_key])
            bi.set_traps_f(np.array(bi_tilt_f), np.array(bi_twist_f))
            bi.set_traps_df(np.zeros(len(bi_tilt_f)), np.zeros(len(bi_twist_f)))
        dt = np.float(dt)

        for dopant in schottky_diode.Semiconductor.dopants:
            dopant_key = dopant.name + '_F'
            if dopant_key in dopants_skip_list:
                if debug:
                    print 'Dopant', dopant_key, 'does not need an update'
                continue
            dopants_f[dopant_key] += df_dopants[dopant_key] * dt
            dopants_f[dopant_key][np.where(dopants_f[dopant_key] > 1.0)] = 1.0
            dopants_f[dopant_key][np.where(dopants_f[dopant_key] < 0.0)] = 0.0
            dopant.set_F_interp(z_nodes, dopants_f[dopant_key])
            dopant.set_dF_interp(z_nodes, np.zeros_like(dopants_f[dopant_key]))

        for bi in schottky_diode.Semiconductor.bonding_interfaces:
            bi_tilt_f = []
            for trap in bi.dsl_tilt.traps:
                localized_trap_key = bi.label + '_tilt_' + trap[0].name + '_F'
                if localized_trap_key not in localized_traps_skip_list:
                    bonding_interface_f[localized_trap_key] += df_bonding_interfaces[localized_trap_key] * dt
                    if bonding_interface_f[localized_trap_key] > 1:
                        bonding_interface_f[localized_trap_key] = 1
                    elif bonding_interface_f[localized_trap_key] < 0:
                        bonding_interface_f[localized_trap_key] = 0
                if debug:
                    print 'F:', bonding_interface_f[localized_trap_key]
                bi_tilt_f.append(bonding_interface_f[localized_trap_key])
            bi_twist_f = []
            for trap in bi.dsl_twist.traps:
                localized_trap_key = bi.label + '_twist_' + trap[0].name + '_F'
                if localized_trap_key not in localized_traps_skip_list:
                    bonding_interface_f[localized_trap_key] += df_bonding_interfaces[localized_trap_key] * dt
                    if bonding_interface_f[localized_trap_key] > 1:
                        bonding_interface_f[localized_trap_key] = 1
                    elif bonding_interface_f[localized_trap_key] < 0:
                        bonding_interface_f[localized_trap_key] = 0
                if debug:
                    print 'F:', bonding_interface_f[localized_trap_key]
                bi_twist_f.append(bonding_interface_f[localized_trap_key])
            bi.set_traps_f(np.array(bi_tilt_f), np.array(bi_twist_f))
            bi.set_traps_df(np.zeros(len(bi_tilt_f)), np.zeros(len(bi_twist_f)))
        t += dt

    if debug_plot:
        plt.ioff()

    return t_points, potential_t, field_d, z_t, diode_voltage_drop_t, current_density_t, \
        bonding_interfaces_f_t, dopants_f_t, last_state_id
예제 #7
0
def calculate_for_temperature(args):
    silicon, electrode, temperature, voltage_range = args
    print temperature
    db_name = prefix + '_dc_%03.2fK.db' % temperature
    db_name = join(data_dir, db_name)
    project = Project(db_name=db_name,
                      backend='sqlite',
                      hostname='',
                      overwrite=False)
    diode = SchottkyDiode(project,
                          'Au-nSi_BW',
                          electrode,
                          silicon,
                          DeadLayer=1.5e-7,
                          L=5e-6)
    diode.set_T(temperature)
    potential = []
    field = []
    diode_voltage = []
    diode_voltage_error = []
    current_density = []
    current_density_error = []
    bonding_interface_f = {}
    dopants_f_sum = {}
    z = []
    dopants_f = []
    for voltage in voltage_range:
        diode.set_Va(voltage)
        type_sign = -1 if silicon.dop_type == 'n' else 1
        potential_i = Psi_approx(diode.L,
                                 -(diode.V_bi(eV=True) + type_sign * voltage),
                                 0.0)
        potential_i, field_i, z_nodes, rho_err_points, \
            diode_voltage_i, diode_voltage_error_i, \
            current_density_i, current_density_error_i, \
            bonding_interface_f_i, dopants_f_i, \
            measurement_id = Poisson.Reccurent_Poisson_solver(diode, potential_i, Vd_error=1e-6,
                                                              equilibrium_filling=True, t=mp.inf,
                                                              initial_condition_id=-1,
                                                              rho_rel_err=poisson_relative_error, max_iter=100,
                                                              debug=False)
        potential.append(potential_i)
        field.append(field_i)
        diode_voltage.append(diode_voltage_i)
        diode_voltage_error.append(diode_voltage_error_i)
        current_density.append(current_density_i)
        current_density_error.append(current_density_i)
        z.append(z_nodes)
        dopants_f.append(dopants_f_i)
        for trap_key in bonding_interface_f_i.keys():
            try:
                bonding_interface_f[trap_key].append(
                    bonding_interface_f_i[trap_key])
            except KeyError:
                bonding_interface_f[trap_key] = [
                    bonding_interface_f_i[trap_key]
                ]
        for dopant_key in dopants_f_i.keys():
            try:
                dopants_f_sum[dopant_key].append(
                    np.sum(dopants_f_i[dopant_key]))
            except KeyError:
                dopants_f_sum[dopant_key] = [np.sum(dopants_f_i[dopant_key])]

    data = {
        temperature: {
            'applied_voltage': voltage_range,
            'diode_voltage': diode_voltage,
            'diode_voltage_error': diode_voltage_error,
            'current_density': current_density,
            'current_density_error': current_density_error
        }
    }
    for trap_key in bonding_interface_f.keys():
        data[temperature][trap_key] = bonding_interface_f[trap_key]
    for dopant_key in dopants_f_sum.keys():
        data[temperature][dopant_key + '_sum'] = dopants_f_sum[dopant_key]
    return potential, field, data, z, dopants_f
예제 #8
0
def traps_kinetics(schottky_diode,
                   initial_condition_id,
                   delta_t_min,
                   delta_t_max,
                   t_stop,
                   fast_traps=None,
                   rho_rel_err=1e-1,
                   df_threshold=1e-3,
                   min_t_points=50,
                   dopants_deriv_threshold=5.0e-5,
                   dopants_deriv_window=9,
                   dopants_deriv_z_limit=None,
                   save_to_db=True,
                   potential=None,
                   debug=False,
                   debug_plot=False):
    if dopants_deriv_z_limit is None:
        dopants_deriv_z_limit = 1e8
    z_limit_f = 1e8
    dopants_f_total = {}
    t_points = []
    potential_t = []
    field_d = []
    z_t = []
    diode_voltage_drop_t = []
    current_density_t = []
    bonding_interfaces_f_t = []
    dopants_f_t = []
    n_t = []
    p_t = []

    if save_to_db:
        ic_found, potential, _, z_nodes, _, _, _, _, _, _, _, _ = Poisson.load_diode_state(
            schottky_diode, initial_condition_id, debug=True)
        if not ic_found:
            raise (Exception(
                'Initial condition not found. Please check everything'))

    if debug_plot:
        plt.ion()
        axes = Visual.prepare_debug_axes(
            ['Potential', 'Dopants', 'Localized traps'])
        potential_lines = Visual.create_lines(
            axes['Potential'], ['Start potential', 'Current potential'])
        dopants_lines_names = [
            dopant.name + '_F'
            for dopant in schottky_diode.Semiconductor.dopants
        ]
        localized_traps_lines_names = []
        for bi in schottky_diode.Semiconductor.bonding_interfaces:
            localized_traps_lines_names += [
                bi.label + '_tilt_' + trap[0].name + '_F'
                for trap in bi.dsl_tilt.traps
            ]
            localized_traps_lines_names += [
                bi.label + '_twist_' + trap[0].name + '_F'
                for trap in bi.dsl_twist.traps
            ]
        dopants_lines = Visual.create_lines(axes['Dopants'],
                                            dopants_lines_names)
        localized_traps_lines = Visual.create_lines(
            axes['Localized traps'], localized_traps_lines_names)

    t = 0
    last_state_id = initial_condition_id
    if fast_traps is None:
        fast_traps = []
    slow_traps = {}
    while t <= t_stop:
        print '\n\nt =', t
        potential, field, z_nodes, _, \
            diode_voltage_drop, _, current_density, _, \
            bonding_interface_f, dopants_f, \
            last_state_id = Poisson.Reccurent_Poisson_solver(schottky_diode, potential,
                                                             equilibrium_filling=False,
                                                             fast_traps=fast_traps,
                                                             t=t, initial_condition_id=last_state_id,
                                                             rho_rel_err=rho_rel_err, max_iter=100,
                                                             save_to_db=save_to_db, debug=False)

        t_points.append(t)
        potential_t.append(potential)
        field_d.append(field)
        z_t.append(z_nodes)
        diode_voltage_drop_t.append(diode_voltage_drop)
        current_density_t.append(current_density)
        bonding_interfaces_f_t.append(bonding_interface_f.copy())
        dopants_f_t.append(dopants_f.copy())

        fermi_level = schottky_diode.EfEc(potential, z_nodes, eV=False)

        n, p = schottky_diode.n_carriers_theory(potential, z_nodes)
        if schottky_diode.Semiconductor.dop_type == 'n':
            p = np.zeros_like(p)
        elif schottky_diode.Semiconductor.dop_type == 'p':
            n = np.zeros_like(n)
        n_t.append(n.copy())
        p_t.append(p.copy())

        if debug_plot:
            if t == 0:
                potential_lines['Start potential'].set_data(
                    z_nodes * 1e6, -potential(z_nodes))
            potential_lines['Current potential'].set_data(
                z_nodes * 1e6, -potential(z_nodes))

            for dopant_line_name in dopants_lines_names:
                dopants_lines[dopant_line_name].set_data(
                    z_nodes * 1e6, dopants_f[dopant_line_name])

            for localized_trap_line_name in localized_traps_lines_names:
                localized_trap_f_t = []
                for bonding_interfaces_f_t_i in bonding_interfaces_f_t:
                    localized_trap_f_t.append(
                        bonding_interfaces_f_t_i[localized_trap_line_name])
                localized_traps_lines[localized_trap_line_name].set_data(
                    t_points, localized_trap_f_t)
            Visual.autoscale_axes(axes)
            plt.draw()

        dt = delta_t_max if t_stop - t > delta_t_max else t_stop - t
        if dt == 0:
            for dopant in schottky_diode.Semiconductor.dopants:
                dopant_key = dopant.name + '_F'
                dopants_f_t[-1].update(
                    {dopant_key + '_pf': np.ones_like(z_nodes)})
                dopants_f_t[-1].update(
                    {dopant_key + '_df': np.zeros_like(z_nodes)})
            break
        if debug:
            print '\n\nT = %2.2f K, t = %2.2g s, dt = %2.2g s' % (
                schottky_diode.T, t, dt)

        #fast_traps = []
        dopants_skip_list = []
        df_dopants = {}
        for dopant in schottky_diode.Semiconductor.dopants:
            dopant_key = dopant.name + '_F'
            dopants_deriv_z_limit_idx = np.where(
                z_nodes < dopants_deriv_z_limit)
            if t == 0:
                dopants_f_total[dopant_key] = [
                    np.trapz(
                        dopants_f_t[0][dopant_key][dopants_deriv_z_limit_idx],
                        x=z_nodes[dopants_deriv_z_limit_idx])
                ]
            else:
                dopants_f_total[dopant_key].append(
                    np.trapz(
                        dopants_f_t[-1][dopant_key][dopants_deriv_z_limit_idx],
                        x=z_nodes[dopants_deriv_z_limit_idx]))
            print 'Total Donor charge %2.2g' % dopants_f_total[dopant_key][-1]
            if t > 0:
                loc_der = (dopants_f_total[dopant_key][-1] - dopants_f_total[dopant_key][-2]) \
                          / (t_points[-1] - t_points[-2]) / dopants_f_total[dopant_key][0]
                print 'local derivative %2.2g%%' % (loc_der * 100)
            if dopant.name in fast_traps:
                if debug:
                    print '\nDopant:', dopant.name
                    print 'This dopant is in a fast-traps list, skipping.'
                dopants_skip_list.append(dopant_key)
                continue
            if dopant.name in slow_traps.keys():
                if debug:
                    print '\nDopant:', dopant.name
                    print 'This dopant is in a slow-traps list, skipping.'
                df_dt = np.zeros_like(z_nodes)
                for wp in range(dopants_deriv_window):
                    df_dt[dopants_deriv_z_limit_idx] += dopants_f_t[-wp - 2][
                        dopant_key + '_df'][dopants_deriv_z_limit_idx]
                df_dt /= dopants_deriv_window
                dopants_f_t[-1].update({dopant_key + '_df': df_dt})
                df_dopants[dopant_key] = df_dt
                #dopants_skip_list.append(dopant_key)
                continue
            poole_frenkel_e = np.ones_like(z_nodes, dtype=np.float)
            poole_frenkel_h = np.ones_like(z_nodes, dtype=np.float)
            barrier_lowering_e = np.zeros_like(n, dtype=np.float)
            barrier_lowering_h = np.zeros_like(p, dtype=np.float)
            field_z = field(z_nodes)

            if dopant.trap_potential.get_potential_by_name(
                    'Charged Dislocation') is not None:
                kT = to_numeric(k * schottky_diode.T / q)
                theta_points = 90
                theta = np.linspace(0, np.pi, num=theta_points, endpoint=True)
                #theta = np.linspace(0, np.pi / 2, num=theta_points, endpoint=True)
                barrier_lowering = np.zeros((theta_points, len(z_nodes)),
                                            dtype=np.float)
                max_N_l = dopant.trap_potential.get_potential_by_name('Charged Dislocation')\
                        .max_linear_charge_density
                dsl_charge_density = max_N_l * dopant.F(z_nodes)
                for z_num, local_electric_field in enumerate(field_z):
                    #print z_num, 'of', len(z_nodes)
                    #dsl_charge_density = max_N_l * dopant.F(z_nodes[z_num])
                    local_electric_field_r = abs(local_electric_field)
                    local_electric_field_theta = 0 if local_electric_field >= 0 else np.pi
                    local_electric_field_3d = (local_electric_field_r,
                                               local_electric_field_theta, 0.0)
                    dopant.trap_potential.get_potential_by_name('Charged Dislocation')\
                        .set_linear_charge_density(dsl_charge_density[z_num])
                    dopant.trap_potential.get_potential_by_name('External Field')\
                        .external_field = local_electric_field_3d

                    loc_f = local_electric_field_r
                    loc_a = dopant.trap_potential.get_potential_by_name(
                        'Charged Dislocation').a
                    loc_b = -dopant.trap_potential.get_potential_by_name(
                        'Deformation').a
                    r0 = np.zeros_like(theta)
                    if loc_f < 1.0e-5:
                        if z_nodes[z_num] < z_limit_f:
                            z_limit_f = z_nodes[z_num]
                        #print 'here', loc_f, z_nodes[z_num]*1e6
                        try:
                            r0[:] = loc_b / loc_a
                        except FloatingPointError:
                            pass
                        #print len(r0), r0
                    else:
                        determinant = loc_a**2 + 4 * loc_b * loc_f * np.cos(
                            theta)
                        idx = np.where(determinant >= 0)
                        sqrt = np.sqrt(loc_a**2 +
                                       4 * loc_b * loc_f * np.cos(theta[idx]))
                        sol1 = (-loc_a - sqrt) / (2 * loc_f *
                                                  np.cos(theta[idx]))
                        sol2 = (-loc_a + sqrt) / (2 * loc_f *
                                                  np.cos(theta[idx]))
                        sol1[np.where(sol1 < 0.0)] = 0.0
                        #sol2[np.where(sol2 < 0.0)] = 0.0
                        sol = sol1.copy()
                        #sol2_selection = np.where(sol2 > 0)
                        sol2_selection = np.where((sol2 > 0) & (sol2 < sol1))
                        sol[sol2_selection] = sol2[sol2_selection]
                        sol2_selection = np.where((sol2 > 0) & (sol1 <= 0))
                        sol[sol2_selection] = sol2[sol2_selection]
                        r0[idx] = sol
                        #idx = np.where(r0 < loc_b / loc_a / 3)
                        #r0[idx] = loc_b / loc_a
                        zero_theta_idx = np.where(
                            abs(loc_f * np.cos(theta)) < 1.0e-5)
                        try:
                            r0[zero_theta_idx] = loc_b / loc_a
                        except FloatingPointError:
                            r0[zero_theta_idx] = 0.0
                    non_zero_r_idx = np.where(r0 > 0.0)
                    bl_grid = dopant.trap_potential.potential(
                        r0[non_zero_r_idx], theta[non_zero_r_idx], 0)
                    #np.save('./bl_grid_'+str(z_nodes[z_num]*1e6)+'_'+str(t), bl_grid)
                    #print np.rad2deg(theta[non_zero_r_idx])
                    #print bl_grid[0,:,0].shape, theta.shape
                    #print bl_grid[0,:,0]
                    bl_flat = np.zeros_like(theta)
                    try:
                        bl_flat[non_zero_r_idx] = bl_grid[0, :, 0]
                    except IndexError:
                        pass
                    #print kT
                    #print bl_flat
                    #barrier_lowering[:,z_num] = np.array([dopant.trap_potential.barrier_lowering(theta_i)[0] for theta_i in theta])
                    barrier_lowering[:, z_num] = bl_flat
                    #print barrier_lowering[:, z_num]
                    #print bl_flat - barrier_lowering[:, z_num]
                    #poole_frenkel = 0.5 * np.trapz(np.sin(theta) * np.exp(abs(barrier_lowering[:, 0]) / kT), theta)
                #poole_frenkel = 0.5 * np.trapz(np.exp(abs(barrier_lowering) / kT), theta, axis=0)
                #poole_frenkel = 0.5 + np.trapz(np.exp(abs(barrier_lowering) / kT), theta, axis=0) / np.pi
                poole_frenkel = np.trapz(
                    np.exp(abs(barrier_lowering) / kT), theta, axis=0) / np.pi
                #print poole_frenkel
                if np.sum(barrier_lowering[:, 0]) < 0:
                    poole_frenkel_e = poole_frenkel
                    #print 'emission boost e:', poole_frenkel
                elif np.sum(barrier_lowering[:, 0]) > 0:
                    poole_frenkel_h = poole_frenkel
                    #print 'emission boost h:', poole_frenkel

            try:
                dopants_f_t[-1].update({dopant_key + '_pf': poole_frenkel})
            except:
                dopants_f_t[-1].update(
                    {dopant_key + '_pf': np.ones_like(z_nodes)})

            df_dt, tau = dopant.df_dt(schottky_diode.T,
                                      schottky_diode.Semiconductor,
                                      dopants_f[dopant_key],
                                      n,
                                      p,
                                      poole_frenkel_e=poole_frenkel_e,
                                      poole_frenkel_h=poole_frenkel_h,
                                      barrier_lowering_e=barrier_lowering_e,
                                      barrier_lowering_h=barrier_lowering_h,
                                      use_mpmath=False,
                                      debug=False)
            z_limit_f_idx = np.where(z_nodes < z_limit_f)
            z_limit_f_idx0 = np.where(z_t[0] < z_limit_f)
            dopants_f_t[-1].update({dopant_key + '_df': df_dt})
            df_dopants[dopant_key] = df_dt
            #print df_dt
            df_total = np.sum(df_dt[z_limit_f_idx]) / np.sum(
                dopants_f_t[0][dopant_key][z_limit_f_idx0])
            max_dt_local = df_threshold / np.max(np.abs(df_dt))
            max_dt_total = df_threshold / np.max(np.abs(df_total))
            max_dt = min(max_dt_local, max_dt_total)
            if debug:
                print '\nDopant:', dopant.name
                print 'Z limit of %2.2g m: left %d points of %d' % (
                    z_limit_f, len(z_nodes[z_limit_f_idx]), len(z_nodes))
                print 'Min time constant %2.2g s' % tau
                print 'Max dF local:', np.max(
                    np.abs(df_dt)), 'th:', df_threshold
                print 'Max dF total:', np.max(
                    np.abs(df_total)), 'th:', df_threshold
                print 'Max dt:', max_dt, 'dt:', dt
            if len(t_points) > dopants_deriv_window:
                deriv = np.array(dopants_f_total[dopant_key][-dopants_deriv_window + 1:]) \
                        - np.array(dopants_f_total[dopant_key][-dopants_deriv_window:-1])
                deriv /= dopants_f_total[dopant_key][0]
                deriv /= np.array(
                    t_points[-dopants_deriv_window + 1:]) - np.array(
                        t_points[-dopants_deriv_window:-1])
                deriv = np.average(deriv)
                if debug:
                    print 'Dopants derivative: %2.2g%%' % (deriv * 100)
                    print 'Derivative threshold: %2.2g%%' % (
                        dopants_deriv_threshold * 100)
            else:
                deriv = 1e8
            if abs(deriv) < dopants_deriv_threshold and len(
                    t_points) >= min_t_points:
                if debug:
                    print 'Traps are all set. Adding dopant to slow traps.'
                slow_traps[dopant.name] = deriv
            if dt > max_dt > delta_t_min:
                if debug:
                    print 'Setting dt to', max_dt
                dt = max_dt
            elif max_dt < delta_t_min:
                if debug:
                    print 'Traps are too fast. Setting dopant occupation to equilibrium value'
                dopant_f = dopant.equilibrium_f(schottky_diode.T,
                                                schottky_diode.Semiconductor,
                                                fermi_level,
                                                electron_volts=False,
                                                debug=False)
                dopant.set_F_interp(z_nodes, dopant_f)
                dopant.set_dF_interp(z_nodes, np.zeros_like(dopant_f))
                fast_traps.append(dopant.name)
                dopants_skip_list.append(dopant_key)

        localized_traps_skip_list = []
        df_bonding_interfaces = {}
        for bi in schottky_diode.Semiconductor.bonding_interfaces:
            fermi_level_at_bi = schottky_diode.EfEc(potential,
                                                    bi.depth,
                                                    eV=False)
            electric_field_at_bi = field(bi.depth)
            n_bi, p_bi = schottky_diode.n_carriers_theory(potential, bi.depth)
            if schottky_diode.Semiconductor.dop_type == 'n':
                p_bi = 0.0
            elif schottky_diode.Semiconductor.dop_type == 'p':
                n_bi = 0.0
            if debug:
                print '\nBI:', bi.label
                print 'n_BI = %2.4g' % n_bi
                print 'p_BI = %2.4g' % p_bi

            bi_tilt_f = []
            for trap_idx, trap in enumerate(bi.dsl_tilt.traps):
                localized_trap_key = bi.label + '_tilt_' + trap[0].name + '_F'
                print 'BI Density of Charge = %2.2g cm-2' % (
                    bi.density_of_charge / 1e4)
                print 'TILT F = %2.2f' % bi.dsl_tilt_f[trap_idx]
                dsl_charge_density = bi.dsl_tilt_f[trap_idx] * trap[1]
                print 'TILT Density of Charge = %2.2g cm-1' % (
                    dsl_charge_density / 1e2)
                print 'EXT FIELD = %2.2g V*cm' % (electric_field_at_bi / 1e2)
                electric_field_at_bi_r = abs(electric_field_at_bi)
                electric_field_at_bi_theta = 0 if electric_field_at_bi >= 0 else np.pi
                electric_field_at_bi_3d = (electric_field_at_bi_r,
                                           electric_field_at_bi_theta, 0.0)
                trap[0].trap_potential.get_potential_by_name(
                    'Charged Dislocation').set_linear_charge_density(
                        dsl_charge_density)
                trap[0].trap_potential.get_potential_by_name(
                    'External Field').external_field = electric_field_at_bi_3d

                kT = to_numeric(k * schottky_diode.T / q)
                theta = np.linspace(0, np.pi, num=100, endpoint=True)
                barrier_lowering = np.array([
                    trap[0].trap_potential.barrier_lowering(theta_i)
                    for theta_i in theta
                ])
                poole_frenkel = 0.5 * np.trapz(
                    np.sin(theta) * np.exp(abs(barrier_lowering[:, 0]) / kT),
                    theta)
                poole_frenkel_e = 1.0
                poole_frenkel_h = 1.0
                if np.sum(barrier_lowering[:, 0]) < 0:
                    poole_frenkel_e = poole_frenkel
                    print 'emission boost e: %2.4g' % poole_frenkel
                elif np.sum(barrier_lowering[:, 0]) > 0:
                    poole_frenkel_h = poole_frenkel
                    print 'emission boost h: %2.4g' % poole_frenkel
                barrier_lowering_e = 0.0
                barrier_lowering_h = 0.0
                df_dt, tau = trap[0].df_dt(
                    schottky_diode.T,
                    schottky_diode.Semiconductor,
                    bonding_interface_f[localized_trap_key],
                    n_bi,
                    p_bi,
                    poole_frenkel_e=poole_frenkel_e,
                    poole_frenkel_h=poole_frenkel_h,
                    barrier_lowering_e=barrier_lowering_e,
                    barrier_lowering_h=barrier_lowering_h,
                    use_mpmath=False,
                    debug=False)
                df_bonding_interfaces[localized_trap_key] = df_dt
                try:
                    max_dt = df_threshold / abs(df_dt)
                except ZeroDivisionError:
                    max_dt = 1e250
                if debug:
                    print '\nTrap:', trap[0].name
                    print 'time constant %2.2g s' % tau
                    print 'dF: %2.4g, th: %2.2f' % (df_dt, df_threshold)
                    print 'Max dt:', max_dt, 'dt:', dt
                if dt > max_dt > delta_t_min:
                    if debug:
                        print 'Setting dt to', max_dt
                    dt = max_dt
                elif max_dt < delta_t_min:
                    if dt > 10 * max_dt:
                        if debug:
                            print 'Trap is too fast. Setting trap occupation to equilibrium value'
                        bonding_interface_f[localized_trap_key] = trap[
                            0].equilibrium_f(schottky_diode.T,
                                             schottky_diode.Semiconductor,
                                             fermi_level_at_bi,
                                             electron_volts=False,
                                             debug=False)
                        localized_traps_skip_list.append(localized_trap_key)
                    else:
                        if debug:
                            print 'Setting dt to', max_dt
                        dt = max_dt
                        # fast_traps.append(bi.label + '_tilt_' + trap[0].name)
                bi_tilt_f.append(bonding_interface_f[localized_trap_key])
            bi_twist_f = []
            for trap in bi.dsl_twist.traps:
                localized_trap_key = bi.label + '_twist_' + trap[0].name + '_F'
                trap[0].trap_potential.get_potential_by_name(
                    'External Field').external_field = electric_field_at_bi
                print 'EXT FIELD = %2.2g V*cm' % (electric_field_at_bi / 1e2)
                print trap[0].trap_potential.barrier_lowering()
                barrier_lowering_e = 0.0
                barrier_lowering_h = 0.0
                df_dt, tau = trap[0].df_dt(
                    schottky_diode.T,
                    schottky_diode.Semiconductor,
                    bonding_interface_f[localized_trap_key],
                    n_bi,
                    p_bi,
                    barrier_lowering_e=barrier_lowering_e,
                    barrier_lowering_h=barrier_lowering_h,
                    use_mpmath=False,
                    debug=False)
                df_bonding_interfaces[localized_trap_key] = df_dt
                try:
                    max_dt = df_threshold / abs(df_dt)
                except ZeroDivisionError:
                    max_dt = 1e250
                if debug:
                    print '\nTrap:', trap[0].name
                    print 'time constant %2.2g s' % tau
                    print 'dF: %2.4g, th: %2.2f' % (df_dt, df_threshold)
                    print 'Max dt:', max_dt, 'dt:', dt
                if dt > max_dt > delta_t_min:
                    if debug:
                        print 'Setting dt to', max_dt
                    dt = max_dt
                elif max_dt < delta_t_min:
                    if dt > 10 * max_dt:
                        if debug:
                            print 'Trap is too fast. Setting trap occupation to equilibrium value'
                        bonding_interface_f[localized_trap_key] = trap[
                            0].equilibrium_f(schottky_diode.T,
                                             schottky_diode.Semiconductor,
                                             fermi_level,
                                             electron_volts=False,
                                             debug=False)
                        localized_traps_skip_list.append(localized_trap_key)
                    else:
                        if debug:
                            print 'Setting dt to', max_dt
                        dt = max_dt
                    # fast_traps.append(bi.label + '_twist_' + trap[0].name)
                bi_twist_f.append(bonding_interface_f[localized_trap_key])
            bi.set_traps_f(np.array(bi_tilt_f), np.array(bi_twist_f))
            bi.set_traps_df(np.zeros(len(bi_tilt_f)),
                            np.zeros(len(bi_twist_f)))
        dt = np.float(dt)

        for dopant in schottky_diode.Semiconductor.dopants:
            dopant_key = dopant.name + '_F'
            if dopant_key in dopants_skip_list:
                if debug:
                    print '\nDopant', dopant.name, 'does not need an update'
                continue
            dopants_f_corr = dopants_f[dopant_key] + df_dopants[dopant_key] * dt
            dopants_f_corr[np.where(dopants_f_corr > 1.0)] = 1.0
            dopants_f_corr[np.where(dopants_f_corr < 0.0)] = 0.0
            dopants_f_corr[np.where(
                z_nodes >= z_limit_f)] = dopants_f_corr[z_limit_f_idx][-1]
            dopant.set_F_interp(z_nodes, dopants_f_corr)
            dopant.set_dF_interp(z_nodes, np.zeros_like(dopants_f_corr))

        for bi in schottky_diode.Semiconductor.bonding_interfaces:
            bi_tilt_f = []
            for trap in bi.dsl_tilt.traps:
                localized_trap_key = bi.label + '_tilt_' + trap[0].name + '_F'
                if localized_trap_key not in localized_traps_skip_list:
                    bonding_interface_f[
                        localized_trap_key] += df_bonding_interfaces[
                            localized_trap_key] * dt
                    if bonding_interface_f[localized_trap_key] > 1:
                        bonding_interface_f[localized_trap_key] = 1
                    elif bonding_interface_f[localized_trap_key] < 0:
                        bonding_interface_f[localized_trap_key] = 0
                if debug:
                    print 'F:', bonding_interface_f[localized_trap_key]
                bi_tilt_f.append(bonding_interface_f[localized_trap_key])
            bi_twist_f = []
            for trap in bi.dsl_twist.traps:
                localized_trap_key = bi.label + '_twist_' + trap[0].name + '_F'
                if localized_trap_key not in localized_traps_skip_list:
                    bonding_interface_f[
                        localized_trap_key] += df_bonding_interfaces[
                            localized_trap_key] * dt
                    if bonding_interface_f[localized_trap_key] > 1:
                        bonding_interface_f[localized_trap_key] = 1
                    elif bonding_interface_f[localized_trap_key] < 0:
                        bonding_interface_f[localized_trap_key] = 0
                if debug:
                    print 'F:', bonding_interface_f[localized_trap_key]
                bi_twist_f.append(bonding_interface_f[localized_trap_key])
            bi.set_traps_f(np.array(bi_tilt_f), np.array(bi_twist_f))
            bi.set_traps_df(np.zeros(len(bi_tilt_f)),
                            np.zeros(len(bi_twist_f)))
        t += dt

    if debug_plot:
        plt.ioff()

    return t_points, potential_t, field_d, z_t, diode_voltage_drop_t, current_density_t, \
        bonding_interfaces_f_t, dopants_f_t, n_t, p_t, last_state_id