def runTest7(): L = 4e-4 # length of the system in the x-direction [m] dd = .05e-4 Ly = 2e-4 # Mesh x = np.concatenate( (np.linspace(0, 1e-4 - dd, 70, endpoint=False), np.linspace(1e-4 - dd, 1e-4 + dd, 20, endpoint=False), np.linspace(1e-4 + dd, 3e-4 - dd, 140, endpoint=False), np.linspace(3e-4 - dd, 3e-4 + dd, 20, endpoint=False), np.linspace(3e-4 + dd, L, 70))) y = np.concatenate( (np.linspace(0, 1e-4 - dd, 70, endpoint=False), np.linspace(1e-4 - dd, 1e-4 + dd, 20, endpoint=False), np.linspace(1e-4 + dd, 2e-4, 70))) #x = np.linspace(0,L, 1000) # Create a system sys = sesame.Builder(x, y) tau = 1e-8 vt = 0.025851991024560 Nc1 = 1e17 Nv1 = 1e18 Nc2 = 1e17 Nv2 = 1e18 # Dictionary with the material parameters mat1 = { 'Nc': Nc1, 'Nv': Nv1, 'Eg': 1., 'epsilon': 10, 'Et': 0, 'mu_e': 100, 'mu_h': 40, 'tau_e': tau, 'tau_h': tau, 'affinity': 4.15 } mat2 = { 'Nc': Nc2, 'Nv': Nv2, 'Eg': 1.1, 'epsilon': 100, 'Et': 0, 'mu_e': 100, 'mu_h': 40, 'tau_e': tau, 'tau_h': tau, 'affinity': 4.05 } junction = 2e-4 # extent of the junction from the left contact [m] def region1(pos): x, y = pos val = x <= 1e-4 return val def region2(pos): x, y = pos val = (x > 1e-4) & (x < 3e-4) & (y >= 1e-4) return val def region3(pos): x, y = pos val = (x > 1e-4) & (x < 3e-4) & (y < 1e-4) return val def region4(pos): x, y = pos val = x >= 3e-4 return val # Add the material to the system sys.add_material(mat1, region1) sys.add_material(mat1, region2) sys.add_material(mat2, region3) sys.add_material(mat2, region4) # Add the donors nD1 = 1e15 # [cm^-3] sys.add_donor(nD1, region1) sys.add_donor(nD1, region2) nD2 = 1e15 # [cm^-3] sys.add_acceptor(nD2, region3) sys.add_acceptor(nD2, region4) # Define the surface recombination velocities for electrons and holes [m/s] sys.contact_type('Ohmic', 'Ohmic') SS = 1e50 Sn_left, Sp_left, Sn_right, Sp_right = SS, SS, SS, SS sys.contact_S(Sn_left, Sp_left, Sn_right, Sp_right) # Electrostatic potential dimensionless solution = sesame.solve_equilibrium(sys, periodic_bcs=False, verbose=False) veq = np.copy(solution['v']) solution.update({ 'x': sys.xpts, 'y': sys.ypts, 'chi': sys.bl, 'eg': sys.Eg, 'Nc': sys.Nc, 'Nv': sys.Nv, 'epsilon': sys.epsilon }) # IV curve solution.update({ 'efn': np.zeros((sys.nx * sys.ny, )), 'efp': np.zeros((sys.nx * sys.ny, )) }) G = 1 * 1e18 f = lambda x, y: G sys.generation(f) solution = sesame.solve(sys, solution, maxiter=5000, periodic_bcs=False, verbose=False) az = sesame.Analyzer(sys, solution) tj = -az.full_current() voltages = np.linspace(.0, .8, 9) result = solution # sites of the right contact nx = sys.nx s = [nx - 1 + j * nx + k * nx * sys.ny for k in range(sys.nz) \ for j in range(sys.ny)] # sign of the voltage to apply if sys.rho[nx - 1] < 0: q = 1 else: q = -1 j = [] # Loop over the applied potentials made dimensionless Vapp = voltages / sys.scaling.energy for idx, vapp in enumerate(Vapp): # Apply the voltage on the right contact result['v'][s] = veq[s] + q * vapp # Call the Drift Diffusion Poisson solver result = sesame.solve(sys, result, maxiter=1000, periodic_bcs=False, verbose=False) # Compute current az = sesame.Analyzer(sys, result) tj = az.full_current() * sys.scaling.current * sys.scaling.length / ( 2e-4) j.append(tj) jcomsol = np.array([ 0.50272, 0.48515, 0.40623, -0.16696, -5.1204, -58.859, -819.11, -7024.4, -27657 ]) jcomsol = jcomsol * 1e-4 error = np.max( np.abs( (jcomsol - np.transpose(j)) / (.5 * (jcomsol + np.transpose(j)))))
# add donor defect along GB sys.add_line_defects([p1, p2], rho_GB, S_GB, E=E_GB, transition=(1, 0)) # add acceptor defect along GB sys.add_line_defects([p1, p2], rho_GB, S_GB, E=E_GB, transition=(0, -1)) # Solve equilibirum problem first solution = sesame.solve_equilibrium(sys) # define a function for generation profile f = lambda x, y: 2.3e21 * np.exp(-2.3e4 * x) # add generation to the system sys.generation(f) # Solve problem under short-circuit current conditions solution = sesame.solve(sys, solution) # Get analyzer object to compute observables az = sesame.Analyzer(sys, solution) # Compute short-circuit current j = az.full_current() # Print Jsc print(j * sys.scaling.current * sys.scaling.length * 1e3) # specify applied voltages voltages = np.linspace(0, .1, 1) # find j-v j = sesame.IVcurve(sys, voltages, solution, '2dGB_V') # save the result result = {'voltages': voltages, 'j': j} np.save('IV_values', result)
def runTest4(): rhoGBlist = np.linspace(1e6*1e-4,1e18*1e-4,2) sys = system(rhoGBlist[0]) solution = sesame.solve_equilibrium(sys, periodic_bcs=False, verbose=False) s0 = 1e-18*1e4 rhoGBlist = [1e6*1e-4, 1e18*1e-4] for idx, rhoGB in enumerate(rhoGBlist): sys = system(rhoGB,s0) solution = sesame.solve_equilibrium(sys, solution, maxiter=5000, periodic_bcs=False, verbose=False) veq = np.copy(solution['v']) efn = np.zeros((sys.nx * sys.ny,)) efp = np.zeros((sys.nx * sys.ny,)) solution.update({'efn': efn, 'efp': efp}) junction = .1e-6*1e2 # Define a function for the generation rate G = 1 phi0 = 1e21 * G * 1e-4 alpha = 2.3e6 * 1e-2 # alpha = 2e4 cm^-1 for CdTe f = lambda x, y: phi0 * alpha * np.exp(-alpha * x) sys.generation(f) slist = [1e-18 * 1e4] sys = system(rhoGBlist[1],slist[0]) sys.generation(f) solution = sesame.solve(sys, solution, maxiter=5000, verbose=False) az = sesame.Analyzer(sys, solution) tj = -az.full_current() voltages = np.linspace(.0, .8, 9) result = solution # sites of the right contact nx = sys.nx s = [nx - 1 + j * nx + k * nx * sys.ny for k in range(sys.nz) \ for j in range(sys.ny)] # sign of the voltage to apply if sys.rho[nx - 1] < 0: q = 1 else: q = -1 j = [] # Loop over the applied potentials made dimensionless Vapp = voltages / sys.scaling.energy for idx, vapp in enumerate(Vapp): # Apply the voltage on the right contact result['v'][s] = veq[s] + q * vapp # Call the Drift Diffusion Poisson solver result = sesame.solve(sys, result, maxiter=1000, periodic_bcs=False, verbose=False) # Compute current az = sesame.Analyzer(sys, result) tj = az.full_current() * sys.scaling.current * sys.scaling.length / (3e-6*1e2) * 1e4 j.append(tj) jcomsol = np.array([-136.07, -135.73, -135.30, -134.73, -133.61, -129.76, -119.33, -83.149, 115.90]) jcomsol = -jcomsol error = np.max(np.abs((jcomsol - np.transpose(j)) / (.5 * (jcomsol + np.transpose(j))))) print("error = {0}".format(error))
def runTest2(): L = 4e-6*1e2 # length of the system in the x-direction [m] dd = .005e-6*1e2 # Mesh x = np.concatenate((np.linspace(0,L/2-dd, 100, endpoint=False), np.linspace(L/2-dd, L/2+dd, 20, endpoint=False), np.linspace(L/2+dd,L, 100))) # Create a system sys = sesame.Builder(x, input_length='cm') tau = 1e8 vt = 0.025851991024560; Nc1 = 2.2*1e18 Nv1 = 2.2*1e18 Nc2 = 2.2*1e18 Nv2 = 2.2*1e18 # Dictionary with the material parameters mat1 = {'Nc':Nc1, 'Nv':Nv1, 'Eg':1.5, 'epsilon':1000, 'Et': 0, 'mu_e':100, 'mu_h':40, 'tau_e':tau, 'tau_h':tau, 'band_offset': 4.05} mat2 = {'Nc':Nc2, 'Nv':Nv2, 'Eg':1.5, 'epsilon':10000, 'Et': 0, 'mu_e':100, 'mu_h':40, 'tau_e':tau, 'tau_h':tau, 'band_offset': 4.05} junction = 2e-6*1e2 # extent of the junction from the left contact [m] def region1(pos): return pos < junction # Add the acceptors region2 = lambda pos: 1 - region1(pos) # Add the material to the system sys.add_material(mat1, region1) sys.add_material(mat2, region2) # Define Ohmic contacts sys.contact_type('Ohmic', 'Ohmic') # Add the donors nD1 = 1e15 # [m^-3] sys.add_donor(nD1, region1) nD2 = 1e15 # [m^-3] sys.add_acceptor(nD2, region2) # Define the surface recombination velocities for electrons and holes [m/s] SS = 1e50 Sn_left, Sp_left, Sn_right, Sp_right = SS, SS, SS, SS sys.contact_S(Sn_left, Sp_left, Sn_right, Sp_right) # Electrostatic potential dimensionless solution = sesame.solve_equilibrium(sys, verbose=False) veq = np.copy(solution['v']) G = 1*1e24*1e-6 f = lambda x: G sys.generation(f) solution = sesame.solve(sys, solution, verbose=False) solution.update({'x': sys.xpts, 'chi': sys.bl, 'eg': sys.Eg, 'Nc': sys.Nc, 'Nv': sys.Nv}) voltages = np.linspace(0, 0.9, 10) result = solution # sites of the right contact nx = sys.nx s = [nx-1 + j*nx + k*nx*sys.ny for k in range(sys.nz)\ for j in range(sys.ny)] # sign of the voltage to apply if sys.rho[nx-1] < 0: q = 1 else: q = -1 j = [] # Loop over the applied potentials made dimensionless Vapp = voltages / sys.scaling.energy for idx, vapp in enumerate(Vapp): # Apply the voltage on the right contact result['v'][s] = veq[s] + q*vapp # Call the Drift Diffusion Poisson solver result = sesame.solve(sys, result, maxiter=1000, verbose=False) # Compute current az = sesame.Analyzer(sys, result) tj = az.full_current()* sys.scaling.current j.append(tj) jcomsol = np.array([0.55569,0.54937,0.5423,0.53436,0.52535,0.51499,0.50217,0.4622,-0.47448,-31.281]) jcomsol = jcomsol * 1e-4 error = np.max(np.abs((jcomsol-np.transpose(j))/(.5*(jcomsol+np.transpose(j))))) print("error = {0}".format(error))
import sesame import numpy as np import matplotlib.pyplot as plt from scipy.io import savemat J = [] for i in range(10): filename = "../tutorial3/2dGB_V_%d.gzip" % i sys, results = sesame.load_sim(filename) az = sesame.Analyzer(sys, results) J.append(az.full_current() * sys.scaling.current * sys.scaling.length) print("current [A/cm] = ", J) ################## sys, results = sesame.load_sim("2dGB_V_0.gzip") az = sesame.Analyzer(sys, results) # Line endpoints of the grain boundary core p1 = (20e-7, 1.5e-4) #[cm] p2 = (2.9e-4, 1.5e-4) #[cm] # get the coordinate indices of the grain boundary core X, sites = az.line(sys, p1, p2) # obtain solution data along the GB core efn_GB = results['efn'][sites] efp_GB = results['efp'][sites] v_GB = results['v'][sites] #In this code we compute the integrated defect recombination along the grain boundary core::
def runTest3(): rhoGBlist = np.linspace(1e6 * 1e-4, 1e18 * 1e-4, 2) sys = system(rhoGBlist[0]) solution = sesame.solve_equilibrium(sys, verbose=False) s0 = 1e-18 * 1e4 rhoGBlist = [1e6 * 1e-4, 1e18 * 1e-4] for idx, rhoGB in enumerate(rhoGBlist): sys = system(rhoGB, s0) solution = sesame.solve_equilibrium(sys, solution, maxiter=5000, verbose=False) veq = np.copy(solution['v']) efn = np.zeros((sys.nx * sys.ny, )) efp = np.zeros((sys.nx * sys.ny, )) solution.update({'efn': efn, 'efp': efp}) junction = .1e-6 * 1e2 # Define a function for the generation rate G = 1 phi0 = 1e21 * G * 1e-4 alpha = 2.3e6 * 1e-2 # alpha = 2e4 cm^-1 for CdTe f = lambda x, y: phi0 * alpha * np.exp(-alpha * x) sys.generation(f) slist = [1e-18 * 1e4] sys = system(rhoGBlist[1], slist[0]) sys.generation(f) solution = sesame.solve(sys, solution, maxiter=5000, verbose=False) az = sesame.Analyzer(sys, solution) tj = -az.full_current() voltages = np.linspace(.0, .8, 9) result = solution # sites of the right contact nx = sys.nx s = [nx - 1 + j * nx + k * nx * sys.ny for k in range(sys.nz) \ for j in range(sys.ny)] # sign of the voltage to apply if sys.rho[nx - 1] < 0: q = 1 else: q = -1 j = [] # Loop over the applied potentials made dimensionless Vapp = voltages / sys.scaling.energy for idx, vapp in enumerate(Vapp): # Apply the voltage on the right contact result['v'][s] = veq[s] + q * vapp # Call the Drift Diffusion Poisson solver result = sesame.solve(sys, result, maxiter=1000, verbose=False) # Compute current az = sesame.Analyzer(sys, result) tj = az.full_current() * sys.scaling.current * sys.scaling.length / ( 3e-6 * 1e2) j.append(tj) jSesame_12_4_2017 = np.array([ 135.14066065175203, 134.97430561196626, 134.70499402818209, 134.28271667573679, 133.27884008619145, 129.49875552490002, 119.14704988797484, 83.157765739151415, -114.57979137988193 ]) jSesame_12_4_2017 = jSesame_12_4_2017 * 1e-4 error = np.max( np.abs((jSesame_12_4_2017 - np.transpose(j)) / (.5 * (jSesame_12_4_2017 + np.transpose(j))))) print("error = {0}".format(error))
def runTest1(): L = 3e-4 # length of the system in the x-direction [cm] dd = 1e-7*1e2 # Mesh x = np.concatenate((np.linspace(0,5e-7*1e2-dd,50, endpoint=False), np.linspace(5e-7*1e2-dd,5e-7*1e2+dd,20, endpoint=False), np.linspace(5e-7*1e2+dd,1e-6*1e2, 100, endpoint=False), np.linspace(1e-6*1e2, L, 200))) # Create a system sys = sesame.Builder(x,input_length='cm') tau = 1e-8 vt = 0.025851991024560 Nc1 = 8*1e17 Nv1 = 1.8*1e19 Nc2 = 8*1e17 Nv2 = 1.8*1e19 # Dictionary with the material parameters mat1 = {'Nc':Nc1, 'Nv':Nv1, 'Eg':2.4, 'epsilon':10, 'Et': 0, 'mu_e':320, 'mu_h':40, 'tau_e':tau, 'tau_h':tau, 'affinity': 4.15} mat2 = {'Nc':Nc2, 'Nv':Nv2, 'Eg':1.5, 'epsilon':10, 'Et': 0, 'mu_e':320, 'mu_h':40, 'tau_e':tau, 'tau_h':tau, 'affinity': 4.05} junction = 5e-7*1e2 # extent of the junction from the left contact [m] def region1(pos): x = pos return x < junction # Add the acceptors region2 = lambda pos: 1 - region1(pos) # Add the material to the system sys.add_material(mat1, region1) sys.add_material(mat2, region2) # Add the donors nD1 = 1e17 # [cm^-3] sys.add_donor(nD1, region1) nD2 = 1e15 # [cm^-3] sys.add_acceptor(nD2, region2) # Define Ohmic contacts sys.contact_type('Ohmic', 'Ohmic') # Define the surface recombination velocities for electrons and holes [m/s] SS = 1e50*1e2 Sn_left, Sp_left, Sn_right, Sp_right = SS, SS, SS, SS sys.contact_S(Sn_left, Sp_left, Sn_right, Sp_right) solution = sesame.solve(sys, compute='Poisson', verbose=False) veq = np.copy(solution['v']) G = 1*1e24*1e-6 f = lambda x: G sys.generation(f) solution = sesame.solve(sys, guess=solution, verbose=False) solution.update({'x': sys.xpts, 'chi': sys.bl, 'eg': sys.Eg, 'Nc': sys.Nc, 'Nv': sys.Nv}) voltages = np.linspace(0, 0.8, 9) result = solution # sites of the right contact nx = sys.nx s = [nx-1 + j*nx for j in range(sys.ny)] # sign of the voltage to apply if sys.rho[nx-1] < 0: q = 1 else: q = -1 j = [] # Loop over the applied potentials made dimensionless Vapp = voltages / sys.scaling.energy for idx, vapp in enumerate(Vapp): # Apply the voltage on the right contact result['v'][s] = veq[s] + q*vapp # Call the Drift Diffusion Poisson solver result = sesame.solve(sys, guess=result, maxiter=1000, verbose=False) # Compute current az = sesame.Analyzer(sys, result) tj = az.full_current()* sys.scaling.current j.append(tj) jcomsol = np.array([0.32117,0.31672,0.31198,0.30683,0.30031,0.28562,0.20949,-0.39374,-7.0681]) jcomsol = jcomsol * 1e-4 # converting to A/cm^2 error = np.max(np.abs((jcomsol-np.transpose(j))/(.5*(jcomsol+np.transpose(j))))) print("error = {0}".format(error))
def runTest8(): L = 4e-4 # length of the system in the x-direction [m] dd = .05e-4 Ly = 2e-4 # Mesh x = np.concatenate( (np.linspace(0, 1e-4 - dd, 70, endpoint=False), np.linspace(1e-4 - dd, 1e-4 + dd, 20, endpoint=False), np.linspace(1e-4 + dd, 3e-4 - dd, 140, endpoint=False), np.linspace(3e-4 - dd, 3e-4 + dd, 20, endpoint=False), np.linspace(3e-4 + dd, L, 70))) y = np.concatenate( (np.linspace(0, 1e-4 - dd, 70, endpoint=False), np.linspace(1e-4 - dd, 1e-4 + dd, 20, endpoint=False), np.linspace(1e-4 + dd, 2e-4, 70))) # Create a system sys = sesame.Builder(x, y) tau = 1e-8 vt = 0.025851991024560 Nc1 = 1e17 Nv1 = 1e18 Nc2 = 1e17 Nv2 = 1e18 # Dictionary with the material parameters mat1 = { 'Nc': Nc1, 'Nv': Nv1, 'Eg': 1., 'epsilon': 10, 'Et': 0, 'mu_e': 100, 'mu_h': 40, 'tau_e': tau, 'tau_h': tau, 'affinity': 4.15 } mat2 = { 'Nc': Nc2, 'Nv': Nv2, 'Eg': 1.1, 'epsilon': 100, 'Et': 0, 'mu_e': 100, 'mu_h': 40, 'tau_e': tau, 'tau_h': tau, 'affinity': 4.05 } junction = 2e-4 # extent of the junction from the left contact [m] def region1(pos): x, y = pos val = x <= 1e-4 return val def region2(pos): x, y = pos val = (x > 1e-4) & (x < 3e-4) & (y >= 1e-4) return val def region3(pos): x, y = pos val = (x > 1e-4) & (x < 3e-4) & (y < 1e-4) return val def region4(pos): x, y = pos val = x >= 3e-4 return val # Add the material to the system sys.add_material(mat1, region1) sys.add_material(mat1, region2) sys.add_material(mat2, region3) sys.add_material(mat2, region4) # Add the donors nD1 = 1e15 # [cm^-3] sys.add_donor(nD1, region1) sys.add_donor(nD1, region2) nD2 = 1e15 # [cm^-3] sys.add_acceptor(nD2, region3) sys.add_acceptor(nD2, region4) # Define the surface recombination velocities for electrons and holes [m/s] sys.contact_type('Ohmic', 'Ohmic') SS = 1e50 Sn_left, Sp_left, Sn_right, Sp_right = SS, SS, SS, SS sys.contact_S(Sn_left, Sp_left, Sn_right, Sp_right) # Electrostatic potential dimensionless solution = sesame.solve(sys, compute='Poisson', periodic_bcs=False, verbose=False) veq = np.copy(solution['v']) solution.update({ 'x': sys.xpts, 'y': sys.ypts, 'chi': sys.bl, 'eg': sys.Eg, 'Nc': sys.Nc, 'Nv': sys.Nv, 'epsilon': sys.epsilon }) # IV curve solution.update({ 'efn': np.zeros((sys.nx * sys.ny, )), 'efp': np.zeros((sys.nx * sys.ny, )) }) G = 1 * 1e18 f = lambda x, y: G sys.generation(f) solution = sesame.solve(sys, guess=solution, maxiter=5000, periodic_bcs=True, verbose=False) az = sesame.Analyzer(sys, solution) tj = -az.full_current() voltages = np.linspace(.0, .8, 9) result = solution # sites of the right contact nx = sys.nx s = [nx - 1 + j * nx for j in range(sys.ny)] # sign of the voltage to apply if sys.rho[nx - 1] < 0: q = 1 else: q = -1 j = [] # Loop over the applied potentials made dimensionless Vapp = voltages / sys.scaling.energy for idx, vapp in enumerate(Vapp): # Apply the voltage on the right contact result['v'][s] = veq[s] + q * vapp # Call the Drift Diffusion Poisson solver result = sesame.solve(sys, guess=result, maxiter=1000, periodic_bcs=True, verbose=False) # Compute current az = sesame.Analyzer(sys, result) tj = az.full_current() * sys.scaling.current * sys.scaling.length / ( 2e-4) j.append(tj) jSesame_12_4_2017 = np.array([ 0.51880926865443222, 0.49724822874328478, 0.38634212450640715, -0.41864449697811151, -7.1679242861918242, -76.107867495994327, -919.58279216747349, -7114.3078754855478, -28453.412760553809 ]) jSesame_12_4_2017 = jSesame_12_4_2017 * 1e-4 error = np.max( np.abs((jSesame_12_4_2017 - np.transpose(j)) / (.5 * (jSesame_12_4_2017 + np.transpose(j))))) print("error = {0}".format(error))