def getPolAbs(n, d, freq, theta): """ Gets Polarized Absorption of optical elements Parameters ---------- n : list Index of refraction for each element in the stack d : list Thickness for each element in the stack freq : float [Hz] Frequency theta: Incident angle """ lam_vac = c / freq * 1000. s = tmm.coh_tmm('s', n, d, theta, lam_vac) p = tmm.coh_tmm('p', n, d, theta, lam_vac) sA = 1 - s['T'] - s['R'] pA = 1 - p['T'] - p['R'] return -((sA - pA) / 2)
def spectrum(self, materials, thickness, theta=0, plot=False, title=False): ''' Input: materials: list thickness: list theta: degree, the incidence angle Return: s: array, spectrum ''' degree = pi / 180 if self.substrate != 'Air': thickness.insert(-1, self.substrate_thick) # substrate thickness R, T, A = [], [], [] for i, lambda_vac in enumerate(self.wavelength * 1e3): # we assume the last layer is glass if self.substrate == 'Glass': n_list = [1] + [self.nk_dict[mat][i] for mat in materials] + [1.45, 1] elif self.substrate == 'Air': n_list = [1] + [self.nk_dict[mat][i] for mat in materials] + [1] else: n_list = [1] + [self.nk_dict[mat][i] for mat in materials ] + [self.nk_dict[self.substrate][i], 1] # n_list = [1] + [self.nk_dict[mat][i] for mat in materials] + [self.nk_dict['Cr'][i]] # mport pdb; pdb.set_trace() res = coh_tmm('s', n_list, thickness, theta * degree, lambda_vac) if theta != 0: res_t = coh_tmm('p', n_list, thickness, theta * degree, lambda_vac) res['R'] = (res['R'] + res_t['R']) / 2 res['T'] = (res['T'] + res_t['T']) / 2 R.append(res['R']) T.append(res['T']) R, T = np.array(R), np.array(T) A = 1 - R - T if plot: self.plot_spectrum(R, T, A) if title: thick = thickness[1:-1] title = ' | '.join( ['{}nm {}'.format(d, m) for d, m in zip(thick, materials)]) if self.substrate is not 'Air': title = 'Air | ' + title + ' | {}nm {} '.format( self.substrate_thick, self.substrate) + '| Air' else: title = 'Air | ' + title + ' | Air' plt.title(title, **{'size': '10'}) # plt.show() return R, T, A
def test_sample1(): """ Here's a thin non-absorbing layer, on top of a thick absorbing layer, with air on both sides. Plotting reflected intensity versus wavenumber, at two different incident angles. """ # list of layer thicknesses in nm d_list = [inf, 100, 300, inf] # list of refractive indices n_list = [1, 2.2, 3.3 + 0.3j, 1] # list of wavenumbers to plot in nm^-1 ks = linspace(0.0001, .01, num=400) # initialize lists of y-values to plot Rnorm = [] R45 = [] # coh_tmm(pol, n_list, d_list, th_0, lam_vac) for k in ks: # For normal incidence, s and p polarizations are identical. # I arbitrarily decided to use 's'. Rnorm.append(coh_tmm('s', n_list, d_list, 0, 1 / k)['R']) R45.append(unpolarized_RT(n_list, d_list, 45 * degree, 1 / k)['R']) kcm = ks * 1e7 #ks in cm^-1 rather than nm^-1 plt.figure() plt.plot(kcm, Rnorm, 'blue', kcm, R45, 'purple') plt.xlabel('k (cm$^{-1}$)') plt.ylabel('Fraction reflected') plt.title('Reflection of unpolarized light at 0$^\circ$ incidence (blue), ' '45$^\circ$ (purple)') plt.show() return 0
def calc_rt_pytmm(pol, omega, kx, n, d): """API-compatible wrapper around pytmm """ vec_omega = omega.numpy() vec_lambda = C0 / vec_omega * 2 * np.pi vec_n = n.numpy() vec_d = d.numpy() vec_d = np.append(np.inf, vec_d) vec_d = np.append(vec_d, np.inf) vec_kx = kx.numpy().reshape([-1, 1]) vec_k0 = 2 * np.pi / vec_lambda.reshape([1, -1]) vec_theta = np.arcsin(vec_kx / vec_k0) r = np.zeros((len(kx), len(omega)), dtype=np.complex64) t = np.zeros((len(kx), len(omega)), dtype=np.complex64) for i, theta in enumerate(vec_theta): for j, lam in enumerate(vec_lambda): out = coh_tmm(pol, vec_n, vec_d, theta[j], lam) r[i, j] = out['r'] t[i, j] = out['t'] t = tf.constant(t) r = tf.constant(r) return tf.constant(t), tf.constant(r)
def FabryPerotTest(): lam_vac = linspace(0.75, 1.7, 100) n_outside = 1 n_inside = 3 thickness = 1 incidence_angle = 0 reflectance, transmittance = FabryPerot(lam_vac, n_outside, n_inside, thickness, incidence_angle) # list of layer thicknesses in nm d_list = [inf, thickness, inf] # list of refractive indices n_list = [n_outside, n_inside, n_outside] Rnorm = [] Tnorm = [] for lam_vac_current in lam_vac: result = coh_tmm('s', n_list, d_list, 0, lam_vac_current) Rnorm.append(result['R']) Tnorm.append(result['T']) plt.figure() plt.plot(lam_vac, reflectance, 'red') plt.plot(lam_vac, transmittance, 'blue') plt.plot(lam_vac, Rnorm, 'ro') plt.plot(lam_vac, Tnorm, 'bo') plt.xlabel('$\lambda$ (nm)') plt.ylabel('reflectance, transmittance') plt.title( 'reflectance (red), transmittance (blue) of unpolarized light at 0$^\circ$ incidence' ) plt.show()
def Theory(): th = tarwave / (4 * nh) tl = tarwave / (4 * nl) print('tarwave: {}, nh: {:.3f}, nl: {:.3f}'.format(tarwave, nh, nl)) print('Th: {}, Tl: {}'.format(th, tl)) n_list = [1, nh, nl, nh, nl, nh, nl, nh, 1] d_list = [np.inf, th, tl, th, tl, th, tl, th, np.inf] start = time.time() Rnorm = [] for w in wavelength[0]: Rnorm.append(tmm.coh_tmm('s', n_list, d_list, 0, w)['R']) print("time: ", time.time() - start) Rnorm = np.reshape(Rnorm, newshape=(1, wavelength.shape[1])) fwhml, fwhmf = pixelDBR.calBand(Rnorm, wavelength, tarwave, minwave, wavestep, 0.5) b99l, b99f = pixelDBR.calBand(Rnorm, wavelength, tarwave, minwave, wavestep, 0.99) print("======== Result ========") print('THeory fwhm: {} um, {:.3f} THz'.format(fwhml, fwhmf * 10**-12)) print('THeory 99% width: {} um, {:.3f} THz'.format(b99l, b99f * 10**-12)) plt.figure(1) x = np.reshape(wavelength, wavelength.shape[1]) Rnorm = np.reshape(Rnorm, wavelength.shape[1]) plt.plot(x, Rnorm) plt.figure(2) x = (c * (1. / wavelength)) x = np.reshape(x, wavelength.shape[1]) Rnorm = np.reshape(Rnorm, wavelength.shape[1]) plt.plot(x, Rnorm) plt.show()
def calc_reflectances(n_fn_list, d_list, th_0, pol='s', spectral_range='narrow'): """ Calculate the reflection spectrum of a thin-film stack. n_fn_list[m] should be a function that inputs wavelength in nm and outputs refractive index of the m'th layer. In other words, n_fn_list[2](456) == 1.53 + 0.4j mans that layer #2 has a refractive index of 1.53 + 0.4j at 456nm. These functions could be defined with scipy.interpolate.interp1d() for example. pol, d_list and th_0 are defined as in tmm.coh_tmm ... but d_list MUST be in units of nanometers spectral_range can be 'full' if all the functions in n_fn_list can take wavelength arguments between 360-830nm; or 'narrow' if some or all require arguments only in the range 400-700nm. The wavelengths outside the 'narrow' range make only a tiny difference to the color, because they are almost invisible to the eye. If spectral_range is 'narrow', then the n(400) values are used for 360-400 and n(700) for 700-830nm Returns a 2-column array where the first column is wavelength in nm (360,361,362,...,830) and the second column is reflectivity (from 0 to 1, where 1 is a perfect mirror). This range is chosen to be consistent with colorpy.illuminants. See colorpy.ciexyz.start_wl_nm etc. """ lam_vac_list = arange(360, 831) num_layers = len(n_fn_list) def extend_spectral_range(n_fn): """ Starting with a narrow-spectrum refractive index function n_fn(wavelength), create then return the corresponding full-spectrum refractive index function """ def extended_n_fn(lam): if lam < 400: return n_fn(400) elif lam > 700: return n_fn(700) else: return n_fn(lam) return extended_n_fn if spectral_range == 'narrow': n_fn_list = [extend_spectral_range(n_fn) for n_fn in n_fn_list] final_answer = [] for lam_vac in lam_vac_list: n_list = [n_fn_list[i](lam_vac) for i in range(num_layers)] R = tmm.coh_tmm(pol, n_list, d_list, th_0, lam_vac)['R'] final_answer.append([lam_vac,R]) final_answer = array(final_answer) return final_answer
def R(stack): R_list = [] for lambda_vac in LAMBDAS: n_list = [1] for layer in range(0,stack.num): n1 = round(get_r_index.get_cplx(stack.period.lay1.material, lambda_vac),4) n_list.append(n1) n2 = round(get_r_index.get_cplx(stack.period.lay2.material, lambda_vac),4) n_list.append(n2) n_list.append(round(get_r_index.get_cplx('c-Si', lambda_vac), 4)) R_list.append(tmm.coh_tmm('s', n_list, make_d_list(stack), ANGLE, lambda_vac)['R']) return R_list
def calR(s, dx, N_pixel, wavelength, nh, nl): # list of layer thickness in nm d_list = [np.inf] + [dx for i in range(N_pixel)] + [np.inf] # list of refractive nht = nh * (s == 1).astype(int) nlt = nl * (s == 0).astype(int) nt = nht + nlt n_list = [1] + nt.tolist() + [1] # initialize lists of y-values Rnorm = [] for w in wavelength[0]: Rnorm.append(tmm.coh_tmm('s', n_list, d_list, 0, w)['R']) return Rnorm
def getIP(n, d, freq, theta): """ Gets IP of optical elements Parameters ---------- n : list Index of refraction for each element in the stack d : list Thickness for each element in the stack freq : float [Hz] Frequency theta: Incident angle """ lam_vac = c / freq * 1000. # lam_vac = 2.0 s = tmm.coh_tmm('s', n, d, theta, lam_vac) p = tmm.coh_tmm('p', n, d, theta, lam_vac) return -(s['T'] - p['T']) / 2
def calculate_absorption_profile(structure, wavelength, z_limit=None, steps_size=2, dist=None, no_back_reflexion=True): """ It calculates the absorbed energy density within the material. From the documentation: 'In principle this has units of [power]/[volume], but we can express it as a multiple of incoming light power density on the material, which has units [power]/[area], so that absorbed energy density has units of 1/[length].' Integrating this absorption profile in the whole stack gives the same result that the absorption obtained with calculate_rat as long as the spacial mesh (controlled by steps_thinest_layer) is fine enough. If the structure is very thick and the mesh not thin enough, the calculation might diverege at short wavelengths. For now, it only works for normal incident, coherent light. :param structure: A solcore structure with layers and materials. :param wavelength: Wavelengths in which calculate the data (in nm). An array-like object. :param z_limit: Maximum value in the z direction :return: A dictionary containing the positions (in nm) and a 2D array with the absorption in the structure as a function of the position and the wavelength. """ 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 dist is None: if z_limit is None: z_limit = np.sum(np.array(stack.widths)) dist = np.arange(0, z_limit, steps_size) output = {'position': dist, 'absorption': np.zeros((num_wl, len(dist)))} for i, wl in enumerate(wavelength): out = tmm.coh_tmm('p', stack.get_indices(wl), stack.get_widths(), 0, wl) for j, d in enumerate(dist): layer, d_in_layer = tmm.find_in_structure_with_inf( stack.get_widths(), d) data = tmm.position_resolved(layer, d_in_layer, out) output['absorption'][i, j] = data['absor'] return output
def cal_pop_fitness(coating_complex_functions, substrate_complex_function, new_population, min, max, type): fitness = np.ones(new_population.shape[0])*(-99999999999) for i in range(new_population.shape[0]): lamda_size = (max-min)//10+1 lamdas = np.linspace(min, max, num = lamda_size) # print('wavelength ranges is', lamdas) reflections = [] for wa in lamdas: refractive_element = [1] for k in range(len(coating_complex_functions)): refractive_element.append(coating_complex_functions[k](wa)) refractive_element.append(substrate_complex_function(wa)) reflections.append(tmm.coh_tmm('s', refractive_element, new_population[i].tolist(), 0, wa)['R']) if type == 'Antireflection': fitness[i] = 1-np.average(reflections) if type == 'Highreflection': fitness[i] = np.average(reflections) return fitness
def thick_slab_reflectance_tmm(polarization, index_substrate, aoi, wavelength): """ Reflection from a thick slab of material. Parameters ---------- polarization : str Light polarization, can be "s" or "p" or "mixed" index_substrate : (N,) ndarray Index of refraction of the slab of material evaluated at the wavelengths specified in the `wavelength` input. aoi : float Angle of incidence in degrees wavelength : (N,) ndarray wavelength in nm, must be the same length as index_substrate. Returns ------- """ wavelength = wavelength.astype('float') degree = pi / 180 R = np.zeros_like(wavelength) if polarization in ['s', 'p']: for j in range(len(R)): R[j] = coh_tmm(polarization, [1.0003, index_substrate[j]], [inf, inf], aoi * degree, wavelength[j])['R'] elif polarization == 'mixed': for j in range(len(R)): R[j] = unpolarized_RT([1.0003, index_substrate[j]], [inf, inf], aoi * degree, wavelength[j])['R'] else: raise Exception("polarization must be 's','p' or 'mixed'") return R
def main(): while True: try: num = int(input('Number of periods: ')) d = int(input('Thickness of one period (nm): ')) layer1 = int( input('Thickness of the first layer in a period (nm): ')) mode = input('Transmission (t) or Ellipsometry (e)? ') break except: print('Thats not a valid option!') aperiod = period(d, layer1) # Setting up the list with thicknesses d_list = [inf] # starts with air at infinity for periods in range(0, num): d_list.append(aperiod.get_layer1()) if aperiod.get_layer2() != 0: d_list.append(aperiod.get_layer2()) d_list.append(inf) # end with wafer(?) at infinity # # Starting the calculations: if mode == 't': T_list = [] for lambda_vac in lambda_list: # Setting up the list with indices of refraction n_list = [1] # starts with air for periods in range(0, num): n_list.append(get_r_index.get_cplx('ITO', lambda_vac)) if aperiod.get_layer2() not 0: n_list.append(get_r_index.get_cplx('Al', lambda_vac)) n_list.append(3.49 + 0) # Si (wafer) T_list.append( tmm.coh_tmm('s', n_list, d_list, 70 * degree, lambda_vac)['T']) plt.figure() plt.xlabel('Wavelength (nm)') plt.ylabel('Fraction of power Transmitted') plt.plot(lambda_list, T_list)
def calR(s, Nslice, wavelength, nh, nl, high: bool): # list of layer thickness in nm d_list = [np.inf] + s.tolist() + [np.inf] # list of refractive indices nt = np.empty(s.shape) for i in range(Nslice): if high: # high index material start if (i % 2) == 1: nt[i] = nl else: nt[i] = nh else: # low index material start if (i % 2) == 1: nt[i] = nh else: nt[i] = nl n_list = [1] + nt.tolist() + [1] # initialize lists of y-values Rnorm = [] for w in wavelength[0]: Rnorm.append(tmm.coh_tmm('s', n_list, d_list, 0, w)['R']) return Rnorm
def r_fn_coh(d): coh_res = coh_tmm('s', [n_air, n_glass, n_air], [np.inf, d, np.inf], 0, wavelength) return coh_res['r']
def calculateoptimaldesign(request, id): design_condition = {} coat_mat = [] coat_mat_id = [] working_min = list( OptimalFilmDesign.objects.filter(id=id).values_list("wave_min", flat=True)) working_max = list( OptimalFilmDesign.objects.filter(id=id).values_list("wave_max", flat=True)) plot_min = [working_min[0] - 100] plot_max = [working_max[0] + 100] for i in range(1, 5): mat = list( OptimalFilmDesign.objects.filter(id=id).values_list("material_%d" % (i), flat=True))[0] search = Pages.objects.filter(book=mat, hasrefractive=1, hasextinction=1, rangeMax__gte=working_max[0] / 1000, rangeMin__lte=working_min[0] / 1000).values_list("pageid", flat=True) if search.exists(): mat_id = search else: mat_id = Pages.objects.filter(book=mat, hasrefractive=1, rangeMax__gte=working_max[0] / 1000, rangeMin__lte=working_min[0] / 1000).values_list("pageid", flat=True) if mat_id.exists(): coat_mat_id.append(list(mat_id)[0]) coat_mat_id = list(set(coat_mat_id)) for m in range(len(coat_mat_id)): new = OpticalMaterial(coat_mat_id[m]) new.get_refractives() coat_mat.append(new) working_min.append(new.minwave) working_max.append(new.maxwave) plot_min.append(new.minwave) plot_max.append(new.maxwave) sub_mat_name = list( OptimalFilmDesign.objects.filter(id=id).values_list( "material_substrate", flat=True))[0] search_sub = Pages.objects.filter(book=sub_mat_name, hasrefractive=1, hasextinction=1).values_list("pageid", flat=True) if search_sub.exists(): substrate_mat_id = list(search_sub)[0] else: substrate_mat_id = list( Pages.objects.filter(book=sub_mat, hasrefractive=1).values_list("pageid", flat=True))[0] substrate = OpticalMaterial(substrate_mat_id) substrate.get_refractives() working_min.append(substrate.minwave) working_max.append(substrate.maxwave) plot_min.append(substrate.minwave) plot_max.append(substrate.maxwave) design_condition['substrate'] = substrate design_condition['coat_material'] = coat_mat design_condition['minrange'] = max(working_min) design_condition['maxrange'] = min(working_max) design_condition['maxthickness'] = list( OptimalFilmDesign.objects.filter(id=id).values_list("max_thickness", flat=True))[0] design_condition['goal'] = list( OptimalFilmDesign.objects.filter(id=id).values_list("filmtype", flat=True))[0] best_design = optimizedesign(design_condition['substrate'], design_condition['coat_material'], design_condition['minrange'], design_condition['maxrange'], design_condition['maxthickness'], design_condition['goal']) if best_design != None: best_coatings = best_design[0] best_ds = best_design[1][0][0] best_reflection = best_design[2][0] plot_min = max(plot_min) plot_max = min(plot_max) lamdas = list(np.linspace(plot_min, plot_max, num=100)) coating_complex_functions = [] best_coatings_names = [] for i in range(len(best_coatings)): function = best_coatings[i].get_complex_function() coating_complex_functions.append(function) best_coatings_names.append(best_coatings[i].name) substrate_complex_function = substrate.get_complex_function() plot_reflection = [] plot_transmission = [] for wa in lamdas: refractive_element = [1] for k in range(len(coating_complex_functions)): # print(coating_refractive_functions[i](medium_wavelength)) refractive_element.append(coating_complex_functions[k](wa)) refractive_element.append(substrate_complex_function(wa)) # print(refractive_element) plot_reflection.append( tmm.coh_tmm('s', refractive_element, best_ds.tolist(), 0, wa)['R']) plot_transmission.append( tmm.coh_tmm('s', refractive_element, best_ds.tolist(), 0, wa)['T']) coating_thickness_lib = [] for ele in range(len(best_coatings_names)): element = {} element['order'] = ele + 1 element['name'] = best_coatings_names[ele] element['thickness'] = best_ds[ele + 1] coating_thickness_lib.append(element) else: best_coatings = None best_ds = None best_reflection = None best_coatings_names = None lamdas = None plot_reflection = None plot_transmission = None coating_thickness_lib = [] coating_materials = Pages.objects.filter(pageid__in=coat_mat_id) substrate_material = Pages.objects.filter(pageid=substrate_mat_id) context = { 'coat_mat': coating_materials, 'substrate_mat': substrate_material, 'design_condition': design_condition, 'plot_wave': lamdas, 'plot_reflection': plot_reflection, 'plot_transmission': plot_transmission, 'best_coating_name': best_coatings_names, 'best_design_thickness': best_ds, 'best_design_coatings': coating_thickness_lib, 'best_reflectance': best_reflection, } return render(request, 'optical_parameter/calculateoptimalfilm.html', context)
def design(request): incident_angle = request.GET.get("Incident_angle") incident_angle_radians = 0 if incident_angle != None: incident_angle_radians = math.radians(float(incident_angle)) if incident_angle == None: incident_angle = 0 lamda_poynting = request.GET.get("lamda_poynting") if lamda_poynting == None: lamda_poynting = 400 if request.user.is_authenticated: design = Film.objects.filter(optical_designer_id=request.user.id) else: design = Film.objects.filter(optical_designer_id=1) mat_type = list(design.values_list("type", flat=True)) mat_mat = list(design.values_list("material", flat=True)) mat_thick = [np.inf] mat_thickness = list(design.values_list("thickness", flat=True)) mat_thick = mat_thick + mat_thickness + [np.inf] mat_layer = list(design.values_list("layer_sequence", flat=True)) working_min = [] working_max = [] object = [] refractives = [] refrac_fns = [] miss_ex_mats = [] for i in range(0, len(mat_type)): results = Pages.objects.filter(book=str(mat_mat[i]), hasrefractive=1, hasextinction=1).values_list("pageid", flat=True) if results.exists(): objects = results else: objects = Pages.objects.filter(book=str(mat_mat[i]), hasrefractive=1).values_list( "pageid", flat=True) if objects.exists(): object.append(objects[0]) mat_refractiveindex = Refractiveindex.objects.filter( pageid_id=objects[0]) mat_excoeff = Extcoeff.objects.filter(pageid_id=objects[0]) wave_r = list(mat_refractiveindex.values_list("wave", flat=True)) wave_re = [i * 1000 for i in wave_r] n_re = list(mat_refractiveindex.values_list("refindex", flat=True)) wave_e = list(mat_excoeff.values_list("wave", flat=True)) wave_ex = [i * 1000 for i in wave_e] k_ex = [0.000000001] * len(wave_re) if mat_excoeff.exists(): k_ex = list(mat_excoeff.values_list("coeff", flat=True)) else: miss_ex_mats.append( list( Pages.objects.filter(pageid=objects[0]).values_list( "book", flat=True))[0]) refrac_element = [] for wa in range(0, len(wave_re)): refrac_element.append( [wave_re[wa], complex(n_re[wa], k_ex[wa])]) # print(refrac_element) refrac_array = np.array(refrac_element) refractives.append(refrac_array) n_fn = interpolate.interp1d(refrac_array[:, 0].real, refrac_array[:, 1], kind='quadratic') refrac_fns.append(n_fn) working_min.append(min(refrac_array[:, 0].real)) working_max.append(max(refrac_array[:, 0].real)) working_range = [0, 0] if len(working_max) > 0: working_range = [max(working_min), min(working_max)] lamdas = list(np.linspace(working_range[0], working_range[1], 100)) Rnorm = [] Tnorm = [] d_list = mat_thick for lamda in lamdas: # For normal incidence, s and p polarizations are identical. # I arbitrarily decided to use 's'. n_list = [1] for lay in range(0, len(mat_type)): n_list.append(refrac_fns[lay](lamda)) n_list.append(1) Rnorm.append( tmm.coh_tmm('s', n_list, d_list, incident_angle_radians, lamda)['R']) Tnorm.append( tmm.coh_tmm('s', n_list, d_list, incident_angle_radians, lamda)['T']) coh_tmm_data_s = tmm.coh_tmm('s', n_list, d_list, incident_angle_radians, lamda_poynting) coh_tmm_data_p = tmm.coh_tmm('p', n_list, d_list, incident_angle_radians, lamda_poynting) ds = np.linspace(0, sum(d_list[1:-1]), num=100) poyn = [] absor = [] for d in ds: layer, d_in_layer = tmm.find_in_structure_with_inf(d_list, d) data = tmm.position_resolved(layer, d_in_layer, coh_tmm_data_s) poyn.append(data['poyn']) absor.append(data['absor']) ds = list(ds) context = { 'Design': design, 'Wavelength': lamdas, 'Reflectance': Rnorm, 'Transmitance': Tnorm, 'Working_range': working_range, 'Angle': incident_angle, 'Absorption': absor, 'Ponyting': poyn, 'Depth': ds, 'Miss_ex_mat': miss_ex_mats, } return render(request, 'optical_parameter/design.html', context)
def getCoeffs(n, d, freq, theta, pol): """Returns T, R, A coefficients for an optical stack of polarization pol ('s' or 'p')""" lam_vac = c / freq * 1000 #vacuum wavelength in mm s = tmm.coh_tmm(pol, n, d, theta, lam_vac) return [s['T'], s['R'], 1 - s['T'] - s['R']]
import numpy as np import matplotlib.pyplot as plt import tmm degree = np.pi/180 # list of layer thicknesses in nm d_list = [tmm.inf, 5, tmm.inf] # list of refractive indices n_list = [1, 2.68, 1] nabs_list = [1 ,2.68+0.01j, 1] # list of wavenumbers to plot in nm^-1 lams = np.linspace(1, 1.25, num=400) # initialize lists of y-values to plot Rnorm = [] Rabs = [] for lam in lams: # For normal incidence, s and p polarizations are identical. # I arbitrarily decided to use 's'. Rnorm.append(tmm.coh_tmm('s', n_list, d_list, 0, lam)['R']) #R45.append(tmm.unpolarized_RT(n_list, d_list, 45*degree, lam)['R']) Rabs.append(tmm.coh_tmm('s', nabs_list, d_list, 0, lam)['R']) plt.figure() plt.plot(lams, Rnorm, 'blue', lams, Rabs, 'purple') plt.xlabel('$\lambda$ ($\mu$m)') plt.ylabel('Fraction reflected') plt.title('Modest page 56') plt.show()
def thin_film_reflectance_tmm(polarization, index_film, index_substrate, film_thickness, aoi, wavelength, vectorize=False): """ Calculate reflection from a thin film on a substrate. dimensions in nm. Parameters ---------- polarization index_film index_substrate film_thickness aoi wavelength vectorize Returns ------- """ degree = pi / 180 wavelength = wavelength.astype('float') d_list = [np.inf, film_thickness, np.inf] index_air = 1.0003 R = np.zeros_like(wavelength) if polarization in ['s', 'p']: for j in range(len(R)): n_list = [1.0003, index_film[j], index_substrate[j]] R[j] = coh_tmm(polarization, n_list, d_list, aoi * degree, wavelength[j])['R'] elif polarization == 'mixed': if vectorize: def unpolarized_RT_func( index_film, index_substrate, aoi, film_thickness, wavelength, ): return unpolarized_RT( n_list=[index_air, index_film, index_substrate], d_list=[np.inf, film_thickness, np.inf], th_0=aoi * degree, lam_vac=wavelength)['R'] unpolarized_RT_vectorized = np.vectorize(unpolarized_RT_func) R = unpolarized_RT_vectorized(index_film, index_substrate, aoi, film_thickness, wavelength) print('vectorized done') else: for j in range(len(R)): n_list = [index_air, index_film[j], index_substrate[j]] R[j] = unpolarized_RT(n_list, d_list, aoi * degree, wavelength[j])['R'] else: raise Exception("polarization must be 's','p' or 'mixed'") return R
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
n_list.append(n_vacuum) distance_list = np.real( distance_list) # Avoids an error that distances have imaginary component # The wavelengths we want to analyse wave_length_list = np.linspace(target_wave_length - wave_length_delta, target_wave_length + wave_length_delta, samples) # These arrays will contain the results of our calculations reflection_list = [] transmission_list = [] absorption_list = [] for wave_length in wave_length_list: coh_tmm_result = tmm.coh_tmm(polarization, n_list, distance_list, theta0, wave_length) tmm_absorption_result = np.sum( tmm.absorp_in_each_layer(coh_tmm_result)[1:-1]) reflection_list.append(coh_tmm_result['R']) transmission_list.append(coh_tmm_result['T']) absorption_list.append(tmm_absorption_result) # Plot RT plt.title('Transmission and reflection for various wave lengths') plt.plot(wave_length_list, transmission_list, label="T") plt.plot(wave_length_list, reflection_list, label="R") plt.xlabel('Wavelength (nm)') plt.ylabel('Fraction of incoming power')
n.append(n0**(2. / 3)) d.append(lam0 / (4.0 * real(n0)**(2. / 3))) n.append(n0) d.append(2.0) n.append(n0**(2. / 3)) d.append(lam0 / (4.0 * real(n0)**(2. / 3))) n.append(n0**(1. / 3)) d.append(lam0 / (4.0 * real(n0)**(1. / 3))) n.append(1.0) d.append(inf) ips = [] lam_vac = 299.792458 / 150. # p-wave p = tmm.coh_tmm('p', n, d, deg2rad(12.5), lam_vac) # s-wave s = tmm.coh_tmm('s', n, d, deg2rad(12.5), lam_vac) # ips += [(p['T']-s['T'])/2.0] for f in frequency: lam_vac = 299.792458 / f # p-wave p = tmm.coh_tmm('p', n, d, deg2rad(12.5), lam_vac) # s-wave s = tmm.coh_tmm('s', n, d, deg2rad(12.5), lam_vac) ips += [(p['T'] - s['T']) / (p['T'] + s['T'])] print(mean(ips[130:171]))
def test_DBR(args): # .. todo:: find way to visualize DBR, maybe TMM module has something for that or use PIL module or similar n_low = 2.94 n_high = 3.55 n_cav = n_high wavelength_0_nm = 910 t_low = wavelength_0_nm / (4 * n_low) t_high = wavelength_0_nm / (4 * n_high) t_cav = 4 * wavelength_0_nm / (4 * n_high) # TMM for 33/24 DBR with lambda cavity leads to Q = 3.1335e+05 #lam_range = 0.01 #N_top = 24 ##N_bottom = 16 # 33 #N_bottom = 33 #int(round(N_top*33/24)) #lam_range = args.lam_range N_top = args.N_top N_bottom = args.N_bottom # list of layer thicknesses in nm # list of refractive indices d_list = [inf] n_list = [1] for i in range(N_top): d_list.extend([t_high, t_low]) n_list.extend([n_high, n_low]) if args.no_cavity: d_list.extend([t_high]) n_list.extend([n_high]) else: d_list.extend([t_cav]) n_list.extend([n_cav]) for i in range(N_bottom): d_list.extend([t_low, t_high]) n_list.extend([n_low, n_high]) d_list.extend([inf]) n_list.extend([1]) print(d_list) print(n_list) print(len(d_list)) print(len(n_list)) # lambda range to use main_points = [wavelength_0_nm] for r in args.lam_range: main_points.append(wavelength_0_nm - r) main_points.append(wavelength_0_nm + r) main_points.sort() print('main_points = {}'.format(main_points)) lam_vac = linspaces(main_points, (len(main_points) - 1) * [args.Npoints]) #print('lam_vac = {}'.format(lam_vac)) #raise #if lam_range <= 0.01: #lam_vac = linspace(wavelength_0_nm-lam_range, wavelength_0_nm+lam_range, args.Npoints) #else: #lam_vac = linspaces(wavelength_0_nm-lam_range, wavelength_0_nm-0.01, wavelength_0_nm+lam_range, args.Npoints,wavelength_0_nm+lam_range, args.Npoints) Rnorm = [] Tnorm = [] for lam_vac_current in lam_vac: result = coh_tmm('s', n_list, d_list, 0, lam_vac_current) Rnorm.append(result['R']) Tnorm.append(result['T']) info = DBRinfo(n_low, n_high) print(info) a = t_high + t_low lam_bot = a / info['topgap'] lam_mid = a / info['midgap'] lam_top = a / info['botgap'] print([lam_bot, lam_mid, lam_top]) Tnorm = numpy.array(Tnorm) if args.normalize: Tnorm = Tnorm / max(Tnorm) plt.figure() if args.plot_reflection: plt.plot(lam_vac, Rnorm, 'r') plt.plot(lam_vac, Tnorm, 'b') #plt.axvline(lam_bot, linestyle='--', color='g') plt.axvline(lam_mid, linestyle='--', color='g') #plt.axvline(lam_top, linestyle='--', color='g') plt.xlabel('$\lambda$ (nm)') plt.ylabel('reflectance, transmittance') plt.title( 'reflectance (red), transmittance (blue) of unpolarized light at 0$^\circ$ incidence' ) plt.show() if args.csvfile: csvfile = args.csvfile else: csvfile = 'DBR_Nbot-{}_Ntop-{}_N-{}_r-{}_norm-{}_cav-{}.csv'.format( args.N_bottom, args.N_top, args.Npoints, args.lam_range, args.normalize, not args.no_cavity) #numpy.savetxt('test_TMM.csv', numpy.transpose([lam_vac,Tnorm]), delimiter=';', header='lam_vac;Tnorm') numpy.savetxt(csvfile, numpy.transpose([lam_vac, Tnorm, Rnorm]), delimiter=';', header='lam_vac;Tnorm;Rnorm') return
def Simulate(self, n_Sub, n_Space, n_File, n=2.38): """This function simulates the reflectivity of the DBR structure using Rnorm from the TMM package""" # n_File is a string that is the filename of one of the included refractive index files for GaN. If it's false then a constant value is used. # Run the sims print(self.Period) # Using constant value for n_GaN if n_File == False: # Initialise Wavelength range to model (Resolution is a nm) self.Wav = linspace(200, 1000, 800) # Make Layer Thickness List Repeat = [self.T_GaN] + self.T_Graded self.d_list = [inf] + Repeat * self.NLayers + [self.T_Temp] + [inf] # initialize lists of y-values to plot self.Rnorm = [] ############ Calculations ############ n_Por = porosity_to_n(self.Por_Graded, n, n_Space).tolist() # Make list of refractive indices Repeat = [n] + n_Por self.n_list = [1] + Repeat * self.NLayers + [n] + [n_Sub] for Lambda in self.Wav: # For normal incidence, s and p polarizations are identical. # I arbitrarily decided to use 's'. self.Rnorm.append( coh_tmm('s', self.n_list, self.d_list, 0, Lambda)['R']) # Using data file for n_GaN else: # Load GaN refractive index data self.n_File = n_File data = np.loadtxt(self.n_File + '.csv', delimiter=',', skiprows=1) [self.Wav, n_GaN] = np.transpose( data) # Transpose data and assign the two columns self.Wav = self.Wav * 1000 # Convert Wavelength to nm (from um) n_func = interp1d( self.Wav, n_GaN ) # This interpolation function allows the look up of n for any wavelength # Initialise Wavelength range to model (Resolution is a nm) self.Wav = linspace(min(self.Wav), min(1000, self.Wav[-1]), num=int((1000 - min(self.Wav)))) # Make Layer Thickness List Repeat = [self.T_GaN] + self.T_Graded self.d_list = [inf] + Repeat * self.NLayers + [self.T_Temp] + [inf] # initialize lists of y-values to plot self.Rnorm = [] ############ Calculations ############ for Lambda in self.Wav: n = n_func(Lambda).tolist() n_Por = porosity_to_n(self.Por_Graded, n, n_Space).tolist() self.nPor.append(n_Por) # Make list of refractive indices Repeat = [n] + n_Por self.n_list = [1] + Repeat * self.NLayers + [n] + [n_Sub] # For normal incidence, s and p polarizations are identical. # I arbitrarily decided to use 's'. self.Rnorm.append( coh_tmm('s', self.n_list, self.d_list, 0, Lambda)['R'])
def FabryPerotTest(): n_outside = 1 n_inside = 3 thickness = 1 lam_vac = linspace(0.4, 1.0, 100) incidence_angle = linspace(-45, 45, 91) # x = linspace(-3,3,100) # y = linspace(-3,3,20) # Z = numpy.random.rand(len(x), len(y)) X, Y = numpy.meshgrid(incidence_angle, lam_vac) # X, Y = numpy.meshgrid(x, y) # Z = (1 - X / 2. + X ** 5 + Y ** 3) * numpy.exp(-X ** 2 - Y ** 2) # Z = numpy.sin((2*numpy.pi/6) * X ) # Z = numpy.sin((2*numpy.pi/6) * Y ) # Z = numpy.zeros((len(y), len(x))) # Z = numpy.zeros((len(y), len(x))) Z_theory = numpy.zeros(X.shape) Z_TMM = numpy.zeros(X.shape) # for i in range(X.shape[0]): # Z[i, :] = numpy.sin((2*numpy.pi/6) * (incidence_angle-i) ) for idx, cur_incidence_angle_deg in enumerate(incidence_angle): cur_incidence_angle_rad = numpy.deg2rad(cur_incidence_angle_deg) reflectance, transmittance = FabryPerot(lam_vac, n_outside, n_inside, thickness, cur_incidence_angle_rad) Z_theory[:, idx] = reflectance # list of layer thicknesses in nm d_list = [inf, thickness, inf] # list of refractive indices n_list = [n_outside, n_inside, n_outside] Rnorm = [] Tnorm = [] for lam_vac_current in lam_vac: result = coh_tmm('s', n_list, d_list, cur_incidence_angle_rad, lam_vac_current) Rnorm.append(result['R']) Tnorm.append(result['T']) Z_TMM[:, idx] = Rnorm # plt.figure() # plt.plot(lam_vac, reflectance, 'red') # plt.plot(lam_vac, transmittance, 'blue') # plt.plot(lam_vac, Rnorm, 'ro') # plt.plot(lam_vac, Tnorm, 'bo') # plt.xlabel('$\lambda$ (nm)') # plt.ylabel('reflectance, transmittance') # plt.title('reflectance (red), transmittance (blue) of unpolarized light at 0$^\circ$ incidence') # plt.show() fig, (ax0, ax1) = plt.subplots(1, 2) xlabel = 'Incidence angle (degrees)' ylabel = 'Wavelength (um)' # plt.pcolor(X,Y,Z); c = ax0.pcolor(X, Y, Z_theory) ax0.set_title('Theory') ax0.set(xlabel=xlabel, ylabel=ylabel) c = ax1.pcolor(X, Y, Z_TMM) ax1.set_title('TMM') ax1.set(xlabel=xlabel, ylabel=ylabel) ax1.label_outer() fig.suptitle('Fabry-Perot reflectance') plt.show() return
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
def SimulateParts(self, n_Sub, n_Space, n_File, TopDBR, n=2.38): """This function is an alternative to SImulate for structures made up of two different DBRs. Takes another DBR structure as an additional argument and calculates the reflectivity of the combined structure""" # Run the sims print(self.Period) # Using constant value for n_GaN if n_File == False: # Initialise Wavelength range to model (Resolution is a nm) self.Wav = linspace(200, 1000, 800) # Make Layer Thickness List Repeat = [self.T_GaN] + self.T_Graded RepeatTop = [TopDBR.T_GaN] + TopDBR.T_Graded self.d_list = [ inf ] + RepeatTop * TopDBR.NLayers + Repeat * self.NLayers + [ self.T_Temp ] + [inf] # initialize lists of y-values to plot self.Rnorm = [] ############ Calculations ############ n_Por = porosity_to_n(self.Por_Graded, n, n_Space).tolist() n_PorTop = porosity_to_n(TopDBR.Por_Graded, n, n_Space).tolist() # Make list of refractive indices Repeat = [n] + n_Por RepeatTop = [n] + n_PorTop self.n_list = [ 1 ] + RepeatTop * TopDBR.NLayers + Repeat * self.NLayers + [n] + [ n_Sub ] for Lambda in self.Wav: # For normal incidence, s and p polarizations are identical. # I arbitrarily decided to use 's'. self.Rnorm.append( coh_tmm('s', self.n_list, self.d_list, 0, Lambda)['R']) # Using data file for n_GaN else: # Load GaN refractive index data self.n_File = n_File data = np.loadtxt(self.n_File + '.csv', delimiter=',', skiprows=1) [self.Wav, n_GaN] = np.transpose( data) # Transpose data and assign the two columns self.Wav = self.Wav * 1000 # Convert Wavelength to nm (from um) n_func = interp1d( self.Wav, n_GaN ) # This interpolation function allows the look up of n for any wavelength # Initialise Wavelength range to model (Resolution is a nm) self.Wav = linspace(min(self.Wav), min(1000, self.Wav[-1]), num=int((1000 - min(self.Wav)))) # Make Layer Thickness List Repeat = [self.T_GaN] + self.T_Graded RepeatTop = [TopDBR.T_GaN] + TopDBR.T_Graded self.d_list = [ inf ] + RepeatTop * TopDBR.NLayers + Repeat * self.NLayers + [ self.T_Temp ] + [inf] # initialize lists of y-values to plot self.Rnorm = [] ############ Calculations ############ for Lambda in self.Wav: n = n_func(Lambda).tolist() n_Por = porosity_to_n(self.Por_Graded, n, n_Space).tolist() self.nPor.append(n_Por) n_PorTop = porosity_to_n(TopDBR.Por_Graded, n, n_Space).tolist() TopDBR.nPor.append(n_PorTop) # Make list of refractive indices Repeat = [n] + n_Por RepeatTop = [n] + n_PorTop self.n_list = [ 1 ] + RepeatTop * TopDBR.NLayers + Repeat * self.NLayers + [ n ] + [n_Sub] # For normal incidence, s and p polarizations are identical. # I arbitrarily decided to use 's'. self.Rnorm.append( coh_tmm('s', self.n_list, self.d_list, 0, Lambda)['R'])