def epsilon_d_to_nk_function(lamda_list, sigma_bar0, lamda_tau, interpolation_type = 'cubic'): epsilon_d = -sigma_bar0 *(lamda_list**2/( 1.0j*lamda_list + lamda_tau )) epsilon_abs = sqrt(epsilon_d * epsilon_d.conjugate()) n_d = sqrt((epsilon_abs + epsilon_d.real)/2.0).real k_d = sqrt((epsilon_abs - epsilon_d.real)/2.0).real from TRANK import extrap nk_d_f = extrap(lamda_list, n_d + 1.0j*k_d, kind = interpolation_type) return nk_d_f
from basic_setup import fit_nk_f, spectrum_list_generator, parameter_list_generator fit_nk_f = functionize_nk_file(data_directory + 'fit_nk_fine.txt', skiprows=0) lamda_list = loadtxt(data_directory + 'fit_nk.txt', unpack=True, usecols=[0]) lamda_fine = loadtxt(data_directory + 'fit_nk_fine.txt', unpack=True, usecols=[0]) rms_error_fine = rms_error_spectrum( lamda_list=lamda_fine, nk_f=fit_nk_f, spectrum_list_generator=spectrum_list_generator, parameter_list_generator=parameter_list_generator) rms_f = extrap(lamda_fine, rms_error_fine, kind='linear') try_mkdir(map_direct) from matplotlib.backends.backend_pdf import PdfPages pdf_page_combined = PdfPages(map_direct + 'all_error_maps.pdf') from matplotlib.pylab import * from matplotlib.colors import LogNorm from matplotlib import ticker fit_n_max = fit_nk_f(lamda_list).real.max() fit_k_max = fit_nk_f(lamda_list).imag.max() num_n_points = 50 num_k_points = 100
tmm_spectra_dir = 'tmm_predicted_spectra/' ###### # this ugly hack only defines the TR_pair_list_generator if the data actually exists from os.path import isfile if isfile(tmm_spectra_dir+ '%i_deg_spectra.txt'%angle_list[1]): spectrum_function_list = [] for angle in angle_list: file_name = tmm_spectra_dir+ '%i_deg_spectra.txt'%angle lamda, T_list, R_list = loadtxt(file_name, usecols = [0,1,2], unpack = True) # lnear interpoation prevents interpoation of TRA values outside 0-100% spectrum_function_list.append( extrap(lamda, T_list, kind = 'linear' ) ) spectrum_function_list.append( extrap(lamda, R_list, kind = 'linear' ) ) ### this function is what we are creating as aa def spectrum_list_generator(lamda): # for measured or simulated spectra #spectrum_list = [] #for spectrum_function in spectrum_function_list: #effectivly loops over angles, evaluated the interpolating functions # spectrum_list.append(spectrum_function(lamda)) spectrum_list = [spectrum_function(lamda) for spectrum_function in spectrum_function_list] # why not just directly use the spectrum_function_list? because this allows us in the future to use spectra with different Wavelength ranges! return spectrum_list #must a list of spectra pairs matching the params def parameter_list_generator(lamda): # layer geometry and neighbor properties param_list = []
ylim = max_rms_cutoff - (max_rms_cutoff/net_rms_cutoff)*net_rms if max_rms < ylim: use_old_nk = True passes = 2 #use_old_nk = False if use_old_nk == False: old_lamda = lamda_fine from numpy.random import rand min_n, max_n = 0.0, 2.0 min_k, max_k = 0.0, 0.1 rand_n = rand(lamda_fine.size)*(max_n - min_n) + min_n rand_k = rand(lamda_fine.size)*(max_k - min_k) + min_k fit_nk_f = extrap(lamda_fine, rand_n + 1.0j*rand_k) def fit_nk_f(lamda): return 1.0+0.01j+0.00*lamda nk_plot(fit_nk_f, lamda_fine = lamda_fine, lamda_list = old_lamda, file_name = data_directory+'initial_nk.pdf', title_string='Initial nk',show_nodes = True, show_plots = show_plots) if show_plots: show() error_adaptive_iterative_fit_spectra( nk_f_guess = fit_nk_f,
nk_f_list.append(nk_f_air) thickness_list.append(inf) coherency_list.append('i') ########### fit_nk_f = nk_f_list[layer_index_of_fit] ################# experimental data spectrum_function_list = [] spectrum_name_list = [] # this is for me to label things later R_data = loadtxt('Reflection_10nm_CuAg_on_silica_substrate.txt', skiprows=2).T lamda = R_data[0] # lnear interpoation prevents interpoation of TRA values outside 0-100% spectrum_function_list.append(extrap(lamda, R_data[1] / 100.0, kind='linear')) spectrum_name_list.append('0 deg Reflection') spectrum_function_list.append(extrap(lamda, R_data[2] / 100.0, kind='linear')) spectrum_name_list.append('30 deg S-polarization Reflection') spectrum_function_list.append(extrap(lamda, R_data[3] / 100.0, kind='linear')) spectrum_name_list.append('30 deg P-polarization Reflection') spectrum_function_list.append(extrap(lamda, R_data[4] / 100.0, kind='linear')) spectrum_name_list.append('40 deg S-polarization Reflection') spectrum_function_list.append(extrap(lamda, R_data[5] / 100.0, kind='linear')) spectrum_name_list.append('40 deg P-polarization Reflection') spectrum_function_list.append(extrap(lamda, R_data[6] / 100.0, kind='linear')) spectrum_name_list.append('50 deg S-polarization Reflection') spectrum_function_list.append(extrap(lamda, R_data[7] / 100.0, kind='linear'))
########### #fit_nk_f = nk_f_list[layer_index_of_fit] ######################### experimental data spectrum_function_list = [] spectrum_name_list = [] # this is for me to label things later #### front side R_data = loadtxt('Normal_Reflectance.txt', skiprows = 2).T lamda = R_data[0] # lnear interpoation prevents interpoation of TRA values outside 0-100% spectrum_function_list.append( extrap(lamda, R_data[1], kind = 'linear' ) ) spectrum_name_list.append('0 deg Reflectance') R_data = loadtxt('Reflectance.txt', skiprows = 2).T lamda = R_data[0] spectrum_function_list.append( extrap(lamda, R_data[1], kind = 'linear' ) ) spectrum_name_list.append('55 deg Unpolarized Reflectance') if False: spectrum_function_list.append( extrap(lamda, R_data[2], kind = 'linear' ) ) spectrum_name_list.append('65 deg Unpolarization Reflection') spectrum_function_list.append( extrap(lamda, R_data[3], kind = 'linear' ) ) spectrum_name_list.append('75 deg Unpolarization Reflection')
def fit_TRA_holy_nksqr_BFGS(lamda_list, TR_pair_list_generator, parameter_list_generator, nk_f_guess, delta_weight = 0.1, tolerance = 1e-4, no_negative = True): '''n_front and n_back must be real valued for this to work without caveats. thickness and lambda can be any units, so long as they are the same, lamda_list must be sorted''' from numpy import pi,exp,abs,sqrt, array, matmul, loadtxt, zeros, savetxt, inf, diff, ones from scipy.optimize import root, least_squares, minimize from TRANK import extrap point_multiplicity = len(TR_pair_list_generator(lamda_list[0])) #print(point_multiplicity) # 3.0 is from T, R, and A abs_delta_weight = sqrt(delta_weight**2 * point_multiplicity * 3.0 * (len(lamda_list)/(len(lamda_list)-1.0))) from multiprocessing import Pool, cpu_count my_pool = Pool(cpu_count()) def TR_error(nk_list): c_nk_list = [] muh_inputs = [] for i in range(len(lamda_list)): nk = nk_list[2*i] + 1.0j*nk_list[2*i+1] c_nk_list.append(nk) muh_inputs.append( (lamda_list[i], nk, TR_pair_list_generator, parameter_list_generator ) ) #print (zip(lamda_list, c_nk_list)) error_list_lists = my_pool.map(TRA_lamda_error, muh_inputs) #error_list_lists =my_pool.map(lamda_error, zip(lamda_list, c_nk_list)) #print (error_list_lists) #error_list = [] #for sub_error_list in error_list_lists: # error_list = error_list + sub_error_list base_line_error_square = (array(error_list_lists)**2).sum() delta_array = diff(c_nk_list)*abs_delta_weight #delta_errors =(delta_array.real**2 + delta_array.imag**2) * abs_delta_weight #error_list = error_list + list(delta_errors) #error_list = error_list + list(delta_array.real) + list(delta_array.imag) delta_errors_square = (delta_array.real**2 + delta_array.imag**2).sum() * abs_delta_weight return base_line_error_square + delta_errors_square ####### now for a guess list ############## nk_guess_list = [] for i in range(len(lamda_list)): nk = nk_f_guess(lamda_list[i]) nk_guess_list.append(abs(nk.real)) nk_guess_list.append(abs(nk.imag)) ######### test #print(TR_error(nk_guess_list)) ############ nk guessing over, time for creating and minimizing error function if no_negative: solution = minimize(TR_error, x0 = nk_guess_list, method = 'L-BFGS-B', bounds = 2*len(lamda_list)*[(0,inf)] , tol = tolerance, options = {'disp' : True } ).x else: solution = minimize(TR_error, x0 = nk_guess_list, method = 'L-BFGS-B', tol = tolerance, options = {'disp' : True } ).x my_pool.terminate() my_pool.close() n_list=[] k_list=[] for i in range(len(lamda_list)): n_list.append(solution[2*i] ) k_list.append(solution[2*i+1]) nf = extrap(lamda_list, n_list, kind = 'cubic') kf = extrap(lamda_list, k_list, kind = 'cubic') def fit_nk_f(lamda): return nf(lamda) + 1.0j*kf(lamda) return fit_nk_f
def fit_TRA_nk_sqr_KK_compliant(lamda_list, lamda_fine, TR_pair_list_generator, parameter_list_generator, nk_f_guess, delta_weight = 0.1, tolerance = 1e-5, no_negative = True, interpolation_type = 'cubic', method = 'least_squares'): '''n_front and n_back must be real valued for this to work without caveats. thickness and lambda can be any units, so long as they are the same, lamda_list must be sorted''' from numpy import pi,exp,abs,sqrt, array, matmul, loadtxt, zeros, savetxt, inf, diff, ones, mean from scipy.optimize import root, least_squares, minimize from TRANK import extrap point_multiplicity = len(TR_pair_list_generator(lamda_list[0])) #print(point_multiplicity) # 3.0 is from T, R, and A abs_delta_weight = sqrt(delta_weight**2 * point_multiplicity * 3.0 * (len(lamda_list)/(len(lamda_list)-1.0))) from multiprocessing import Pool, cpu_count my_pool = Pool(cpu_count()) #my_pool = Pool() #my_pool = Pool(1) def TR_error(k_and_p_list): # the last value is the principle value #FYI -> k = array(k_and_p_list[0:-1]) k = k_and_p_list[0:-1] p = k_and_p_list[-1] n = p + KK_lamda(lamda_list = lamda_list, lamda_fine = lamda_fine, k = k ) muh_inputs = [] for i in range(len(lamda_list)): nk = n[i]+1.0j*k[i]# double check this works properly later muh_inputs.append( (lamda_list[i], nk, TR_pair_list_generator, parameter_list_generator ) ) #print (zip(lamda_list, c_nk_list)) error_list_lists = my_pool.map(TRA_lamda_error, muh_inputs) #error_list_lists =my_pool.map(lamda_error, zip(lamda_list, c_nk_list)) #print (error_list_lists) error_list = [] for sub_error_list in error_list_lists: error_list = error_list + sub_error_list error_list = error_list + list( abs_delta_weight*diff(n) ) + list( abs_delta_weight * diff(k)) return error_list ####### now for a guess list ############## guess_k_and_p_list= [] p = 0.0 for i in range(len(lamda_list)): nk = nk_f_guess(lamda_list[i]) if no_negative and nk.imag < 0.0: k = 0 else: k = nk.imag guess_k_and_p_list.append( k) p+= nk.real # now we put p at the end p = p/len(lamda_list) - 1.0 # this is a guess for the principle value print ('principle value guess:',p) guess_k_and_p_list.append(p) ######### test if False: print(TR_error(guess_k_and_p_list)) #use this to see if the TR_error works ############ nk guessing over, time for creating and minimizing error function if method == 'least_squares': inputs = dict(fun = TR_error, x0 = guess_k_and_p_list, ftol = tolerance, xtol = tolerance, gtol = tolerance, verbose = 2) if no_negative: inputs.update(dict( bounds = [len(lamda_list)*[0.0]+[-inf],len(lamda_list)*[inf]+[inf]] )) solution = least_squares(**inputs ).x elif method == 'SLSQP': inputs = dict(fun = lambda x: 0.5*sum(TR_error(x)**2), x0 = guess_k_and_p_list, method = 'SLSQP', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = len(lamda_list)*[(0,inf)] + [(-inf,inf)] )) solution = minimize(**inputs ).x elif method == 'L-BFGS-B': inputs = dict(fun = lambda x: 0.5*sum(TR_error(x)**2), x0 = guess_k_and_p_list, method = 'L-BFGS-B', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = len(lamda_list)*[(0,inf)] + [(-inf,inf)] )) solution = minimize(**inputs ).x elif method == 'TNC': inputs = dict(fun = lambda x: 0.5*sum(TR_error(x)**2), x0 = guess_k_and_p_list, method = 'TNC', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = len(lamda_list)*[(0,inf)] + [(-inf,inf)] )) solution = minimize(**inputs ).x else: raise ValueError("Invalid minimization method!") my_pool.terminate() my_pool.close() k_and_p_list = solution k = k_and_p_list[0:-1] p = k_and_p_list[-1] n = p + KK_lamda(lamda_list = lamda_list, lamda_fine = lamda_fine, k = k ) print ('Final principle value:',p) nf = extrap(lamda_list, n, kind = interpolation_type) kf = extrap(lamda_list, k, kind = interpolation_type) def fit_nk_f(lamda): return nf(lamda) + 1.0j*kf(lamda) return fit_nk_f
def fit_TRA_nk_sqr(lamda_list, TR_pair_list_generator, parameter_list_generator, nk_f_guess, delta_weight = 0.1, tolerance = 1e-4, no_negative = True, interpolation_type = 'cubic', method = 'least_squares'): '''n_front and n_back must be real valued for this to work without caveats. thickness and lambda can be any units, so long as they are the same, lamda_list must be sorted''' from numpy import pi,exp,abs,sqrt, array, matmul, loadtxt, zeros, savetxt, inf, diff, ones from scipy.optimize import root, least_squares, minimize from TRANK import extrap point_multiplicity = len(TR_pair_list_generator(lamda_list[0])) #print(point_multiplicity) # 3.0 is from T, R, and A abs_delta_weight = sqrt(delta_weight**2 * point_multiplicity * 3.0 * (len(lamda_list)/(len(lamda_list)-1.0))) from multiprocessing import Pool, cpu_count my_pool = Pool(cpu_count()) #my_pool = Pool() #my_pool = Pool(1) def TR_error(nk_list): c_nk_list = [] muh_inputs = [] for i in range(len(lamda_list)): nk = nk_list[2*i] + 1.0j*nk_list[2*i+1] c_nk_list.append(nk) muh_inputs.append( (lamda_list[i], nk, TR_pair_list_generator, parameter_list_generator ) ) #print (zip(lamda_list, c_nk_list)) error_list_lists = my_pool.map(TRA_lamda_error, muh_inputs) #error_list_lists =my_pool.map(lamda_error, zip(lamda_list, c_nk_list)) #print (error_list_lists) error_list = [] for sub_error_list in error_list_lists: error_list = error_list + sub_error_list delta_array = diff(c_nk_list)*abs_delta_weight #delta_errors =(delta_array.real**2 + delta_array.imag**2) * abs_delta_weight #error_list = error_list + list(delta_errors) error_list = error_list + list(delta_array.real) + list(delta_array.imag) return array(error_list) ####### now for a guess list ############## nk_guess_list = [] for i in range(len(lamda_list)): nk = nk_f_guess(lamda_list[i]) nk_guess_list.append(abs(nk.real)) nk_guess_list.append(abs(nk.imag)) ######### test #print(TR_error(nk_guess_list)) ############ nk guessing over, time for creating and minimizing error function if method == 'least_squares': inputs = dict(fun = TR_error, x0 = nk_guess_list, ftol = tolerance, xtol = tolerance, gtol = tolerance, verbose = 2) if no_negative: inputs.update(dict( bounds = [zeros(2*len(lamda_list)),inf*ones(2*len(lamda_list))] )) solution = least_squares(**inputs ).x elif method == 'L-BFGS-B': inputs = dict(fun = lambda x: 0.5*sum(TR_error(x)**2), x0 = nk_guess_list, method = 'L-BFGS-B', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = 2*len(lamda_list)*[(0,inf)])) solution = minimize(**inputs ).x elif method == 'SLSQP': inputs = dict(fun = lambda x: 0.5*sum(TR_error(x)**2), x0 = nk_guess_list, method = 'SLSQP', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = 2*len(lamda_list)*[(0,inf)])) solution = minimize(**inputs ).x elif method == 'TNC': inputs = dict(fun = lambda x: 0.5*sum(TR_error(x)**2), x0 = nk_guess_list, method = 'TNC', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = 2*len(lamda_list)*[(0,inf)])) solution = minimize(**inputs ).x else: raise ValueError("Invalid minimization method!") my_pool.terminate() my_pool.close() n_list=[] k_list=[] for i in range(len(lamda_list)): n_list.append(solution[2*i] ) k_list.append(solution[2*i+1]) nf = extrap(lamda_list, n_list, kind = interpolation_type) kf = extrap(lamda_list, k_list, kind = interpolation_type) def fit_nk_f(lamda): return nf(lamda) + 1.0j*kf(lamda) return fit_nk_f
def fit_spectra_nk_sqr(lamda_list, spectrum_list_generator, parameter_list_generator, nk_f_guess, delta_weight = 0.1, k_weight_fraction = 1.0, tolerance = 1e-5, no_negative = True, interpolation_type = 'cubic', method = 'least_squares', threads = 0, input_data=None, test_setup=None, TB1=None ): '''n_front and n_back must be real valued for this to work without caveats. thickness and lambda can be any units, so long as they are the same, lamda_list must be sorted''' from numpy import pi,exp,abs,sqrt, array, matmul, loadtxt, zeros, savetxt, inf, diff, ones from scipy.optimize import root, least_squares, minimize from TRANK import extrap #point_multiplicity = len(spectrum_list_generator(lamda_list[0])) #print(point_multiplicity) #point_multiplicity_list = [len(spectrum_list_generator(lamda)) for lamda in lamda_list ] #point_multiplicity = point_multiplicity_list[0] abs_delta_weight = sqrt(delta_weight**2 * (len(lamda_list)/(len(lamda_list)-1.0))) from multiprocessing import Pool, cpu_count if threads <= 0: threads = cpu_count() TB1.append ('Using %i Processes' % threads) my_pool=Pool(threads) def F_error(nk_list): c_nk_list = [] muh_inputs = [] for i in range(len(lamda_list)): nk = nk_list[2*i] + 1.0j*nk_list[2*i+1] c_nk_list.append(nk) muh_inputs.append( (lamda_list[i], nk, test_setup) ) ''' ctx=mp.get_context('spawn') p=ctx.Process(target=spectrum_lamda_error,args=(child_conn,muh_inputs[i],)) p.start() print (parent_conn.recv()) p.join() ''' #lock=RLock() error_list_lists =my_pool.map(spectrum_lamda_error, muh_inputs) #error_list_lists = map(spectrum_lamda_error, muh_inputs) #combine the sub error lists into #+=��mean to do so? error_list = [] for sub_error_list in error_list_lists: error_list = error_list + sub_error_list delta_array = diff(c_nk_list)*abs_delta_weight error_list = error_list + list(delta_array.real) + list(k_weight_fraction * delta_array.imag) #make up some points? return error_list ####### now for a guess list ############## nk_guess_list = [] for i in range(len(lamda_list)): nk = nk_f_guess(lamda_list[i]) if no_negative: n = nk.real k = nk.imag if n < 0.0 : n = 0.0 if k < 0.0 : k = 0.0 nk_guess_list.append(n) nk_guess_list.append(k) else: nk_guess_list.append(nk.real) nk_guess_list.append(nk.imag) ######### test if False: print(F_error(nk_guess_list)) ############ nk guessing over, time for creating and minimizing error function if method == 'least_squares': inputs = dict(fun = F_error, x0 = nk_guess_list, ftol = tolerance, xtol = tolerance, gtol = tolerance, verbose = 2) if no_negative: inputs.update(dict( bounds = [zeros(2*len(lamda_list)),inf*ones(2*len(lamda_list))] )) solution = least_squares(**inputs ).x elif method == 'L-BFGS-B': inputs = dict(fun = lambda x: 0.5*sum(array(F_error(x))**2), x0 = nk_guess_list, method = 'L-BFGS-B', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = 2*len(lamda_list)*[(0,inf)])) solution = minimize(**inputs ).x elif method == 'SLSQP': inputs = dict(fun = lambda x: 0.5*sum(array(F_error(x))**2), x0 = nk_guess_list, method = 'SLSQP', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = 2*len(lamda_list)*[(0,inf)])) solution = minimize(**inputs ).x elif method == 'TNC': inputs = dict(fun = lambda x: 0.5*sum(array(F_error(x))**2), x0 = nk_guess_list, method = 'TNC', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = 2*len(lamda_list)*[(0,inf)])) solution = minimize(**inputs ).x else: raise ValueError("Invalid minimization method!") my_pool.terminate() my_pool.close() nk_list=[] for i in range(len(lamda_list)): nk_list.append(solution[2*i] + 1.0j*solution[2*i+1] ) fit_nk_f = extrap(lamda_list, nk_list, kind = interpolation_type) return fit_nk_f
thickness_list_r = list(reversed(thickness_list)) layer_index_of_fit_r = len(thickness_list)-layer_index_of_fit - 1 ################# experimental data # lnear interpoation prevents interpoation of TRA values outside 0-100% spectrum_function_list = [] spectrum_name_list = [] # this is for me to label things later lamda_ranges = [] # [first index, last index, lamda min, lamda_max] # groups data by lamda ranges ####### Frontside # In MS Excel, I get the best results when saving as windows .txt files and then removing any poorly converted characters in those files T_data = loadtxt('transmittance.txt', skiprows = 2).T lamda = T_data[0] spectrum_function_list.append( extrap(lamda, T_data[1] ) ) spectrum_name_list.append('0 deg Transmittance') ####### R_data = loadtxt('normal_reflectance.txt', skiprows = 2).T lamda = R_data[0] spectrum_function_list.append( extrap(lamda, R_data[1] ) ) spectrum_name_list.append('0 deg Unpolarized Reflectance') ####### R_data = loadtxt('reflectance.txt', skiprows = 2).T lamda = R_data[0] # S => TE # P => TM spectrum_function_list.append( extrap(lamda, R_data[1] ) )
def fit_spectra_nk_sqr_drude_KK_compliant(lamda_list, spectrum_list_generator, parameter_list_generator, nk_f_guess, sigma_bar0_guess = 0.0, lamda_tau_guess = 0.0, epsilon_f1p_guess = 0.0, delta_weight = 0.1, k_weight_fraction = 1.0, tolerance = 1e-5, no_negative = True, interpolation_type = 'cubic', method = 'least_squares', threads = 0): '''n_front and n_back must be real valued for this to work without caveats. thickness and lambda can be any units, so long as they are the same, lamda_list must be sorted''' from numpy import pi,exp,abs,sqrt, array, matmul, loadtxt, zeros, savetxt, inf, diff, ones, mean, trapz from scipy.optimize import root, least_squares, minimize from TRANK import extrap #from TRANK import parallel_DKKT_n_from_lamda_k as KKT from TRANK import parallel_DKKT_n_from_lamda_k_with_edge_corrections as KKT from TRANK import spectrum_lamda_error abs_delta_weight = sqrt(delta_weight**2 * (len(lamda_list)/(len(lamda_list)-1.0))) from multiprocessing import Pool, cpu_count if threads <= 0: threads = cpu_count() my_pool = Pool(threads) print ('Using %i Threads' % threads) lamda_list = array(lamda_list) def F_error(epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list): # the last values are the principle value epsilon_f2 = epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list[0:-3] epsilon_f1p = epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list[-3] lamda_tau = epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list[-2] sigma_bar0 = epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list[-1] epsilon_f1 = epsilon_f1p + KKT(lamda_list = lamda_list, k = epsilon_f2, compute_pool = my_pool ) epsilon_f = epsilon_f1 + 1.0j*epsilon_f2 epsilon_d = -sigma_bar0 *(lamda_list**2/( 1.0j*lamda_list + lamda_tau )) epsilon = epsilon_f + epsilon_d epsilon_abs = sqrt(epsilon*epsilon.conjugate()) n = sqrt((epsilon_abs + epsilon.real)/2.0).real k = sqrt((epsilon_abs - epsilon.real)/2.0).real # since we are casting the imaginary part as real muh_inputs = [] for i in range(len(lamda_list)): nk = n[i]+1.0j*k[i]# double check this works properly later muh_inputs.append( (lamda_list[i], nk, spectrum_list_generator, parameter_list_generator ) ) #print (zip(lamda_list, c_nk_list)) error_list_lists = my_pool.map(spectrum_lamda_error, muh_inputs) #error_list_lists =my_pool.map(lamda_error, zip(lamda_list, c_nk_list)) #print (error_list_lists) error_list = [] for sub_error_list in error_list_lists: error_list = error_list + sub_error_list only_penalize_free = True if only_penalize_free: epsilon_f_abs = sqrt(epsilon_f.conjugate() * epsilon_f) n_f = sqrt((epsilon_f_abs + epsilon_f1)/2.0).real k_f = sqrt((epsilon_f_abs - epsilon_f1)/2.0).real # since we are casting the imaginary part as real error_list = error_list + list( abs_delta_weight*diff(n_f) ) + list( k_weight_fraction * abs_delta_weight * diff(k_f)) else: error_list = error_list + list( abs_delta_weight*diff(n) ) + list( k_weight_fraction * abs_delta_weight * diff(k)) return error_list ####### now for a guess list ############## nk_d_f = epsilon_d_to_nk_function(lamda_list, sigma_bar0_guess, lamda_tau_guess, interpolation_type = 'cubic') epsilon_f2_list = [] epsilon_f1_list = [] for i in range(len(lamda_list)): nk = nk_f_guess(lamda_list[i]) n, k = nk.real, nk.imag nk_d = nk_d_f(lamda_list[i]) n_d, k_d = nk_d.real, nk_d.imag if no_negative: if n < 0.0: n = 0 if k < 0.0: k = 0 epsilon_f1_list.append( (n**2 - k**2) - (n_d**2 - k_d**2) ) # subtracting the drude component epsilon_f2 = 2*n*k - 2*n_d*k_d if no_negative and epsilon_f2 < 0.0: epsilon_f2 = 0.0 epsilon_f2_list.append( epsilon_f2) if epsilon_f1p_guess == 0.0: epsilon_f1p = trapz(epsilon_f1_list, lamda_list)/(lamda_list[-1] - lamda_list[0]) else: epsilon_f1p = epsilon_f1p_guess if sigma_bar0_guess == 0.0: from numpy import polyfit sigma_bar0 = polyfit(lamda_list, epsilon_f2_list, 1)[0] else: sigma_bar0 = sigma_bar0_guess if lamda_tau_guess == 0.0: lamda_tau = max(lamda_list)*10 else: lamda_tau = lamda_tau_guess if no_negative: if sigma_bar0 < 0.0: sigma_bar0 = 0 if lamda_tau < 0.0: lamda_tau = 0 guess_epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list = array( epsilon_f2_list + [epsilon_f1p] + [lamda_tau] + [sigma_bar0 ] ) print ('epsilon_f1p (principle value) guess:',epsilon_f1p) print ('lambda_tau guess: ',lamda_tau) print ('sigma_bar0 guess: ',sigma_bar0) ######### test if False: print(F_error(guess_epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list)) #use this to see if the TR_error works ############ nk guessing over, time for creating and minimizing error function if method == 'least_squares': inputs = dict(fun = F_error, x0 = guess_epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list, ftol = tolerance, xtol = tolerance, gtol = tolerance, verbose = 2) if no_negative: inputs.update(dict( bounds = [len(lamda_list)*[0.0]+[-inf]+[0.0]+[0.0], len(lamda_list)*[inf]+[inf]+[inf]+[inf]] )) solution = least_squares(**inputs ).x elif method == 'SLSQP': inputs = dict(fun = lambda x: 0.5*sum(array(F_error(x))**2), x0 = guess_epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list, method = 'SLSQP', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = len(lamda_list)*[(0,inf)] + [(-inf,inf), (0,inf), (0,inf)] )) solution = minimize(**inputs ).x elif method == 'L-BFGS-B': inputs = dict(fun = lambda x: 0.5*sum(array(F_error(x))**2), x0 = guess_epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list, method = 'L-BFGS-B', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = len(lamda_list)*[(0,inf)] + [(-inf,inf), (0,inf), (0,inf)] )) solution = minimize(**inputs ).x elif method == 'TNC': inputs = dict(fun = lambda x: 0.5*sum(array(F_error(x))**2), x0 = guess_epsilonf2_epsilonf1p_lamdatau_and_sigmabar0_list, method = 'TNC', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = len(lamda_list)*[(0,inf)] + [(-inf,inf), (0,inf), (0,inf)] )) solution = minimize(**inputs ).x else: raise ValueError("Invalid minimization method!") ##### now for unpacking epsilon2_epsilon1p_lamdatau_and_sigmabar0_list = solution epsilon_f2 = epsilon2_epsilon1p_lamdatau_and_sigmabar0_list[0:-3] epsilon_f1p = epsilon2_epsilon1p_lamdatau_and_sigmabar0_list[-3] lamda_tau = epsilon2_epsilon1p_lamdatau_and_sigmabar0_list[-2] sigma_bar0 = epsilon2_epsilon1p_lamdatau_and_sigmabar0_list[-1] epsilon_f1 = epsilon_f1p + KKT(lamda_list = lamda_list, k = epsilon_f2, compute_pool = my_pool ) epsilon_f = epsilon_f1 + 1.0j*epsilon_f2 epsilon_d = -sigma_bar0 *(lamda_list**2/( 1.0j*lamda_list + lamda_tau )) epsilon = epsilon_f + epsilon_d epsilon_abs = sqrt(epsilon*epsilon.conjugate()) n = sqrt((epsilon_abs + epsilon.real)/2.0) k = sqrt((epsilon_abs - epsilon.real)/2.0) print ('Final epsilon_f1p (principle value):',epsilon_f1p) print ('Final lambda_tau :',lamda_tau) print ('Final sigma_bar0 value :',sigma_bar0) fit_nk_f = extrap(lamda_list, n + 1.0j*k, kind = interpolation_type) my_pool.terminate() my_pool.close() return fit_nk_f, lamda_tau, sigma_bar0, epsilon_f1p
def fit_spectra_nk_sqr_KK_compliant(lamda_list, spectrum_list_generator, parameter_list_generator, nk_f_guess, delta_weight = 0.1, k_weight_fraction = 1.0, tolerance = 1e-5, no_negative = True, interpolation_type = 'cubic', method = 'least_squares', threads = 0): '''n_front and n_back must be real valued for this to work without caveats. thickness and lambda can be any units, so long as they are the same, lamda_list must be sorted''' from numpy import pi,exp,abs,sqrt, array, matmul, loadtxt, zeros, savetxt, inf, diff, ones, mean, trapz from scipy.optimize import root, least_squares, minimize from TRANK import extrap #from TRANK import parallel_DKKT_n_from_lamda_k as KKT from TRANK import parallel_DKKT_n_from_lamda_k_with_edge_corrections as KKT #point_multiplicity = len(TR_pair_list_generator(lamda_list[0])) #print(point_multiplicity) abs_delta_weight = sqrt(delta_weight**2 * (len(lamda_list)/(len(lamda_list)-1.0))) from multiprocessing import Pool, cpu_count if threads <= 0: threads = cpu_count() my_pool = Pool(threads) print ('Using %i Threads' % threads) def F_error(k_and_p_list): # the last value is the principle value #FYI -> k = array(k_and_p_list[0:-1]) k = k_and_p_list[0:-1] p = k_and_p_list[-1] n = p + KKT(lamda_list = lamda_list, k = k, compute_pool = my_pool ) muh_inputs = [] for i in range(len(lamda_list)): nk = n[i]+1.0j*k[i]# double check this works properly later muh_inputs.append( (lamda_list[i], nk, spectrum_list_generator, parameter_list_generator ) ) #print (zip(lamda_list, c_nk_list)) error_list_lists = my_pool.map(spectrum_lamda_error, muh_inputs) #error_list_lists =my_pool.map(lamda_error, zip(lamda_list, c_nk_list)) #print (error_list_lists) error_list = [] for sub_error_list in error_list_lists: error_list = error_list + sub_error_list error_list = error_list + list( abs_delta_weight*diff(n) ) + list( k_weight_fraction * abs_delta_weight * diff(k)) return error_list ####### now for a guess list ############## guess_k_and_p_list= [] n_list = [] for i in range(len(lamda_list)): nk = nk_f_guess(lamda_list[i]) n, k = nk.real, nk.imag if no_negative and k < 0.0: k = 0 if no_negative and n < 0.0: n = 0 guess_k_and_p_list.append( k) n_list.append(n) # now we put p at the end p = trapz(n_list, lamda_list)/(lamda_list[-1] - lamda_list[0]) # this is a guess for the principle value print ('principle value guess:',p) guess_k_and_p_list.append(p) ######### test if False: print(F_error(guess_k_and_p_list)) #use this to see if the TR_error works ############ nk guessing over, time for creating and minimizing error function if method == 'least_squares': inputs = dict(fun = F_error, x0 = guess_k_and_p_list, ftol = tolerance, xtol = tolerance, gtol = tolerance, verbose = 2) if no_negative: inputs.update(dict( bounds = [len(lamda_list)*[0.0]+[-inf],len(lamda_list)*[inf]+[inf]] )) solution = least_squares(**inputs ).x elif method == 'SLSQP': inputs = dict(fun = lambda x: 0.5*sum(array(F_error(x))**2), x0 = guess_k_and_p_list, method = 'SLSQP', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = len(lamda_list)*[(0,inf)] + [(-inf,inf)] )) solution = minimize(**inputs ).x elif method == 'L-BFGS-B': inputs = dict(fun = lambda x: 0.5*sum(array(F_error(x))**2), x0 = guess_k_and_p_list, method = 'L-BFGS-B', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = len(lamda_list)*[(0,inf)] + [(-inf,inf)] )) solution = minimize(**inputs ).x elif method == 'TNC': inputs = dict(fun = lambda x: 0.5*sum(array(F_error(x))**2), x0 = guess_k_and_p_list, method = 'TNC', tol = tolerance, options = {'disp' : True, 'iprint': 2} ) if no_negative: inputs.update(dict( bounds = len(lamda_list)*[(0,inf)] + [(-inf,inf)] )) solution = minimize(**inputs ).x else: raise ValueError("Invalid minimization method!") k_and_p_list = solution k = k_and_p_list[0:-1] p = k_and_p_list[-1] n = p + KKT(lamda_list = lamda_list, k = k, compute_pool = my_pool ) print ('Final principle value:',p) fit_nk_f = extrap(lamda_list, n + 1.0j*k, kind = interpolation_type) my_pool.terminate() my_pool.close() return fit_nk_f