def load_diode_state(SchDiode, measurement_id, initial_condition_id=-1, debug=False): point_names_long = gen_point_names_Electric_Field_measurement(SchDiode) if debug: print '==> Looking for saved solution in the database' points_names = [point_names_long['z'][0], point_names_long['Psi'][0], point_names_long['E'][0], point_names_long['Vd'][0], point_names_long['Vd_err'][0], point_names_long['J'][0], point_names_long['J_err'][0], point_names_long['rho_rel_err'][0], point_names_long['ic_id'][0]] for BI in SchDiode.Semiconductor.bonding_interfaces: for trap in BI.dsl_tilt.traps: points_names.append(point_names_long[BI.label + '_tilt_' + trap[0].name + '_F'][0]) for trap in BI.dsl_twist.traps: points_names.append(point_names_long[BI.label + '_twist_' + trap[0].name + '_F'][0]) for dopant in SchDiode.Semiconductor.dopants: points_names.append(point_names_long[dopant.name + '_F'][0]) try: data = SchDiode.Project.get_data_points_by_names(measurement_id, points_names) except: if debug: print '==> No solutions found' return False, Psi_zero, Psi_zero, np.zeros(1), np.zeros(1), 0, 0, 0, 0, {}, {}, measurement_id z_nodes = data[points_names[0]][:, 0] Psi_points = data[points_names[1]][:, 0] E_points = data[points_names[2]][:, 0] Vd = data[points_names[3]][:, 0] Vd_err = data[points_names[4]][:, 0] J = data[points_names[5]][:, 0] J_err = data[points_names[6]][:, 0] rho_rel_error_array = data[points_names[7]][:, 0] ic_id = data[points_names[8]][:, 0] if len(rho_rel_error_array) > 0 and (ic_id[0] == initial_condition_id or initial_condition_id == -1): if debug: print '==> Solution found' Psi = interp_Fn(z_nodes, Psi_points, interp_type='last') E = interp_Fn(z_nodes, E_points, interp_type='last') SchDiode.FieldInversionPoint, _, _, _ = SchDiode.get_phi_bn(Psi, Vd, SchottkyEffect=False) print '*** !!! Inversion pt (load) !!!', SchDiode.FieldInversionPoint BI_F = {} for BI in SchDiode.Semiconductor.bonding_interfaces: F_tilt = [] F_twist = [] for trap in BI.dsl_tilt.traps: F_i = data[point_names_long[BI.label + '_tilt_' + trap[0].name + '_F'][0]][:, 0] BI_F[BI.label + '_tilt_' + trap[0].name + '_F'] = F_i[0] F_tilt.append(F_i[0]) for trap in BI.dsl_twist.traps: F_i = data[point_names_long[BI.label + '_twist_' + trap[0].name + '_F'][0]][:, 0] BI_F[BI.label + '_twist_' + trap[0].name + '_F'] = F_i[0] F_twist.append(F_i[0]) BI.set_traps_f(np.array(F_tilt), np.array(F_twist)) dopants_F = {} for dopant in SchDiode.Semiconductor.dopants: F_i = data[point_names_long[dopant.name + '_F'][0]][:, 0] dopants_F[dopant.name + '_F'] = F_i # print 'l1' dopant.set_F_interp(z_nodes, F_i) # print 'l2' return True, Psi, E, z_nodes, rho_rel_error_array, Vd, Vd_err, J, J_err, BI_F, dopants_F, measurement_id else: if debug: print '==> No solutions found' return False, Psi_zero, Psi_zero, np.zeros(1), np.zeros(1), 0, 0, 0, 0, {}, {}, measurement_id
def dirichlet_non_linear_poisson_solver_mesh(mesh, Psi0, f, dfdDPsi, rel=False, W=1, debug=False): ''' solves equation of form d2Psi/dx2 = f(Psi(x)) Psi(x0) = bc1, Psi(xn) = bc2 using FDE algorithm of O(h2) precision and Tailor series for linearization. ''' Psi0_nodes = Psi0(mesh.phys_nodes()) f_nodes = f(mesh.phys_nodes(), Psi0) dfdDPsi_nodes = dfdDPsi(mesh.phys_nodes(), Psi0) mesh, Psi_nodes, DPsi = dirichlet_non_linear_poisson_solver_mesh_arrays(mesh, Psi0_nodes, f_nodes, dfdDPsi_nodes, rel, W, debug) Psi = interp_Fn(mesh.phys_nodes(), Psi_nodes)#, interp_type='last') return mesh, Psi, DPsi
def dirichlet_non_linear_poisson_solver(nodes, Psi0, f, dfdDPsi, bc1, bc2, J=1, rel=False, W=1, debug=False): ''' solves equation of form d2Psi/dx2 = f(Psi(x)) Psi(x0) = bc1, Psi(xn) = bc2 using FDE algorithm of O(h2) precision and Tailor series for linearization. ''' Psi0_nodes = Psi0(nodes) f_nodes = f(nodes, Psi0) dfdDPsi_nodes = dfdDPsi(nodes, Psi0) Psi_nodes, DPsi, R = dirichlet_non_linear_poisson_solver_arrays(nodes, Psi0_nodes, f_nodes, dfdDPsi_nodes, bc1, bc2, J, rel, W, debug) Psi = interp_Fn(nodes, Psi_nodes) return Psi, DPsi, R
def dirichlet_non_linear_poisson_solver_mesh(mesh, Psi0, f, dfdDPsi, rel=False, W=1, debug=False): ''' solves equation of form d2Psi/dx2 = f(Psi(x)) Psi(x0) = bc1, Psi(xn) = bc2 using FDE algorithm of O(h2) precision and Tailor series for linearization. ''' Psi0_nodes = Psi0(mesh.phys_nodes()) f_nodes = f(mesh.phys_nodes(), Psi0) dfdDPsi_nodes = dfdDPsi(mesh.phys_nodes(), Psi0) mesh, Psi_nodes, DPsi = dirichlet_non_linear_poisson_solver_mesh_arrays( mesh, Psi0_nodes, f_nodes, dfdDPsi_nodes, rel, W, debug) Psi = interp_Fn(mesh.phys_nodes(), Psi_nodes) #, interp_type='last') return mesh, Psi, DPsi
def dirichlet_non_linear_poisson_solver(nodes, Psi0, f, dfdDPsi, bc1, bc2, J=1, rel=False, W=1, debug=False): ''' solves equation of form d2Psi/dx2 = f(Psi(x)) Psi(x0) = bc1, Psi(xn) = bc2 using FDE algorithm of O(h2) precision and Tailor series for linearization. ''' Psi0_nodes = Psi0(nodes) f_nodes = f(nodes, Psi0) dfdDPsi_nodes = dfdDPsi(nodes, Psi0) Psi_nodes, DPsi, R = dirichlet_non_linear_poisson_solver_arrays( nodes, Psi0_nodes, f_nodes, dfdDPsi_nodes, bc1, bc2, J, rel, W, debug) Psi = interp_Fn(nodes, Psi_nodes) return Psi, DPsi, R
def set_dF_interp(self, Z, dF): ''' z and dF must be 1D arrays of equal size ''' self.dF = interp_Fn(Z, dF, interp_type='last')
def set_F_interp(self, Z, F): ''' z and F must be 1D arrays of equal size ''' self.F = interp_Fn(Z, F, interp_type='last')
def Reccurent_Poisson_solver(SchDiode, Psi=Psi_zero, Vd_guess=None, Vd_error=1e-6, equilibrium_filling=True, fast_traps=None, t=mp.inf, initial_condition_id=-1, rho_rel_err=1e-3, max_iter=100, debug=False): recurrent_solver_start_time = time.time() Va = SchDiode.Va kT_eV = to_numeric(k * SchDiode.T / q) measurement_id = add_Electric_Field_Measurement(SchDiode, Va, equilibrium_filling, t, initial_condition_id) Solution_found, Psi_found, E, z_nodes, rho_rel_err_points, Vd, Vd_err, J, J_err, BI_F, dopants_F, measurement_id = load_diode_state( SchDiode, measurement_id, initial_condition_id, debug) if Solution_found: Psi = Psi_found Vd_guess = Vd[-1] J_tmp = J[-1] if max(abs(rho_rel_err_points)) <= rho_rel_err: if debug: print '==> Solution satisfy rel_error condition' return Psi, E, z_nodes, rho_rel_err_points, Vd[0], Vd_err[0], J[0], J_err[ 0], BI_F, dopants_F, measurement_id if debug or 1: print '==> Solution found does not satisfy rel_error condition' print '==> Recalculating...' SchDiode.FieldInversionPoint, PHI_bn, _, PHI_b = SchDiode.get_phi_bn(Psi, Vd_guess, SchottkyEffect=False) else: if debug: print '==> No solutions found' if Vd_guess is None: Vd_guess = Va PHI_b = abs(SchDiode.V_bi(eV=True)) SchDiode.FieldInversionPoint = 0 else: SchDiode.FieldInversionPoint, PHI_bn, _, PHI_b = SchDiode.get_phi_bn(Psi, Vd_guess, SchottkyEffect=False) if Va < PHI_b: Vd_guess = Va J_tmp = 0 converged = False current_iter = 0 Vd_tmp_corr = 0 Vd_guess_monitor_length = 5 Vd_guess_monitor = np.arange(Vd_guess_monitor_length, dtype=np.float) Vd_guess_monitor_count = 0 stalled = False while not converged and not stalled and current_iter < max_iter: if debug: print '\nIteration:', current_iter, '**' if debug or 1: print 'Vd_tmp =', Vd_guess if debug: print 'PHI_b =', PHI_b if Vd_guess >= PHI_b: Vd_guess = PHI_b - 1 * kT_eV if debug: print 'Vd_tmp =', Vd_guess Vd_guess_monitor[Vd_guess_monitor_count] = Vd_guess Vd_guess_monitor_count += 1 if Vd_guess_monitor_count == Vd_guess_monitor_length: Vd_guess_monitor_count = 0 if np.unique(Vd_guess_monitor).size == 1: stalled = True print 'Solution process stalled on iteration', current_iter, '!!!' continue nodes_num = int(np.floor(SchDiode.L * 1e6 + 1) * 100) nodes, _ = np.linspace(0, SchDiode.L, num=nodes_num + 1, endpoint=True, retstep=True) Meshes = Poisson_eq_num_solver_amr(SchDiode, nodes, Psi, Vd_guess, equilibrium_filling, fast_traps, max_iterations=50, residual_threshold=rho_rel_err, int_residual_threshold=5e-14, max_level=5, mesh_refinement_threshold=1e-19, debug=debug) z_nodes, Psi_points, rho_rel_err_points = Meshes.flatten(debug=False) dz = np.gradient(z_nodes) E_points = -np.gradient(Psi_points, dz, edge_order=2) Psi = interp_Fn(z_nodes, Psi_points, interp_type='last') E = interp_Fn(z_nodes, E_points, interp_type='last') SchDiode.FieldInversionPoint, PHI_bn, _, PHI_b = SchDiode.get_phi_bn(Psi, Vd_guess, SchottkyEffect=False) print '*** !!! Inversion pt (calc) !!!', SchDiode.FieldInversionPoint if debug: print 'PHI_b, PHI_bn =', PHI_b, PHI_bn Vd_tmp_corr, J_tmp_corr = SchDiode.ThermionicEmissionCurrent(Va, PHI_bn, debug=True) if debug: print 'V_corr, J =', Vd_tmp_corr, J_tmp_corr Vd_err = abs(Vd_guess - Vd_tmp_corr) J_err = abs(J_tmp - J_tmp_corr) if debug or 1: print 'Vd err =', Vd_err if debug or 1: print 'J err =', J_err, '\n' if Vd_err < Vd_error: converged = True else: Vd_guess = Vd_tmp_corr J_tmp = J_tmp_corr current_iter += 1 Vd = Vd_tmp_corr J = J_tmp if debug: print 'Calculation converged' recurrent_solver_elapsed_time = time.time() - recurrent_solver_start_time if debug: print 'Total recurrent solver execution time =', recurrent_solver_elapsed_time, 's\n' save_diode_state(SchDiode, measurement_id, initial_condition_id, z_nodes, Psi_points, E_points, rho_rel_err_points, Vd, Vd_err, J, J_err, debug) BI_F = {} for BI in SchDiode.Semiconductor.bonding_interfaces: for i, trap in enumerate(BI.dsl_tilt.traps): BI_F[BI.label + '_tilt_' + trap[0].name + '_F'] = BI.dsl_tilt_f[i] for i, trap in enumerate(BI.dsl_twist.traps): BI_F[BI.label + '_twist_' + trap[0].name + '_F'] = BI.dsl_twist_f[i] dopants_F = {} for dopant in SchDiode.Semiconductor.dopants: dopants_F[dopant.name + '_F'] = dopant.F(z_nodes) recurrent_solver_elapsed_time = time.time() - recurrent_solver_start_time if debug: print 'Total recurrent solver execution time =', recurrent_solver_elapsed_time, 's' return Psi, E, z_nodes, rho_rel_err_points, Vd, Vd_err, J, J_err, BI_F, dopants_F, measurement_id
def load_diode_state(SchDiode, measurement_id, initial_condition_id=-1, debug=False): point_names_long = gen_point_names_Electric_Field_measurement(SchDiode) if debug: print '==> Looking for saved solution in the database' points_names = [ point_names_long['z'][0], point_names_long['Psi'][0], point_names_long['E'][0], point_names_long['Vd'][0], point_names_long['Vd_err'][0], point_names_long['J'][0], point_names_long['J_err'][0], point_names_long['rho_rel_err'][0], point_names_long['ic_id'][0] ] for BI in SchDiode.Semiconductor.bonding_interfaces: for trap in BI.dsl_tilt.traps: points_names.append(point_names_long[BI.label + '_tilt_' + trap[0].name + '_F'][0]) for trap in BI.dsl_twist.traps: points_names.append(point_names_long[BI.label + '_twist_' + trap[0].name + '_F'][0]) for dopant in SchDiode.Semiconductor.dopants: points_names.append(point_names_long[dopant.name + '_F'][0]) try: data = SchDiode.Project.get_data_points_by_names( measurement_id, points_names) except: if debug: print '==> No solutions found' return False, Psi_zero, Psi_zero, np.zeros(1), np.zeros( 1), 0, 0, 0, 0, {}, {}, measurement_id z_nodes = data[points_names[0]][:, 0] Psi_points = data[points_names[1]][:, 0] E_points = data[points_names[2]][:, 0] Vd = data[points_names[3]][:, 0] Vd_err = data[points_names[4]][:, 0] J = data[points_names[5]][:, 0] J_err = data[points_names[6]][:, 0] rho_rel_error_array = data[points_names[7]][:, 0] ic_id = data[points_names[8]][:, 0] if len(rho_rel_error_array) > 0 and (ic_id[0] == initial_condition_id or initial_condition_id == -1): if debug: print '==> Solution found' Psi = interp_Fn(z_nodes, Psi_points, interp_type='last') E = interp_Fn(z_nodes, E_points, interp_type='last') SchDiode.FieldInversionPoint, _, _, _ = SchDiode.get_phi_bn( Psi, Vd, SchottkyEffect=False) print '*** !!! Inversion pt (load) !!!', SchDiode.FieldInversionPoint BI_F = {} for BI in SchDiode.Semiconductor.bonding_interfaces: F_tilt = [] F_twist = [] for trap in BI.dsl_tilt.traps: F_i = data[point_names_long[BI.label + '_tilt_' + trap[0].name + '_F'][0]][:, 0] BI_F[BI.label + '_tilt_' + trap[0].name + '_F'] = F_i[0] F_tilt.append(F_i[0]) for trap in BI.dsl_twist.traps: F_i = data[point_names_long[BI.label + '_twist_' + trap[0].name + '_F'][0]][:, 0] BI_F[BI.label + '_twist_' + trap[0].name + '_F'] = F_i[0] F_twist.append(F_i[0]) BI.set_traps_f(np.array(F_tilt), np.array(F_twist)) dopants_F = {} for dopant in SchDiode.Semiconductor.dopants: F_i = data[point_names_long[dopant.name + '_F'][0]][:, 0] dopants_F[dopant.name + '_F'] = F_i # print 'l1' dopant.set_F_interp(z_nodes, F_i) # print 'l2' return True, Psi, E, z_nodes, rho_rel_error_array, Vd, Vd_err, J, J_err, BI_F, dopants_F, measurement_id else: if debug: print '==> No solutions found' return False, Psi_zero, Psi_zero, np.zeros(1), np.zeros( 1), 0, 0, 0, 0, {}, {}, measurement_id
def Reccurent_Poisson_solver(SchDiode, Psi=Psi_zero, Vd_guess=None, Vd_error=1e-6, equilibrium_filling=True, fast_traps=None, t=mp.inf, initial_condition_id=-1, rho_rel_err=1e-3, max_iter=100, save_to_db=True, debug=False): recurrent_solver_start_time = time.time() Va = SchDiode.Va kT_eV = to_numeric(k * SchDiode.T / q) if save_to_db: measurement_id = add_Electric_Field_Measurement( SchDiode, Va, equilibrium_filling, t, initial_condition_id) Solution_found, Psi_found, E, z_nodes, rho_rel_err_points, Vd, Vd_err, J, J_err, BI_F, dopants_F, measurement_id = load_diode_state( SchDiode, measurement_id, initial_condition_id, debug) else: Solution_found = False measurement_id = -1 if Solution_found: Psi = Psi_found Vd_guess = Vd[-1] J_tmp = J[-1] if max(abs(rho_rel_err_points)) <= rho_rel_err: if debug: print '==> Solution satisfy rel_error condition' return Psi, E, z_nodes, rho_rel_err_points, Vd[0], Vd_err[0], J[ 0], J_err[0], BI_F, dopants_F, measurement_id if debug or 1: print '==> Solution found does not satisfy rel_error condition' print '==> Recalculating...' SchDiode.FieldInversionPoint, PHI_bn, _, PHI_b = SchDiode.get_phi_bn( Psi, Vd_guess, SchottkyEffect=False) else: if debug: print '==> No solutions found' if Vd_guess is None: Vd_guess = Va PHI_b = abs(SchDiode.V_bi(eV=True)) SchDiode.FieldInversionPoint = 0 else: SchDiode.FieldInversionPoint, PHI_bn, _, PHI_b = SchDiode.get_phi_bn( Psi, Vd_guess, SchottkyEffect=False) if Va < PHI_b: Vd_guess = Va J_tmp = 0 converged = False current_iter = 0 Vd_tmp_corr = 0 Vd_guess_monitor_length = 5 Vd_guess_monitor = np.arange(Vd_guess_monitor_length, dtype=np.float) Vd_guess_monitor_count = 0 stalled = False while not converged and not stalled and current_iter < max_iter: if debug: print '\nIteration:', current_iter, '**' if debug or 1: print 'Vd_tmp =', Vd_guess if debug: print 'PHI_b =', PHI_b if Vd_guess >= PHI_b: Vd_guess = PHI_b - 1 * kT_eV if debug: print 'Vd_tmp =', Vd_guess Vd_guess_monitor[Vd_guess_monitor_count] = Vd_guess Vd_guess_monitor_count += 1 if Vd_guess_monitor_count == Vd_guess_monitor_length: Vd_guess_monitor_count = 0 if np.unique(Vd_guess_monitor).size == 1: stalled = True print 'Solution process stalled on iteration', current_iter, '!!!' continue nodes_num = int(np.floor(SchDiode.L * 1e6 + 1) * 100) nodes, _ = np.linspace(0, SchDiode.L, num=nodes_num + 1, endpoint=True, retstep=True) Meshes = Poisson_eq_num_solver_amr(SchDiode, nodes, Psi, Vd_guess, equilibrium_filling, fast_traps, max_iterations=50, residual_threshold=rho_rel_err, int_residual_threshold=5e-14, max_level=5, mesh_refinement_threshold=1e-19, debug=debug) z_nodes, Psi_points, rho_rel_err_points = Meshes.flatten(debug=False) E_points = -np.gradient(Psi_points, z_nodes, edge_order=2) Psi = interp_Fn(z_nodes, Psi_points, interp_type='last') E = interp_Fn(z_nodes, E_points, interp_type='last') SchDiode.FieldInversionPoint, PHI_bn, _, PHI_b = SchDiode.get_phi_bn( Psi, Vd_guess, SchottkyEffect=False) print '*** !!! Inversion pt (calc) !!!', SchDiode.FieldInversionPoint if debug: print 'PHI_b, PHI_bn =', PHI_b, PHI_bn Vd_tmp_corr, J_tmp_corr = SchDiode.ThermionicEmissionCurrent( Va, PHI_bn, debug=True) if debug: print 'V_corr, J =', Vd_tmp_corr, J_tmp_corr Vd_err = abs(Vd_guess - Vd_tmp_corr) J_err = abs(J_tmp - J_tmp_corr) if debug or 1: print 'Vd err =', Vd_err if debug or 1: print 'J err =', J_err, '\n' if Vd_err < Vd_error: converged = True else: Vd_guess = Vd_tmp_corr J_tmp = J_tmp_corr current_iter += 1 Vd = Vd_tmp_corr J = J_tmp if debug: print 'Calculation converged' recurrent_solver_elapsed_time = time.time() - recurrent_solver_start_time if debug: print 'Total recurrent solver execution time =', recurrent_solver_elapsed_time, 's\n' if save_to_db: save_diode_state(SchDiode, measurement_id, initial_condition_id, z_nodes, Psi_points, E_points, rho_rel_err_points, Vd, Vd_err, J, J_err, debug) BI_F = {} for BI in SchDiode.Semiconductor.bonding_interfaces: for i, trap in enumerate(BI.dsl_tilt.traps): BI_F[BI.label + '_tilt_' + trap[0].name + '_F'] = BI.dsl_tilt_f[i] for i, trap in enumerate(BI.dsl_twist.traps): BI_F[BI.label + '_twist_' + trap[0].name + '_F'] = BI.dsl_twist_f[i] dopants_F = {} for dopant in SchDiode.Semiconductor.dopants: dopants_F[dopant.name + '_F'] = dopant.F(z_nodes) recurrent_solver_elapsed_time = time.time() - recurrent_solver_start_time if debug: print 'Total recurrent solver execution time =', recurrent_solver_elapsed_time, 's' return Psi, E, z_nodes, rho_rel_err_points, Vd, Vd_err, J, J_err, BI_F, dopants_F, measurement_id