def rotate_wf(wf_list,theta,axis,ref_pt): """ This function takes a Wannier Function list, and rotates the coordinates of the WF centres by an angle theta about the axis 'axis'. It returns a new list of Wannier Functions with the rotated coordinates. """ import numpy from numpy import dot as dot from numpy import cross as cross from math import cos as cos from math import sin as sin wf_list_final = [] for wf in wf_list: new_wf = wannier_function() # first we compute the relative vector v_rel = numpy.array([wf.x,wf.y,wf.z]) - ref_pt # then we rotate v_rot = dot(v_rel,axis)*axis+cos(theta)*(v_rel-dot(v_rel,axis)*axis)+ \ sin(theta)*cross(axis,v_rel) # then we reintroduce the absolute coordinates v_final = v_rot + ref_pt # now we update the wf coordinates new_wf.setindex(wf.index) new_wf.setx(v_final[0]) new_wf.sety(v_final[1]) new_wf.setz(v_final[2]) new_wf.setonsite(wf.onsite) # adding the new wf to the final list wf_list_final.append(new_wf) return wf_list_final
def main_routine(wf_total, wf_per_pl, cells_per_pl, cond_dir, second_dir, wannier_functions, atom_number, atomic_coordinates, matrix, angle, delta): # first we separate the left-most principal layer, the conductor region # and the right-most principal layer PL1 = wannier_functions[:wf_per_pl] conductor = wannier_functions[wf_per_pl:-wf_per_pl] PL4 = wannier_functions[-wf_per_pl:] # now we compute the unit vector for the axis of rotation point_A = barycenter(PL1) point_B = barycenter(PL4) unit_vector = (1.0/numpy.linalg.norm(point_B-point_A))*(point_B-point_A) if cond_dir=='x': reference = numpy.array([1.0,0.0,0.0]) elif cond_dir=='y': reference = numpy.array([0.0,1.0,0.0]) else: reference = numpy.array([0.0,0.0,1.0]) if numpy.dot(unit_vector,reference)<=0.95: print "" print " Warning in rotate_conductor :" print " The computed unit vector for the axis of" print " rotation seems to be off from the reference" print " unit vector : %s" %(cond_dir) print " The dot product of unit vector with %s is : %3.2f" %(cond_dir,numpy.dot(unit_vector,reference)) print "" user_answer = "" while user_answer not in ["yes", "no"]: user_answer = str(raw_input(" is this OK ? ('yes' or 'no') ")) if user_answer=='no': print " Exiting the program..." print "" sys.exit(1) # we search the groups of WF with similar centres. To do this # a group is identified by the index of the first WF in the group # and the group size gp_dict = {} gp_bool = numpy.zeros(len(conductor),dtype='bool') for i in xrange(len(conductor)): if gp_bool[i]==False: gp_bool[i] = True gp_size = 1 # for each wf we search for similar centres just around that wf for j in xrange(max(i-10,0),min(i+11,len(conductor))): if gp_bool[j]==False: if same_center(conductor[i],conductor[j]): gp_bool[j] = True gp_size += 1 # if gp_size is at least 2 we add this group to the dictionnary if gp_size >= 2: gp_dict[conductor[i].index] = gp_size # now we need to remove the redondant WF from the conductor not_to_add = [] for wf in conductor: if wf.index in gp_dict.keys(): for j in xrange(1,gp_dict[wf.index]): not_to_add.append(wf.index+j) reduced_conductor = [] for wf in conductor: if wf.index not in not_to_add: reduced_conductor.append(wf) # with the reduced_conductor list, we can rotate the centers reduced_rotated_conductor = rotate_wf(reduced_conductor,angle,unit_vector,point_A) # we then sort the rotated Wannier Functions sorted_reduced_conductor = sort(reduced_rotated_conductor, cond_dir, second_dir, delta) # we re-insert the WF with similar centers sorted_conductor = [] for wf in sorted_reduced_conductor: if wf.index not in gp_dict.keys(): sorted_conductor.append(wf) else: sorted_conductor.append(wf) for j in xrange(1,gp_dict[wf.index]): new_wf = wannier_function() pos_in_list = wf.index+j-conductor[0].index new_wf.setindex(conductor[pos_in_list].index) new_wf.setx(wf.x) new_wf.sety(wf.y) new_wf.setz(wf.z) new_wf.setonsite(conductor[pos_in_list].onsite) sorted_conductor.append(new_wf) # we now find the mapping between the original order of WF # and the final order after sorting final_order = [] reference = conductor[0].index for wf in sorted_conductor: final_order.append(wf.index-reference) # now we can reconstruct the matrix final_matrix = numpy.zeros((matrix.shape[0],matrix.shape[1]),dtype='float') for i in xrange(matrix.shape[0]): for j in xrange(matrix.shape[1]): final_matrix[i,j] = matrix[final_order[i],final_order[j]] write_htC('rotated_matrix_htC.dat',final_matrix) # at last we re-generate the *_tran_info.dat file final_wf_list = PL1 + sorted_conductor + PL4 final_atomic_coordinates = rotate_atoms(atomic_coordinates,angle,unit_vector,point_A) write_tran_info(wf_total, wf_per_pl, cells_per_pl, cond_dir, second_dir, final_wf_list, atom_number, final_atomic_coordinates) return