def NKT_TMM_spectrum_wrapper(nk_fit, thickness, lamda, snell_angle_front, layer_index_of_fit, nk_f_list, thickness_list, coherency_list, tm_polarization_fraction, spectrum): #this is just a fancy wrapper for inc_tmm # does the order matter? nk_list = [ nk_f(lamda) for nk_f in nk_f_list] nk_list[layer_index_of_fit] = nk_fit # overwrite input nk_f with the fit one. basically, it would make the code much uglier if I made an excption local_thickness_list = [layer_thickness for layer_thickness in thickness_list] local_thickness_list[layer_index_of_fit] = thickness te_result = inc_tmm('s', nk_list, local_thickness_list, coherency_list, snell_angle_front, lamda) tm_result = inc_tmm('p', nk_list, local_thickness_list, coherency_list, snell_angle_front, lamda) T = tm_polarization_fraction * tm_result['T'] + (1.0-tm_polarization_fraction) * te_result['T'] R = tm_polarization_fraction * tm_result['R'] + (1.0-tm_polarization_fraction) * te_result['R'] A = 1 - T - R if callable(spectrum)==False: result_dict = { 'T': T, 'R': R, 'A': A } result = result_dict[spectrum] else: result = spectrum(T,R) # allows you to create things like extiction where the spectrum is 1-T return result
def TMM_spectrum_wrapper(nk_fit, lamda, snell_angle_front, layer_index_of_fit, nk_f_list, thickness_list, coherency_list, tm_polarization_fraction, spectrum): #this is just a fancy wrapper for inc_tmm nk_list = [ nk_f(lamda) for nk_f in nk_f_list] try: # just try iterating through the layer_index_of_fit to see if its a list of just an int for index in layer_index_of_fit: nk_list[index] = nk_fit # overwrite input nk_f with the fit one. except: nk_list[layer_index_of_fit] = nk_fit te_result = inc_tmm('s', nk_list, thickness_list, coherency_list, snell_angle_front, lamda) tm_result = inc_tmm('p', nk_list, thickness_list, coherency_list, snell_angle_front, lamda) T = tm_polarization_fraction * tm_result['T'] + (1.0-tm_polarization_fraction) * te_result['T'] R = tm_polarization_fraction * tm_result['R'] + (1.0-tm_polarization_fraction) * te_result['R'] if callable(spectrum)==False: A = 1 - T - R result_dict = { 'T': T, 'R': R, 'A': A } result = result_dict[spectrum] else: result = spectrum(T,R) # allows you to create things like extiction where the spectrum is 1-T return result
def TR(nk_fit, lamda, snell_angle_front, layer_index_of_fit, nk_f_list, thickness_list, coherency_list, tm_polarization_fraction): #this is just a fancy wrapper for inc_tmm nk_list = [ nk_f(lamda) for nk_f in nk_f_list] nk_list[layer_index_of_fit] = nk_fit # overwrite input nk_f with the fit one. basically, it would make the code much uglier if I made an excption te_result = inc_tmm('s', nk_list, thickness_list, coherency_list, snell_angle_front, lamda) tm_result = inc_tmm('p', nk_list, thickness_list, coherency_list, snell_angle_front, lamda) T = tm_polarization_fraction * tm_result['T'] + (1.0-tm_polarization_fraction) * te_result['T'] R = tm_polarization_fraction * tm_result['R'] + (1.0-tm_polarization_fraction) * te_result['R'] return T, R
def TM(params): prm = params.valuesdict() global Tsim Tsim = numpy.array([]) global Rsim Rsim = numpy.array([]) global Ssim Ssim = prm['Cs'] / lamb**prm['alpha'] global n_collect n_collect = numpy.array([]) global k_collect k_collect = numpy.array([]) d_list = [numpy.inf, prm['d'], numpy.inf] c_list = ['i' for i in range(len(d_list))] for i, l in enumerate(lamb): n = Sellmeier(l, prm['A'], prm['B1'], prm['C1']) k = epsilon[numpy.where( lamb_epsilon == l)][0] * l / (4 * numpy.pi) * prm['Cd'] n_collect = numpy.append(n_collect, n) k_collect = numpy.append(k_collect, k) if numpy.isnan(n) == True: return 1e99 break nk_list = [1, n + k * 1j, 1] sim = tmm.inc_tmm('s', nk_list, d_list, c_list, 0 + 0j, l) Tsim = numpy.append(Tsim, sim['T']) Rsim = numpy.append(Rsim, sim['R']) global res res = Tmeas - (Tsim - Ssim) global Rquadrat Rquadrat = 1 - numpy.var(res) / numpy.var(Tmeas) # ~ print(Rquadrat) return res
def get_RAT(self,lam,inc_angle): thicks = [tmm.inf] iorcs = ['i'] nks = [1] for layer in self.layers: nks.append(layer.nk(lam)) thicks.append(layer.d) iorcs.append(layer.i_or_c) thicks.append(tmm.inf) iorcs.append('i') nks.append(1) front_spol = tmm.inc_tmm('s',nks,thicks,iorcs,inc_angle,lam) front_ppol = tmm.inc_tmm('p',nks,thicks,iorcs,inc_angle,lam) R = (front_spol['R']+front_ppol['R']) / 2. T = (front_spol['T']+front_ppol['T']) / 2. return [R,1-R-T,T]
def solar_results(activeLayer, AL_thickness, theta, atWL, calc_Efield, calc_Jsc, calc_Jsc_loss, calc_Q): #JB # list of layer thicknesses in nm d_list[activeLayer] = AL_thickness # JB angle = theta th0 = angle * np.pi / 180 checkwavelength = atWL stepsize = 1 # allocate lists of y-values to plot R_a_s = [] R_a_p = [] T_a_s = [] T_a_p = [] A_a_s = [] A_a_p = [] E_s = [] E_p = [] E_xyz_tot = [] PA_s = [] PA_p = [] Gxl = [] Gxl_tot = [] Gxl_refl = [] Gxl_parasitic = [] for i, wl in enumerate(wavelengths): n_list = n_k[:, i] #calculate all data coherent (returns more values) and incoherent coh_tmm_data_s = tmm.coh_tmm('s', n_list, d_list, angle * np.pi / 180, wl) coh_tmm_data_p = tmm.coh_tmm('p', n_list, d_list, angle * np.pi / 180, wl) incoh_tmm_data_s = tmm.inc_tmm('s', n_list, d_list, c_list, angle * np.pi / 180, wl) incoh_tmm_data_p = tmm.inc_tmm('p', n_list, d_list, c_list, angle * np.pi / 180, wl) #use for R,T,A R_a_s.append(incoh_tmm_data_s['R']) R_a_p.append(incoh_tmm_data_p['R']) T_a_s.append(incoh_tmm_data_s['T']) T_a_p.append(incoh_tmm_data_p['T']) A_a_s.append(tmm.inc_absorp_in_each_layer(incoh_tmm_data_s)) A_a_p.append(tmm.inc_absorp_in_each_layer(incoh_tmm_data_p)) E_s.append([]) E_p.append([]) E_xyz_tot.append([]) PA_s.append([]) PA_p.append([]) Gxl.append([]) Gxl_tot.append([]) Gxl_refl.append([]) Gxl_parasitic.append([]) #E-field for every layer different if calc_Efield == 1: x_pos_abs = 0 t = [] for j in range(stackBegin, len(d_list) - 1): if j == 1: vw_s = incoh_tmm_data_s['VW_list'][j] kz_s = coh_tmm_data_s['kz_list'][j] vw_p = incoh_tmm_data_p['VW_list'][j] kz_p = coh_tmm_data_p['kz_list'][j] else: vw_s = coh_tmm_data_s['vw_list'][j] kz_s = coh_tmm_data_s['kz_list'][j] th_s = coh_tmm_data_s['th_list'][j] vw_p = coh_tmm_data_p['vw_list'][j] kz_p = coh_tmm_data_p['kz_list'][j] th_p = coh_tmm_data_p['th_list'][j] alpha = 4 * np.pi * np.imag(n_k[j, i]) / wl #at every point x x_pos_rel = 0 for x in range(x_pos_abs, x_pos_abs + d_list[j] + 1): t.append(x) E_plus_s = vw_s[0] * np.exp(1j * kz_s * x_pos_rel) E_minus_s = vw_s[1] * np.exp(-1j * kz_s * x_pos_rel) E_plus_p = vw_p[0] * np.exp(1j * kz_p * x_pos_rel) E_minus_p = vw_p[1] * np.exp(-1j * kz_p * x_pos_rel) E_pos_s = E_plus_s + E_minus_s E_pos_p = E_plus_p + E_minus_p E_s[i].append(E_pos_s) E_p[i].append(E_pos_p) E_z_pos = E_pos_s / np.sqrt(np.cos(th0)) E_y_pos = E_pos_p * np.cos(th_p) / np.sqrt(np.cos(th0)) E_x_pos = ((-1) * E_plus_p + E_minus_p) * n_list[0] * np.sin(th0) / ( n_list[j] * np.sqrt(np.cos(th0))) E_xyz_pos = 0.5 * np.square(np.absolute(E_z_pos)) + 0.5 * ( np.square(np.absolute(E_y_pos)) + np.square(np.absolute(E_x_pos))) E_xyz_tot[i].append(E_xyz_pos) Q_pos_xyz = alpha * np.real(n_k[j, i]) * power[i] * E_xyz_pos #calculate Energy dissipation and exciton generation rate if j == activeLayer: Gxl[i].append(Q_pos_xyz * 1e-3 * wl * 1e-9 / (h * c)) Gxl_tot[i].append(Q_pos_xyz * 1e-3 * wl * 1e-9 / (h * c)) else: Q_pos_xyz = alpha * np.real(n_k[j, i]) * power[i] * ( 0.5 * np.square(np.absolute(E_z_pos)) + 0.5 * (np.square(np.absolute(E_y_pos)) + np.square(np.absolute(E_x_pos)))) Gxl_parasitic[i].append(Q_pos_xyz * 1e-3 * wl * 1e-9 / (h * c)) Gxl_tot[i].append(Q_pos_xyz * 1e-3 * wl * 1e-9 / (h * c)) R_frac = 0.5 * incoh_tmm_data_s[ 'R'] + 0.5 * incoh_tmm_data_p['R'] Q_pos_xyz = Q_pos_xyz * (R_frac / (1 - R_frac)) Gxl_refl[i].append(Q_pos_xyz * 1e-3 * wl * 1e-9 / (h * c)) #calculate pointing vectors #PA_s[i].append(tmm.position_resolved(j, x_pos_rel, coh_tmm_data_s)['poyn']) #PA_p[i].append(tmm.position_resolved(j, x_pos_rel, coh_tmm_data_p)['poyn']) x_pos_rel += 1 x_pos_abs += d_list[j] #convert all lists to arrays for plotting R_a_s = np.array(R_a_s) R_a_p = np.array(R_a_p) T_a_s = np.array(T_a_s) T_a_p = np.array(T_a_p) A_a_s = np.array(A_a_s) A_a_p = np.array(A_a_p) #get the 50% polarized fields R_a_tot = 0.5 * (R_a_s + R_a_p) T_a_tot = 0.5 * (T_a_s + T_a_p) A_tot = 0.5 * A_a_s + 0.5 * A_a_p A_tot2 = A_tot # JB #plot A in each layer # JB plt.figure(6) plt.clf() plt.plot(wavelengths, A_tot2[:, activeLayer], 'blue', label="A_perov") plt.xlabel('wavelength (nm)') plt.ylabel('A') plt.title('Our plot at %s' % angle) plt.legend() plt.show() np.savetxt('A_tot.out', np.c_[wavelengths, A_tot], delimiter=',') # JB # delete first and last layer A_tot = np.delete(A_tot, 0, 1) # delete first column of C A_tot = np.delete(A_tot, -1, 1) # delete last column of C A_tot = A_tot.sum(axis=1) #save the data np.savetxt('RTA.out', np.c_[wavelengths, T_a_tot, R_a_tot, A_tot, T_a_tot + R_a_tot + A_tot], delimiter=',', header='Wavelength,T,R,A,Sum') #plot the results for R,T,A plt.close('all') plt.figure(1) plt.clf() plt.plot(wavelengths, T_a_tot, 'blue', label="Transmission") plt.plot(wavelengths, R_a_tot, 'purple', label="Reflection") plt.plot(wavelengths, A_tot, 'red', label="Absorption") plt.plot(wavelengths, T_a_tot + R_a_tot + A_tot, 'green', label="Sum") plt.xlabel('wl (nm)') plt.ylabel('Fraction reflected') plt.title('Our plot at %s' % angle) plt.legend() plt.ylim([0, 0.2]) # JB plt.xlim([300, 850]) # JB plt.show() if calc_Efield == 1: t_a = np.array(t) i_faces = np.array(d_list) i_faces = np.delete(i_faces, 0) # delete first column of C i_faces = np.delete(i_faces, 0) # delete second column of C i_faces = np.delete(i_faces, -1) # delete last column of C #calculate power of E-fields for s and p E_a_s = np.array(E_s) E_a_p = np.array(E_p) E_2_s = np.square(np.absolute(E_s[wavelengths.index(checkwavelength)])) E_2_p = np.square(np.absolute(E_p[wavelengths.index(checkwavelength)])) #save the data for the efield np.savetxt('E2_distribution.out', np.c_[t_a, E_2_s, E_2_p, E_2_s * 0.5 + E_2_p * 0.5], delimiter=',', header='Position,E2_s,E2_p,E2_tot') #plot E field distrubtion plt.figure(2) plt.clf() plt.plot(t_a, E_2_s, 'blue', label="s-pol") plt.plot(t_a, E_2_p, 'red', label="p-pol") plt.plot(t_a, E_2_s * 0.5 + E_2_p * 0.5, 'green', label="Tot") plt.vlines(np.cumsum(i_faces), 0, 1, colors='k', linestyles='solid', label='') plt.xlabel('x (nm)') plt.ylabel('E2') plt.title('Our plot at %s' % angle) plt.legend() plt.show() #calculate generation and Jsc if calc_Jsc == 1: lambdastep = 1 if np.size(wavelengths) > 1: lambdastep = (np.amax(wavelengths) - np.amin(wavelengths)) / ( np.size(wavelengths) - 1) Gx = np.sum(Gxl, axis=0) * lambdastep Jsc = np.sum(Gx, axis=0) * stepsize * q * 1e3 print("Jsc:") print(Jsc) if calc_Jsc_loss == 1: Gx_parasitic = np.sum(Gxl_parasitic, axis=0) * lambdastep Jsc_parasitic = np.sum(Gx_parasitic, axis=0) * stepsize * q * 1e3 Gx_refl = np.sum(Gxl_refl, axis=0) * lambdastep Jsc_refl = np.sum(Gx_refl, axis=0) * stepsize * q * 1e3 print("Jsc Loss from reflection:") print(Jsc_refl) print("Jsc loss from parasitic absorption:") print(Jsc_parasitic) #save the data for the generation np.savetxt('Jsc_data.out', np.c_[Jsc, Jsc_refl, Jsc_parasitic], delimiter=',', header='Jsc,Jsc_refl,Jsc_parasitic') if calc_Q == 1: Gx_tot = np.sum(Gxl_tot, axis=0) * lambdastep #save the data for the generation np.savetxt('G_distribution.out', np.c_[t_a, Gx_tot], delimiter=',', header='Position,G') plt.figure(3) plt.clf() plt.plot(t_a, Gx_tot, 'blue') plt.vlines(np.cumsum(i_faces), 0, 1, colors='k', linestyles='solid', label='') plt.xlabel('x (nm)') plt.ylabel('Q') plt.title('Charge generation profile') plt.show() return Jsc return A_a_s, A_a_p, A_tot2 #JB
def solar_results(activeLayer, AL_thickness,theta,atWL,calc_Efield,calc_Jsc,calc_Jsc_loss,calc_Q): #JB # list of layer thicknesses in nm d_list[activeLayer]=AL_thickness # JB angle=theta th0=angle*np.pi/180 checkwavelength=atWL stepsize=1 # allocate lists of y-values to plot R_a_s=[] R_a_p=[] T_a_s=[] T_a_p=[] A_a_s=[] A_a_p=[] E_s=[] E_p=[] E_xyz_tot=[] PA_s=[] PA_p=[] Gxl=[] Gxl_tot=[] Gxl_refl=[] Gxl_parasitic=[] for i,wl in enumerate(wavelengths): n_list=n_k[:,i] #calculate all data coherent (returns more values) and incoherent coh_tmm_data_s = tmm.coh_tmm('s',n_list, d_list, angle*np.pi/180, wl) coh_tmm_data_p = tmm.coh_tmm('p',n_list, d_list, angle*np.pi/180, wl) incoh_tmm_data_s = tmm.inc_tmm('s',n_list, d_list, c_list, angle*np.pi/180, wl) incoh_tmm_data_p = tmm.inc_tmm('p',n_list, d_list, c_list, angle*np.pi/180, wl) #use for R,T,A R_a_s.append(incoh_tmm_data_s['R']) R_a_p.append(incoh_tmm_data_p['R']) T_a_s.append(incoh_tmm_data_s['T']) T_a_p.append(incoh_tmm_data_p['T']) A_a_s.append(tmm.inc_absorp_in_each_layer(incoh_tmm_data_s)) A_a_p.append(tmm.inc_absorp_in_each_layer(incoh_tmm_data_p)) E_s.append([]) E_p.append([]) E_xyz_tot.append([]) PA_s.append([]) PA_p.append([]) Gxl.append([]) Gxl_tot.append([]) Gxl_refl.append([]) Gxl_parasitic.append([]) #E-field for every layer different if calc_Efield==1: x_pos_abs=0 t=[] for j in range(stackBegin,len(d_list)-1): if j==1: vw_s = incoh_tmm_data_s['VW_list'][j] kz_s = coh_tmm_data_s['kz_list'][j] vw_p = incoh_tmm_data_p['VW_list'][j] kz_p = coh_tmm_data_p['kz_list'][j] else: vw_s = coh_tmm_data_s['vw_list'][j] kz_s = coh_tmm_data_s['kz_list'][j] th_s = coh_tmm_data_s['th_list'][j] vw_p = coh_tmm_data_p['vw_list'][j] kz_p = coh_tmm_data_p['kz_list'][j] th_p = coh_tmm_data_p['th_list'][j] alpha=4*np.pi*np.imag(n_k[j,i])/wl #at every point x x_pos_rel=0 for x in range(x_pos_abs,x_pos_abs+d_list[j]+1): t.append(x) E_plus_s=vw_s[0] * np.exp(1j * kz_s * x_pos_rel) E_minus_s=vw_s[1] * np.exp(-1j * kz_s * x_pos_rel) E_plus_p=vw_p[0] * np.exp(1j * kz_p * x_pos_rel) E_minus_p=vw_p[1] * np.exp(-1j * kz_p * x_pos_rel) E_pos_s=E_plus_s + E_minus_s E_pos_p=E_plus_p + E_minus_p E_s[i].append(E_pos_s) E_p[i].append(E_pos_p) E_z_pos=E_pos_s/np.sqrt(np.cos(th0)) E_y_pos=E_pos_p*np.cos(th_p)/np.sqrt(np.cos(th0)) E_x_pos=((-1)*E_plus_p + E_minus_p)*n_list[0]*np.sin(th0)/(n_list[j]*np.sqrt(np.cos(th0))) E_xyz_pos=0.5*np.square(np.absolute(E_z_pos))+0.5*(np.square(np.absolute(E_y_pos))+np.square(np.absolute(E_x_pos))) E_xyz_tot[i].append(E_xyz_pos) Q_pos_xyz=alpha*np.real(n_k[j,i])*power[i]*E_xyz_pos #calculate Energy dissipation and exciton generation rate if j==activeLayer: Gxl[i].append(Q_pos_xyz*1e-3*wl*1e-9/(h*c)); Gxl_tot[i].append(Q_pos_xyz*1e-3*wl*1e-9/(h*c)); else: Q_pos_xyz=alpha*np.real(n_k[j,i])*power[i]*(0.5*np.square(np.absolute(E_z_pos))+0.5*(np.square(np.absolute(E_y_pos))+np.square(np.absolute(E_x_pos)))) Gxl_parasitic[i].append(Q_pos_xyz*1e-3*wl*1e-9/(h*c)); Gxl_tot[i].append(Q_pos_xyz*1e-3*wl*1e-9/(h*c)); R_frac=0.5*incoh_tmm_data_s['R']+0.5*incoh_tmm_data_p['R'] Q_pos_xyz=Q_pos_xyz*(R_frac/(1-R_frac)) Gxl_refl[i].append(Q_pos_xyz*1e-3*wl*1e-9/(h*c)); #calculate pointing vectors #PA_s[i].append(tmm.position_resolved(j, x_pos_rel, coh_tmm_data_s)['poyn']) #PA_p[i].append(tmm.position_resolved(j, x_pos_rel, coh_tmm_data_p)['poyn']) x_pos_rel+=1 x_pos_abs+=d_list[j] #convert all lists to arrays for plotting R_a_s=np.array(R_a_s) R_a_p=np.array(R_a_p) T_a_s=np.array(T_a_s) T_a_p=np.array(T_a_p) A_a_s=np.array(A_a_s) A_a_p=np.array(A_a_p) #get the 50% polarized fields R_a_tot=0.5*(R_a_s+R_a_p) T_a_tot=0.5*(T_a_s+T_a_p) A_tot=0.5*A_a_s+0.5*A_a_p A_tot2=A_tot # JB #plot A in each layer # JB plt.figure(6) plt.clf() plt.plot(wavelengths,A_tot2[:,activeLayer],'blue',label="A_perov") plt.xlabel('wavelength (nm)') plt.ylabel('A') plt.title('Our plot at %s'%angle) plt.legend() plt.show() np.savetxt('A_tot.out', np.c_[wavelengths,A_tot], delimiter=',') # JB # delete first and last layer A_tot = np.delete(A_tot, 0, 1) # delete first column of C A_tot = np.delete(A_tot, -1, 1) # delete last column of C A_tot=A_tot.sum(axis=1) #save the data np.savetxt('RTA.out', np.c_[wavelengths,T_a_tot,R_a_tot,A_tot,T_a_tot+R_a_tot+A_tot], delimiter=',',header='Wavelength,T,R,A,Sum') #plot the results for R,T,A plt.close('all') plt.figure(1) plt.clf() plt.plot(wavelengths,T_a_tot,'blue',label="Transmission") plt.plot(wavelengths,R_a_tot,'purple',label="Reflection") plt.plot(wavelengths,A_tot,'red',label="Absorption") plt.plot(wavelengths,T_a_tot+R_a_tot+A_tot,'green',label="Sum") plt.xlabel('wl (nm)') plt.ylabel('Fraction reflected') plt.title('Our plot at %s'%angle) plt.legend() plt.ylim([0,0.2]) # JB plt.xlim([300,850]) # JB plt.show() if calc_Efield==1: t_a=np.array(t) i_faces= np.array(d_list) i_faces = np.delete(i_faces, 0) # delete first column of C i_faces = np.delete(i_faces, 0) # delete second column of C i_faces = np.delete(i_faces, -1) # delete last column of C #calculate power of E-fields for s and p E_a_s=np.array(E_s) E_a_p=np.array(E_p) E_2_s=np.square(np.absolute(E_s[wavelengths.index(checkwavelength)])) E_2_p=np.square(np.absolute(E_p[wavelengths.index(checkwavelength)])) #save the data for the efield np.savetxt('E2_distribution.out', np.c_[t_a,E_2_s,E_2_p,E_2_s*0.5+E_2_p*0.5], delimiter=',',header='Position,E2_s,E2_p,E2_tot') #plot E field distrubtion plt.figure(2) plt.clf() plt.plot(t_a,E_2_s,'blue',label="s-pol") plt.plot(t_a,E_2_p,'red',label="p-pol") plt.plot(t_a,E_2_s*0.5+E_2_p*0.5,'green',label="Tot") plt.vlines(np.cumsum(i_faces), 0, 1, colors='k', linestyles='solid', label='') plt.xlabel('x (nm)') plt.ylabel('E2') plt.title('Our plot at %s'%angle) plt.legend() plt.show() #calculate generation and Jsc if calc_Jsc==1: lambdastep=1 if np.size(wavelengths)>1: lambdastep=(np.amax(wavelengths)-np.amin(wavelengths))/(np.size(wavelengths)-1) Gx=np.sum(Gxl,axis=0)*lambdastep; Jsc=np.sum(Gx,axis=0)*stepsize*q*1e3 print("Jsc:") print(Jsc) if calc_Jsc_loss==1: Gx_parasitic=np.sum(Gxl_parasitic,axis=0)*lambdastep; Jsc_parasitic=np.sum(Gx_parasitic,axis=0)*stepsize*q*1e3 Gx_refl=np.sum(Gxl_refl,axis=0)*lambdastep; Jsc_refl=np.sum(Gx_refl,axis=0)*stepsize*q*1e3 print("Jsc Loss from reflection:") print(Jsc_refl) print("Jsc loss from parasitic absorption:") print(Jsc_parasitic) #save the data for the generation np.savetxt('Jsc_data.out', np.c_[Jsc,Jsc_refl,Jsc_parasitic], delimiter=',',header='Jsc,Jsc_refl,Jsc_parasitic') if calc_Q==1: Gx_tot=np.sum(Gxl_tot,axis=0)*lambdastep; #save the data for the generation np.savetxt('G_distribution.out', np.c_[t_a,Gx_tot], delimiter=',',header='Position,G') plt.figure(3) plt.clf() plt.plot(t_a,Gx_tot,'blue') plt.vlines(np.cumsum(i_faces), 0, 1, colors='k', linestyles='solid', label='') plt.xlabel('x (nm)') plt.ylabel('Q') plt.title('Charge generation profile') plt.show() return Jsc return A_a_s, A_a_p, A_tot2 #JB
def calculate_rat(structure, wavelength, angle=0, pol='u', coherent=True, coherency_list=None, no_back_reflexion=True): """ Calculates the reflected, absorbed and transmitted intensity of the structure for the wavelengths and angles defined. :param structure: A solcore Structure object with layers and materials or a OptiStack object. :param wavelength: Wavelengths (in nm) in which calculate the data. :param angle: Angle (in degrees) of the incident light. Default: 0 (normal incidence). :param pol: Polarisation of the light: 's', 'p' or 'u'. Default: 'u' (unpolarised). :param coherent: If the light is coeherent or not. If not, a coherency list must be added. :param coherency_list: A list indicating in which layers light should be treated as coeherent ('c') and in which incoherent ('i'). It needs as many elements as layers in the structure. :param no_back_reflexion: If reflexion from the back must be supressed. Default=True. :return: A dictionary with the R, A and T at the specified wavelengths and angle. """ num_wl = len(wavelength) if 'OptiStack' in str(type(structure)): stack = structure stack.no_back_reflexion = no_back_reflexion else: stack = OptiStack(structure, no_back_reflexion=no_back_reflexion) if not coherent: if coherency_list is not None: assert len(coherency_list) == stack.num_layers, \ 'Error: The coherency list must have as many elements (now {}) as the ' \ 'number of layers (now {}).'.format(len(coherency_list), stack.num_layers) coherency_list = ['i'] + coherency_list + ['i'] else: raise Exception( 'Error: For incoherent or partly incoherent calculations you must supply the ' 'coherency_list parameter with as many elements as the number of layers in the ' 'structure') output = { 'R': np.zeros(num_wl), 'A': np.zeros(num_wl), 'T': np.zeros(num_wl), 'all_p': [], 'all_s': [] } if pol in 'sp': if coherent: for i, wl in enumerate(wavelength): out = tmm.coh_tmm(pol, stack.get_indices(wl), stack.get_widths(), angle * degree, wl) output['R'][i] = out['R'] output['A'][i] = 1 - out['R'] - out['T'] output['T'][i] = out['T'] else: for i, wl in enumerate(wavelength): out = tmm.inc_tmm(pol, stack.get_indices(wl), stack.get_widths(), coherency_list, angle * degree, wl) output['R'][i] = out['R'] output['A'][i] = 1 - out['R'] - out['T'] output['T'][i] = out['T'] else: if coherent: for i, wl in enumerate(wavelength): out = tmm.unpolarized_RT(stack.get_indices(wl), stack.get_widths(), angle * degree, wl) output['R'][i] = out['R'] output['A'][i] = 1 - out['R'] - out['T'] output['T'][i] = out['T'] else: for i, wl in enumerate(wavelength): out_p = tmm.inc_tmm('p', stack.get_indices(wl), stack.get_widths(), coherency_list, angle * degree, wl) out_s = tmm.inc_tmm('s', stack.get_indices(wl), stack.get_widths(), coherency_list, angle * degree, wl) output['R'][i] = 0.5 * (out_p['R'] + out_s['R']) output['T'][i] = 0.5 * (out_p['T'] + out_s['T']) output['A'][i] = 1 - output['R'][i] - output['T'][i] output['all_p'].append(out_p['power_entering_list']) output['all_s'].append(out_s['power_entering_list']) return output
#IREQEs = [] #layerchoice = 4 layerchoice = 4 layerchoice2 = 5 for lam in lams: nks = [1] for layer in layers: nks.append(layer.nk(lam)) nks.append(1) nks_bw = nks[::-1] front_spol = tmm.inc_tmm('s', nks, thicks, iorcs, inc_angle, lam) front_ppol = tmm.inc_tmm('p', nks, thicks, iorcs, inc_angle, lam) back_spol = tmm.inc_tmm('s', nks_bw, thicks_bw, iorcs_bw, inc_angle, lam) back_ppol = tmm.inc_tmm('p', nks_bw, thicks_bw, iorcs_bw, inc_angle, lam) AbsByAbsorber_spol = tmm.inc_absorp_in_each_layer(front_spol)[layerchoice] AbsByAbsorber_ppol = tmm.inc_absorp_in_each_layer(front_ppol)[layerchoice] AbsByAbsorbers.append((AbsByAbsorber_spol + AbsByAbsorber_ppol) / 2.) # EQE_spol2 = tmm.inc_absorp_in_each_layer(front_spol)[layerchoice2] # EQE_ppol2 = tmm.inc_absorp_in_each_layer(front_ppol)[layerchoice2] # EQEs2.append( (EQE_spol2 + EQE_ppol2) / 2. ) Rfs.append((front_spol['R'] + front_ppol['R']) / 2.)