def system(N=0,s=1e-18*1e4): # dimensions of the system Lx = 3e-6*1e2 #[m] Ly = 3e-6*1e2 #[m] # extent of the junction from the left contact [m] junction = .1e-6*1e2 ## initial: 60,50,10... 40,20,40 # Mesh x = np.concatenate((np.linspace(0,.2e-6*1e2, 30, endpoint=False), np.linspace(0.2e-6*1e2, 1.4e-6*1e2, 60, endpoint=False), np.linspace(1.4e-6*1e2, 2.7e-6*1e2, 60, endpoint=False), np.linspace(2.7e-6*1e2, Lx-0.02e-6*1e2, 30, endpoint=False), np.linspace(Lx-0.02e-6*1e2, Lx, 10))) #y = np.linspace(0, 1.25e-6, 40) y = np.concatenate((np.linspace(0, 1.25e-6*1e2, 60, endpoint=False), np.linspace(1.25e-6*1e2, 1.75e-6*1e2, 50, endpoint=False), np.linspace(1.75e-6*1e2, Ly, 60))) # Create a system sys = sesame.Builder(x, y) def region(pos): x, y = pos return x < junction # Add the donors nD = 1e17 # [m^-3] sys.add_donor(nD, region) # Add the acceptors region2 = lambda pos: 1 - region(pos) nA = 1e15 # [m^-3] sys.add_acceptor(nA, region2) # Use perfectly selective contacts sys.contact_type('Ohmic','Ohmic') #Sn_left, Sp_left, Sn_right, Sp_right = 1e50, 0, 0, 1e50 Sn_left, Sp_left, Sn_right, Sp_right = 1e50, 1e50, 1e50, 1e50 sys.contact_S(Sn_left, Sp_left, Sn_right, Sp_right) Nc = 8e17 Nv = 1.8e19 q = 1.60217662*1e-19 kb = 1.38064852*1e-23 t = 300 vt = kb*t/q # Dictionary with the material parameters mat = {'Nc':Nc, 'Nv':Nv, 'Eg':1.5, 'epsilon':9.4, 'Et': 0*vt*np.log(Nc/Nv), 'mu_e':320, 'mu_h':40, 'tau_e':10*1e-9, 'tau_h':10*1e-9} # Add the material to the system sys.add_material(mat) # gap state characteristics #s = 1e-24 # trap capture cross section [m^2] E = 0.4 + .5*vt*np.log(Nc/Nv) # energy of gap state (eV) from midgap # Specify the two points that make the line containing additional charges p1 = (.1e-6*1e2, 1.5*1e-6*1e2) #[m] p2 = (2.9e-6*1e2, 1.5*1e-6*1e2) #[m] # Pass the information to the system sys.add_line_defects([p1, p2], N, s, E=E, transition=(1,0)) sys.add_line_defects([p1, p2], N, s, E=E, transition=(0,-1)) return sys
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)))))
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))
t1 = 25*1e-7 # thickness of CdS t2 = 4*1e-4 # thickness of CdTe # Heterojunctions require dense mesh near the interface dd = 1e-7 # 2*dd is the distance over which mesh is refined # Define the mesh x = np.concatenate((np.linspace(0, dd, 10, endpoint=False), # L contact interface np.linspace(dd, t1-dd, 50, endpoint=False), # material 1 np.linspace(t1 - dd, t1 + dd, 10, endpoint=False), # interface 1 np.linspace(t1 + dd, (t1+t2) - dd, 100, endpoint=False), # material 2 np.linspace((t1+t2) - dd, (t1+t2), 10))) # R contact interface # Build system sys = sesame.Builder(x) # CdS material dictionary CdS = {'Nc': 2.2e18, 'Nv':1.8e19, 'Eg':2.4, 'epsilon':10, 'Et': 0, 'mu_e':100, 'mu_h':25, 'tau_e':1e-8, 'tau_h':1e-13, 'affinity': 4.} # CdTe material dictionary CdTe = {'Nc': 8e17, 'Nv': 1.8e19, 'Eg':1.5, 'epsilon':9.4, 'Et': 0, 'mu_e':320, 'mu_h':40, 'tau_e':5e-9, 'tau_h':5e-9, 'affinity': 3.9} # CdS region CdS_region = lambda pos: pos[0]<=t1 # CdTe region CdTe_region = lambda pos: pos[0]>t1
def system(params): # we assume the params are given in order: [rho_GB, E_GB, S_GB, tau] rho_GB = params[0] E_GB = params[1] S_GB = params[2] tau = params[3] # Dimensions of the system Lx = 3e-4 # [cm] Ly = 3e-4 # [cm] # Mesh x = np.concatenate( (np.linspace(0, 0.2e-4, 30, endpoint=False), np.linspace(0.2e-4, 1.4e-4, 60, endpoint=False), np.linspace(1.4e-4, 2.7e-4, 60, endpoint=False), np.linspace(2.7e-4, 2.98e-4, 30, endpoint=False), np.linspace(2.98e-4, Lx, 10))) y = np.concatenate( (np.linspace(0, 1.25e-4, 60, endpoint=False), np.linspace(1.25e-4, 1.75e-4, 50, endpoint=False), np.linspace(1.75e-4, Ly, 60))) # Create a system sys = sesame.Builder(x, y) # Dictionary with the material parameters mat = { 'Nc': 8e17, 'Nv': 1.8e19, 'Eg': 1.5, 'epsilon': 9.4, 'Et': 0, 'mu_e': 320, 'mu_h': 40, 'tau_e': tau, 'tau_h': tau } # Add the material to the system sys.add_material(mat) # Extent of the junction from the left contact [cm] junction = .1e-4 # [cm] # Define a function specifiying the n-type region def region1(pos): x, y = pos return x < junction # Define a function specifiying the p-type region def region2(pos): x, y = pos return x >= junction # Add the donors nD = 1e17 # Donor density [cm^-3] sys.add_donor(nD, region1) # Add the acceptors nA = 1e15 # Acceptor density [cm^-3] sys.add_acceptor(nA, region2) # Define contacts: CdS and CdTe contacts are Ohmic sys.contact_type('Ohmic', 'Ohmic') # Define the surface recombination velocities for electrons and holes [cm/s] Sn_left, Sp_left, Sn_right, Sp_right = 1e7, 1e7, 1e7, 1e7 # This function specifies the simulation contact recombination velocity [cm/s] sys.contact_S(Sn_left, Sp_left, Sn_right, Sp_right) # Specify the two points that make the line containing additional charges p1 = (0.1e-4, 1.5e-4) # [cm] p2 = (2.9e-4, 1.5e-4) # [cm] # Add donor defect along GB sys.add_defects([p1, p2], rho_GB, S_GB, E=E_GB, transition=(1, 0)) # Add acceptor defect along GB sys.add_defects([p1, p2], rho_GB, S_GB, E=E_GB, transition=(0, -1)) return sys
# extent of the junction from the left contact [cm] junction = .1e-4 # [cm] # Mesh x = np.concatenate((np.linspace(0, .2e-4, 30, endpoint=False), np.linspace(0.2e-4, 1.4e-4, 60, endpoint=False), np.linspace(1.4e-4, 2.9e-4, 70, endpoint=False), np.linspace(2.9e-4, 3e-4, 10))) y = np.concatenate((np.linspace(0, 1.75e-4, 50, endpoint=False), np.linspace(1.75e-4, 2.75e-4, 50, endpoint=False), np.linspace(2.75e-4, Ly, 50))) # Create a system sys = sesame.Builder(x, y, periodic=False) # Dictionary with the material parameters mat = { 'Nc': 8e17, 'Nv': 1.8e19, 'Eg': 1.5, 'epsilon': 9.4, 'Et': 0, 'mu_e': 320, 'mu_h': 40, 'tau_e': 10 * 1e-9, 'tau_h': 10 * 1e-9, 'B': 1e-10 }
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))
import sesame import numpy as np L = 3e-4 # length of the system in the x-direction [cm] # Mesh xpts = np.concatenate( (np.linspace(0, 1.2e-4, 100, endpoint=False), np.linspace(1.2e-4, L, 50))) # Create a system sys = sesame.Builder(xpts) # Dictionary with the material parameters material = { 'Nc': 1e19, 'Nv': 1e19, 'Eg': 1.5, 'affinity': 3.9, 'epsilon': 9.4, 'mu_e': 100, 'mu_h': 100, 'tau_e': 10e-9, 'tau_h': 10e-9, 'Et': 0 } # Add the material to the system sys.add_material(material) junction = 50e-7 # extent of the junction from the left contact [cm]