def vs_pol_prof(s, p, A_total): profile = np.zeros(len(dist)) S.SetExcitationPlanewave((theta, phi), s, p, 0) S.SetFrequency(1 / wl) for j, d in enumerate(dist): layer, d_in_layer = tmm.find_in_structure_with_inf(widths, d) layer_name = 'layer_' + str( layer + 1) # layer_1 is air above so need to add 1 data = rcwa_position_resolved(S, layer_name, d_in_layer, A_total) profile[j] = data return profile
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 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 calculate_absorption_profile_rcwa(structure, size, orders, wavelength, rat_output, z_limit=None, steps_size=2, dist=None, theta=0, phi=0, pol='u'): """ 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. :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 dist is None: if z_limit is None: stack = OptiStack(structure) 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)))} S, stack_OS, shape_mats_OS = initialise_S(structure, size, orders) if pol in 'sp': if pol == 's': s = 1 p = 0 elif pol == 'p': s = 0 p = 1 S.SetExcitationPlanewave((theta, phi), s, p, 0) for i, wl in enumerate(wavelength): update_epsilon(S, stack_OS, shape_mats_OS, wl) S.SetFrequency(1 / wl) A = rat_output['A'][i] for j, d in enumerate(dist): layer, d_in_layer = tmm.find_in_structure_with_inf( stack_OS.get_widths(), d) # don't need to change this layer_name = 'layer_' + str( layer + 1) # layer_1 is air above so need to add 1 data = rcwa_position_resolved(S, layer_name, d_in_layer, A) output['absorption'][i, j] = data else: for i, wl in enumerate( wavelength): # set the material values and indices in here update_epsilon(S, stack_OS, shape_mats_OS, wl) S.SetFrequency(1 / wl) A = rat_output['A'][i] for j, d in enumerate(dist): layer, d_in_layer = tmm.find_in_structure_with_inf( stack_OS.get_widths(), d) # don't need to change this layer_name = 'layer_' + str( layer + 1) # layer_1 is air above so need to add 1 S.SetExcitationPlanewave((theta, phi), 0, 1, 0) # p-polarization data_p = rcwa_position_resolved(S, layer_name, d_in_layer, A) S.SetExcitationPlanewave((theta, phi), 1, 0, 0) # p-polarization data_s = rcwa_position_resolved(S, layer_name, d_in_layer, A) output['absorption'][i, j] = 0.5 * (data_p + data_s) return output
def calculate_absorption_profile_rcwa(structure, size, orders, wavelength, rat_output, z_limit=None, steps_size=2, dist=None, theta=0, phi=0, pol='u', substrate=None): """ 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 size: list with 2 entries, size of the unit cell (right now, can only be rectangular :param orders: number of orders to retain in the RCWA calculations. :param wavelength: Wavelengths (in nm) in which calculate the data. :param rat_output: output from calculate_rat_rcwa :param z_limit: Maximum value in the z direction at which to calculate depth-dependent absorption (nm) :param steps_size: if the dist is not specified, the step size in nm to use in the depth-dependent calculation :param dist: the positions (in nm) at which to calculate depth-dependent absorption :param theta: polar incidence angle (in degrees) of the incident light. Default: 0 (normal incidence) :param phi: azimuthal incidence angle in degrees. Default: 0 :param pol: Polarisation of the light: 's', 'p' or 'u'. Default: 'u' (unpolarised). :param substrate: semi-infinite transmission medium :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 dist is None: if z_limit is None: stack = OptiStack(structure) 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)))} S, stack_OS, shape_mats_OS = initialise_S(structure, size, orders, substrate) if pol in 'sp': if pol == 's': s = 1 p = 0 elif pol == 'p': s = 0 p = 1 S.SetExcitationPlanewave((theta, phi), s, p, 0) for i, wl in enumerate(wavelength): update_epsilon(S, stack_OS, shape_mats_OS, wl) S.SetFrequency(1 / wl) A = rat_output['A'][i] for j, d in enumerate(dist): layer, d_in_layer = tmm.find_in_structure_with_inf( stack_OS.get_widths(), d) # don't need to change this layer_name = 'layer_' + str( layer + 1) # layer_1 is air above so need to add 1 data = rcwa_position_resolved(S, layer_name, d_in_layer, A) output['absorption'][i, j] = data else: for i, wl in enumerate( wavelength): # set the material values and indices in here print(i) update_epsilon(S, stack_OS, shape_mats_OS, wl) S.SetFrequency(1 / wl) A = rat_output['A'][i] for j, d in enumerate(dist): layer, d_in_layer = tmm.find_in_structure_with_inf( stack_OS.get_widths(), d) # don't need to change this layer_name = 'layer_' + str( layer + 1) # layer_1 is air above so need to add 1 S.SetExcitationPlanewave((theta, phi), 0, 1, 0) # p-polarization data_p = rcwa_position_resolved(S, layer_name, d_in_layer, A) S.SetExcitationPlanewave((theta, phi), 1, 0, 0) # p-polarization data_s = rcwa_position_resolved(S, layer_name, d_in_layer, A) output['absorption'][i, j] = 0.5 * (data_p + data_s) return output
def RCWA_wl_prof(self, wl, rat_output_A, dist, geom_list, layers_oc, shapes_oc, s_names, pol, theta, phi, widths, size, orders, rcwa_options): #widths = stack_OS.get_widths() S = initialise_S(size, orders, geom_list, layers_oc, shapes_oc, s_names, widths, rcwa_options) profile_data = np.zeros(len(dist)) A = rat_output_A if len(pol) == 2: S.SetExcitationPlanewave((theta, phi), pol[0], pol[1], 0) S.SetFrequency(1 / wl) for j, d in enumerate(dist): layer, d_in_layer = tmm.find_in_structure_with_inf( widths, d) # don't need to change this layer_name = 'layer_' + str( layer + 1) # layer_1 is air above so need to add 1 data = rcwa_position_resolved(S, layer_name, d_in_layer, A) profile_data[j] = data else: if pol in 'sp': if pol == 's': s = 1 p = 0 elif pol == 'p': s = 0 p = 1 S.SetExcitationPlanewave((theta, phi), s, p, 0) S.SetFrequency(1 / wl) for j, d in enumerate(dist): layer, d_in_layer = tmm.find_in_structure_with_inf( widths, d) # don't need to change this layer_name = 'layer_' + str( layer + 1) # layer_1 is air above so need to add 1 data = rcwa_position_resolved(S, layer_name, d_in_layer, A) profile_data[j] = data else: S.SetFrequency(1 / wl) A = rat_output_A for j, d in enumerate(dist): layer, d_in_layer = tmm.find_in_structure_with_inf( widths, d) # don't need to change this layer_name = 'layer_' + str( layer + 1) # layer_1 is air above so need to add 1 S.SetExcitationPlanewave((theta, phi), 0, 1, 0) # p-polarization data_p = rcwa_position_resolved(S, layer_name, d_in_layer, A) S.SetExcitationPlanewave((theta, phi), 1, 0, 0) # p-polarization data_s = rcwa_position_resolved(S, layer_name, d_in_layer, A) profile_data[j] = 0.5 * (data_s + data_p) return profile_data